Compare commits

..

2 Commits

Author SHA1 Message Date
WerWolv
5caefcc9f2 git: Configure runners better 2025-08-22 20:15:03 +02:00
WerWolv
cb38d98f5c git: Switch over to runs-on 2025-08-22 20:03:32 +02:00
509 changed files with 11894 additions and 27668 deletions

View File

@@ -1,97 +1,69 @@
# All rules should have a comment associated # Generated from CLion Inspection settings
# Directives that do not have any effect (e.g. disabling a rule that is not enabled) can be done to add an explanation comment. ---
# Or at least an empty comment # to show they were put here explicitely, Checks: '-*,
# and not as part of the historical CLion-generated rules mpi-*,
# Note: `- -X` means disable X bugprone-*,
# CLI usage: go to the build directory and run: `run-clang-tidy -allow-no-checks -source-filter ".*/lib/.*" -fix -j` -bugprone-signal-handler,
-bugprone-narrowing-conversions,
Checks: -bugprone-redundant-branch-condition,
- -* -bugprone-exception-escape,
- mpi-* -bugprone-shared-ptr-array-mismatch,
- bugprone-* -bugprone-implicit-widening-of-multiplication-result,
- -bugprone-signal-handler -bugprone-signed-char-misuse,
- -bugprone-narrowing-conversions -bugprone-unhandled-exception-at-new,
- -bugprone-redundant-branch-condition -bugprone-infinite-loop,
- -bugprone-exception-escape -bugprone-easily-swappable-parameters,
- -bugprone-shared-ptr-array-mismatch cert-err52-cpp,
- -bugprone-implicit-widening-of-multiplication-result cert-err60-cpp,
- -bugprone-signed-char-misuse cert-err34-c,
- -bugprone-unhandled-exception-at-new cert-str34-c,
- -bugprone-infinite-loop cert-dcl21-cpp,
- -bugprone-easily-swappable-parameters cert-msc50-cpp,
- -bugprone-float-loop-counter # cert-msc51-cpp,
- -bugprone-unchecked-string-to-number-conversion # Unfortunately no alternative cert-dcl58-cpp,
- -bugprone-branch-clone # Mostly warns about one-line duplicates cert-flp30-c,
- cert-err52-cpp cppcoreguidelines-avoid-const-or-ref-data-members,
- cert-err60-cpp cppcoreguidelines-pro-type-member-init,
- cert-str34-c cppcoreguidelines-slicing,
- cert-dcl21-cpp cppcoreguidelines-interfaces-global-init,
- cert-msc50-cpp cppcoreguidelines-pro-type-static-cast-downcast,
- cert-msc51-cpp cppcoreguidelines-narrowing-conversions,
- cert-dcl58-cpp google-default-arguments,
- cppcoreguidelines-avoid-const-or-ref-data-members google-runtime-operator,
- cppcoreguidelines-pro-type-member-init # We want to use default member initializers google-explicit-constructor,
- cppcoreguidelines-slicing hicpp-multiway-paths-covered,
- cppcoreguidelines-interfaces-global-init hicpp-exception-baseclass,
- -cppcoreguidelines-pro-type-static-cast-downcast # dynamic_cast has a runtime overhead misc-*,
- -cppcoreguidelines-narrowing-conversions # -misc-definitions-in-headers,
- google-runtime-operator -misc-unused-parameters,
- google-explicit-constructor -misc-unused-alias-decls,
- -google-default-arguments # Provider and ViewProvider read() is a good example of why this is useful -misc-use-anonymous-namespace,
- hicpp-multiway-paths-covered -misc-misleading-identifier,
- hicpp-exception-baseclass -misc-confusable-identifiers,
- misc-* -misc-misleading-bidirectional,
- -misc-definitions-in-headers -misc-static-assert,
- -misc-unused-parameters -misc-no-recursion,
- -misc-unused-alias-decls -misc-const-correctness,
- -misc-use-anonymous-namespace modernize-*,
- -misc-misleading-identifier -modernize-use-trailing-return-type,
- -misc-confusable-identifiers openmp-use-default-none,
- -misc-misleading-bidirectional performance-*,
- -misc-static-assert -performance-no-int-to-ptr,
- -misc-no-recursion portability-*,
- -misc-const-correctness -portability-restrict-system-includes,
- -misc-use-internal-linkage # False positives if header where function is defined is not included readability-*,
- -misc-include-cleaner # Allow indirect includes -readability-redundant-preprocessor,
- -misc-non-private-member-variables-in-classes # -readability-named-parameter,
- modernize-* -readability-function-size,
- -modernize-use-trailing-return-type -readability-use-anyofallof,
- -modernize-use-std-print # We want to use fmt::print instead -readability-identifier-length,
- -modernize-use-integer-sign-comparison # Too much occurrences to change -readability-magic-numbers,
- openmp-use-default-none -readability-braces-around-statements,
- performance-* -readability-suspicious-call-argument,
- -performance-no-int-to-ptr -readability-isolate-declaration,
- portability-* -readability-else-after-return,
- -portability-restrict-system-includes -readability-redundant-access-specifiers,
- readability-* -readability-function-cognitive-complexity,
- -readability-redundant-preprocessor -readability-identifier-naming,
- -readability-named-parameter *-include-cleaner,
- -readability-function-size -readability-qualified-auto'
- -readability-use-anyofallof
- -readability-identifier-length
- -readability-magic-numbers
- -readability-braces-around-statements
- -readability-suspicious-call-argument
- -readability-isolate-declaration
- -readability-else-after-return
- -readability-redundant-access-specifiers
- -readability-function-cognitive-complexity
- -readability-identifier-naming
- -readability-qualified-auto
- -readability-use-std-min-max # Less readable imo
- -readability-math-missing-parentheses # Basic math
- -readability-implicit-bool-conversion # Not much of a problem ?
- -readability-convert-member-functions-to-static #
- -readability-use-concise-preprocessor-directives # We do not use #ifdef
- -readability-uppercase-literal-suffix # Not important enough
- -readability-redundant-string-cstr # Sometimes used to stop at first null byte
- -readability-static-accessed-through-instance #
- -readability-ambiguous-smartptr-reset-call # Fix is hard to read
# Will fix later
- -modernize-avoid-c-arrays
- -readability-make-member-function-const # idk + lots of occurences
- -readability-misleading-indentation # We need to handle cases with #if defined()
- -bugprone-unchecked-optional-access
- -performance-unnecessary-value-param # idk
- -readability-avoid-nested-conditional-operator

4
.github/FUNDING.yml vendored
View File

@@ -1,5 +1,5 @@
# Sponsor links # Sponsor links
patreon: werwolv
custom: https://werwolv.net/donate
github: WerWolv github: WerWolv
ko_fi: WerWolv
custom: "https://werwolv.net/donate"

View File

@@ -1,7 +0,0 @@
#!/bin/sh
set -xe
ARTIFACT_NAME="$1"
ARTIFACT_ID=$(gh api repos/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID/artifacts --jq ".artifacts[] | select(.name==\"$ARTIFACT_NAME\") | .id")
gh api -X DELETE repos/$GITHUB_REPOSITORY/actions/artifacts/$ARTIFACT_ID
echo "Deleted artifact $ARTIFACT_NAME with ID $ARTIFACT_ID"

View File

@@ -57,7 +57,6 @@ jobs:
-DCMAKE_C_FLAGS="-fuse-ld=lld" \ -DCMAKE_C_FLAGS="-fuse-ld=lld" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \ -DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
-DIMHEX_PATTERNS_PULL_MASTER=ON \ -DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_EXCLUDE_PLUGINS="script_loader" \
-G Ninja \ -G Ninja \
.. ..
ninja install ninja install

View File

@@ -1,9 +1,5 @@
name: Build name: Build
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
on: on:
push: push:
branches: branches:
@@ -27,10 +23,10 @@ jobs:
include: include:
- architecture_name: "x86_64" - architecture_name: "x86_64"
msystem: "mingw64" msystem: "mingw64"
runner_os: "windows-2025" runner_os: runs-on=${{ github.run_id }}/image=windows22-base-x64/family=c7a.16xlarge
- architecture_name: "arm64" - architecture_name: "arm64"
msystem: "clangarm64" msystem: "clangarm64"
runner_os: "windows-11-arm" runner_os: windows-11-arm
runs-on: ${{ matrix.runner_os }} runs-on: ${{ matrix.runner_os }}
name: 🪟 Windows MSYS2 ${{ matrix.architecture_name }} name: 🪟 Windows MSYS2 ${{ matrix.architecture_name }}
@@ -53,7 +49,7 @@ jobs:
submodules: recursive submodules: recursive
- name: 📜 Setup ccache - name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1 uses: hendrikmuhs/ccache-action@main
id: cache-ccache id: cache-ccache
with: with:
key: ${{ runner.os }}-mingw-ccache-${{ github.run_id }} key: ${{ runner.os }}-mingw-ccache-${{ github.run_id }}
@@ -99,6 +95,7 @@ jobs:
-DIMHEX_GENERATE_PDBS=ON \ -DIMHEX_GENERATE_PDBS=ON \
-DIMHEX_REPLACE_DWARF_WITH_PDB=ON \ -DIMHEX_REPLACE_DWARF_WITH_PDB=ON \
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" \ -DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" \
-DCPACK_WIX_VERSION="4" \
-DCPACK_WIX_ROOT="$(echo "$USERPROFILE" | tr '\\' '/')/.dotnet/tools" \ -DCPACK_WIX_ROOT="$(echo "$USERPROFILE" | tr '\\' '/')/.dotnet/tools" \
.. ..
@@ -109,8 +106,8 @@ jobs:
- name: 🕯️ Install WiX Toolkit - name: 🕯️ Install WiX Toolkit
run: | run: |
"C:/Program Files/dotnet/dotnet.exe" tool install --global wix@6.0.2 "C:/Program Files/dotnet/dotnet.exe" tool install --global wix
"$(echo "$USERPROFILE" | tr '\\' '/')/.dotnet/tools/wix" extension add --global WixToolset.UI.wixext/6.0.2 "$(echo "$USERPROFILE" | tr '\\' '/')/.dotnet/tools/wix" extension add -g WixToolset.UI.wixext
- name: 🪲 Create PDBs for MSI - name: 🪲 Create PDBs for MSI
run: | run: |
@@ -169,7 +166,6 @@ jobs:
- name: ⬆️ Upload Windows Installer - name: ⬆️ Upload Windows Installer
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
id: upload-installer
with: with:
if-no-files-found: error if-no-files-found: error
name: Windows Installer ${{ matrix.architecture_name }} name: Windows Installer ${{ matrix.architecture_name }}
@@ -190,7 +186,7 @@ jobs:
run: | run: |
set -x set -x
echo "NoGPU version Powered by Mesa 3D : https://fdossena.com/?p=mesa%2Findex.frag" > build/install/MESA.md echo "NoGPU version Powered by Mesa 3D : https://fdossena.com/?p=mesa%2Findex.frag" > build/install/MESA.md
curl --connect-timeout 30 --retry 5 --retry-delay 0 --retry-max-time 30 https://downloads.fdossena.com/geth.php?r=mesa64-latest -L -o mesa.7z curl https://downloads.fdossena.com/geth.php?r=mesa64-latest -L -o mesa.7z
7z e mesa.7z 7z e mesa.7z
mv opengl32.dll build/install mv opengl32.dll build/install
@@ -210,10 +206,10 @@ jobs:
include: include:
- architecture_name: "x86_64" - architecture_name: "x86_64"
vs_arch: "amd64" vs_arch: "amd64"
runner_os: "windows-2025" runner_os: runs-on=${{ github.run_id }}/image=windows22-base-x64/family=c7a.16xlarge
- architecture_name: "arm64" - architecture_name: "arm64"
vs_arch: "amd64_arm64" vs_arch: "amd64_arm64"
runner_os: "windows-11-arm" runner_os: windows-11-arm
runs-on: ${{ matrix.runner_os }} runs-on: ${{ matrix.runner_os }}
name: 🪟 Windows MSVC ${{ matrix.architecture_name }} name: 🪟 Windows MSVC ${{ matrix.architecture_name }}
@@ -237,7 +233,7 @@ jobs:
arch: ${{ matrix.vs_arch }} arch: ${{ matrix.vs_arch }}
- name: 📜 Setup ccache - name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1 uses: hendrikmuhs/ccache-action@main
id: cache-ccache id: cache-ccache
with: with:
key: ${{ runner.os }}-msvc-${{ matrix.vs_arch }}-ccache-${{ github.run_id }} key: ${{ runner.os }}-msvc-${{ matrix.vs_arch }}-ccache-${{ github.run_id }}
@@ -246,7 +242,7 @@ jobs:
- name: 📦 Install vcpkg - name: 📦 Install vcpkg
uses: friendlyanon/setup-vcpkg@v1 uses: friendlyanon/setup-vcpkg@v1
with: { committish: 66c0373dc7fca549e5803087b9487edfe3aca0a1 } with: { committish: ef7dbf94b9198bc58f45951adcf1f041fcbc5ea0 }
- name: ⬇️ Install dependencies - name: ⬇️ Install dependencies
run: | run: |
@@ -283,6 +279,7 @@ jobs:
-DIMHEX_COMMIT_HASH_LONG="$env:GITHUB_SHA" ` -DIMHEX_COMMIT_HASH_LONG="$env:GITHUB_SHA" `
-DIMHEX_COMMIT_BRANCH="$($env:GITHUB_REF -replace '.*/', '')" ` -DIMHEX_COMMIT_BRANCH="$($env:GITHUB_REF -replace '.*/', '')" `
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" ` -DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" `
-DCPACK_WIX_VERSION="4" `
-DCPACK_WIX_ROOT="$($env:USERPROFILE -replace '\\','/')/.dotnet/tools" ` -DCPACK_WIX_ROOT="$($env:USERPROFILE -replace '\\','/')/.dotnet/tools" `
. .
@@ -293,8 +290,8 @@ jobs:
- name: 🕯️ Install WiX Toolkit - name: 🕯️ Install WiX Toolkit
run: | run: |
& "C:/Program Files/dotnet/dotnet.exe" tool install --global wix@6.0.2 & "C:/Program Files/dotnet/dotnet.exe" tool install --global wix
& "$($env:USERPROFILE -replace '\\','/')/.dotnet/tools/wix" extension add --global WixToolset.UI.wixext/6.0.2 & "$($env:USERPROFILE -replace '\\','/')/.dotnet/tools/wix" extension add -g WixToolset.UI.wixext
- name: 📦 Bundle MSI - name: 📦 Bundle MSI
run: | run: |
@@ -319,7 +316,7 @@ jobs:
imhex-*.msi imhex-*.msi
win-plugin-template-test: win-plugin-template-test:
runs-on: windows-2022 runs-on: runs-on=${{ github.run_id }}/image=windows22-base-x64/family=c7a.16xlarge
name: 🧪 Plugin Template Test name: 🧪 Plugin Template Test
defaults: defaults:
@@ -383,13 +380,24 @@ jobs:
# MacOS build # MacOS build
macos-x86: macos-x86:
runs-on: macos-15-intel runs-on: macos-13
permissions: permissions:
id-token: write id-token: write
attestations: write attestations: write
name: 🍎 macOS 10.15 x86_64 strategy:
fail-fast: false
matrix:
include:
- file_suffix: "-NoGPU"
name_suffix: "NoGPU"
custom_glfw: true
- file_suffix: ""
name_suffix: ""
custom_glfw: false
name: 🍎 macOS 13 x86_64 ${{ matrix.name_suffix }}
steps: steps:
- name: 🧰 Checkout - name: 🧰 Checkout
@@ -404,55 +412,76 @@ jobs:
- name: 📜 Setup ccache - name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1 uses: hendrikmuhs/ccache-action@v1
with: with:
key: ${{ runner.os }}-ccache-${{ github.run_id }} key: ${{ runner.os }}${{ matrix.file_suffix }}-ccache-${{ github.run_id }}
restore-keys: ${{ runner.os }}-ccache restore-keys: ${{ runner.os }}${{ matrix.file_suffix }}-ccache
max-size: 1G max-size: 1G
- name: Set Xcode version - name: Set Xcode version
run: | run: sudo xcode-select -s /Library/Developer/CommandLineTools
sudo xcode-select --install || true
sudo xcode-select -s /Library/Developer/CommandLineTools
- name: 📦 Install MacPorts
run: |
wget https://github.com/macports/macports-base/releases/download/v2.11.6/MacPorts-2.11.6-15-Sequoia.pkg
sudo installer -pkg MacPorts-2.11.6-15-Sequoia.pkg -target /
export PATH=/opt/local/bin:/opt/local/sbin:$PATH
echo "PATH=/opt/local/bin:/opt/local/sbin:$PATH" >> $GITHUB_ENV
echo "MACOSX_DEPLOYMENT_TARGET=10.15" >> $GITHUB_ENV
echo "universal_target 10.15" | sudo tee -a /opt/local/etc/macports/macports.conf
echo "macos_deployment_target 10.15" | sudo tee -a /opt/local/etc/macports/macports.conf
echo "macosx_sdk_version 10.15" | sudo tee -a /opt/local/etc/macports/macports.conf
sudo port selfupdate
- name: ⬇️ Install dependencies - name: ⬇️ Install dependencies
env: env:
# Make brew not display useless errors # Make brew not display useless errors
HOMEBREW_TESTS: 1 HOMEBREW_TESTS: 1
run: | run: |
brew install llvm@21 automake brew reinstall python --quiet || true
sudo -E port install mbedtls3 nlohmann-json ccache freetype libmagic pkgconfig curl glfw ninja zlib xz bzip2 zstd libssh2 md4c brew link --overwrite --quiet python 2>/dev/null || true
brew bundle --quiet --file dist/macOS/Brewfile || true
rm -rf /usr/local/Cellar/capstone
- name: ⬇️ Install classic glfw
if: ${{! matrix.custom_glfw }}
run: |
brew install --quiet glfw || true
- name: ⬇️ Install .NET - name: ⬇️ Install .NET
uses: actions/setup-dotnet@v4 uses: actions/setup-dotnet@v4
with: with:
dotnet-version: '8.0.100' dotnet-version: '8.0.100'
- name: 🧰 Checkout glfw
if: ${{ matrix.custom_glfw }}
uses: actions/checkout@v4
with:
repository: glfw/glfw
path: glfw
# GLFW custom build (to allow software rendering)
- name: ⬇️ Patch and install custom glfw
if: ${{ matrix.custom_glfw }}
run: |
set -x
cd glfw
git apply ../dist/macOS/0001-glfw-SW.patch
mkdir build
cd build
cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
-DBUILD_SHARED_LIBS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
..
ninja install
# MacOS cmake build # MacOS cmake build
- name: 🛠️ Configure CMake - name: 🛠️ Configure CMake
run: | run: |
set -x set -x
mkdir -p build mkdir -p build
cd build cd build
CC=$(brew --prefix llvm@21)/bin/clang \ CC=$(brew --prefix llvm)/bin/clang \
CXX=$(brew --prefix llvm@21)/bin/clang++ \ CXX=$(brew --prefix llvm)/bin/clang++ \
OBJC=$(brew --prefix llvm@21)/bin/clang \ OBJC=$(brew --prefix llvm)/bin/clang \
OBJCXX=$(brew --prefix llvm@21)/bin/clang++ \ OBJCXX=$(brew --prefix llvm)/bin/clang++ \
PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \
cmake -G "Ninja" \ cmake -G "Ninja" \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \ -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
-DIMHEX_GENERATE_PACKAGE=ON \ -DIMHEX_GENERATE_PACKAGE=ON \
-DIMHEX_SYSTEM_LIBRARY_PATH="$(brew --prefix llvm@21)/lib;$(brew --prefix llvm@21)/lib/unwind;$(brew --prefix llvm@21)/lib/c++;$(brew --prefix)/lib" \ -DIMHEX_SYSTEM_LIBRARY_PATH="$(brew --prefix llvm)/lib;$(brew --prefix llvm)/lib/unwind;$(brew --prefix llvm)/lib/c++;$(brew --prefix)/lib" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \ -DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
@@ -470,6 +499,7 @@ jobs:
run: | run: |
set -x set -x
cd build/install cd build/install
mv imhex.app ImHex.app
codesign --remove-signature ImHex.app codesign --remove-signature ImHex.app
codesign --force --deep --sign - ImHex.app codesign --force --deep --sign - ImHex.app
@@ -498,7 +528,7 @@ jobs:
break; break;
fi fi
done done
mv *.dmg ../../imhex-${{ env.IMHEX_VERSION }}-macOS-x86_64.dmg mv *.dmg ../../imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.file_suffix }}-x86_64.dmg
- name: 🗝️ Generate build provenance attestations - name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2 uses: actions/attest-build-provenance@v2
@@ -511,12 +541,12 @@ jobs:
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
if-no-files-found: error if-no-files-found: error
name: macOS DMG x86_64 name: macOS DMG ${{ matrix.name_suffix }} x86_64
path: ./*.dmg path: ./*.dmg
macos-arm64: macos-arm64:
runs-on: ubuntu-24.04 runs-on: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
name: 🍎 macOS 11 arm64 name: 🍎 macOS 13 arm64
outputs: outputs:
IMHEX_VERSION: ${{ steps.build.outputs.IMHEX_VERSION }} IMHEX_VERSION: ${{ steps.build.outputs.IMHEX_VERSION }}
@@ -560,11 +590,11 @@ jobs:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
run: | run: |
gh extension install actions/gh-actions-cache gh extension install actions/gh-actions-cache
gh cache delete "macos-arm64-cache" --confirm || true gh actions-cache delete "build-macos-arm64-cache" --confirm || true
macos-arm64-package: macos-arm64-package:
runs-on: macos-15-intel runs-on: macos-13
name: 🍎 macOS 11 arm64 Packaging name: 🍎 macOS 13 arm64 Packaging
needs: macos-arm64 needs: macos-arm64
env: env:
@@ -590,6 +620,7 @@ jobs:
run: | run: |
set -x set -x
cd out cd out
mv imhex.app ImHex.app
codesign --remove-signature ImHex.app codesign --remove-signature ImHex.app
codesign --force --deep --entitlements Entitlements.plist --sign - ImHex.app codesign --force --deep --entitlements Entitlements.plist --sign - ImHex.app
@@ -640,21 +671,15 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- name: "Ubuntu" - release_num: "24.04"
release_num: "24.04" - release_num: "24.10"
image: "ubuntu:24.04" - release_num: "25.04"
- name: "Ubuntu"
release_num: "25.10"
image: "ubuntu:25.10"
- name: "Debian"
release_num: "13"
image: "debian:13"
name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }} x86_64 name: 🐧 Ubuntu ${{ matrix.release_num }}
runs-on: ubuntu-24.04 runs-on: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
container: container:
image: "${{ matrix.image }}" image: "ubuntu:${{ matrix.release_num }}"
options: --privileged options: --privileged
permissions: permissions:
@@ -673,8 +698,8 @@ jobs:
- name: 📜 Setup ccache - name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1 uses: hendrikmuhs/ccache-action@v1
with: with:
key: ${{ matrix.image }}-ccache-${{ github.run_id }} key: Ubuntu-${{ matrix.release_num }}-ccache-${{ github.run_id }}
restore-keys: ${{ matrix.image }}-ccache restore-keys: Ubuntu-${{ matrix.release_num }}-ccache
max-size: 1G max-size: 1G
- name: ⬇️ Install dependencies - name: ⬇️ Install dependencies
@@ -719,7 +744,7 @@ jobs:
run: | run: |
cp -r build/DEBIAN build/DebDir cp -r build/DEBIAN build/DebDir
dpkg-deb -Zzstd --build build/DebDir dpkg-deb -Zzstd --build build/DebDir
mv build/DebDir.deb imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.deb mv build/DebDir.deb imhex-${{ env.IMHEX_VERSION }}-Ubuntu-${{ matrix.release_num }}-x86_64.deb
- name: 🗝️ Generate build provenance attestations - name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2 uses: actions/attest-build-provenance@v2
@@ -732,7 +757,7 @@ jobs:
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
if-no-files-found: error if-no-files-found: error
name: ${{ matrix.name }} ${{ matrix.release_num }} DEB x86_64 name: Ubuntu ${{ matrix.release_num }} DEB x86_64
path: '*.deb' path: '*.deb'
# AppImage build # AppImage build
@@ -744,11 +769,11 @@ jobs:
- architecture: "x86_64" - architecture: "x86_64"
architecture_package: "amd64" architecture_package: "amd64"
architecture_appimage_builder: "x86_64" architecture_appimage_builder: "x86_64"
image: ubuntu-24.04 image: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
- architecture: "arm64" - architecture: "arm64"
architecture_package: "arm64" architecture_package: "arm64"
architecture_appimage_builder: "aarch64" architecture_appimage_builder: "aarch64"
image: ubuntu-24.04-arm image: runs-on=${{ github.run_id }}/runner=16cpu-linux-arm64/image=ubuntu24-full-arm64
runs-on: ${{ matrix.image }} runs-on: ${{ matrix.image }}
name: ⬇️ AppImage ${{ matrix.architecture }} name: ⬇️ AppImage ${{ matrix.architecture }}
@@ -807,8 +832,8 @@ jobs:
# ArchLinux build # ArchLinux build
archlinux-build: archlinux-build:
name: 🐧 ArchLinux x86_64 name: 🐧 ArchLinux
runs-on: ubuntu-24.04 runs-on: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
container: container:
image: archlinux:base-devel image: archlinux:base-devel
@@ -923,11 +948,20 @@ jobs:
matrix: matrix:
include: include:
- name: Fedora - name: Fedora
release_num: 43 release_num: rawhide
mock_config: fedora-43 mock_config: fedora-rawhide
- name: Fedora
release_num: 42
mock_config: fedora-42
- name: Fedora
release_num: 41
mock_config: fedora-41
- name: RHEL-AlmaLinux
release_num: 9
mock_config: "alma+epel-9"
name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }} x86_64 name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }}
runs-on: ubuntu-24.04 runs-on: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
container: container:
image: "almalinux:10" image: "almalinux:10"
@@ -1052,9 +1086,9 @@ jobs:
matrix: matrix:
include: include:
- architecture: "x86_64" - architecture: "x86_64"
image: ubuntu-24.04 image: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
- architecture: "arm64" - architecture: "arm64"
image: ubuntu-24.04-arm image: runs-on=${{ github.run_id }}/runner=16cpu-linux-arm64/image=ubuntu24-full-arm64
name: 🐧 Snap ${{ matrix.architecture }} name: 🐧 Snap ${{ matrix.architecture }}
runs-on: ${{ matrix.image }} runs-on: ${{ matrix.image }}
@@ -1083,18 +1117,12 @@ jobs:
run: | run: |
export IMHEX_VERSION=$(cat VERSION) export IMHEX_VERSION=$(cat VERSION)
echo "IMHEX_VERSION=$IMHEX_VERSION" >> $GITHUB_ENV echo "IMHEX_VERSION=$IMHEX_VERSION" >> $GITHUB_ENV
if [[ "$IMHEX_VERSION" == *.WIP ]]; then
echo "IMHEX_VERSION_STRING=$IMHEX_VERSION-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
else
echo "IMHEX_VERSION_STRING=$IMHEX_VERSION" >> $GITHUB_ENV
fi
echo "CCACHE=ccache" >> $GITHUB_ENV echo "CCACHE=ccache" >> $GITHUB_ENV
- name: 📜 Move snap directory to root - name: 📜 Move snap directory to root
run: | run: |
mkdir -p ./snap mkdir -p ./snap
envsubst '${IMHEX_VERSION_STRING},${CCACHE}' < ./dist/snap/snapcraft.yaml > ./snap/snapcraft.yaml envsubst '${IMHEX_VERSION},${CCACHE}' < ./dist/snap/snapcraft.yaml > ./snap/snapcraft.yaml
- name: 📜 Setup ccache - name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1 uses: hendrikmuhs/ccache-action@v1
@@ -1107,10 +1135,6 @@ jobs:
run: | run: |
sudo snapcraft --destructive-mode sudo snapcraft --destructive-mode
- name: 🟩 Rename Snap
run: |
mv *.snap imhex-${{ env.IMHEX_VERSION }}-${{ matrix.architecture }}.snap
- name: 🗝️ Generate build provenance attestations - name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2 uses: actions/attest-build-provenance@v2
if: ${{ github.event.repository.fork == false && github.event_name != 'pull_request' }} if: ${{ github.event.repository.fork == false && github.event_name != 'pull_request' }}
@@ -1133,10 +1157,10 @@ jobs:
include: include:
- architecture: "x86_64" - architecture: "x86_64"
flatpak_arch: "x86_64" flatpak_arch: "x86_64"
image: ubuntu-24.04 image: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
- architecture: "arm64" - architecture: "arm64"
flatpak_arch: "aarch64" flatpak_arch: "aarch64"
image: ubuntu-24.04-arm image: runs-on=${{ github.run_id }}/runner=16cpu-linux-arm64/image=ubuntu24-full-arm64
name: 🐧 Flatpak ${{ matrix.architecture }} name: 🐧 Flatpak ${{ matrix.architecture }}
runs-on: ${{ matrix.image }} runs-on: ${{ matrix.image }}
@@ -1187,8 +1211,12 @@ jobs:
imhex-${{ env.IMHEX_VERSION }}-${{ matrix.architecture }}.flatpak imhex-${{ env.IMHEX_VERSION }}-${{ matrix.architecture }}.flatpak
webassembly-build: webassembly-build:
runs-on: ubuntu-24.04 runs-on: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
name: 🌍 Web name: 🌍 Web
permissions:
pages: write
id-token: write
actions: write
steps: steps:
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -1208,20 +1236,17 @@ jobs:
cache-source: cache cache-source: cache
cache-target: /cache cache-target: /cache
- name: 🔨 Copy necessary files
run: |
mkdir -p out/nightly
cp dist/web/serve.py out/nightly/start_imhex_web.py
- name: 🛠️ Build using docker - name: 🛠️ Build using docker
run: | run: |
mkdir -p out/nightly
docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out/nightly --target raw docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out/nightly --target raw
- name: ⬇️ Download Release artifact - name: ⬇️ Download Release
if: ${{ github.event.repository.fork == false }} if: ${{ github.event.repository.fork == false }}
env: uses: robinraju/release-downloader@v1
GH_TOKEN: ${{ github.token }} with:
run: gh --repo $GITHUB_REPOSITORY release download --pattern "imhex-*-Web.zip" latest: true
fileName: 'imhex-*-Web.zip'
- name: 🔨 Fix permissions - name: 🔨 Fix permissions
if: ${{ github.event.repository.fork == false }} if: ${{ github.event.repository.fork == false }}
@@ -1234,6 +1259,10 @@ jobs:
with: with:
path: out/ path: out/
- name: 🔨 Copy necessary files
run: |
cp dist/web/serve.py out/nightly/start_imhex_web.py
- name: ⬆️ Upload package - name: ⬆️ Upload package
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
@@ -1252,7 +1281,7 @@ jobs:
webassembly-deploy: webassembly-deploy:
environment: environment:
name: ImHex Web name: github-pages
url: ${{ steps.deployment.outputs.page_url }} url: ${{ steps.deployment.outputs.page_url }}
permissions: permissions:
pages: write pages: write
@@ -1265,64 +1294,11 @@ jobs:
needs: webassembly-build needs: webassembly-build
steps: steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
- name: 🌍 Deploy WebAssembly Build to GitHub Pages - name: 🌍 Deploy WebAssembly Build to GitHub Pages
id: deployment id: deployment
uses: actions/deploy-pages@v4 uses: actions/deploy-pages@v4
- name: 🗑️ Delete artifact - name: 🗑️ Delete artifact
env: uses: geekyeggo/delete-artifact@v5
GH_TOKEN: ${{ github.token }}
run: |
.github/scripts/delete-artifact.sh "github-pages"
webassembly-docker-image-deploy:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
needs: webassembly-build
name: 🐋 Deploy to ghcr.io
permissions:
contents: read
packages: write
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
- name: ⬇️ Download artifact
uses: actions/download-artifact@v4
with: with:
name: ImHex Web name: github-pages
path: out
- name: 📜 Login to ghcr.io
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: ⛓️ Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}/imhex-web
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: 🔨 Build and push Docker image
uses: docker/build-push-action@v6
env:
DOCKER_BUILD_RECORD_UPLOAD: false
with:
context: .
file: dist/web/Host.Dockerfile
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@@ -1,47 +0,0 @@
# https://gist.github.com/iTrooz/d5bacca32c0974edc6c1ac3ad3ee82f3
# See https://github.com/cli/cli/issues/9125
# Extract archive with `tar -xf cache.tzst --transform 's@\.\./@#@g' -P` to avoid ../ errors
name: Download cache key
on:
workflow_dispatch:
inputs:
cache_key:
description: 'Cache key'
required: true
type: string
jobs:
cache-download:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Query cache version
id: version
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION=$(gh api repos/$GITHUB_REPOSITORY/actions/caches \
--jq "
.actions_caches[]
| select(.ref == \"refs/heads/$GITHUB_REF_NAME\")
| select(.key == \"${{ github.event.inputs.cache_key }}\")
| .version
")
echo "version=$VERSION" | tee $GITHUB_OUTPUT
- name: Restore cache
uses: iTrooz/cache/restore@restore_with_version
with:
# Path won't be actually used, we will match by 'version'.
path: .
key: ${{ github.event.inputs.cache_key }}
version: ${{ steps.version.outputs.version }}
- name: Upload cached folder as artifact
uses: actions/upload-artifact@v4
with:
name: cache-artifact
path: |
/home/runner/work/**/*.tzst

View File

@@ -11,7 +11,8 @@ on:
jobs: jobs:
nightly-release: nightly-release:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
name: 🌃 Update Nightly Release name: Update Nightly Release
steps: steps:
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -21,35 +22,27 @@ jobs:
fetch-tags: true fetch-tags: true
- name: 🌃 Check for new commits - name: 🌃 Check for new commits
id: check_commits
run: | run: |
cd ImHex
git config --global --add safe.directory $(pwd)
if [ -z "$(git log nightly..HEAD --oneline)" ]; then if [ -z "$(git log nightly..HEAD --oneline)" ]; then
echo "No new commits since last nightly. Exiting." echo "No new commits since last nightly. Exiting."
echo "::set-output name=should_run::false" exit 0
else
echo "::set-output name=should_run::true"
fi fi
- name: 📜 Set version variable - name: 📜 Set version variable
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
run: | run: |
project_version=`cat ImHex/VERSION` project_version=`cat ImHex/VERSION`
echo "IMHEX_VERSION=$project_version" >> $GITHUB_ENV echo "IMHEX_VERSION=$project_version" >> $GITHUB_ENV
# TODO: Replace by Github CLI when github.com/cli/cli/pull/12435 is closed
- name: ⬇️ Download artifacts from latest workflow - name: ⬇️ Download artifacts from latest workflow
uses: dawidd6/action-download-artifact@v6 uses: dawidd6/action-download-artifact@v6
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: build.yml workflow: build.yml
branch: master branch: ${{ github.event.release.target_commitish }}
workflow_conclusion: success workflow_conclusion: success
skip_unpack: true skip_unpack: true
- name: 🗜️ Unzip files when needed - name: 🗜️ Unzip files when needed
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
run: | run: |
set -x set -x
for zipfile in ./*.zip for zipfile in ./*.zip
@@ -65,33 +58,32 @@ jobs:
done done
- name: 🟩 Rename artifacts when needed - name: 🟩 Rename artifacts when needed
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
run: | run: |
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip
mv "Windows Portable arm64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-arm64.zip mv "Windows Portable arm64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-arm64.zip
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-Web.zip mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-Web.zip
mv ./*_amd64.snap $(echo ./*_amd64.snap | sed 's/_amd64\.snap$/-x86_64.snap/' | sed 's/_/-/1')
mv ./*_arm64.snap $(echo ./*_arm64.snap | sed 's/_arm64\.snap$/-arm64.snap/' | sed 's/_/-/1')
rm artifact.tar || true rm artifact.tar || true
- name: 📖 Generate Release Notes - name: 📖 Generate Release Notes
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
id: release_notes id: release_notes
continue-on-error: true continue-on-error: true
run: | run: |
cd ImHex cd ImHex
echo "## Nightly ${GITHUB_SHA::7} Changelog" > changelog.md echo "## Nightly ${GITHUB_SHA::7} Changelog" > changelog.md
git fetch --tags --recurse-submodules=no git fetch --tags --recurse-submodules=no
git log nightly..origin/master --oneline --no-merges --pretty=format:'* %s' >> changelog.md git log nightly..HEAD --oneline --no-merges --pretty=format:'* %s' >> changelog.md
- name: 📦 Update Pre-Release - name: 📦 Update Pre-Release
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
run: | run: |
set -e set -e
cd ImHex cd ImHex
# Move nightly tag to latest commit # Move nightly tag to latest commit
git tag -f nightly origin/master git tag -f nightly HEAD
git push origin nightly --force git push origin nightly --force
# Auth for GitHub CLI # Auth for GitHub CLI
@@ -109,8 +101,6 @@ jobs:
gh release upload nightly ../*.* --clobber gh release upload nightly ../*.* --clobber
- name: ⬆️ Publish x86_64 Snap package - name: ⬆️ Publish x86_64 Snap package
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
continue-on-error: true
uses: snapcore/action-publish@v1 uses: snapcore/action-publish@v1
env: env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }} SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
@@ -119,26 +109,9 @@ jobs:
release: edge release: edge
- name: ⬆️ Publish arm64 Snap package - name: ⬆️ Publish arm64 Snap package
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
continue-on-error: true
uses: snapcore/action-publish@v1 uses: snapcore/action-publish@v1
env: env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }} SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
with: with:
snap: imhex-${{ env.IMHEX_VERSION }}-arm64.snap snap: imhex-${{ env.IMHEX_VERSION }}-arm64.snap
release: edge release: edge
website_update:
name: 🌍 Update ImHex Landing Website
needs: nightly-release
runs-on: ubuntu-24.04
env:
WEBSITE_DISPATCH_TOKEN: ${{ secrets.WEBSITE_DISPATCH_TOKEN }}
steps:
- name: ✉️ Dispatch Landing page update
if: ${{ env.WEBSITE_DISPATCH_TOKEN != '' }}
uses: peter-evans/repository-dispatch@v4
with:
token: ${{ secrets.WEBSITE_DISPATCH_TOKEN }}
repository: WerWolv/ImHexWebsite
event-type: update_page

View File

@@ -7,12 +7,6 @@ on:
release: release:
types: [published] types: [published]
workflow_dispatch: workflow_dispatch:
inputs:
commit_hash:
type: string
description: 'The commit hash to build (defaults to the latest commit on the default branch)'
required: false
default: ''
jobs: jobs:
release-update-repos: release-update-repos:
@@ -31,7 +25,7 @@ jobs:
project_version=`cat ImHex/VERSION` project_version=`cat ImHex/VERSION`
tag_version="${{github.event.release.tag_name}}" tag_version="${{github.event.release.tag_name}}"
tag_version="${tag_version:1}" tag_version="${tag_version:1}"
if [ "$project_version" != "$tag_version" ] && [ ! -z "$tag_version" ]; then if [ "$project_version" != "$tag_version" ]; then
echo "::warning::$project_version and $tag_version are not the same ! Refusing to populate release" echo "::warning::$project_version and $tag_version are not the same ! Refusing to populate release"
exit 1 exit 1
fi fi
@@ -47,7 +41,6 @@ jobs:
tag: ImHex-v${{ env.IMHEX_VERSION }} tag: ImHex-v${{ env.IMHEX_VERSION }}
repo: PatternLanguage repo: PatternLanguage
token: ${{ secrets.RELEASE_TOKEN }} token: ${{ secrets.RELEASE_TOKEN }}
skipIfReleaseExists: true
- name: 🎫 Create ImHex-Patterns release - name: 🎫 Create ImHex-Patterns release
uses: ncipollo/release-action@v1 uses: ncipollo/release-action@v1
@@ -58,7 +51,6 @@ jobs:
tag: ImHex-v${{ env.IMHEX_VERSION }} tag: ImHex-v${{ env.IMHEX_VERSION }}
repo: ImHex-Patterns repo: ImHex-Patterns
token: ${{ secrets.RELEASE_TOKEN }} token: ${{ secrets.RELEASE_TOKEN }}
skipIfReleaseExists: true
- name: 🎫 Create imhex-download-sdk release - name: 🎫 Create imhex-download-sdk release
uses: ncipollo/release-action@v1 uses: ncipollo/release-action@v1
@@ -69,13 +61,11 @@ jobs:
tag: v${{ env.IMHEX_VERSION }} tag: v${{ env.IMHEX_VERSION }}
repo: imhex-download-sdk repo: imhex-download-sdk
token: ${{ secrets.RELEASE_TOKEN }} token: ${{ secrets.RELEASE_TOKEN }}
skipIfReleaseExists: true
release-upload-artifacts: release-upload-artifacts:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
name: Release Upload Artifacts name: Release Upload Artifacts
outputs:
IMHEX_VERSION: ${{ steps.verify_version.outputs.IMHEX_VERSION }}
steps: steps:
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -84,19 +74,17 @@ jobs:
submodules: recursive submodules: recursive
- name: 📜 Verify version and set version variable - name: 📜 Verify version and set version variable
id: verify_version
run: | run: |
set -x set -x
project_version=`cat ImHex/VERSION` project_version=`cat ImHex/VERSION`
tag_version="${{github.event.release.tag_name}}" tag_version="${{github.event.release.tag_name}}"
tag_version="${tag_version:1}" tag_version="${tag_version:1}"
if [ "$project_version" != "$tag_version" ] && [ ! -z "$tag_version" ]; then if [ "$project_version" != "$tag_version" ]; then
echo "::warning::$project_version and $tag_version are not the same ! Refusing to populate release" echo "::warning::$project_version and $tag_version are not the same ! Refusing to populate release"
exit 1 exit 1
fi fi
echo "IMHEX_VERSION=$project_version" >> $GITHUB_ENV echo "IMHEX_VERSION=$project_version" >> $GITHUB_ENV
echo "IMHEX_VERSION=$project_version" >> $GITHUB_OUTPUT
- name: 🗜️ Create tarball from sources with dependencies - name: 🗜️ Create tarball from sources with dependencies
run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex
@@ -109,7 +97,6 @@ jobs:
branch: ${{ github.event.release.target_commitish }} branch: ${{ github.event.release.target_commitish }}
workflow_conclusion: success workflow_conclusion: success
skip_unpack: true skip_unpack: true
commit: ${{ github.event.inputs.commit_hash }}
- name: 🗜️ Unzip files when needed - name: 🗜️ Unzip files when needed
run: | run: |
@@ -128,87 +115,27 @@ jobs:
- name: 🟩 Rename artifacts when needed - name: 🟩 Rename artifacts when needed
run: | run: |
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip || true mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip
mv "Windows Portable arm64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-arm64.zip || true mv "Windows Portable arm64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-arm64.zip
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip || true mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-Web.zip || true mv ./*_amd64.snap $(echo ./*_amd64.snap | sed 's/_amd64\.snap$/-x86_64.snap/' | sed 's/_/-/1')
mv ./*_arm64.snap $(echo ./*_arm64.snap | sed 's/_arm64\.snap$/-arm64.snap/' | sed 's/_/-/1')
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-Web.zip
rm artifact.tar || true rm artifact.tar || true
- name: ⬆️ Upload Unsigned x86_64 Windows Installer
uses: actions/upload-artifact@v4
id: upload-installer-x86_64
with:
if-no-files-found: error
name: Windows Installer x86_64
path: |
imhex-*-x86_64.msi
- name: ⬆️ Upload Unsigned ARM64 Windows Installer
if: false
uses: actions/upload-artifact@v4
id: upload-installer-arm64
with:
if-no-files-found: error
name: Windows Installer ARM64
path: |
imhex-*-arm64.msi
- name: 🗑️ Delete unsigned installers
run: |
rm imhex-*-x86_64.msi
- name: 🗝️ Sign x86_64 Installer
uses: signpath/github-action-submit-signing-request@v1
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
organization-id: 'f605a0e8-86cd-411c-bb6f-e05025afcc33'
project-slug: 'ImHex'
signing-policy-slug: 'release-signing'
github-artifact-id: '${{ steps.upload-installer-x86_64.outputs.artifact-id }}'
wait-for-completion: true
output-artifact-directory: '.'
- name: 🗝️ Sign ARM64 Installer
if: false
uses: signpath/github-action-submit-signing-request@v1
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
organization-id: 'f605a0e8-86cd-411c-bb6f-e05025afcc33'
project-slug: 'ImHex'
signing-policy-slug: 'release-signing'
github-artifact-id: '${{ steps.upload-installer-arm64.outputs.artifact-id }}'
wait-for-completion: true
output-artifact-directory: '.'
- name: ⬆️ Upload everything to release - name: ⬆️ Upload everything to release
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981 uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
with: with:
files: '*' files: '*'
release-update-aur:
name: Release update AUR package
needs: release-upload-artifacts
runs-on: ubuntu-24.04
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
with:
path: ImHex
- name: ⬇️ Download artifacts
run: |
tagname=${GITHUB_REF#refs/tags/}
version=${tagname#v}
wget https://github.com/WerWolv/ImHex/releases/download/${tagname}/imhex-${version}-ArchLinux-x86_64.pkg.tar.zst
- name: ✒️ Prepare PKGBUILD - name: ✒️ Prepare PKGBUILD
run: | run: |
set -x set -x
cp ImHex/dist/Arch/PKGBUILD . cp ImHex/dist/Arch/PKGBUILD .
hash=`md5sum imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst | cut -d ' ' -f 1` hash=`md5sum imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst | cut -d ' ' -f 1`
sed -i 's/%version%/${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}/g' PKGBUILD sed -i 's/%version%/${{ env.IMHEX_VERSION }}/g' PKGBUILD
sed -i "s/(SKIP)/($hash)/g" PKGBUILD sed -i "s/(SKIP)/($hash)/g" PKGBUILD
- name: ⬆️ Publish AUR package - name: ⬆️ Publish AUR package
@@ -222,9 +149,9 @@ jobs:
pkgname: imhex-bin pkgname: imhex-bin
pkgbuild: ./PKGBUILD pkgbuild: ./PKGBUILD
commit_username: iTrooz commit_username: iTrooz
commit_email: hey@itrooz.fr commit_email: itrooz@protonmail.com
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }} ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
commit_message: Bump to version ${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }} commit_message: Bump to version ${{ env.IMHEX_VERSION }}
ssh_keyscan_types: rsa,ecdsa,ed25519 ssh_keyscan_types: rsa,ecdsa,ed25519
release-update-winget: release-update-winget:
@@ -236,7 +163,6 @@ jobs:
shell: pwsh shell: pwsh
run: | run: |
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
- name: ⬆️ Update winget manifest - name: ⬆️ Update winget manifest
shell: pwsh shell: pwsh
env: env:
@@ -254,7 +180,7 @@ jobs:
release-update-snapstore: release-update-snapstore:
name: Release update snapstore package name: Release update snapstore package
needs: release-upload-artifacts needs: release-upload-artifacts
runs-on: ubuntu-24.04 runs-on: ubuntu-20.04
steps: steps:
- name: ⬇️ Download artifacts - name: ⬇️ Download artifacts
run: | run: |
@@ -264,19 +190,17 @@ jobs:
wget https://github.com/WerWolv/ImHex/releases/download/${tagname}/imhex-${version}-arm64.snap wget https://github.com/WerWolv/ImHex/releases/download/${tagname}/imhex-${version}-arm64.snap
- name: ⬆️ Publish x86_64 Snap package - name: ⬆️ Publish x86_64 Snap package
continue-on-error: true
uses: snapcore/action-publish@v1 uses: snapcore/action-publish@v1
env: env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }} SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
with: with:
snap: imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-x86_64.snap snap: imhex-${{ env.IMHEX_VERSION }}-x86_64.snap
release: stable release: stable
- name: ⬆️ Publish arm64 Snap package - name: ⬆️ Publish arm64 Snap package
continue-on-error: true
uses: snapcore/action-publish@v1 uses: snapcore/action-publish@v1
env: env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }} SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
with: with:
snap: imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-arm64.snap snap: imhex-${{ env.IMHEX_VERSION }}-arm64.snap
release: stable release: stable

2
.gitignore vendored
View File

@@ -12,8 +12,6 @@
/install/ /install/
/out/ /out/
/dist/ImHex.run.xml
*.mgc *.mgc
*.kdev4 *.kdev4
imgui.ini imgui.ini

4
.gitmodules vendored
View File

@@ -18,6 +18,10 @@
path = lib/third_party/capstone path = lib/third_party/capstone
url = https://github.com/capstone-engine/capstone url = https://github.com/capstone-engine/capstone
ignore = dirty ignore = dirty
[submodule "lib/third_party/jthread/jthread"]
path = lib/third_party/jthread/jthread
url = https://github.com/josuttis/jthread
ignore = dirty
[submodule "lib/third_party/edlib"] [submodule "lib/third_party/edlib"]
path = lib/third_party/edlib path = lib/third_party/edlib
url = https://github.com/Martinsos/edlib url = https://github.com/Martinsos/edlib

View File

@@ -1,39 +1,33 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
# Options # Options
## General option(IMHEX_PLUGINS_IN_SHARE "Put the plugins in share/imhex/plugins instead of lib[..]/imhex/plugins (Linux only)" OFF)
option(IMHEX_STRIP_RELEASE "Strip the release builds" ON ) option(IMHEX_STRIP_RELEASE "Strip the release builds" ON )
option(IMHEX_OFFLINE_BUILD "Enable offline build" OFF) option(IMHEX_OFFLINE_BUILD "Enable offline build" OFF)
option(IMHEX_IGNORE_BAD_CLONE "Disable the bad clone prevention checks" OFF) option(IMHEX_IGNORE_BAD_CLONE "Disable the bad clone prevention checks" OFF)
option(IMHEX_PATTERNS_PULL_MASTER "Download latest files from master branch of the ImHex-Patterns repo" OFF) option(IMHEX_PATTERNS_PULL_MASTER "Download latest files from master branch of the ImHex-Patterns repo" OFF)
option(IMHEX_IGNORE_BAD_COMPILER "Allow compiling with an unsupported compiler" OFF) option(IMHEX_IGNORE_BAD_COMPILER "Allow compiling with an unsupported compiler" OFF)
option(IMHEX_USE_GTK_FILE_PICKER "Use GTK file picker instead of xdg-desktop-portals (Linux only)" OFF) option(IMHEX_USE_GTK_FILE_PICKER "Use GTK file picker instead of xdg-desktop-portals (Linux only)" OFF)
option(IMHEX_DISABLE_STACKTRACE "Disables support for printing stack traces" OFF)
option(IMHEX_BUNDLE_DOTNET "Bundle .NET runtime" ON ) option(IMHEX_BUNDLE_DOTNET "Bundle .NET runtime" ON )
option(IMHEX_ENABLE_LTO "Enables Link Time Optimizations if possible" OFF) option(IMHEX_ENABLE_LTO "Enables Link Time Optimizations if possible" OFF)
option(IMHEX_USE_DEFAULT_BUILD_SETTINGS "Use default build settings" OFF) option(IMHEX_USE_DEFAULT_BUILD_SETTINGS "Use default build settings" OFF)
option(IMHEX_STRICT_WARNINGS "Enable most available warnings and treat them as errors" ON )
option(IMHEX_BUILD_HARDENING "Enable hardening flags for build" ON ) option(IMHEX_BUILD_HARDENING "Enable hardening flags for build" ON )
option(IMHEX_GENERATE_PACKAGE "Specify if a cpack package should be built. (Windows only)" OFF) option(IMHEX_STATIC_LINK_PLUGINS "Statically link all plugins into the main executable" OFF)
option(IMHEX_MACOS_CREATE_BUNDLE "Creates a macOS .app bundle when building (macOS only)" ON ) option(IMHEX_GENERATE_PACKAGE "Specify if a native package should be built. (Windows and MacOS only)" OFF)
option(IMHEX_ENABLE_UNITY_BUILD "Enables building ImHex as a unity build." OFF) option(IMHEX_ENABLE_UNITY_BUILD "Enables building ImHex as a unity build." OFF)
option(IMHEX_GENERATE_PDBS "Enable generating PDB files in non-debug builds (Windows only)" OFF)
option(IMHEX_REPLACE_DWARF_WITH_PDB "Remove DWARF information from binaries when generating PDBS (Windows only)" OFF)
option(IMHEX_ENABLE_STD_ASSERTS "Enable debug asserts in the C++ std library. (Breaks Plugin ABI!)" OFF)
option(IMHEX_ENABLE_UNIT_TESTS "Enable building unit tests" ON )
option(IMHEX_ENABLE_PLUGIN_TESTS "Enable building plugin tests" ON )
option(IMHEX_ENABLE_IMGUI_TEST_ENGINE "Enable the ImGui Test Engine" OFF)
option(IMHEX_ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF) option(IMHEX_ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF)
option(IMHEX_COMPRESS_DEBUG_INFO "Compress debug information" ON )
option(IMHEX_ENABLE_CXX_MODULES "Enable C++20 Module compilation. Testing only!" OFF) option(IMHEX_ENABLE_CXX_MODULES "Enable C++20 Module compilation. Testing only!" OFF)
option(IMHEX_ENABLE_CPPCHECK "Enable cppcheck static analysis" OFF) option(IMHEX_ENABLE_CPPCHECK "Enable cppcheck static analysis" OFF)
option(IMHEX_BUNDLE_PLUGIN_SDK "Enable bundling of Plugin SDK into install package" ON ) option(IMHEX_BUNDLE_PLUGIN_SDK "Enable bundling of Plugin SDK into install package" ON )
## Testing
option(IMHEX_ENABLE_UNIT_TESTS "Enable building unit tests" ON )
option(IMHEX_ENABLE_IMGUI_TEST_ENGINE "Enable the ImGui Test Engine" OFF)
option(IMHEX_ENABLE_STD_ASSERTS "Enable debug asserts in the C++ std library. (Breaks Plugin ABI!)" OFF)
## Debug info
option(IMHEX_COMPRESS_DEBUG_INFO "Compress debug information" ON )
option(IMHEX_GENERATE_PDBS "Enable generating PDB files in non-debug builds (Windows only)" OFF)
option(IMHEX_REPLACE_DWARF_WITH_PDB "Remove DWARF information from binaries when generating PDBS (Windows only)" OFF)
option(IMHEX_STRICT_WARNINGS "Enable most available warnings and treat them as errors" ON )
option(IMHEX_DISABLE_STACKTRACE "Disables support for printing stack traces" OFF)
## Plugins
option(IMHEX_STATIC_LINK_PLUGINS "Statically link all plugins into the main executable" OFF)
option(IMHEX_ENABLE_PLUGIN_TESTS "Enable building plugin tests" ON )
option(IMHEX_INCLUDE_PLUGINS "Semicolon-separated list of plugins to include in the build (empty = build all)" "" )
option(IMHEX_EXCLUDE_PLUGINS "Semicolon-separated list of plugins to exclude from the build" "" )
set(IMHEX_BASE_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}") set(IMHEX_BASE_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}")
set(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules") set(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules")
@@ -53,7 +47,7 @@ loadVersion(IMHEX_VERSION IMHEX_VERSION_PLAIN)
setVariableInParent(IMHEX_VERSION ${IMHEX_VERSION}) setVariableInParent(IMHEX_VERSION ${IMHEX_VERSION})
configureCMake() configureCMake()
project(ImHex project(imhex
LANGUAGES C CXX LANGUAGES C CXX
VERSION ${IMHEX_VERSION_PLAIN} VERSION ${IMHEX_VERSION_PLAIN}
DESCRIPTION "The ImHex Hex Editor" DESCRIPTION "The ImHex Hex Editor"

View File

@@ -59,14 +59,13 @@
{ {
"name": "vs2022-x86", "name": "vs2022-x86",
"displayName": "Visual Studio 2022 x86", "displayName": "Visual Studio 2022 x86",
"generator": "Ninja", "generator": "Visual Studio 17 2022",
"binaryDir": "${sourceDir}/build/${presetName}", "binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": { "cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_GENERATOR_PLATFORM": "Win32",
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"VCPKG_MANIFEST_DIR": "${sourceDir}/dist" "VCPKG_MANIFEST_DIR": "${sourceDir}/dist"
},
"environment": {
"VSCMD_ARG_TGT_ARCH": "x86"
} }
} }
], ],

View File

@@ -29,23 +29,14 @@
## Supporting ## Supporting
If you like my work, please consider supporting me on GitHub Sponsors, Ko-Fi or PayPal. Thanks a lot! If you like my work, please consider supporting me on GitHub Sponsors, Patreon or PayPal. Thanks a lot!
<p align="center"> <p align="center">
<a href="https://github.com/sponsors/WerWolv"><img src="https://werwolv.net/assets/github_banner.png" alt="GitHub donate button" /></a> <a href="https://github.com/sponsors/WerWolv"><img src="https://werwolv.net/assets/github_banner.png" alt="GitHub donate button" /></a>
<a href="https://ko-fi.com/WerWolv"><img src="https://werwolv.net/assets/kofi_banner.png" alt="Ko-Fi donate button" /></a> <a href="https://www.patreon.com/werwolv"><img src="https://c5.patreon.com/external/logo/become_a_patron_button.png" alt="Patreon donate button" /></a>
<a href="https://werwolv.net/donate"><img src="https://werwolv.net/assets/paypal_banner.png" alt="PayPal donate button" /></a> <a href="https://werwolv.net/donate"><img src="https://werwolv.net/assets/paypal_banner.png" alt="PayPal donate button" /></a>
</p> </p>
### Notable Sponsors
| | |
|:---------------------------------------------------------------------------------------------------:|-----------------------------------------------------------------------------------|
| [![JetBrains logo](https://avatars.githubusercontent.com/u/878437?s=48)](https://www.jetbrains.com) | JetBrains, providing us with free All Products Pack licenses for development |
| [![SignPath logo](https://avatars.githubusercontent.com/u/34448643?s=48)](https://signpath.io/) | SignPath, providing us with free Code Signing Certificates for our Windows builds |
| [![AWS logo](https://avatars.githubusercontent.com/u/2232217?s=48)](https://aws.amazon.com) | Amazon, providing us with free AWS Cloud Credits for our CI |
Would you like to appear here as well? Contact us at [imhex@werwolv.net](mailto:imhex@werwolv.net)!
## Screenshots ## Screenshots
![Hex editor, patterns and data information](https://github.com/user-attachments/assets/902a7c4c-410d-490f-999e-14c856fec027) ![Hex editor, patterns and data information](https://github.com/user-attachments/assets/902a7c4c-410d-490f-999e-14c856fec027)
![Bookmarks, data information, find view and data processor](https://github.com/user-attachments/assets/58eefa1f-31c9-4bb8-a1c1-8cdd8ddbd29f) ![Bookmarks, data information, find view and data processor](https://github.com/user-attachments/assets/58eefa1f-31c9-4bb8-a1c1-8cdd8ddbd29f)
@@ -336,8 +327,8 @@ To use ImHex, the following minimal system requirements need to be met.
- **OS**: - **OS**:
- **Windows**: Windows 7 or higher (Windows 10/11 recommended) - **Windows**: Windows 7 or higher (Windows 10/11 recommended)
- **macOS**: macOS 15 (Sequoia) or higher, - **macOS**: macOS 13 (Ventura) or higher,
- Lower versions should still work too, but you'll need to compile ImHex yourself. The release binaries will NOT work due to GitHub not having any macOS 15 or lower CI runners available. - Lower versions should still work too, but you'll need to compile ImHex yourself. The release binaries will NOT work due to GitHub not having any macOS 12 or lower CI runners available.
- The macOS build is not signed and will require you to manually allow them in the Security & Privacy settings. - The macOS build is not signed and will require you to manually allow them in the Security & Privacy settings.
- **Linux**: "Modern" Linux. The following distributions have official releases available. Other distros are supported through the AppImage, Flatpak and Snap releases. - **Linux**: "Modern" Linux. The following distributions have official releases available. Other distros are supported through the AppImage, Flatpak and Snap releases.
- Ubuntu and Debian - Ubuntu and Debian
@@ -375,20 +366,9 @@ For more information, check out the [Compiling](/dist/compiling) guide.
## Contributing ## Contributing
See [Contributing](/CONTRIBUTING.md) See [Contributing](/CONTRIBUTING.md)
## Plugin development ## Plugin development
To develop plugins for ImHex, use the following template project to get started. You then have access to the entirety of libimhex as well as the ImHex API and the Content Registry to interact with ImHex or to add new content. To develop plugins for ImHex, use the following template project to get started. You then have access to the entirety of libimhex as well as the ImHex API and the Content Registry to interact with ImHex or to add new content.
To build a plugin, you will need to use our SDK
### Getting the SDK locally
You can build the SDK by compiling ImHex like this:
- `cmake -G Ninja -DIMHEX_BUNDLE_PLUGIN_SDK=ON -B build`
- `cd build`
- `DESTDIR=install ninja install`
The SDK will then be available at `install/usr/local/share/imhex/sdk`. You will need to set the variable `IMHEX_SDK_PATH` to that (absolute) path.
### Getting the SDK in a Github Actions CI
You can use [this action](https://github.com/WerWolv/imhex-download-sdk) to automatically download the SDK to your Github Runner
- [ImHex Plugin Template](https://github.com/WerWolv/ImHex-Plugin-Template) - [ImHex Plugin Template](https://github.com/WerWolv/ImHex-Plugin-Template)
@@ -430,18 +410,3 @@ Notable exceptions to this are the following parts which are under the LGPLv2.1
- **/plugins/ui**: The UI plugin library that contains some common UI elements that can be used by other plugins - **/plugins/ui**: The UI plugin library that contains some common UI elements that can be used by other plugins
The reason for this is to allow for proprietary plugins to be developed for ImHex. The reason for this is to allow for proprietary plugins to be developed for ImHex.
### Code Signing Policy
Free code signing provided by [SignPath.io](https://about.signpath.io/),
certificate by [SignPath Foundation](https://signpath.org/).
This program will not transfer any information to other networked systems
unless specifically requested by the user or the person installing or
operating it.
#### People with direct push access
- [WerWolv](https://github.com/WerWolv)
- [iTrooz](https://github.com/iTrooz)
- [jumanji144](https://github.com/jumanji144)
- [AxCut](https://github.com/paxcut)

View File

@@ -1 +1 @@
1.39.0.WIP 1.38.0.WIP

View File

View File

@@ -175,11 +175,15 @@ macro(detectOS)
endif() endif()
include(GNUInstallDirs) include(GNUInstallDirs)
if(IMHEX_PLUGINS_IN_SHARE)
set(PLUGINS_INSTALL_LOCATION "share/imhex/plugins")
else()
set(PLUGINS_INSTALL_LOCATION "${CMAKE_INSTALL_LIBDIR}/imhex/plugins") set(PLUGINS_INSTALL_LOCATION "${CMAKE_INSTALL_LIBDIR}/imhex/plugins")
# Add System plugin location for plugins to be loaded from # Add System plugin location for plugins to be loaded from
# IMPORTANT: This does not work for Sandboxed or portable builds such as the Flatpak or AppImage release # IMPORTANT: This does not work for Sandboxed or portable builds such as the Flatpak or AppImage release
add_compile_definitions(SYSTEM_PLUGINS_LOCATION="${CMAKE_INSTALL_FULL_LIBDIR}/imhex") add_compile_definitions(SYSTEM_PLUGINS_LOCATION="${CMAKE_INSTALL_FULL_LIBDIR}/imhex")
endif()
else () else ()
message(FATAL_ERROR "Unknown / unsupported system!") message(FATAL_ERROR "Unknown / unsupported system!")
@@ -201,18 +205,11 @@ macro(configurePackingResources)
set(CPACK_GENERATOR "WIX") set(CPACK_GENERATOR "WIX")
set(CPACK_PACKAGE_NAME "ImHex") set(CPACK_PACKAGE_NAME "ImHex")
set(CPACK_PACKAGE_VENDOR "WerWolv") set(CPACK_PACKAGE_VENDOR "WerWolv")
set(CPACK_WIX_VERSION 4)
set(CPACK_WIX_PRODUCT_GUID "*")
set(CPACK_WIX_UPGRADE_GUID "05000E99-9659-42FD-A1CF-05C554B39285") set(CPACK_WIX_UPGRADE_GUID "05000E99-9659-42FD-A1CF-05C554B39285")
set(CPACK_WIX_PRODUCT_ICON "${PROJECT_SOURCE_DIR}/resources/dist/windows/icon.ico") set(CPACK_WIX_PRODUCT_ICON "${PROJECT_SOURCE_DIR}/resources/dist/windows/icon.ico")
set(CPACK_WIX_UI_BANNER "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_banner.png") set(CPACK_WIX_UI_BANNER "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_banner.png")
set(CPACK_WIX_UI_DIALOG "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_dialog.png") set(CPACK_WIX_UI_DIALOG "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_dialog.png")
set(CPACK_WIX_CULTURES "en-US;de-DE;ja-JP;it-IT;pt-BR;zh-CN;zh-TW;ru-RU") set(CPACK_WIX_CULTURES "en-US;de-DE;ja-JP;it-IT;pt-BR;zh-CN;zh-TW;ru-RU")
set(CPACK_WIX_TEMPLATE "${PROJECT_SOURCE_DIR}/resources/dist/windows/WIX.template.in")
set(CPACK_WIX_EXTENSIONS "WixToolset.UI.wixext")
file(GLOB_RECURSE CPACK_WIX_EXTRA_SOURCES "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix/*.wxs")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "ImHex") set(CPACK_PACKAGE_INSTALL_DIRECTORY "ImHex")
set_property(INSTALL "$<TARGET_FILE_NAME:main>" set_property(INSTALL "$<TARGET_FILE_NAME:main>"
PROPERTY CPACK_START_MENU_SHORTCUTS "ImHex" PROPERTY CPACK_START_MENU_SHORTCUTS "ImHex"
@@ -221,9 +218,9 @@ macro(configurePackingResources)
endif() endif()
elseif (APPLE OR ${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin") elseif (APPLE OR ${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin")
set(IMHEX_ICON "${IMHEX_BASE_FOLDER}/resources/dist/macos/AppIcon.icns") set(IMHEX_ICON "${IMHEX_BASE_FOLDER}/resources/dist/macos/AppIcon.icns")
set(BUNDLE_NAME "ImHex.app") set(BUNDLE_NAME "imhex.app")
if (IMHEX_MACOS_CREATE_BUNDLE) if (IMHEX_GENERATE_PACKAGE)
set(APPLICATION_TYPE MACOSX_BUNDLE) set(APPLICATION_TYPE MACOSX_BUNDLE)
set_source_files_properties(${IMHEX_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") set_source_files_properties(${IMHEX_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
set(MACOSX_BUNDLE_ICON_FILE "AppIcon.icns") set(MACOSX_BUNDLE_ICON_FILE "AppIcon.icns")
@@ -259,7 +256,7 @@ macro(addPluginDirectories)
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${IMHEX_MAIN_OUTPUT_DIRECTORY}/plugins") set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${IMHEX_MAIN_OUTPUT_DIRECTORY}/plugins")
if (APPLE) if (APPLE)
if (IMHEX_MACOS_CREATE_BUNDLE) if (IMHEX_GENERATE_PACKAGE)
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGINS_INSTALL_LOCATION}) set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGINS_INSTALL_LOCATION})
endif () endif ()
else () else ()
@@ -315,7 +312,7 @@ macro(createPackage)
POST_EXCLUDE_REGEXES ".*system32/.*\\.dll" POST_EXCLUDE_REGEXES ".*system32/.*\\.dll"
) )
if(_c_deps_FILENAMES AND _c_deps AND NOT (_c_deps STREQUAL "")) if(_c_deps_FILENAMES AND NOT _c_deps STREQUAL "")
message(WARNING "Conflicting dependencies for library: \"${_c_deps}\"!") message(WARNING "Conflicting dependencies for library: \"${_c_deps}\"!")
endif() endif()
@@ -336,47 +333,41 @@ macro(createPackage)
downloadImHexPatternsFiles(".") downloadImHexPatternsFiles(".")
elseif(UNIX AND NOT APPLE) elseif(UNIX AND NOT APPLE)
set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION}) set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION})
configure_file(${IMHEX_BASE_FOLDER}/dist/DEBIAN/control.in ${CMAKE_BINARY_DIR}/DEBIAN/control) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dist/DEBIAN/control.in ${CMAKE_BINARY_DIR}/DEBIAN/control)
install(FILES ${IMHEX_BASE_FOLDER}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex)
install(FILES ${IMHEX_BASE_FOLDER}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
install(FILES ${IMHEX_BASE_FOLDER}/dist/imhex.mime.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages RENAME imhex.xml) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.mime.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages RENAME imhex.xml)
install(FILES ${IMHEX_BASE_FOLDER}/resources/icon.svg DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.svg) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.svg DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.svg)
downloadImHexPatternsFiles("./share/imhex") downloadImHexPatternsFiles("./share/imhex")
# install AppStream file # install AppStream file
install(FILES ${IMHEX_BASE_FOLDER}/dist/net.werwolv.ImHex.metainfo.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/net.werwolv.ImHex.metainfo.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo)
endif() endif()
if (APPLE) if (APPLE)
if (IMHEX_MACOS_CREATE_BUNDLE) if (IMHEX_GENERATE_PACKAGE)
set(EXTRA_BUNDLE_LIBRARY_PATHS ${EXTRA_BUNDLE_LIBRARY_PATHS} "${IMHEX_SYSTEM_LIBRARY_PATH}") set(EXTRA_BUNDLE_LIBRARY_PATHS ${EXTRA_BUNDLE_LIBRARY_PATHS} "${IMHEX_SYSTEM_LIBRARY_PATH}")
include(PostprocessBundle) include(PostprocessBundle)
set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION}) set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION})
set_property(TARGET main PROPERTY MACOSX_BUNDLE_INFO_PLIST ${MACOSX_BUNDLE_INFO_PLIST}) set_property(TARGET main PROPERTY MACOSX_BUNDLE_INFO_PLIST ${MACOSX_BUNDLE_INFO_PLIST})
set_property(TARGET main PROPERTY MACOSX_BUNDLE_BUNDLE_NAME "${MACOSX_BUNDLE_BUNDLE_NAME}")
# Fix rpath # Fix rpath
install(CODE "execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath \"@executable_path/../Frameworks/\" $<TARGET_FILE:main>)") install(CODE "execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath \"@executable_path/../Frameworks/\" $<TARGET_FILE:main>)")
install(CODE "execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath \"@executable_path/../Frameworks/\" $<TARGET_FILE:updater>)")
add_custom_target(build-time-make-plugins-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${IMHEX_BUNDLE_PATH}/Contents/MacOS/plugins")
add_custom_target(build-time-make-resources-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${IMHEX_BUNDLE_PATH}/Contents/Resources")
downloadImHexPatternsFiles("${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/MacOS") downloadImHexPatternsFiles("${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/MacOS")
install(FILES ${IMHEX_ICON} DESTINATION "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Resources")
install(TARGETS main BUNDLE DESTINATION ".") install(TARGETS main BUNDLE DESTINATION ".")
install(TARGETS updater DESTINATION "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/MacOS") install(TARGETS updater BUNDLE DESTINATION ".")
install(
FILES ${IMHEX_BASE_FOLDER}/dist/cli/imhex.sh
DESTINATION "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/MacOS/cli"
RENAME imhex
PERMISSIONS
OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE
)
# Update library references to make the bundle portable # Update library references to make the bundle portable
postprocess_bundle(imhex_all main) postprocess_bundle(imhex_all main)
@@ -407,31 +398,9 @@ macro(createPackage)
if (TARGET main-forwarder) if (TARGET main-forwarder)
install(TARGETS main-forwarder BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}) install(TARGETS main-forwarder BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR})
endif() endif()
if (WIN32)
install(
FILES ${IMHEX_BASE_FOLDER}/dist/cli/imhex.bat
DESTINATION ${CMAKE_INSTALL_BINDIR}/cli
RENAME imhex.bat
PERMISSIONS
OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE
)
else()
install(
FILES ${IMHEX_BASE_FOLDER}/dist/cli/imhex.sh
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/imhex
RENAME imhex
PERMISSIONS
OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE
)
endif()
endif() endif()
if (IMHEX_MACOS_CREATE_BUNDLE) if (IMHEX_GENERATE_PACKAGE)
set(CPACK_BUNDLE_NAME "ImHex") set(CPACK_BUNDLE_NAME "ImHex")
include(CPack) include(CPack)
@@ -560,9 +529,6 @@ function(detectBadClone)
file (GLOB EXTERNAL_DIRS "lib/external/*" "lib/third_party/*") file (GLOB EXTERNAL_DIRS "lib/external/*" "lib/third_party/*")
foreach (EXTERNAL_DIR ${EXTERNAL_DIRS}) foreach (EXTERNAL_DIR ${EXTERNAL_DIRS})
if(NOT IS_DIRECTORY "${EXTERNAL_DIR}")
continue()
endif()
file(GLOB_RECURSE RESULT "${EXTERNAL_DIR}/*") file(GLOB_RECURSE RESULT "${EXTERNAL_DIR}/*")
list(LENGTH RESULT ENTRY_COUNT) list(LENGTH RESULT ENTRY_COUNT)
if(ENTRY_COUNT LESS_EQUAL 1) if(ENTRY_COUNT LESS_EQUAL 1)
@@ -590,9 +556,7 @@ endfunction()
macro(detectBundledPlugins) macro(detectBundledPlugins)
file(GLOB PLUGINS_DIRS "plugins/*") file(GLOB PLUGINS_DIRS "plugins/*")
if (IMHEX_INCLUDE_PLUGINS) if (NOT DEFINED IMHEX_INCLUDE_PLUGINS)
set(PLUGINS ${IMHEX_INCLUDE_PLUGINS})
else()
foreach(PLUGIN_DIR ${PLUGINS_DIRS}) foreach(PLUGIN_DIR ${PLUGINS_DIRS})
if (EXISTS "${PLUGIN_DIR}/CMakeLists.txt") if (EXISTS "${PLUGIN_DIR}/CMakeLists.txt")
get_filename_component(PLUGIN_NAME ${PLUGIN_DIR} NAME) get_filename_component(PLUGIN_NAME ${PLUGIN_DIR} NAME)
@@ -601,6 +565,8 @@ macro(detectBundledPlugins)
endif () endif ()
endif() endif()
endforeach() endforeach()
else()
set(PLUGINS ${IMHEX_INCLUDE_PLUGINS})
endif() endif()
foreach(PLUGIN_NAME ${PLUGINS}) foreach(PLUGIN_NAME ${PLUGINS})
@@ -611,13 +577,9 @@ macro(detectBundledPlugins)
message(FATAL_ERROR "No bundled plugins enabled") message(FATAL_ERROR "No bundled plugins enabled")
endif() endif()
set(REQUIRED_PLUGINS builtin fonts ui) if (NOT ("builtin" IN_LIST PLUGINS))
foreach(PLUGIN ${REQUIRED_PLUGINS}) message(FATAL_ERROR "The 'builtin' plugin is required for ImHex to work!")
list(FIND PLUGINS ${PLUGIN} PLUGIN_INDEX)
if (PLUGIN_INDEX EQUAL -1)
message(FATAL_ERROR "Required plugin '${PLUGIN}' is not enabled!")
endif () endif ()
endforeach()
endmacro() endmacro()
macro(setVariableInParent variable value) macro(setVariableInParent variable value)
@@ -643,15 +605,17 @@ function(downloadImHexPatternsFiles dest)
install(CODE "set(imhex_patterns_SOURCE_DIR \"${imhex_patterns_SOURCE_DIR}\")") install(CODE "set(imhex_patterns_SOURCE_DIR \"${imhex_patterns_SOURCE_DIR}\")")
install(CODE [[ install(CODE [[
message(STATUS "Downloading ImHex patterns from branch '${PATTERNS_BRANCH}'...") message(STATUS "Downloading ImHex patterns from branch '${PATTERNS_BRANCH}'...")
if (NOT EXISTS "${imhex_patterns_SOURCE_DIR}") if (EXISTS "${imhex_patterns_SOURCE_DIR}")
file(REMOVE_RECURSE "${imhex_patterns_SOURCE_DIR}")
else ()
file(MAKE_DIRECTORY "${imhex_patterns_SOURCE_DIR}") file(MAKE_DIRECTORY "${imhex_patterns_SOURCE_DIR}")
endif()
execute_process( execute_process(
COMMAND COMMAND
git clone --recurse-submodules --branch ${PATTERNS_BRANCH} https://github.com/WerWolv/ImHex-Patterns.git "${imhex_patterns_SOURCE_DIR}" git clone --recurse-submodules --branch ${PATTERNS_BRANCH} https://github.com/WerWolv/ImHex-Patterns.git "${imhex_patterns_SOURCE_DIR}"
COMMAND_ERROR_IS_FATAL ANY COMMAND_ERROR_IS_FATAL ANY
) )
endif()
]]) ]])
else () else ()
set(imhex_patterns_SOURCE_DIR "") set(imhex_patterns_SOURCE_DIR "")
@@ -781,19 +745,15 @@ macro(setupCompilerFlags target)
endif() endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND APPLE) if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND APPLE)
addCCXXFlag("-Wno-unknown-warning-option" ${target})
# On macOS, when using clang from Homebrew, properly setup the libc++ library path so
# it's using the one from Homebrew instead of the system one.
execute_process(COMMAND brew --prefix llvm OUTPUT_VARIABLE LLVM_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND brew --prefix llvm OUTPUT_VARIABLE LLVM_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
if (NOT LLVM_PREFIX STREQUAL "" AND ${CMAKE_CXX_COMPILER} STREQUAL "${LLVM_PREFIX}/bin/clang++")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++") addCCXXFlag("-Wno-unknown-warning-option" ${target})
endif()
if (CMAKE_BUILD_TYPE STREQUAL "Debug") if (CMAKE_BUILD_TYPE STREQUAL "Debug")
add_compile_definitions(_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG) add_compile_definitions(_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG)
else()
add_compile_definitions(_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE)
endif() endif()
endif() endif()
@@ -850,13 +810,6 @@ macro(setUninstallTarget)
endmacro() endmacro()
macro(addBundledLibraries) macro(addBundledLibraries)
# Make sure the build is using vcpkg on Windows and Emscripten, otherwise none of these dependencies will be found
if (MSVC OR EMSCRIPTEN)
if (NOT (CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg"))
message(AUTHOR_WARNING "Your current environment probably needs to be setup to use vcpkg, otherwise none of the dependencies will be found!")
endif()
endif()
set(EXTERNAL_LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/lib/external") set(EXTERNAL_LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/lib/external")
set(THIRD_PARTY_LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/lib/third_party") set(THIRD_PARTY_LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/lib/third_party")
set(BUILD_SHARED_LIBS OFF) set(BUILD_SHARED_LIBS OFF)
@@ -930,6 +883,18 @@ macro(addBundledLibraries)
find_package(LLVM REQUIRED Demangle) find_package(LLVM REQUIRED Demangle)
endif() endif()
if (NOT USE_SYSTEM_JTHREAD)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/jthread EXCLUDE_FROM_ALL)
set(JTHREAD_LIBRARIES jthread)
else()
find_path(JOSUTTIS_JTHREAD_INCLUDE_DIRS "condition_variable_any2.hpp")
include_directories(${JOSUTTIS_JTHREAD_INCLUDE_DIRS})
add_library(jthread INTERFACE)
target_include_directories(jthread INTERFACE ${JOSUTTIS_JTHREAD_INCLUDE_DIRS})
set(JTHREAD_LIBRARIES jthread)
endif()
if (USE_SYSTEM_BOOST) if (USE_SYSTEM_BOOST)
find_package(Boost REQUIRED CONFIG COMPONENTS regex) find_package(Boost REQUIRED CONFIG COMPONENTS regex)
set(BOOST_LIBRARIES Boost::regex) set(BOOST_LIBRARIES Boost::regex)

View File

@@ -2,7 +2,11 @@ find_path(LIBMAGIC_INCLUDE_DIR magic.h)
find_library(LIBMAGIC_LIBRARY NAMES magic) find_library(LIBMAGIC_LIBRARY NAMES magic)
find_package_handle_standard_args(Magic DEFAULT_MSG if (LIBMAGIC_INCLUDE_DIR AND LIBMAGIC_LIBRARY)
set(LIBMAGIC_FOUND TRUE)
endif (LIBMAGIC_INCLUDE_DIR AND LIBMAGIC_LIBRARY)
find_package_handle_standard_args("libmagic" DEFAULT_MSG
LIBMAGIC_LIBRARY LIBMAGIC_LIBRARY
LIBMAGIC_INCLUDE_DIR LIBMAGIC_INCLUDE_DIR
) )
@@ -10,5 +14,5 @@ find_package_handle_standard_args(Magic DEFAULT_MSG
mark_as_advanced( mark_as_advanced(
LIBMAGIC_INCLUDE_DIR LIBMAGIC_INCLUDE_DIR
LIBMAGIC_LIBRARY LIBMAGIC_LIBRARY
Magic_FOUND LIBMAGIC_FOUND
) )

View File

@@ -26,9 +26,8 @@ SET(MBEDTLS_FIND_QUIETLY TRUE)
FIND_LIBRARY(MBEDTLS_LIBRARY NAMES mbedtls libmbedtls libmbedx509) FIND_LIBRARY(MBEDTLS_LIBRARY NAMES mbedtls libmbedtls libmbedx509)
FIND_LIBRARY(MBEDX509_LIBRARY NAMES mbedx509 libmbedx509) FIND_LIBRARY(MBEDX509_LIBRARY NAMES mbedx509 libmbedx509)
FIND_LIBRARY(MBEDCRYPTO_LIBRARY NAMES mbedcrypto libmbedcrypto) FIND_LIBRARY(MBEDCRYPTO_LIBRARY NAMES mbedcrypto libmbedcrypto)
FIND_LIBRARY(TFPSACRYPTO_LIBRARY NAMES libtfpsacrypto tfpsacrypto)
IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND (MBEDCRYPTO_LIBRARY OR TFPSACRYPTO_LIBRARY)) IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND MBEDCRYPTO_LIBRARY)
SET(MBEDTLS_FOUND TRUE) SET(MBEDTLS_FOUND TRUE)
ENDIF() ENDIF()
@@ -38,24 +37,14 @@ IF(MBEDTLS_FOUND)
GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY} NAME_WE) GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY} NAME_WE)
GET_FILENAME_COMPONENT(MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY} NAME_WE) GET_FILENAME_COMPONENT(MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY} NAME_WE)
GET_FILENAME_COMPONENT(MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY} NAME_WE) GET_FILENAME_COMPONENT(MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY} NAME_WE)
GET_FILENAME_COMPONENT(TFPSACRYPTO_LIBRARY_FILE ${TFPSACRYPTO_LIBRARY} NAME_WE)
STRING(REGEX REPLACE "^lib" "" MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY_FILE}) STRING(REGEX REPLACE "^lib" "" MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY_FILE})
STRING(REGEX REPLACE "^lib" "" MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY_FILE}) STRING(REGEX REPLACE "^lib" "" MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY_FILE})
STRING(REGEX REPLACE "^lib" "" MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE}) STRING(REGEX REPLACE "^lib" "" MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE})
STRING(REGEX REPLACE "^lib" "" TFPSACRYPTO_LIBRARY_FILE ${TFPSACRYPTO_LIBRARY_FILE})
if (TFPSACRYPTO_LIBRARY)
SET(MBEDTLS_CRYPTO_LIBRARY_FILE ${TFPSACRYPTO_LIBRARY_FILE})
elseif (MBEDCRYPTO_LIBRARY)
SET(MBEDTLS_CRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE})
else ()
MESSAGE(FATAL_ERROR "Could not find mbedTLS Crypto library")
endif()
if (MSVC) if (MSVC)
SET(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY_FILE}.lib ${MBEDX509_LIBRARY_FILE}.lib ${MBEDTLS_CRYPTO_LIBRARY_FILE}.lib) SET(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY_FILE}.lib ${MBEDX509_LIBRARY_FILE}.lib ${MBEDCRYPTO_LIBRARY_FILE}.lib)
else() else()
SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDTLS_CRYPTO_LIBRARY_FILE}") SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}")
endif() endif()
IF(NOT MBEDTLS_FIND_QUIETLY) IF(NOT MBEDTLS_FIND_QUIETLY)

View File

@@ -65,9 +65,9 @@ elseif (APPLE)
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/trace/include") INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/trace/include")
else() else()
set_target_properties(libimhex PROPERTIES set_target_properties(libimhex PROPERTIES
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/libimhex.so" IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../libimhex.so"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex/include") INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex/include")
set_target_properties(tracing PROPERTIES set_target_properties(tracing PROPERTIES
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libtracing.a" IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../libtracing.a"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/trace/include") INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/trace/include")
endif() endif()

View File

@@ -15,8 +15,8 @@ AppDir:
- "{{ARCHITECTURE_PACKAGE}}" - "{{ARCHITECTURE_PACKAGE}}"
allow_unauthenticated: true allow_unauthenticated: true
sources: sources:
- sourceline: 'deb [arch=amd64] https://us.archive.ubuntu.com/ubuntu/ noble main restricted universe multiverse' - sourceline: 'deb [arch=amd64] http://us.archive.ubuntu.com/ubuntu/ oracular main restricted universe multiverse'
- sourceline: 'deb [arch=arm64] https://ports.ubuntu.com/ubuntu-ports/ noble main restricted universe multiverse' - sourceline: 'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ oracular main restricted universe multiverse'
include: include:
- libgdk-pixbuf2.0-0 - libgdk-pixbuf2.0-0
- libgdk-pixbuf2.0-common - libgdk-pixbuf2.0-common

View File

@@ -1,4 +1,4 @@
FROM ubuntu:24.04 as build FROM ubuntu:24.10 as build
# Used to invalidate layer cache but not mount cache # Used to invalidate layer cache but not mount cache
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493 # See https://github.com/moby/moby/issues/41715#issuecomment-733976493
@@ -30,9 +30,9 @@ ARG LTO=ON
ARG BUILD_TYPE=RelWithDebInfo ARG BUILD_TYPE=RelWithDebInfo
ARG GIT_COMMIT_HASH ARG GIT_COMMIT_HASH
ARG GIT_BRANCH ARG GIT_BRANCH
ARG ARCHITECTURE_PACKAGE=x86_64 ARG ARCHITECTURE_PACKAGE
ARG ARCHITECTURE_FILE_NAME=amd64 ARG ARCHITECTURE_FILE_NAME
ARG ARCHITECTURE_APPIMAGE_BUILDER=x86_64 ARG ARCHITECTURE_APPIMAGE_BUILDER
WORKDIR /build WORKDIR /build
# Ubuntu sh doesnt support string substitution # Ubuntu sh doesnt support string substitution
@@ -51,9 +51,7 @@ CC=gcc-14 CXX=g++-14 cmake -G "Ninja" \
-DIMHEX_COMMIT_HASH_LONG="${GIT_COMMIT_HASH}" \ -DIMHEX_COMMIT_HASH_LONG="${GIT_COMMIT_HASH}" \
-DIMHEX_COMMIT_BRANCH="${GIT_BRANCH}" \ -DIMHEX_COMMIT_BRANCH="${GIT_BRANCH}" \
-DIMHEX_ENABLE_LTO=${LTO} \ -DIMHEX_ENABLE_LTO=${LTO} \
-DIMHEX_BUNDLE_PLUGIN_SDK=OFF \ -DIMHEX_PLUGINS_IN_SHARE=ON \
`# To prevent using a libdir with an architecture-specific name` \
-DCMAKE_INSTALL_LIBDIR="lib" \
/imhex /imhex
EOF EOF

View File

@@ -4,7 +4,7 @@ Section: editors
Priority: optional Priority: optional
Architecture: amd64 Architecture: amd64
License: GNU GPL-2 License: GNU GPL-2
Depends: libfontconfig1, libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal, libssh2-1, libmd4c0 Depends: libfontconfig1, libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal, libssh2-1, md4c
Maintainer: WerWolv <hey@werwolv.net> Maintainer: WerWolv <hey@werwolv.net>
Description: ImHex Hex Editor Description: ImHex Hex Editor
A Hex Editor for Reverse Engineers, Programmers and A Hex Editor for Reverse Engineers, Programmers and

13
dist/ImHex.run.xml vendored
View File

@@ -1,13 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="ImHex" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" WORKING_DIR="file://$CMakeCurrentBuildDir$" PASS_PARENT_ENVS_2="true" PROJECT_NAME="ImHex" TARGET_NAME="imhex_all" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="ImHex" RUN_TARGET_NAME="main">
<envs>
<env name="NO_DEBUG_BANNER" value="1" />
</envs>
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<configuration default="false" name="CMake Debug" type="CMakeListConfigurationType" factoryName="CMakeListConfigurationFactory">
<method v="2" />
</configuration>
</component>

3
dist/cli/imhex.bat vendored
View File

@@ -1,3 +0,0 @@
@echo off
start "" "%~dp0..\imhex.exe" %*

5
dist/cli/imhex.sh vendored
View File

@@ -1,5 +0,0 @@
#!/bin/sh
script_path=$(readlink -f "$0")
script_dir=$(dirname "${script_path}")
"${script_dir}/../imhex" "$@" > /dev/null 2>&1 &

View File

@@ -3,7 +3,7 @@
On macOS, ImHex is built through regular GCC and LLVM clang. On macOS, ImHex is built through regular GCC and LLVM clang.
1. Clone the repo using `git clone https://github.com/WerWolv/ImHex --recurse-submodules` 1. Clone the repo using `git clone https://github.com/WerWolv/ImHex --recurse-submodules`
2. Install all the dependencies using `brew bundle --file dist/macOS/Brewfile` 2. Install all the dependencies using `brew bundle --no-lock --file dist/macOS/Brewfile`
3. Build ImHex itself using the following commands: 3. Build ImHex itself using the following commands:
```sh ```sh
cd ImHex cd ImHex
@@ -20,5 +20,3 @@ cmake -G "Ninja" \
.. ..
ninja install ninja install
``` ```
If your MacOS installation doesn't have graphic acceleration, you can check the [MacOS NoGPU guide](./macos_nogpu.md)

View File

@@ -1,10 +0,0 @@
### Compiling and running ImHex on macOS without a GPU
In order to run ImHex on a macOS installation without a GPU, you need a custom build of GLFW. You can build it this way:
Note: only tested on macOS x86
1. `git clone --depth 1 https://github.com/glfw/glfw`
2. `git apply {IMHEX_DIR}/dist/macOS/0001-glfw-SW.patch` (file is [here](../macOS/0001-glfw-SW.patch) in the ImHex repository. [Source](https://github.com/glfw/glfw/issues/2080).)
3. `cmake -G "Ninja" -DBUILD_SHARED_LIBS=ON ..`
4. `ninja install`, or `ninja` and figure out how to make ImHex detect the shared library

54
dist/flake.nix vendored
View File

@@ -1,54 +0,0 @@
{
description = "ImHex";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs = { self, nixpkgs }:
let
supportedSystems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin" ];
forAllSystems = f: nixpkgs.lib.genAttrs supportedSystems (system: f system);
in {
devShells = forAllSystems (system:
let
pkgs = import nixpkgs { inherit system; };
in
{
default = pkgs.mkShell {
buildInputs = [
pkgs.cmake
pkgs.clang
pkgs.lld
pkgs.nghttp3
pkgs.pkg-config
pkgs.glfw
pkgs.fontconfig
pkgs.file
pkgs.mbedtls
pkgs.freetype
pkgs.dbus
pkgs.gtk3
pkgs.curl
pkgs.fmt
pkgs.yara
pkgs.nlohmann_json
pkgs.ninja
pkgs.zlib
pkgs.bzip2
pkgs.xz
pkgs.zstd
pkgs.lz4
pkgs.libssh2
pkgs.md4c
];
shellHook = ''
export CC=${pkgs.clang}/bin/clang
export CXX=${pkgs.clang}/bin/clang++
'';
};
});
};
}

View File

@@ -120,7 +120,6 @@ modules:
- -DUSE_SYSTEM_FMT=ON - -DUSE_SYSTEM_FMT=ON
- -DUSE_SYSTEM_YARA=ON - -DUSE_SYSTEM_YARA=ON
- -DIMHEX_OFFLINE_BUILD=ON - -DIMHEX_OFFLINE_BUILD=ON
- -DIMHEX_BUNDLE_PLUGIN_SDK=OFF
- -DCMAKE_INSTALL_LIBDIR=lib - -DCMAKE_INSTALL_LIBDIR=lib
- -DCMAKE_INSTALL_RPATH='$ORIGIN/../lib:$ORIGIN/../lib64' - -DCMAKE_INSTALL_RPATH='$ORIGIN/../lib:$ORIGIN/../lib64'
sources: sources:

View File

@@ -1,5 +1,5 @@
From 9c8665af4c2e2ce66555c15c05c72027bfdf0cb6 Mon Sep 17 00:00:00 2001 From 9c8665af4c2e2ce66555c15c05c72027bfdf0cb6 Mon Sep 17 00:00:00 2001
From: iTrooz <hey@itrooz.fr> From: iTrooz <itrooz@protonmail.com>
Date: Mon, 29 Aug 2022 17:29:38 +0200 Date: Mon, 29 Aug 2022 17:29:38 +0200
Subject: [PATCH] Use software rendering on MacOS Subject: [PATCH] Use software rendering on MacOS

View File

@@ -1,7 +1,7 @@
# This base image is also known as "crosscompile". See arm64.crosscompile.Dockerfile # This base image is also known as "crosscompile". See arm64.crosscompile.Dockerfile
FROM ghcr.io/werwolv/macos-crosscompile:6d89b20ac5ebedb6f680f94637591c94cb36f40b as build FROM ghcr.io/werwolv/macos-crosscompile:clang20-nosdk as build
ENV MACOSX_DEPLOYMENT_TARGET 11.0 ENV MACOSX_DEPLOYMENT_TARGET 13.0
# -- DOWNLOADING STUFF # -- DOWNLOADING STUFF
@@ -17,13 +17,13 @@ cp /tmp/arm-osx-mytriplet.cmake /vcpkg/triplets/community/arm-osx-mytriplet.cmak
EOF EOF
## Install make ## Install make
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y make cmake RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y make
## fix environment ## fix environment
### add install_name_tool for cmake command that won't have the right env set (see PostprocessBundle.cmake function postprocess_bundle()) ### add install_name_tool for cmake command that won't have the right env set (see PostprocessBundle.cmake function postprocess_bundle())
RUN cp /osxcross/build/cctools-port/cctools/misc/install_name_tool /usr/bin/install_name_tool RUN cp /osxcross/build/cctools-port/cctools/misc/install_name_tool /usr/bin/install_name_tool
### a cmake thing wants 'otool' and not '' apparently ### a cmake thing wants 'otool' and not '' apparently
RUN cp /osxcross/target/bin/aarch64-apple-darwin24-otool /usr/bin/otool RUN cp /osxcross/target/bin/aarch64-apple-darwin23-otool /usr/bin/otool
## Clone glfw ## Clone glfw
RUN <<EOF RUN <<EOF
@@ -36,10 +36,10 @@ EOF
RUN --mount=type=cache,target=/cache <<EOF RUN --mount=type=cache,target=/cache <<EOF
## Download SDK is missing (it may have been removed from the image) ## Download SDK is missing (it may have been removed from the image)
set -xe set -xe
if [ ! -d /osxcross/target/SDK/MacOSX15.0.sdk ]; then if [ ! -d /osxcross/target/SDK/MacOSX14.0.sdk ]; then
wget https://github.com/joseluisq/macosx-sdks/releases/download/15.0/MacOSX15.0.sdk.tar.xz -O /cache/MacOSX15.0.sdk.tar.xz -nc || true wget https://github.com/joseluisq/macosx-sdks/releases/download/14.0/MacOSX14.0.sdk.tar.xz -O /cache/MacOSX14.0.sdk.tar.xz -nc || true
mkdir -p /osxcross/target/SDK mkdir -p /osxcross/target/SDK
tar -C /osxcross/target/SDK -xf /cache/MacOSX15.0.sdk.tar.xz tar -C /osxcross/target/SDK -xf /cache/MacOSX14.0.sdk.tar.xz
fi fi
EOF EOF
@@ -101,7 +101,7 @@ RUN --mount=type=cache,target=/cache <<EOF
make -j $JOBS install make -j $JOBS install
# Now, we cross-compile it and install it in the libraries folder # Now, we cross-compile it and install it in the libraries folder
CC=/osxcross/target/bin/aarch64-apple-darwin24-clang CXX=/osxcross/target/bin/aarch64-apple-darwin24-clang++ ./configure --prefix /vcpkg/installed/arm-osx-mytriplet --host $OSXCROSS_HOST CC=/osxcross/target/bin/aarch64-apple-darwin23-clang CXX=/osxcross/target/bin/aarch64-apple-darwin23-clang++ ./configure --prefix /vcpkg/installed/arm-osx-mytriplet --host $OSXCROSS_HOST
make -j $JOBS make -j $JOBS
make install make install
@@ -132,7 +132,6 @@ if [ "$CUSTOM_GLFW" ]; then
mkdir build mkdir build
cd build cd build
CC=o64-clang CXX=o64-clang++ cmake -G "Ninja" \ CC=o64-clang CXX=o64-clang++ cmake -G "Ninja" \
-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \ -DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DBUILD_SHARED_LIBS=ON \ -DBUILD_SHARED_LIBS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
@@ -140,7 +139,7 @@ if [ "$CUSTOM_GLFW" ]; then
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \ -DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_INSTALL_PREFIX=/vcpkg/installed/arm-osx-mytriplet \ -DCMAKE_INSTALL_PREFIX=/vcpkg/installed/arm-osx-mytriplet \
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=13.3 \ -DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 \
.. ..
ninja -j $JOBS install ninja -j $JOBS install
@@ -151,25 +150,25 @@ EOF
# Build ImHex # Build ImHex
## Copy ImHex ## Copy ImHex
COPY --from=imhex / /mnt/ImHex COPY --from=imhex / /mnt/ImHex
## Configure ImHex build ## Patch ImHex with hacks
# COPY toolchain.cmake.2 /osxcross/target/toolchain.cmake
# Configure ImHex build
RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/_deps \ RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/_deps \
cd /mnt/ImHex && \ cd /mnt/ImHex && \
# compilers # compilers
CC=o64-clang CXX=o64-clang++ OBJC=/osxcross/target/bin/aarch64-apple-darwin24-clang OBJCXX=/osxcross/target/bin/aarch64-apple-darwin24-clang++ \ CC=o64-clang CXX=o64-clang++ OBJC=/osxcross/target/bin/aarch64-apple-darwin23-clang OBJCXX=/osxcross/target/bin/aarch64-apple-darwin23-clang++ \
cmake -G "Ninja" \ cmake -G "Ninja" \
`# ccache flags` \ `# ccache flags` \
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_OBJC_COMPILER_LAUNCHER=ccache -DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_OBJC_COMPILER_LAUNCHER=ccache -DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
`# MacOS cross-compiling flags` \ `# MacOS cross-compiling flags` \
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=13.3 \ -DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 \
`# Override compilers for code generators` \ `# Override compilers for code generators` \
-DNATIVE_CMAKE_C_COMPILER=/usr/bin/clang -DNATIVE_CMAKE_CXX_COMPILER=/usr/bin/clang++ \ -DNATIVE_CMAKE_C_COMPILER=/usr/bin/clang -DNATIVE_CMAKE_CXX_COMPILER=/usr/bin/clang++ \
`# Normal ImHex flags` \ `# Normal ImHex flags` \
-DIMHEX_GENERATE_PACKAGE=ON -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ -DIMHEX_GENERATE_PACKAGE=ON -DCMAKE_BUILD_TYPE=$BUILD_TYPE \
`# other flags` \ `# other flags` \
-DIMHEX_STRICT_WARNINGS=OFF \ -DIMHEX_STRICT_WARNINGS=OFF \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
-DCMAKE_INSTALL_PREFIX=/mnt/ImHex/build/install \ -DCMAKE_INSTALL_PREFIX=/mnt/ImHex/build/install \
-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \
-B build -B build
## Build ImHex ## Build ImHex
RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/_deps <<EOF RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/_deps <<EOF
@@ -184,4 +183,4 @@ EOF
FROM scratch FROM scratch
COPY --from=build /mnt/ImHex/build/install/ImHex.app ImHex.app COPY --from=build /mnt/ImHex/build/install/imhex.app imhex.app

View File

@@ -4,9 +4,9 @@ FROM ubuntu:22.04
ENV PATH $PATH:/osxcross/target/bin ENV PATH $PATH:/osxcross/target/bin
ENV LD_LIBRARY_PATH /osxcross/target/lib ENV LD_LIBRARY_PATH /osxcross/target/lib
ENV OSXCROSS_SDK /osxcross/target/SDK/MacOSX14.0.sdk ENV OSXCROSS_SDK /osxcross/target/SDK/MacOSX14.0.sdk
ENV OSXCROSS_TARGET darwin24 ENV OSXCROSS_TARGET darwin23
ENV OSXCROSS_TARGET_DIR /osxcross/target ENV OSXCROSS_TARGET_DIR /osxcross/target
ENV OSXCROSS_HOST aarch64-apple-darwin24 ENV OSXCROSS_HOST aarch64-apple-darwin23
# -- DOWNLOADING STUFF # -- DOWNLOADING STUFF

View File

@@ -1,11 +0,0 @@
set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_BUILD_TYPE release)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_CMAKE_SYSTEM_NAME Darwin)
set(VCPKG_OSX_ARCHITECTURES x86_64)
set(VCPKG_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "" FORCE)
set(VCPKG_C_FLAGS "-mmacosx-version-min=10.15")
set(VCPKG_CXX_FLAGS "-mmacosx-version-min=10.15")
set(ENV{MACOSX_DEPLOYMENT_TARGET} "10.15")

View File

@@ -38,7 +38,7 @@
<url type="homepage">https://imhex.werwolv.net</url> <url type="homepage">https://imhex.werwolv.net</url>
<url type="bugtracker">https://github.com/WerWolv/ImHex/issues</url> <url type="bugtracker">https://github.com/WerWolv/ImHex/issues</url>
<url type="help">https://docs.werwolv.net/imhex</url> <url type="help">https://docs.werwolv.net/imhex</url>
<url type="donation">https://github.com/sponsors/WerWolv</url> <url type="donation">https://www.patreon.com/werwolv</url>
<url type="contact">https://imhex.werwolv.net/discord</url> <url type="contact">https://imhex.werwolv.net/discord</url>
<url type="vcs-browser">https://github.com/WerWolv/ImHex</url> <url type="vcs-browser">https://github.com/WerWolv/ImHex</url>
<url type="contribute">https://github.com/WerWolv/ImHex/blob/master/CONTRIBUTING.md</url> <url type="contribute">https://github.com/WerWolv/ImHex/blob/master/CONTRIBUTING.md</url>
@@ -64,8 +64,4 @@
</release> </release>
</releases> </releases>
<update_contact>hey@werwolv.net</update_contact> <update_contact>hey@werwolv.net</update_contact>
<recommends>
<control>keyboard</control>
<control>pointing</control>
</recommends>
</component> </component>

4
dist/rpm/imhex.spec vendored
View File

@@ -145,7 +145,8 @@ appstream-util validate-relax --nonet %{buildroot}%{_metainfodir}/net.werwolv.Im
# install licenses # install licenses
%if 0%{?rhel} == 9 %if 0%{?rhel} == 9
cp -a lib/third_party/capstone/LICENSES/LICENSE.TXT %{buildroot}%{_datadir}/licenses/%{name}/capstone-LICENSE cp -a lib/third_party/capstone/LICENSE.TXT %{buildroot}%{_datadir}/licenses/%{name}/capstone-LICENSE
cp -a lib/third_party/capstone/suite/regress/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/capstone-regress-LICENSE
%endif %endif
cp -a lib/third_party/microtar/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/microtar-LICENSE cp -a lib/third_party/microtar/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/microtar-LICENSE
cp -a lib/third_party/xdgpp/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/xdgpp-LICENSE cp -a lib/third_party/xdgpp/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/xdgpp-LICENSE
@@ -155,7 +156,6 @@ cp -a lib/third_party/xdgpp/LICENSE %{buildroot
%license %{_datadir}/licenses/%{name}/ %license %{_datadir}/licenses/%{name}/
%doc README.md %doc README.md
%{_bindir}/imhex %{_bindir}/imhex
%{_datadir}/imhex/imhex
%{_datadir}/pixmaps/%{name}.* %{_datadir}/pixmaps/%{name}.*
%{_datadir}/applications/%{name}.desktop %{_datadir}/applications/%{name}.desktop
%{_libdir}/libimhex.so.* %{_libdir}/libimhex.so.*

View File

@@ -1,7 +1,7 @@
name: imhex name: imhex
title: ImHex title: ImHex
base: core24 base: core24
version: ${IMHEX_VERSION_STRING} version: ${IMHEX_VERSION}
summary: Hex editor for reverse engineering summary: Hex editor for reverse engineering
description: ImHex is a hex editor for reverse engineering, reverse engineering, and analyzing binary files. It provides a powerful and flexible interface for working with binary data, including features like pattern matching, scripting, and a customizable user interface. description: ImHex is a hex editor for reverse engineering, reverse engineering, and analyzing binary files. It provides a powerful and flexible interface for working with binary data, including features like pattern matching, scripting, and a customizable user interface.
grade: stable grade: stable
@@ -40,8 +40,6 @@ parts:
- -DCMAKE_BUILD_TYPE=Release - -DCMAKE_BUILD_TYPE=Release
- -DCMAKE_C_COMPILER_LAUNCHER=${CCACHE} - -DCMAKE_C_COMPILER_LAUNCHER=${CCACHE}
- -DCMAKE_CXX_COMPILER_LAUNCHER=${CCACHE} - -DCMAKE_CXX_COMPILER_LAUNCHER=${CCACHE}
- -DIMHEX_PATTERNS_PULL_MASTER=ON
- -DIMHEX_BUNDLE_PLUGIN_SDK=OFF
cmake-generator: Ninja cmake-generator: Ninja
build-packages: build-packages:
- cmake - cmake

2
dist/vcpkg.json vendored
View File

@@ -1,7 +1,7 @@
{ {
"name": "vcpkg", "name": "vcpkg",
"version": "1.0.0", "version": "1.0.0",
"builtin-baseline": "66c0373dc7fca549e5803087b9487edfe3aca0a1", "builtin-baseline": "7e21420f775f72ae938bdeb5e6068f722088f06a",
"dependencies": [ "dependencies": [
"libmagic", "libmagic",
"freetype", "freetype",

14
dist/web/Dockerfile vendored
View File

@@ -1,8 +1,8 @@
FROM emscripten/emsdk:4.0.21 AS build FROM emscripten/emsdk:4.0.8 AS build
# Used to invalidate layer cache but not mount cache # Used to invalidate layer cache but not mount cache
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493 # See https://github.com/moby/moby/issues/41715#issuecomment-733976493
ARG UNIQUEKEY=1 ARG UNIQUEKEY 1
RUN apt update RUN apt update
RUN apt install -y git ccache autoconf automake libtool pkg-config ninja-build RUN apt install -y git ccache autoconf automake libtool pkg-config ninja-build
@@ -12,13 +12,13 @@ RUN <<EOF
# Note: we are a patch on the libmagic port # Note: we are a patch on the libmagic port
set -xe set -xe
git clone --depth 1 https://github.com/microsoft/vcpkg /vcpkg git clone https://github.com/microsoft/vcpkg /vcpkg
git -C /vcpkg pull
/vcpkg/bootstrap-vcpkg.sh /vcpkg/bootstrap-vcpkg.sh
sed -i 's/vcpkg_install_make(${EXTRA_ARGS})/vcpkg_install_make(${EXTRA_ARGS} SUBPATH src)/g' /vcpkg/ports/libmagic/portfile.cmake sed -i 's/vcpkg_install_make(${EXTRA_ARGS})/vcpkg_install_make(${EXTRA_ARGS} SUBPATH src)/g' /vcpkg/ports/libmagic/portfile.cmake
EOF EOF
# Patch vcpkg build instructions to add -pthread flag # Patch vcpkg build instructions to add -pthread
# Even dependencies must be built with -pthread to be able to use USE_PTHREADS=1
RUN <<EOF RUN <<EOF
set -xe set -xe
@@ -50,7 +50,6 @@ ENV CCACHE_DIR=/cache/ccache
RUN mkdir /build RUN mkdir /build
WORKDIR /build WORKDIR /build
ARG BUILD_TYPE=Release
RUN --mount=type=cache,target=/cache \ RUN --mount=type=cache,target=/cache \
--mount=type=bind,source=.,target=/imhex <<EOF --mount=type=bind,source=.,target=/imhex <<EOF
@@ -71,7 +70,7 @@ ccache -zs
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \ -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
-DLIBROMFS_COMPRESS_RESOURCES=OFF \ -DLIBROMFS_COMPRESS_RESOURCES=OFF \
-DIMHEX_ENABLE_PLUGIN_TESTS=OFF \ -DIMHEX_ENABLE_PLUGIN_TESTS=OFF \
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_BUILD_TYPE=Release
ninja -j $JOBS ninja -j $JOBS
@@ -107,4 +106,3 @@ COPY --from=build [ \
FROM nginx FROM nginx
COPY --from=raw . /usr/share/nginx/html COPY --from=raw . /usr/share/nginx/html
RUN chmod -R 755 /usr/share/nginx/html

View File

@@ -1,9 +0,0 @@
FROM python:3.12-slim
WORKDIR /imhex
COPY ./out/ .
EXPOSE 9090
CMD [ "python", "/imhex/start_imhex_web.py" ]

View File

@@ -1,4 +1,5 @@
# docker compose -f dist/web/compose.yml up --build # docker compose -f dist/web/compose.yml up --build
version: '3'
services: services:
imhex_web: imhex_web:
image: imhex_web:latest image: imhex_web:latest

2
dist/web/serve.py vendored
View File

@@ -10,6 +10,6 @@ class MyHttpRequestHandler(http.server.SimpleHTTPRequestHandler):
if __name__ == '__main__': if __name__ == '__main__':
os.chdir(".") os.chdir(".")
httpd = http.server.HTTPServer(("0.0.0.0", 9090), MyHttpRequestHandler) httpd = http.server.HTTPServer(("localhost", 9090), MyHttpRequestHandler)
print(f"Serving {os.getcwd()} on http://{httpd.server_address[0]}:{httpd.server_address[1]}") print(f"Serving {os.getcwd()} on http://{httpd.server_address[0]}:{httpd.server_address[1]}")
httpd.serve_forever() httpd.serve_forever()

View File

@@ -15,17 +15,17 @@
<!-- Open Graph / Facebook --> <!-- Open Graph / Facebook -->
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta property="og:url" content="https://web.imhex.werwolv.net/"> <meta property="og:url" content="https://imhex.werwolv.net/">
<meta property="og:title" content="ImHex Web - Online Hex Editor"> <meta property="og:title" content="ImHex Web - Online Hex Editor">
<meta property="og:image" content="splash_wasm.png"> <meta property="og:image" content="https://imhex.werwolv.net/assets/splash_wasm.png">
<!-- Twitter --> <!-- Twitter -->
<meta property="twitter:card" content="summary_large_image"> <meta property="twitter:card" content="summary_large_image">
<meta property="twitter:url" content="https://web.imhex.werwolv.net/"> <meta property="twitter:url" content="https://imhex.werwolv.net/">
<meta property="twitter:title" content="ImHex Web - Online Hex Editor"> <meta property="twitter:title" content="ImHex Web - Online Hex Editor">
<meta property="twitter:description" <meta property="twitter:description"
content="A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM."> content="A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.">
<meta property="twitter:image" content="splash_wasm.png"> <meta property="twitter:image" content="https://imhex.werwolv.net/assets/splash_wasm.png">
<link rel="stylesheet" type="text/css" href="style.css"> <link rel="stylesheet" type="text/css" href="style.css">
@@ -37,8 +37,8 @@
"email": "hey@werwolv.net", "email": "hey@werwolv.net",
"founder": "WerWolv", "founder": "WerWolv",
"slogan": "A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.", "slogan": "A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.",
"url": "https://web.imhex.werwolv.net", "url": "https://imhex.werwolv.net",
"logo": "https://web.imhex.werwolv.net/icon.svg" "logo": "https://imhex.werwolv.net/assets/logos/logo.svg"
} }
</script> </script>
@@ -96,9 +96,7 @@
</div> </div>
</div> </div>
<div id="canvas-wrapper" class="imhex-web-canvas-wrapper"> <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<canvas class="imhex-web-canvas canvas-fixed" id="canvas" ></canvas>
</div>
<script src="wasm-config.js"></script> <script src="wasm-config.js"></script>
<script async src="imhex.js"></script> <script async src="imhex.js"></script>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 478 KiB

View File

@@ -186,22 +186,3 @@ a:hover {
top: 0; top: 0;
left: 0; left: 0;
} }
.imhex-web-canvas {
width: 100%;
height: 100%;
display: block;
overflow: hidden;
image-rendering: smooth;
margin: 0;
padding: 0;
z-index: 1;
}
.imhex-web-canvas-wrapper {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
background-size: 100% 100%;
}

View File

@@ -59,14 +59,8 @@ monkeyPatch((file, done) => {
const mibTotal = (wasmSize / 1024**2).toFixed(1); const mibTotal = (wasmSize / 1024**2).toFixed(1);
let root = document.querySelector(':root'); let root = document.querySelector(':root');
if (root != null) {
root.style.setProperty("--progress", `${percent}%`) root.style.setProperty("--progress", `${percent}%`)
let progressBar = document.getElementById("progress-bar-content"); document.getElementById("progress-bar-content").innerHTML = `${percent}% &nbsp;[${mibNow} MiB / ${mibTotal} MiB]`;
if (progressBar != null) {
progressBar.innerHTML = `${percent}% &nbsp;[${mibNow} MiB / ${mibTotal} MiB]`;
}
}
}); });
function glfwSetCursorCustom(wnd, shape) { function glfwSetCursorCustom(wnd, shape) {
@@ -106,16 +100,80 @@ var notWorkingTimer = setTimeout(() => {
}, 5000); }, 5000);
var Module = { var Module = {
preRun: () => { preRun: [],
ENV.IMHEX_SKIP_SPLASH_SCREEN = "1";
},
postRun: function() { postRun: function() {
// Patch the emscripten GLFW module to send mouse and touch events in the right order
// For ImGui interactions to correctly work with touch input, MousePos events need
// to be processed first and then MouseButton events in the next frame. By default,
// GLFW does the exact opposite, which causes buttons to require two taps to register
// and windows get "stuck" to the cursor when dragged or resized
GLFW.onMousemove = event => {
if (event.type === "touchmove") {
event.preventDefault();
let primaryChanged = false;
for (let i of event.changedTouches) {
if (GLFW.primaryTouchId === i.identifier) {
Browser.setMouseCoords(i.pageX, i.pageY);
primaryChanged = true;
break;
}
}
if (!primaryChanged) {
return;
}
} else {
Browser.calculateMouseEvent(event);
}
};
GLFW.onMouseButtonChanged = (event, status) => {
if (!GLFW.active) return;
if (event.target != Module["canvas"]) return;
const isTouchType = event.type === "touchstart" || event.type === "touchend" || event.type === "touchcancel";
let eventButton = 0;
if (isTouchType) {
event.preventDefault();
let primaryChanged = false;
if (GLFW.primaryTouchId === null && event.type === "touchstart" && event.targetTouches.length > 0) {
const chosenTouch = event.targetTouches[0];
GLFW.primaryTouchId = chosenTouch.identifier;
Browser.setMouseCoords(chosenTouch.pageX, chosenTouch.pageY);
primaryChanged = true;
} else if (event.type === "touchend" || event.type === "touchcancel") {
for (let i of event.changedTouches) {
if (GLFW.primaryTouchId === i.identifier) {
GLFW.primaryTouchId = null;
primaryChanged = true;
break;
}
}
}
if (!primaryChanged) {
return;
}
} else {
Browser.calculateMouseEvent(event);
eventButton = GLFW.DOMToGLFWMouseButton(event);
}
if (status == 1) {
GLFW.active.buttons |= (1 << eventButton);
try {
event.target.setCapture();
} catch (e) {}
} else {
GLFW.active.buttons &= ~(1 << eventButton);
}
if (GLFW.active.cursorPosFunc) {
getWasmTableEntry(GLFW.active.cursorPosFunc)(GLFW.active.id, Browser.mouseX, Browser.mouseY);
}
if (GLFW.active.mouseButtonFunc) {
getWasmTableEntry(GLFW.active.mouseButtonFunc)(GLFW.active.id, eventButton, status, GLFW.getModBits(GLFW.active));
}
};
}, },
onRuntimeInitialized: function() { onRuntimeInitialized: function() {
// Triggered when the wasm module is loaded and ready to use. // Triggered when the wasm module is loaded and ready to use.
let loading = document.getElementById("loading");
if (loading != null)
document.getElementById("loading").style.display = "none" document.getElementById("loading").style.display = "none"
document.getElementById("canvas").style.display = "initial" document.getElementById("canvas").style.display = "initial"
@@ -199,6 +257,16 @@ if (urlParams.has("lang")) {
Module["arguments"].push(urlParams.get("save-editor")); Module["arguments"].push(urlParams.get("save-editor"));
} }
window.addEventListener('resize', js_resizeCanvas, false);
function js_resizeCanvas() {
let canvas = document.getElementById('canvas');
canvas.top = document.documentElement.clientTop;
canvas.left = document.documentElement.clientLeft;
canvas.width = Math.min(document.documentElement.clientWidth, window.innerWidth || 0);
canvas.height = Math.min(document.documentElement.clientHeight, window.innerHeight || 0);
}
// Prevent some default browser shortcuts from preventing ImHex ones to work // Prevent some default browser shortcuts from preventing ImHex ones to work
document.addEventListener('keydown', e => { document.addEventListener('keydown', e => {
if (e.ctrlKey) { if (e.ctrlKey) {

View File

@@ -42,7 +42,6 @@ set(LIBIMHEX_SOURCES
source/helpers/keys.cpp source/helpers/keys.cpp
source/helpers/udp_server.cpp source/helpers/udp_server.cpp
source/helpers/scaling.cpp source/helpers/scaling.cpp
source/helpers/binary_pattern.cpp
source/test/tests.cpp source/test/tests.cpp
@@ -57,13 +56,19 @@ set(LIBIMHEX_SOURCES
source/ui/toast.cpp source/ui/toast.cpp
source/ui/banner.cpp source/ui/banner.cpp
source/mcp/client.cpp
source/mcp/server.cpp
source/subcommands/subcommands.cpp source/subcommands/subcommands.cpp
) )
if (APPLE) if (APPLE)
set(OSX_SDK_PATH /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.sdk)
if (NOT CMAKE_OSX_SYSROOT)
if (IS_DIRECTORY ${OSX_SDK_PATH})
set(CMAKE_OSX_SYSROOT ${OSX_SDK_PATH})
else ()
message(WARNING "CMAKE_OSX_SYSROOT not set and macOS SDK not found! Using default one.")
endif ()
endif ()
set(LIBIMHEX_SOURCES ${LIBIMHEX_SOURCES} set(LIBIMHEX_SOURCES ${LIBIMHEX_SOURCES}
source/helpers/utils_macos.m source/helpers/utils_macos.m
source/helpers/macos_menu.m source/helpers/macos_menu.m

View File

@@ -145,17 +145,62 @@ EXPORT_MODULE namespace hex {
* @brief Returns the icon of the achievement * @brief Returns the icon of the achievement
* @return Icon of the achievement * @return Icon of the achievement
*/ */
[[nodiscard]] const char* getIcon() const { [[nodiscard]] const ImGuiExt::Texture &getIcon() const {
return m_icon.c_str(); if (m_iconData.empty())
return m_icon;
if (m_icon.isValid())
return m_icon;
m_icon = ImGuiExt::Texture::fromImage(m_iconData.data(), m_iconData.size(), ImGuiExt::Texture::Filter::Linear);
return m_icon;
} }
/** /**
* @brief Sets the icon of the achievement * @brief Sets the icon of the achievement
* @param icon Icon glyph * @param data Icon data
* @return Reference to the achievement * @return Reference to the achievement
*/ */
Achievement& setIcon(std::string icon) { Achievement& setIcon(std::span<const std::byte> data) {
m_icon = std::move(icon); m_iconData.reserve(data.size());
for (auto &byte : data)
m_iconData.emplace_back(static_cast<u8>(byte));
return *this;
}
/**
* @brief Sets the icon of the achievement
* @param data Icon data
* @return Reference to the achievement
*/
Achievement& setIcon(std::span<const u8> data) {
m_iconData.assign(data.begin(), data.end());
return *this;
}
/**
* @brief Sets the icon of the achievement
* @param data Icon data
* @return Reference to the achievement
*/
Achievement& setIcon(std::vector<u8> data) {
m_iconData = std::move(data);
return *this;
}
/**
* @brief Sets the icon of the achievement
* @param data Icon data
* @return Reference to the achievement
*/
Achievement& setIcon(const std::vector<std::byte> &data) {
m_iconData.reserve(data.size());
for (auto &byte : data)
m_iconData.emplace_back(static_cast<u8>(byte));
return *this; return *this;
} }
@@ -239,7 +284,8 @@ EXPORT_MODULE namespace hex {
std::function<void(Achievement &)> m_clickCallback; std::function<void(Achievement &)> m_clickCallback;
std::string m_icon; std::vector<u8> m_iconData;
mutable ImGuiExt::Texture m_icon;
u32 m_progress = 0; u32 m_progress = 0;
u32 m_maxProgress = 1; u32 m_maxProgress = 1;

View File

@@ -16,7 +16,7 @@ EXPORT_MODULE namespace hex {
void stopServices(); void stopServices();
} }
void registerService(const UnlocalizedString &unlocalizedName, const impl::Callback &callback); void registerService(const UnlocalizedString &unlocalizedString, const impl::Callback &callback);
} }
} }

View File

@@ -7,8 +7,6 @@
#include <map> #include <map>
#include <string> #include <string>
#include <hex/mcp/server.hpp>
EXPORT_MODULE namespace hex { EXPORT_MODULE namespace hex {
/* Network Communication Interface Registry. Allows adding new communication interface endpoints */ /* Network Communication Interface Registry. Allows adding new communication interface endpoints */
@@ -24,19 +22,4 @@ EXPORT_MODULE namespace hex {
} }
namespace ContentRegistry::MCP {
namespace impl {
std::unique_ptr<mcp::Server>& getMcpServerInstance();
void setEnabled(bool enabled);
}
bool isEnabled();
bool isConnected();
void registerTool(std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json &params)> function);
}
} }

View File

@@ -27,10 +27,9 @@ EXPORT_MODULE namespace hex {
struct FindOccurrence { struct FindOccurrence {
Region region; Region region;
enum class DecodeType { ASCII, UTF8, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
std::endian endian = std::endian::native; std::endian endian = std::endian::native;
enum class DecodeType : u8 { ASCII, UTF8, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
bool selected; bool selected;
std::string string;
}; };
using FindExporterCallback = std::function<std::vector<u8>(const std::vector<FindOccurrence>&, std::function<std::string(FindOccurrence)>)>; using FindExporterCallback = std::function<std::vector<u8>(const std::vector<FindOccurrence>&, std::function<std::string(FindOccurrence)>)>;

View File

@@ -8,7 +8,6 @@
#include <optional> #include <optional>
#include <string> #include <string>
#include <vector> #include <vector>
#include <bit>
EXPORT_MODULE namespace hex { EXPORT_MODULE namespace hex {
@@ -23,10 +22,8 @@ EXPORT_MODULE namespace hex {
namespace impl { namespace impl {
struct DoNotUseThisByItselfTag {};
using DisplayFunction = std::function<std::string()>; using DisplayFunction = std::function<std::string()>;
using EditingFunction = std::function<std::optional<std::vector<u8>>(std::string&, std::endian, DoNotUseThisByItselfTag)>; using EditingFunction = std::function<std::vector<u8>(std::string, std::endian)>;
using GeneratorFunction = std::function<DisplayFunction(const std::vector<u8> &, std::endian, NumberDisplayStyle)>; using GeneratorFunction = std::function<DisplayFunction(const std::vector<u8> &, std::endian, NumberDisplayStyle)>;
struct Entry { struct Entry {
@@ -41,35 +38,6 @@ EXPORT_MODULE namespace hex {
} }
namespace EditWidget {
class Widget {
public:
using Function = std::function<std::vector<u8>(const std::string&, std::endian)>;
explicit Widget(const Function &function) : m_function(function) {}
virtual ~Widget() = default;
virtual std::optional<std::vector<u8>> draw(std::string &value, std::endian endian) = 0;
std::optional<std::vector<u8>> operator()(std::string &value, std::endian endian, impl::DoNotUseThisByItselfTag) {
return draw(value, endian);
}
std::vector<u8> getBytes(const std::string &value, std::endian endian) const {
return m_function(value, endian);
}
private:
Function m_function;
};
struct TextInput : Widget {
explicit TextInput(const Function &function) : Widget(function) {}
std::optional<std::vector<u8>> draw(std::string &value, std::endian endian) override;
};
}
/** /**
* @brief Adds a new entry to the data inspector * @brief Adds a new entry to the data inspector
* @param unlocalizedName The unlocalized name of the entry * @param unlocalizedName The unlocalized name of the entry

View File

@@ -38,14 +38,24 @@ EXPORT_MODULE namespace hex {
[[nodiscard]] const Hash *getType() const { return m_type; } [[nodiscard]] const Hash *getType() const { return m_type; }
[[nodiscard]] const std::string& getName() const { return m_name; } [[nodiscard]] const std::string& getName() const { return m_name; }
std::vector<u8> get(const Region& region, prv::Provider *provider) const { const std::vector<u8>& get(const Region& region, prv::Provider *provider) {
return m_callback(region, provider); if (m_cache.empty()) {
m_cache = m_callback(region, provider);
}
return m_cache;
}
void reset() {
m_cache.clear();
} }
private: private:
Hash *m_type; Hash *m_type;
std::string m_name; std::string m_name;
Callback m_callback; Callback m_callback;
std::vector<u8> m_cache;
}; };
virtual void draw() { } virtual void draw() { }

View File

@@ -19,7 +19,7 @@ EXPORT_MODULE namespace hex {
void addProviderName(const UnlocalizedString &unlocalizedName, const char *icon); void addProviderName(const UnlocalizedString &unlocalizedName, const char *icon);
using ProviderCreationFunction = std::function<std::shared_ptr<prv::Provider>()>; using ProviderCreationFunction = std::function<std::unique_ptr<prv::Provider>()>;
void add(const std::string &typeName, ProviderCreationFunction creationFunction); void add(const std::string &typeName, ProviderCreationFunction creationFunction);
struct Entry { struct Entry {

View File

@@ -52,7 +52,7 @@ EXPORT_MODULE namespace hex {
return *this; return *this;
} }
Interface& setTooltip(const UnlocalizedString &tooltip) { Interface& setTooltip(const std::string &tooltip) {
m_tooltip = tooltip; m_tooltip = tooltip;
return *this; return *this;
@@ -239,14 +239,6 @@ EXPORT_MODULE namespace hex {
nlohmann::json store() override { return {}; } nlohmann::json store() override { return {}; }
}; };
class Spacer : public Widget {
public:
bool draw(const std::string &name) override;
void load(const nlohmann::json &) override {}
nlohmann::json store() override { return {}; }
};
} }
namespace impl { namespace impl {
@@ -298,8 +290,8 @@ EXPORT_MODULE namespace hex {
public: public:
SettingsValue(nlohmann::json value) : m_value(std::move(value)) {} SettingsValue(nlohmann::json value) : m_value(std::move(value)) {}
template<typename T> requires (!(std::is_reference_v<T> || std::is_const_v<T>)) template<typename T>
[[nodiscard]] T get(T defaultValue) const { T get(std::common_type_t<T> defaultValue) const {
try { try {
auto result = m_value; auto result = m_value;
if (result.is_number() && std::same_as<T, bool>) if (result.is_number() && std::same_as<T, bool>)
@@ -316,8 +308,8 @@ EXPORT_MODULE namespace hex {
nlohmann::json m_value; nlohmann::json m_value;
}; };
template<typename T> requires (!(std::is_reference_v<T> || std::is_const_v<T>)) template<typename T>
[[nodiscard]] T read(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, T defaultValue) { [[nodiscard]] T read(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const std::common_type_t<T> &defaultValue) {
auto setting = impl::getSetting(unlocalizedCategory, unlocalizedName, defaultValue); auto setting = impl::getSetting(unlocalizedCategory, unlocalizedName, defaultValue);
try { try {
@@ -334,8 +326,8 @@ EXPORT_MODULE namespace hex {
} }
} }
template<typename T> requires (!(std::is_reference_v<T> || std::is_const_v<T>)) template<typename T>
void write(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, T value) { void write(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const std::common_type_t<T> &value) {
impl::getSetting(unlocalizedCategory, unlocalizedName, value) = value; impl::getSetting(unlocalizedCategory, unlocalizedName, value) = value;
impl::runOnChangeHandlers(unlocalizedCategory, unlocalizedName, value); impl::runOnChangeHandlers(unlocalizedCategory, unlocalizedName, value);
@@ -344,75 +336,10 @@ EXPORT_MODULE namespace hex {
using OnChangeCallback = std::function<void(const SettingsValue &)>; using OnChangeCallback = std::function<void(const SettingsValue &)>;
u64 onChange(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const OnChangeCallback &callback); u64 onChange(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const OnChangeCallback &callback);
void removeOnChangeHandler(u64 id);
using OnSaveCallback = std::function<void()>; using OnSaveCallback = std::function<void()>;
u64 onSave(const OnSaveCallback &callback); u64 onSave(const OnSaveCallback &callback);
template<typename T, wolv::type::StaticString UnlocalizedCategory, wolv::type::StaticString UnlocalizedName>
requires (!(std::is_reference_v<T> || std::is_const_v<T>))
class SettingsVariable {
public:
explicit(false) SettingsVariable(T defaultValue) noexcept : m_defaultValue(std::move(defaultValue)) { }
SettingsVariable(const SettingsVariable&) = delete;
SettingsVariable& operator=(const SettingsVariable&) = delete;
SettingsVariable(SettingsVariable&&) = delete;
SettingsVariable& operator=(SettingsVariable&&) = delete;
~SettingsVariable() {
if (m_onChangeId > 0)
removeOnChangeHandler(m_onChangeId);
}
[[nodiscard]] T get() const {
registerChangeHandler();
if (!m_value.has_value()) {
m_value = read<T>(
UnlocalizedCategory.value.data(),
UnlocalizedName.value.data(),
m_defaultValue
);
}
return m_value.value_or(m_defaultValue);
}
void set(T value) {
registerChangeHandler();
write<T>(
UnlocalizedCategory.value.data(),
UnlocalizedName.value.data(),
std::move(value)
);
}
explicit(false) operator T() const {
return get();
}
SettingsVariable& operator=(T value) {
set(std::move(value));
return *this;
}
private:
void registerChangeHandler() const {
if (m_onChangeId > 0)
return;
m_onChangeId = onChange(UnlocalizedCategory.value.data(), UnlocalizedName.value.data(), [this](const SettingsValue &value) {
m_value = value.get<T>(m_defaultValue);
});
}
private:
mutable std::optional<T> m_value;
T m_defaultValue;
mutable u64 m_onChangeId = 0;
};
} }
} }

View File

@@ -68,7 +68,6 @@ EXPORT_MODULE namespace hex {
constexpr static auto SeparatorValue = "$SEPARATOR$"; constexpr static auto SeparatorValue = "$SEPARATOR$";
constexpr static auto SubMenuValue = "$SUBMENU$"; constexpr static auto SubMenuValue = "$SUBMENU$";
constexpr static auto TaskBarMenuValue = "$TASKBAR$";
const std::multimap<u32, MainMenuItem>& getMainMenuItems(); const std::multimap<u32, MainMenuItem>& getMainMenuItems();
@@ -160,15 +159,13 @@ EXPORT_MODULE namespace hex {
* @param function The function to call when the entry is clicked * @param function The function to call when the entry is clicked
* @param enabledCallback The function to call to determine if the entry is enabled * @param enabledCallback The function to call to determine if the entry is enabled
* @param view The view to use for the entry. If nullptr, the item will always be visible * @param view The view to use for the entry. If nullptr, the item will always be visible
* @param showOnWelcomeScreen If this entry should be shown on the welcome screen
*/ */
void addMenuItemSubMenu( void addMenuItemSubMenu(
std::vector<UnlocalizedString> unlocalizedMainMenuNames, std::vector<UnlocalizedString> unlocalizedMainMenuNames,
u32 priority, u32 priority,
const impl::MenuCallback &function, const impl::MenuCallback &function,
const impl::EnabledCallback& enabledCallback = []{ return true; }, const impl::EnabledCallback& enabledCallback = []{ return true; },
View *view = nullptr, View *view = nullptr
bool showOnWelcomeScreen = false
); );
/** /**
@@ -179,7 +176,6 @@ EXPORT_MODULE namespace hex {
* @param function The function to call when the entry is clicked * @param function The function to call when the entry is clicked
* @param enabledCallback The function to call to determine if the entry is enabled * @param enabledCallback The function to call to determine if the entry is enabled
* @param view The view to use for the entry. If nullptr, the item will always be visible * @param view The view to use for the entry. If nullptr, the item will always be visible
* @param showOnWelcomeScreen If this entry should be shown on the welcome screen
*/ */
void addMenuItemSubMenu( void addMenuItemSubMenu(
std::vector<UnlocalizedString> unlocalizedMainMenuNames, std::vector<UnlocalizedString> unlocalizedMainMenuNames,
@@ -187,8 +183,7 @@ EXPORT_MODULE namespace hex {
u32 priority, u32 priority,
const impl::MenuCallback &function, const impl::MenuCallback &function,
const impl::EnabledCallback& enabledCallback = []{ return true; }, const impl::EnabledCallback& enabledCallback = []{ return true; },
View *view = nullptr, View *view = nullptr
bool showOnWelcomeScreen = false
); );
@@ -200,19 +195,6 @@ EXPORT_MODULE namespace hex {
*/ */
void addMenuItemSeparator(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, View *view = nullptr); void addMenuItemSeparator(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, View *view = nullptr);
/**
* @brief Adds a new main menu entry
* @param unlocalizedMainMenuNames The unlocalized names of the main menu entries
* @param priority The priority of the entry. Lower values are displayed first
* @param function The function to call when the entry is clicked
* @param enabledCallback The function to call to determine if the entry is enabled
*/
void addTaskBarMenuItem(
std::vector<UnlocalizedString> unlocalizedMainMenuNames,
u32 priority,
const impl::MenuCallback &function,
const impl::EnabledCallback& enabledCallback
);
/** /**
* @brief Adds a new welcome screen entry * @brief Adds a new welcome screen entry
@@ -234,10 +216,10 @@ EXPORT_MODULE namespace hex {
/** /**
* @brief Adds a menu item to the toolbar * @brief Adds a menu item to the toolbar
* @param unlocalizedNames Unlocalized name of the menu item * @param unlocalizedName Unlocalized name of the menu item
* @param color Color of the toolbar icon * @param color Color of the toolbar icon
*/ */
void addMenuItemToToolbar(const std::vector<UnlocalizedString> &unlocalizedNames, ImGuiCustomCol color); void addMenuItemToToolbar(const UnlocalizedString &unlocalizedName, ImGuiCustomCol color);
/** /**
* @brief Reconstructs the toolbar items list after they have been modified * @brief Reconstructs the toolbar items list after they have been modified

View File

@@ -79,11 +79,6 @@ namespace hex {
*/ */
EVENT_DEF(EventProjectOpened); EVENT_DEF(EventProjectOpened);
/**
* @brief Called when a project is saved/saved as
*/
EVENT_DEF(EventProjectSaved);
/** /**
* @brief Called when a native message was received from another ImHex instance * @brief Called when a native message was received from another ImHex instance
* @param rawData Raw bytes received from other instance * @param rawData Raw bytes received from other instance

View File

@@ -15,7 +15,7 @@ namespace hex {
* This event is responsible for (optionally) initializing the provider and calling EventProviderOpened * This event is responsible for (optionally) initializing the provider and calling EventProviderOpened
* (although the event can also be called manually without problem) * (although the event can also be called manually without problem)
*/ */
EVENT_DEF(EventProviderCreated, std::shared_ptr<prv::Provider>); EVENT_DEF(EventProviderCreated, prv::Provider *);
/** /**
* @brief Called as a continuation of EventProviderCreated * @brief Called as a continuation of EventProviderCreated

View File

@@ -8,12 +8,7 @@ namespace hex {
/** /**
* @brief Creates a provider from its unlocalized name, and add it to the provider list * @brief Creates a provider from its unlocalized name, and add it to the provider list
*/ */
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, std::shared_ptr<hex::prv::Provider> *); EVENT_DEF(RequestCreateProvider, std::string, bool, bool, hex::prv::Provider **);
/**
* @brief Used internally when opening a provider through the API
*/
EVENT_DEF(RequestOpenProvider, std::shared_ptr<prv::Provider>);
/** /**
* @brief Move the data from all PerProvider instances from one provider to another * @brief Move the data from all PerProvider instances from one provider to another

View File

@@ -86,7 +86,7 @@ EXPORT_MODULE namespace hex {
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation) * @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
* @param select Whether to select the provider after adding it * @param select Whether to select the provider after adding it
*/ */
void add(std::shared_ptr<prv::Provider> &&provider, bool skipLoadInterface = false, bool select = true); void add(std::unique_ptr<prv::Provider> &&provider, bool skipLoadInterface = false, bool select = true);
/** /**
* @brief Creates a new provider and adds it to the list of providers * @brief Creates a new provider and adds it to the list of providers
@@ -111,18 +111,12 @@ EXPORT_MODULE namespace hex {
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation) * @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
* @param select Whether to select the provider after adding it * @param select Whether to select the provider after adding it
*/ */
std::shared_ptr<prv::Provider> createProvider( prv::Provider* createProvider(
const UnlocalizedString &unlocalizedName, const UnlocalizedString &unlocalizedName,
bool skipLoadInterface = false, bool skipLoadInterface = false,
bool select = true bool select = true
); );
/**
* @brief Opens a provider, making its data available to ImHex and handling any error that may occur
* @param provider The provider to open
*/
void openProvider(std::shared_ptr<prv::Provider> provider);
} }
} }

View File

@@ -62,7 +62,6 @@ EXPORT_MODULE namespace hex {
void setMainWindowSize(u32 width, u32 height); void setMainWindowSize(u32 width, u32 height);
void setMainDockSpaceId(ImGuiID id); void setMainDockSpaceId(ImGuiID id);
void setMainWindowHandle(GLFWwindow *window); void setMainWindowHandle(GLFWwindow *window);
void setMainWindowFocusState(bool focused);
void setGlobalScale(float scale); void setGlobalScale(float scale);
void setNativeScale(float scale); void setNativeScale(float scale);
@@ -162,12 +161,6 @@ EXPORT_MODULE namespace hex {
*/ */
GLFWwindow* getMainWindowHandle(); GLFWwindow* getMainWindowHandle();
/**
* @brief Checks if the main window is currently focused
* @return Whether the main window is focused
*/
bool isMainWindowFocused();
/** /**
* @brief Checks if borderless window mode is enabled currently * @brief Checks if borderless window mode is enabled currently
* @return Whether borderless window mode is enabled * @return Whether borderless window mode is enabled
@@ -178,7 +171,7 @@ EXPORT_MODULE namespace hex {
* @brief Checks if multi-window mode is enabled currently * @brief Checks if multi-window mode is enabled currently
* @return Whether multi-window mode is enabled * @return Whether multi-window mode is enabled
*/ */
bool isMultiWindowModeEnabled(); bool isMutliWindowModeEnabled();
/** /**
* @brief Gets the init arguments passed to ImHex from the splash screen * @brief Gets the init arguments passed to ImHex from the splash screen
@@ -283,7 +276,7 @@ EXPORT_MODULE namespace hex {
* @brief Gets the current ImHex version * @brief Gets the current ImHex version
* @return ImHex version * @return ImHex version
*/ */
const SemanticVersion& getImHexVersion(); SemanticVersion getImHexVersion();
/** /**
* @brief Gets the current git commit hash * @brief Gets the current git commit hash

View File

@@ -27,7 +27,6 @@ EXPORT_MODULE namespace hex {
LanguageId id; LanguageId id;
std::string name, nativeName; std::string name, nativeName;
LanguageId fallbackLanguageId; LanguageId fallbackLanguageId;
bool hidden;
std::vector<PathEntry> languageFilePaths; std::vector<PathEntry> languageFilePaths;
}; };
@@ -59,6 +58,7 @@ EXPORT_MODULE namespace hex {
private: private:
std::size_t m_entryHash; std::size_t m_entryHash;
std::string m_unlocalizedString;
}; };
class LangConst { class LangConst {
@@ -102,14 +102,6 @@ EXPORT_MODULE namespace hex {
UnlocalizedString(const std::string &string) : m_unlocalizedString(string) { } UnlocalizedString(const std::string &string) : m_unlocalizedString(string) { }
UnlocalizedString(const char *string) : m_unlocalizedString(string) { } UnlocalizedString(const char *string) : m_unlocalizedString(string) { }
UnlocalizedString(const Lang& arg) = delete; UnlocalizedString(const Lang& arg) = delete;
UnlocalizedString(std::string &&string) : m_unlocalizedString(std::move(string)) { }
UnlocalizedString(UnlocalizedString &&) = default;
UnlocalizedString(const UnlocalizedString &) = default;
UnlocalizedString &operator=(const UnlocalizedString &) = default;
UnlocalizedString &operator=(UnlocalizedString &&) = default;
UnlocalizedString &operator=(const std::string &string) { m_unlocalizedString = string; return *this; }
UnlocalizedString &operator=(std::string &&string) { m_unlocalizedString = std::move(string); return *this; }
[[nodiscard]] operator std::string() const { [[nodiscard]] operator std::string() const {
return m_unlocalizedString; return m_unlocalizedString;

View File

@@ -151,8 +151,6 @@ EXPORT_MODULE namespace hex {
*/ */
static void clearShortcuts(); static void clearShortcuts();
static Shortcut getShortcutByName(const std::vector<UnlocalizedString> &unlocalizedName, const View *view = nullptr);
static void resumeShortcuts(); static void resumeShortcuts();
static void pauseShortcuts(); static void pauseShortcuts();

View File

@@ -10,7 +10,6 @@
#include <condition_variable> #include <condition_variable>
#include <source_location> #include <source_location>
#include <thread> #include <thread>
#include <hex/trace/exceptions.hpp>
EXPORT_MODULE namespace hex { EXPORT_MODULE namespace hex {
@@ -23,7 +22,7 @@ EXPORT_MODULE namespace hex {
class Task { class Task {
public: public:
Task() = default; Task() = default;
Task(UnlocalizedString unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function); Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function);
Task(const Task&) = delete; Task(const Task&) = delete;
Task(Task &&other) noexcept; Task(Task &&other) noexcept;
@@ -71,8 +70,6 @@ EXPORT_MODULE namespace hex {
[[nodiscard]] u64 getValue() const; [[nodiscard]] u64 getValue() const;
[[nodiscard]] u64 getMaxValue() const; [[nodiscard]] u64 getMaxValue() const;
void wait() const;
private: private:
void finish(); void finish();
void interruption(); void interruption();
@@ -90,21 +87,12 @@ EXPORT_MODULE namespace hex {
std::atomic<bool> m_background = true; std::atomic<bool> m_background = true;
std::atomic<bool> m_blocking = false; std::atomic<bool> m_blocking = false;
std::atomic_flag m_interrupted; std::atomic<bool> m_interrupted = false;
std::atomic_flag m_finished; std::atomic<bool> m_finished = false;
std::atomic_flag m_hadException; std::atomic<bool> m_hadException = false;
std::string m_exceptionMessage; std::string m_exceptionMessage;
struct TaskInterruptor: public std::exception { struct TaskInterruptor { virtual ~TaskInterruptor() = default; };
TaskInterruptor() {
trace::disableExceptionCaptureForCurrentThread();
}
virtual ~TaskInterruptor() = default;
[[nodiscard]] const char* what() const noexcept override {
return "Task Interrupted";
}
};
friend class TaskHolder; friend class TaskHolder;
friend class TaskManager; friend class TaskManager;
@@ -126,7 +114,6 @@ EXPORT_MODULE namespace hex {
[[nodiscard]] u32 getProgress() const; [[nodiscard]] u32 getProgress() const;
void interrupt() const; void interrupt() const;
void wait() const;
private: private:
std::weak_ptr<Task> m_task; std::weak_ptr<Task> m_task;
}; };
@@ -252,8 +239,6 @@ EXPORT_MODULE namespace hex {
static const std::list<std::shared_ptr<Task>>& getRunningTasks(); static const std::list<std::shared_ptr<Task>>& getRunningTasks();
static void runDeferredCalls(); static void runDeferredCalls();
static void addTaskCompletionCallback(const std::function<void(Task&)>& function);
private: private:
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function); static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function);
}; };

View File

@@ -10,8 +10,6 @@
#include <hex/ui/imgui_imhex_extensions.h> #include <hex/ui/imgui_imhex_extensions.h>
struct ImRect;
EXPORT_MODULE namespace hex { EXPORT_MODULE namespace hex {
class TutorialManager { class TutorialManager {
@@ -24,8 +22,6 @@ EXPORT_MODULE namespace hex {
Right = 8 Right = 8
}; };
using DrawFunction = std::function<void()>;
struct Tutorial { struct Tutorial {
Tutorial() = delete; Tutorial() = delete;
Tutorial(const UnlocalizedString &unlocalizedName, const UnlocalizedString &unlocalizedDescription) : Tutorial(const UnlocalizedString &unlocalizedName, const UnlocalizedString &unlocalizedDescription) :
@@ -105,7 +101,6 @@ EXPORT_MODULE namespace hex {
std::vector<Highlight> m_highlights; std::vector<Highlight> m_highlights;
std::optional<Message> m_message; std::optional<Message> m_message;
std::function<void()> m_onAppear, m_onComplete; std::function<void()> m_onAppear, m_onComplete;
DrawFunction m_drawFunction;
}; };
Step& addStep(); Step& addStep();
@@ -151,7 +146,6 @@ EXPORT_MODULE namespace hex {
* @param unlocalizedName Name of tutorial to start * @param unlocalizedName Name of tutorial to start
*/ */
static void startTutorial(const UnlocalizedString &unlocalizedName); static void startTutorial(const UnlocalizedString &unlocalizedName);
static void stopCurrentTutorial();
static void startHelpHover(); static void startHelpHover();
static void addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString); static void addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString);
@@ -172,10 +166,6 @@ EXPORT_MODULE namespace hex {
*/ */
static void reset(); static void reset();
static void setRenderer(std::function<DrawFunction(const std::string &)> renderer);
static void postElementRendered(ImGuiID id, const ImRect &boundingBox);
private: private:
TutorialManager() = delete; TutorialManager() = delete;

View File

@@ -7,7 +7,6 @@
#include <set> #include <set>
#include <span> #include <span>
#include <utility>
#include <vector> #include <vector>
#include <nlohmann/json_fwd.hpp> #include <nlohmann/json_fwd.hpp>
@@ -50,15 +49,9 @@ namespace hex::dp {
virtual void store(nlohmann::json &j) const { std::ignore = j; } virtual void store(nlohmann::json &j) const { std::ignore = j; }
virtual void load(const nlohmann::json &j) { std::ignore = j; } virtual void load(const nlohmann::json &j) { std::ignore = j; }
struct NodeError: public std::exception { struct NodeError {
Node *node; Node *node;
std::string message; std::string message;
NodeError(Node *node, std::string message) : node(node), message(std::move(message)) {}
[[nodiscard]] const char* what() const noexcept override {
return this->message.c_str();
}
}; };
void resetOutputData() { void resetOutputData() {
@@ -109,7 +102,7 @@ namespace hex::dp {
void unmarkInputProcessed(u32 index); void unmarkInputProcessed(u32 index);
protected: protected:
[[noreturn]] void throwNodeError(const std::string &msg); [[noreturn]] void throwNodeError(const std::string &message);
void setOverlayData(u64 address, const std::vector<u8> &data); void setOverlayData(u64 address, const std::vector<u8> &data);
void setAttributes(std::vector<Attribute> attributes); void setAttributes(std::vector<Attribute> attributes);

View File

@@ -1,7 +1,6 @@
#pragma once #pragma once
#include <hex/api/imhex_api/system.hpp> #include <hex/api/imhex_api/system.hpp>
#include <hex/helpers/logger.hpp>
namespace hex { namespace hex {
@@ -10,9 +9,6 @@ namespace hex {
class AutoResetBase { class AutoResetBase {
public: public:
virtual ~AutoResetBase() = default; virtual ~AutoResetBase() = default;
private:
friend void ImHexApi::System::impl::cleanup();
virtual void reset() = 0; virtual void reset() = 0;
}; };
@@ -23,20 +19,16 @@ namespace hex {
public: public:
using Type = T; using Type = T;
AutoReset() noexcept { AutoReset() {
try {
ImHexApi::System::impl::addAutoResetObject(this); ImHexApi::System::impl::addAutoResetObject(this);
} catch (std::exception &e) {
log::error("Failed to register AutoReset object: {}", e.what());
}
} }
explicit(false) AutoReset(const T &value) : AutoReset() { AutoReset(const T &value) : AutoReset() {
m_value = value; m_value = value;
m_valid = true; m_valid = true;
} }
explicit(false) AutoReset(T &&value) noexcept : AutoReset() { AutoReset(T &&value) noexcept : AutoReset() {
m_value = std::move(value); m_value = std::move(value);
m_valid = true; m_valid = true;
} }
@@ -69,27 +61,29 @@ namespace hex {
return m_value; return m_value;
} }
AutoReset& operator=(const T &value) { T& operator=(const T &value) {
m_value = value; m_value = value;
m_valid = true; m_valid = true;
return *this; return m_value;
} }
AutoReset& operator=(T &&value) noexcept { T& operator=(T &&value) noexcept {
m_value = std::move(value); m_value = std::move(value);
m_valid = true; m_valid = true;
return *this; return m_value;
} }
[[nodiscard]] bool isValid() const { bool isValid() const {
return m_valid; return m_valid;
} }
private: private:
friend void ImHexApi::System::impl::cleanup();
void reset() override { void reset() override {
if constexpr (requires(T t) { t.reset(); }) { if constexpr (requires { m_value.reset(); }) {
m_value.reset(); m_value.reset();
} else if constexpr (requires(T t) { t.clear(); }) { } else if constexpr (requires { m_value.clear(); }) {
m_value.clear(); m_value.clear();
} else if constexpr (std::is_pointer_v<T>) { } else if constexpr (std::is_pointer_v<T>) {
m_value = nullptr; // cppcheck-suppress nullPointer m_value = nullptr; // cppcheck-suppress nullPointer

View File

@@ -10,19 +10,92 @@ namespace hex {
class BinaryPattern { class BinaryPattern {
public: public:
BinaryPattern() = default;
explicit BinaryPattern(const std::string &pattern);
[[nodiscard]] bool isValid() const;
[[nodiscard]] u64 getSize() const;
[[nodiscard]] bool matches(const std::vector<u8> &bytes) const;
[[nodiscard]] bool matchesByte(u8 byte, u32 offset) const;
struct Pattern { struct Pattern {
u8 mask, value; u8 mask, value;
}; };
BinaryPattern() = default;
explicit BinaryPattern(const std::string &pattern) : m_patterns(parseBinaryPatternString(pattern)) { }
[[nodiscard]] bool isValid() const { return !m_patterns.empty(); }
[[nodiscard]] bool matches(const std::vector<u8> &bytes) const {
if (bytes.size() < m_patterns.size())
return false;
for (u32 i = 0; i < m_patterns.size(); i++) {
if (!this->matchesByte(bytes[i], i))
return false;
}
return true;
}
[[nodiscard]] bool matchesByte(u8 byte, u32 offset) const {
const auto &pattern = m_patterns[offset];
return (byte & pattern.mask) == pattern.value;
}
[[nodiscard]] u64 getSize() const {
return m_patterns.size();
}
private:
static std::vector<Pattern> parseBinaryPatternString(std::string string) {
std::vector<Pattern> result;
if (string.length() < 2)
return { };
bool inString = false;
while (string.length() > 0) {
Pattern pattern = { 0, 0 };
if (string.starts_with("\"")) {
inString = !inString;
string = string.substr(1);
continue;
} else if (inString) {
pattern = { 0xFF, u8(string.front()) };
string = string.substr(1);
} else if (string.starts_with("??")) {
pattern = { 0x00, 0x00 };
string = string.substr(2);
} else if ((std::isxdigit(string.front()) || string.front() == '?') && string.length() >= 2) {
const auto hex = string.substr(0, 2);
for (const auto &c : hex) {
pattern.mask <<= 4;
pattern.value <<= 4;
if (std::isxdigit(c)) {
pattern.mask |= 0x0F;
if (auto hexValue = hex::hexCharToValue(c); hexValue.has_value())
pattern.value |= hexValue.value();
else
return { };
} else if (c != '?') {
return { };
}
}
string = string.substr(2);
} else if (std::isspace(string.front())) {
string = string.substr(1);
continue;
} else {
return { };
}
result.push_back(pattern);
}
if (inString)
return { };
return result;
}
private: private:
std::vector<Pattern> m_patterns; std::vector<Pattern> m_patterns;
}; };

View File

@@ -14,10 +14,6 @@
static_assert(false, "Debug variables are only intended for use during development."); static_assert(false, "Debug variables are only intended for use during development.");
#endif #endif
namespace hex::trace {
struct StackTraceResult;
}
namespace hex::dbg { namespace hex::dbg {
namespace impl { namespace impl {
@@ -51,6 +47,4 @@ namespace hex::dbg {
bool debugModeEnabled(); bool debugModeEnabled();
void setDebugModeEnabled(bool enabled); void setDebugModeEnabled(bool enabled);
void printStackTrace(const trace::StackTraceResult &stackTrace);
} }

View File

@@ -27,11 +27,10 @@ namespace hex {
EncodingFile& operator=(const EncodingFile &other); EncodingFile& operator=(const EncodingFile &other);
EncodingFile& operator=(EncodingFile &&other) noexcept; EncodingFile& operator=(EncodingFile &&other) noexcept;
[[nodiscard]] std::pair<std::string_view, size_t> getEncodingFor(std::span<const u8> buffer) const; [[nodiscard]] std::pair<std::string_view, size_t> getEncodingFor(std::span<u8> buffer) const;
[[nodiscard]] u64 getEncodingLengthFor(std::span<u8> buffer) const; [[nodiscard]] u64 getEncodingLengthFor(std::span<u8> buffer) const;
[[nodiscard]] u64 getShortestSequence() const { return m_shortestSequence; } [[nodiscard]] u64 getShortestSequence() const { return m_shortestSequence; }
[[nodiscard]] u64 getLongestSequence() const { return m_longestSequence; } [[nodiscard]] u64 getLongestSequence() const { return m_longestSequence; }
[[nodiscard]] std::string decodeAll(std::span<const u8> buffer) const;
[[nodiscard]] bool valid() const { return m_valid; } [[nodiscard]] bool valid() const { return m_valid; }

View File

@@ -2,9 +2,7 @@
#include <hex.hpp> #include <hex.hpp>
#include <hex/api/task_manager.hpp>
#include <hex/helpers/literals.hpp> #include <hex/helpers/literals.hpp>
#include <hex/helpers/fs.hpp>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -29,14 +27,4 @@ namespace hex::magic {
bool isValidMIMEType(const std::string &mimeType); bool isValidMIMEType(const std::string &mimeType);
struct FoundPattern {
std::fs::path patternFilePath;
std::string author;
std::string description;
std::optional<std::string> mimeType;
std::optional<u64> magicOffset;
};
std::vector<FoundPattern> findViablePatterns(prv::Provider *provider, Task* task = nullptr);
} }

View File

@@ -12,9 +12,6 @@ namespace hex::menu {
bool beginMenu(const char *label, bool enabled = true); bool beginMenu(const char *label, bool enabled = true);
void endMenu(); void endMenu();
bool beginTaskBarMenu();
void endTaskBarMenu();
bool beginMenuEx(const char* label, const char* icon, bool enabled = true); bool beginMenuEx(const char* label, const char* icon, bool enabled = true);
bool menuItem(const char *label, const Shortcut &shortcut = Shortcut::None, bool selected = false, bool enabled = true); bool menuItem(const char *label, const Shortcut &shortcut = Shortcut::None, bool selected = false, bool enabled = true);

View File

@@ -10,7 +10,6 @@
#include <span> #include <span>
#include <string> #include <string>
#include <numbers> #include <numbers>
#include <array>
#include <opengl_support.h> #include <opengl_support.h>
#include "imgui.h" #include "imgui.h"
@@ -936,7 +935,7 @@ namespace hex::gl {
void attachTexture(const Texture &texture) const; void attachTexture(const Texture &texture) const;
private: private:
GLuint m_frameBuffer = 0, m_renderBuffer = 0; GLuint m_frameBuffer, m_renderBuffer;
}; };
class AxesVectors { class AxesVectors {

View File

@@ -28,8 +28,6 @@
#include <imgui.h> #include <imgui.h>
#include <wolv/utils/charconv.hpp>
namespace hex { namespace hex {
#if !defined(HEX_MODULE_EXPORT) #if !defined(HEX_MODULE_EXPORT)
@@ -98,8 +96,6 @@ namespace hex {
void startProgram(const std::vector<std::string> &command); void startProgram(const std::vector<std::string> &command);
int executeCommand(const std::string &command); int executeCommand(const std::string &command);
std::optional<std::string> executeCommandWithOutput(const std::string &command);
void executeCommandDetach(const std::string &command);
void openWebpage(std::string url); void openWebpage(std::string url);
extern "C" void registerFont(const char *fontName, const char *fontPath); extern "C" void registerFont(const char *fontName, const char *fontPath);
@@ -265,11 +261,7 @@ namespace hex {
if (!std::isxdigit(byteString[i]) || !std::isxdigit(byteString[i + 1])) if (!std::isxdigit(byteString[i]) || !std::isxdigit(byteString[i + 1]))
return {}; return {};
auto value = wolv::util::from_chars<u64>(byteString.substr(i, 2), 16); result.push_back(std::strtoul(byteString.substr(i, 2).c_str(), nullptr, 16));
if (!value.has_value())
return {};
result.push_back(*value);
} }
return result; return result;
@@ -370,7 +362,7 @@ namespace hex {
[[nodiscard]] std::optional<std::string> getEnvironmentVariable(const std::string &env); [[nodiscard]] std::optional<std::string> getEnvironmentVariable(const std::string &env);
[[nodiscard]] std::string limitStringLength(const std::string &string, size_t maxLength, bool fromBothEnds = true); [[nodiscard]] std::string limitStringLength(const std::string &string, size_t maxLength);
[[nodiscard]] std::optional<std::fs::path> getInitialFilePath(); [[nodiscard]] std::optional<std::fs::path> getInitialFilePath();

View File

@@ -32,7 +32,6 @@
void macosInstallEventListener(); void macosInstallEventListener();
void toastMessageMacos(const char *title, const char *message); void toastMessageMacos(const char *title, const char *message);
void macosSetupDockMenu(void);
} }
#endif #endif

View File

@@ -1,15 +0,0 @@
#pragma once
#include <iostream>
namespace hex::mcp {
class Client {
public:
Client() = default;
~Client() = default;
int run(std::istream &input, std::ostream &output);
};
}

View File

@@ -1,123 +0,0 @@
#pragma once
#include <hex.hpp>
#include <functional>
#include <nlohmann/json.hpp>
#include <wolv/net/socket_server.hpp>
namespace hex::mcp {
class JsonRpc {
public:
explicit JsonRpc(std::string request) : m_request(std::move(request)){ }
struct MethodNotFoundException : std::exception {};
struct InvalidParametersException : std::exception {};
enum class ErrorCode: i16 {
ParseError = -32700,
InvalidRequest = -32600,
MethodNotFound = -32601,
InvalidParams = -32602,
InternalError = -32603,
};
using Callback = std::function<nlohmann::json(const std::string &method, const nlohmann::json &params)>;
std::optional<std::string> execute(const Callback &callback);
void setError(ErrorCode code, std::string message);
private:
std::optional<nlohmann::json> handleMessage(const nlohmann::json &request, const Callback &callback);
std::optional<nlohmann::json> handleBatchedMessages(const nlohmann::json &request, const Callback &callback);
nlohmann::json createDefaultMessage();
nlohmann::json createErrorMessage(ErrorCode code, const std::string &message);
nlohmann::json createResponseMessage(const nlohmann::json &result);
private:
std::string m_request;
std::optional<int> m_id;
struct Error {
ErrorCode code;
std::string message;
};
std::optional<Error> m_error;
};
struct TextContent {
std::string text;
operator nlohmann::json() const {
nlohmann::json result;
result["content"] = nlohmann::json::array({
nlohmann::json::object({
{ "type", "text" },
{ "text", text }
})
});
return result;
}
};
struct StructuredContent {
std::string text;
nlohmann::json data;
operator nlohmann::json() const {
nlohmann::json result;
result["content"] = nlohmann::json::array({
nlohmann::json::object({
{ "type", "text" },
{ "text", text }
})
});
result["structuredContent"] = data;
return result;
}
};
class Server {
public:
constexpr static auto McpInternalPort = 19743;
Server();
~Server();
void listen();
void shutdown();
void disconnect();
bool isConnected();
void addPrimitive(std::string type, std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json &params)> function);
struct ClientInfo {
std::string name;
std::string version;
std::string protocolVersion;
};
const ClientInfo& getClientInfo() const {
return m_clientInfo;
}
private:
nlohmann::json handleInitialize(const nlohmann::json &params);
void handleNotifications(const std::string &method, const nlohmann::json &params);
struct Primitive {
nlohmann::json capabilities;
std::function<nlohmann::json(const nlohmann::json &params)> function;
};
std::map<std::string, std::map<std::string, Primitive>> m_primitives;
wolv::net::SocketServer m_server;
bool m_connected = false;
ClientInfo m_clientInfo;
};
}

View File

@@ -46,7 +46,7 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
[[maybe_unused]] static auto& getFeaturesImpl() { [[maybe_unused]] static auto& getFeaturesImpl() {
static hex::AutoReset<std::vector<hex::Feature>> features; static hex::AutoReset<std::vector<hex::Feature>> features;
return *features; return features;
} }
#if defined (IMHEX_STATIC_LINK_PLUGINS) #if defined (IMHEX_STATIC_LINK_PLUGINS)

View File

@@ -21,7 +21,7 @@ namespace hex::prv {
CachedProvider(size_t cacheBlockSize = 4096, size_t maxBlocks = 1024); CachedProvider(size_t cacheBlockSize = 4096, size_t maxBlocks = 1024);
~CachedProvider() override; ~CachedProvider() override;
OpenResult open() override; bool open() override;
void close() override; void close() override;
void readRaw(u64 offset, void *buffer, size_t size) override; void readRaw(u64 offset, void *buffer, size_t size) override;

View File

@@ -27,7 +27,7 @@ namespace hex::prv {
[[nodiscard]] bool isSavable() const override { return m_name.empty(); } [[nodiscard]] bool isSavable() const override { return m_name.empty(); }
[[nodiscard]] bool isSavableAsRecent() const override { return false; } [[nodiscard]] bool isSavableAsRecent() const override { return false; }
[[nodiscard]] OpenResult open() override; [[nodiscard]] bool open() override;
void close() override { } void close() override { }
void readRaw(u64 offset, void *buffer, size_t size) override; void readRaw(u64 offset, void *buffer, size_t size) override;

View File

@@ -72,21 +72,6 @@ namespace hex::prv {
[[nodiscard]] virtual std::vector<Description> getDataDescription() const = 0; [[nodiscard]] virtual std::vector<Description> getDataDescription() const = 0;
}; };
class IProviderDataBackupable {
public:
explicit IProviderDataBackupable(Provider *provider);
virtual ~IProviderDataBackupable() = default;
void createBackupIfNeeded(const std::fs::path &inputFilePath);
private:
Provider *m_provider = nullptr;
bool m_backupCreated = false;
bool m_shouldCreateBackups = true;
u64 m_maxSize;
std::string m_backupExtension;
};
/** /**
* @brief Represent the data source for a tab in the UI * @brief Represent the data source for a tab in the UI
*/ */
@@ -94,65 +79,6 @@ namespace hex::prv {
public: public:
constexpr static u64 MaxPageSize = 0xFFFF'FFFF'FFFF'FFFF; constexpr static u64 MaxPageSize = 0xFFFF'FFFF'FFFF'FFFF;
class OpenResult {
public:
OpenResult() : m_result(std::monostate{}) {}
[[nodiscard]] static OpenResult failure(std::string errorMessage) {
OpenResult result;
result.m_result = std::move(errorMessage);
return result;
}
[[nodiscard]] static OpenResult warning(std::string warningMessage) {
OpenResult result;
result.m_result = std::move(warningMessage);
result.m_warning = true;
return result;
}
[[nodiscard]] static OpenResult redirect(Provider *provider) {
OpenResult result;
result.m_result = provider;
return result;
}
[[nodiscard]] bool isSuccess() const {
return std::holds_alternative<std::monostate>(m_result);
}
[[nodiscard]] bool isFailure() const {
return std::holds_alternative<std::string>(m_result) && !m_warning;
}
[[nodiscard]] bool isWarning() const {
return std::holds_alternative<std::string>(m_result) && m_warning;
}
[[nodiscard]] bool isRedirecting() const {
return std::holds_alternative<Provider*>(m_result);
}
[[nodiscard]] Provider* getRedirectProvider() const {
if (std::holds_alternative<Provider*>(m_result)) {
return std::get<Provider*>(m_result);
}
return nullptr;
}
[[nodiscard]] std::string_view getErrorMessage() const {
if (std::holds_alternative<std::string>(m_result)) {
return std::get<std::string>(m_result);
}
return "";
}
private:
std::variant<std::monostate, std::string, Provider*> m_result;
bool m_warning = false;
};
Provider(); Provider();
virtual ~Provider(); virtual ~Provider();
Provider(const Provider&) = delete; Provider(const Provider&) = delete;
@@ -168,7 +94,7 @@ namespace hex::prv {
* @note This is not related to the EventProviderOpened event * @note This is not related to the EventProviderOpened event
* @return true if the provider was opened successfully, else false * @return true if the provider was opened successfully, else false
*/ */
[[nodiscard]] virtual OpenResult open() = 0; [[nodiscard]] virtual bool open() = 0;
/** /**
* @brief Closes this provider * @brief Closes this provider
@@ -336,6 +262,9 @@ namespace hex::prv {
void skipLoadInterface() { m_skipLoadInterface = true; } void skipLoadInterface() { m_skipLoadInterface = true; }
[[nodiscard]] bool shouldSkipLoadInterface() const { return m_skipLoadInterface; } [[nodiscard]] bool shouldSkipLoadInterface() const { return m_skipLoadInterface; }
void setErrorMessage(const std::string &errorMessage) { m_errorMessage = errorMessage; }
[[nodiscard]] const std::string& getErrorMessage() const { return m_errorMessage; }
template<std::derived_from<undo::Operation> T> template<std::derived_from<undo::Operation> T>
bool addUndoableOperation(auto && ... args) { bool addUndoableOperation(auto && ... args) {
return m_undoRedoStack.add<T>(std::forward<decltype(args)...>(args)...); return m_undoRedoStack.add<T>(std::forward<decltype(args)...>(args)...);
@@ -367,6 +296,8 @@ namespace hex::prv {
*/ */
bool m_skipLoadInterface = false; bool m_skipLoadInterface = false;
std::string m_errorMessage = "Unspecified error";
u64 m_pageSize = MaxPageSize; u64 m_pageSize = MaxPageSize;
}; };

View File

@@ -7,7 +7,6 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include <mutex>
#include <vector> #include <vector>
namespace hex::prv { namespace hex::prv {
@@ -41,8 +40,6 @@ namespace hex::prv::undo {
bool add(std::unique_ptr<Operation> &&operation); bool add(std::unique_ptr<Operation> &&operation);
static std::recursive_mutex& getMutex();
const std::vector<std::unique_ptr<Operation>> &getAppliedOperations() const { const std::vector<std::unique_ptr<Operation>> &getAppliedOperations() const {
return m_undoStack; return m_undoStack;
} }

View File

@@ -49,7 +49,7 @@ namespace hex::test {
[[nodiscard]] UnlocalizedString getTypeName() const override { return "hex.test.provider.test"; } [[nodiscard]] UnlocalizedString getTypeName() const override { return "hex.test.provider.test"; }
OpenResult open() override { return {}; } bool open() override { return true; }
void close() override { } void close() override { }
nlohmann::json storeSettings(nlohmann::json) const override { return {}; } nlohmann::json storeSettings(nlohmann::json) const override { return {}; }

View File

@@ -11,7 +11,6 @@
#include <hex/helpers/fmt.hpp> #include <hex/helpers/fmt.hpp>
#include <hex/helpers/concepts.hpp> #include <hex/helpers/concepts.hpp>
#include <hex/helpers/fs.hpp> #include <hex/helpers/fs.hpp>
#include <hex/helpers/scaling.hpp>
#include <wolv/utils/string.hpp> #include <wolv/utils/string.hpp>
@@ -134,8 +133,8 @@ namespace ImGuiExt {
bool IconHyperlink(const char *icon, const char *label, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0); bool IconHyperlink(const char *icon, const char *label, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
bool Hyperlink(const char *label, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0); bool Hyperlink(const char *label, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
bool BulletHyperlink(const char *label, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0); bool BulletHyperlink(const char *label, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
bool DescriptionButton(const char *label, const char *description, const char *icon, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0); bool DescriptionButton(const char *label, const char *description, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
bool DescriptionButtonProgress(const char *label, const char *description, const char *icon, float fraction, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0); bool DescriptionButtonProgress(const char *label, const char *description, float fraction, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
void HelpHover(const char *text, const char *icon = "(?)", ImU32 iconColor = ImGui::GetColorU32(ImGuiCol_ButtonActive)); void HelpHover(const char *text, const char *icon = "(?)", ImU32 iconColor = ImGui::GetColorU32(ImGuiCol_ButtonActive));
@@ -254,12 +253,11 @@ namespace ImGuiExt {
} }
void TextFormattedWrappedSelectable(std::string_view fmt, auto &&...args) { void TextFormattedWrappedSelectable(std::string_view fmt, auto &&...args) {
using namespace hex;
// Manually wrap text, using the letter M (generally the widest character in non-monospaced fonts) to calculate the character width to use. // Manually wrap text, using the letter M (generally the widest character in non-monospaced fonts) to calculate the character width to use.
auto text = wolv::util::trim(wolv::util::wrapMonospacedString( auto text = wolv::util::trim(wolv::util::wrapMonospacedString(
fmt::format(fmt::runtime(fmt), std::forward<decltype(args)>(args)...), fmt::format(fmt::runtime(fmt), std::forward<decltype(args)>(args)...),
ImGui::CalcTextSize("M").x, ImGui::CalcTextSize("M").x,
std::max(100_scaled, ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize - ImGui::GetStyle().FrameBorderSize) ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize - ImGui::GetStyle().FrameBorderSize
)); ));
auto textSize = ImGui::CalcTextSize(text.c_str()); auto textSize = ImGui::CalcTextSize(text.c_str());
@@ -270,7 +268,7 @@ namespace ImGuiExt {
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0F); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0F);
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4()); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4());
ImGui::PushItemWidth(textSize.x + ImGui::GetStyle().FramePadding.x * 2); ImGui::PushItemWidth(ImGui::CalcTextSize(text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2);
ImGui::InputTextMultiline( ImGui::InputTextMultiline(
"##", "##",
const_cast<char *>(text.c_str()), const_cast<char *>(text.c_str()),
@@ -314,12 +312,11 @@ namespace ImGuiExt {
bool BitCheckbox(const char* label, bool* v); bool BitCheckbox(const char* label, bool* v);
bool DimmedButton(const char* label, ImVec2 size = ImVec2(0, 0), ImGuiButtonFlags flags = ImGuiButtonFlags_None); bool DimmedButton(const char* label, ImVec2 size = ImVec2(0, 0));
bool DimmedIconButton(const char *symbol, ImVec4 color, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0)); bool DimmedIconButton(const char *symbol, ImVec4 color, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0)); bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
bool DimmedIconToggle(const char *icon, bool *v); bool DimmedIconToggle(const char *icon, bool *v);
bool DimmedIconToggle(const char *iconOn, const char *iconOff, bool *v); bool DimmedIconToggle(const char *iconOn, const char *iconOff, bool *v);
bool DimmedArrowButton(const char *id, ImGuiDir dir, ImVec2 size = ImVec2(ImGui::GetFrameHeight(), ImGui::GetFrameHeight()));
void TextOverlay(const char *text, ImVec2 pos, float maxWidth = -1); void TextOverlay(const char *text, ImVec2 pos, float maxWidth = -1);

View File

@@ -6,7 +6,6 @@
#include <list> #include <list>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <hex/api/task_manager.hpp>
namespace hex { namespace hex {
@@ -52,10 +51,10 @@ namespace hex {
template<typename ...Args> template<typename ...Args>
static void open(Args && ... args) { static void open(Args && ... args) {
TaskManager::doLater([=] { std::lock_guard lock(getMutex());
auto toast = std::make_unique<T>(args...);
auto toast = std::make_unique<T>(std::forward<Args>(args)...);
getQueuedToasts().emplace_back(std::move(toast)); getQueuedToasts().emplace_back(std::move(toast));
});
} }
}; };

View File

@@ -26,7 +26,7 @@ namespace hex {
* @brief Draws the view * @brief Draws the view
* @note Do not override this method. Override drawContent() instead * @note Do not override this method. Override drawContent() instead
*/ */
virtual void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) = 0; virtual void draw() = 0;
/** /**
* @brief Draws the content of the view * @brief Draws the content of the view
@@ -82,12 +82,10 @@ namespace hex {
*/ */
[[nodiscard]] virtual View* getMenuItemInheritView() const { return nullptr; } [[nodiscard]] virtual View* getMenuItemInheritView() const { return nullptr; }
[[nodiscard]] const char *getIcon() const { return m_icon; } [[nodiscard]] const char *getIcon() const { return m_icon; }
[[nodiscard]] const UnlocalizedString& getUnlocalizedName() const; [[nodiscard]] const UnlocalizedString& getUnlocalizedName() const;
[[nodiscard]] std::string getName() const; [[nodiscard]] std::string getName() const;
[[nodiscard]] virtual bool shouldDefaultFocus() const { return false; }
[[nodiscard]] virtual bool shouldStoreWindowState() const { return true; } [[nodiscard]] virtual bool shouldStoreWindowState() const { return true; }
[[nodiscard]] bool &getWindowOpenState(); [[nodiscard]] bool &getWindowOpenState();
@@ -110,22 +108,10 @@ namespace hex {
void trackViewState(); void trackViewState();
void setFocused(bool focused); void setFocused(bool focused);
protected:
/**
* @brief Called when this view is opened (i.e. made visible).
*/
virtual void onOpen() {}
/**
* @brief Called when this view is closed (i.e. made invisible).
*/
virtual void onClose() {}
public: public:
class Window; class Window;
class Special; class Special;
class Floating; class Floating;
class Scrolling;
class Modal; class Modal;
class FullScreen; class FullScreen;
@@ -147,24 +133,17 @@ namespace hex {
class View::Window : public View { class View::Window : public View {
public: public:
explicit Window(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon) {} explicit Window(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon) {}
[[nodiscard]] ImGuiWindow *getFocusedSubWindow() const { return m_focusedSubWindow; }
/** void draw() final {
* @brief Draws help text for the view if (this->shouldDraw()) {
*/ ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
virtual void drawHelpText() = 0; const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
if (ImGui::Begin(title.c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse | this->getWindowFlags())) {
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) override; this->drawContent();
}
[[nodiscard]] virtual bool allowScroll() const { ImGui::End();
return false; }
} }
private:
void handleFocusRestoration();
private:
ImGuiWindow *m_focusedSubWindow{nullptr};
}; };
/** /**
@@ -175,7 +154,12 @@ namespace hex {
public: public:
explicit Special(UnlocalizedString unlocalizedName) : View(std::move(unlocalizedName), "") {} explicit Special(UnlocalizedString unlocalizedName) : View(std::move(unlocalizedName), "") {}
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final; void draw() final {
if (this->shouldDraw()) {
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
this->drawContent();
}
}
}; };
/** /**
@@ -185,25 +169,10 @@ namespace hex {
public: public:
explicit Floating(UnlocalizedString unlocalizedName, const char *icon) : Window(std::move(unlocalizedName), icon) {} explicit Floating(UnlocalizedString unlocalizedName, const char *icon) : Window(std::move(unlocalizedName), icon) {}
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final; [[nodiscard]] ImGuiWindowFlags getWindowFlags() const override { return ImGuiWindowFlags_NoDocking; }
[[nodiscard]] bool shouldStoreWindowState() const override { return false; } [[nodiscard]] bool shouldStoreWindowState() const override { return false; }
}; };
/**
* @brief A view that draws all its content at once without any scrolling being done by the window itself
*/
class View::Scrolling : public View::Window {
public:
explicit Scrolling(UnlocalizedString unlocalizedName, const char *icon) : Window(std::move(unlocalizedName), icon) {}
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
[[nodiscard]] bool allowScroll() const final {
return true;
}
};
/** /**
* @brief A view that draws a modal window. The window will always be drawn on top and will block input to other windows * @brief A view that draws a modal window. The window will always be drawn on top and will block input to other windows
*/ */
@@ -211,7 +180,24 @@ namespace hex {
public: public:
explicit Modal(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon) {} explicit Modal(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon) {}
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final; void draw() final {
if (this->shouldDraw()) {
if (this->getWindowOpenState())
ImGui::OpenPopup(View::toWindowName(this->getUnlocalizedName()).c_str());
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
if (ImGui::BeginPopupModal(title.c_str(), this->hasCloseButton() ? &this->getWindowOpenState() : nullptr, ImGuiWindowFlags_NoCollapse | this->getWindowFlags())) {
this->drawContent();
ImGui::EndPopup();
}
if (ImGui::IsKeyPressed(ImGuiKey_Escape))
this->getWindowOpenState() = false;
}
}
[[nodiscard]] virtual bool hasCloseButton() const { return true; } [[nodiscard]] virtual bool hasCloseButton() const { return true; }
[[nodiscard]] bool shouldStoreWindowState() const override { return false; } [[nodiscard]] bool shouldStoreWindowState() const override { return false; }
@@ -221,7 +207,10 @@ namespace hex {
public: public:
explicit FullScreen() : View("FullScreen", "") {} explicit FullScreen() : View("FullScreen", "") {}
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final; void draw() final {
this->drawContent();
this->drawAlwaysVisibleContent();
}
}; };
} }

View File

@@ -264,7 +264,8 @@ namespace hex {
} }
} }
if (json.empty()) return; if (json.empty())
return;
#if defined(OS_WEB) #if defined(OS_WEB)
auto data = json.dump(); auto data = json.dump();

View File

@@ -594,12 +594,6 @@ namespace hex {
return false; return false;
} }
bool Spacer::draw(const std::string& name) {
std::ignore = name;
ImGui::NewLine();
return false;
}
} }
@@ -630,22 +624,22 @@ namespace hex {
void add(Type type, const std::string &command, const UnlocalizedString &unlocalizedDescription, const impl::DisplayCallback &displayCallback, const impl::ExecuteCallback &executeCallback) { void add(Type type, const std::string &command, const UnlocalizedString &unlocalizedDescription, const impl::DisplayCallback &displayCallback, const impl::ExecuteCallback &executeCallback) {
log::debug("Registered new command palette command: {}", command); log::debug("Registered new command palette command: {}", command);
impl::s_entries->push_back(impl::Entry { .type=type, .command=command, .unlocalizedDescription=unlocalizedDescription, .displayCallback=displayCallback, .executeCallback=executeCallback }); impl::s_entries->push_back(impl::Entry { type, command, unlocalizedDescription, displayCallback, executeCallback });
} }
void addHandler(Type type, const std::string &command, const impl::QueryCallback &queryCallback, const impl::DisplayCallback &displayCallback) { void addHandler(Type type, const std::string &command, const impl::QueryCallback &queryCallback, const impl::DisplayCallback &displayCallback) {
log::debug("Registered new command palette command handler: {}", command); log::debug("Registered new command palette command handler: {}", command);
impl::s_handlers->push_back(impl::Handler { .type=type, .command=command, .queryCallback=queryCallback, .displayCallback=displayCallback }); impl::s_handlers->push_back(impl::Handler { type, command, queryCallback, displayCallback });
} }
void setDisplayedContent(const impl::ContentDisplayCallback &displayCallback) { void setDisplayedContent(const impl::ContentDisplayCallback &displayCallback) {
impl::s_displayedContent = impl::ContentDisplay { .showSearchBox=true, .callback=displayCallback }; impl::s_displayedContent = impl::ContentDisplay { true, displayCallback };
} }
void openWithContent(const impl::ContentDisplayCallback &displayCallback) { void openWithContent(const impl::ContentDisplayCallback &displayCallback) {
RequestOpenCommandPalette::post(); RequestOpenCommandPalette::post();
impl::s_displayedContent = impl::ContentDisplay { .showSearchBox=false, .callback=displayCallback }; impl::s_displayedContent = impl::ContentDisplay { false, displayCallback };
} }
} }
@@ -783,12 +777,12 @@ namespace hex {
void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount) { void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount) {
log::debug("Registered new pattern visualizer function: {}", name); log::debug("Registered new pattern visualizer function: {}", name);
(*impl::s_visualizers)[name] = impl::Visualizer { .parameterCount=parameterCount, .callback=function }; (*impl::s_visualizers)[name] = impl::Visualizer { parameterCount, function };
} }
void addInlineVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount) { void addInlineVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount) {
log::debug("Registered new inline pattern visualizer function: {}", name); log::debug("Registered new inline pattern visualizer function: {}", name);
(*impl::s_inlineVisualizers)[name] = impl::Visualizer { .parameterCount=parameterCount, .callback=function }; (*impl::s_inlineVisualizers)[name] = impl::Visualizer { parameterCount, function };
} }
} }
@@ -854,7 +848,7 @@ namespace hex {
void add(const UnlocalizedString &unlocalizedName, const char *icon, const impl::Callback &function) { void add(const UnlocalizedString &unlocalizedName, const char *icon, const impl::Callback &function) {
log::debug("Registered new tool: {}", unlocalizedName.get()); log::debug("Registered new tool: {}", unlocalizedName.get());
impl::s_tools->emplace_back(impl::Entry { .unlocalizedName=unlocalizedName, .icon=icon, .function=function }); impl::s_tools->emplace_back(impl::Entry { unlocalizedName, icon, function });
} }
} }
@@ -870,18 +864,6 @@ namespace hex {
} }
namespace EditWidget {
std::optional<std::vector<u8>> TextInput::draw(std::string &value, std::endian endian) {
if (ImGui::InputText("##InspectorLineEditing", value,
ImGuiInputTextFlags_EnterReturnsTrue |
ImGuiInputTextFlags_AutoSelectAll)) {
return getBytes(value, endian);
}
return std::nullopt;
}
}
void add(const UnlocalizedString &unlocalizedName, size_t requiredSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction) { void add(const UnlocalizedString &unlocalizedName, size_t requiredSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction) {
log::debug("Registered new data inspector format: {}", unlocalizedName.get()); log::debug("Registered new data inspector format: {}", unlocalizedName.get());
@@ -1009,7 +991,7 @@ namespace hex {
coloredIcon.color = ImGuiCustomCol_ToolbarGray; coloredIcon.color = ImGuiCustomCol_ToolbarGray;
impl::s_menuItems->insert({ impl::s_menuItems->insert({
priority, impl::MenuItem { .unlocalizedNames=unlocalizedMainMenuNames, .icon=coloredIcon, .shortcut=shortcut, .view=view, .callback=function, .enabledCallback=enabledCallback, .selectedCallback=selectedCallback, .toolbarIndex=-1 } priority, impl::MenuItem { unlocalizedMainMenuNames, coloredIcon, shortcut, view, function, enabledCallback, selectedCallback, -1 }
}); });
if (shortcut != Shortcut::None) { if (shortcut != Shortcut::None) {
@@ -1024,32 +1006,23 @@ namespace hex {
} }
} }
void addMenuItemSubMenu(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback, View *view, bool showOnWelcomeScreen) { void addMenuItemSubMenu(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback, View *view) {
addMenuItemSubMenu(std::move(unlocalizedMainMenuNames), "", priority, function, enabledCallback, view, showOnWelcomeScreen); addMenuItemSubMenu(std::move(unlocalizedMainMenuNames), "", priority, function, enabledCallback, view);
} }
void addMenuItemSubMenu(std::vector<UnlocalizedString> unlocalizedMainMenuNames, const char *icon, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback, View *view, bool showOnWelcomeScreen) { void addMenuItemSubMenu(std::vector<UnlocalizedString> unlocalizedMainMenuNames, const char *icon, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback, View *view) {
log::debug("Added new menu item sub menu to menu {} with priority {}", unlocalizedMainMenuNames[0].get(), priority); log::debug("Added new menu item sub menu to menu {} with priority {}", unlocalizedMainMenuNames[0].get(), priority);
unlocalizedMainMenuNames.emplace_back(impl::SubMenuValue); unlocalizedMainMenuNames.emplace_back(impl::SubMenuValue);
impl::s_menuItems->insert({ impl::s_menuItems->insert({
priority, impl::MenuItem { .unlocalizedNames=unlocalizedMainMenuNames, .icon=icon, .shortcut=showOnWelcomeScreen ? Shortcut({ ShowOnWelcomeScreen }) : Shortcut::None, .view=view, .callback=function, .enabledCallback=enabledCallback, .selectedCallback=[]{ return false; }, .toolbarIndex=-1 } priority, impl::MenuItem { unlocalizedMainMenuNames, icon, Shortcut::None, view, function, enabledCallback, []{ return false; }, -1 }
}); });
} }
void addMenuItemSeparator(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, View *view) { void addMenuItemSeparator(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, View *view) {
unlocalizedMainMenuNames.emplace_back(impl::SeparatorValue); unlocalizedMainMenuNames.emplace_back(impl::SeparatorValue);
impl::s_menuItems->insert({ impl::s_menuItems->insert({
priority, impl::MenuItem { .unlocalizedNames=unlocalizedMainMenuNames, .icon="", .shortcut=Shortcut::None, .view=view, .callback=[]{}, .enabledCallback=[]{ return true; }, .selectedCallback=[]{ return false; }, .toolbarIndex=-1 } priority, impl::MenuItem { unlocalizedMainMenuNames, "", Shortcut::None, view, []{}, []{ return true; }, []{ return false; }, -1 }
});
}
void addTaskBarMenuItem(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback) {
log::debug("Added new taskbar menu item to menu {} ", unlocalizedMainMenuNames[0].get());
unlocalizedMainMenuNames.insert(unlocalizedMainMenuNames.begin(), impl::TaskBarMenuValue);
impl::s_menuItems->insert({
priority, impl::MenuItem { .unlocalizedNames=unlocalizedMainMenuNames, .icon="", .shortcut=Shortcut::None, .view=nullptr, .callback=function, .enabledCallback=enabledCallback, .selectedCallback=[]{ return false; }, .toolbarIndex=-1 }
}); });
} }
@@ -1065,13 +1038,13 @@ namespace hex {
impl::s_toolbarItems->push_back(function); impl::s_toolbarItems->push_back(function);
} }
void addMenuItemToToolbar(const std::vector<UnlocalizedString>& unlocalizedNames, ImGuiCustomCol color) { void addMenuItemToToolbar(const UnlocalizedString& unlocalizedName, ImGuiCustomCol color) {
const auto maxIndex = std::ranges::max_element(impl::getMenuItems(), [](const auto &a, const auto &b) { const auto maxIndex = std::ranges::max_element(impl::getMenuItems(), [](const auto &a, const auto &b) {
return a.second.toolbarIndex < b.second.toolbarIndex; return a.second.toolbarIndex < b.second.toolbarIndex;
})->second.toolbarIndex; })->second.toolbarIndex;
for (auto &[priority, menuItem] : *impl::s_menuItems) { for (auto &[priority, menuItem] : *impl::s_menuItems) {
if (menuItem.unlocalizedNames == unlocalizedNames) { if (menuItem.unlocalizedNames.back() == unlocalizedName) {
menuItem.toolbarIndex = maxIndex + 1; menuItem.toolbarIndex = maxIndex + 1;
menuItem.icon.color = color; menuItem.icon.color = color;
updateToolbarItems(); updateToolbarItems();
@@ -1123,18 +1096,18 @@ namespace hex {
} }
namespace ContentRegistry::Provider {
namespace impl {
namespace ContentRegistry::Provider::impl {
void add(const std::string &typeName, ProviderCreationFunction creationFunction) { void add(const std::string &typeName, ProviderCreationFunction creationFunction) {
(void)RequestCreateProvider::subscribe([expectedName = typeName, creationFunction](const std::string &name, bool skipLoadInterface, bool selectProvider, std::shared_ptr<prv::Provider> *provider) { (void)RequestCreateProvider::subscribe([expectedName = typeName, creationFunction](const std::string &name, bool skipLoadInterface, bool selectProvider, prv::Provider **provider) {
if (name != expectedName) return; if (name != expectedName) return;
auto newProvider = creationFunction(); auto newProvider = creationFunction();
if (provider != nullptr) { if (provider != nullptr) {
*provider = newProvider; *provider = newProvider.get();
ImHexApi::Provider::add(std::move(newProvider), skipLoadInterface, selectProvider); ImHexApi::Provider::add(std::move(newProvider), skipLoadInterface, selectProvider);
} }
}); });
@@ -1154,7 +1127,7 @@ namespace hex {
} }
}
namespace ContentRegistry::DataFormatter { namespace ContentRegistry::DataFormatter {
@@ -1310,8 +1283,9 @@ namespace hex {
} }
namespace ContentRegistry::Diffing {
namespace ContentRegistry::Diffing::impl { namespace impl {
static AutoReset<std::vector<std::unique_ptr<Algorithm>>> s_algorithms; static AutoReset<std::vector<std::unique_ptr<Algorithm>>> s_algorithms;
const std::vector<std::unique_ptr<Algorithm>>& getAlgorithms() { const std::vector<std::unique_ptr<Algorithm>>& getAlgorithms() {
@@ -1324,8 +1298,11 @@ namespace hex {
} }
}
namespace ContentRegistry::Hashes::impl { namespace ContentRegistry::Hashes {
namespace impl {
static AutoReset<std::vector<std::unique_ptr<Hash>>> s_hashes; static AutoReset<std::vector<std::unique_ptr<Hash>>> s_hashes;
const std::vector<std::unique_ptr<Hash>>& getHashes() { const std::vector<std::unique_ptr<Hash>>& getHashes() {
@@ -1338,6 +1315,7 @@ namespace hex {
} }
}
namespace ContentRegistry::BackgroundServices { namespace ContentRegistry::BackgroundServices {
@@ -1345,7 +1323,7 @@ namespace hex {
class Service { class Service {
public: public:
Service(UnlocalizedString unlocalizedName, std::jthread thread) : m_unlocalizedName(std::move(unlocalizedName)), m_thread(std::move(thread)) { } Service(const UnlocalizedString &unlocalizedName, std::jthread thread) : m_unlocalizedName(std::move(unlocalizedName)), m_thread(std::move(thread)) { }
Service(const Service&) = delete; Service(const Service&) = delete;
Service(Service &&) = default; Service(Service &&) = default;
~Service() { ~Service() {
@@ -1417,40 +1395,6 @@ namespace hex {
} }
namespace ContentRegistry::MCP {
namespace impl {
std::unique_ptr<mcp::Server>& getMcpServerInstance() {
static std::unique_ptr<mcp::Server> server;
if (server == nullptr)
server = std::make_unique<mcp::Server>();
return server;
}
static bool s_mcpEnabled = false;
void setEnabled(bool enabled) {
s_mcpEnabled = enabled;
}
}
bool isEnabled() {
return impl::s_mcpEnabled;
}
bool isConnected() {
return impl::getMcpServerInstance()->isConnected();
}
void registerTool(std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json &params)> function) {
impl::getMcpServerInstance()->addPrimitive("tools", capabilities, function);
}
}
namespace ContentRegistry::Experiments { namespace ContentRegistry::Experiments {
namespace impl { namespace impl {
@@ -1545,8 +1489,9 @@ namespace hex {
} }
namespace ContentRegistry::Disassemblers {
namespace ContentRegistry::Disassemblers::impl { namespace impl {
static AutoReset<std::map<std::string, impl::CreatorFunction>> s_architectures; static AutoReset<std::map<std::string, impl::CreatorFunction>> s_architectures;
@@ -1562,3 +1507,5 @@ namespace hex {
} }
} }
}

View File

@@ -1,4 +1,3 @@
#include <algorithm>
#include <hex/api/event_manager.hpp> #include <hex/api/event_manager.hpp>
namespace hex { namespace hex {
@@ -36,7 +35,7 @@ namespace hex {
void EventManager::unsubscribe(void *token, impl::EventId id) { void EventManager::unsubscribe(void *token, impl::EventId id) {
auto &tokenStore = getTokenStore(); auto &tokenStore = getTokenStore();
auto iter = std::ranges::find_if(tokenStore, [&](auto &item) { auto iter = std::find_if(tokenStore.begin(), tokenStore.end(), [&](auto &item) {
return item.first == token && item.second->first == id; return item.first == token && item.second->first == id;
}); });

View File

@@ -47,10 +47,6 @@
#if defined(OS_WEB) #if defined(OS_WEB)
#include <emscripten.h> #include <emscripten.h>
#elif defined(OS_MACOS)
extern "C" {
void macosRegisterFont(const unsigned char *data, size_t size);
}
#endif #endif
namespace hex { namespace hex {
@@ -261,7 +257,7 @@ namespace hex {
} }
void setSelection(u64 address, size_t size, prv::Provider *provider) { void setSelection(u64 address, size_t size, prv::Provider *provider) {
setSelection({ { .address=address, .size=size }, provider == nullptr ? Provider::get() : provider }); setSelection({ { address, size }, provider == nullptr ? Provider::get() : provider });
} }
void addVirtualFile(const std::string &path, std::vector<u8> data, Region region) { void addVirtualFile(const std::string &path, std::vector<u8> data, Region region) {
@@ -285,7 +281,7 @@ namespace hex {
} }
u64 add(u64 address, size_t size, const std::string &name, const std::string &comment, u32 color) { u64 add(u64 address, size_t size, const std::string &name, const std::string &comment, u32 color) {
return add(Region { .address=address, .size=size }, name, comment, color); return add(Region { address, size }, name, comment, color);
} }
void remove(u64 id) { void remove(u64 id) {
@@ -298,8 +294,8 @@ namespace hex {
namespace ImHexApi::Provider { namespace ImHexApi::Provider {
static i64 s_currentProvider = -1; static i64 s_currentProvider = -1;
static AutoReset<std::vector<std::shared_ptr<prv::Provider>>> s_providers; static AutoReset<std::vector<std::unique_ptr<prv::Provider>>> s_providers;
static AutoReset<std::map<prv::Provider*, std::shared_ptr<prv::Provider>>> s_providersToRemove; static AutoReset<std::map<prv::Provider*, std::unique_ptr<prv::Provider>>> s_providersToRemove;
namespace impl { namespace impl {
@@ -386,7 +382,7 @@ namespace hex {
}); });
} }
void add(std::shared_ptr<prv::Provider> &&provider, bool skipLoadInterface, bool select) { void add(std::unique_ptr<prv::Provider> &&provider, bool skipLoadInterface, bool select) {
std::scoped_lock lock(impl::s_providerMutex); std::scoped_lock lock(impl::s_providerMutex);
if (TaskManager::getRunningTaskCount() > 0) if (TaskManager::getRunningTaskCount() > 0)
@@ -395,7 +391,7 @@ namespace hex {
if (skipLoadInterface) if (skipLoadInterface)
provider->skipLoadInterface(); provider->skipLoadInterface();
EventProviderCreated::post(provider); EventProviderCreated::post(provider.get());
s_providers->emplace_back(std::move(provider)); s_providers->emplace_back(std::move(provider));
if (select || s_providers->size() == 1) if (select || s_providers->size() == 1)
@@ -495,17 +491,13 @@ namespace hex {
}); });
} }
std::shared_ptr<prv::Provider> createProvider(const UnlocalizedString &unlocalizedName, bool skipLoadInterface, bool select) { prv::Provider* createProvider(const UnlocalizedString &unlocalizedName, bool skipLoadInterface, bool select) {
std::shared_ptr<prv::Provider> result = nullptr; prv::Provider* result = nullptr;
RequestCreateProvider::post(unlocalizedName, skipLoadInterface, select, &result); RequestCreateProvider::post(unlocalizedName, skipLoadInterface, select, &result);
return result; return result;
} }
void openProvider(std::shared_ptr<prv::Provider> provider) {
RequestOpenProvider::post(provider);
}
} }
namespace ImHexApi::System { namespace ImHexApi::System {
@@ -538,11 +530,6 @@ namespace hex {
s_mainWindowHandle = window; s_mainWindowHandle = window;
} }
static bool s_mainWindowFocused = false;
void setMainWindowFocusState(bool focused) {
s_mainWindowFocused = focused;
}
static float s_globalScale = 1.0; static float s_globalScale = 1.0;
void setGlobalScale(float scale) { void setGlobalScale(float scale) {
@@ -680,15 +667,13 @@ namespace hex {
if (!sessionType.has_value() || sessionType == "x11") if (!sessionType.has_value() || sessionType == "x11")
return 1.0F; return 1.0F;
else { else {
int windowW, windowH; float xScale = 0, yScale = 0;
int displayW, displayH; glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &xScale, &yScale);
glfwGetWindowSize(getMainWindowHandle(), &windowW, &windowH);
glfwGetFramebufferSize(getMainWindowHandle(), &displayW, &displayH);
return (windowW > 0) ? float(displayW) / windowW : 1.0f; return std::midpoint(xScale, yScale);
} }
#elif defined(OS_WEB) #elif defined(OS_WEB)
return emscripten_get_device_pixel_ratio(); return 1.0F;
#else #else
return 1.0F; return 1.0F;
#endif #endif
@@ -715,15 +700,11 @@ namespace hex {
return impl::s_mainWindowHandle; return impl::s_mainWindowHandle;
} }
bool isMainWindowFocused() {
return impl::s_mainWindowFocused;
}
bool isBorderlessWindowModeEnabled() { bool isBorderlessWindowModeEnabled() {
return impl::s_borderlessWindowMode; return impl::s_borderlessWindowMode;
} }
bool isMultiWindowModeEnabled() { bool isMutliWindowModeEnabled() {
return impl::s_multiWindowMode; return impl::s_multiWindowMode;
} }
@@ -915,16 +896,15 @@ namespace hex {
} }
} }
return { { .name=name, .version=version } }; return { { name, version } };
} }
const SemanticVersion& getImHexVersion() { SemanticVersion getImHexVersion() {
#if defined(IMHEX_VERSION) #if defined(IMHEX_VERSION)
static auto version = SemanticVersion(IMHEX_VERSION); static auto version = SemanticVersion(IMHEX_VERSION);
return version; return version;
#else #else
static auto version = SemanticVersion(); return {};
return version;
#endif #endif
} }
@@ -966,9 +946,7 @@ namespace hex {
} }
bool isNightlyBuild() { bool isNightlyBuild() {
const static bool isNightly = getImHexVersion().nightly(); return getImHexVersion().nightly();
return isNightly;
} }
std::optional<std::string> checkForUpdate() { std::optional<std::string> checkForUpdate() {
@@ -1001,13 +979,7 @@ namespace hex {
const auto nightlyUpdateTime = hex::parseTime("%Y-%m-%dT%H:%M:%SZ", firstAsset["updated_at"].get<std::string>()); const auto nightlyUpdateTime = hex::parseTime("%Y-%m-%dT%H:%M:%SZ", firstAsset["updated_at"].get<std::string>());
const auto imhexBuildTime = ImHexApi::System::getBuildTime(); const auto imhexBuildTime = ImHexApi::System::getBuildTime();
if (nightlyUpdateTime.has_value() && imhexBuildTime.has_value() && *nightlyUpdateTime > *imhexBuildTime) {
// Give a bit of time leniency for the update time check
// We're comparing here the binary build time to the release upload time. If we were to strictly compare
// upload time to be greater than current build time, the check would always be true since the CI
// takes a few minutes after the build to actually upload the artifact.
// TODO: Is there maybe a better way to handle this without downloading the artifact just to check the build time?
if (nightlyUpdateTime.has_value() && imhexBuildTime.has_value() && *nightlyUpdateTime > *imhexBuildTime + std::chrono::hours(1)) {
return "Nightly"; return "Nightly";
} }
} else { } else {
@@ -1220,10 +1192,6 @@ namespace hex {
offset, offset,
fontSizeMultiplier fontSizeMultiplier
); );
#if defined(OS_MACOS)
macosRegisterFont(data.data(), data.size_bytes());
#endif
} }
void registerFont(const Font& font) { void registerFont(const Font& font) {
@@ -1235,7 +1203,7 @@ namespace hex {
if (it == impl::s_fontDefinitions->end()) { if (it == impl::s_fontDefinitions->end()) {
const auto defaultFont = ImGui::GetDefaultFont(); const auto defaultFont = ImGui::GetDefaultFont();
return { .regular=defaultFont, .bold=defaultFont, .italic=defaultFont }; return { defaultFont, defaultFont, defaultFont };
} else } else
return it->second; return it->second;
} }

View File

@@ -146,7 +146,7 @@ namespace hex {
} }
void LayoutManager::lockLayout(bool locked) { void LayoutManager::lockLayout(bool locked) {
log::debug("Layout {}", locked ? "locked" : "unlocked"); log::info("Layout {}", locked ? "locked" : "unlocked");
s_layoutLocked = locked; s_layoutLocked = locked;
} }

View File

@@ -7,7 +7,6 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <mutex> #include <mutex>
#include <hex/helpers/debugging.hpp>
namespace hex { namespace hex {
@@ -50,13 +49,9 @@ namespace hex {
definition.fallbackLanguageId = item["fallback"].get<std::string>(); definition.fallbackLanguageId = item["fallback"].get<std::string>();
} }
if (item.contains("hidden") && item["hidden"].get<bool>()) {
definition.hidden = true;
}
const auto path = item["path"].get<std::string>(); const auto path = item["path"].get<std::string>();
definition.languageFilePaths.emplace_back(PathEntry{ .path=path, .callback=callback }); definition.languageFilePaths.emplace_back(PathEntry{ path, callback });
} }
} }
@@ -104,21 +99,9 @@ namespace hex {
for (const auto &entry : json.items()) { for (const auto &entry : json.items()) {
auto value = entry.value().get<std::string>(); auto value = entry.value().get<std::string>();
// Skip empty values
if (value.empty()) if (value.empty())
continue; continue;
// Handle references to files
if (value.starts_with("#@")) {
try {
value = path.callback(value.substr(2));
} catch (std::exception &e) {
log::error("Failed to load localization file reference '{}': {}", entry.key(), e.what());
continue;
}
}
localizations.try_emplace(LangConst::hash(entry.key()), std::move(value)); localizations.try_emplace(LangConst::hash(entry.key()), std::move(value));
} }
} catch (std::exception &e) { } catch (std::exception &e) {
@@ -155,7 +138,7 @@ namespace hex {
static AutoReset<std::unordered_map<std::size_t, std::string>> loadedLocalization; static AutoReset<std::unordered_map<std::size_t, std::string>> loadedLocalization;
static std::mutex mutex; static std::mutex mutex;
std::scoped_lock lock(mutex); std::lock_guard lock(mutex);
if (*currentLanguageId != languageId) { if (*currentLanguageId != languageId) {
currentLanguageId = languageId; currentLanguageId = languageId;
loadedLocalization->clear(); loadedLocalization->clear();
@@ -171,33 +154,16 @@ namespace hex {
const LanguageDefinition& getLanguageDefinition(const LanguageId &languageId) { const LanguageDefinition& getLanguageDefinition(const LanguageId &languageId) {
const auto bestMatch = findBestLanguageMatch(languageId); const auto bestMatch = findBestLanguageMatch(languageId);
const auto &result = (*s_languageDefinitions)[bestMatch]; return (*s_languageDefinitions)[bestMatch];
if (!dbg::debugModeEnabled()) {
if (result.hidden)
return getLanguageDefinition(result.fallbackLanguageId);
}
return result;
} }
} }
static AutoReset<std::map<std::size_t, std::string>> s_unlocalizedNames; Lang::Lang(const char *unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)), m_unlocalizedString(unlocalizedString) { }
Lang::Lang(const std::string &unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)), m_unlocalizedString(unlocalizedString) { }
Lang::Lang(std::string_view unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)) { Lang::Lang(const LangConst &localizedString) : m_entryHash(localizedString.m_entryHash), m_unlocalizedString(localizedString.m_unlocalizedString) { }
if (!s_unlocalizedNames->contains(m_entryHash)) [[unlikely]] { Lang::Lang(const UnlocalizedString &unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString.get())), m_unlocalizedString(unlocalizedString.get()) { }
s_unlocalizedNames->emplace(m_entryHash, unlocalizedString); Lang::Lang(std::string_view unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)), m_unlocalizedString(unlocalizedString) { }
}
}
Lang::Lang(const char *unlocalizedString) : Lang(std::string_view(unlocalizedString)) { }
Lang::Lang(const std::string &unlocalizedString) : Lang(std::string_view(unlocalizedString)) { }
Lang::Lang(const LangConst &localizedString) : m_entryHash(localizedString.m_entryHash) {
if (!s_unlocalizedNames->contains(m_entryHash)) [[unlikely]] {
s_unlocalizedNames->emplace(m_entryHash, localizedString.m_unlocalizedString);
}
}
Lang::Lang(const UnlocalizedString &unlocalizedString) : Lang(unlocalizedString.get()) { }
Lang::operator std::string() const { Lang::operator std::string() const {
return get(); return get();
@@ -216,11 +182,7 @@ namespace hex {
const auto it = lang.find(m_entryHash); const auto it = lang.find(m_entryHash);
if (it == lang.end()) { if (it == lang.end()) {
if (auto unlocalizedIt = s_unlocalizedNames->find(m_entryHash); unlocalizedIt != s_unlocalizedNames->end()) { return m_unlocalizedString.c_str();
return unlocalizedIt->second.c_str();
} else {
return "<unlocalized>";
}
} else { } else {
return it->second.c_str(); return it->second.c_str();
} }

View File

@@ -85,7 +85,7 @@ namespace hex {
} }
Plugin::Plugin(const std::string &name, const hex::PluginFunctions &functions) : Plugin::Plugin(const std::string &name, const hex::PluginFunctions &functions) :
m_path(name), m_addedManually(true), m_functions(functions) { } m_handle(0), m_path(name), m_addedManually(true), m_functions(functions) { }
Plugin::Plugin(Plugin &&other) noexcept { Plugin::Plugin(Plugin &&other) noexcept {

View File

@@ -44,7 +44,7 @@ namespace hex {
} }
std::fs::path ProjectFile::getPath() { std::fs::path ProjectFile::getPath() {
return *s_currProjectPath; return s_currProjectPath;
} }
void ProjectFile::setPath(const std::fs::path &path) { void ProjectFile::setPath(const std::fs::path &path) {

View File

@@ -260,11 +260,8 @@ namespace hex {
case CTRLCMD.getKeyCode(): case CTRLCMD.getKeyCode():
result.cmd = true; result.cmd = true;
break; break;
case CurrentView.getKeyCode(): case CurrentView.getKeyCode(): break;
case AllowWhileTyping.getKeyCode(): case AllowWhileTyping.getKeyCode(): break;
case ShowOnWelcomeScreen.getKeyCode():
// Ignore flags that are only used internally by the ShortcutManager
break;
default: default:
macosGetKey(Keys(key.getKeyCode()), &result.key); macosGetKey(Keys(key.getKeyCode()), &result.key);
break; break;
@@ -281,25 +278,25 @@ namespace hex {
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) { void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get()); log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { .shortcut=shortcut, .unlocalizedName=unlocalizedName, .callback=callback, .enabledCallback=enabledCallback } }); auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, unlocalizedName, callback, enabledCallback } });
if (!inserted) log::error("Failed to add shortcut!"); if (!inserted) log::error("Failed to add shortcut!");
} }
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) { void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.get()); log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { .shortcut=shortcut, .unlocalizedName={ unlocalizedName }, .callback=callback, .enabledCallback=enabledCallback } }); auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, { unlocalizedName }, callback, enabledCallback } });
if (!inserted) log::error("Failed to add shortcut!"); if (!inserted) log::error("Failed to add shortcut!");
} }
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) { void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get()); log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { .shortcut=shortcut, .unlocalizedName=unlocalizedName, .callback=callback, .enabledCallback=enabledCallback } }); auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback, enabledCallback } });
if (!inserted) log::error("Failed to add shortcut!"); if (!inserted) log::error("Failed to add shortcut!");
} }
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) { void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.get()); log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { .shortcut=shortcut, .unlocalizedName={ unlocalizedName }, .callback=callback, .enabledCallback=enabledCallback } }); auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, { unlocalizedName }, callback, enabledCallback } });
if (!inserted) log::error("Failed to add shortcut!"); if (!inserted) log::error("Failed to add shortcut!");
} }
@@ -329,13 +326,12 @@ namespace hex {
if (ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId)) if (ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId))
return true; return true;
auto it = shortcuts.end(); const bool currentlyTyping = ImGui::GetIO().WantTextInput;
if (ImGui::GetIO().WantTextInput) {
it = shortcuts.find(shortcut + AllowWhileTyping); auto it = shortcuts.find(shortcut + AllowWhileTyping);
} else { if (!currentlyTyping && it == shortcuts.end()) {
it = shortcuts.find(shortcut);
if (it == shortcuts.end()) if (it == shortcuts.end())
it = shortcuts.find(shortcut + AllowWhileTyping); it = shortcuts.find(shortcut);
} }
if (it != shortcuts.end()) { if (it != shortcuts.end()) {
@@ -367,17 +363,7 @@ namespace hex {
if (keyCode != 0) if (keyCode != 0)
s_prevShortcut = Shortcut(pressedShortcut.getKeys()); s_prevShortcut = Shortcut(pressedShortcut.getKeys());
std::set<const View*> processedViews; runShortcut(pressedShortcut, currentView);
while (true) {
if (runShortcut(pressedShortcut, currentView)) {
break;
}
processedViews.insert(currentView);
currentView = currentView->getMenuItemInheritView();
if (currentView == nullptr || processedViews.contains(currentView))
break;
}
} }
void ShortcutManager::processGlobals(bool ctrl, bool alt, bool shift, bool super, u32 keyCode) { void ShortcutManager::processGlobals(bool ctrl, bool alt, bool shift, bool super, u32 keyCode) {
@@ -401,24 +387,6 @@ namespace hex {
s_globalShortcuts->clear(); s_globalShortcuts->clear();
} }
Shortcut ShortcutManager::getShortcutByName(const std::vector<UnlocalizedString> &unlocalizedName, const View *view) {
if (view != nullptr) {
for (const auto &[shortcut, entry] : view->m_shortcuts) {
if (entry.unlocalizedName == unlocalizedName) {
return entry.shortcut;
}
}
} else {
for (const auto &[shortcut, entry] : *s_globalShortcuts) {
if (entry.unlocalizedName == unlocalizedName) {
return entry.shortcut;
}
}
}
return Shortcut::None;
}
void ShortcutManager::resumeShortcuts() { void ShortcutManager::resumeShortcuts() {
s_paused = false; s_paused = false;
} }

View File

@@ -7,9 +7,6 @@
#include <ranges> #include <ranges>
#include <jthread.hpp> #include <jthread.hpp>
#include <hex/helpers/debugging.hpp>
#include <hex/trace/exceptions.hpp>
#include <utility>
#if defined(OS_WINDOWS) #if defined(OS_WINDOWS)
#include <windows.h> #include <windows.h>
@@ -55,7 +52,6 @@ namespace hex {
std::list<std::function<void()>> s_deferredCalls; std::list<std::function<void()>> s_deferredCalls;
std::unordered_map<SourceLocationWrapper, std::function<void()>> s_onceDeferredCalls; std::unordered_map<SourceLocationWrapper, std::function<void()>> s_onceDeferredCalls;
std::list<std::function<void()>> s_tasksFinishedCallbacks; std::list<std::function<void()>> s_tasksFinishedCallbacks;
std::list<std::function<void(Task&)>> s_taskCompletionCallbacks;
std::mutex s_queueMutex; std::mutex s_queueMutex;
std::condition_variable s_jobCondVar; std::condition_variable s_jobCondVar;
@@ -68,7 +64,7 @@ namespace hex {
} }
Task::Task(UnlocalizedString unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function) Task::Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function)
: m_unlocalizedName(std::move(unlocalizedName)), : m_unlocalizedName(std::move(unlocalizedName)),
m_maxValue(maxValue), m_maxValue(maxValue),
m_function(std::move(function)), m_function(std::move(function)),
@@ -86,17 +82,9 @@ namespace hex {
m_maxValue = u64(other.m_maxValue); m_maxValue = u64(other.m_maxValue);
m_currValue = u64(other.m_currValue); m_currValue = u64(other.m_currValue);
if (other.m_finished.test()) m_finished = bool(other.m_finished);
m_finished.test_and_set(); m_hadException = bool(other.m_hadException);
if (other.m_hadException.test()) m_interrupted = bool(other.m_interrupted);
m_hadException.test_and_set();
if (other.m_interrupted.test())
m_interrupted.test_and_set();
m_finished.notify_all();
m_hadException.notify_all();
m_interrupted.notify_all();
m_shouldInterrupt = bool(other.m_shouldInterrupt); m_shouldInterrupt = bool(other.m_shouldInterrupt);
} }
@@ -155,11 +143,11 @@ namespace hex {
bool Task::isFinished() const { bool Task::isFinished() const {
return m_finished.test(); return m_finished;
} }
bool Task::hadException() const { bool Task::hadException() const {
return m_hadException.test(); return m_hadException;
} }
bool Task::shouldInterrupt() const { bool Task::shouldInterrupt() const {
@@ -167,11 +155,11 @@ namespace hex {
} }
bool Task::wasInterrupted() const { bool Task::wasInterrupted() const {
return m_interrupted.test(); return m_interrupted;
} }
void Task::clearException() { void Task::clearException() {
m_hadException.clear(); m_hadException = false;
} }
std::string Task::getExceptionMessage() const { std::string Task::getExceptionMessage() const {
@@ -192,18 +180,12 @@ namespace hex {
return m_maxValue; return m_maxValue;
} }
void Task::wait() const {
m_finished.wait(false);
}
void Task::finish() { void Task::finish() {
m_finished.test_and_set(); m_finished = true;
m_finished.notify_all();
} }
void Task::interruption() { void Task::interruption() {
m_interrupted.test_and_set(); m_interrupted = true;
m_interrupted.notify_all();
} }
void Task::exception(const char *message) { void Task::exception(const char *message) {
@@ -211,8 +193,7 @@ namespace hex {
// Store information about the caught exception // Store information about the caught exception
m_exceptionMessage = message; m_exceptionMessage = message;
m_hadException.test_and_set(); m_hadException = true;
m_hadException.notify_all();
// Call the interrupt callback on the current thread if one is set // Call the interrupt callback on the current thread if one is set
if (m_interruptCallback) if (m_interruptCallback)
@@ -260,14 +241,6 @@ namespace hex {
task->interrupt(); task->interrupt();
} }
void TaskHolder::wait() const {
const auto &task = m_task.lock();
if (!task)
return;
task->wait();
}
u32 TaskHolder::getProgress() const { u32 TaskHolder::getProgress() const {
const auto &task = m_task.lock(); const auto &task = m_task.lock();
if (!task) if (!task)
@@ -314,8 +287,6 @@ namespace hex {
} }
try { try {
trace::enableExceptionCaptureForCurrentThread();
// Set the thread name to the name of the task // Set the thread name to the name of the task
TaskManager::setCurrentThreadName(Lang(task->m_unlocalizedName)); TaskManager::setCurrentThreadName(Lang(task->m_unlocalizedName));
@@ -323,34 +294,21 @@ namespace hex {
task->m_function(*task); task->m_function(*task);
log::debug("Task '{}' finished", task->m_unlocalizedName.get()); log::debug("Task '{}' finished", task->m_unlocalizedName.get());
{
std::scoped_lock lock(s_tasksFinishedMutex);
for (const auto &callback : s_taskCompletionCallbacks)
callback(*task);
}
} catch (const Task::TaskInterruptor &) { } catch (const Task::TaskInterruptor &) {
// Handle the task being interrupted by user request // Handle the task being interrupted by user request
task->interruption(); task->interruption();
} catch (const std::exception &e) { } catch (const std::exception &e) {
log::error("Exception in task '{}': {}", task->m_unlocalizedName.get(), e.what()); log::error("Exception in task '{}': {}", task->m_unlocalizedName.get(), e.what());
dbg::printStackTrace(trace::getStackTrace());
// Handle the task throwing an uncaught exception // Handle the task throwing an uncaught exception
task->exception(e.what()); task->exception(e.what());
} catch (...) { } catch (...) {
log::error("Exception in task '{}'", task->m_unlocalizedName.get()); log::error("Exception in task '{}'", task->m_unlocalizedName.get());
dbg::printStackTrace(trace::getStackTrace());
// Handle the task throwing an uncaught exception of unknown type // Handle the task throwing an uncaught exception of unknown type
task->exception("Unknown Exception"); task->exception("Unknown Exception");
} }
trace::disableExceptionCaptureForCurrentThread();
s_currentTask = nullptr; s_currentTask = nullptr;
task->finish(); task->finish();
} }
@@ -369,10 +327,7 @@ namespace hex {
thread.request_stop(); thread.request_stop();
// Wake up all the idle worker threads so they can exit // Wake up all the idle worker threads so they can exit
{
std::unique_lock lock(s_queueMutex);
s_jobCondVar.notify_all(); s_jobCondVar.notify_all();
}
// Wait for all worker threads to exit // Wait for all worker threads to exit
s_workers.clear(); s_workers.clear();
@@ -383,14 +338,13 @@ namespace hex {
s_deferredCalls.clear(); s_deferredCalls.clear();
s_onceDeferredCalls.clear(); s_onceDeferredCalls.clear();
s_tasksFinishedCallbacks.clear(); s_tasksFinishedCallbacks.clear();
s_taskCompletionCallbacks.clear();
} }
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task&)> function) { TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task&)> function) {
std::scoped_lock lock(s_queueMutex); std::scoped_lock lock(s_queueMutex);
// Construct new task // Construct new task
auto task = std::make_shared<Task>(unlocalizedName, maxValue, background, blocking, std::move(function)); auto task = std::make_shared<Task>(std::move(unlocalizedName), maxValue, background, blocking, std::move(function));
s_tasks.emplace_back(task); s_tasks.emplace_back(task);
@@ -405,12 +359,12 @@ namespace hex {
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function) { TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function) {
log::debug("Creating task {}", unlocalizedName.get()); log::debug("Creating task {}", unlocalizedName.get());
return createTask(unlocalizedName, maxValue, false, false, std::move(function)); return createTask(std::move(unlocalizedName), maxValue, false, false, std::move(function));
} }
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function) { TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function) {
log::debug("Creating task {}", unlocalizedName.get()); log::debug("Creating task {}", unlocalizedName.get());
return createTask(unlocalizedName, maxValue, false, false, return createTask(std::move(unlocalizedName), maxValue, false, false,
[function = std::move(function)](Task&) { [function = std::move(function)](Task&) {
function(); function();
} }
@@ -419,12 +373,12 @@ namespace hex {
TaskHolder TaskManager::createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void(Task &)> function) { TaskHolder TaskManager::createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void(Task &)> function) {
log::debug("Creating background task {}", unlocalizedName.get()); log::debug("Creating background task {}", unlocalizedName.get());
return createTask(unlocalizedName, 0, true, false, std::move(function)); return createTask(std::move(unlocalizedName), 0, true, false, std::move(function));
} }
TaskHolder TaskManager::createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void()> function) { TaskHolder TaskManager::createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void()> function) {
log::debug("Creating background task {}", unlocalizedName.get()); log::debug("Creating background task {}", unlocalizedName.get());
return createTask(unlocalizedName, 0, true, false, return createTask(std::move(unlocalizedName), 0, true, false,
[function = std::move(function)](Task&) { [function = std::move(function)](Task&) {
function(); function();
} }
@@ -433,12 +387,12 @@ namespace hex {
TaskHolder TaskManager::createBlockingTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function) { TaskHolder TaskManager::createBlockingTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function) {
log::debug("Creating blocking task {}", unlocalizedName.get()); log::debug("Creating blocking task {}", unlocalizedName.get());
return createTask(unlocalizedName, maxValue, true, true, std::move(function)); return createTask(std::move(unlocalizedName), maxValue, true, true, std::move(function));
} }
TaskHolder TaskManager::createBlockingTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function) { TaskHolder TaskManager::createBlockingTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function) {
log::debug("Creating blocking task {}", unlocalizedName.get()); log::debug("Creating blocking task {}", unlocalizedName.get());
return createTask(unlocalizedName, maxValue, true, true, return createTask(std::move(unlocalizedName), maxValue, true, true,
[function = std::move(function)](Task&) { [function = std::move(function)](Task&) {
function(); function();
} }
@@ -592,13 +546,5 @@ namespace hex {
return s_mainThreadId == std::this_thread::get_id(); return s_mainThreadId == std::this_thread::get_id();
} }
void TaskManager::addTaskCompletionCallback(const std::function<void(Task &)> &function) {
std::scoped_lock lock(s_tasksFinishedMutex);
for (const auto &task : s_tasks) {
task->interrupt();
}
s_taskCompletionCallbacks.push_back(function);
}
} }

View File

@@ -31,7 +31,7 @@ namespace hex {
void ThemeManager::addThemeHandler(const std::string &name, const ColorMap &colorMap, const std::function<ImColor(u32)> &getFunction, const std::function<void(u32, ImColor)> &setFunction) { void ThemeManager::addThemeHandler(const std::string &name, const ColorMap &colorMap, const std::function<ImColor(u32)> &getFunction, const std::function<void(u32, ImColor)> &setFunction) {
std::unique_lock lock(s_themeMutex); std::unique_lock lock(s_themeMutex);
(*s_themeHandlers)[name] = { .colorMap=colorMap, .getFunction=getFunction, .setFunction=setFunction }; (*s_themeHandlers)[name] = { colorMap, getFunction, setFunction };
} }
void ThemeManager::addStyleHandler(const std::string &name, const StyleMap &styleMap) { void ThemeManager::addStyleHandler(const std::string &name, const StyleMap &styleMap) {

View File

@@ -32,8 +32,6 @@ namespace hex {
ImGuiID s_activeHelpId; ImGuiID s_activeHelpId;
bool s_helpHoverActive = false; bool s_helpHoverActive = false;
AutoReset<std::function<std::function<void()>(const std::string &)>> s_renderer;
class IDStack { class IDStack {
public: public:
@@ -57,7 +55,7 @@ namespace hex {
void add(const void *pointer) { void add(const void *pointer) {
const ImGuiID seed = idStack.back(); const ImGuiID seed = idStack.back();
const ImGuiID id = ImHashData((const void*) &pointer, sizeof(pointer), seed); const ImGuiID id = ImHashData(&pointer, sizeof(pointer), seed);
idStack.push_back(id); idStack.push_back(id);
} }
@@ -96,21 +94,8 @@ namespace hex {
} }
void TutorialManager::init() { void TutorialManager::init() {
if (*s_renderer == nullptr) { EventImGuiElementRendered::subscribe([](ImGuiID id, const std::array<float, 4> bb){
*s_renderer = [](const std::string &message) { const auto boundingBox = ImRect(bb[0], bb[1], bb[2], bb[3]);
return [message] {
ImGui::PushTextWrapPos(300_scaled);
ImGui::TextUnformatted(message.c_str());
ImGui::PopTextWrapPos();
ImGui::NewLine();
};
};
}
}
void TutorialManager::postElementRendered(ImGuiID id, const ImRect &boundingBox) {
if (!ImGui::IsRectVisible(boundingBox.Min, boundingBox.Max))
return;
{ {
const auto element = hex::s_highlights->find(id); const auto element = hex::s_highlights->find(id);
@@ -137,6 +122,7 @@ namespace hex {
s_hoveredId = id; s_hoveredId = id;
} }
} }
});
} }
const std::map<std::string, TutorialManager::Tutorial>& TutorialManager::getTutorials() { const std::map<std::string, TutorialManager::Tutorial>& TutorialManager::getTutorials() {
@@ -215,13 +201,9 @@ namespace hex {
s_currentTutorial->second.start(); s_currentTutorial->second.start();
} }
void TutorialManager::stopCurrentTutorial() {
s_currentTutorial = s_tutorials->end();
}
void TutorialManager::drawHighlights() { void TutorialManager::drawHighlights() {
if (s_helpHoverActive) { if (s_helpHoverActive) {
const auto &drawList = ImGui::GetForegroundDrawList(ImGui::GetMainViewport()); const auto &drawList = ImGui::GetForegroundDrawList();
drawList->AddText(ImGui::GetMousePos() + scaled({ 10, -5, }), ImGui::GetColorU32(ImGuiCol_Text), "?"); drawList->AddText(ImGui::GetMousePos() + scaled({ 10, -5, }), ImGui::GetColorU32(ImGuiCol_Text), "?");
for (const auto &[id, boundingBox] : *s_interactiveHelpDisplays) { for (const auto &[id, boundingBox] : *s_interactiveHelpDisplays) {
@@ -269,7 +251,6 @@ namespace hex {
{ {
auto highlightColor = ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_Highlight); auto highlightColor = ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_Highlight);
highlightColor.w *= ImSin(ImGui::GetTime() * 6.0F) / 4.0F + 0.75F; highlightColor.w *= ImSin(ImGui::GetTime() * 6.0F) / 4.0F + 0.75F;
ImHexApi::System::unlockFrameRate();
drawList->AddRect(rect.Min - ImVec2(5, 5), rect.Max + ImVec2(5, 5), ImColor(highlightColor), 5.0F, ImDrawFlags_None, 2.0F); drawList->AddRect(rect.Min - ImVec2(5, 5), rect.Max + ImVec2(5, 5), ImColor(highlightColor), 5.0F, ImDrawFlags_None, 2.0F);
} }
@@ -318,10 +299,10 @@ namespace hex {
if (!message.has_value()) { if (!message.has_value()) {
message = Tutorial::Step::Message { message = Tutorial::Step::Message {
.position=Position::None, Position::None,
.unlocalizedTitle="", "",
.unlocalizedMessage="", "",
.allowSkip=false false
}; };
} }
@@ -348,39 +329,34 @@ namespace hex {
ImGui::SetNextWindowPos(position, ImGuiCond_Always, pivot); ImGui::SetNextWindowPos(position, ImGuiCond_Always, pivot);
ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID); ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID);
ImGui::SetNextWindowSize(ImVec2(300_scaled, 0)); if (ImGui::Begin("##TutorialMessage", nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing)) {
bool open = true;
if (ImGui::Begin(message->unlocalizedTitle.empty() ? "##TutorialMessage" : Lang(message->unlocalizedTitle), &open, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindowRead()); ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindowRead());
auto &step = s_currentTutorial->second.m_currentStep; if (!message->unlocalizedTitle.empty())
ImGuiExt::Header(Lang(message->unlocalizedTitle), true);
if (!message->unlocalizedMessage.empty()) { if (!message->unlocalizedMessage.empty()) {
step->m_drawFunction(); ImGui::PushTextWrapPos(300_scaled);
ImGui::NewLine(); ImGui::TextUnformatted(Lang(message->unlocalizedMessage));
ImGui::PopTextWrapPos();
ImGui::NewLine(); ImGui::NewLine();
} }
ImGui::BeginDisabled(step == s_currentTutorial->second.m_steps.begin()); ImGui::BeginDisabled(s_currentTutorial->second.m_currentStep == s_currentTutorial->second.m_steps.begin());
if (ImGuiExt::DimmedArrowButton("Backwards", ImGuiDir_Left)) { if (ImGui::ArrowButton("Backwards", ImGuiDir_Left)) {
s_currentTutorial->second.m_currentStep->advance(-1); s_currentTutorial->second.m_currentStep->advance(-1);
} }
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::SameLine(); ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - ImGui::GetFrameHeight() - ImGui::GetStyle().WindowPadding.x); ImGui::BeginDisabled(!message->allowSkip && s_currentTutorial->second.m_currentStep == s_currentTutorial->second.m_latestStep);
ImGui::BeginDisabled(!message->allowSkip && step == s_currentTutorial->second.m_latestStep); if (ImGui::ArrowButton("Forwards", ImGuiDir_Right)) {
if (ImGuiExt::DimmedArrowButton("Forwards", ImGuiDir_Right)) { s_currentTutorial->second.m_currentStep->advance(1);
step->advance(1);
} }
ImGui::EndDisabled(); ImGui::EndDisabled();
} }
ImGui::End(); ImGui::End();
if (!open) {
stopCurrentTutorial();
}
} }
void TutorialManager::drawTutorial() { void TutorialManager::drawTutorial() {
@@ -407,10 +383,6 @@ namespace hex {
s_highlightDisplays->clear(); s_highlightDisplays->clear();
} }
void TutorialManager::setRenderer(std::function<DrawFunction(const std::string &)> renderer) {
s_renderer = std::move(renderer);
}
TutorialManager::Tutorial::Step& TutorialManager::Tutorial::addStep() { TutorialManager::Tutorial::Step& TutorialManager::Tutorial::addStep() {
auto &newStep = m_steps.emplace_back(this); auto &newStep = m_steps.emplace_back(this);
m_currentStep = m_steps.end(); m_currentStep = m_steps.end();
@@ -426,9 +398,6 @@ namespace hex {
return; return;
m_currentStep->addHighlights(); m_currentStep->addHighlights();
if (m_currentStep->m_message.has_value())
m_currentStep->m_drawFunction = (*s_renderer)(Lang(m_currentStep->m_message->unlocalizedMessage));
} }
void TutorialManager::Tutorial::Step::addHighlights() const { void TutorialManager::Tutorial::Step::addHighlights() const {
@@ -453,12 +422,8 @@ namespace hex {
std::advance(m_parent->m_latestStep, steps); std::advance(m_parent->m_latestStep, steps);
std::advance(m_parent->m_currentStep, steps); std::advance(m_parent->m_currentStep, steps);
if (m_parent->m_currentStep != m_parent->m_steps.end()) { if (m_parent->m_currentStep != m_parent->m_steps.end())
m_parent->m_currentStep->addHighlights(); m_parent->m_currentStep->addHighlights();
if (m_message.has_value())
m_parent->m_currentStep->m_drawFunction = (*s_renderer)(Lang(m_parent->m_currentStep->m_message->unlocalizedMessage));
}
else else
s_currentTutorial = s_tutorials->end(); s_currentTutorial = s_tutorials->end();
} }
@@ -481,10 +446,10 @@ namespace hex {
TutorialManager::Tutorial::Step& TutorialManager::Tutorial::Step::setMessage(const UnlocalizedString &unlocalizedTitle, const UnlocalizedString &unlocalizedMessage, Position position) { TutorialManager::Tutorial::Step& TutorialManager::Tutorial::Step::setMessage(const UnlocalizedString &unlocalizedTitle, const UnlocalizedString &unlocalizedMessage, Position position) {
m_message = Message { m_message = Message {
.position=position, position,
.unlocalizedTitle=unlocalizedTitle, unlocalizedTitle,
.unlocalizedMessage=unlocalizedMessage, unlocalizedMessage,
.allowSkip=false false
}; };
return *this; return *this;
@@ -495,10 +460,10 @@ namespace hex {
m_message->allowSkip = true; m_message->allowSkip = true;
} else { } else {
m_message = Message { m_message = Message {
.position=Position::Bottom | Position::Right, Position::Bottom | Position::Right,
.unlocalizedTitle="", "",
.unlocalizedMessage="", "",
.allowSkip=true true
}; };
} }

Some files were not shown because too many files have changed in this diff Show More