mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-28 15:57:03 -05:00
Compare commits
42 Commits
feature/ap
...
releases/v
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
811214ddb7 | ||
|
|
cb406ea357 | ||
|
|
edb1a8876b | ||
|
|
2757075a10 | ||
|
|
8a4599feea | ||
|
|
f8f47012c4 | ||
|
|
32e2ccbca0 | ||
|
|
4d1e29d747 | ||
|
|
22dc3c6589 | ||
|
|
1c2bb0c049 | ||
|
|
5d53417683 | ||
|
|
c79321b550 | ||
|
|
0785270dfa | ||
|
|
84999d5c06 | ||
|
|
a0ca0e8596 | ||
|
|
1d99f8534d | ||
|
|
cfbc6e085a | ||
|
|
a45d30edca | ||
|
|
5a053aa146 | ||
|
|
d5a69d9201 | ||
|
|
dd0204f31d | ||
|
|
3b799388c2 | ||
|
|
c7c4ecad6d | ||
|
|
6784678ff0 | ||
|
|
dd8e7025d0 | ||
|
|
c2f661f021 | ||
|
|
c6fc26e2e7 | ||
|
|
3a99d53ba5 | ||
|
|
5fced6bb63 | ||
|
|
67930cf65d | ||
|
|
b305adb286 | ||
|
|
cbcf7b78e9 | ||
|
|
c922d9ceec | ||
|
|
ad235fad25 | ||
|
|
dffb7e95e3 | ||
|
|
916c1b7d4b | ||
|
|
2743b04f50 | ||
|
|
dbe8bfd75f | ||
|
|
c6c599c75b | ||
|
|
c2b7b4a11e | ||
|
|
495255484e | ||
|
|
b92b0922d5 |
7
.github/workflows/analysis.yml
vendored
7
.github/workflows/analysis.yml
vendored
@@ -8,7 +8,7 @@ on:
|
||||
jobs:
|
||||
codeql:
|
||||
name: 🐛 CodeQL
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
set -x
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=gcc-14 CXX=g++-14 cmake \
|
||||
CC=gcc-12 CXX=g++-12 cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
@@ -57,9 +57,8 @@ jobs:
|
||||
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
|
||||
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
|
||||
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
||||
-G Ninja \
|
||||
..
|
||||
ninja install
|
||||
make -j 4 install
|
||||
|
||||
- name: 🗯️ Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
472
.github/workflows/build.yml
vendored
472
.github/workflows/build.yml
vendored
@@ -6,7 +6,6 @@ on:
|
||||
- 'master'
|
||||
- 'releases/**'
|
||||
- 'tests/**'
|
||||
- 'feature/**'
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -19,18 +18,11 @@ jobs:
|
||||
win:
|
||||
runs-on: windows-2022
|
||||
name: 🪟 Windows MINGW64
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
|
||||
env:
|
||||
CCACHE_DIR: "${{ github.workspace }}/.ccache"
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -72,7 +64,7 @@ jobs:
|
||||
cd build
|
||||
|
||||
cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
||||
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
||||
-DIMHEX_GENERATE_PACKAGE=ON \
|
||||
-DIMHEX_USE_DEFAULT_BUILD_SETTINGS=ON \
|
||||
@@ -89,64 +81,11 @@ jobs:
|
||||
run: |
|
||||
cd build
|
||||
ninja install
|
||||
|
||||
- name: 🪲 Create PDBs for MSI
|
||||
run: |
|
||||
cd build
|
||||
|
||||
mkdir cv2pdb
|
||||
cd cv2pdb
|
||||
wget https://github.com/rainers/cv2pdb/releases/download/v0.52/cv2pdb-0.52.zip
|
||||
unzip cv2pdb-0.52.zip
|
||||
cd ..
|
||||
|
||||
cv2pdb/cv2pdb.exe imhex.exe
|
||||
cv2pdb/cv2pdb.exe imhex-gui.exe
|
||||
cv2pdb/cv2pdb.exe libimhex.dll
|
||||
cv2pdb/cv2pdb.exe libpl.dll
|
||||
|
||||
for plugin in plugins/*.hexplug; do
|
||||
cv2pdb/cv2pdb.exe $plugin
|
||||
done
|
||||
|
||||
rm -rf cv2pdb
|
||||
|
||||
- name: 📦 Bundle MSI
|
||||
run: |
|
||||
cd build
|
||||
cpack
|
||||
mv ImHex-*.msi ../imhex-${{ env.IMHEX_VERSION }}-Windows-x86_64.msi
|
||||
mv ImHex-*.msi ../imhex-${{env.IMHEX_VERSION}}-Windows-x86_64.msi
|
||||
|
||||
echo "ImHex checks for the existence of this file to determine if it is running in portable mode. You should not delete this file" > $PWD/install/PORTABLE
|
||||
|
||||
- name: 🪲 Create PDBs for ZIP
|
||||
run: |
|
||||
cd build/install
|
||||
|
||||
mkdir cv2pdb
|
||||
cd cv2pdb
|
||||
wget https://github.com/rainers/cv2pdb/releases/download/v0.52/cv2pdb-0.52.zip
|
||||
unzip cv2pdb-0.52.zip
|
||||
cd ..
|
||||
|
||||
cv2pdb/cv2pdb.exe imhex.exe
|
||||
cv2pdb/cv2pdb.exe imhex-gui.exe
|
||||
cv2pdb/cv2pdb.exe libimhex.dll
|
||||
cv2pdb/cv2pdb.exe libpl.dll
|
||||
|
||||
for plugin in plugins/*.hexplug; do
|
||||
cv2pdb/cv2pdb.exe $plugin
|
||||
done
|
||||
|
||||
rm -rf cv2pdb
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
with:
|
||||
subject-path: |
|
||||
imhex-*.msi
|
||||
|
||||
- name: ⬆️ Upload Windows Installer
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -180,70 +119,9 @@ jobs:
|
||||
path: |
|
||||
build/install/*
|
||||
|
||||
win-plugin-template-test:
|
||||
runs-on: windows-2022
|
||||
name: 🧪 Plugin Template Test
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
|
||||
needs: win
|
||||
|
||||
env:
|
||||
IMHEX_SDK_PATH: "${{ github.workspace }}/out/sdk"
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout ImHex
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: imhex
|
||||
|
||||
- name: 🟦 Install msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: mingw64
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
run: |
|
||||
set -x
|
||||
imhex/dist/get_deps_msys2.sh
|
||||
|
||||
- name: 🧰 Checkout ImHex-Plugin-Template
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: WerWolv/ImHex-Plugin-Template
|
||||
submodules: recursive
|
||||
path: template
|
||||
|
||||
- name: ⬇️ Download artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: Windows Portable x86_64
|
||||
path: out
|
||||
|
||||
- name: 🛠️ Build
|
||||
run: |
|
||||
set -x
|
||||
cd template
|
||||
mkdir -p build
|
||||
cd build
|
||||
|
||||
cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||
-DIMHEX_USE_DEFAULT_BUILD_SETTINGS=ON \
|
||||
-DUSE_SYSTEM_CAPSTONE=ON \
|
||||
..
|
||||
|
||||
ninja
|
||||
|
||||
# MacOS build
|
||||
macos-x86:
|
||||
runs-on: macos-13
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
macos:
|
||||
runs-on: macos-12
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -254,7 +132,7 @@ jobs:
|
||||
- suffix: ""
|
||||
custom_glfw: false
|
||||
|
||||
name: 🍎 macOS 13${{ matrix.suffix }}
|
||||
name: 🍎 macOS 12.0${{matrix.suffix}}
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
@@ -274,19 +152,15 @@ jobs:
|
||||
max-size: 1G
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
env:
|
||||
# Make brew not display useless errors
|
||||
HOMEBREW_TESTS: 1
|
||||
run: |
|
||||
brew reinstall python --quiet || true
|
||||
brew link --overwrite --quiet python 2>/dev/null || true
|
||||
brew bundle --no-lock --quiet --file dist/macOS/Brewfile || true
|
||||
brew reinstall python || brew link --overwrite python || true
|
||||
brew bundle --no-lock --file dist/Brewfile
|
||||
rm -rf /usr/local/Cellar/capstone
|
||||
|
||||
- name: ⬇️ Install classic glfw
|
||||
if: ${{! matrix.custom_glfw }}
|
||||
if: ${{! matrix.custom_glfw}}
|
||||
run: |
|
||||
brew install --quiet glfw || true
|
||||
brew install glfw || true
|
||||
|
||||
- name: ⬇️ Install .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
@@ -294,7 +168,7 @@ jobs:
|
||||
dotnet-version: '8.0.100'
|
||||
|
||||
- name: 🧰 Checkout glfw
|
||||
if: ${{ matrix.custom_glfw }}
|
||||
if: ${{matrix.custom_glfw}}
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: glfw/glfw
|
||||
@@ -302,7 +176,7 @@ jobs:
|
||||
|
||||
# GLFW custom build (to allow software rendering)
|
||||
- name: ⬇️ Patch and install custom glfw
|
||||
if: ${{ matrix.custom_glfw }}
|
||||
if: ${{matrix.custom_glfw}}
|
||||
run: |
|
||||
set -x
|
||||
cd glfw
|
||||
@@ -312,7 +186,7 @@ jobs:
|
||||
cd build
|
||||
|
||||
cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
||||
-DBUILD_SHARED_LIBS=ON \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
@@ -327,15 +201,14 @@ jobs:
|
||||
set -x
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=$(brew --prefix llvm)/bin/clang \
|
||||
CXX=$(brew --prefix llvm)/bin/clang++ \
|
||||
CC=$(brew --prefix gcc@12)/bin/gcc-12 \
|
||||
CXX=$(brew --prefix gcc@12)/bin/g++-12 \
|
||||
OBJC=$(brew --prefix llvm)/bin/clang \
|
||||
OBJCXX=$(brew --prefix llvm)/bin/clang++ \
|
||||
PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \
|
||||
cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
||||
-DIMHEX_GENERATE_PACKAGE=ON \
|
||||
-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_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||
@@ -363,43 +236,28 @@ jobs:
|
||||
cd build/install
|
||||
chmod -R 755 ImHex.app/
|
||||
|
||||
- name: 🔫 Kill XProtect
|
||||
run: |
|
||||
# See https://github.com/actions/runner-images/issues/7522
|
||||
echo Killing XProtect...; sudo pkill -9 XProtect >/dev/null || true;
|
||||
echo Waiting for XProtect process...; while pgrep XProtect; do sleep 3; done;
|
||||
|
||||
- name: 📦 Create DMG
|
||||
run: |
|
||||
brew install imagemagick
|
||||
git clone https://github.com/sindresorhus/create-dmg
|
||||
cd create-dmg
|
||||
npm i && npm -g i
|
||||
cd ../build/install
|
||||
create-dmg ImHex.app || true
|
||||
mv *.dmg ../../imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.suffix }}-x86_64.dmg
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
with:
|
||||
subject-path: |
|
||||
./*.dmg
|
||||
set -x
|
||||
mkdir bundle
|
||||
mv build/install/ImHex.app bundle
|
||||
cd bundle
|
||||
ln -s /Applications Applications
|
||||
cd ..
|
||||
hdiutil create -volname "ImHex" -srcfolder bundle -ov -format UDZO imhex-${{env.IMHEX_VERSION}}-macOS${{matrix.suffix}}-x86_64.dmg
|
||||
|
||||
- name: ⬆️ Upload DMG
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: macOS DMG${{ matrix.suffix }} x86_64
|
||||
name: macOS DMG${{matrix.suffix}} x86_64
|
||||
path: ./*.dmg
|
||||
|
||||
macos-arm64:
|
||||
runs-on: ubuntu-24.04
|
||||
name: 🍎 macOS 13 arm64
|
||||
|
||||
macos-arm64-build:
|
||||
runs-on: ubuntu-22.04
|
||||
name: 🍎 macOS 12.1 arm64
|
||||
outputs:
|
||||
IMHEX_VERSION: ${{ steps.build.outputs.IMHEX_VERSION }}
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -440,17 +298,11 @@ jobs:
|
||||
gh actions-cache delete "build-macos-arm64-cache" --confirm || true
|
||||
|
||||
macos-arm64-package:
|
||||
runs-on: macos-13
|
||||
name: 🍎 macOS 13 arm64 Packaging
|
||||
needs: macos-arm64
|
||||
|
||||
runs-on: macos-12
|
||||
name: 🍎 macOS 12.1 arm64 Packaging
|
||||
needs: macos-arm64-build
|
||||
env:
|
||||
IMHEX_VERSION: ${{ needs.macos-arm64-build.outputs.IMHEX_VERSION }}
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
- name: ⬇️ Download artifact
|
||||
uses: actions/download-artifact@v4
|
||||
@@ -477,28 +329,15 @@ jobs:
|
||||
cd out
|
||||
chmod -R 755 ImHex.app/
|
||||
|
||||
- name: 🔫 Kill XProtect
|
||||
run: |
|
||||
# See https://github.com/actions/runner-images/issues/7522
|
||||
echo Killing XProtect...; sudo pkill -9 XProtect >/dev/null || true;
|
||||
echo Waiting for XProtect process...; while pgrep XProtect; do sleep 3; done;
|
||||
|
||||
- name: 📦 Create DMG
|
||||
run: |
|
||||
brew install imagemagick
|
||||
git clone https://github.com/sindresorhus/create-dmg
|
||||
cd create-dmg
|
||||
npm i && npm -g i
|
||||
cd ../out
|
||||
create-dmg ImHex.app || true
|
||||
mv *.dmg ../imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.suffix }}-arm64.dmg
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
with:
|
||||
subject-path: |
|
||||
./*.dmg
|
||||
set -x
|
||||
mkdir bundle
|
||||
mv out/ImHex.app bundle
|
||||
cd bundle
|
||||
ln -s /Applications Applications
|
||||
cd ..
|
||||
hdiutil create -volname "ImHex" -srcfolder bundle -ov -format UDZO imhex-${{env.IMHEX_VERSION}}-macOS-arm64.dmg
|
||||
|
||||
- name: ⬆️ Upload DMG
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -513,20 +352,16 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- release_num: "24.04"
|
||||
- release_num: "24.10"
|
||||
- release_num: 22.04
|
||||
- release_num: 24.04
|
||||
|
||||
name: 🐧 Ubuntu ${{ matrix.release_num }}
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container:
|
||||
image: "ubuntu:${{ matrix.release_num }}"
|
||||
options: --privileged
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
- name: ⬇️ Install setup dependencies
|
||||
run: apt update && apt install -y git curl
|
||||
@@ -539,8 +374,8 @@ jobs:
|
||||
- name: 📜 Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: Ubuntu-${{ matrix.release_num }}-ccache-${{ github.run_id }}
|
||||
restore-keys: Ubuntu-${{ matrix.release_num }}-ccache
|
||||
key: Ubuntu-${{matrix.release_num}}-ccache-${{ github.run_id }}
|
||||
restore-keys: Ubuntu-${{matrix.release_num}}-ccache
|
||||
max-size: 1G
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
@@ -561,8 +396,8 @@ jobs:
|
||||
git config --global --add safe.directory '*'
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=gcc-14 CXX=g++-14 cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||
CC=gcc-12 CXX=g++-12 cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
@@ -584,15 +419,8 @@ jobs:
|
||||
- name: 📦 Bundle DEB
|
||||
run: |
|
||||
cp -r build/DEBIAN build/DebDir
|
||||
dpkg-deb -Zzstd --build build/DebDir
|
||||
mv build/DebDir.deb imhex-${{ env.IMHEX_VERSION }}-Ubuntu-${{ matrix.release_num }}-x86_64.deb
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
with:
|
||||
subject-path: |
|
||||
./*.deb
|
||||
dpkg-deb -Zgzip --build build/DebDir
|
||||
mv build/DebDir.deb imhex-${{env.IMHEX_VERSION}}-Ubuntu-${{ matrix.release_num }}-x86_64.deb
|
||||
|
||||
- name: ⬆️ Upload DEB
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -603,26 +431,8 @@ jobs:
|
||||
|
||||
# AppImage build
|
||||
appimage:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- architecture: "x86_64"
|
||||
architecture_package: "amd64"
|
||||
architecture_appimage_builder: "x86_64"
|
||||
image: ubuntu-24.04
|
||||
- architecture: "arm64"
|
||||
architecture_package: "arm64"
|
||||
architecture_appimage_builder: "aarch64"
|
||||
image: ubuntu-24.04-arm
|
||||
|
||||
runs-on: ${{ matrix.image }}
|
||||
name: ⬇️ AppImage ${{ matrix.architecture }}
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
name: ⬇️ AppImage
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -644,45 +454,32 @@ jobs:
|
||||
|
||||
- name: 🛠️ Build using docker
|
||||
run: |
|
||||
docker buildx build . -f dist/AppImage/Dockerfile --progress=plain --build-arg "BUILD_TYPE=$BUILD_TYPE" \
|
||||
--build-arg "GIT_COMMIT_HASH=$GITHUB_SHA" --build-arg "GIT_BRANCH=${GITHUB_REF##*/}" \
|
||||
--build-arg "ARCHITECTURE_PACKAGE=${{ matrix.architecture_package }}" --build-arg "ARCHITECTURE_FILE_NAME=${{ matrix.architecture }}" --build-arg "ARCHITECTURE_APPIMAGE_BUILDER=${{ matrix.architecture_appimage_builder }}" \
|
||||
--output out
|
||||
docker buildx build . -f dist/appimage/Dockerfile --progress=plain --build-arg "BUILD_TYPE=$BUILD_TYPE" \
|
||||
--build-arg "GIT_COMMIT_HASH=$GITHUB_SHA" --build-arg "GIT_BRANCH=${GITHUB_REF##*/}" --output out
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
with:
|
||||
subject-path: |
|
||||
out/*.AppImage
|
||||
out/*.AppImage.zsync
|
||||
|
||||
- name: ⬆️ Upload AppImage
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: Linux AppImage ${{ matrix.architecture }}
|
||||
name: Linux AppImage x86_64
|
||||
path: 'out/*.AppImage'
|
||||
|
||||
- name: ⬆️ Upload AppImage zsync
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: Linux AppImage zsync ${{ matrix.architecture }}
|
||||
name: Linux AppImage zsync x86_64
|
||||
path: 'out/*.AppImage.zsync'
|
||||
|
||||
# ArchLinux build
|
||||
archlinux-build:
|
||||
name: 🐧 ArchLinux
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container:
|
||||
image: archlinux:base-devel
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
- name: ⬇️ Update all packages
|
||||
run: |
|
||||
@@ -720,7 +517,7 @@ jobs:
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=gcc CXX=g++ cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
@@ -745,7 +542,7 @@ jobs:
|
||||
- name: ✒️ Prepare PKGBUILD
|
||||
run: |
|
||||
cp dist/Arch/PKGBUILD build
|
||||
sed -i 's/%version%/${{ env.IMHEX_VERSION }}/g' build/PKGBUILD
|
||||
sed -i 's/%version%/${{env.IMHEX_VERSION}}/g' build/PKGBUILD
|
||||
|
||||
# makepkg doesn't want to run as root, so I had to chmod 777 all over
|
||||
- name: 📦 Package ArchLinux .pkg.tar.zst
|
||||
@@ -755,23 +552,16 @@ jobs:
|
||||
|
||||
# the name is a small trick to make makepkg recognize it as the source
|
||||
# else, it would try to download the file from the release
|
||||
tar -cvf imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst -C installDir .
|
||||
tar -cvf imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst -C installDir .
|
||||
|
||||
chmod -R 777 .
|
||||
|
||||
sudo -u nobody makepkg
|
||||
|
||||
# Replace the old file
|
||||
rm imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst
|
||||
rm imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
|
||||
rm *imhex-bin-debug* # rm debug package which is created for some reason
|
||||
mv *.pkg.tar.zst imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
with:
|
||||
subject-path: |
|
||||
build/imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst
|
||||
mv *.pkg.tar.zst imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
|
||||
|
||||
- name: ⬆️ Upload imhex-archlinux.pkg.tar.zst
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -779,7 +569,7 @@ jobs:
|
||||
if-no-files-found: error
|
||||
name: ArchLinux .pkg.tar.zst x86_64
|
||||
path: |
|
||||
build/imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst
|
||||
build/imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
|
||||
|
||||
# RPM distro builds
|
||||
rpm-build:
|
||||
@@ -791,46 +581,29 @@ jobs:
|
||||
mock_release: rawhide
|
||||
release_num: rawhide
|
||||
mock_config: fedora-rawhide
|
||||
- name: Fedora
|
||||
mock_release: f41
|
||||
release_num: 41
|
||||
mock_config: fedora-41
|
||||
- name: Fedora
|
||||
mock_release: f40
|
||||
release_num: 40
|
||||
mock_config: fedora-40
|
||||
- name: Fedora
|
||||
mock_release: f39
|
||||
release_num: 39
|
||||
mock_config: fedora-39
|
||||
- name: RHEL-AlmaLinux
|
||||
mock_release: epel9
|
||||
release_num: 9
|
||||
mock_config: "alma+epel-9"
|
||||
|
||||
name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }}
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container:
|
||||
image: "almalinux:9"
|
||||
options: --privileged --pid=host --security-opt apparmor=unconfined
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
image: "fedora:latest"
|
||||
options: --privileged
|
||||
|
||||
steps:
|
||||
# This, together with the `--pid=host --security-opt apparmor=unconfined` docker options is required to allow
|
||||
# fedpkg to work inside a Docker container running on Ubuntu again.
|
||||
# GitHub seems to have enabled AppArmor on their Ubuntu CI runners which limits Docker in ways that cause
|
||||
# programs inside it to fail.
|
||||
# Without this, fedpkg will throw the unhelpful error message 'Insufficient Rights'
|
||||
# This step uses nsenter to execute commands on the host that disable AppArmor entirely.
|
||||
- name: 🛡️ Disable AppArmor on Host
|
||||
run: |
|
||||
nsenter -t 1 -m -u -n -i sudo systemctl disable --now apparmor.service
|
||||
nsenter -t 1 -m -u -n -i sudo aa-teardown || true
|
||||
nsenter -t 1 -m -u -n -i sudo sysctl --write kernel.apparmor_restrict_unprivileged_unconfined=0
|
||||
nsenter -t 1 -m -u -n -i sudo sysctl --write kernel.apparmor_restrict_unprivileged_userns=0
|
||||
|
||||
- name: ⬇️ Install git-core and EPEL repo
|
||||
run: dnf install git-core epel-release -y
|
||||
- name: ⬇️ Install git-core
|
||||
run: dnf install --disablerepo="*" --enablerepo="fedora" git-core -y
|
||||
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -849,8 +622,8 @@ jobs:
|
||||
- name: ⬇️ Update all packages and install dependencies
|
||||
run: |
|
||||
set -x
|
||||
dnf upgrade -y
|
||||
dnf install -y \
|
||||
dnf upgrade --disablerepo="*" --enablerepo="fedora,updates" -y
|
||||
dnf install --disablerepo="*" --enablerepo="fedora,updates" -y \
|
||||
fedpkg \
|
||||
ccache
|
||||
|
||||
@@ -876,16 +649,16 @@ jobs:
|
||||
- name: ✒️ Modify spec file
|
||||
run: |
|
||||
sed -i \
|
||||
-e 's/Version: VERSION$/Version: ${{ env.IMHEX_VERSION }}/g' \
|
||||
-e 's/IMHEX_OFFLINE_BUILD=ON/IMHEX_OFFLINE_BUILD=OFF/g' \
|
||||
-e '/IMHEX_OFFLINE_BUILD=OFF/a -D IMHEX_PATTERNS_PULL_MASTER=ON \\' \
|
||||
-e '/BuildRequires: cmake/a BuildRequires: git-core' \
|
||||
-e '/%files/a %{_datadir}/%{name}/' \
|
||||
-e 's/Version: VERSION$/Version: ${{env.IMHEX_VERSION}}/g' \
|
||||
-e 's/IMHEX_OFFLINE_BUILD=ON/IMHEX_OFFLINE_BUILD=OFF/g' \
|
||||
-e '/IMHEX_OFFLINE_BUILD=OFF/a -D IMHEX_PATTERNS_PULL_MASTER=ON \\' \
|
||||
-e '/BuildRequires: cmake/a BuildRequires: git-core' \
|
||||
-e '/%files/a %{_datadir}/%{name}/' \
|
||||
$GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec
|
||||
|
||||
- name: 📜 Fix ccache on EL9
|
||||
if: matrix.mock_release == 'epel9'
|
||||
run: sed -i '/\. \/opt\/rh\/gcc-toolset-14\/enable/a PATH=/usr/lib64/ccache:$PATH' $GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec
|
||||
run: sed -i '/\. \/opt\/rh\/gcc-toolset-12\/enable/a PATH=/usr/lib64/ccache:$PATH' $GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec
|
||||
|
||||
- name: 🟩 Copy spec file to build root
|
||||
run: mv $GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec $GITHUB_WORKSPACE/imhex.spec
|
||||
@@ -907,15 +680,8 @@ jobs:
|
||||
|
||||
- name: 🟩 Move and rename finished RPM
|
||||
run: |
|
||||
mv $GITHUB_WORKSPACE/results_imhex/${{ env.IMHEX_VERSION }}/*/imhex-${{ env.IMHEX_VERSION }}-0.*.x86_64.rpm \
|
||||
$GITHUB_WORKSPACE/imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.rpm
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
with:
|
||||
subject-path: |
|
||||
imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.rpm
|
||||
mv $GITHUB_WORKSPACE/results_imhex/${{env.IMHEX_VERSION}}/*/imhex-${{env.IMHEX_VERSION}}-0.*.x86_64.rpm \
|
||||
$GITHUB_WORKSPACE/imhex-${{env.IMHEX_VERSION}}-${{matrix.name}}-${{matrix.release_num}}-x86_64.rpm
|
||||
|
||||
- name: ⬆️ Upload RPM
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -923,86 +689,4 @@ jobs:
|
||||
if-no-files-found: error
|
||||
name: ${{ matrix.name }} ${{ matrix.release_num }} RPM x86_64
|
||||
path: |
|
||||
imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.rpm
|
||||
|
||||
webassembly-build:
|
||||
runs-on: ubuntu-24.04
|
||||
name: 🌍 Web
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
actions: write
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: 📁 Restore docker /cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: cache
|
||||
key: web-cache-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: 🐳 Inject /cache into docker
|
||||
uses: reproducible-containers/buildkit-cache-dance@v2
|
||||
with:
|
||||
cache-source: cache
|
||||
cache-target: /cache
|
||||
|
||||
- name: 🛠️ Build using docker
|
||||
run: |
|
||||
docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out --target raw
|
||||
|
||||
- name: 🔨 Fix permissions
|
||||
run: |
|
||||
chmod -c -R +rX "out/"
|
||||
|
||||
- name: ⬆️ Upload artifacts
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: out/
|
||||
|
||||
- name: 🔨 Copy necessary files
|
||||
run: |
|
||||
cp dist/web/serve.py out/start_imhex_web.py
|
||||
|
||||
- name: ⬆️ Upload package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: ImHex Web
|
||||
path: out/*
|
||||
|
||||
# See https://github.com/actions/cache/issues/342#issuecomment-1711054115
|
||||
- name: 🗑️ Delete old cache
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache || true
|
||||
gh actions-cache delete "build-web-cache" --confirm || true
|
||||
|
||||
webassembly-deploy:
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
actions: write
|
||||
name: 📃 Deploy to GitHub Pages
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
if: ${{ github.ref == 'refs/heads/master' && github.event.repository.fork == false }}
|
||||
needs: webassembly-build
|
||||
|
||||
steps:
|
||||
- name: 🌍 Deploy WebAssembly Build to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
|
||||
- name: 🗑️ Delete artifact
|
||||
uses: geekyeggo/delete-artifact@v5
|
||||
with:
|
||||
name: github-pages
|
||||
imhex-${{env.IMHEX_VERSION}}-${{matrix.name}}-${{matrix.release_num}}-x86_64.rpm
|
||||
|
||||
80
.github/workflows/build_web.yml
vendored
Normal file
80
.github/workflows/build_web.yml
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
name: Build for the web
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/**'
|
||||
- 'tests/**'
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
actions: write
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
name: 🌍 WebAssembly
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: 📁 Restore docker /cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: cache
|
||||
key: web-cache-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: 🐳 Inject /cache into docker
|
||||
uses: reproducible-containers/buildkit-cache-dance@v2
|
||||
with:
|
||||
cache-source: cache
|
||||
cache-target: /cache
|
||||
|
||||
- name: 🛠️ Build using docker
|
||||
run: |
|
||||
docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out --target raw
|
||||
|
||||
- name: 🔨 Fix permissions
|
||||
run: |
|
||||
chmod -c -R +rX "out/"
|
||||
|
||||
- name: ⬆️ Upload artifacts
|
||||
uses: actions/upload-pages-artifact@v2
|
||||
with:
|
||||
path: out/
|
||||
|
||||
# See https://github.com/actions/cache/issues/342#issuecomment-1711054115
|
||||
- name: 🗑️ Delete old cache
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache
|
||||
gh actions-cache delete "build-web-cache" --confirm
|
||||
|
||||
|
||||
deploy:
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
|
||||
name: 📃 Deploy to GitHub Pages
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
if: ${{ github.ref == 'refs/heads/master' && github.event.repository.fork == false }}
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- name: 🌍 Deploy
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v2
|
||||
9
.github/workflows/release.yml
vendored
9
.github/workflows/release.yml
vendored
@@ -10,7 +10,7 @@ on:
|
||||
|
||||
jobs:
|
||||
release-update-repos:
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-latest
|
||||
name: Release Update Repos
|
||||
|
||||
steps:
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
|
||||
release-upload-artifacts:
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-latest
|
||||
name: Release Upload Artifacts
|
||||
|
||||
steps:
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex
|
||||
|
||||
- name: ⬇️ Download artifacts from latest workflow
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
uses: dawidd6/action-download-artifact@v3
|
||||
with:
|
||||
github_token: ${{secrets.GITHUB_TOKEN}}
|
||||
workflow: build.yml
|
||||
@@ -117,7 +117,6 @@ jobs:
|
||||
run: |
|
||||
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-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
|
||||
|
||||
- name: ⬆️ Upload everything to release
|
||||
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
|
||||
@@ -148,7 +147,7 @@ jobs:
|
||||
commit_email: itrooz@protonmail.com
|
||||
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
||||
commit_message: Bump to version ${{ env.IMHEX_VERSION }}
|
||||
ssh_keyscan_types: rsa,ecdsa,ed25519
|
||||
ssh_keyscan_types: rsa,dsa,ecdsa,ed25519
|
||||
|
||||
release-update-winget:
|
||||
name: Release update winget package
|
||||
|
||||
30
.github/workflows/stale_issues.yml
vendored
30
.github/workflows/stale_issues.yml
vendored
@@ -1,30 +0,0 @@
|
||||
name: Close inactive issues
|
||||
on:
|
||||
schedule:
|
||||
- cron: "30 1 * * 0"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
close-issues:
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
operations-per-run: '200'
|
||||
ascending: true
|
||||
days-before-issue-stale: 334
|
||||
days-before-issue-close: 30
|
||||
stale-issue-label: "stale"
|
||||
stale-issue-message: |
|
||||
This issue is marked stale as it has been open for 11 months without activity.
|
||||
Please try the latest ImHex version. (Avaiable here: https://imhex.download/ for release and https://imhex.download/#nightly for development version)
|
||||
If the issue persists on the latest version, please make a comment on this issue again
|
||||
|
||||
Without response, this issue will be closed in one month.
|
||||
close-issue-message: ""
|
||||
days-before-pr-stale: -1
|
||||
days-before-pr-close: -1
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
38
.github/workflows/tests.yml
vendored
38
.github/workflows/tests.yml
vendored
@@ -6,7 +6,6 @@ on:
|
||||
- 'master'
|
||||
- 'releases/**'
|
||||
- 'tests/**'
|
||||
- 'feature/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'master'
|
||||
@@ -16,7 +15,7 @@ on:
|
||||
jobs:
|
||||
tests:
|
||||
name: 🧪 Unit Tests
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
@@ -39,13 +38,14 @@ jobs:
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo bash dist/get_deps_debian.sh
|
||||
sudo apt install gcovr -y
|
||||
|
||||
- name: 🛠️ Build
|
||||
run: |
|
||||
set -x
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=gcc-14 CXX=g++-14 cmake \
|
||||
CC=gcc-12 CXX=g++-12 cmake \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DIMHEX_ENABLE_UNIT_TESTS=ON \
|
||||
-DIMHEX_ENABLE_PLUGIN_TESTS=ON \
|
||||
@@ -54,10 +54,8 @@ jobs:
|
||||
-DCMAKE_C_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all --coverage" \
|
||||
-DCMAKE_CXX_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all --coverage" \
|
||||
-DIMHEX_OFFLINE_BUILD=ON \
|
||||
-G Ninja \
|
||||
..
|
||||
ninja unit_tests
|
||||
ninja imhex_all
|
||||
make -j4 unit_tests
|
||||
|
||||
- name: 🧪 Perform plcli Integration Tests
|
||||
run: |
|
||||
@@ -70,24 +68,16 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
# Generate report from all gcov .gcda files
|
||||
#- name: 🧪 Generate coverage report
|
||||
# run: |
|
||||
# sudo apt install python3-pip python3-venv
|
||||
# python3 -m venv venv
|
||||
# . venv/bin/activate
|
||||
# pip3 install gcovr
|
||||
# cd build
|
||||
# gcovr --gcov-executable /usr/bin/gcov-14 --exclude '.*/yara_rules/' --exclude '.*/third_party/' --exclude '.*/external/' --root .. --xml coverage_report.xml --verbose --gcov-ignore-errors all
|
||||
#
|
||||
#- name: Upload coverage reports to Codecov
|
||||
# env:
|
||||
# CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
# if: ${{ env.CODECOV_TOKEN }}
|
||||
# uses: codecov/codecov-action@v4
|
||||
# with:
|
||||
# fail_ci_if_error: true
|
||||
# token: ${{ secrets.CODECOV_TOKEN }}
|
||||
# file: build/coverage_report.xml
|
||||
- name: 🧪 Generate coverage report
|
||||
run: |
|
||||
gcovr --gcov-executable /usr/bin/gcov-12 -r . build --xml coverage_report.xml --verbose
|
||||
|
||||
- name: Upload coverage reports to Codecov
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
fail_ci_if_error: true
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
file: coverage_report.xml
|
||||
|
||||
langs:
|
||||
name: 🧪 Langs
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,7 +6,6 @@ cmake-build-*/
|
||||
build*/
|
||||
local/
|
||||
venv/
|
||||
.cache/
|
||||
|
||||
*.mgc
|
||||
*.kdev4
|
||||
|
||||
7
.gitmodules
vendored
7
.gitmodules
vendored
@@ -28,7 +28,7 @@
|
||||
ignore = dirty
|
||||
[submodule "lib/third_party/lunasvg"]
|
||||
path = lib/third_party/lunasvg
|
||||
url = https://github.com/WerWolv/lunasvg
|
||||
url = https://github.com/sammycage/lunasvg
|
||||
ignore = dirty
|
||||
|
||||
[submodule "lib/external/libromfs"]
|
||||
@@ -43,7 +43,4 @@
|
||||
|
||||
[submodule "lib/third_party/HashLibPlus"]
|
||||
path = lib/third_party/HashLibPlus
|
||||
url = https://github.com/WerWolv/HashLibPlus
|
||||
[submodule "lib/external/disassembler"]
|
||||
path = lib/external/disassembler
|
||||
url = https://github.com/WerWolv/Disassembler
|
||||
url = https://github.com/WerWolv/HashLibPlus
|
||||
@@ -32,14 +32,13 @@ include("${IMHEX_BASE_FOLDER}/cmake/ide_helpers.cmake")
|
||||
# Basic compiler and cmake configurations
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
include("${IMHEX_BASE_FOLDER}/cmake/build_helpers.cmake")
|
||||
|
||||
# Setup project
|
||||
loadVersion(IMHEX_VERSION IMHEX_VERSION_PLAIN)
|
||||
setVariableInParent(IMHEX_VERSION ${IMHEX_VERSION})
|
||||
|
||||
configureCMake()
|
||||
|
||||
project(imhex
|
||||
LANGUAGES C CXX
|
||||
VERSION ${IMHEX_VERSION_PLAIN}
|
||||
@@ -73,18 +72,16 @@ addPluginDirectories()
|
||||
|
||||
# Add unit tests
|
||||
if (IMHEX_ENABLE_UNIT_TESTS)
|
||||
if (NOT TARGET unit_tests)
|
||||
enable_testing()
|
||||
add_custom_target(unit_tests)
|
||||
add_subdirectory(tests EXCLUDE_FROM_ALL)
|
||||
endif ()
|
||||
enable_testing()
|
||||
add_subdirectory(tests EXCLUDE_FROM_ALL)
|
||||
endif ()
|
||||
|
||||
# Configure more resources that will be added to the install package
|
||||
generatePDBs()
|
||||
generateSDKDirectory()
|
||||
|
||||
# Handle package generation
|
||||
createPackage()
|
||||
|
||||
# Accommodate IDEs with FOLDER support
|
||||
# Accomodate IDEs with FOLDER support
|
||||
tweakTargetsForIDESupport()
|
||||
|
||||
@@ -27,11 +27,6 @@ chmod +x imhex-*.AppImage
|
||||
./imhex-*.AppImage
|
||||
```
|
||||
|
||||
If you're experiencing glib / libgtk assertion failures, you might need to setup your `XDG_DATA_DIRS` env var correctly. In this case, run the following command before executing the AppImage. (See issue [ImHex/#2038](https://github.com/WerWolv/ImHex/issues/2038))
|
||||
```bash
|
||||
export XDG_DATA_DIRS="/usr/local/share:/usr/share"
|
||||
```
|
||||
|
||||
#### Flatpak
|
||||
To install the Flatpak, make sure you have the Flathub repository added to your system. Then simply run the following command:
|
||||
|
||||
|
||||
33
README.md
33
README.md
@@ -38,8 +38,8 @@ If you like my work, please consider supporting me on GitHub Sponsors, Patreon o
|
||||
</p>
|
||||
|
||||
## Screenshots
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
<details>
|
||||
<summary><strong>More Screenshots</strong></summary>
|
||||
@@ -314,26 +314,23 @@ To use ImHex, the following minimal system requirements need to be met.
|
||||
> ImHex requires a GPU with OpenGL 3.0 support in general.
|
||||
> There are releases available (with the `-NoGPU` suffix) that are software rendered and don't require a GPU, however these can be a lot slower than the GPU accelerated versions.
|
||||
>
|
||||
> If possible at all, make ImHex use the dedicated GPU on your system instead of the integrated one.
|
||||
> ImHex will usually run fine with integrated GPUs as well but certain Intel HD GPU drivers on Windows are known to cause graphical artifacts.
|
||||
> If possible at all, make ImHex use the dedicated GPU on your system instead of the integrated one (especially Intel HD GPUs are known to cause issues).
|
||||
|
||||
- **OS**:
|
||||
- **Windows**: Windows 7 or higher (Windows 10/11 recommended)
|
||||
- **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.
|
||||
- The macOS build is not signed and will require you to manually allow them in the Security & Privacy settings.
|
||||
- **macOS**: macOS 12.1 (Monterey) or higher,
|
||||
- Lower versions are supported, but you'll need to compile ImHex yourself
|
||||
- **Linux**: "Modern" Linux. The following distributions have official releases available. Other distros are supported through the AppImage and Flatpak releases.
|
||||
- Ubuntu and Debian
|
||||
- Fedora
|
||||
- RHEL/AlmaLinux
|
||||
- Ubuntu 22.04/23.04
|
||||
- Fedora 36/37
|
||||
- RHEL/AlmaLinux 9
|
||||
- Arch Linux
|
||||
- Basically any other distro will work as well when compiling ImHex from sources.
|
||||
- **CPU**: Officially supported are x86_64 and ARM64, though any Little Endian 64 bit CPU should work.
|
||||
- **CPU**: x86_64 (64 Bit)
|
||||
- **GPU**: OpenGL 3.0 or higher
|
||||
- Integrated Intel HD iGPUs are supported, however certain drivers are known to cause various graphical artifacts, especially on Windows. Use at your own risk.
|
||||
- Intel HD drivers are really buggy and often cause graphic artifacts
|
||||
- In case you don't have a GPU available, there are software rendered releases available for Windows and macOS
|
||||
- **RAM**: ~150MiB, more is required for more complex analysis
|
||||
- **Storage**: 150MiB
|
||||
- **RAM**: 256MB, more may be required for more complicated analysis
|
||||
- **Storage**: 100MB
|
||||
|
||||
## Installing
|
||||
|
||||
@@ -342,10 +339,8 @@ Information on how to install ImHex can be found in the [Install](/INSTALL.md) g
|
||||
## Compiling
|
||||
|
||||
To compile ImHex on any platform, GCC (or Clang) is required with a version that supports C++23 or higher.
|
||||
Windows and Linux releases are being built using latest available GCC.
|
||||
MacOS releases are being built using latest available LLVM Clang.
|
||||
|
||||
Important to note is, the MSVC and AppleClang compilers are both **NOT** supported since they're both generally severely outdated and lack features GCC and LLVM Clang have.
|
||||
On macOS, Clang is also required to compile some ObjC code.
|
||||
All releases are being built using latest available GCC.
|
||||
|
||||
> [!NOTE]
|
||||
> Many dependencies are bundled into the repository using submodules so make sure to clone it using the `--recurse-submodules` option.
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
# Some libraries we use set the BUILD_SHARED_LIBS variable to ON, which causes CMake to
|
||||
# display a warning about options being set using set() instead of option().
|
||||
# Explicitly set the policy to NEW to suppress the warning.
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
||||
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW)
|
||||
|
||||
if (POLICY CMP0177)
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0177 OLD)
|
||||
cmake_policy(SET CMP0177 OLD)
|
||||
endif()
|
||||
|
||||
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Disable deprecated warnings" FORCE)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
if(IMHEX_STRIP_RELEASE)
|
||||
@@ -239,8 +225,7 @@ macro(createPackage)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.mime.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages RENAME imhex.xml)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.svg DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.svg)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.png)
|
||||
downloadImHexPatternsFiles("./share/imhex")
|
||||
|
||||
# install AppStream file
|
||||
@@ -254,7 +239,6 @@ macro(createPackage)
|
||||
|
||||
if (APPLE)
|
||||
if (IMHEX_GENERATE_PACKAGE)
|
||||
set(EXTRA_BUNDLE_LIBRARY_PATHS ${EXTRA_BUNDLE_LIBRARY_PATHS} "${IMHEX_SYSTEM_LIBRARY_PATH}")
|
||||
include(PostprocessBundle)
|
||||
|
||||
set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION})
|
||||
@@ -323,6 +307,9 @@ endfunction()
|
||||
macro(configureCMake)
|
||||
message(STATUS "Configuring ImHex v${IMHEX_VERSION}")
|
||||
|
||||
# Enable C and C++ languages
|
||||
enable_language(C CXX)
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE BOOL "Enable position independent code for all targets" FORCE)
|
||||
|
||||
# Configure use of recommended build tools
|
||||
@@ -384,12 +371,18 @@ macro(configureCMake)
|
||||
message(WARNING "LTO is not supported: ${output_error}")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Some libraries we use set the BUILD_SHARED_LIBS variable to ON, which causes CMake to
|
||||
# display a warning about options being set using set() instead of option().
|
||||
# Explicitly set the policy to NEW to suppress the warning.
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
||||
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW)
|
||||
|
||||
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Disable deprecated warnings" FORCE)
|
||||
endmacro()
|
||||
|
||||
function(configureProject)
|
||||
# Enable C and C++ languages
|
||||
enable_language(C CXX)
|
||||
|
||||
if (XCODE)
|
||||
# Support Xcode's multi configuration paradigm by placing built artifacts into separate directories
|
||||
set(IMHEX_MAIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Configs/$<CONFIG>" PARENT_SCOPE)
|
||||
@@ -580,7 +573,7 @@ macro(setupCompilerFlags target)
|
||||
set(IMHEX_CXX_FLAGS "-fexceptions -frtti")
|
||||
|
||||
# Disable some warnings
|
||||
set(IMHEX_C_CXX_FLAGS "-Wno-array-bounds -Wno-deprecated-declarations -Wno-unknown-pragmas")
|
||||
set(IMHEX_C_CXX_FLAGS "-Wno-unknown-warning-option -Wno-array-bounds -Wno-deprecated-declarations -Wno-unknown-pragmas")
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
@@ -589,13 +582,6 @@ macro(setupCompilerFlags target)
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND APPLE)
|
||||
execute_process(COMMAND brew --prefix llvm OUTPUT_VARIABLE LLVM_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
|
||||
set(IMHEX_C_CXX_FLAGS "-Wno-unknown-warning-option")
|
||||
endif()
|
||||
|
||||
# Disable some warnings for gcc
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
set(IMHEX_C_CXX_FLAGS "${IMHEX_C_CXX_FLAGS} -Wno-restrict -Wno-stringop-overread -Wno-stringop-overflow -Wno-dangling-reference")
|
||||
@@ -654,7 +640,6 @@ macro(addBundledLibraries)
|
||||
set(FPHSA_NAME_MISMATCHED ON CACHE BOOL "")
|
||||
|
||||
if(NOT USE_SYSTEM_FMT)
|
||||
set(FMT_INSTALL OFF CACHE BOOL "Disable install targets for libfmt" FORCE)
|
||||
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/fmt EXCLUDE_FROM_ALL)
|
||||
set(FMT_LIBRARIES fmt::fmt-header-only)
|
||||
else()
|
||||
@@ -717,8 +702,8 @@ macro(addBundledLibraries)
|
||||
endif()
|
||||
|
||||
if (USE_SYSTEM_BOOST)
|
||||
find_package(Boost REQUIRED)
|
||||
set(BOOST_LIBRARIES Boost::regex)
|
||||
find_package(boost REQUIRED)
|
||||
set(BOOST_LIBRARIES boost::regex)
|
||||
else()
|
||||
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/boost ${CMAKE_CURRENT_BINARY_DIR}/boost EXCLUDE_FROM_ALL)
|
||||
set(BOOST_LIBRARIES boost::regex)
|
||||
@@ -734,7 +719,6 @@ macro(addBundledLibraries)
|
||||
endif()
|
||||
|
||||
add_subdirectory(${EXTERNAL_LIBS_FOLDER}/pattern_language EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(${EXTERNAL_LIBS_FOLDER}/disassembler EXCLUDE_FROM_ALL)
|
||||
|
||||
if (LIBPL_SHARED_LIBRARY)
|
||||
install(
|
||||
@@ -791,6 +775,59 @@ function(enableUnityBuild TARGET)
|
||||
endif ()
|
||||
endfunction()
|
||||
|
||||
function(generatePDBs)
|
||||
if (NOT IMHEX_GENERATE_PDBS)
|
||||
return()
|
||||
endif ()
|
||||
|
||||
if (NOT WIN32 OR CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
return()
|
||||
endif ()
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
cv2pdb
|
||||
URL "https://github.com/rainers/cv2pdb/releases/download/v0.52/cv2pdb-0.52.zip"
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP ON
|
||||
)
|
||||
FetchContent_Populate(cv2pdb)
|
||||
|
||||
set(PDBS_TO_GENERATE main main-forwarder libimhex ${PLUGINS})
|
||||
foreach (PDB ${PDBS_TO_GENERATE})
|
||||
if (PDB STREQUAL "main")
|
||||
set(GENERATED_PDB imhex)
|
||||
elseif (PDB STREQUAL "main-forwarder")
|
||||
set(GENERATED_PDB imhex-gui)
|
||||
elseif (PDB STREQUAL "libimhex")
|
||||
set(GENERATED_PDB libimhex)
|
||||
else ()
|
||||
set(GENERATED_PDB plugins/${PDB})
|
||||
endif ()
|
||||
|
||||
if (IMHEX_REPLACE_DWARF_WITH_PDB)
|
||||
set(PDB_OUTPUT_PATH ${CMAKE_BINARY_DIR}/${GENERATED_PDB})
|
||||
else ()
|
||||
set(PDB_OUTPUT_PATH)
|
||||
endif()
|
||||
|
||||
add_custom_target(${PDB}_pdb DEPENDS ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb)
|
||||
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMAND
|
||||
(
|
||||
${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb &&
|
||||
${cv2pdb_SOURCE_DIR}/cv2pdb64.exe $<TARGET_FILE:${PDB}> ${PDB_OUTPUT_PATH} &&
|
||||
${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/${GENERATED_PDB}
|
||||
) || (exit 0)
|
||||
COMMAND_EXPAND_LISTS)
|
||||
|
||||
install(FILES ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb DESTINATION ".")
|
||||
|
||||
add_dependencies(imhex_all ${PDB}_pdb)
|
||||
endforeach ()
|
||||
|
||||
endfunction()
|
||||
|
||||
function(generateSDKDirectory)
|
||||
if (WIN32)
|
||||
set(SDK_PATH "./sdk")
|
||||
@@ -811,7 +848,7 @@ function(generateSDKDirectory)
|
||||
if (NOT USE_SYSTEM_NLOHMANN_JSON)
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/nlohmann_json DESTINATION "${SDK_PATH}/lib/third_party")
|
||||
endif()
|
||||
if (NOT USE_SYSTEM_BOOST)
|
||||
if (NOT USE_SYSTEM_NLOHMANN_JSON)
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/boost DESTINATION "${SDK_PATH}/lib/third_party")
|
||||
endif()
|
||||
|
||||
@@ -819,12 +856,6 @@ function(generateSDKDirectory)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/cmake/build_helpers.cmake DESTINATION "${SDK_PATH}/cmake")
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/sdk/ DESTINATION "${SDK_PATH}")
|
||||
install(TARGETS libimhex ARCHIVE DESTINATION "${SDK_PATH}/lib")
|
||||
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/plugins/ui DESTINATION "${SDK_PATH}/lib" PATTERN "**/source/*" EXCLUDE)
|
||||
install(TARGETS ui ARCHIVE DESTINATION "${SDK_PATH}/lib")
|
||||
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/plugins/fonts DESTINATION "${SDK_PATH}/lib" PATTERN "**/source/*" EXCLUDE)
|
||||
install(TARGETS fonts ARCHIVE DESTINATION "${SDK_PATH}/lib")
|
||||
endfunction()
|
||||
|
||||
function(addIncludesFromLibrary target library)
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
find_path(LZ4_INCLUDE_DIR
|
||||
NAMES lz4.h
|
||||
HINTS "${LZ4_INCLUDEDIR}" "${LZ4_HINTS}/include"
|
||||
PATHS
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
)
|
||||
|
||||
find_library(LZ4_LIBRARY
|
||||
NAMES lz4 liblz4
|
||||
HINTS "${LZ4_LIBDIR}" "${LZ4_HINTS}/lib"
|
||||
PATHS
|
||||
/usr/local/lib
|
||||
/usr/lib
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args( LZ4 DEFAULT_MSG LZ4_LIBRARY LZ4_INCLUDE_DIR )
|
||||
|
||||
if( LZ4_FOUND )
|
||||
include( CheckIncludeFile )
|
||||
include( CMakePushCheckState )
|
||||
|
||||
set( LZ4_INCLUDE_DIRS ${LZ4_INCLUDE_DIR} )
|
||||
set( LZ4_LIBRARIES ${LZ4_LIBRARY} )
|
||||
|
||||
cmake_push_check_state()
|
||||
set( CMAKE_REQUIRED_INCLUDES ${LZ4_INCLUDE_DIRS} )
|
||||
check_include_file( lz4frame.h HAVE_LZ4FRAME_H )
|
||||
cmake_pop_check_state()
|
||||
|
||||
if (WIN32)
|
||||
set ( LZ4_DLL_DIR "${LZ4_HINTS}/bin"
|
||||
CACHE PATH "Path to LZ4 DLL"
|
||||
)
|
||||
file( GLOB _lz4_dll RELATIVE "${LZ4_DLL_DIR}"
|
||||
"${LZ4_DLL_DIR}/lz4*.dll"
|
||||
)
|
||||
set ( LZ4_DLL ${_lz4_dll}
|
||||
# We're storing filenames only. Should we use STRING instead?
|
||||
CACHE FILEPATH "LZ4 DLL file name"
|
||||
)
|
||||
file( GLOB _lz4_pdb RELATIVE "${LZ4_DLL_DIR}"
|
||||
"${LZ4_DLL_DIR}/lz4*.pdb"
|
||||
)
|
||||
set ( LZ4_PDB ${_lz4_pdb}
|
||||
CACHE FILEPATH "LZ4 PDB file name"
|
||||
)
|
||||
mark_as_advanced( LZ4_DLL_DIR LZ4_DLL LZ4_PDB )
|
||||
endif()
|
||||
else()
|
||||
set( LZ4_INCLUDE_DIRS )
|
||||
set( LZ4_LIBRARIES )
|
||||
endif()
|
||||
|
||||
mark_as_advanced( LZ4_LIBRARIES LZ4_INCLUDE_DIRS )
|
||||
|
||||
add_library( LZ4::lz4 INTERFACE IMPORTED )
|
||||
set_property( TARGET LZ4::lz4 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${LZ4_INCLUDE_DIRS} )
|
||||
set_property( TARGET LZ4::lz4 PROPERTY INTERFACE_LINK_LIBRARIES ${LZ4_LIBRARIES} )
|
||||
@@ -55,9 +55,9 @@ IF(MBEDTLS_FOUND)
|
||||
MESSAGE(STATUS " Crypto: ${MBEDCRYPTO_LIBRARY}")
|
||||
ENDIF(NOT MBEDTLS_FIND_QUIETLY)
|
||||
ELSE(MBEDTLS_FOUND)
|
||||
IF(mbedTLS_FIND_REQUIRED)
|
||||
IF(MBEDTLS_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find mbedTLS")
|
||||
ENDIF(mbedTLS_FIND_REQUIRED)
|
||||
ENDIF(MBEDTLS_FIND_REQUIRED)
|
||||
ENDIF(MBEDTLS_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
@@ -67,4 +67,4 @@ MARK_AS_ADVANCED(
|
||||
MBEDTLS_LIBRARY
|
||||
MBEDX509_LIBRARY
|
||||
MBEDCRYPTO_LIBRARY
|
||||
)
|
||||
)
|
||||
@@ -11,23 +11,31 @@ AppDir:
|
||||
exec_args: $@
|
||||
apt:
|
||||
arch:
|
||||
- "{{ARCHITECTURE_PACKAGE}}"
|
||||
- amd64
|
||||
allow_unauthenticated: true
|
||||
sources:
|
||||
- sourceline: 'deb [arch=amd64] http://us.archive.ubuntu.com/ubuntu/ oracular main restricted universe multiverse'
|
||||
- sourceline: 'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ oracular main restricted universe multiverse'
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy main restricted
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy-updates main restricted
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy universe
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy-updates universe
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy multiverse
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy-updates multiverse
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy-backports main restricted
|
||||
universe multiverse
|
||||
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security main restricted
|
||||
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security universe
|
||||
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security multiverse
|
||||
include:
|
||||
- librsvg2-common
|
||||
- libbz2-1.0
|
||||
- libcap2
|
||||
- libdbus-1-3
|
||||
- libfontconfig1
|
||||
- libgpg-error0
|
||||
- liblzma5
|
||||
- libnss-mdns
|
||||
- libpcre3
|
||||
- libselinux1
|
||||
- libtinfo6
|
||||
- libbz2-1.0:amd64
|
||||
- libcap2:amd64
|
||||
- libdbus-1-3:amd64
|
||||
- libgpg-error0:amd64
|
||||
- liblzma5:amd64
|
||||
- libnss-mdns:amd64
|
||||
- libpcre3:amd64
|
||||
- libselinux1:amd64
|
||||
- libtinfo6:amd64
|
||||
files:
|
||||
include:
|
||||
- /lib/x86_64-linux-gnu/libLLVM-13.so.1
|
||||
@@ -124,6 +132,6 @@ AppDir:
|
||||
- usr/share/doc/*/NEWS.*
|
||||
- usr/share/doc/*/TODO.*
|
||||
AppImage:
|
||||
arch: "{{ARCHITECTURE_APPIMAGE_BUILDER}}"
|
||||
update-information: gh-releases-zsync|WerWolv|ImHex|latest|imhex-*-{{ARCHITECTURE_FILE_NAME}}.AppImage.zsync
|
||||
file_name: imhex-{{VERSION}}-{{ARCHITECTURE_FILE_NAME}}.AppImage
|
||||
arch: x86_64
|
||||
update-information: gh-releases-zsync|WerWolv|ImHex|latest|imhex-*-x86_64.AppImage.zsync
|
||||
file_name: imhex-{{VERSION}}-x86_64.AppImage
|
||||
1
dist/Arch/Dockerfile
vendored
1
dist/Arch/Dockerfile
vendored
@@ -13,7 +13,6 @@ RUN pacman -S --needed --noconfirm \
|
||||
glfw-x11 \
|
||||
file \
|
||||
mbedtls \
|
||||
fontconfig \
|
||||
freetype2 \
|
||||
curl \
|
||||
dbus \
|
||||
|
||||
4
dist/Arch/PKGBUILD
vendored
4
dist/Arch/PKGBUILD
vendored
@@ -8,7 +8,7 @@ pkgdesc="A Hex Editor for Reverse Engineers, Programmers and people who value th
|
||||
arch=("x86_64")
|
||||
url="https://github.com/WerWolv/ImHex"
|
||||
license=('GPL2')
|
||||
depends=(glfw mbedtls fontconfig freetype2 libglvnd dbus gtk3 curl fmt yara nlohmann-json zlib bzip2 xz zstd)
|
||||
depends=(glfw mbedtls freetype2 libglvnd dbus gtk3 curl fmt yara nlohmann-json zlib bzip2 xz zstd)
|
||||
makedepends=(git)
|
||||
provides=(imhex)
|
||||
conflicts=(imhex)
|
||||
@@ -26,5 +26,5 @@ package() {
|
||||
|
||||
install -d "$pkgdir/usr/share/imhex"
|
||||
cp -r "$srcdir/usr/share/imhex/"{constants,encodings,includes,magic,patterns} "$pkgdir/usr/share/imhex"
|
||||
cp -r "$srcdir/usr/share/"{applications,licenses,pixmaps,mime} "$pkgdir/usr/share"
|
||||
cp -r "$srcdir/usr/share/"{applications,licenses,pixmaps} "$pkgdir/usr/share"
|
||||
}
|
||||
|
||||
1
dist/macOS/Brewfile → dist/Brewfile
vendored
1
dist/macOS/Brewfile → dist/Brewfile
vendored
@@ -6,6 +6,7 @@ brew "freetype2"
|
||||
brew "libmagic"
|
||||
brew "pkg-config"
|
||||
brew "curl"
|
||||
brew "gcc@12"
|
||||
brew "llvm"
|
||||
brew "glfw"
|
||||
brew "ninja"
|
||||
2
dist/DEBIAN/control.in
vendored
2
dist/DEBIAN/control.in
vendored
@@ -4,7 +4,7 @@ Section: editors
|
||||
Priority: optional
|
||||
Architecture: amd64
|
||||
License: GNU GPL-2
|
||||
Depends: libfontconfig1, libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal
|
||||
Depends: libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal
|
||||
Maintainer: WerWolv <hey@werwolv.net>
|
||||
Description: ImHex Hex Editor
|
||||
A Hex Editor for Reverse Engineers, Programmers and
|
||||
|
||||
13
dist/ImHex-9999.ebuild
vendored
13
dist/ImHex-9999.ebuild
vendored
@@ -20,14 +20,13 @@ DEPEND=""
|
||||
RDEPEND="${DEPEND}
|
||||
media-libs/glfw
|
||||
sys-apps/file
|
||||
net-libs/mbedtls
|
||||
dev-libs/mbedtls
|
||||
dev-cpp/nlohmann_json
|
||||
sys-apps/dbus
|
||||
sys-apps/xdg-desktop-portal
|
||||
dbus
|
||||
xdg-desktop-portal
|
||||
sys-libs/zlib
|
||||
app-arch/bzip2
|
||||
app-arch/lzma
|
||||
app-arch/zstd
|
||||
app-arch/lz4
|
||||
app-arch/bzip2
|
||||
app-arch/lzma
|
||||
app-arch/zstd
|
||||
"
|
||||
BDEPEND="${DEPEND}"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM ubuntu:24.10 as build
|
||||
FROM ubuntu:22.04 as build
|
||||
|
||||
# Used to invalidate layer cache but not mount cache
|
||||
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493
|
||||
@@ -14,13 +14,24 @@ apt update
|
||||
# general deps
|
||||
apt install -y ccache git wget
|
||||
# appimage tools deps
|
||||
apt install -y python3-pip python3-venv python3-setuptools desktop-file-utils libgdk-pixbuf2.0-dev fuse ninja-build
|
||||
apt install -y python3-pip python3-setuptools desktop-file-utils libgdk-pixbuf2.0-dev fuse ninja-build
|
||||
apt install -y squashfs-tools zsync
|
||||
|
||||
# imhex deps
|
||||
/tmp/get_deps_debian.sh
|
||||
EOF
|
||||
|
||||
RUN --mount=type=cache,target=/cache <<EOF
|
||||
# Download appimage-builder
|
||||
set -xe
|
||||
|
||||
mkdir -p /cache/bin
|
||||
wget -nc https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O /cache/bin/appimagetool || true
|
||||
chmod +x /cache/bin/appimagetool
|
||||
|
||||
pip3 install git+https://github.com/AppImageCrafters/appimage-builder@f38699e
|
||||
EOF
|
||||
|
||||
ENV PATH="/cache/bin/:${PATH}"
|
||||
|
||||
# Copy Imhex source
|
||||
@@ -30,19 +41,13 @@ ARG LTO=ON
|
||||
ARG BUILD_TYPE=RelWithDebInfo
|
||||
ARG GIT_COMMIT_HASH
|
||||
ARG GIT_BRANCH
|
||||
ARG ARCHITECTURE_PACKAGE
|
||||
ARG ARCHITECTURE_FILE_NAME
|
||||
ARG ARCHITECTURE_APPIMAGE_BUILDER
|
||||
WORKDIR /build
|
||||
|
||||
# Ubuntu sh doesnt support string substitution
|
||||
SHELL ["bash", "-c"]
|
||||
|
||||
SHELL ["bash", "-c"] # Ubuntu sh doesnt support string substitution
|
||||
RUN <<EOF
|
||||
# Prepare ImHex build
|
||||
set -xe
|
||||
|
||||
CC=gcc-14 CXX=g++-14 cmake -G "Ninja" \
|
||||
CC=gcc-12 CXX=g++-12 cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
@@ -66,23 +71,11 @@ ccache -s
|
||||
EOF
|
||||
|
||||
RUN <<EOF
|
||||
# Download appimage-builder
|
||||
# Package ImHex as AppImage
|
||||
set -xe
|
||||
|
||||
mkdir -p /cache/bin
|
||||
wget -nc https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O /cache/bin/appimagetool || true
|
||||
chmod +x /cache/bin/appimagetool
|
||||
|
||||
python3 -m venv venv
|
||||
. venv/bin/activate
|
||||
pip3 install git+https://github.com/AppImageCrafters/appimage-builder@f38699e
|
||||
|
||||
# Package ImHex as AppImage
|
||||
export VERSION=$(cat /imhex/VERSION)
|
||||
export ARCHITECTURE_PACKAGE=${ARCHITECTURE_PACKAGE}
|
||||
export ARCHITECTURE_FILE_NAME=${ARCHITECTURE_FILE_NAME}
|
||||
export ARCHITECTURE_APPIMAGE_BUILDER=${ARCHITECTURE_APPIMAGE_BUILDER}
|
||||
appimage-builder --recipe /imhex/dist/AppImage/AppImageBuilder.yml
|
||||
appimage-builder --recipe /imhex/dist/AppImageBuilder.yml
|
||||
EOF
|
||||
|
||||
FROM scratch
|
||||
4
dist/get_deps_archlinux.sh
vendored
4
dist/get_deps_archlinux.sh
vendored
@@ -5,7 +5,6 @@ pacman -S $@ --needed \
|
||||
gcc \
|
||||
lld \
|
||||
glfw \
|
||||
fontconfig \
|
||||
file \
|
||||
mbedtls \
|
||||
freetype2 \
|
||||
@@ -19,5 +18,4 @@ pacman -S $@ --needed \
|
||||
zlib \
|
||||
bzip2 \
|
||||
xz \
|
||||
zstd \
|
||||
lz4
|
||||
zstd
|
||||
|
||||
8
dist/get_deps_debian.sh
vendored
8
dist/get_deps_debian.sh
vendored
@@ -8,8 +8,8 @@ fi
|
||||
|
||||
apt install -y \
|
||||
build-essential \
|
||||
gcc-14 \
|
||||
g++-14 \
|
||||
gcc-12 \
|
||||
g++-12 \
|
||||
lld \
|
||||
${PKGCONF:-} \
|
||||
cmake \
|
||||
@@ -18,7 +18,6 @@ apt install -y \
|
||||
libglm-dev \
|
||||
libmagic-dev \
|
||||
libmbedtls-dev \
|
||||
libfontconfig-dev \
|
||||
libfreetype-dev \
|
||||
libdbus-1-dev \
|
||||
libcurl4-gnutls-dev \
|
||||
@@ -27,5 +26,4 @@ apt install -y \
|
||||
zlib1g-dev \
|
||||
libbz2-dev \
|
||||
liblzma-dev \
|
||||
libzstd-dev \
|
||||
liblz4-dev
|
||||
libzstd-dev
|
||||
|
||||
4
dist/get_deps_fedora.sh
vendored
4
dist/get_deps_fedora.sh
vendored
@@ -4,7 +4,6 @@ dnf install -y \
|
||||
cmake \
|
||||
dbus-devel \
|
||||
file-devel \
|
||||
fontconfig-devel \
|
||||
freetype-devel \
|
||||
libcurl-devel \
|
||||
gcc-c++ \
|
||||
@@ -17,5 +16,4 @@ dnf install -y \
|
||||
libzstd-devel \
|
||||
zlib-devel \
|
||||
bzip2-devel \
|
||||
xz-devel \
|
||||
lz4-devel
|
||||
xz-devel
|
||||
5
dist/get_deps_msys2.sh
vendored
5
dist/get_deps_msys2.sh
vendored
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
pacman -S --needed --noconfirm pactoys unzip
|
||||
pacman -S --needed --noconfirm pactoys
|
||||
pacboy -S --needed --noconfirm \
|
||||
gcc:p \
|
||||
lld:p \
|
||||
@@ -17,5 +17,4 @@ pacboy -S --needed --noconfirm \
|
||||
zlib:p \
|
||||
bzip2:p \
|
||||
xz:p \
|
||||
zstd:p \
|
||||
lz4:p
|
||||
zstd:p
|
||||
|
||||
8
dist/get_deps_tumbleweed.sh
vendored
8
dist/get_deps_tumbleweed.sh
vendored
@@ -3,9 +3,8 @@
|
||||
zypper install \
|
||||
cmake \
|
||||
ninja \
|
||||
gcc14 \
|
||||
gcc14-c++ \
|
||||
fontconfig-devel \
|
||||
gcc12 \
|
||||
gcc12-c++ \
|
||||
freetype2-devel \
|
||||
libcurl-devel \
|
||||
dbus-1-devel \
|
||||
@@ -17,5 +16,4 @@ zypper install \
|
||||
libzstd-devel \
|
||||
zlib-devel \
|
||||
bzip3-devel \
|
||||
xz-devel \
|
||||
lz4-dev
|
||||
xz-devel
|
||||
|
||||
7
dist/imhex.desktop
vendored
7
dist/imhex.desktop
vendored
@@ -1,5 +1,4 @@
|
||||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Name=ImHex
|
||||
Comment=ImHex Hex Editor
|
||||
GenericName=Hex Editor
|
||||
@@ -10,9 +9,3 @@ StartupNotify=true
|
||||
Categories=Development;IDE;
|
||||
StartupWMClass=imhex
|
||||
Keywords=static-analysis;reverse-engineering;disassembler;disassembly;hacking;forensics;hex-editor;cybersecurity;security;binary-analysis;
|
||||
MimeType=application/vnd.imhex.proj;
|
||||
Actions=NewFile;
|
||||
|
||||
[Desktop Action NewFile]
|
||||
Exec=imhex --new
|
||||
Name=Create New File
|
||||
8
dist/imhex.mime.xml
vendored
8
dist/imhex.mime.xml
vendored
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
||||
<mime-type type="application/vnd.imhex.proj">
|
||||
<comment>ImHex Project</comment>
|
||||
<glob pattern="*.hexproj"/>
|
||||
</mime-type>
|
||||
</mime-info>
|
||||
16
dist/langtool.py
vendored
16
dist/langtool.py
vendored
@@ -129,19 +129,16 @@ def main():
|
||||
key in lang_data["translations"]
|
||||
and lang_data["translations"][key] != INVALID_TRANSLATION
|
||||
)
|
||||
if (
|
||||
has_translation
|
||||
and not (
|
||||
(command == "retranslate" or command == "untranslate")
|
||||
and re.compile(args.keys).fullmatch(key)
|
||||
)
|
||||
and not command == "fmtzh"
|
||||
if not has_translation and not (
|
||||
(command == "retranslate" or command == "untranslate")
|
||||
and re.compile(args.keys).fullmatch(key)
|
||||
):
|
||||
continue
|
||||
if command == "check":
|
||||
print(
|
||||
f"Error: Translation {lang_data['code']} is missing translation for key '{key}'"
|
||||
)
|
||||
exit(2)
|
||||
elif (
|
||||
command == "translate"
|
||||
or command == "retranslate"
|
||||
@@ -151,10 +148,7 @@ def main():
|
||||
continue
|
||||
reference_tranlsation = (
|
||||
" '%s'" % reference_lang_data["translations"][key]
|
||||
if (
|
||||
reference_lang_data
|
||||
and key in reference_lang_data["translations"]
|
||||
)
|
||||
if reference_lang_data
|
||||
else ""
|
||||
)
|
||||
print(
|
||||
|
||||
10
dist/macOS/arm64.Dockerfile
vendored
10
dist/macOS/arm64.Dockerfile
vendored
@@ -1,7 +1,7 @@
|
||||
# This base image is also known as "crosscompile". See arm64.crosscompile.Dockerfile
|
||||
FROM ghcr.io/itrooz/macos-crosscompile:clang19-nosdk as build
|
||||
FROM ghcr.io/itrooz/macos-crosscompile:clang17-nosdk as build
|
||||
|
||||
ENV MACOSX_DEPLOYMENT_TARGET 13.0
|
||||
ENV MACOSX_DEPLOYMENT_TARGET 12.1
|
||||
|
||||
# -- DOWNLOADING STUFF
|
||||
|
||||
@@ -118,7 +118,7 @@ if [ "$CUSTOM_GLFW" ]; then
|
||||
cd /mnt/glfw
|
||||
mkdir build
|
||||
cd build
|
||||
CC=o64-clang CXX=o64-clang++ cmake -G "Ninja" \
|
||||
CC=o64-gcc CXX=o64-g++ cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DBUILD_SHARED_LIBS=ON \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
@@ -126,7 +126,7 @@ if [ "$CUSTOM_GLFW" ]; then
|
||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
||||
-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.0 \
|
||||
-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=12.1 \
|
||||
..
|
||||
ninja -j $JOBS install
|
||||
|
||||
@@ -148,7 +148,7 @@ RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/
|
||||
`# ccache flags` \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_OBJC_COMPILER_LAUNCHER=ccache -DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
||||
`# 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.0 \
|
||||
-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=12.1 \
|
||||
`# Override compilers for code generators` \
|
||||
-DNATIVE_CMAKE_C_COMPILER=/usr/bin/clang -DNATIVE_CMAKE_CXX_COMPILER=/usr/bin/clang++ \
|
||||
`# Normal ImHex flags` \
|
||||
|
||||
15
dist/macOS/arm64.crosscompile.Dockerfile
vendored
15
dist/macOS/arm64.crosscompile.Dockerfile
vendored
@@ -1,4 +1,4 @@
|
||||
# This image is provided for reference, but a (probably more up to date) image should be available at https://github.com/iTrooz/macos-crosscompile
|
||||
# This image is is provided for reference, but a (probably more up to date) image should be available at https://github.com/iTrooz/macos-crosscompile
|
||||
FROM ubuntu:22.04
|
||||
|
||||
ENV PATH $PATH:/osxcross/target/bin
|
||||
@@ -68,6 +68,19 @@ RUN --mount=type=cache,target=/cache <<EOF
|
||||
|
||||
ccache -s
|
||||
EOF
|
||||
# Not needed, because we don't use gcc for cross-compiling anymore
|
||||
# ## Install dependencies for gcc-13
|
||||
# RUN apt install -y gcc g++ zlib1g-dev libmpc-dev libmpfr-dev libgmp-dev
|
||||
# ## Build cross-compiler gcc-13
|
||||
# RUN --mount=type=cache,target=/cache <<EOF
|
||||
# set -xe
|
||||
# ccache -zs
|
||||
|
||||
# cd /osxcross
|
||||
# UNATTENDED=1 CC=/usr/lib/ccache/gcc CXX=/usr/lib/ccache/g++ GCC_VERSION=13.2.0 ./build_gcc.sh
|
||||
|
||||
# ccache -s
|
||||
# EOF
|
||||
|
||||
ARG DELETE_SDK=1
|
||||
RUN <<EOF
|
||||
|
||||
16
dist/rpm/imhex.spec
vendored
16
dist/rpm/imhex.spec
vendored
@@ -16,7 +16,6 @@ BuildRequires: cmake
|
||||
BuildRequires: desktop-file-utils
|
||||
BuildRequires: dbus-devel
|
||||
BuildRequires: file-devel
|
||||
BuildRequires: fontconfig-devel
|
||||
BuildRequires: freetype-devel
|
||||
BuildRequires: fmt-devel
|
||||
BuildRequires: gcc-c++
|
||||
@@ -35,7 +34,7 @@ BuildRequires: zlib-devel
|
||||
BuildRequires: bzip2-devel
|
||||
BuildRequires: xz-devel
|
||||
%if 0%{?rhel}
|
||||
BuildRequires: gcc-toolset-14
|
||||
BuildRequires: gcc-toolset-12
|
||||
%endif
|
||||
|
||||
Provides: bundled(gnulib)
|
||||
@@ -71,9 +70,9 @@ rm -rf lib/third_party/{fmt,nlohmann_json,yara}
|
||||
|
||||
%build
|
||||
%if 0%{?rhel}
|
||||
. /opt/rh/gcc-toolset-14/enable
|
||||
. /opt/rh/gcc-toolset-12/enable
|
||||
%set_build_flags
|
||||
CXXFLAGS+=" -std=gnu++23"
|
||||
CXXFLAGS+=" -std=gnu++2b"
|
||||
%endif
|
||||
%cmake \
|
||||
-D CMAKE_BUILD_TYPE=Release \
|
||||
@@ -94,9 +93,9 @@ CXXFLAGS+=" -std=gnu++23"
|
||||
|
||||
%check
|
||||
%if 0%{?rhel}
|
||||
. /opt/rh/gcc-toolset-14/enable
|
||||
. /opt/rh/gcc-toolset-12/enable
|
||||
%set_build_flags
|
||||
CXXFLAGS+=" -std=gnu++23"
|
||||
CXXFLAGS+=" -std=gnu++2b"
|
||||
%endif
|
||||
|
||||
|
||||
@@ -123,11 +122,8 @@ cp -a lib/third_party/xdgpp/LICENSE %{buildroot
|
||||
%doc README.md
|
||||
%{_bindir}/imhex
|
||||
%{_bindir}/imhex-updater
|
||||
%{_datadir}/pixmaps/%{name}.svg
|
||||
%{_datadir}/pixmaps/%{name}.png
|
||||
%{_datadir}/applications/%{name}.desktop
|
||||
%{_datadir}/mime/packages/%{name}.xml
|
||||
%{_libdir}/libimhex.so*
|
||||
%{_libdir}/%{name}/
|
||||
%{_libdir}/*.hexpluglib
|
||||
/usr/lib/debug/%{_libdir}/*.debug
|
||||
%{_metainfodir}/net.werwolv.%{name}.metainfo.xml
|
||||
16
dist/web/Dockerfile
vendored
16
dist/web/Dockerfile
vendored
@@ -1,11 +1,11 @@
|
||||
FROM emscripten/emsdk:3.1.51 AS build
|
||||
FROM emscripten/emsdk:3.1.51 as build
|
||||
|
||||
# Used to invalidate layer cache but not mount cache
|
||||
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493
|
||||
ARG UNIQUEKEY 1
|
||||
|
||||
RUN apt update
|
||||
RUN apt install -y git ccache autoconf automake libtool cmake pkg-config ninja-build
|
||||
RUN apt install -y git ccache autoconf automake libtool cmake pkg-config
|
||||
|
||||
RUN <<EOF
|
||||
# Install vcpkg
|
||||
@@ -27,7 +27,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||
' >> /emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake
|
||||
EOF
|
||||
|
||||
ENV VCPKG_DEFAULT_BINARY_CACHE=/cache/vcpkg
|
||||
ENV VCPKG_DEFAULT_BINARY_CACHE /cache/vcpkg
|
||||
RUN --mount=type=cache,target=/cache <<EOF
|
||||
# Install dependencies with vcpkg
|
||||
set -xe
|
||||
@@ -45,7 +45,7 @@ EOF
|
||||
|
||||
# Build ImHex
|
||||
ARG JOBS=4
|
||||
ENV CCACHE_DIR=/cache/ccache
|
||||
ENV CCACHE_DIR /cache/ccache
|
||||
|
||||
RUN mkdir /build
|
||||
WORKDIR /build
|
||||
@@ -56,7 +56,6 @@ set -xe
|
||||
ccache -zs
|
||||
|
||||
cmake /imhex \
|
||||
-G "Ninja" \
|
||||
-DIMHEX_OFFLINE_BUILD=ON \
|
||||
-DIMHEX_STATIC_LINK_PLUGINS=ON \
|
||||
-DIMHEX_EXCLUDE_PLUGINS="script_loader" \
|
||||
@@ -67,10 +66,9 @@ cmake /imhex
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake \
|
||||
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
|
||||
-DLIBROMFS_COMPRESS_RESOURCES=OFF \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
ninja -j $JOBS
|
||||
make -j $JOBS
|
||||
|
||||
cp /imhex/dist/web/source/* /build
|
||||
ccache -s
|
||||
@@ -80,7 +78,7 @@ EOF
|
||||
# See https://stackoverflow.com/questions/41701849/cannot-modify-accept-encoding-with-fetch https://github.com/AnthumChris/fetch-progress-indicators/issues/13
|
||||
RUN du -b /build/imhex.wasm | cut -f1 > imhex.wasm.size
|
||||
|
||||
FROM scratch AS raw
|
||||
FROM scratch as raw
|
||||
COPY --from=build [ \
|
||||
# ImHex \
|
||||
"/build/imhex.wasm", \
|
||||
@@ -94,7 +92,7 @@ COPY --from=build [ \
|
||||
"/build/wasm-config.js", \
|
||||
"/build/enable-threads.js", \
|
||||
"/build/favicon.ico", \
|
||||
"/build/icon.svg", \
|
||||
"/build/icon.png", \
|
||||
"/build/manifest.json", \
|
||||
"/build/robots.txt", \
|
||||
"/build/sitemap.xml", \
|
||||
|
||||
BIN
dist/web/source/favicon.ico
vendored
BIN
dist/web/source/favicon.ico
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 122 KiB |
BIN
dist/web/source/icon.png
vendored
Normal file
BIN
dist/web/source/icon.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 157 KiB |
11
dist/web/source/icon.svg
vendored
11
dist/web/source/icon.svg
vendored
@@ -1,11 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" version="1">
|
||||
<rect style="opacity:0.2" width="55" height="10" x="5" y="-60" rx="1.41" transform="rotate(90)"/>
|
||||
<rect style="fill:#2b50a1" width="55" height="10" x="4" y="-60" rx="1.41" transform="rotate(90)"/>
|
||||
<rect style="fill:#2b50a1" width="55" height="10" x="4" y="-14" rx="1.41" transform="rotate(90)"/>
|
||||
<rect style="fill:#2b50a1" width="55" height="10" x="4" y="-33" rx="1.41" transform="rotate(90)"/>
|
||||
<path style="opacity:0.2" d="M 5.3808594,5 C 4.6158118,5 4,5.6158118 4,6.3808594 V 13.619141 C 4,14.384188 4.6158118,15 5.3808594,15 H 31.619141 C 32.384188,15 33,14.384188 33,13.619141 V 6.3808594 C 33,5.6158118 32.384188,5 31.619141,5 Z M 40.400391,5 C 39.624791,5 39,5.6247906 39,6.4003906 V 13.599609 C 39,14.375209 39.624791,15 40.400391,15 H 58.599609 C 59.375209,15 60,14.375209 60,13.599609 V 6.4003906 C 60,5.6247906 59.375209,5 58.599609,5 Z M 5.3808594,50 C 4.6158118,50 4,50.615812 4,51.380859 v 7.238282 C 4,59.384188 4.6158118,60 5.3808594,60 H 31.619141 C 32.384188,60 33,59.384188 33,58.619141 V 51.380859 C 33,50.615812 32.384188,50 31.619141,50 Z"/>
|
||||
<rect style="fill:#3a6be0" width="29" height="10" x="4" y="4" rx="1.381"/>
|
||||
<rect style="fill:#3a6be0" width="21" height="10" x="39" y="4" rx="1.4"/>
|
||||
<rect style="fill:#3a6be0" width="29" height="10" x="4" y="49" rx="1.381"/>
|
||||
<path style="fill:#ffffff;opacity:0.1" d="M 5.3808594 4 C 4.6158118 4 4 4.6158118 4 5.3808594 L 4 6.3808594 C 4 5.6158118 4.6158118 5 5.3808594 5 L 31.619141 5 C 32.384188 5 33 5.6158118 33 6.3808594 L 33 5.3808594 C 33 4.6158118 32.384188 4 31.619141 4 L 5.3808594 4 z M 40.400391 4 C 39.624791 4 39 4.6247906 39 5.4003906 L 39 6.4003906 C 39 5.6247906 39.624791 5 40.400391 5 L 58.599609 5 C 59.375209 5 60 5.6247906 60 6.4003906 L 60 5.4003906 C 60 4.6247906 59.375209 4 58.599609 4 L 40.400391 4 z M 5.3808594 49 C 4.6158118 49 4 49.615812 4 50.380859 L 4 51.380859 C 4 50.615812 4.6158118 50 5.3808594 50 L 31.619141 50 C 32.384188 50 33 50.615812 33 51.380859 L 33 50.380859 C 33 49.615812 32.384188 49 31.619141 49 L 5.3808594 49 z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
4
dist/web/source/index.html
vendored
4
dist/web/source/index.html
vendored
@@ -11,7 +11,7 @@
|
||||
<meta name="title" content="ImHex">
|
||||
<meta name="description" content="Free and extremely powerful Online Hex Editor for your Web Browser. ImHex is a free and open source Hex Editor for Reverse Engineers and Developers and Data Analysts.">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<link rel="apple-touch-icon" href="icon.svg">
|
||||
<link rel="apple-touch-icon" href="icon.png">
|
||||
|
||||
<!-- Open Graph / Facebook -->
|
||||
<meta property="og:type" content="website">
|
||||
@@ -38,7 +38,7 @@
|
||||
"founder": "WerWolv",
|
||||
"slogan": "A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.",
|
||||
"url": "https://imhex.werwolv.net",
|
||||
"logo": "https://imhex.werwolv.net/assets/logos/logo.svg"
|
||||
"logo": "https://imhex.werwolv.net/assets/logos/logo.png"
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
4
dist/web/source/manifest.json
vendored
4
dist/web/source/manifest.json
vendored
@@ -10,8 +10,8 @@
|
||||
],
|
||||
"icons": [
|
||||
{
|
||||
"src": "icon.svg",
|
||||
"type": "image/svg",
|
||||
"src": "icon.png",
|
||||
"type": "image/png",
|
||||
"sizes": "640x640"
|
||||
}
|
||||
],
|
||||
|
||||
9
dist/web/source/wasm-config.js
vendored
9
dist/web/source/wasm-config.js
vendored
@@ -261,11 +261,4 @@ function js_resizeCanvas() {
|
||||
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
|
||||
document.addEventListener('keydown', e => {
|
||||
if (e.ctrlKey) {
|
||||
if (e.which == 83) e.preventDefault();
|
||||
}
|
||||
})
|
||||
}
|
||||
1
lib/external/disassembler
vendored
1
lib/external/disassembler
vendored
Submodule lib/external/disassembler deleted from 172c61ec3f
2
lib/external/libromfs
vendored
2
lib/external/libromfs
vendored
Submodule lib/external/libromfs updated: 60ba28a53b...03adcfdde0
2
lib/external/libwolv
vendored
2
lib/external/libwolv
vendored
Submodule lib/external/libwolv updated: 323ad9e4f0...0e3ba3aa6f
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
Submodule lib/external/pattern_language updated: 947b99cbe7...c7bca89b1a
@@ -38,7 +38,6 @@ set(LIBIMHEX_SOURCES
|
||||
source/helpers/debugging.cpp
|
||||
source/helpers/default_paths.cpp
|
||||
source/helpers/imgui_hooks.cpp
|
||||
source/helpers/semantic_version.cpp
|
||||
|
||||
source/test/tests.cpp
|
||||
|
||||
@@ -50,7 +49,6 @@ set(LIBIMHEX_SOURCES
|
||||
source/ui/view.cpp
|
||||
source/ui/popup.cpp
|
||||
source/ui/toast.cpp
|
||||
source/ui/banner.cpp
|
||||
|
||||
source/subcommands/subcommands.cpp
|
||||
)
|
||||
@@ -135,14 +133,13 @@ if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
|
||||
if (WIN32)
|
||||
set_target_properties(libimhex PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
|
||||
target_link_options(libimhex PRIVATE -Wl,--export-all-symbols)
|
||||
target_link_libraries(libimhex PRIVATE Netapi32.lib)
|
||||
elseif (APPLE)
|
||||
find_library(FOUNDATION NAMES Foundation)
|
||||
target_link_libraries(libimhex PUBLIC ${FOUNDATION})
|
||||
endif ()
|
||||
|
||||
target_link_libraries(libimhex PRIVATE microtar libwolv ${NFD_LIBRARIES} magic dl)
|
||||
target_link_libraries(libimhex PUBLIC libpl ${IMGUI_LIBRARIES} ${JTHREAD_LIBRARIES})
|
||||
target_link_libraries(libimhex PRIVATE microtar libwolv ${NFD_LIBRARIES} magic dl ${JTHREAD_LIBRARIES})
|
||||
target_link_libraries(libimhex PUBLIC libpl ${IMGUI_LIBRARIES})
|
||||
|
||||
precompileHeaders(libimhex "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
endif()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/helpers/types.hpp>
|
||||
#include <hex/helpers/intrinsics.hpp>
|
||||
@@ -295,7 +295,6 @@ namespace hex {
|
||||
};
|
||||
|
||||
class AchievementManager {
|
||||
static bool s_initialized;
|
||||
public:
|
||||
AchievementManager() = delete;
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/api/shortcut_manager.hpp>
|
||||
#include <hex/helpers/concepts.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <span>
|
||||
#include <string>
|
||||
@@ -20,11 +20,11 @@ using ImGuiDataType = int;
|
||||
using ImGuiInputTextFlags = int;
|
||||
struct ImColor;
|
||||
enum ImGuiCustomCol : int;
|
||||
typedef int ImGuiColorEditFlags;
|
||||
|
||||
namespace hex {
|
||||
|
||||
class View;
|
||||
class Shortcut;
|
||||
class Task;
|
||||
|
||||
namespace dp {
|
||||
@@ -44,6 +44,7 @@ namespace hex {
|
||||
plugins when needed.
|
||||
*/
|
||||
namespace ContentRegistry {
|
||||
|
||||
/* Settings Registry. Allows adding of new entries into the ImHex preferences window. */
|
||||
namespace Settings {
|
||||
|
||||
@@ -177,7 +178,7 @@ namespace hex {
|
||||
|
||||
class SliderDataSize : public Widget {
|
||||
public:
|
||||
SliderDataSize(u64 defaultValue, u64 min, u64 max, u64 stepSize) : m_value(defaultValue), m_min(min), m_max(max), m_stepSize(stepSize) { }
|
||||
SliderDataSize(u64 defaultValue, u64 min, u64 max) : m_value(defaultValue), m_min(min), m_max(max) { }
|
||||
bool draw(const std::string &name) override;
|
||||
|
||||
void load(const nlohmann::json &data) override;
|
||||
@@ -188,12 +189,11 @@ namespace hex {
|
||||
protected:
|
||||
u64 m_value;
|
||||
u64 m_min, m_max;
|
||||
u64 m_stepSize;
|
||||
};
|
||||
|
||||
class ColorPicker : public Widget {
|
||||
public:
|
||||
explicit ColorPicker(ImColor defaultColor, ImGuiColorEditFlags flags = 0);
|
||||
explicit ColorPicker(ImColor defaultColor);
|
||||
|
||||
bool draw(const std::string &name) override;
|
||||
|
||||
@@ -203,14 +203,12 @@ namespace hex {
|
||||
[[nodiscard]] ImColor getColor() const;
|
||||
|
||||
protected:
|
||||
std::array<float, 4> m_value = {}, m_defaultValue = {};
|
||||
ImGuiColorEditFlags m_flags;
|
||||
std::array<float, 4> m_value{};
|
||||
};
|
||||
|
||||
class DropDown : public Widget {
|
||||
public:
|
||||
explicit DropDown(const std::vector<std::string> &items, const std::vector<nlohmann::json> &settingsValues, const nlohmann::json &defaultItem) : m_items(items.begin(), items.end()), m_settingsValues(settingsValues), m_defaultItem(defaultItem) { }
|
||||
explicit DropDown(const std::vector<UnlocalizedString> &items, const std::vector<nlohmann::json> &settingsValues, const nlohmann::json &defaultItem) : m_items(items), m_settingsValues(settingsValues), m_defaultItem(defaultItem) { }
|
||||
explicit DropDown(const std::vector<std::string> &items, const std::vector<nlohmann::json> &settingsValues, const nlohmann::json &defaultItem) : m_items(items), m_settingsValues(settingsValues), m_defaultItem(defaultItem) { }
|
||||
|
||||
bool draw(const std::string &name) override;
|
||||
|
||||
@@ -221,7 +219,7 @@ namespace hex {
|
||||
const nlohmann::json& getValue() const;
|
||||
|
||||
protected:
|
||||
std::vector<UnlocalizedString> m_items;
|
||||
std::vector<std::string> m_items;
|
||||
std::vector<nlohmann::json> m_settingsValues;
|
||||
nlohmann::json m_defaultItem;
|
||||
|
||||
@@ -383,7 +381,7 @@ namespace hex {
|
||||
};
|
||||
|
||||
using DisplayCallback = std::function<std::string(std::string)>;
|
||||
using ExecuteCallback = std::function<std::optional<std::string>(std::string)>;
|
||||
using ExecuteCallback = std::function<void(std::string)>;
|
||||
using QueryCallback = std::function<std::vector<QueryResult>(std::string)>;
|
||||
|
||||
struct Entry {
|
||||
@@ -419,7 +417,7 @@ namespace hex {
|
||||
const std::string &command,
|
||||
const UnlocalizedString &unlocalizedDescription,
|
||||
const impl::DisplayCallback &displayCallback,
|
||||
const impl::ExecuteCallback &executeCallback = [](auto) { return std::nullopt; });
|
||||
const impl::ExecuteCallback &executeCallback = [](auto) {});
|
||||
|
||||
/**
|
||||
* @brief Adds a new command handler to the command palette
|
||||
@@ -440,7 +438,7 @@ namespace hex {
|
||||
|
||||
namespace impl {
|
||||
|
||||
using VisualizerFunctionCallback = std::function<void(pl::ptrn::Pattern&, bool, std::span<const pl::core::Token::Literal>)>;
|
||||
using VisualizerFunctionCallback = std::function<void(pl::ptrn::Pattern&, pl::ptrn::IIterable&, bool, std::span<const pl::core::Token::Literal>)>;
|
||||
|
||||
struct FunctionDefinition {
|
||||
pl::api::Namespace ns;
|
||||
@@ -452,14 +450,6 @@ namespace hex {
|
||||
bool dangerous;
|
||||
};
|
||||
|
||||
struct TypeDefinition {
|
||||
pl::api::Namespace ns;
|
||||
std::string name;
|
||||
|
||||
pl::api::FunctionParameterCount parameterCount;
|
||||
pl::api::TypeCallback callback;
|
||||
};
|
||||
|
||||
struct Visualizer {
|
||||
pl::api::FunctionParameterCount parameterCount;
|
||||
VisualizerFunctionCallback callback;
|
||||
@@ -469,7 +459,6 @@ namespace hex {
|
||||
const std::map<std::string, Visualizer>& getInlineVisualizers();
|
||||
const std::map<std::string, pl::api::PragmaHandler>& getPragmas();
|
||||
const std::vector<FunctionDefinition>& getFunctions();
|
||||
const std::vector<TypeDefinition>& getTypes();
|
||||
|
||||
}
|
||||
|
||||
@@ -528,20 +517,6 @@ namespace hex {
|
||||
const pl::api::FunctionCallback &func
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Adds a new type to the pattern language
|
||||
* @param ns The namespace of the type
|
||||
* @param name The name of the type
|
||||
* @param parameterCount The amount of non-type template parameters the type takes
|
||||
* @param func The type callback
|
||||
*/
|
||||
void addType(
|
||||
const pl::api::Namespace &ns,
|
||||
const std::string &name,
|
||||
pl::api::FunctionParameterCount parameterCount,
|
||||
const pl::api::TypeCallback &func
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Adds a new visualizer to the pattern language
|
||||
* @note Visualizers are extensions to the [[hex::visualize]] attribute, used to visualize data
|
||||
@@ -626,7 +601,8 @@ namespace hex {
|
||||
/* Data Inspector Registry. Allows adding of new types to the data inspector */
|
||||
namespace DataInspector {
|
||||
|
||||
enum class NumberDisplayStyle : u8 {
|
||||
enum class NumberDisplayStyle
|
||||
{
|
||||
Decimal,
|
||||
Hexadecimal,
|
||||
Octal
|
||||
@@ -680,13 +656,6 @@ namespace hex {
|
||||
std::optional<impl::EditingFunction> editingFunction = std::nullopt
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Allows adding new menu items to data inspector row context menus. Call this function inside the
|
||||
* draw function of the data inspector row definition.
|
||||
* @param function Callback that will draw menu items
|
||||
*/
|
||||
void drawMenuItems(const std::function<void()> &function);
|
||||
|
||||
}
|
||||
|
||||
/* Data Processor Node Registry. Allows adding new processor nodes to be used in the data processor */
|
||||
@@ -779,7 +748,7 @@ namespace hex {
|
||||
struct MenuItem {
|
||||
std::vector<UnlocalizedString> unlocalizedNames;
|
||||
Icon icon;
|
||||
Shortcut shortcut;
|
||||
std::unique_ptr<Shortcut> shortcut;
|
||||
View *view;
|
||||
MenuCallback callback;
|
||||
EnabledCallback enabledCallback;
|
||||
@@ -1017,7 +986,7 @@ namespace hex {
|
||||
|
||||
namespace impl {
|
||||
|
||||
using Callback = std::function<std::string(prv::Provider *provider, u64 address, size_t size, bool preview)>;
|
||||
using Callback = std::function<std::string(prv::Provider *provider, u64 address, size_t size)>;
|
||||
struct ExportMenuEntry {
|
||||
UnlocalizedString unlocalizedName;
|
||||
Callback callback;
|
||||
@@ -1025,7 +994,7 @@ namespace hex {
|
||||
|
||||
struct FindOccurrence {
|
||||
Region region;
|
||||
enum class DecodeType { ASCII, UTF8, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
|
||||
enum class DecodeType { ASCII, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
|
||||
std::endian endian = std::endian::native;
|
||||
bool selected;
|
||||
};
|
||||
@@ -1304,7 +1273,7 @@ namespace hex {
|
||||
void stopServices();
|
||||
}
|
||||
|
||||
void registerService(const UnlocalizedString &unlocalizedString, const impl::Callback &callback);
|
||||
void registerService(const UnlocalizedString &unlocalizedName, const impl::Callback &callback);
|
||||
}
|
||||
|
||||
/* Network Communication Interface Registry. Allows adding new communication interface endpoints */
|
||||
@@ -1363,7 +1332,6 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
/* Data Information Registry. Allows adding new analyzers to the data information view */
|
||||
namespace DataInformation {
|
||||
|
||||
class InformationSection {
|
||||
@@ -1430,54 +1398,6 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
/* Disassembler Registry. Allows adding new disassembler architectures */
|
||||
namespace Disassembler {
|
||||
|
||||
struct Instruction {
|
||||
u64 address;
|
||||
u64 offset;
|
||||
size_t size;
|
||||
std::string bytes;
|
||||
std::string mnemonic;
|
||||
std::string operators;
|
||||
};
|
||||
|
||||
class Architecture {
|
||||
public:
|
||||
explicit Architecture(std::string name) : m_name(std::move(name)) {}
|
||||
virtual ~Architecture() = default;
|
||||
|
||||
virtual bool start() = 0;
|
||||
virtual void end() = 0;
|
||||
|
||||
virtual std::optional<Instruction> disassemble(u64 imageBaseAddress, u64 instructionLoadAddress, u64 instructionDataAddress, std::span<const u8> code) = 0;
|
||||
virtual void drawSettings() = 0;
|
||||
|
||||
[[nodiscard]] const std::string& getName() const { return m_name; }
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
using CreatorFunction = std::function<std::unique_ptr<Architecture>()>;
|
||||
|
||||
void addArchitectureCreator(CreatorFunction function);
|
||||
|
||||
const std::map<std::string, CreatorFunction>& getArchitectures();
|
||||
|
||||
}
|
||||
|
||||
template<std::derived_from<Architecture> T>
|
||||
void add(auto && ...args) {
|
||||
impl::addArchitectureCreator([...args = std::move(args)] {
|
||||
return std::make_unique<T>(args...);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,15 @@
|
||||
#define EVENT_DEF_NO_LOG(event_name, ...) EVENT_DEF_IMPL(event_name, #event_name, false, __VA_ARGS__)
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
struct GLFWwindow;
|
||||
namespace hex {
|
||||
class Achievement;
|
||||
class View;
|
||||
}
|
||||
|
||||
namespace pl::ptrn { class Pattern; }
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace impl {
|
||||
@@ -90,8 +99,7 @@ namespace hex {
|
||||
|
||||
/**
|
||||
* @brief The EventManager allows subscribing to and posting events to different parts of the program.
|
||||
* To create a new event, use the EVENT_DEF macro. This will create a new event type with the given name and parameters.
|
||||
* Events should be created in an `events_*.hpp` category file under the `events` folder, and never directly here.
|
||||
* To create a new event, use the EVENT_DEF macro. This will create a new event type with the given name and parameters
|
||||
*/
|
||||
class EventManager {
|
||||
public:
|
||||
@@ -121,9 +129,15 @@ namespace hex {
|
||||
static void subscribe(void *token, typename E::Callback function) {
|
||||
std::scoped_lock lock(getEventMutex());
|
||||
|
||||
if (isAlreadyRegistered(token, E::Id)) {
|
||||
log::fatal("The token '{}' has already registered the same event ('{}')", token, wolv::type::getTypeName<E>());
|
||||
return;
|
||||
if (getTokenStore().contains(token)) {
|
||||
auto&& [begin, end] = getTokenStore().equal_range(token);
|
||||
const auto eventRegistered = std::any_of(begin, end, [&](auto &item) {
|
||||
return item.second->first == E::Id;
|
||||
});
|
||||
if (eventRegistered) {
|
||||
log::fatal("The token '{}' has already registered the same event ('{}')", token, wolv::type::getTypeName<E>());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
getTokenStore().insert({ token, subscribe<E>(function) });
|
||||
@@ -148,7 +162,16 @@ namespace hex {
|
||||
static void unsubscribe(void *token) noexcept {
|
||||
std::scoped_lock lock(getEventMutex());
|
||||
|
||||
unsubscribe(token, E::Id);
|
||||
auto &tokenStore = getTokenStore();
|
||||
auto iter = std::find_if(tokenStore.begin(), tokenStore.end(), [&](auto &item) {
|
||||
return item.first == token && item.second->first == E::Id;
|
||||
});
|
||||
|
||||
if (iter != tokenStore.end()) {
|
||||
getEvents().erase(iter->second);
|
||||
tokenStore.erase(iter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,9 +209,118 @@ namespace hex {
|
||||
static std::multimap<void *, EventList::iterator>& getTokenStore();
|
||||
static EventList& getEvents();
|
||||
static std::recursive_mutex& getEventMutex();
|
||||
|
||||
static bool isAlreadyRegistered(void *token, impl::EventId id);
|
||||
static void unsubscribe(void *token, impl::EventId id);
|
||||
};
|
||||
|
||||
/* Default Events */
|
||||
|
||||
/**
|
||||
* @brief Called when Imhex finished startup, and will enter the main window rendering loop
|
||||
*/
|
||||
EVENT_DEF(EventImHexStartupFinished);
|
||||
|
||||
EVENT_DEF(EventFileLoaded, std::fs::path);
|
||||
EVENT_DEF(EventDataChanged, prv::Provider *);
|
||||
EVENT_DEF(EventHighlightingChanged);
|
||||
EVENT_DEF(EventWindowClosing, GLFWwindow *);
|
||||
EVENT_DEF(EventRegionSelected, ImHexApi::HexEditor::ProviderRegion);
|
||||
EVENT_DEF(EventAbnormalTermination, int);
|
||||
EVENT_DEF(EventThemeChanged);
|
||||
EVENT_DEF(EventOSThemeChanged);
|
||||
EVENT_DEF(EventWindowFocused, bool);
|
||||
|
||||
/**
|
||||
* @brief Called when the provider is created.
|
||||
* This event is responsible for (optionally) initializing the provider and calling EventProviderOpened
|
||||
* (although the event can also be called manually without problem)
|
||||
*/
|
||||
EVENT_DEF(EventProviderCreated, prv::Provider *);
|
||||
EVENT_DEF(EventProviderChanged, prv::Provider *, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Called as a continuation of EventProviderCreated
|
||||
* this event is normally called immediately after EventProviderCreated successfully initialized the provider.
|
||||
* If no initialization (Provider::skipLoadInterface() has been set), this event should be called manually
|
||||
* If skipLoadInterface failed, this event is not called
|
||||
*
|
||||
* @note this is not related to Provider::open()
|
||||
*/
|
||||
EVENT_DEF(EventProviderOpened, prv::Provider *);
|
||||
EVENT_DEF(EventProviderClosing, prv::Provider *, bool *);
|
||||
EVENT_DEF(EventProviderClosed, prv::Provider *);
|
||||
EVENT_DEF(EventProviderDeleted, prv::Provider *);
|
||||
EVENT_DEF(EventProviderSaved, prv::Provider *);
|
||||
EVENT_DEF(EventWindowInitialized);
|
||||
EVENT_DEF(EventWindowDeinitializing, GLFWwindow *);
|
||||
EVENT_DEF(EventBookmarkCreated, ImHexApi::Bookmarks::Entry&);
|
||||
EVENT_DEF(EventPatchCreated, u64, u8, u8);
|
||||
EVENT_DEF(EventPatternEvaluating);
|
||||
EVENT_DEF(EventPatternExecuted, const std::string&);
|
||||
EVENT_DEF(EventPatternEditorChanged, const std::string&);
|
||||
EVENT_DEF(EventStoreContentDownloaded, const std::fs::path&);
|
||||
EVENT_DEF(EventStoreContentRemoved, const std::fs::path&);
|
||||
EVENT_DEF(EventImHexClosing);
|
||||
EVENT_DEF(EventAchievementUnlocked, const Achievement&);
|
||||
EVENT_DEF(EventSearchBoxClicked, u32);
|
||||
EVENT_DEF(EventViewOpened, View*);
|
||||
EVENT_DEF(EventFirstLaunch);
|
||||
|
||||
EVENT_DEF(EventFileDragged, bool);
|
||||
EVENT_DEF(EventFileDropped, std::fs::path);
|
||||
|
||||
EVENT_DEF(EventProviderDataModified, prv::Provider *, u64, u64, const u8*);
|
||||
EVENT_DEF(EventProviderDataInserted, prv::Provider *, u64, u64);
|
||||
EVENT_DEF(EventProviderDataRemoved, prv::Provider *, u64, u64);
|
||||
EVENT_DEF(EventProviderDirtied, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Called when a project has been loaded
|
||||
*/
|
||||
EVENT_DEF(EventProjectOpened);
|
||||
|
||||
EVENT_DEF_NO_LOG(EventFrameBegin);
|
||||
EVENT_DEF_NO_LOG(EventFrameEnd);
|
||||
EVENT_DEF_NO_LOG(EventSetTaskBarIconState, u32, u32, u32);
|
||||
EVENT_DEF_NO_LOG(EventImGuiElementRendered, ImGuiID, const std::array<float, 4>&);
|
||||
|
||||
EVENT_DEF(RequestAddInitTask, std::string, bool, std::function<bool()>);
|
||||
EVENT_DEF(RequestAddExitTask, std::string, std::function<bool()>);
|
||||
EVENT_DEF(RequestOpenWindow, std::string);
|
||||
EVENT_DEF(RequestHexEditorSelectionChange, Region);
|
||||
EVENT_DEF(RequestPatternEditorSelectionChange, u32, u32);
|
||||
EVENT_DEF(RequestJumpToPattern, const pl::ptrn::Pattern*);
|
||||
EVENT_DEF(RequestAddBookmark, Region, std::string, std::string, color_t, u64*);
|
||||
EVENT_DEF(RequestRemoveBookmark, u64);
|
||||
EVENT_DEF(RequestSetPatternLanguageCode, std::string);
|
||||
EVENT_DEF(RequestRunPatternCode);
|
||||
EVENT_DEF(RequestLoadPatternLanguageFile, std::fs::path);
|
||||
EVENT_DEF(RequestSavePatternLanguageFile, std::fs::path);
|
||||
EVENT_DEF(RequestUpdateWindowTitle);
|
||||
EVENT_DEF(RequestCloseImHex, bool);
|
||||
EVENT_DEF(RequestRestartImHex);
|
||||
EVENT_DEF(RequestOpenFile, std::fs::path);
|
||||
EVENT_DEF(RequestChangeTheme, std::string);
|
||||
EVENT_DEF(RequestOpenPopup, std::string);
|
||||
EVENT_DEF(RequestAddVirtualFile, std::fs::path, std::vector<u8>, Region);
|
||||
|
||||
/**
|
||||
* @brief Creates a provider from it's unlocalized name, and add it to the provider list
|
||||
*/
|
||||
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, hex::prv::Provider **);
|
||||
EVENT_DEF(RequestInitThemeHandlers);
|
||||
|
||||
/**
|
||||
* @brief Send an event to the main Imhex instance
|
||||
*/
|
||||
EVENT_DEF(SendMessageToMainInstance, const std::string, const std::vector<u8>&);
|
||||
|
||||
/**
|
||||
* Move the data from all PerProvider instances from one provider to another.
|
||||
* The 'from' provider should not have any per provider data after this, and should be immediately deleted
|
||||
*/
|
||||
EVENT_DEF(MovePerProviderData, prv::Provider *, prv::Provider *);
|
||||
|
||||
/**
|
||||
* Called when ImHex managed to catch an error in a general try/catch to prevent/recover from a crash
|
||||
*/
|
||||
EVENT_DEF(EventCrashRecovered, const std::exception &);
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Forward declarations */
|
||||
struct GLFWwindow;
|
||||
namespace hex { class View; }
|
||||
|
||||
/* GUI events definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Signals a newly opened window
|
||||
*
|
||||
* This event is sent when the window has just been opened and docked by the Window manager.
|
||||
*
|
||||
* FIXME: In the event that a newly created window is already docked, this will not be sent.
|
||||
*
|
||||
* FIXME: This is currently only used for the introduction tutorial.
|
||||
* If the event's only purpose is this, maybe rename it?
|
||||
*
|
||||
* @param view the new view reference
|
||||
*/
|
||||
EVENT_DEF(EventViewOpened, View*);
|
||||
|
||||
/**
|
||||
* @brief Signals a change in the DPI scale.
|
||||
*
|
||||
* This event is called once at startup to signal native scale definition (by passing the same value twice).
|
||||
* On Windows OS, this event can also be posted if the window DPI has been changed.
|
||||
*
|
||||
* @param oldScale the old scale
|
||||
* @param newScale the current scale that's now in use
|
||||
*/
|
||||
EVENT_DEF(EventDPIChanged, float, float);
|
||||
|
||||
/**
|
||||
* @brief Signals the focus of the ImHex main window.
|
||||
*
|
||||
* This is directly tied as a GLFW window focus callback, and will be called accordingly when GLFW detects
|
||||
* a change in focus.
|
||||
*
|
||||
* @param isFocused true if the window is focused
|
||||
*/
|
||||
EVENT_DEF(EventWindowFocused, bool);
|
||||
|
||||
/**
|
||||
* @brief Signals a window being closed.
|
||||
*
|
||||
* Allows reactive clean up of running tasks, and prevents ImHex from closing
|
||||
* by displaying an exit confirmation popup.
|
||||
*
|
||||
* @param window The window reference
|
||||
*/
|
||||
EVENT_DEF(EventWindowClosing, GLFWwindow*);
|
||||
|
||||
/**
|
||||
* @brief Informs that the main window is initialized
|
||||
*
|
||||
* On Windows OS, it is used to initialize system theme, if ImHex's theme is following it.
|
||||
*
|
||||
* FIXME: Change event name to reflect Theme detection, if it's only used for that purpose?
|
||||
*/
|
||||
EVENT_DEF(EventWindowInitialized);
|
||||
|
||||
/**
|
||||
* @brief Informs that the main window is deinitializing
|
||||
*
|
||||
* Allows for lifecycle cleanup before ImHex shutdown.
|
||||
*
|
||||
* @param window The window reference
|
||||
*/
|
||||
EVENT_DEF(EventWindowDeinitializing, GLFWwindow*);
|
||||
|
||||
/**
|
||||
* @brief Signals a theme change in the host OS
|
||||
*
|
||||
* Allows ImHex to react to OS theme changes dynamically during execution.
|
||||
*/
|
||||
EVENT_DEF(EventOSThemeChanged);
|
||||
|
||||
}
|
||||
|
||||
/* silent (no-logging) GUI events definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Signals the start of a new ImGui frame
|
||||
*/
|
||||
EVENT_DEF_NO_LOG(EventFrameBegin);
|
||||
|
||||
/**
|
||||
* @brief Signals the end of an ImGui frame
|
||||
*/
|
||||
EVENT_DEF_NO_LOG(EventFrameEnd);
|
||||
|
||||
/**
|
||||
* @brief Windows OS: Sets the taskbar icon state
|
||||
*
|
||||
* This event is used on Windows OS to display progress through the taskbar icon (the famous "green loading bar"
|
||||
* in the taskbar).
|
||||
*
|
||||
* @param progressState the progress state (converted from the TaskProgressState enum)
|
||||
* @param progressType the type of progress (converted from the TaskProgressType enum)
|
||||
* @param percentage actual progress percentage (expected from 0 to 100)
|
||||
*
|
||||
* @see hex::ImHexApi::System::TaskProgressState
|
||||
* @see hex::ImHexApi::System::TaskProgressType
|
||||
*/
|
||||
EVENT_DEF_NO_LOG(EventSetTaskBarIconState, u32, u32, u32);
|
||||
|
||||
/**
|
||||
* @brief Informs of an ImGui element being rendered
|
||||
*
|
||||
* @param elementId the element's ID
|
||||
* @param boundingBox the bounding box (composed of 4 floats)
|
||||
*/
|
||||
EVENT_DEF_NO_LOG(EventImGuiElementRendered, ImGuiID, const std::array<float, 4>&);
|
||||
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/helpers/patches.hpp>
|
||||
|
||||
/* Forward declarations */
|
||||
namespace hex { class Achievement; }
|
||||
|
||||
/* Interaction events definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Signals a file was loaded
|
||||
*
|
||||
* FIXME: this event is unused and should be scrapped.
|
||||
*
|
||||
* @param path the loaded file's path
|
||||
*/
|
||||
EVENT_DEF(EventFileLoaded, std::fs::path);
|
||||
|
||||
/**
|
||||
* @brief Signals a change in the current data
|
||||
*
|
||||
* Enables provider reaction to data change, especially the data inspector.
|
||||
*
|
||||
* This is caused by the following:
|
||||
* - an explicit provider reload, requested by the user (Ctrl+R)
|
||||
* - any user action that results in the creation of an "undo" stack action (generally a data modification)
|
||||
*
|
||||
* @param provider the Provider subject to the data change
|
||||
*/
|
||||
EVENT_DEF(EventDataChanged, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals a change in highlighting
|
||||
*
|
||||
* The event's only purpose is for the Hex editor to clear highlights when receiving this event.
|
||||
*/
|
||||
EVENT_DEF(EventHighlightingChanged);
|
||||
|
||||
/**
|
||||
* @brief Informs of a provider region being selected
|
||||
*
|
||||
* This is very generally used to signal user actions that select a specific region within the provider.
|
||||
* It is also used to pass on regions when the provider changes.
|
||||
*
|
||||
* @param providerRegion the provider-aware region being selected
|
||||
*/
|
||||
EVENT_DEF(EventRegionSelected, ImHexApi::HexEditor::ProviderRegion);
|
||||
|
||||
/**
|
||||
* @brief Signals a theme change
|
||||
*
|
||||
* On Windows OS, this is used to reflect the theme color onto the window frame.
|
||||
*/
|
||||
EVENT_DEF(EventThemeChanged);
|
||||
|
||||
/**
|
||||
* @brief Signals that a bookmark was created
|
||||
*
|
||||
* For now, this event's only purpose is to unlock an achievement.
|
||||
*
|
||||
* @param entry the new bookmark
|
||||
*/
|
||||
EVENT_DEF(EventBookmarkCreated, ImHexApi::Bookmarks::Entry&);
|
||||
|
||||
/**
|
||||
* @brief Called upon creation of an IPS patch.
|
||||
* As for now, the event only serves a purpose for the achievement unlock.
|
||||
*
|
||||
* @param data the pointer to the patch content's start
|
||||
* @param size the patch data size
|
||||
* @param kind the patch's kind
|
||||
*/
|
||||
EVENT_DEF(EventPatchCreated, const u8*, u64, const PatchKind);
|
||||
|
||||
/**
|
||||
* @brief Signals the beginning of evaluation of the current pattern
|
||||
*
|
||||
* This allows resetting the drawer view for the pattern data while we wait for the execution completion.
|
||||
*/
|
||||
EVENT_DEF(EventPatternEvaluating);
|
||||
|
||||
/**
|
||||
* @brief Signals the completion of the pattern evaluation
|
||||
*
|
||||
* This causes another reset in the drawer view, to refresh the table displayed to the user.
|
||||
*
|
||||
* @param code the execution's status code
|
||||
*/
|
||||
EVENT_DEF(EventPatternExecuted, const std::string&);
|
||||
|
||||
/**
|
||||
* @brief Denotes when pattern editor has changed
|
||||
*
|
||||
* FIXME: this event is unused and should be scrapped.
|
||||
*/
|
||||
EVENT_DEF(EventPatternEditorChanged, const std::string&);
|
||||
|
||||
/**
|
||||
* @brief Signals that a Content Store item was downloaded
|
||||
*
|
||||
* FIXME: this event is unused and should be scrapped.
|
||||
*
|
||||
* @param path the item's path on the filesystem
|
||||
*/
|
||||
EVENT_DEF(EventStoreContentDownloaded, const std::fs::path&);
|
||||
|
||||
/**
|
||||
* @brief Signals the removal of a Content Store item
|
||||
*
|
||||
* Note: at the time of the event firing, the item has already been removed from the filesystem.
|
||||
*
|
||||
* FIXME: this event is unused and should be scrapped.
|
||||
*
|
||||
* @param path the item's old file path where it used to be in the filesystem
|
||||
*/
|
||||
EVENT_DEF(EventStoreContentRemoved, const std::fs::path&);
|
||||
|
||||
/**
|
||||
* @brief Signals the unlocking of an achievement
|
||||
*
|
||||
* This is used by the achievement manager to refresh the achievement display, as well as store progress to
|
||||
* the appropriate storage file.
|
||||
*
|
||||
* @param achievement the achievement that was unlocked
|
||||
*/
|
||||
EVENT_DEF(EventAchievementUnlocked, const Achievement&);
|
||||
|
||||
/**
|
||||
* @brief Signals a click on the search box
|
||||
*
|
||||
* As there are different behaviours depending on the click (left or right) done by the user,
|
||||
* this allows the consequences of said click to be registered in their own components.
|
||||
*
|
||||
* @param button the ImGuiMouseButton's value
|
||||
*/
|
||||
EVENT_DEF(EventSearchBoxClicked, u32);
|
||||
|
||||
/**
|
||||
* @brief Updates on whether a file is being dragged into ImHex
|
||||
*
|
||||
* Allows ImGUi to display a file dragging information on screen when a file is being dragged.
|
||||
*
|
||||
* @param isFileDragged true if a file is being dragged
|
||||
*/
|
||||
EVENT_DEF(EventFileDragged, bool);
|
||||
|
||||
/**
|
||||
* @brief Triggers loading when a file is dropped
|
||||
*
|
||||
* The event fires when a file is dropped into ImHex, which passes it to file handlers to load it.
|
||||
*
|
||||
* @param path the dropped file's path
|
||||
*/
|
||||
EVENT_DEF(EventFileDropped, std::fs::path);
|
||||
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Lifecycle events definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Called when Imhex finished startup, and will enter the main window rendering loop
|
||||
*/
|
||||
EVENT_DEF(EventImHexStartupFinished);
|
||||
|
||||
/**
|
||||
* @brief Called when ImHex is closing, to trigger the last shutdown hooks
|
||||
*
|
||||
* This is the last event to fire before complete graceful shutdown.
|
||||
*/
|
||||
EVENT_DEF(EventImHexClosing);
|
||||
|
||||
/**
|
||||
* @brief Signals that it's ImHex first launch ever
|
||||
*
|
||||
* This event allows for the launch of the ImHex tutorial (also called Out of Box experience).
|
||||
*/
|
||||
EVENT_DEF(EventFirstLaunch);
|
||||
|
||||
/**
|
||||
* FIXME: this event is unused and should be scrapped.
|
||||
*/
|
||||
EVENT_DEF(EventAnySettingChanged);
|
||||
|
||||
/**
|
||||
* @brief Ensures correct plugin cleanup on crash
|
||||
*
|
||||
* This event is fired when catching an unexpected error that cannot be recovered and
|
||||
* which forces Imhex to close immediately.
|
||||
*
|
||||
* Subscribing to this event ensures that the plugin can correctly clean up any mission-critical tasks
|
||||
* before forceful shutdown.
|
||||
*
|
||||
* @param signal the POSIX signal code
|
||||
*/
|
||||
EVENT_DEF(EventAbnormalTermination, int);
|
||||
|
||||
/**
|
||||
* @brief Informs of the ImHex versions (and difference, if any)
|
||||
*
|
||||
* Called on every startup to inform subscribers of the two versions picked up:
|
||||
* - the version of the previous launch, gathered from the settings file
|
||||
* - the current version, gathered directly from C++ code
|
||||
*
|
||||
* In most cases, and unless ImHex was updated, the two parameters will be the same.
|
||||
*
|
||||
* FIXME: Maybe rename the event to signal a startup information, instead of the misleading
|
||||
* title that the event could be fired when ImHex detects that it was updated since last launch?
|
||||
*
|
||||
* @param previousLaunchVersion ImHex's version during the previous launch
|
||||
* @param currentVersion ImHex's current version for this startup
|
||||
*/
|
||||
EVENT_DEF(EventImHexUpdated, SemanticVersion, SemanticVersion);
|
||||
|
||||
/**
|
||||
* @brief Called when ImHex managed to catch an error in a general try/catch to prevent/recover from a crash
|
||||
*/
|
||||
EVENT_DEF(EventCrashRecovered, const std::exception &);
|
||||
|
||||
/**
|
||||
* @brief Called when a project has been loaded
|
||||
*/
|
||||
EVENT_DEF(EventProjectOpened);
|
||||
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Provider events definitions */
|
||||
namespace hex {
|
||||
/**
|
||||
* @brief Called when the provider is created.
|
||||
* This event is responsible for (optionally) initializing the provider and calling EventProviderOpened
|
||||
* (although the event can also be called manually without problem)
|
||||
*/
|
||||
EVENT_DEF(EventProviderCreated, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Called as a continuation of EventProviderCreated
|
||||
* this event is normally called immediately after EventProviderCreated successfully initialized the provider.
|
||||
* If no initialization (Provider::skipLoadInterface() has been set), this event should be called manually
|
||||
* If skipLoadInterface failed, this event is not called
|
||||
*
|
||||
* @note this is not related to Provider::open()
|
||||
*/
|
||||
EVENT_DEF(EventProviderOpened, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals a change in provider (in-place)
|
||||
*
|
||||
* Note: if the provider was deleted, the new ("current") provider will be `nullptr`
|
||||
*
|
||||
* @param oldProvider the old provider
|
||||
* @param currentProvider the current provider
|
||||
*/
|
||||
EVENT_DEF(EventProviderChanged, prv::Provider *, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals that a provider was saved
|
||||
*
|
||||
* @param provider the saved provider
|
||||
*/
|
||||
EVENT_DEF(EventProviderSaved, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals a provider is closing
|
||||
*
|
||||
* FIXME: as for now, this behaves as a request more than an event. Also, the boolean is always set to true,
|
||||
* and serves no purpose. This should be moved into the Provider requests section and declared accordingly.
|
||||
*
|
||||
* @param provider the closing provider
|
||||
* @param shouldClose whether the provider should close
|
||||
*/
|
||||
EVENT_DEF(EventProviderClosing, prv::Provider *, bool *);
|
||||
|
||||
/**
|
||||
* @brief Signals that a provider was closed
|
||||
*
|
||||
* As this is a closure information broadcast, the provider should generally not be accessed, as it could
|
||||
* result in problems.
|
||||
*
|
||||
* @param provider the now-closed provider
|
||||
*/
|
||||
EVENT_DEF(EventProviderClosed, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals that a provider is being deleted
|
||||
*
|
||||
* Provider's data should not be accessed.
|
||||
*
|
||||
* @param provider the provider
|
||||
*/
|
||||
EVENT_DEF(EventProviderDeleted, prv::Provider *);
|
||||
|
||||
}
|
||||
|
||||
/* Provider data events definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Signals the dirtying of a provider
|
||||
*
|
||||
* Any data modification that occurs in a provider dirties it, until its state is either saved or restored.
|
||||
* This event signals that fact to subscribers so additional code can be executed for certain cases.
|
||||
*/
|
||||
EVENT_DEF(EventProviderDirtied, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals an insertion of new data into a provider
|
||||
*
|
||||
* @param provider the provider
|
||||
* @param offset the start of the insertion
|
||||
* @param size the new data's size
|
||||
*/
|
||||
EVENT_DEF(EventProviderDataInserted, prv::Provider *, u64, u64);
|
||||
|
||||
/**
|
||||
* @brief Signals a modification in the provider's data
|
||||
*
|
||||
* @param provider the provider
|
||||
* @param offset the data modification's offset (start address)
|
||||
* @param size the buffer's size
|
||||
* @param buffer the modified data written at this address
|
||||
*/
|
||||
EVENT_DEF(EventProviderDataModified, prv::Provider *, u64, u64, const u8*);
|
||||
|
||||
/**
|
||||
* @brief Signals a removal of some of the provider's data
|
||||
*
|
||||
* @param provider the provider
|
||||
* @param offset the deletion offset (start address)
|
||||
* @param size the deleted data's size
|
||||
*/
|
||||
EVENT_DEF(EventProviderDataRemoved, prv::Provider *, u64, u64);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* GUI requests definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Requests the opening of a new window.
|
||||
*
|
||||
* @param name the window's name
|
||||
*/
|
||||
EVENT_DEF(RequestOpenWindow, std::string);
|
||||
|
||||
/**
|
||||
* @brief Centralized request to update ImHex's main window title
|
||||
*
|
||||
* This request can be called to make ImHex refresh its main window title, taking into account a new project
|
||||
* or file opened/closed.
|
||||
*/
|
||||
EVENT_DEF(RequestUpdateWindowTitle);
|
||||
|
||||
/**
|
||||
* @brief Requests a theme type (light or dark) change
|
||||
*
|
||||
* @param themeType either `Light` or `Dark`
|
||||
*/
|
||||
EVENT_DEF(RequestChangeTheme, std::string);
|
||||
|
||||
/**
|
||||
* @brief Requests the opening of a popup
|
||||
*
|
||||
* @param name the popup's name
|
||||
*/
|
||||
EVENT_DEF(RequestOpenPopup, std::string);
|
||||
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Forward declarations */
|
||||
namespace pl::ptrn { class Pattern; }
|
||||
|
||||
/* Interaction requests definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Requests a selection change in the Hex editor
|
||||
*
|
||||
* This request is handled by the Hex editor, which proceeds to check if the selection is valid.
|
||||
* If it is invalid, the Hex editor fires the `EventRegionSelected` event with nullptr region info.
|
||||
*
|
||||
* @param region the region that should be selected
|
||||
*/
|
||||
EVENT_DEF(RequestHexEditorSelectionChange, Region);
|
||||
|
||||
/**
|
||||
* @brief Requests the Pattern editor to move selection
|
||||
*
|
||||
* Requests the Pattern editor to move the cursor's position to reflect the user's click or movement.
|
||||
*
|
||||
* @param line the target line
|
||||
* @param column the target column
|
||||
*/
|
||||
EVENT_DEF(RequestPatternEditorSelectionChange, u32, u32);
|
||||
|
||||
/**
|
||||
* @brief Requests a jump to a given pattern
|
||||
*
|
||||
* This request is fired by the Hex editor when the user asks to jump to the pattern.
|
||||
* It is then caught and reflected by the Pattern data component.
|
||||
*
|
||||
* @param pattern the pattern to jump to
|
||||
*/
|
||||
EVENT_DEF(RequestJumpToPattern, const pl::ptrn::Pattern*);
|
||||
|
||||
/**
|
||||
* @brief Requests to add a bookmark
|
||||
*
|
||||
* @param region the region to be bookmarked
|
||||
* @param name the bookmark's name
|
||||
* @param comment a comment
|
||||
* @param color the color
|
||||
* @param id the bookmark's unique ID
|
||||
*/
|
||||
EVENT_DEF(RequestAddBookmark, Region, std::string, std::string, color_t, u64*);
|
||||
|
||||
/**
|
||||
* @brief Requests a bookmark removal
|
||||
*
|
||||
* @param id the bookmark's unique ID
|
||||
*/
|
||||
EVENT_DEF(RequestRemoveBookmark, u64);
|
||||
|
||||
/**
|
||||
* @brief Request the Pattern editor to set its code
|
||||
*
|
||||
* This request allows the rest of ImHex to interface with the Pattern editor component, by setting its code.
|
||||
* This allows for `.hexpat` file loading, and more.
|
||||
*
|
||||
* @param code the code's string
|
||||
*/
|
||||
EVENT_DEF(RequestSetPatternLanguageCode, std::string);
|
||||
|
||||
/**
|
||||
* @brief Requests the Pattern editor to run the current code
|
||||
*
|
||||
* This is only ever used in the introduction tutorial.
|
||||
*
|
||||
* FIXME: the name is misleading, as for now this activates the pattern's auto-evaluation rather than a
|
||||
* one-off execution
|
||||
*/
|
||||
EVENT_DEF(RequestRunPatternCode);
|
||||
|
||||
/**
|
||||
* @brief Request to load a pattern language file
|
||||
*
|
||||
* FIXME: this request is unused, as now another component is responsible for pattern file loading.
|
||||
* This request should be scrapped.
|
||||
*
|
||||
* @param path the pattern file's path
|
||||
*/
|
||||
EVENT_DEF(RequestLoadPatternLanguageFile, std::fs::path);
|
||||
|
||||
/**
|
||||
* @brief Request to save a pattern language file
|
||||
*
|
||||
* FIXME: this request is unused, as now another component is responsible for pattern file saving.
|
||||
* This request should be scrapped.
|
||||
*
|
||||
* @param path the pattern file's path
|
||||
*/
|
||||
EVENT_DEF(RequestSavePatternLanguageFile, std::fs::path);
|
||||
|
||||
/**
|
||||
* @brief Requests ImHex to open and process a file
|
||||
*
|
||||
* @param path the file's path
|
||||
*/
|
||||
EVENT_DEF(RequestOpenFile, std::fs::path);
|
||||
|
||||
/**
|
||||
* @brief Adds a virtual file in the Pattern editor
|
||||
*
|
||||
* @param path the file's path
|
||||
* @param data the file's data
|
||||
* @param region the impacted region
|
||||
*/
|
||||
EVENT_DEF(RequestAddVirtualFile, std::fs::path, std::vector<u8>, Region);
|
||||
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Lifecycle requests definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Emit a request to add an initialization task to the list
|
||||
*
|
||||
* These tasks will be executed at startup.
|
||||
*
|
||||
* @param name Name of the init task
|
||||
* @param isAsync Whether the task is asynchronous (true if yes)
|
||||
* @param callbackFunction The function to call to execute the task
|
||||
*/
|
||||
EVENT_DEF(RequestAddInitTask, std::string, bool, std::function<bool()>);
|
||||
|
||||
/**
|
||||
* @brief Emit a request to add an exit task to the list
|
||||
*
|
||||
* These tasks will be executed during the exit phase.
|
||||
*
|
||||
* FIXME: request is unused and should be scrapped.
|
||||
*
|
||||
* @param name Name of the exit task
|
||||
* @param callbackFunction The function to call to execute the task
|
||||
*/
|
||||
EVENT_DEF(RequestAddExitTask, std::string, std::function<bool()>);
|
||||
|
||||
/**
|
||||
* @brief Requests ImHex's graceful shutdown
|
||||
*
|
||||
* If there are no questions (bool set to true), ImHex closes immediately.
|
||||
* If set to false, there is a procedure run to prompt a confirmation to the user.
|
||||
*
|
||||
* @param noQuestions true if no questions
|
||||
*/
|
||||
EVENT_DEF(RequestCloseImHex, bool);
|
||||
|
||||
/**
|
||||
* @brief Requests ImHex's restart
|
||||
*
|
||||
* This event is necessary for ImHex to restart in the main loop for native and web platforms,
|
||||
* as ImHex cannot simply close and re-open.
|
||||
*
|
||||
* This event serves no purpose on Linux, Windows and macOS platforms.
|
||||
*/
|
||||
EVENT_DEF(RequestRestartImHex);
|
||||
|
||||
/**
|
||||
* @brief Requests the initialization of theme handlers
|
||||
*
|
||||
* This is called during ImGui bootstrapping, and should not be called at any other time.
|
||||
*/
|
||||
EVENT_DEF(RequestInitThemeHandlers);
|
||||
|
||||
/**
|
||||
* @brief Requests version and first-startup checks
|
||||
*
|
||||
* This request is called during ImHex's startup, and allows ImHex to check if it was updated since last launch.
|
||||
* It also ensures newcomers (that open ImHex for the first time) are greeted with the tutorial.
|
||||
*
|
||||
* FIXME: the name is misleading, as this request does not effectively start any migration. It only executes
|
||||
* checks about ImHex's version. The name should be changed to reflect this behaviour.
|
||||
*/
|
||||
EVENT_DEF(RequestStartMigration);
|
||||
|
||||
/**
|
||||
* @brief Send a subcommand to the main Imhex instance
|
||||
*
|
||||
* This request is called to send a subcommand to the main ImHex instance.
|
||||
* This subcommand will then be executed by a handler when ImHex finishing initializing
|
||||
* (`EventImHexStartupFinished`).
|
||||
*
|
||||
* FIXME: change the name so that it is prefixed with "Request" like every other request.
|
||||
*
|
||||
* @param name the subcommand's name
|
||||
* @param data the subcommand's data
|
||||
*/
|
||||
EVENT_DEF(SendMessageToMainInstance, const std::string, const std::vector<u8>&);
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Provider requests definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Creates a provider from its unlocalized name, and add it to the provider list
|
||||
*/
|
||||
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, hex::prv::Provider **);
|
||||
|
||||
/**
|
||||
* @brief Move the data from all PerProvider instances from one provider to another
|
||||
*
|
||||
* The 'from' provider should not have any per provider data after this, and should be immediately deleted
|
||||
*
|
||||
* FIXME: rename with the "Request" prefix to apply standard naming convention.
|
||||
*/
|
||||
EVENT_DEF(MovePerProviderData, prv::Provider *, prv::Provider *);
|
||||
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/helpers/semantic_version.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
@@ -493,7 +492,6 @@ namespace hex {
|
||||
*/
|
||||
float getNativeScale();
|
||||
|
||||
float getBackingScaleFactor();
|
||||
|
||||
/**
|
||||
* @brief Gets the current main window position
|
||||
@@ -582,14 +580,6 @@ namespace hex {
|
||||
*/
|
||||
const std::string& getGLRenderer();
|
||||
|
||||
/**
|
||||
* @brief Checks if ImHex is being run in a "Corporate Environment"
|
||||
* This function simply checks for common telltale signs such as if the machine is joined a
|
||||
* domain. It's not super accurate, but it's still useful for statistics
|
||||
* @return True if it is
|
||||
*/
|
||||
bool isCorporateEnvironment();
|
||||
|
||||
/**
|
||||
* @brief Checks if ImHex is running in portable mode
|
||||
* @return Whether ImHex is running in portable mode
|
||||
@@ -628,7 +618,7 @@ namespace hex {
|
||||
* @brief Gets the current ImHex version
|
||||
* @return ImHex version
|
||||
*/
|
||||
SemanticVersion getImHexVersion();
|
||||
std::string getImHexVersion(bool withBuildType = true);
|
||||
|
||||
/**
|
||||
* @brief Gets the current git commit hash
|
||||
@@ -705,13 +695,6 @@ namespace hex {
|
||||
*/
|
||||
void* getLibImHexModuleHandle();
|
||||
|
||||
/**
|
||||
* Adds a new migration routine that will be executed when upgrading from a lower version than specified in migrationVersion
|
||||
* @param migrationVersion Upgrade point version
|
||||
* @param function Function to run
|
||||
*/
|
||||
void addMigrationRoutine(SemanticVersion migrationVersion, std::function<void()> function);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -753,8 +736,11 @@ namespace hex {
|
||||
|
||||
const std::vector<Font>& getFonts();
|
||||
|
||||
std::map<UnlocalizedString, ImFont*>& getFontDefinitions();
|
||||
void setCustomFontPath(const std::fs::path &path);
|
||||
void setFontSize(float size);
|
||||
void setFontAtlas(ImFontAtlas *fontAtlas);
|
||||
|
||||
void setFonts(ImFont *bold, ImFont *italic);
|
||||
}
|
||||
|
||||
GlyphRange glyph(const char *glyph);
|
||||
@@ -767,8 +753,26 @@ namespace hex {
|
||||
|
||||
constexpr static float DefaultFontSize = 13.0;
|
||||
|
||||
void registerFont(const UnlocalizedString &fontName);
|
||||
ImFont* getFont(const UnlocalizedString &fontName);
|
||||
ImFont* Bold();
|
||||
ImFont* Italic();
|
||||
|
||||
/**
|
||||
* @brief Gets the current custom font path
|
||||
* @return The current custom font path
|
||||
*/
|
||||
const std::filesystem::path& getCustomFontPath();
|
||||
|
||||
/**
|
||||
* @brief Gets the current font size
|
||||
* @return The current font size
|
||||
*/
|
||||
float getFontSize();
|
||||
|
||||
/**
|
||||
* @brief Gets the current font atlas
|
||||
* @return Current font atlas
|
||||
*/
|
||||
ImFontAtlas* getFontAtlas();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <wolv/types/static_string.hpp>
|
||||
#include <fmt/format.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -25,30 +22,24 @@ namespace hex {
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
void setFallbackLanguage(const std::string &language);
|
||||
void resetLanguageStrings();
|
||||
|
||||
}
|
||||
|
||||
void loadLanguage(std::string language);
|
||||
void loadLanguage(const std::string &language);
|
||||
std::string getLocalizedString(const std::string &unlocalizedString, const std::string &language = "");
|
||||
|
||||
[[nodiscard]] const std::map<std::string, std::string> &getSupportedLanguages();
|
||||
[[nodiscard]] const std::string &getFallbackLanguage();
|
||||
[[nodiscard]] const std::string &getSelectedLanguage();
|
||||
|
||||
}
|
||||
|
||||
struct UnlocalizedString;
|
||||
|
||||
class LangConst;
|
||||
|
||||
class Lang {
|
||||
public:
|
||||
explicit Lang(const char *unlocalizedString);
|
||||
explicit Lang(const std::string &unlocalizedString);
|
||||
explicit(false) Lang(const LangConst &localizedString);
|
||||
explicit Lang(const UnlocalizedString &unlocalizedString);
|
||||
explicit Lang(std::string_view unlocalizedString);
|
||||
|
||||
@@ -56,54 +47,30 @@ namespace hex {
|
||||
[[nodiscard]] operator std::string_view() const;
|
||||
[[nodiscard]] operator const char *() const;
|
||||
|
||||
const char* get() const;
|
||||
[[nodiscard]] const std::string &get() const;
|
||||
|
||||
private:
|
||||
std::size_t m_entryHash;
|
||||
std::string m_unlocalizedString;
|
||||
};
|
||||
|
||||
class LangConst {
|
||||
public:
|
||||
[[nodiscard]] operator std::string() const;
|
||||
[[nodiscard]] operator std::string_view() const;
|
||||
[[nodiscard]] operator const char *() const;
|
||||
[[nodiscard]] std::string operator+(const std::string &&left, const Lang &&right);
|
||||
[[nodiscard]] std::string operator+(const Lang &&left, const std::string &&right);
|
||||
[[nodiscard]] std::string operator+(const std::string_view &&left, const Lang &&right);
|
||||
[[nodiscard]] std::string operator+(const Lang &&left, const std::string_view &&right);
|
||||
[[nodiscard]] std::string operator+(const char *left, const Lang &&right);
|
||||
[[nodiscard]] std::string operator+(const Lang &&left, const char *right);
|
||||
[[nodiscard]] std::string operator+(const Lang &&left, const Lang &&right);
|
||||
|
||||
const char* get() const;
|
||||
[[nodiscard]] inline Lang operator""_lang(const char *string, size_t) {
|
||||
return Lang(string);
|
||||
}
|
||||
|
||||
constexpr static size_t hash(std::string_view string) {
|
||||
constexpr u64 p = 131;
|
||||
constexpr u64 m = std::numeric_limits<std::uint32_t>::max() - 4;
|
||||
u64 total = 0;
|
||||
u64 currentMultiplier = 1;
|
||||
|
||||
for (char c : string) {
|
||||
total = (total + currentMultiplier * c) % m;
|
||||
currentMultiplier = (currentMultiplier * p) % m;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr explicit LangConst(std::size_t hash, const char *unlocalizedString) : m_entryHash(hash), m_unlocalizedString(unlocalizedString) {}
|
||||
|
||||
template<wolv::type::StaticString>
|
||||
friend consteval LangConst operator""_lang();
|
||||
friend class Lang;
|
||||
|
||||
private:
|
||||
std::size_t m_entryHash;
|
||||
const char *m_unlocalizedString = nullptr;
|
||||
};
|
||||
|
||||
struct UnlocalizedString {
|
||||
public:
|
||||
UnlocalizedString() = default;
|
||||
|
||||
template<typename T>
|
||||
UnlocalizedString(T &&arg) : m_unlocalizedString(std::forward<T>(arg)) {
|
||||
static_assert(!std::same_as<std::remove_cvref_t<T>, Lang>, "Expected a unlocalized name, got a localized one!");
|
||||
UnlocalizedString(auto && arg) : m_unlocalizedString(std::forward<decltype(arg)>(arg)) {
|
||||
static_assert(!std::same_as<std::remove_cvref_t<decltype(arg)>, Lang>, "Expected a unlocalized name, got a localized one!");
|
||||
}
|
||||
|
||||
[[nodiscard]] operator std::string() const {
|
||||
@@ -135,17 +102,9 @@ namespace hex {
|
||||
std::string m_unlocalizedString;
|
||||
};
|
||||
|
||||
template<wolv::type::StaticString String>
|
||||
[[nodiscard]] consteval LangConst operator""_lang() {
|
||||
return LangConst(LangConst::hash(String.value.data()), String.value.data());
|
||||
}
|
||||
|
||||
// {fmt} formatter for hex::Lang and hex::LangConst
|
||||
// {fmt} formatter for hex::Lang
|
||||
inline auto format_as(const hex::Lang &entry) {
|
||||
return entry.get();
|
||||
}
|
||||
inline auto format_as(const hex::LangConst &entry) {
|
||||
return entry.get();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,31 +2,142 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/helpers/keys.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
struct ImGuiWindow;
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
struct KeyEquivalent {
|
||||
bool valid;
|
||||
bool ctrl, opt, cmd, shift;
|
||||
int key;
|
||||
};
|
||||
struct ImGuiWindow;
|
||||
|
||||
namespace hex {
|
||||
|
||||
class View;
|
||||
|
||||
enum class Keys {
|
||||
Space = GLFW_KEY_SPACE,
|
||||
Apostrophe = GLFW_KEY_APOSTROPHE,
|
||||
Comma = GLFW_KEY_COMMA,
|
||||
Minus = GLFW_KEY_MINUS,
|
||||
Period = GLFW_KEY_PERIOD,
|
||||
Slash = GLFW_KEY_SLASH,
|
||||
Num0 = GLFW_KEY_0,
|
||||
Num1 = GLFW_KEY_1,
|
||||
Num2 = GLFW_KEY_2,
|
||||
Num3 = GLFW_KEY_3,
|
||||
Num4 = GLFW_KEY_4,
|
||||
Num5 = GLFW_KEY_5,
|
||||
Num6 = GLFW_KEY_6,
|
||||
Num7 = GLFW_KEY_7,
|
||||
Num8 = GLFW_KEY_8,
|
||||
Num9 = GLFW_KEY_9,
|
||||
Semicolon = GLFW_KEY_SEMICOLON,
|
||||
Equals = GLFW_KEY_EQUAL,
|
||||
A = GLFW_KEY_A,
|
||||
B = GLFW_KEY_B,
|
||||
C = GLFW_KEY_C,
|
||||
D = GLFW_KEY_D,
|
||||
E = GLFW_KEY_E,
|
||||
F = GLFW_KEY_F,
|
||||
G = GLFW_KEY_G,
|
||||
H = GLFW_KEY_H,
|
||||
I = GLFW_KEY_I,
|
||||
J = GLFW_KEY_J,
|
||||
K = GLFW_KEY_K,
|
||||
L = GLFW_KEY_L,
|
||||
M = GLFW_KEY_M,
|
||||
N = GLFW_KEY_N,
|
||||
O = GLFW_KEY_O,
|
||||
P = GLFW_KEY_P,
|
||||
Q = GLFW_KEY_Q,
|
||||
R = GLFW_KEY_R,
|
||||
S = GLFW_KEY_S,
|
||||
T = GLFW_KEY_T,
|
||||
U = GLFW_KEY_U,
|
||||
V = GLFW_KEY_V,
|
||||
W = GLFW_KEY_W,
|
||||
X = GLFW_KEY_X,
|
||||
Y = GLFW_KEY_Y,
|
||||
Z = GLFW_KEY_Z,
|
||||
LeftBracket = GLFW_KEY_LEFT_BRACKET,
|
||||
Backslash = GLFW_KEY_BACKSLASH,
|
||||
RightBracket = GLFW_KEY_RIGHT_BRACKET,
|
||||
GraveAccent = GLFW_KEY_GRAVE_ACCENT,
|
||||
World1 = GLFW_KEY_WORLD_1,
|
||||
World2 = GLFW_KEY_WORLD_2,
|
||||
Escape = GLFW_KEY_ESCAPE,
|
||||
Enter = GLFW_KEY_ENTER,
|
||||
Tab = GLFW_KEY_TAB,
|
||||
Backspace = GLFW_KEY_BACKSPACE,
|
||||
Insert = GLFW_KEY_INSERT,
|
||||
Delete = GLFW_KEY_DELETE,
|
||||
Right = GLFW_KEY_RIGHT,
|
||||
Left = GLFW_KEY_LEFT,
|
||||
Down = GLFW_KEY_DOWN,
|
||||
Up = GLFW_KEY_UP,
|
||||
PageUp = GLFW_KEY_PAGE_UP,
|
||||
PageDown = GLFW_KEY_PAGE_DOWN,
|
||||
Home = GLFW_KEY_HOME,
|
||||
End = GLFW_KEY_END,
|
||||
CapsLock = GLFW_KEY_CAPS_LOCK,
|
||||
ScrollLock = GLFW_KEY_SCROLL_LOCK,
|
||||
NumLock = GLFW_KEY_NUM_LOCK,
|
||||
PrintScreen = GLFW_KEY_PRINT_SCREEN,
|
||||
Pause = GLFW_KEY_PAUSE,
|
||||
F1 = GLFW_KEY_F1,
|
||||
F2 = GLFW_KEY_F2,
|
||||
F3 = GLFW_KEY_F3,
|
||||
F4 = GLFW_KEY_F4,
|
||||
F5 = GLFW_KEY_F5,
|
||||
F6 = GLFW_KEY_F6,
|
||||
F7 = GLFW_KEY_F7,
|
||||
F8 = GLFW_KEY_F8,
|
||||
F9 = GLFW_KEY_F9,
|
||||
F10 = GLFW_KEY_F10,
|
||||
F11 = GLFW_KEY_F11,
|
||||
F12 = GLFW_KEY_F12,
|
||||
F13 = GLFW_KEY_F13,
|
||||
F14 = GLFW_KEY_F14,
|
||||
F15 = GLFW_KEY_F15,
|
||||
F16 = GLFW_KEY_F16,
|
||||
F17 = GLFW_KEY_F17,
|
||||
F18 = GLFW_KEY_F18,
|
||||
F19 = GLFW_KEY_F19,
|
||||
F20 = GLFW_KEY_F20,
|
||||
F21 = GLFW_KEY_F21,
|
||||
F22 = GLFW_KEY_F22,
|
||||
F23 = GLFW_KEY_F23,
|
||||
F24 = GLFW_KEY_F24,
|
||||
F25 = GLFW_KEY_F25,
|
||||
KeyPad0 = GLFW_KEY_KP_0,
|
||||
KeyPad1 = GLFW_KEY_KP_1,
|
||||
KeyPad2 = GLFW_KEY_KP_2,
|
||||
KeyPad3 = GLFW_KEY_KP_3,
|
||||
KeyPad4 = GLFW_KEY_KP_4,
|
||||
KeyPad5 = GLFW_KEY_KP_5,
|
||||
KeyPad6 = GLFW_KEY_KP_6,
|
||||
KeyPad7 = GLFW_KEY_KP_7,
|
||||
KeyPad8 = GLFW_KEY_KP_8,
|
||||
KeyPad9 = GLFW_KEY_KP_9,
|
||||
KeyPadDecimal = GLFW_KEY_KP_DECIMAL,
|
||||
KeyPadDivide = GLFW_KEY_KP_DIVIDE,
|
||||
KeyPadMultiply = GLFW_KEY_KP_MULTIPLY,
|
||||
KeyPadSubtract = GLFW_KEY_KP_SUBTRACT,
|
||||
KeyPadAdd = GLFW_KEY_KP_ADD,
|
||||
KeyPadEnter = GLFW_KEY_KP_ENTER,
|
||||
KeyPadEqual = GLFW_KEY_KP_EQUAL,
|
||||
Menu = GLFW_KEY_MENU,
|
||||
};
|
||||
|
||||
|
||||
class Key {
|
||||
public:
|
||||
constexpr Key() = default;
|
||||
constexpr Key(Keys key) : m_key(static_cast<u32>(key)) { }
|
||||
|
||||
bool operator==(const Key &) const = default;
|
||||
auto operator<=>(const Key &) const = default;
|
||||
|
||||
[[nodiscard]] constexpr u32 getKeyCode() const { return m_key; }
|
||||
@@ -41,32 +152,224 @@ namespace hex {
|
||||
constexpr static auto SUPER = Key(static_cast<Keys>(0x0800'0000));
|
||||
constexpr static auto CurrentView = Key(static_cast<Keys>(0x1000'0000));
|
||||
constexpr static auto AllowWhileTyping = Key(static_cast<Keys>(0x2000'0000));
|
||||
constexpr static auto CTRLCMD = Key(static_cast<Keys>(0x4000'0000));
|
||||
|
||||
#if defined (OS_MACOS)
|
||||
constexpr static auto CTRLCMD = SUPER;
|
||||
#else
|
||||
constexpr static auto CTRLCMD = CTRL;
|
||||
#endif
|
||||
|
||||
class Shortcut {
|
||||
public:
|
||||
Shortcut() = default;
|
||||
Shortcut(Keys key);
|
||||
explicit Shortcut(std::set<Key> keys);
|
||||
Shortcut(Keys key) : m_keys({ key }) { }
|
||||
explicit Shortcut(std::set<Key> keys) : m_keys(std::move(keys)) { }
|
||||
Shortcut(const Shortcut &other) = default;
|
||||
Shortcut(Shortcut &&) noexcept = default;
|
||||
|
||||
constexpr static auto None = Keys(0);
|
||||
|
||||
Shortcut& operator=(const Shortcut &other) = default;
|
||||
|
||||
Shortcut& operator=(Shortcut &&) noexcept = default;
|
||||
|
||||
Shortcut operator+(const Key &other) const;
|
||||
Shortcut &operator+=(const Key &other);
|
||||
bool operator<(const Shortcut &other) const;
|
||||
bool operator==(const Shortcut &other) const;
|
||||
constexpr static inline auto None = Keys(0);
|
||||
|
||||
bool isLocal() const;
|
||||
std::string toString() const;
|
||||
KeyEquivalent toKeyEquivalent() const;
|
||||
const std::set<Key>& getKeys() const;
|
||||
bool has(Key key) const;
|
||||
bool matches(const Shortcut &other) const;
|
||||
Shortcut operator+(const Key &other) const {
|
||||
Shortcut result = *this;
|
||||
result.m_keys.insert(other);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Shortcut &operator+=(const Key &other) {
|
||||
m_keys.insert(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator<(const Shortcut &other) const {
|
||||
return m_keys < other.m_keys;
|
||||
}
|
||||
|
||||
bool operator==(const Shortcut &other) const {
|
||||
auto thisKeys = m_keys;
|
||||
auto otherKeys = other.m_keys;
|
||||
|
||||
thisKeys.erase(CurrentView);
|
||||
thisKeys.erase(AllowWhileTyping);
|
||||
otherKeys.erase(CurrentView);
|
||||
otherKeys.erase(AllowWhileTyping);
|
||||
|
||||
return thisKeys == otherKeys;
|
||||
}
|
||||
|
||||
bool isLocal() const {
|
||||
return m_keys.contains(CurrentView);
|
||||
}
|
||||
|
||||
std::string toString() const {
|
||||
std::string result;
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
constexpr static auto CTRL_NAME = "CTRL";
|
||||
constexpr static auto ALT_NAME = "OPT";
|
||||
constexpr static auto SHIFT_NAME = "SHIFT";
|
||||
constexpr static auto SUPER_NAME = "CMD";
|
||||
#else
|
||||
constexpr static auto CTRL_NAME = "CTRL";
|
||||
constexpr static auto ALT_NAME = "ALT";
|
||||
constexpr static auto SHIFT_NAME = "SHIFT";
|
||||
constexpr static auto SUPER_NAME = "SUPER";
|
||||
#endif
|
||||
|
||||
constexpr static auto Concatination = " + ";
|
||||
|
||||
auto keys = m_keys;
|
||||
if (keys.erase(CTRL) > 0) {
|
||||
result += CTRL_NAME;
|
||||
result += Concatination;
|
||||
}
|
||||
if (keys.erase(ALT) > 0) {
|
||||
result += ALT_NAME;
|
||||
result += Concatination;
|
||||
}
|
||||
if (keys.erase(SHIFT) > 0) {
|
||||
result += SHIFT_NAME;
|
||||
result += Concatination;
|
||||
}
|
||||
if (keys.erase(SUPER) > 0) {
|
||||
result += SUPER_NAME;
|
||||
result += Concatination;
|
||||
}
|
||||
keys.erase(CurrentView);
|
||||
|
||||
for (const auto &key : keys) {
|
||||
switch (Keys(key.getKeyCode())) {
|
||||
case Keys::Space: result += "SPACE"; break;
|
||||
case Keys::Apostrophe: result += "'"; break;
|
||||
case Keys::Comma: result += ","; break;
|
||||
case Keys::Minus: result += "-"; break;
|
||||
case Keys::Period: result += "."; break;
|
||||
case Keys::Slash: result += "/"; break;
|
||||
case Keys::Num0: result += "0"; break;
|
||||
case Keys::Num1: result += "1"; break;
|
||||
case Keys::Num2: result += "2"; break;
|
||||
case Keys::Num3: result += "3"; break;
|
||||
case Keys::Num4: result += "4"; break;
|
||||
case Keys::Num5: result += "5"; break;
|
||||
case Keys::Num6: result += "6"; break;
|
||||
case Keys::Num7: result += "7"; break;
|
||||
case Keys::Num8: result += "8"; break;
|
||||
case Keys::Num9: result += "9"; break;
|
||||
case Keys::Semicolon: result += ";"; break;
|
||||
case Keys::Equals: result += "="; break;
|
||||
case Keys::A: result += "A"; break;
|
||||
case Keys::B: result += "B"; break;
|
||||
case Keys::C: result += "C"; break;
|
||||
case Keys::D: result += "D"; break;
|
||||
case Keys::E: result += "E"; break;
|
||||
case Keys::F: result += "F"; break;
|
||||
case Keys::G: result += "G"; break;
|
||||
case Keys::H: result += "H"; break;
|
||||
case Keys::I: result += "I"; break;
|
||||
case Keys::J: result += "J"; break;
|
||||
case Keys::K: result += "K"; break;
|
||||
case Keys::L: result += "L"; break;
|
||||
case Keys::M: result += "M"; break;
|
||||
case Keys::N: result += "N"; break;
|
||||
case Keys::O: result += "O"; break;
|
||||
case Keys::P: result += "P"; break;
|
||||
case Keys::Q: result += "Q"; break;
|
||||
case Keys::R: result += "R"; break;
|
||||
case Keys::S: result += "S"; break;
|
||||
case Keys::T: result += "T"; break;
|
||||
case Keys::U: result += "U"; break;
|
||||
case Keys::V: result += "V"; break;
|
||||
case Keys::W: result += "W"; break;
|
||||
case Keys::X: result += "X"; break;
|
||||
case Keys::Y: result += "Y"; break;
|
||||
case Keys::Z: result += "Z"; break;
|
||||
case Keys::LeftBracket: result += "["; break;
|
||||
case Keys::Backslash: result += "\\"; break;
|
||||
case Keys::RightBracket: result += "]"; break;
|
||||
case Keys::GraveAccent: result += "`"; break;
|
||||
case Keys::World1: result += "WORLD1"; break;
|
||||
case Keys::World2: result += "WORLD2"; break;
|
||||
case Keys::Escape: result += "ESC"; break;
|
||||
case Keys::Enter: result += "ENTER"; break;
|
||||
case Keys::Tab: result += "TAB"; break;
|
||||
case Keys::Backspace: result += "BACKSPACE"; break;
|
||||
case Keys::Insert: result += "INSERT"; break;
|
||||
case Keys::Delete: result += "DELETE"; break;
|
||||
case Keys::Right: result += "RIGHT"; break;
|
||||
case Keys::Left: result += "LEFT"; break;
|
||||
case Keys::Down: result += "DOWN"; break;
|
||||
case Keys::Up: result += "UP"; break;
|
||||
case Keys::PageUp: result += "PAGEUP"; break;
|
||||
case Keys::PageDown: result += "PAGEDOWN"; break;
|
||||
case Keys::Home: result += "HOME"; break;
|
||||
case Keys::End: result += "END"; break;
|
||||
case Keys::CapsLock: result += "CAPSLOCK"; break;
|
||||
case Keys::ScrollLock: result += "SCROLLLOCK"; break;
|
||||
case Keys::NumLock: result += "NUMLOCK"; break;
|
||||
case Keys::PrintScreen: result += "PRINTSCREEN"; break;
|
||||
case Keys::Pause: result += "PAUSE"; break;
|
||||
case Keys::F1: result += "F1"; break;
|
||||
case Keys::F2: result += "F2"; break;
|
||||
case Keys::F3: result += "F3"; break;
|
||||
case Keys::F4: result += "F4"; break;
|
||||
case Keys::F5: result += "F5"; break;
|
||||
case Keys::F6: result += "F6"; break;
|
||||
case Keys::F7: result += "F7"; break;
|
||||
case Keys::F8: result += "F8"; break;
|
||||
case Keys::F9: result += "F9"; break;
|
||||
case Keys::F10: result += "F10"; break;
|
||||
case Keys::F11: result += "F11"; break;
|
||||
case Keys::F12: result += "F12"; break;
|
||||
case Keys::F13: result += "F13"; break;
|
||||
case Keys::F14: result += "F14"; break;
|
||||
case Keys::F15: result += "F15"; break;
|
||||
case Keys::F16: result += "F16"; break;
|
||||
case Keys::F17: result += "F17"; break;
|
||||
case Keys::F18: result += "F18"; break;
|
||||
case Keys::F19: result += "F19"; break;
|
||||
case Keys::F20: result += "F20"; break;
|
||||
case Keys::F21: result += "F21"; break;
|
||||
case Keys::F22: result += "F22"; break;
|
||||
case Keys::F23: result += "F23"; break;
|
||||
case Keys::F24: result += "F24"; break;
|
||||
case Keys::F25: result += "F25"; break;
|
||||
case Keys::KeyPad0: result += "KP0"; break;
|
||||
case Keys::KeyPad1: result += "KP1"; break;
|
||||
case Keys::KeyPad2: result += "KP2"; break;
|
||||
case Keys::KeyPad3: result += "KP3"; break;
|
||||
case Keys::KeyPad4: result += "KP4"; break;
|
||||
case Keys::KeyPad5: result += "KP5"; break;
|
||||
case Keys::KeyPad6: result += "KP6"; break;
|
||||
case Keys::KeyPad7: result += "KP7"; break;
|
||||
case Keys::KeyPad8: result += "KP8"; break;
|
||||
case Keys::KeyPad9: result += "KP9"; break;
|
||||
case Keys::KeyPadDecimal: result += "KPDECIMAL"; break;
|
||||
case Keys::KeyPadDivide: result += "KPDIVIDE"; break;
|
||||
case Keys::KeyPadMultiply: result += "KPMULTIPLY"; break;
|
||||
case Keys::KeyPadSubtract: result += "KPSUBTRACT"; break;
|
||||
case Keys::KeyPadAdd: result += "KPADD"; break;
|
||||
case Keys::KeyPadEnter: result += "KPENTER"; break;
|
||||
case Keys::KeyPadEqual: result += "KPEQUAL"; break;
|
||||
case Keys::Menu: result += "MENU"; break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
result += " + ";
|
||||
}
|
||||
|
||||
if (result.ends_with(" + "))
|
||||
result = result.substr(0, result.size() - 3);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const std::set<Key>& getKeys() const { return m_keys; }
|
||||
|
||||
private:
|
||||
friend Shortcut operator+(const Key &lhs, const Key &rhs);
|
||||
@@ -74,7 +377,12 @@ namespace hex {
|
||||
std::set<Key> m_keys;
|
||||
};
|
||||
|
||||
Shortcut operator+(const Key &lhs, const Key &rhs);
|
||||
inline Shortcut operator+(const Key &lhs, const Key &rhs) {
|
||||
Shortcut result;
|
||||
result.m_keys = { lhs, rhs };
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The ShortcutManager handles global and view-specific shortcuts.
|
||||
@@ -83,12 +391,10 @@ namespace hex {
|
||||
class ShortcutManager {
|
||||
public:
|
||||
using Callback = std::function<void()>;
|
||||
using EnabledCallback = std::function<bool()>;
|
||||
struct ShortcutEntry {
|
||||
Shortcut shortcut;
|
||||
std::vector<UnlocalizedString> unlocalizedName;
|
||||
UnlocalizedString unlocalizedName;
|
||||
Callback callback;
|
||||
EnabledCallback enabledCallback;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -96,10 +402,8 @@ namespace hex {
|
||||
* @param shortcut The shortcut to add.
|
||||
* @param unlocalizedName The unlocalized name of the shortcut
|
||||
* @param callback The callback to call when the shortcut is triggered.
|
||||
* @param enabledCallback Callback that's called to check if this shortcut is enabled
|
||||
*/
|
||||
static void addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||
static void addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||
static void addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback);
|
||||
|
||||
/**
|
||||
* @brief Add a view-specific shortcut. View-specific shortcuts can only be triggered when the specified view is focused.
|
||||
@@ -107,10 +411,8 @@ namespace hex {
|
||||
* @param shortcut The shortcut to add.
|
||||
* @param unlocalizedName The unlocalized name of the shortcut
|
||||
* @param callback The callback to call when the shortcut is triggered.
|
||||
* @param enabledCallback Callback that's called to check if this shortcut is enabled
|
||||
*/
|
||||
static void addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||
static void addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||
static void addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback);
|
||||
|
||||
|
||||
/**
|
||||
@@ -143,17 +445,12 @@ namespace hex {
|
||||
static void resumeShortcuts();
|
||||
static void pauseShortcuts();
|
||||
|
||||
static void enableMacOSMode();
|
||||
|
||||
[[nodiscard]] static std::optional<UnlocalizedString> getLastActivatedMenu();
|
||||
static void resetLastActivatedMenu();
|
||||
|
||||
[[nodiscard]] static std::optional<Shortcut> getPreviousShortcut();
|
||||
|
||||
[[nodiscard]] static std::vector<ShortcutEntry> getGlobalShortcuts();
|
||||
[[nodiscard]] static std::vector<ShortcutEntry> getViewShortcuts(const View *view);
|
||||
|
||||
[[nodiscard]] static bool updateShortcut(const Shortcut &oldShortcut, Shortcut newShortcut, View *view = nullptr);
|
||||
[[nodiscard]] static bool updateShortcut(const Shortcut &oldShortcut, const Shortcut &newShortcut, View *view = nullptr);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -22,7 +22,7 @@ namespace hex {
|
||||
class Task {
|
||||
public:
|
||||
Task() = default;
|
||||
Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function);
|
||||
Task(UnlocalizedString unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function);
|
||||
|
||||
Task(const Task&) = delete;
|
||||
Task(Task &&other) noexcept;
|
||||
@@ -130,37 +130,20 @@ namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Creates a new asynchronous task that gets displayed in the Task Manager in the footer
|
||||
* @param unlocalizedName Name of the task
|
||||
* @param name Name of the task
|
||||
* @param maxValue Maximum value of the task
|
||||
* @param function Function to be executed
|
||||
* @return A TaskHolder holding a weak reference to the task
|
||||
*/
|
||||
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function);
|
||||
|
||||
/**
|
||||
* @brief Creates a new asynchronous task that gets displayed in the Task Manager in the footer
|
||||
* @param unlocalizedName Name of the task
|
||||
* @param maxValue Maximum value of the task
|
||||
* @param function Function to be executed
|
||||
* @return A TaskHolder holding a weak reference to the task
|
||||
*/
|
||||
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function);
|
||||
static TaskHolder createTask(std::string name, u64 maxValue, std::function<void(Task &)> function);
|
||||
|
||||
/**
|
||||
* @brief Creates a new asynchronous task that does not get displayed in the Task Manager
|
||||
* @param unlocalizedName Name of the task
|
||||
* @param name Name of the task
|
||||
* @param function Function to be executed
|
||||
* @return A TaskHolder holding a weak reference to the task
|
||||
*/
|
||||
static TaskHolder createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void(Task &)> function);
|
||||
|
||||
/**
|
||||
* @brief Creates a new asynchronous task that does not get displayed in the Task Manager
|
||||
* @param unlocalizedName Name of the task
|
||||
* @param function Function to be executed
|
||||
* @return A TaskHolder holding a weak reference to the task
|
||||
*/
|
||||
static TaskHolder createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void()> function);
|
||||
static TaskHolder createBackgroundTask(std::string name, std::function<void(Task &)> function);
|
||||
|
||||
/**
|
||||
* @brief Creates a new synchronous task that will execute the given function at the start of the next frame
|
||||
@@ -207,7 +190,7 @@ namespace hex {
|
||||
static void runDeferredCalls();
|
||||
|
||||
private:
|
||||
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function);
|
||||
static TaskHolder createTask(std::string name, u64 maxValue, bool background, std::function<void(Task &)> function);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -56,7 +56,6 @@ namespace hex {
|
||||
*/
|
||||
static void addStyleHandler(const std::string &name, const StyleMap &styleMap);
|
||||
|
||||
static void reapplyCurrentTheme();
|
||||
|
||||
static std::vector<std::string> getThemeNames();
|
||||
static const std::string &getImageTheme();
|
||||
@@ -67,7 +66,6 @@ namespace hex {
|
||||
|
||||
static void reset();
|
||||
|
||||
static void setAccentColor(const ImColor &color);
|
||||
|
||||
public:
|
||||
struct ThemeHandler {
|
||||
@@ -83,7 +81,6 @@ namespace hex {
|
||||
static const std::map<std::string, ThemeHandler>& getThemeHandlers();
|
||||
static const std::map<std::string, StyleHandler>& getStyleHandlers();
|
||||
|
||||
|
||||
private:
|
||||
ThemeManager() = default;
|
||||
};
|
||||
|
||||
@@ -151,9 +151,6 @@ namespace hex {
|
||||
static void addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString);
|
||||
static void addInteractiveHelpLink(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, std::string link);
|
||||
|
||||
static void setLastItemInteractiveHelpPopup(std::function<void()> callback);
|
||||
static void setLastItemInteractiveHelpLink(std::string link);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Draws the tutorial
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
|
||||
#include <hex/helpers/intrinsics.hpp>
|
||||
#include <hex/data_processor/attribute.hpp>
|
||||
|
||||
#include <set>
|
||||
@@ -11,7 +12,6 @@
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
#include <imgui.h>
|
||||
#include <hex/providers/provider_data.hpp>
|
||||
|
||||
namespace hex::prv {
|
||||
class Provider;
|
||||
@@ -42,12 +42,11 @@ namespace hex::dp {
|
||||
m_overlay = overlay;
|
||||
}
|
||||
|
||||
void draw();
|
||||
virtual void drawNode() { }
|
||||
virtual void process() = 0;
|
||||
virtual void reset() { }
|
||||
|
||||
virtual void store(nlohmann::json &j) const { std::ignore = j; }
|
||||
virtual void load(const nlohmann::json &j) { std::ignore = j; }
|
||||
virtual void store(nlohmann::json &j) const { hex::unused(j); }
|
||||
virtual void load(const nlohmann::json &j) { hex::unused(j); }
|
||||
|
||||
struct NodeError {
|
||||
Node *node;
|
||||
@@ -81,11 +80,6 @@ namespace hex::dp {
|
||||
void setIntegerOnOutput(u32 index, i128 integer);
|
||||
void setFloatOnOutput(u32 index, double floatingPoint);
|
||||
|
||||
static void interrupt();
|
||||
|
||||
protected:
|
||||
virtual void drawNode() { }
|
||||
|
||||
private:
|
||||
int m_id;
|
||||
UnlocalizedString m_unlocalizedTitle, m_unlocalizedName;
|
||||
@@ -96,16 +90,45 @@ namespace hex::dp {
|
||||
|
||||
static int s_idCounter;
|
||||
|
||||
Attribute& getAttribute(u32 index);
|
||||
Attribute *getConnectedInputAttribute(u32 index);
|
||||
void markInputProcessed(u32 index);
|
||||
void unmarkInputProcessed(u32 index);
|
||||
Attribute& getAttribute(u32 index) {
|
||||
if (index >= this->getAttributes().size())
|
||||
throw std::runtime_error("Attribute index out of bounds!");
|
||||
|
||||
return this->getAttributes()[index];
|
||||
}
|
||||
|
||||
Attribute *getConnectedInputAttribute(u32 index) {
|
||||
const auto &connectedAttribute = this->getAttribute(index).getConnectedAttributes();
|
||||
|
||||
if (connectedAttribute.empty())
|
||||
return nullptr;
|
||||
|
||||
return connectedAttribute.begin()->second;
|
||||
}
|
||||
|
||||
void markInputProcessed(u32 index) {
|
||||
const auto &[iter, inserted] = m_processedInputs.insert(index);
|
||||
if (!inserted)
|
||||
throwNodeError("Recursion detected!");
|
||||
}
|
||||
|
||||
void unmarkInputProcessed(u32 index) {
|
||||
m_processedInputs.erase(index);
|
||||
}
|
||||
|
||||
protected:
|
||||
[[noreturn]] void throwNodeError(const std::string &message);
|
||||
[[noreturn]] void throwNodeError(const std::string &message) {
|
||||
throw NodeError { this, message };
|
||||
}
|
||||
|
||||
void setOverlayData(u64 address, const std::vector<u8> &data);
|
||||
void setAttributes(std::vector<Attribute> attributes);
|
||||
|
||||
void setAttributes(std::vector<Attribute> attributes) {
|
||||
m_attributes = std::move(attributes);
|
||||
|
||||
for (auto &attr : m_attributes)
|
||||
attr.setParentNode(this);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -2,15 +2,10 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <wolv/utils/expected.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define CRYPTO_ERROR_INVALID_KEY_LENGTH (-1)
|
||||
#define CRYPTO_ERROR_INVALID_MODE (-2)
|
||||
|
||||
namespace hex::prv {
|
||||
class Provider;
|
||||
}
|
||||
@@ -65,5 +60,5 @@ namespace hex::crypt {
|
||||
Key256Bits = 2
|
||||
};
|
||||
|
||||
wolv::util::Expected<std::vector<u8>, int> aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input);
|
||||
std::vector<u8> aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,4 @@ namespace hex::dbg {
|
||||
}
|
||||
}
|
||||
|
||||
bool debugModeEnabled();
|
||||
void setDebugModeEnabled(bool enabled);
|
||||
|
||||
}
|
||||
@@ -82,9 +82,8 @@ namespace hex::paths {
|
||||
const static inline impl::DataPath Nodes("scripts/nodes");
|
||||
const static inline impl::DataPath Layouts("layouts");
|
||||
const static inline impl::DataPath Workspaces("workspaces");
|
||||
const static inline impl::DataPath Disassemblers("disassemblers");
|
||||
|
||||
constexpr static inline std::array<const impl::DefaultPath*, 21> All = {
|
||||
constexpr static inline std::array<const impl::DefaultPath*, 20> All = {
|
||||
&Config,
|
||||
&Recent,
|
||||
|
||||
@@ -107,7 +106,6 @@ namespace hex::paths {
|
||||
&Nodes,
|
||||
&Layouts,
|
||||
&Workspaces,
|
||||
&Disassemblers
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ranges.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -25,16 +25,13 @@
|
||||
|
||||
template<typename T>
|
||||
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(const std::fs::path &path, const std::string &mimeName) {
|
||||
std::ignore = path;
|
||||
std::ignore = mimeName;
|
||||
hex::unused(path, mimeName);
|
||||
throw std::logic_error("Not implemented");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(std::vector<u8> data, const std::string &mimeName, const std::fs::path &fileName) {
|
||||
std::ignore = data;
|
||||
std::ignore = mimeName;
|
||||
std::ignore = fileName;
|
||||
hex::unused(data, mimeName, fileName);
|
||||
throw std::logic_error("Not implemented");
|
||||
}
|
||||
|
||||
|
||||
9
lib/libimhex/include/hex/helpers/intrinsics.hpp
Normal file
9
lib/libimhex/include/hex/helpers/intrinsics.hpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
namespace hex {
|
||||
|
||||
void unused(auto && ... x) {
|
||||
((void)x, ...);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
enum class Keys {
|
||||
#else
|
||||
enum Keys {
|
||||
#endif
|
||||
Space = GLFW_KEY_SPACE,
|
||||
Apostrophe = GLFW_KEY_APOSTROPHE,
|
||||
Comma = GLFW_KEY_COMMA,
|
||||
Minus = GLFW_KEY_MINUS,
|
||||
Period = GLFW_KEY_PERIOD,
|
||||
Slash = GLFW_KEY_SLASH,
|
||||
Num0 = GLFW_KEY_0,
|
||||
Num1 = GLFW_KEY_1,
|
||||
Num2 = GLFW_KEY_2,
|
||||
Num3 = GLFW_KEY_3,
|
||||
Num4 = GLFW_KEY_4,
|
||||
Num5 = GLFW_KEY_5,
|
||||
Num6 = GLFW_KEY_6,
|
||||
Num7 = GLFW_KEY_7,
|
||||
Num8 = GLFW_KEY_8,
|
||||
Num9 = GLFW_KEY_9,
|
||||
Semicolon = GLFW_KEY_SEMICOLON,
|
||||
Equals = GLFW_KEY_EQUAL,
|
||||
A = GLFW_KEY_A,
|
||||
B = GLFW_KEY_B,
|
||||
C = GLFW_KEY_C,
|
||||
D = GLFW_KEY_D,
|
||||
E = GLFW_KEY_E,
|
||||
F = GLFW_KEY_F,
|
||||
G = GLFW_KEY_G,
|
||||
H = GLFW_KEY_H,
|
||||
I = GLFW_KEY_I,
|
||||
J = GLFW_KEY_J,
|
||||
K = GLFW_KEY_K,
|
||||
L = GLFW_KEY_L,
|
||||
M = GLFW_KEY_M,
|
||||
N = GLFW_KEY_N,
|
||||
O = GLFW_KEY_O,
|
||||
P = GLFW_KEY_P,
|
||||
Q = GLFW_KEY_Q,
|
||||
R = GLFW_KEY_R,
|
||||
S = GLFW_KEY_S,
|
||||
T = GLFW_KEY_T,
|
||||
U = GLFW_KEY_U,
|
||||
V = GLFW_KEY_V,
|
||||
W = GLFW_KEY_W,
|
||||
X = GLFW_KEY_X,
|
||||
Y = GLFW_KEY_Y,
|
||||
Z = GLFW_KEY_Z,
|
||||
LeftBracket = GLFW_KEY_LEFT_BRACKET,
|
||||
Backslash = GLFW_KEY_BACKSLASH,
|
||||
RightBracket = GLFW_KEY_RIGHT_BRACKET,
|
||||
GraveAccent = GLFW_KEY_GRAVE_ACCENT,
|
||||
World1 = GLFW_KEY_WORLD_1,
|
||||
World2 = GLFW_KEY_WORLD_2,
|
||||
Escape = GLFW_KEY_ESCAPE,
|
||||
Enter = GLFW_KEY_ENTER,
|
||||
Tab = GLFW_KEY_TAB,
|
||||
Backspace = GLFW_KEY_BACKSPACE,
|
||||
Insert = GLFW_KEY_INSERT,
|
||||
Delete = GLFW_KEY_DELETE,
|
||||
Right = GLFW_KEY_RIGHT,
|
||||
Left = GLFW_KEY_LEFT,
|
||||
Down = GLFW_KEY_DOWN,
|
||||
Up = GLFW_KEY_UP,
|
||||
PageUp = GLFW_KEY_PAGE_UP,
|
||||
PageDown = GLFW_KEY_PAGE_DOWN,
|
||||
Home = GLFW_KEY_HOME,
|
||||
End = GLFW_KEY_END,
|
||||
CapsLock = GLFW_KEY_CAPS_LOCK,
|
||||
ScrollLock = GLFW_KEY_SCROLL_LOCK,
|
||||
NumLock = GLFW_KEY_NUM_LOCK,
|
||||
PrintScreen = GLFW_KEY_PRINT_SCREEN,
|
||||
Pause = GLFW_KEY_PAUSE,
|
||||
F1 = GLFW_KEY_F1,
|
||||
F2 = GLFW_KEY_F2,
|
||||
F3 = GLFW_KEY_F3,
|
||||
F4 = GLFW_KEY_F4,
|
||||
F5 = GLFW_KEY_F5,
|
||||
F6 = GLFW_KEY_F6,
|
||||
F7 = GLFW_KEY_F7,
|
||||
F8 = GLFW_KEY_F8,
|
||||
F9 = GLFW_KEY_F9,
|
||||
F10 = GLFW_KEY_F10,
|
||||
F11 = GLFW_KEY_F11,
|
||||
F12 = GLFW_KEY_F12,
|
||||
F13 = GLFW_KEY_F13,
|
||||
F14 = GLFW_KEY_F14,
|
||||
F15 = GLFW_KEY_F15,
|
||||
F16 = GLFW_KEY_F16,
|
||||
F17 = GLFW_KEY_F17,
|
||||
F18 = GLFW_KEY_F18,
|
||||
F19 = GLFW_KEY_F19,
|
||||
F20 = GLFW_KEY_F20,
|
||||
F21 = GLFW_KEY_F21,
|
||||
F22 = GLFW_KEY_F22,
|
||||
F23 = GLFW_KEY_F23,
|
||||
F24 = GLFW_KEY_F24,
|
||||
F25 = GLFW_KEY_F25,
|
||||
KeyPad0 = GLFW_KEY_KP_0,
|
||||
KeyPad1 = GLFW_KEY_KP_1,
|
||||
KeyPad2 = GLFW_KEY_KP_2,
|
||||
KeyPad3 = GLFW_KEY_KP_3,
|
||||
KeyPad4 = GLFW_KEY_KP_4,
|
||||
KeyPad5 = GLFW_KEY_KP_5,
|
||||
KeyPad6 = GLFW_KEY_KP_6,
|
||||
KeyPad7 = GLFW_KEY_KP_7,
|
||||
KeyPad8 = GLFW_KEY_KP_8,
|
||||
KeyPad9 = GLFW_KEY_KP_9,
|
||||
KeyPadDecimal = GLFW_KEY_KP_DECIMAL,
|
||||
KeyPadDivide = GLFW_KEY_KP_DIVIDE,
|
||||
KeyPadMultiply = GLFW_KEY_KP_MULTIPLY,
|
||||
KeyPadSubtract = GLFW_KEY_KP_SUBTRACT,
|
||||
KeyPadAdd = GLFW_KEY_KP_ADD,
|
||||
KeyPadEnter = GLFW_KEY_KP_ENTER,
|
||||
KeyPadEqual = GLFW_KEY_KP_EQUAL,
|
||||
Menu = GLFW_KEY_MENU,
|
||||
};
|
||||
@@ -807,8 +807,6 @@ namespace hex::gl {
|
||||
void bind() const;
|
||||
void unbind() const;
|
||||
|
||||
bool isValid() const { return m_program != 0; }
|
||||
|
||||
void setUniform(std::string_view name, const int &value);
|
||||
void setUniform(std::string_view name, const float &value);
|
||||
|
||||
|
||||
@@ -21,11 +21,6 @@ namespace hex {
|
||||
MissingEOF
|
||||
};
|
||||
|
||||
enum class PatchKind {
|
||||
IPS,
|
||||
IPS32
|
||||
};
|
||||
|
||||
class Patches {
|
||||
public:
|
||||
Patches() = default;
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <compare>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace hex {
|
||||
|
||||
class SemanticVersion {
|
||||
public:
|
||||
SemanticVersion() = default;
|
||||
SemanticVersion(std::string version);
|
||||
SemanticVersion(std::string_view version);
|
||||
SemanticVersion(const char *version);
|
||||
|
||||
std::strong_ordering operator<=>(const SemanticVersion &) const;
|
||||
bool operator==(const SemanticVersion &other) const;
|
||||
|
||||
u32 major() const;
|
||||
u32 minor() const;
|
||||
u32 patch() const;
|
||||
bool nightly() const;
|
||||
const std::string& buildType() const;
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
std::string get(bool withBuildType = true) const;
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_parts;
|
||||
std::string m_buildType;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -29,7 +29,7 @@ namespace hex {
|
||||
void close();
|
||||
|
||||
/**
|
||||
* @brief get the error string explaining the error that occurred when opening the file.
|
||||
* @brief get the error string explaining the error that occured when opening the file.
|
||||
* This error is a combination of the tar error and the native file open error
|
||||
*/
|
||||
std::string getOpenErrorString() const;
|
||||
@@ -59,4 +59,4 @@ namespace hex {
|
||||
int m_fileOpenErrno = 0;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <cstdint>
|
||||
|
||||
#include <concepts>
|
||||
#include <type_traits>
|
||||
|
||||
using u8 = std::uint8_t;
|
||||
using u16 = std::uint16_t;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <hex/helpers/utils_linux.hpp>
|
||||
#endif
|
||||
|
||||
#include <imgui.h>
|
||||
struct ImVec2;
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -34,29 +34,6 @@ namespace hex {
|
||||
class Provider;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] std::vector<std::vector<T>> sampleChannels(const std::vector<T> &data, size_t count, size_t channels) {
|
||||
if (channels == 0) return {};
|
||||
size_t signalLength = std::max(1.0, double(data.size()) / channels);
|
||||
|
||||
size_t stride = std::max(1.0, double(signalLength) / count);
|
||||
|
||||
std::vector<std::vector<T>> result;
|
||||
result.resize(channels);
|
||||
for (size_t i = 0; i < channels; i++) {
|
||||
result[i].reserve(count);
|
||||
}
|
||||
result.reserve(count);
|
||||
|
||||
for (size_t i = 0; i < data.size(); i += stride) {
|
||||
for (size_t j = 0; j < channels; j++) {
|
||||
result[j].push_back(data[i + j]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] std::vector<T> sampleData(const std::vector<T> &data, size_t count) {
|
||||
size_t stride = std::max(1.0, double(data.size()) / count);
|
||||
@@ -285,13 +262,13 @@ namespace hex {
|
||||
|
||||
[[nodiscard]] float float16ToFloat32(u16 float16);
|
||||
|
||||
[[nodiscard]] inline bool equalsIgnoreCase(std::string_view left, std::string_view right) {
|
||||
[[nodiscard]] inline bool equalsIgnoreCase(const std::string &left, const std::string &right) {
|
||||
return std::equal(left.begin(), left.end(), right.begin(), right.end(), [](char a, char b) {
|
||||
return tolower(a) == tolower(b);
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool containsIgnoreCase(std::string_view a, std::string_view b) {
|
||||
[[nodiscard]] inline bool containsIgnoreCase(const std::string &a, const std::string &b) {
|
||||
auto iter = std::search(a.begin(), a.end(), b.begin(), b.end(), [](char ch1, char ch2) {
|
||||
return std::toupper(ch1) == std::toupper(ch2);
|
||||
});
|
||||
@@ -340,6 +317,4 @@ namespace hex {
|
||||
*/
|
||||
[[nodiscard]] void* getContainingModule(void* symbol);
|
||||
|
||||
[[nodiscard]] std::optional<ImColor> blendColors(const std::optional<ImColor> &a, const std::optional<ImColor> &b);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/helpers/keys.hpp>
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
|
||||
struct GLFWwindow;
|
||||
@@ -19,11 +17,8 @@
|
||||
void enumerateFontsMacos();
|
||||
|
||||
void macosHandleTitlebarDoubleClickGesture(GLFWwindow *window);
|
||||
void macosSetWindowMovable(GLFWwindow *window, bool movable);
|
||||
bool macosIsWindowBeingResizedByUser(GLFWwindow *window);
|
||||
void macosMarkContentEdited(GLFWwindow *window, bool edited = true);
|
||||
|
||||
void macosGetKey(Keys key, int *output);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -70,7 +70,7 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
|
||||
#define IMHEX_LIBRARY_SETUP(name) IMHEX_LIBRARY_SETUP_IMPL(name)
|
||||
|
||||
#define IMHEX_LIBRARY_SETUP_IMPL(name) \
|
||||
namespace { static struct EXIT_HANDLER { ~EXIT_HANDLER() { hex::log::info("Unloaded library '{}'", name); } } HANDLER; } \
|
||||
namespace { static struct EXIT_HANDLER { ~EXIT_HANDLER() { hex::log::debug("Unloaded library '{}'", name); } } HANDLER; } \
|
||||
IMHEX_PLUGIN_VISIBILITY_PREFIX void WOLV_TOKEN_CONCAT(initializeLibrary_, IMHEX_PLUGIN_NAME)(); \
|
||||
IMHEX_PLUGIN_VISIBILITY_PREFIX const char *WOLV_TOKEN_CONCAT(getLibraryName_, IMHEX_PLUGIN_NAME)() { return name; } \
|
||||
IMHEX_PLUGIN_VISIBILITY_PREFIX void WOLV_TOKEN_CONCAT(setImGuiContext_, IMHEX_PLUGIN_NAME)(ImGuiContext *ctx) { \
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace hex::prv {
|
||||
|
||||
[[nodiscard]] std::string getName() const override { return m_name; }
|
||||
|
||||
[[nodiscard]] UnlocalizedString getTypeName() const override { return "MemoryProvider"; }
|
||||
[[nodiscard]] std::string getTypeName() const override { return "MemoryProvider"; }
|
||||
private:
|
||||
void renameFile();
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ namespace hex::prv {
|
||||
|
||||
struct MenuEntry {
|
||||
std::string name;
|
||||
const char *icon;
|
||||
std::function<void()> callback;
|
||||
};
|
||||
|
||||
@@ -152,7 +151,7 @@ namespace hex::prv {
|
||||
* like "hex.builtin.provider.mem_file" or "hex.builtin.provider.file"
|
||||
* @return The provider's type name
|
||||
*/
|
||||
[[nodiscard]] virtual UnlocalizedString getTypeName() const = 0;
|
||||
[[nodiscard]] virtual std::string getTypeName() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Gets a human readable representation of the current provider
|
||||
@@ -166,7 +165,7 @@ namespace hex::prv {
|
||||
void insert(u64 offset, u64 size);
|
||||
void remove(u64 offset, u64 size);
|
||||
|
||||
virtual void resizeRaw(u64 newSize) { std::ignore = newSize; }
|
||||
virtual void resizeRaw(u64 newSize) { hex::unused(newSize); }
|
||||
virtual void insertRaw(u64 offset, u64 size);
|
||||
virtual void removeRaw(u64 offset, u64 size);
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/events/events_provider.hpp>
|
||||
#include <hex/api/events/events_lifecycle.hpp>
|
||||
#include <hex/api/events/requests_provider.hpp>
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <ranges>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/api/events/events_interaction.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
#include <hex/providers/undo_redo/operations/operation.hpp>
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace hex::test {
|
||||
return m_data->size();
|
||||
}
|
||||
|
||||
[[nodiscard]] UnlocalizedString getTypeName() const override { return "hex.test.provider.test"; }
|
||||
[[nodiscard]] std::string getTypeName() const override { return "hex.test.provider.test"; }
|
||||
|
||||
bool open() override { return true; }
|
||||
void close() override { }
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include "hex/api/localization_manager.hpp"
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace impl {
|
||||
|
||||
class BannerBase {
|
||||
public:
|
||||
BannerBase(ImColor color) : m_color(color) {}
|
||||
virtual ~BannerBase() = default;
|
||||
|
||||
virtual void draw() { drawContent(); }
|
||||
virtual void drawContent() = 0;
|
||||
|
||||
[[nodiscard]] static std::list<std::unique_ptr<BannerBase>> &getOpenBanners();
|
||||
|
||||
[[nodiscard]] const ImColor& getColor() const {
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void close() { m_shouldClose = true; }
|
||||
[[nodiscard]] bool shouldClose() const { return m_shouldClose; }
|
||||
|
||||
protected:
|
||||
static std::mutex& getMutex();
|
||||
|
||||
bool m_shouldClose = false;
|
||||
ImColor m_color;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class Banner : public impl::BannerBase {
|
||||
public:
|
||||
using impl::BannerBase::BannerBase;
|
||||
|
||||
template<typename ...Args>
|
||||
static void open(Args && ... args) {
|
||||
std::lock_guard lock(getMutex());
|
||||
|
||||
auto toast = std::make_unique<T>(std::forward<Args>(args)...);
|
||||
getOpenBanners().emplace_back(std::move(toast));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -79,16 +79,16 @@ namespace ImGuiExt {
|
||||
Texture(const Texture&) = delete;
|
||||
Texture(Texture&& other) noexcept;
|
||||
|
||||
[[nodiscard]] static Texture fromImage(const ImU8 *buffer, int size, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromImage(std::span<const std::byte> buffer, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromImage(const char *path, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromImage(const std::fs::path &path, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromGLTexture(unsigned int texture, int width, int height);
|
||||
[[nodiscard]] static Texture fromBitmap(const ImU8 *buffer, int size, int width, int height, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromBitmap(std::span<const std::byte> buffer, int width, int height, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromSVG(const char *path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromSVG(const std::fs::path &path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromSVG(std::span<const std::byte> buffer, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
static Texture fromImage(const ImU8 *buffer, int size, Filter filter = Filter::Nearest);
|
||||
static Texture fromImage(std::span<const std::byte> buffer, Filter filter = Filter::Nearest);
|
||||
static Texture fromImage(const char *path, Filter filter = Filter::Nearest);
|
||||
static Texture fromImage(const std::fs::path &path, Filter filter = Filter::Nearest);
|
||||
static Texture fromGLTexture(unsigned int texture, int width, int height);
|
||||
static Texture fromBitmap(const ImU8 *buffer, int size, int width, int height, Filter filter = Filter::Nearest);
|
||||
static Texture fromBitmap(std::span<const std::byte> buffer, int width, int height, Filter filter = Filter::Nearest);
|
||||
static Texture fromSVG(const char *path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
static Texture fromSVG(const std::fs::path &path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
static Texture fromSVG(std::span<const std::byte> buffer, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
|
||||
|
||||
~Texture();
|
||||
@@ -97,25 +97,29 @@ namespace ImGuiExt {
|
||||
Texture& operator=(Texture&& other) noexcept;
|
||||
|
||||
[[nodiscard]] constexpr bool isValid() const noexcept {
|
||||
return m_textureId != 0;
|
||||
return m_textureId != nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] operator ImTextureID() const noexcept {
|
||||
return m_textureId;
|
||||
}
|
||||
|
||||
[[nodiscard]] ImVec2 getSize() const noexcept {
|
||||
[[nodiscard]] operator intptr_t() const noexcept {
|
||||
return reinterpret_cast<intptr_t>(m_textureId);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto getSize() const noexcept {
|
||||
return ImVec2(m_width, m_height);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr float getAspectRatio() const noexcept {
|
||||
[[nodiscard]] constexpr auto getAspectRatio() const noexcept {
|
||||
if (m_height == 0) return 1.0F;
|
||||
|
||||
return float(m_width) / float(m_height);
|
||||
}
|
||||
|
||||
private:
|
||||
ImTextureID m_textureId = 0;
|
||||
ImTextureID m_textureId = nullptr;
|
||||
int m_width = 0, m_height = 0;
|
||||
};
|
||||
|
||||
@@ -133,8 +137,6 @@ namespace ImGuiExt {
|
||||
|
||||
void UnderlinedText(const char *label, ImColor color = ImGui::GetStyleColorVec4(ImGuiCol_Text), const ImVec2 &size_arg = ImVec2(0, 0));
|
||||
|
||||
void UnderwavedText(const char *label, ImColor textColor = ImGui::GetStyleColorVec4(ImGuiCol_Text), ImColor lineColor = ImGui::GetStyleColorVec4(ImGuiCol_Text), const ImVec2 &size_arg = ImVec2(0, 0));
|
||||
|
||||
void TextSpinner(const char *label);
|
||||
|
||||
void Header(const char *label, bool firstEntry = false);
|
||||
@@ -144,13 +146,13 @@ namespace ImGuiExt {
|
||||
|
||||
bool TitleBarButton(const char *label, ImVec2 size_arg);
|
||||
bool ToolBarButton(const char *symbol, ImVec4 color);
|
||||
bool IconButton(const char *symbol, ImVec4 color, ImVec2 size_arg = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
|
||||
bool IconButton(const char *symbol, ImVec4 color, ImVec2 size_arg = ImVec2(0, 0));
|
||||
|
||||
bool InputIntegerPrefix(const char* label, const char *prefix, void *value, ImGuiDataType type, const char *format, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||
bool InputHexadecimal(const char* label, u32 *value, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||
bool InputHexadecimal(const char* label, u64 *value, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||
|
||||
bool SliderBytes(const char *label, u64 *value, u64 min, u64 max, u64 stepSize = 1, ImGuiSliderFlags flags = ImGuiSliderFlags_None);
|
||||
bool SliderBytes(const char *label, u64 *value, u64 min, u64 max, ImGuiSliderFlags flags = ImGuiSliderFlags_None);
|
||||
|
||||
inline bool HasSecondPassed() {
|
||||
return static_cast<ImU32>(ImGui::GetTime() * 100) % 100 <= static_cast<ImU32>(ImGui::GetIO().DeltaTime * 100);
|
||||
@@ -203,7 +205,7 @@ namespace ImGuiExt {
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4());
|
||||
|
||||
ImGui::PushItemWidth(ImGui::CalcTextSize(text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2);
|
||||
ImGui::InputText("##", const_cast<char *>(text.c_str()), text.size() + 1, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoHorizontalScroll);
|
||||
ImGui::InputText("##", const_cast<char *>(text.c_str()), text.size(), ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoHorizontalScroll);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
@@ -235,13 +237,11 @@ namespace ImGuiExt {
|
||||
|
||||
inline void TextFormattedWrappedSelectable(std::string_view fmt, auto &&...args) {
|
||||
// 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::wrapMonospacedString(
|
||||
hex::format(fmt, std::forward<decltype(args)>(args)...),
|
||||
ImGui::CalcTextSize("M").x,
|
||||
ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize - ImGui::GetStyle().FrameBorderSize
|
||||
));
|
||||
|
||||
auto textSize = ImGui::CalcTextSize(text.c_str());
|
||||
);
|
||||
|
||||
ImGui::PushID(text.c_str());
|
||||
|
||||
@@ -252,8 +252,8 @@ namespace ImGuiExt {
|
||||
ImGui::InputTextMultiline(
|
||||
"##",
|
||||
const_cast<char *>(text.c_str()),
|
||||
text.size() + 1,
|
||||
ImVec2(0, textSize.y),
|
||||
text.size(),
|
||||
ImVec2(0, -FLT_MIN),
|
||||
ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoHorizontalScroll
|
||||
);
|
||||
ImGui::PopItemWidth();
|
||||
@@ -284,7 +284,6 @@ namespace ImGuiExt {
|
||||
}
|
||||
|
||||
bool InputTextIcon(const char* label, const char *icon, std::string &buffer, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||
bool InputTextIconHint(const char* label, const char *icon, const char *hint, std::string &buffer, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||
|
||||
bool InputScalarCallback(const char* label, ImGuiDataType data_type, void* p_data, const char* format, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data);
|
||||
|
||||
@@ -293,12 +292,12 @@ namespace ImGuiExt {
|
||||
bool BitCheckbox(const char* label, bool* v);
|
||||
|
||||
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 DimmedButtonToggle(const char *icon, bool *v, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
|
||||
bool DimmedIconButton(const char *symbol, ImVec4 color, ImVec2 size = ImVec2(0, 0));
|
||||
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size);
|
||||
bool DimmedIconToggle(const char *icon, bool *v);
|
||||
bool DimmedIconToggle(const char *iconOn, const char *iconOff, bool *v);
|
||||
|
||||
void TextOverlay(const char *text, ImVec2 pos, float maxWidth = -1);
|
||||
void TextOverlay(const char *text, ImVec2 pos);
|
||||
|
||||
bool BeginBox();
|
||||
void EndBox();
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/shortcut_manager.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
#include <hex/api/achievement_manager.hpp>
|
||||
#include <hex/api/events/events_interaction.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
#include <hex/helpers/auto_reset.hpp>
|
||||
#include <hex/helpers/default_paths.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#if defined(OS_WEB)
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
namespace hex {
|
||||
|
||||
static AutoReset<std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>>> s_achievements;
|
||||
@@ -200,11 +196,8 @@ namespace hex {
|
||||
|
||||
|
||||
constexpr static auto AchievementsFile = "achievements.json";
|
||||
bool AchievementManager::s_initialized = false;
|
||||
|
||||
void AchievementManager::loadProgress() {
|
||||
if (s_initialized)
|
||||
return;
|
||||
for (const auto &directory : paths::Config.read()) {
|
||||
auto path = directory / AchievementsFile;
|
||||
|
||||
@@ -219,16 +212,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
try {
|
||||
#if defined(OS_WEB)
|
||||
auto data = (char *) MAIN_THREAD_EM_ASM_INT({
|
||||
let data = localStorage.getItem("achievements");
|
||||
return data ? stringToNewUTF8(data) : null;
|
||||
});
|
||||
#else
|
||||
auto data = file.readString();
|
||||
#endif
|
||||
|
||||
auto json = nlohmann::json::parse(data);
|
||||
auto json = nlohmann::json::parse(file.readString());
|
||||
|
||||
for (const auto &[categoryName, achievements] : getAchievements()) {
|
||||
for (const auto &[achievementName, achievement] : achievements) {
|
||||
@@ -243,8 +227,6 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_initialized = true;
|
||||
} catch (const std::exception &e) {
|
||||
log::error("Failed to load achievements: {}", e.what());
|
||||
}
|
||||
@@ -253,8 +235,6 @@ namespace hex {
|
||||
}
|
||||
|
||||
void AchievementManager::storeProgress() {
|
||||
if (!s_initialized)
|
||||
loadProgress();
|
||||
nlohmann::json json;
|
||||
for (const auto &[categoryName, achievements] : getAchievements()) {
|
||||
json[categoryName] = nlohmann::json::object();
|
||||
@@ -267,23 +247,16 @@ namespace hex {
|
||||
if (json.empty())
|
||||
return;
|
||||
|
||||
#if defined(OS_WEB)
|
||||
auto data = json.dump();
|
||||
MAIN_THREAD_EM_ASM({
|
||||
localStorage.setItem("achievements", UTF8ToString($0));
|
||||
}, data.c_str());
|
||||
#else
|
||||
for (const auto &directory : paths::Config.write()) {
|
||||
auto path = directory / AchievementsFile;
|
||||
for (const auto &directory : paths::Config.write()) {
|
||||
auto path = directory / AchievementsFile;
|
||||
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||
if (!file.isValid())
|
||||
continue;
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||
if (!file.isValid())
|
||||
continue;
|
||||
|
||||
file.writeString(json.dump(4));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
file.writeString(json.dump(4));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/shortcut_manager.hpp>
|
||||
#include <hex/api/events/requests_provider.hpp>
|
||||
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
@@ -39,34 +38,6 @@ namespace hex {
|
||||
|
||||
static AutoReset<std::map<std::string, std::map<std::string, std::vector<OnChange>>>> s_onChangeCallbacks;
|
||||
|
||||
static void runAllOnChangeCallbacks() {
|
||||
for (const auto &[category, rest] : *impl::s_onChangeCallbacks) {
|
||||
for (const auto &[name, callbacks] : rest) {
|
||||
for (const auto &[id, callback] : callbacks) {
|
||||
try {
|
||||
callback(getSetting(category, name, {}));
|
||||
} catch (const std::exception &e) {
|
||||
log::error("Failed to load setting [{}/{}]: {}", category, name, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void runOnChangeHandlers(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const nlohmann::json &value) {
|
||||
if (auto categoryIt = s_onChangeCallbacks->find(unlocalizedCategory); categoryIt != s_onChangeCallbacks->end()) {
|
||||
if (auto nameIt = categoryIt->second.find(unlocalizedName); nameIt != categoryIt->second.end()) {
|
||||
for (const auto &[id, callback] : nameIt->second) {
|
||||
try {
|
||||
callback(value);
|
||||
} catch (const nlohmann::json::exception &e) {
|
||||
log::error("Failed to run onChange handler for setting {}/{}: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static AutoReset<nlohmann::json> s_settings;
|
||||
const nlohmann::json& getSettingsData() {
|
||||
return s_settings;
|
||||
@@ -101,28 +72,24 @@ namespace hex {
|
||||
s_settings = nlohmann::json::parse(data);
|
||||
}
|
||||
|
||||
runAllOnChangeCallbacks();
|
||||
for (const auto &[category, rest] : *impl::s_onChangeCallbacks) {
|
||||
for (const auto &[name, callbacks] : rest) {
|
||||
for (const auto &[id, callback] : callbacks) {
|
||||
try {
|
||||
callback(getSetting(category, name, {}));
|
||||
} catch (const std::exception &e) {
|
||||
log::error("Failed to load setting [{}/{}]: {}", category, name, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void store() {
|
||||
if (!s_settings.isValid())
|
||||
return;
|
||||
|
||||
const auto &settingsData = *s_settings;
|
||||
|
||||
// During a crash settings can be empty, causing them to be overwritten.
|
||||
if (settingsData.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto result = settingsData.dump(4);
|
||||
if (result.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto data = s_settings->dump();
|
||||
MAIN_THREAD_EM_ASM({
|
||||
localStorage.setItem("config", UTF8ToString($0));
|
||||
}, result.c_str());
|
||||
}, data.c_str());
|
||||
}
|
||||
|
||||
void clear() {
|
||||
@@ -148,7 +115,17 @@ namespace hex {
|
||||
if (!loaded)
|
||||
store();
|
||||
|
||||
runAllOnChangeCallbacks();
|
||||
for (const auto &[category, rest] : *impl::s_onChangeCallbacks) {
|
||||
for (const auto &[name, callbacks] : rest) {
|
||||
for (const auto &[id, callback] : callbacks) {
|
||||
try {
|
||||
callback(getSetting(category, name, {}));
|
||||
} catch (const std::exception &e) {
|
||||
log::error("Failed to load setting [{}/{}]: {}", category, name, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void store() {
|
||||
@@ -158,7 +135,7 @@ namespace hex {
|
||||
const auto &settingsData = *s_settings;
|
||||
|
||||
// During a crash settings can be empty, causing them to be overwritten.
|
||||
if (s_settings->empty()) {
|
||||
if (settingsData.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -214,19 +191,6 @@ namespace hex {
|
||||
const auto entry = insertOrGetEntry(subCategory->entries, unlocalizedName);
|
||||
|
||||
entry->widget = std::move(widget);
|
||||
if (entry->widget != nullptr) {
|
||||
onChange(unlocalizedCategory, unlocalizedName, [widget = entry->widget.get(), unlocalizedCategory, unlocalizedName](const SettingsValue &) {
|
||||
try {
|
||||
auto defaultValue = widget->store();
|
||||
widget->load(ContentRegistry::Settings::impl::getSetting(unlocalizedCategory, unlocalizedName, defaultValue));
|
||||
widget->onChanged();
|
||||
} catch (const std::exception &e) {
|
||||
log::error("Failed to load setting [{} / {}]: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
|
||||
}
|
||||
});
|
||||
|
||||
runOnChangeHandlers(unlocalizedCategory, unlocalizedName, getSetting(unlocalizedCategory, unlocalizedName, entry->widget->store()));
|
||||
}
|
||||
|
||||
return entry->widget.get();
|
||||
}
|
||||
@@ -235,6 +199,20 @@ namespace hex {
|
||||
hex::log::error("Failed to read setting {}/{}: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
|
||||
}
|
||||
|
||||
void runOnChangeHandlers(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const nlohmann::json &value) {
|
||||
if (auto categoryIt = s_onChangeCallbacks->find(unlocalizedCategory); categoryIt != s_onChangeCallbacks->end()) {
|
||||
if (auto nameIt = categoryIt->second.find(unlocalizedName); nameIt != categoryIt->second.end()) {
|
||||
for (const auto &[id, callback] : nameIt->second) {
|
||||
try {
|
||||
callback(value);
|
||||
} catch (const nlohmann::json::exception &e) {
|
||||
log::error("Failed to run onChange handler for setting {}/{}: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void setCategoryDescription(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedDescription) {
|
||||
@@ -336,7 +314,7 @@ namespace hex {
|
||||
|
||||
|
||||
bool SliderDataSize::draw(const std::string &name) {
|
||||
return ImGuiExt::SliderBytes(name.c_str(), &m_value, m_min, m_max, m_stepSize);
|
||||
return ImGuiExt::SliderBytes(name.c_str(), &m_value, m_min, m_max);
|
||||
}
|
||||
|
||||
void SliderDataSize::load(const nlohmann::json &data) {
|
||||
@@ -352,34 +330,17 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
ColorPicker::ColorPicker(ImColor defaultColor, ImGuiColorEditFlags flags) {
|
||||
m_defaultValue = m_value = {
|
||||
defaultColor.Value.x,
|
||||
defaultColor.Value.y,
|
||||
defaultColor.Value.z,
|
||||
defaultColor.Value.w
|
||||
ColorPicker::ColorPicker(ImColor defaultColor) {
|
||||
m_value = {
|
||||
defaultColor.Value.x,
|
||||
defaultColor.Value.y,
|
||||
defaultColor.Value.z,
|
||||
defaultColor.Value.w
|
||||
};
|
||||
m_flags = flags;
|
||||
}
|
||||
|
||||
bool ColorPicker::draw(const std::string &name) {
|
||||
ImGui::PushID(name.c_str());
|
||||
auto result = ImGui::ColorEdit4("##color_picker", m_value.data(), ImGuiColorEditFlags_NoInputs | m_flags);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("X", ImGui::GetStyle().FramePadding * 2 + ImVec2(ImGui::GetTextLineHeight(), ImGui::GetTextLineHeight()))) {
|
||||
m_value = m_defaultValue;
|
||||
result = true;
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::TextUnformatted(name.c_str());
|
||||
|
||||
ImGui::PopID();
|
||||
|
||||
return result;
|
||||
return ImGui::ColorEdit4(name.c_str(), m_value.data(), ImGuiColorEditFlags_NoInputs);
|
||||
}
|
||||
|
||||
void ColorPicker::load(const nlohmann::json &data) {
|
||||
@@ -405,7 +366,7 @@ namespace hex {
|
||||
bool DropDown::draw(const std::string &name) {
|
||||
auto preview = "";
|
||||
if (static_cast<size_t>(m_value) < m_items.size())
|
||||
preview = m_items[m_value].get().c_str();
|
||||
preview = m_items[m_value].c_str();
|
||||
|
||||
bool changed = false;
|
||||
if (ImGui::BeginCombo(name.c_str(), Lang(preview))) {
|
||||
@@ -591,11 +552,6 @@ namespace hex {
|
||||
return *s_functions;
|
||||
}
|
||||
|
||||
static AutoReset<std::vector<TypeDefinition>> s_types;
|
||||
const std::vector<TypeDefinition>& getTypes() {
|
||||
return *s_types;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static std::string getFunctionName(const pl::api::Namespace &ns, const std::string &name) {
|
||||
@@ -649,16 +605,12 @@ namespace hex {
|
||||
runtime.addFunction(ns, name, paramCount, callback);
|
||||
}
|
||||
|
||||
for (const auto &[ns, name, paramCount, callback] : impl::getTypes()) {
|
||||
runtime.addType(ns, name, paramCount, callback);
|
||||
}
|
||||
|
||||
for (const auto &[name, callback] : impl::getPragmas()) {
|
||||
runtime.addPragma(name, callback);
|
||||
}
|
||||
|
||||
runtime.addDefine("__IMHEX__");
|
||||
runtime.addDefine("__IMHEX_VERSION__", ImHexApi::System::getImHexVersion().get());
|
||||
runtime.addDefine("__IMHEX_VERSION__", ImHexApi::System::getImHexVersion());
|
||||
}
|
||||
|
||||
void addPragma(const std::string &name, const pl::api::PragmaHandler &handler) {
|
||||
@@ -687,15 +639,6 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
void addType(const pl::api::Namespace &ns, const std::string &name, pl::api::FunctionParameterCount parameterCount, const pl::api::TypeCallback &func) {
|
||||
log::debug("Registered new pattern language type: {}", getFunctionName(ns, name));
|
||||
|
||||
impl::s_types->push_back({
|
||||
ns, name,
|
||||
parameterCount, func
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount) {
|
||||
log::debug("Registered new pattern visualizer function: {}", name);
|
||||
@@ -780,14 +723,6 @@ namespace hex {
|
||||
impl::s_entries->push_back({ unlocalizedName, requiredSize, maxSize, std::move(displayGeneratorFunction), std::move(editingFunction) });
|
||||
}
|
||||
|
||||
void drawMenuItems(const std::function<void()> &function) {
|
||||
if (ImGui::BeginPopup("##DataInspectorRowContextMenu")) {
|
||||
function();
|
||||
ImGui::Separator();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::DataProcessorNode {
|
||||
@@ -949,14 +884,14 @@ namespace hex {
|
||||
coloredIcon.color = ImGuiCustomCol_ToolbarGray;
|
||||
|
||||
impl::s_menuItems->insert({
|
||||
priority, impl::MenuItem { unlocalizedMainMenuNames, coloredIcon, shortcut, view, function, enabledCallback, selectedCallback, -1 }
|
||||
priority, impl::MenuItem { unlocalizedMainMenuNames, coloredIcon, std::make_unique<Shortcut>(shortcut), view, function, enabledCallback, selectedCallback, -1 }
|
||||
});
|
||||
|
||||
if (shortcut != Shortcut::None) {
|
||||
if (shortcut.isLocal() && view != nullptr)
|
||||
ShortcutManager::addShortcut(view, shortcut, unlocalizedMainMenuNames, function, enabledCallback);
|
||||
ShortcutManager::addShortcut(view, shortcut, unlocalizedMainMenuNames.back(), function);
|
||||
else
|
||||
ShortcutManager::addGlobalShortcut(shortcut, unlocalizedMainMenuNames, function, enabledCallback);
|
||||
ShortcutManager::addGlobalShortcut(shortcut, unlocalizedMainMenuNames.back(), function);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -969,14 +904,14 @@ namespace hex {
|
||||
|
||||
unlocalizedMainMenuNames.emplace_back(impl::SubMenuValue);
|
||||
impl::s_menuItems->insert({
|
||||
priority, impl::MenuItem { unlocalizedMainMenuNames, icon, Shortcut::None, nullptr, function, enabledCallback, []{ return false; }, -1 }
|
||||
priority, impl::MenuItem { unlocalizedMainMenuNames, icon, std::make_unique<Shortcut>(), nullptr, function, enabledCallback, []{ return false; }, -1 }
|
||||
});
|
||||
}
|
||||
|
||||
void addMenuItemSeparator(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority) {
|
||||
unlocalizedMainMenuNames.emplace_back(impl::SeparatorValue);
|
||||
impl::s_menuItems->insert({
|
||||
priority, impl::MenuItem { unlocalizedMainMenuNames, "", Shortcut::None, nullptr, []{}, []{ return true; }, []{ return false; }, -1 }
|
||||
priority, impl::MenuItem { unlocalizedMainMenuNames, "", std::make_unique<Shortcut>(), nullptr, []{}, []{ return true; }, []{ return false; }, -1 }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1264,7 +1199,7 @@ namespace hex {
|
||||
|
||||
class Service {
|
||||
public:
|
||||
Service(const UnlocalizedString &unlocalizedName, std::jthread thread) : m_unlocalizedName(std::move(unlocalizedName)), m_thread(std::move(thread)) { }
|
||||
Service(std::string name, std::jthread thread) : m_name(std::move(name)), m_thread(std::move(thread)) { }
|
||||
Service(const Service&) = delete;
|
||||
Service(Service &&) = default;
|
||||
~Service() {
|
||||
@@ -1276,8 +1211,8 @@ namespace hex {
|
||||
Service& operator=(const Service&) = delete;
|
||||
Service& operator=(Service &&) = default;
|
||||
|
||||
[[nodiscard]] const UnlocalizedString& getUnlocalizedName() const {
|
||||
return m_unlocalizedName;
|
||||
[[nodiscard]] const std::string& getName() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::jthread& getThread() const {
|
||||
@@ -1285,7 +1220,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
private:
|
||||
UnlocalizedString m_unlocalizedName;
|
||||
std::string m_name;
|
||||
std::jthread m_thread;
|
||||
};
|
||||
|
||||
@@ -1420,23 +1355,4 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::Disassembler {
|
||||
|
||||
namespace impl {
|
||||
|
||||
static AutoReset<std::map<std::string, impl::CreatorFunction>> s_architectures;
|
||||
|
||||
void addArchitectureCreator(impl::CreatorFunction function) {
|
||||
const auto arch = function();
|
||||
(*s_architectures)[arch->getName()] = std::move(function);
|
||||
}
|
||||
|
||||
const std::map<std::string, impl::CreatorFunction>& getArchitectures() {
|
||||
return *s_architectures;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,30 +21,4 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
bool EventManager::isAlreadyRegistered(void *token, impl::EventId id) {
|
||||
if (getTokenStore().contains(token)) {
|
||||
auto&& [begin, end] = getTokenStore().equal_range(token);
|
||||
|
||||
return std::any_of(begin, end, [&](auto &item) {
|
||||
return item.second->first == id;
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void EventManager::unsubscribe(void *token, impl::EventId id) {
|
||||
auto &tokenStore = getTokenStore();
|
||||
auto iter = std::find_if(tokenStore.begin(), tokenStore.end(), [&](auto &item) {
|
||||
return item.first == token && item.second->first == id;
|
||||
});
|
||||
|
||||
if (iter != tokenStore.end()) {
|
||||
getEvents().erase(iter->second);
|
||||
tokenStore.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,13 +1,6 @@
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
|
||||
#include <hex/api/events/events_provider.hpp>
|
||||
#include <hex/api/events/events_lifecycle.hpp>
|
||||
#include <hex/api/events/events_gui.hpp>
|
||||
#include <hex/api/events/requests_interaction.hpp>
|
||||
#include <hex/api/events/requests_lifecycle.hpp>
|
||||
#include <hex/api/events/requests_provider.hpp>
|
||||
#include <hex/api/events/requests_gui.hpp>
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
@@ -18,7 +11,6 @@
|
||||
#include <wolv/utils/string.hpp>
|
||||
|
||||
#include <utility>
|
||||
#include <numeric>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
@@ -26,20 +18,13 @@
|
||||
#include <algorithm>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <hex/helpers/utils_macos.hpp>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#include <windows.h>
|
||||
#include <DSRole.h>
|
||||
#else
|
||||
#include <sys/utsname.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(OS_WEB)
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
namespace hex {
|
||||
|
||||
|
||||
@@ -283,7 +268,7 @@ namespace hex {
|
||||
|
||||
static i64 s_currentProvider = -1;
|
||||
static AutoReset<std::vector<std::unique_ptr<prv::Provider>>> s_providers;
|
||||
static AutoReset<std::map<prv::Provider*, std::unique_ptr<prv::Provider>>> s_providersToRemove;
|
||||
static AutoReset<std::list<std::unique_ptr<prv::Provider>>> s_providersToRemove;
|
||||
|
||||
namespace impl {
|
||||
|
||||
@@ -352,11 +337,8 @@ namespace hex {
|
||||
}
|
||||
|
||||
void markDirty() {
|
||||
const auto provider = get();
|
||||
if (!provider->isDirty()) {
|
||||
provider->markDirty();
|
||||
EventProviderDirtied::post(provider);
|
||||
}
|
||||
get()->markDirty();
|
||||
EventProviderDirtied::post(get());
|
||||
}
|
||||
|
||||
void resetDirty() {
|
||||
@@ -448,8 +430,7 @@ namespace hex {
|
||||
|
||||
// Move provider over to a list of providers to delete
|
||||
eraseMutex.lock();
|
||||
auto providerToRemove = it->get();
|
||||
(*s_providersToRemove)[providerToRemove] = std::move(*it);
|
||||
auto removeIt = s_providersToRemove->emplace(s_providersToRemove->end(), std::move(*it));
|
||||
eraseMutex.unlock();
|
||||
|
||||
// Remove left over references from the main provider list
|
||||
@@ -462,16 +443,16 @@ namespace hex {
|
||||
if (s_providers->empty())
|
||||
EventProviderChanged::post(provider, nullptr);
|
||||
|
||||
EventProviderClosed::post(it->get());
|
||||
EventProviderClosed::post(removeIt->get());
|
||||
RequestUpdateWindowTitle::post();
|
||||
|
||||
// Do the destruction of the provider in the background once all tasks have finished
|
||||
TaskManager::runWhenTasksFinished([providerToRemove] {
|
||||
EventProviderDeleted::post(providerToRemove);
|
||||
TaskManager::createBackgroundTask("Closing Provider", [providerToRemove](Task &) {
|
||||
TaskManager::runWhenTasksFinished([removeIt] {
|
||||
EventProviderDeleted::post(removeIt->get());
|
||||
TaskManager::createBackgroundTask("Closing Provider", [removeIt](Task &) {
|
||||
eraseMutex.lock();
|
||||
auto provider = std::move((*s_providersToRemove)[providerToRemove]);
|
||||
s_providersToRemove->erase(providerToRemove);
|
||||
auto provider = std::move(*removeIt);
|
||||
s_providersToRemove->erase(removeIt);
|
||||
eraseMutex.unlock();
|
||||
|
||||
provider->close();
|
||||
@@ -623,27 +604,6 @@ namespace hex {
|
||||
return impl::s_nativeScale;
|
||||
}
|
||||
|
||||
float getBackingScaleFactor() {
|
||||
#if defined(OS_WINDOWS)
|
||||
return 1.0F;
|
||||
#elif defined(OS_MACOS)
|
||||
return ::getBackingScaleFactor();
|
||||
#elif defined(OS_LINUX)
|
||||
if (std::string_view(::getenv("XDG_SESSION_TYPE")) == "x11")
|
||||
return 1.0F;
|
||||
else {
|
||||
float xScale = 0, yScale = 0;
|
||||
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &xScale, &yScale);
|
||||
|
||||
return std::midpoint(xScale, yScale);
|
||||
}
|
||||
#elif defined(OS_WEB)
|
||||
return 1.0F;
|
||||
#else
|
||||
return 1.0F;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
ImVec2 getMainWindowPosition() {
|
||||
if ((ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) != ImGuiConfigFlags_None)
|
||||
@@ -681,14 +641,6 @@ namespace hex {
|
||||
return hex::getContainingModule(reinterpret_cast<void*>(&getLibImHexModuleHandle));
|
||||
}
|
||||
|
||||
void addMigrationRoutine(SemanticVersion migrationVersion, std::function<void()> function) {
|
||||
EventImHexUpdated::subscribe([migrationVersion, function](const SemanticVersion &oldVersion, const SemanticVersion &newVersion) {
|
||||
if (oldVersion < migrationVersion && newVersion >= migrationVersion) {
|
||||
function();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const std::map<std::string, std::string>& getInitArguments() {
|
||||
return *impl::s_initArguments;
|
||||
@@ -733,27 +685,6 @@ namespace hex {
|
||||
return impl::s_glRenderer;
|
||||
}
|
||||
|
||||
bool isCorporateEnvironment() {
|
||||
#if defined(OS_WINDOWS)
|
||||
{
|
||||
DSROLE_PRIMARY_DOMAIN_INFO_BASIC * info;
|
||||
if ((DsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic, (PBYTE *)&info) == ERROR_SUCCESS) && (info != nullptr))
|
||||
{
|
||||
bool result = std::wstring(info->DomainNameFlat).empty();
|
||||
DsRoleFreeMemory(info);
|
||||
|
||||
return result;
|
||||
} else {
|
||||
DWORD size = 1024;
|
||||
::GetComputerNameExA(ComputerNameDnsDomain, nullptr, &size);
|
||||
return size > 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool isPortableVersion() {
|
||||
static std::optional<bool> portable;
|
||||
if (portable.has_value())
|
||||
@@ -859,11 +790,16 @@ namespace hex {
|
||||
return { { name, version } };
|
||||
}
|
||||
|
||||
SemanticVersion getImHexVersion() {
|
||||
std::string getImHexVersion(bool withBuildType) {
|
||||
#if defined IMHEX_VERSION
|
||||
return SemanticVersion(IMHEX_VERSION);
|
||||
if (withBuildType) {
|
||||
return IMHEX_VERSION;
|
||||
} else {
|
||||
auto version = std::string(IMHEX_VERSION);
|
||||
return version.substr(0, version.find('-'));
|
||||
}
|
||||
#else
|
||||
return {};
|
||||
return "Unknown";
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -875,7 +811,7 @@ namespace hex {
|
||||
return std::string(GIT_COMMIT_HASH_LONG).substr(0, 7);
|
||||
}
|
||||
#else
|
||||
std::ignore = longHash;
|
||||
hex::unused(longHash);
|
||||
return "Unknown";
|
||||
#endif
|
||||
}
|
||||
@@ -897,7 +833,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
bool isNightlyBuild() {
|
||||
return getImHexVersion().nightly();
|
||||
return getImHexVersion(false).ends_with("WIP");
|
||||
}
|
||||
|
||||
bool updateImHex(UpdateType updateType) {
|
||||
@@ -995,6 +931,11 @@ namespace hex {
|
||||
return *s_fonts;
|
||||
}
|
||||
|
||||
static AutoReset<std::fs::path> s_customFontPath;
|
||||
void setCustomFontPath(const std::fs::path &path) {
|
||||
s_customFontPath = path;
|
||||
}
|
||||
|
||||
static float s_fontSize = DefaultFontSize;
|
||||
void setFontSize(float size) {
|
||||
s_fontSize = size;
|
||||
@@ -1012,10 +953,6 @@ namespace hex {
|
||||
s_italicFont = italic;
|
||||
}
|
||||
|
||||
static AutoReset<std::map<UnlocalizedString, ImFont*>> s_fontDefinitions;
|
||||
std::map<UnlocalizedString, ImFont*>& getFontDefinitions() {
|
||||
return *s_fontDefinitions;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1080,6 +1017,10 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
const std::fs::path& getCustomFontPath() {
|
||||
return impl::s_customFontPath;
|
||||
}
|
||||
|
||||
float getFontSize() {
|
||||
return impl::s_fontSize;
|
||||
}
|
||||
@@ -1088,14 +1029,6 @@ namespace hex {
|
||||
return impl::s_fontAtlas;
|
||||
}
|
||||
|
||||
void registerFont(const UnlocalizedString &fontName) {
|
||||
(*impl::s_fontDefinitions)[fontName] = nullptr;
|
||||
}
|
||||
|
||||
ImFont* getFont(const UnlocalizedString &fontName) {
|
||||
return (*impl::s_fontDefinitions)[fontName];
|
||||
}
|
||||
|
||||
ImFont* Bold() {
|
||||
return impl::s_boldFont;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace hex {
|
||||
|
||||
AutoReset<std::string> s_fallbackLanguage;
|
||||
AutoReset<std::string> s_selectedLanguage;
|
||||
AutoReset<std::map<size_t, std::string>> s_currStrings;
|
||||
AutoReset<std::map<std::string, std::string>> s_currStrings;
|
||||
|
||||
}
|
||||
|
||||
@@ -41,34 +41,22 @@ namespace hex {
|
||||
return m_entries;
|
||||
}
|
||||
|
||||
static void loadLanguageDefinitions(const std::vector<LanguageDefinition> &definitions) {
|
||||
for (const auto &definition : definitions) {
|
||||
const auto &entries = definition.getEntries();
|
||||
if (entries.empty())
|
||||
continue;
|
||||
|
||||
for (const auto &[key, value] : entries) {
|
||||
if (value.empty())
|
||||
continue;
|
||||
|
||||
s_currStrings->emplace(LangConst::hash(key), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loadLanguage(std::string language) {
|
||||
void loadLanguage(const std::string &language) {
|
||||
auto &definitions = ContentRegistry::Language::impl::getLanguageDefinitions();
|
||||
|
||||
const auto& fallbackLanguage = getFallbackLanguage();
|
||||
if (!definitions.contains(language))
|
||||
language = fallbackLanguage;
|
||||
return;
|
||||
|
||||
s_currStrings->clear();
|
||||
|
||||
loadLanguageDefinitions(definitions.at(language));
|
||||
for (const auto &definition : definitions.at(language))
|
||||
s_currStrings->insert(definition.getEntries().begin(), definition.getEntries().end());
|
||||
|
||||
if (language != fallbackLanguage)
|
||||
loadLanguageDefinitions(definitions.at(fallbackLanguage));
|
||||
const auto& fallbackLanguage = getFallbackLanguage();
|
||||
if (language != fallbackLanguage && definitions.contains(fallbackLanguage)) {
|
||||
for (const auto &definition : definitions.at(fallbackLanguage))
|
||||
s_currStrings->insert(definition.getEntries().begin(), definition.getEntries().end());
|
||||
}
|
||||
|
||||
s_selectedLanguage = language;
|
||||
}
|
||||
@@ -110,11 +98,11 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
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(const LangConst &localizedString) : m_entryHash(localizedString.m_entryHash), m_unlocalizedString(localizedString.m_unlocalizedString) { }
|
||||
Lang::Lang(const UnlocalizedString &unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString.get())), m_unlocalizedString(unlocalizedString.get()) { }
|
||||
Lang::Lang(std::string_view unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)), m_unlocalizedString(unlocalizedString) { }
|
||||
Lang::Lang(const char *unlocalizedString) : m_unlocalizedString(unlocalizedString) { }
|
||||
Lang::Lang(const std::string &unlocalizedString) : m_unlocalizedString(unlocalizedString) { }
|
||||
Lang::Lang(const UnlocalizedString &unlocalizedString) : m_unlocalizedString(unlocalizedString.get()) { }
|
||||
Lang::Lang(std::string_view unlocalizedString) : m_unlocalizedString(unlocalizedString) { }
|
||||
|
||||
|
||||
Lang::operator std::string() const {
|
||||
return get();
|
||||
@@ -125,41 +113,43 @@ namespace hex {
|
||||
}
|
||||
|
||||
Lang::operator const char *() const {
|
||||
return get();
|
||||
return get().c_str();
|
||||
}
|
||||
|
||||
const char *Lang::get() const {
|
||||
const auto &lang = *LocalizationManager::s_currStrings;
|
||||
|
||||
const auto it = lang.find(m_entryHash);
|
||||
if (it == lang.end()) {
|
||||
return m_unlocalizedString.c_str();
|
||||
} else {
|
||||
return it->second.c_str();
|
||||
}
|
||||
std::string operator+(const std::string &&left, const Lang &&right) {
|
||||
return left + static_cast<std::string>(right);
|
||||
}
|
||||
|
||||
LangConst::operator std::string() const {
|
||||
return get();
|
||||
std::string operator+(const Lang &&left, const std::string &&right) {
|
||||
return static_cast<std::string>(left) + right;
|
||||
}
|
||||
|
||||
LangConst::operator std::string_view() const {
|
||||
return get();
|
||||
std::string operator+(const Lang &&left, const Lang &&right) {
|
||||
return static_cast<std::string>(left) + static_cast<std::string>(right);
|
||||
}
|
||||
|
||||
LangConst::operator const char *() const {
|
||||
return get();
|
||||
std::string operator+(const std::string_view &&left, const Lang &&right) {
|
||||
return std::string(left) + static_cast<std::string>(right);
|
||||
}
|
||||
|
||||
const char *LangConst::get() const {
|
||||
const auto &lang = *LocalizationManager::s_currStrings;
|
||||
std::string operator+(const Lang &&left, const std::string_view &&right) {
|
||||
return static_cast<std::string>(left) + std::string(right);
|
||||
}
|
||||
|
||||
const auto it = lang.find(m_entryHash);
|
||||
if (it == lang.end()) {
|
||||
std::string operator+(const char *left, const Lang &&right) {
|
||||
return left + static_cast<std::string>(right);
|
||||
}
|
||||
|
||||
std::string operator+(const Lang &&left, const char *right) {
|
||||
return static_cast<std::string>(left) + right;
|
||||
}
|
||||
|
||||
const std::string &Lang::get() const {
|
||||
auto &lang = LocalizationManager::s_currStrings;
|
||||
if (lang->contains(m_unlocalizedString))
|
||||
return lang->at(m_unlocalizedString);
|
||||
else
|
||||
return m_unlocalizedString;
|
||||
} else {
|
||||
return it->second.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -112,6 +112,10 @@ namespace hex {
|
||||
}
|
||||
|
||||
Plugin::~Plugin() {
|
||||
if (isLoaded()) {
|
||||
log::info("Trying to unload plugin '{}'", getPluginName());
|
||||
}
|
||||
|
||||
unloadLibrary(m_handle, m_path);
|
||||
}
|
||||
|
||||
@@ -129,7 +133,7 @@ namespace hex {
|
||||
|
||||
|
||||
const auto requestedVersion = getCompatibleVersion();
|
||||
const auto imhexVersion = ImHexApi::System::getImHexVersion().get();
|
||||
const auto imhexVersion = ImHexApi::System::getImHexVersion();
|
||||
if (!imhexVersion.starts_with(requestedVersion)) {
|
||||
if (requestedVersion.empty()) {
|
||||
log::warn("Plugin '{}' did not specify a compatible version, assuming it is compatible with the current version of ImHex.", wolv::util::toUTF8String(m_path.filename()));
|
||||
@@ -331,7 +335,7 @@ namespace hex {
|
||||
void PluginManager::initializeNewPlugins() {
|
||||
for (const auto &plugin : getPlugins()) {
|
||||
if (!plugin.isLoaded())
|
||||
std::ignore = plugin.initializePlugin();
|
||||
hex::unused(plugin.initializePlugin());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include <hex/api/shortcut_manager.hpp>
|
||||
#include <imgui.h>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/helpers/auto_reset.hpp>
|
||||
|
||||
#include <hex/ui/view.hpp>
|
||||
@@ -13,300 +12,29 @@ namespace hex {
|
||||
AutoReset<std::map<Shortcut, ShortcutManager::ShortcutEntry>> s_globalShortcuts;
|
||||
std::atomic<bool> s_paused;
|
||||
std::optional<Shortcut> s_prevShortcut;
|
||||
bool s_macOSMode = false;
|
||||
AutoReset<std::optional<UnlocalizedString>> s_lastShortcutMainMenu;
|
||||
|
||||
}
|
||||
|
||||
Shortcut operator+(const Key &lhs, const Key &rhs) {
|
||||
Shortcut result;
|
||||
result.m_keys = { lhs, rhs };
|
||||
|
||||
return result;
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback) {
|
||||
s_globalShortcuts->insert({ shortcut, { shortcut, unlocalizedName, callback } });
|
||||
}
|
||||
|
||||
Shortcut::Shortcut(Keys key) : m_keys({ key }) {
|
||||
|
||||
}
|
||||
Shortcut::Shortcut(std::set<Key> keys) : m_keys(std::move(keys)) {
|
||||
|
||||
}
|
||||
|
||||
Shortcut Shortcut::operator+(const Key &other) const {
|
||||
Shortcut result = *this;
|
||||
result.m_keys.insert(other);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Shortcut& Shortcut::operator+=(const Key &other) {
|
||||
m_keys.insert(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Shortcut::operator<(const Shortcut &other) const {
|
||||
return m_keys < other.m_keys;
|
||||
}
|
||||
|
||||
bool Shortcut::operator==(const Shortcut &other) const {
|
||||
return m_keys == other.m_keys;
|
||||
}
|
||||
|
||||
bool Shortcut::isLocal() const {
|
||||
return m_keys.contains(CurrentView);
|
||||
}
|
||||
|
||||
const std::set<Key>& Shortcut::getKeys() const {
|
||||
return m_keys;
|
||||
}
|
||||
|
||||
bool Shortcut::has(Key key) const {
|
||||
return m_keys.contains(key);
|
||||
}
|
||||
|
||||
bool Shortcut::matches(const Shortcut& other) const {
|
||||
auto left = this->m_keys;
|
||||
auto right = other.m_keys;
|
||||
|
||||
left.erase(CurrentView);
|
||||
left.erase(AllowWhileTyping);
|
||||
right.erase(CurrentView);
|
||||
right.erase(AllowWhileTyping);
|
||||
|
||||
return left == right;
|
||||
}
|
||||
|
||||
|
||||
std::string Shortcut::toString() const {
|
||||
std::string result;
|
||||
|
||||
const auto CTRL_NAME = s_macOSMode ? "⌃" : "CTRL";
|
||||
const auto ALT_NAME = s_macOSMode ? "⌥" : "ALT";
|
||||
const auto SHIFT_NAME = s_macOSMode ? "⇧" : "SHIFT";
|
||||
const auto SUPER_NAME = s_macOSMode ? "⌘" : "SUPER";
|
||||
const auto Concatination = s_macOSMode ? " " : " + ";
|
||||
|
||||
auto keys = m_keys;
|
||||
if (keys.erase(CTRL) > 0 || (!s_macOSMode && keys.erase(CTRLCMD) > 0)) {
|
||||
result += CTRL_NAME;
|
||||
result += Concatination;
|
||||
}
|
||||
if (keys.erase(ALT) > 0) {
|
||||
result += ALT_NAME;
|
||||
result += Concatination;
|
||||
}
|
||||
if (keys.erase(SHIFT) > 0) {
|
||||
result += SHIFT_NAME;
|
||||
result += Concatination;
|
||||
}
|
||||
if (keys.erase(SUPER) > 0 || (s_macOSMode && keys.erase(CTRLCMD) > 0)) {
|
||||
result += SUPER_NAME;
|
||||
result += Concatination;
|
||||
}
|
||||
keys.erase(CurrentView);
|
||||
|
||||
for (const auto &key : keys) {
|
||||
switch (Keys(key.getKeyCode())) {
|
||||
case Keys::Space: result += "⎵"; break;
|
||||
case Keys::Apostrophe: result += "'"; break;
|
||||
case Keys::Comma: result += ","; break;
|
||||
case Keys::Minus: result += "-"; break;
|
||||
case Keys::Period: result += "."; break;
|
||||
case Keys::Slash: result += "/"; break;
|
||||
case Keys::Num0: result += "0"; break;
|
||||
case Keys::Num1: result += "1"; break;
|
||||
case Keys::Num2: result += "2"; break;
|
||||
case Keys::Num3: result += "3"; break;
|
||||
case Keys::Num4: result += "4"; break;
|
||||
case Keys::Num5: result += "5"; break;
|
||||
case Keys::Num6: result += "6"; break;
|
||||
case Keys::Num7: result += "7"; break;
|
||||
case Keys::Num8: result += "8"; break;
|
||||
case Keys::Num9: result += "9"; break;
|
||||
case Keys::Semicolon: result += ";"; break;
|
||||
case Keys::Equals: result += "="; break;
|
||||
case Keys::A: result += "A"; break;
|
||||
case Keys::B: result += "B"; break;
|
||||
case Keys::C: result += "C"; break;
|
||||
case Keys::D: result += "D"; break;
|
||||
case Keys::E: result += "E"; break;
|
||||
case Keys::F: result += "F"; break;
|
||||
case Keys::G: result += "G"; break;
|
||||
case Keys::H: result += "H"; break;
|
||||
case Keys::I: result += "I"; break;
|
||||
case Keys::J: result += "J"; break;
|
||||
case Keys::K: result += "K"; break;
|
||||
case Keys::L: result += "L"; break;
|
||||
case Keys::M: result += "M"; break;
|
||||
case Keys::N: result += "N"; break;
|
||||
case Keys::O: result += "O"; break;
|
||||
case Keys::P: result += "P"; break;
|
||||
case Keys::Q: result += "Q"; break;
|
||||
case Keys::R: result += "R"; break;
|
||||
case Keys::S: result += "S"; break;
|
||||
case Keys::T: result += "T"; break;
|
||||
case Keys::U: result += "U"; break;
|
||||
case Keys::V: result += "V"; break;
|
||||
case Keys::W: result += "W"; break;
|
||||
case Keys::X: result += "X"; break;
|
||||
case Keys::Y: result += "Y"; break;
|
||||
case Keys::Z: result += "Z"; break;
|
||||
case Keys::LeftBracket: result += "["; break;
|
||||
case Keys::Backslash: result += "\\"; break;
|
||||
case Keys::RightBracket: result += "]"; break;
|
||||
case Keys::GraveAccent: result += "`"; break;
|
||||
case Keys::World1: result += "WORLD1"; break;
|
||||
case Keys::World2: result += "WORLD2"; break;
|
||||
case Keys::Escape: result += "ESC"; break;
|
||||
case Keys::Enter: result += "⏎"; break;
|
||||
case Keys::Tab: result += "⇥"; break;
|
||||
case Keys::Backspace: result += "⌫"; break;
|
||||
case Keys::Insert: result += "INSERT"; break;
|
||||
case Keys::Delete: result += "DELETE"; break;
|
||||
case Keys::Right: result += "RIGHT"; break;
|
||||
case Keys::Left: result += "LEFT"; break;
|
||||
case Keys::Down: result += "DOWN"; break;
|
||||
case Keys::Up: result += "UP"; break;
|
||||
case Keys::PageUp: result += "PAGEUP"; break;
|
||||
case Keys::PageDown: result += "PAGEDOWN"; break;
|
||||
case Keys::Home: result += "HOME"; break;
|
||||
case Keys::End: result += "END"; break;
|
||||
case Keys::CapsLock: result += "⇪"; break;
|
||||
case Keys::ScrollLock: result += "SCROLLLOCK"; break;
|
||||
case Keys::NumLock: result += "NUMLOCK"; break;
|
||||
case Keys::PrintScreen: result += "PRINTSCREEN"; break;
|
||||
case Keys::Pause: result += "PAUSE"; break;
|
||||
case Keys::F1: result += "F1"; break;
|
||||
case Keys::F2: result += "F2"; break;
|
||||
case Keys::F3: result += "F3"; break;
|
||||
case Keys::F4: result += "F4"; break;
|
||||
case Keys::F5: result += "F5"; break;
|
||||
case Keys::F6: result += "F6"; break;
|
||||
case Keys::F7: result += "F7"; break;
|
||||
case Keys::F8: result += "F8"; break;
|
||||
case Keys::F9: result += "F9"; break;
|
||||
case Keys::F10: result += "F10"; break;
|
||||
case Keys::F11: result += "F11"; break;
|
||||
case Keys::F12: result += "F12"; break;
|
||||
case Keys::F13: result += "F13"; break;
|
||||
case Keys::F14: result += "F14"; break;
|
||||
case Keys::F15: result += "F15"; break;
|
||||
case Keys::F16: result += "F16"; break;
|
||||
case Keys::F17: result += "F17"; break;
|
||||
case Keys::F18: result += "F18"; break;
|
||||
case Keys::F19: result += "F19"; break;
|
||||
case Keys::F20: result += "F20"; break;
|
||||
case Keys::F21: result += "F21"; break;
|
||||
case Keys::F22: result += "F22"; break;
|
||||
case Keys::F23: result += "F23"; break;
|
||||
case Keys::F24: result += "F24"; break;
|
||||
case Keys::F25: result += "F25"; break;
|
||||
case Keys::KeyPad0: result += "KP0"; break;
|
||||
case Keys::KeyPad1: result += "KP1"; break;
|
||||
case Keys::KeyPad2: result += "KP2"; break;
|
||||
case Keys::KeyPad3: result += "KP3"; break;
|
||||
case Keys::KeyPad4: result += "KP4"; break;
|
||||
case Keys::KeyPad5: result += "KP5"; break;
|
||||
case Keys::KeyPad6: result += "KP6"; break;
|
||||
case Keys::KeyPad7: result += "KP7"; break;
|
||||
case Keys::KeyPad8: result += "KP8"; break;
|
||||
case Keys::KeyPad9: result += "KP9"; break;
|
||||
case Keys::KeyPadDecimal: result += "KPDECIMAL"; break;
|
||||
case Keys::KeyPadDivide: result += "KPDIVIDE"; break;
|
||||
case Keys::KeyPadMultiply: result += "KPMULTIPLY"; break;
|
||||
case Keys::KeyPadSubtract: result += "KPSUBTRACT"; break;
|
||||
case Keys::KeyPadAdd: result += "KPADD"; break;
|
||||
case Keys::KeyPadEnter: result += "KPENTER"; break;
|
||||
case Keys::KeyPadEqual: result += "KPEQUAL"; break;
|
||||
case Keys::Menu: result += "MENU"; break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
result += Concatination;
|
||||
}
|
||||
|
||||
if (result.ends_with(Concatination))
|
||||
result = result.substr(0, result.size() - strlen(Concatination));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
KeyEquivalent Shortcut::toKeyEquivalent() const {
|
||||
#if defined(OS_MACOS)
|
||||
if (*this == None)
|
||||
return { };
|
||||
|
||||
KeyEquivalent result = {};
|
||||
result.valid = true;
|
||||
|
||||
for (const auto &key : m_keys) {
|
||||
switch (key.getKeyCode()) {
|
||||
case CTRL.getKeyCode():
|
||||
result.ctrl = true;
|
||||
break;
|
||||
case SHIFT.getKeyCode():
|
||||
result.shift = true;
|
||||
break;
|
||||
case ALT.getKeyCode():
|
||||
result.opt = true;
|
||||
break;
|
||||
case SUPER.getKeyCode():
|
||||
case CTRLCMD.getKeyCode():
|
||||
result.cmd = true;
|
||||
break;
|
||||
case CurrentView.getKeyCode(): break;
|
||||
case AllowWhileTyping.getKeyCode(): break;
|
||||
default:
|
||||
macosGetKey(Keys(key.getKeyCode()), &result.key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
#else
|
||||
return { };
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
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());
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, unlocalizedName, callback, enabledCallback } });
|
||||
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) {
|
||||
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, { unlocalizedName }, callback, enabledCallback } });
|
||||
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) {
|
||||
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback, enabledCallback } });
|
||||
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) {
|
||||
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, { unlocalizedName }, callback, enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback) {
|
||||
view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback } });
|
||||
}
|
||||
|
||||
static Shortcut getShortcut(bool ctrl, bool alt, bool shift, bool super, bool focused, u32 keyCode) {
|
||||
Shortcut pressedShortcut;
|
||||
|
||||
if (ctrl)
|
||||
pressedShortcut += s_macOSMode ? CTRL : CTRLCMD;
|
||||
pressedShortcut += CTRL;
|
||||
if (alt)
|
||||
pressedShortcut += ALT;
|
||||
if (shift)
|
||||
pressedShortcut += SHIFT;
|
||||
if (super)
|
||||
pressedShortcut += s_macOSMode ? CTRLCMD : SUPER;
|
||||
pressedShortcut += SUPER;
|
||||
if (focused)
|
||||
pressedShortcut += CurrentView;
|
||||
|
||||
@@ -315,30 +43,17 @@ namespace hex {
|
||||
return pressedShortcut;
|
||||
}
|
||||
|
||||
static void processShortcut(Shortcut shortcut, const std::map<Shortcut, ShortcutManager::ShortcutEntry> &shortcuts) {
|
||||
static void processShortcut(const Shortcut &shortcut, const std::map<Shortcut, ShortcutManager::ShortcutEntry> &shortcuts) {
|
||||
if (s_paused) return;
|
||||
|
||||
if (ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId))
|
||||
return;
|
||||
|
||||
const bool currentlyTyping = ImGui::GetIO().WantTextInput;
|
||||
|
||||
auto it = shortcuts.find(shortcut + AllowWhileTyping);
|
||||
if (!currentlyTyping && it == shortcuts.end()) {
|
||||
if (it == shortcuts.end())
|
||||
it = shortcuts.find(shortcut);
|
||||
}
|
||||
|
||||
if (it != shortcuts.end()) {
|
||||
const auto &[foundShortcut, entry] = *it;
|
||||
|
||||
if (entry.enabledCallback()) {
|
||||
entry.callback();
|
||||
|
||||
if (!entry.unlocalizedName.empty()) {
|
||||
s_lastShortcutMainMenu = entry.unlocalizedName.front();
|
||||
}
|
||||
}
|
||||
if (shortcuts.contains(shortcut + AllowWhileTyping)) {
|
||||
shortcuts.at(shortcut + AllowWhileTyping).callback();
|
||||
} else if (shortcuts.contains(shortcut)) {
|
||||
if (!ImGui::GetIO().WantTextInput)
|
||||
shortcuts.at(shortcut).callback();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,15 +73,6 @@ namespace hex {
|
||||
processShortcut(pressedShortcut, s_globalShortcuts);
|
||||
}
|
||||
|
||||
std::optional<UnlocalizedString> ShortcutManager::getLastActivatedMenu() {
|
||||
return *s_lastShortcutMainMenu;
|
||||
}
|
||||
|
||||
void ShortcutManager::resetLastActivatedMenu() {
|
||||
s_lastShortcutMainMenu->reset();
|
||||
}
|
||||
|
||||
|
||||
void ShortcutManager::clearShortcuts() {
|
||||
s_globalShortcuts->clear();
|
||||
}
|
||||
@@ -416,13 +122,10 @@ namespace hex {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShortcutManager::updateShortcut(const Shortcut &oldShortcut, Shortcut newShortcut, View *view) {
|
||||
if (oldShortcut.matches(newShortcut))
|
||||
bool ShortcutManager::updateShortcut(const Shortcut &oldShortcut, const Shortcut &newShortcut, View *view) {
|
||||
if (oldShortcut == newShortcut)
|
||||
return true;
|
||||
|
||||
if (oldShortcut.has(AllowWhileTyping))
|
||||
newShortcut += AllowWhileTyping;
|
||||
|
||||
bool result;
|
||||
if (view != nullptr) {
|
||||
result = updateShortcutImpl(oldShortcut + CurrentView, newShortcut + CurrentView , view->m_shortcuts);
|
||||
@@ -431,9 +134,9 @@ namespace hex {
|
||||
}
|
||||
|
||||
if (result) {
|
||||
for (auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMenuItemsMutable()) {
|
||||
if (menuItem.view == view && menuItem.shortcut == oldShortcut) {
|
||||
menuItem.shortcut = newShortcut;
|
||||
for (auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMenuItems()) {
|
||||
if (menuItem.view == view && *menuItem.shortcut == oldShortcut) {
|
||||
*menuItem.shortcut = newShortcut;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -442,9 +145,4 @@ namespace hex {
|
||||
return result;
|
||||
}
|
||||
|
||||
void ShortcutManager::enableMacOSMode() {
|
||||
s_macOSMode = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -63,7 +63,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
Task::Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function)
|
||||
Task::Task(UnlocalizedString unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function)
|
||||
: m_unlocalizedName(std::move(unlocalizedName)), m_maxValue(maxValue), m_function(std::move(function)), m_background(background) { }
|
||||
|
||||
Task::Task(hex::Task &&other) noexcept {
|
||||
@@ -327,11 +327,11 @@ namespace hex {
|
||||
s_tasksFinishedCallbacks.clear();
|
||||
}
|
||||
|
||||
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, std::function<void(Task&)> function) {
|
||||
TaskHolder TaskManager::createTask(std::string name, u64 maxValue, bool background, std::function<void(Task&)> function) {
|
||||
std::scoped_lock lock(s_queueMutex);
|
||||
|
||||
// Construct new task
|
||||
auto task = std::make_shared<Task>(std::move(unlocalizedName), maxValue, background, std::move(function));
|
||||
auto task = std::make_shared<Task>(std::move(name), maxValue, background, std::move(function));
|
||||
|
||||
s_tasks.emplace_back(task);
|
||||
|
||||
@@ -344,32 +344,14 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function) {
|
||||
log::debug("Creating task {}", unlocalizedName.get());
|
||||
return createTask(std::move(unlocalizedName), maxValue, false, std::move(function));
|
||||
TaskHolder TaskManager::createTask(std::string name, u64 maxValue, std::function<void(Task &)> function) {
|
||||
log::debug("Creating task {}", name);
|
||||
return createTask(std::move(name), maxValue, false, std::move(function));
|
||||
}
|
||||
|
||||
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function) {
|
||||
log::debug("Creating task {}", unlocalizedName.get());
|
||||
return createTask(std::move(unlocalizedName), maxValue, false,
|
||||
[function = std::move(function)](Task&) {
|
||||
function();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
TaskHolder TaskManager::createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void(Task &)> function) {
|
||||
log::debug("Creating background task {}", unlocalizedName.get());
|
||||
return createTask(std::move(unlocalizedName), 0, true, std::move(function));
|
||||
}
|
||||
|
||||
TaskHolder TaskManager::createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void()> function) {
|
||||
log::debug("Creating background task {}", unlocalizedName.get());
|
||||
return createTask(std::move(unlocalizedName), 0, true,
|
||||
[function = std::move(function)](Task&) {
|
||||
function();
|
||||
}
|
||||
);
|
||||
TaskHolder TaskManager::createBackgroundTask(std::string name, std::function<void(Task &)> function) {
|
||||
log::debug("Creating background task {}", name);
|
||||
return createTask(std::move(name), 0, true, std::move(function));
|
||||
}
|
||||
|
||||
void TaskManager::collectGarbage() {
|
||||
@@ -490,7 +472,7 @@ namespace hex {
|
||||
#elif defined(OS_LINUX)
|
||||
pthread_setname_np(pthread_self(), name.c_str());
|
||||
#elif defined(OS_WEB)
|
||||
std::ignore = name;
|
||||
hex::unused(name);
|
||||
#elif defined(OS_MACOS)
|
||||
pthread_setname_np(name.c_str());
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <hex/api/theme_manager.hpp>
|
||||
#include <hex/api/events/events_interaction.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
@@ -16,17 +16,11 @@ namespace hex {
|
||||
AutoReset<std::map<std::string, ThemeManager::StyleHandler>> s_styleHandlers;
|
||||
AutoReset<std::string> s_imageTheme;
|
||||
AutoReset<std::string> s_currTheme;
|
||||
AutoReset<std::optional<float>> s_accentColor;
|
||||
|
||||
std::recursive_mutex s_themeMutex;
|
||||
}
|
||||
|
||||
|
||||
void ThemeManager::reapplyCurrentTheme() {
|
||||
ThemeManager::changeTheme(s_currTheme);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
@@ -156,28 +150,12 @@ namespace hex {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto colorString = value.get<std::string>();
|
||||
bool accentableColor = false;
|
||||
if (colorString.starts_with("*")) {
|
||||
colorString = colorString.substr(1);
|
||||
accentableColor = true;
|
||||
}
|
||||
auto color = parseColorString(colorString);
|
||||
|
||||
auto color = parseColorString(value.get<std::string>());
|
||||
if (!color.has_value()) {
|
||||
log::warn("Invalid color '{}' for '{}.{}'", colorString, type, key);
|
||||
log::warn("Invalid color '{}' for '{}.{}'", value.get<std::string>(), type, key);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (accentableColor && s_accentColor->has_value()) {
|
||||
float h, s, v;
|
||||
ImGui::ColorConvertRGBtoHSV(color->Value.x, color->Value.y, color->Value.z, h, s, v);
|
||||
|
||||
h = s_accentColor->value();
|
||||
|
||||
ImGui::ColorConvertHSVtoRGB(h, s, v, color->Value.x, color->Value.y, color->Value.z);
|
||||
}
|
||||
|
||||
(*s_themeHandlers)[type].setFunction((*s_themeHandlers)[type].colorMap.at(key), color.value());
|
||||
}
|
||||
}
|
||||
@@ -253,14 +231,6 @@ namespace hex {
|
||||
s_currTheme->clear();
|
||||
}
|
||||
|
||||
void ThemeManager::setAccentColor(const ImColor &color) {
|
||||
float h, s, v;
|
||||
ImGui::ColorConvertRGBtoHSV(color.Value.x, color.Value.y, color.Value.z, h, s, v);
|
||||
|
||||
s_accentColor = h;
|
||||
reapplyCurrentTheme();
|
||||
}
|
||||
|
||||
|
||||
const std::map<std::string, ThemeManager::ThemeHandler> &ThemeManager::getThemeHandlers() {
|
||||
return s_themeHandlers;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/api/events/events_gui.hpp>
|
||||
|
||||
#include <hex/helpers/auto_reset.hpp>
|
||||
|
||||
@@ -12,8 +11,6 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace {
|
||||
@@ -23,12 +20,10 @@ namespace hex {
|
||||
|
||||
AutoReset<std::map<ImGuiID, std::string>> s_highlights;
|
||||
AutoReset<std::vector<std::pair<ImRect, std::string>>> s_highlightDisplays;
|
||||
AutoReset<std::map<ImGuiID, ImRect>> s_interactiveHelpDisplays;
|
||||
|
||||
AutoReset<std::map<ImGuiID, std::function<void()>>> s_interactiveHelpItems;
|
||||
ImRect s_hoveredRect;
|
||||
ImGuiID s_hoveredId;
|
||||
ImGuiID s_activeHelpId;
|
||||
bool s_helpHoverActive = false;
|
||||
|
||||
|
||||
@@ -38,13 +33,6 @@ namespace hex {
|
||||
idStack.push_back(0);
|
||||
}
|
||||
|
||||
void add(const char *string) {
|
||||
const ImGuiID seed = idStack.back();
|
||||
const ImGuiID id = ImHashStr(string, 0, seed);
|
||||
|
||||
idStack.push_back(id);
|
||||
}
|
||||
|
||||
void add(const std::string &string) {
|
||||
const ImGuiID seed = idStack.back();
|
||||
const ImGuiID id = ImHashStr(string.c_str(), string.length(), seed);
|
||||
@@ -96,23 +84,9 @@ namespace hex {
|
||||
EventImGuiElementRendered::subscribe([](ImGuiID id, const std::array<float, 4> bb){
|
||||
const auto boundingBox = ImRect(bb[0], bb[1], bb[2], bb[3]);
|
||||
|
||||
{
|
||||
const auto element = hex::s_highlights->find(id);
|
||||
if (element != hex::s_highlights->end()) {
|
||||
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
|
||||
|
||||
const auto window = ImGui::GetCurrentWindow();
|
||||
if (window != nullptr && window->DockNode != nullptr && window->DockNode->TabBar != nullptr)
|
||||
window->DockNode->TabBar->NextSelectedTabId = window->TabId;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const auto element = s_interactiveHelpItems->find(id);
|
||||
if (element != s_interactiveHelpItems->end()) {
|
||||
(*s_interactiveHelpDisplays)[id] = boundingBox;
|
||||
}
|
||||
|
||||
const auto element = hex::s_highlights->find(id);
|
||||
if (element != hex::s_highlights->end()) {
|
||||
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
|
||||
}
|
||||
|
||||
if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
|
||||
@@ -143,10 +117,10 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
void TutorialManager::addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString) {
|
||||
void TutorialManager::addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString text) {
|
||||
auto id = calculateId(ids);
|
||||
|
||||
s_interactiveHelpItems->emplace(id, [text = std::move(unlocalizedString)]{
|
||||
s_interactiveHelpItems->emplace(id, [text = std::move(text)]{
|
||||
log::info("{}", Lang(text).get());
|
||||
});
|
||||
}
|
||||
@@ -159,39 +133,6 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
void TutorialManager::setLastItemInteractiveHelpPopup(std::function<void()> callback) {
|
||||
auto id = ImGui::GetItemID();
|
||||
|
||||
if (!s_interactiveHelpItems->contains(id)) {
|
||||
s_interactiveHelpItems->emplace(id, [id]{
|
||||
s_activeHelpId = id;
|
||||
});
|
||||
}
|
||||
|
||||
if (id == s_activeHelpId) {
|
||||
ImGui::SetNextWindowSize(scaled({ 400, 0 }));
|
||||
if (ImGui::BeginTooltip()) {
|
||||
callback();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) || ImGui::IsKeyPressed(ImGuiKey_Escape))
|
||||
s_activeHelpId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TutorialManager::setLastItemInteractiveHelpLink(std::string link) {
|
||||
auto id = ImGui::GetItemID();
|
||||
|
||||
if (s_interactiveHelpItems->contains(id))
|
||||
return;
|
||||
|
||||
s_interactiveHelpItems->emplace(id, [link = std::move(link)]{
|
||||
hex::openWebpage(link);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void TutorialManager::startTutorial(const UnlocalizedString &unlocalizedName) {
|
||||
s_currentTutorial = s_tutorials->find(unlocalizedName);
|
||||
if (s_currentTutorial == s_tutorials->end())
|
||||
@@ -205,19 +146,6 @@ namespace hex {
|
||||
const auto &drawList = ImGui::GetForegroundDrawList();
|
||||
drawList->AddText(ImGui::GetMousePos() + scaled({ 10, -5, }), ImGui::GetColorU32(ImGuiCol_Text), "?");
|
||||
|
||||
for (const auto &[id, boundingBox] : *s_interactiveHelpDisplays) {
|
||||
drawList->AddRect(
|
||||
boundingBox.Min - ImVec2(5, 5),
|
||||
boundingBox.Max + ImVec2(5, 5),
|
||||
ImGui::GetColorU32(ImGuiCol_PlotHistogram),
|
||||
5.0F,
|
||||
ImDrawFlags_None,
|
||||
2.0F
|
||||
);
|
||||
}
|
||||
|
||||
s_interactiveHelpDisplays->clear();
|
||||
|
||||
const bool mouseClicked = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
|
||||
if (s_hoveredId != 0) {
|
||||
drawList->AddRectFilled(s_hoveredRect.Min, s_hoveredRect.Max, 0x30FFFFFF);
|
||||
@@ -236,11 +164,6 @@ namespace hex {
|
||||
if (mouseClicked || ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||
s_helpHoverActive = false;
|
||||
}
|
||||
|
||||
// Discard mouse click so it doesn't activate clicked item
|
||||
ImGui::GetIO().MouseDown[ImGuiMouseButton_Left] = false;
|
||||
ImGui::GetIO().MouseReleased[ImGuiMouseButton_Left] = false;
|
||||
ImGui::GetIO().MouseClicked[ImGuiMouseButton_Left] = false;
|
||||
}
|
||||
|
||||
for (const auto &[rect, unlocalizedText] : *s_highlightDisplays) {
|
||||
|
||||
@@ -8,18 +8,12 @@
|
||||
namespace hex::dp {
|
||||
|
||||
int Node::s_idCounter = 1;
|
||||
static std::atomic_bool s_interrupted;
|
||||
|
||||
Node::Node(UnlocalizedString unlocalizedTitle, std::vector<Attribute> attributes) : m_id(s_idCounter++), m_unlocalizedTitle(std::move(unlocalizedTitle)), m_attributes(std::move(attributes)) {
|
||||
for (auto &attr : m_attributes)
|
||||
attr.setParentNode(this);
|
||||
}
|
||||
|
||||
void Node::draw() {
|
||||
this->drawNode();
|
||||
}
|
||||
|
||||
|
||||
const std::vector<u8>& Node::getBufferOnInput(u32 index) {
|
||||
auto attribute = this->getConnectedInputAttribute(index);
|
||||
|
||||
@@ -35,6 +29,9 @@ namespace hex::dp {
|
||||
|
||||
auto &outputData = attribute->getOutputData();
|
||||
|
||||
if (outputData.empty())
|
||||
throwNodeError("No data available at connected attribute");
|
||||
|
||||
return outputData;
|
||||
}
|
||||
|
||||
@@ -151,56 +148,9 @@ namespace hex::dp {
|
||||
m_overlay->getData() = data;
|
||||
}
|
||||
|
||||
[[noreturn]] void Node::throwNodeError(const std::string &message) {
|
||||
throw NodeError { this, message };
|
||||
}
|
||||
|
||||
void Node::setAttributes(std::vector<Attribute> attributes) {
|
||||
m_attributes = std::move(attributes);
|
||||
|
||||
for (auto &attr : m_attributes)
|
||||
attr.setParentNode(this);
|
||||
}
|
||||
|
||||
void Node::setIdCounter(int id) {
|
||||
if (id > s_idCounter)
|
||||
s_idCounter = id;
|
||||
}
|
||||
|
||||
Attribute& Node::getAttribute(u32 index) {
|
||||
if (index >= this->getAttributes().size())
|
||||
throw std::runtime_error("Attribute index out of bounds!");
|
||||
|
||||
return this->getAttributes()[index];
|
||||
}
|
||||
|
||||
Attribute *Node::getConnectedInputAttribute(u32 index) {
|
||||
const auto &connectedAttribute = this->getAttribute(index).getConnectedAttributes();
|
||||
|
||||
if (connectedAttribute.empty())
|
||||
return nullptr;
|
||||
|
||||
return connectedAttribute.begin()->second;
|
||||
}
|
||||
|
||||
void Node::markInputProcessed(u32 index) {
|
||||
const auto &[iter, inserted] = m_processedInputs.insert(index);
|
||||
if (!inserted)
|
||||
throwNodeError("Recursion detected!");
|
||||
|
||||
if (s_interrupted) {
|
||||
s_interrupted = false;
|
||||
throwNodeError("Execution interrupted!");
|
||||
}
|
||||
}
|
||||
|
||||
void Node::unmarkInputProcessed(u32 index) {
|
||||
m_processedInputs.erase(index);
|
||||
}
|
||||
|
||||
void Node::interrupt() {
|
||||
s_interrupted = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
#include <algorithm>
|
||||
#include <hex/helpers/crypto.hpp>
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
#include <wolv/utils/guards.hpp>
|
||||
#include <wolv/utils/expected.hpp>
|
||||
|
||||
#include <mbedtls/version.h>
|
||||
#include <mbedtls/base64.h>
|
||||
@@ -498,8 +496,8 @@ namespace hex::crypt {
|
||||
return encodeLeb128<i128>(value);
|
||||
}
|
||||
|
||||
static wolv::util::Expected<std::vector<u8>, int> aes(mbedtls_cipher_type_t type, mbedtls_operation_t operation, const std::vector<u8> &key,
|
||||
std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::span<const u8> &input) {
|
||||
static std::vector<u8> aes(mbedtls_cipher_type_t type, mbedtls_operation_t operation, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input) {
|
||||
std::vector<u8> output;
|
||||
|
||||
if (input.empty())
|
||||
return {};
|
||||
@@ -509,65 +507,38 @@ namespace hex::crypt {
|
||||
mbedtls_cipher_context_t ctx;
|
||||
auto cipherInfo = mbedtls_cipher_info_from_type(type);
|
||||
|
||||
if (cipherInfo == nullptr)
|
||||
return {};
|
||||
|
||||
int setupResult = mbedtls_cipher_setup(&ctx, cipherInfo);
|
||||
if (setupResult != 0)
|
||||
return wolv::util::Unexpected(setupResult);
|
||||
|
||||
int setKeyResult = mbedtls_cipher_setkey(&ctx, key.data(), key.size() * 8, operation);
|
||||
if (setKeyResult != 0)
|
||||
return wolv::util::Unexpected(setKeyResult);
|
||||
mbedtls_cipher_setup(&ctx, cipherInfo);
|
||||
mbedtls_cipher_setkey(&ctx, key.data(), key.size() * 8, operation);
|
||||
|
||||
std::array<u8, 16> nonceCounter = { 0 };
|
||||
|
||||
auto mode = mbedtls_cipher_get_cipher_mode(&ctx);
|
||||
|
||||
// if we are in ECB mode, we don't need to set the nonce
|
||||
if (mode != MBEDTLS_MODE_ECB) {
|
||||
std::ranges::copy(nonce, nonceCounter.begin());
|
||||
std::ranges::copy(iv, nonceCounter.begin() + 8);
|
||||
}
|
||||
std::copy(nonce.begin(), nonce.end(), nonceCounter.begin());
|
||||
std::copy(iv.begin(), iv.end(), nonceCounter.begin() + 8);
|
||||
|
||||
size_t outputSize = input.size() + mbedtls_cipher_get_block_size(&ctx);
|
||||
std::vector<u8> output(outputSize, 0x00);
|
||||
output.resize(outputSize, 0x00);
|
||||
mbedtls_cipher_crypt(&ctx, nonceCounter.data(), nonceCounter.size(), input.data(), input.size(), output.data(), &outputSize);
|
||||
|
||||
int cryptResult = 0;
|
||||
if (mode == MBEDTLS_MODE_ECB) {
|
||||
cryptResult = mbedtls_cipher_crypt(&ctx, nullptr, 0, input.data(), input.size(), output.data(), &outputSize);
|
||||
} else {
|
||||
cryptResult = mbedtls_cipher_crypt(&ctx, nonceCounter.data(), nonceCounter.size(), input.data(), input.size(), output.data(), &outputSize);
|
||||
}
|
||||
|
||||
// free regardless of the result
|
||||
mbedtls_cipher_free(&ctx);
|
||||
|
||||
if (cryptResult != 0) {
|
||||
return wolv::util::Unexpected(cryptResult);
|
||||
}
|
||||
|
||||
output.resize(input.size());
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
wolv::util::Expected<std::vector<u8>, int> aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input) {
|
||||
std::vector<u8> aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input) {
|
||||
switch (keyLength) {
|
||||
case KeyLength::Key128Bits:
|
||||
if (key.size() != 128 / 8)
|
||||
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_KEY_LENGTH);
|
||||
if (key.size() != 128 / 8) return {};
|
||||
break;
|
||||
case KeyLength::Key192Bits:
|
||||
if (key.size() != 192 / 8)
|
||||
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_KEY_LENGTH);
|
||||
if (key.size() != 192 / 8) return {};
|
||||
break;
|
||||
case KeyLength::Key256Bits:
|
||||
if (key.size() != 256 / 8)
|
||||
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_KEY_LENGTH);
|
||||
if (key.size() != 256 / 8) return {};
|
||||
break;
|
||||
default:
|
||||
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_KEY_LENGTH);
|
||||
return {};
|
||||
}
|
||||
|
||||
mbedtls_cipher_type_t type;
|
||||
@@ -597,7 +568,7 @@ namespace hex::crypt {
|
||||
type = MBEDTLS_CIPHER_AES_128_XTS;
|
||||
break;
|
||||
default:
|
||||
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_MODE);
|
||||
return {};
|
||||
}
|
||||
|
||||
type = mbedtls_cipher_type_t(type + u8(keyLength));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user