mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-31 05:15:55 -05:00
Compare commits
100 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
716d6ae850 | ||
|
|
ceb07b7425 | ||
|
|
4885175ac6 | ||
|
|
d0f1a40f16 | ||
|
|
fc20d751bb | ||
|
|
dfc22abf35 | ||
|
|
de269e7a48 | ||
|
|
0ed885fe0f | ||
|
|
f9fc7051fc | ||
|
|
ab1f4df9d9 | ||
|
|
710771b8b1 | ||
|
|
2d982e2088 | ||
|
|
ef5fbba56b | ||
|
|
eadcc6f38c | ||
|
|
3db50a690c | ||
|
|
96aa929c31 | ||
|
|
e07fc76abf | ||
|
|
f01e227c87 | ||
|
|
cd34d567a7 | ||
|
|
bb429aae62 | ||
|
|
19f99bab0c | ||
|
|
1f433fc36d | ||
|
|
034cc0cd2f | ||
|
|
3efdc02fed | ||
|
|
501d141e13 | ||
|
|
9c1006f3ae | ||
|
|
5b0813478e | ||
|
|
ac964dc5ec | ||
|
|
11c2f240a1 | ||
|
|
8db2bdb6a7 | ||
|
|
7242eb8f4c | ||
|
|
60c6abbfcc | ||
|
|
a4c432f435 | ||
|
|
d50be26771 | ||
|
|
673027c82d | ||
|
|
e02ccd9b9b | ||
|
|
956276d1ee | ||
|
|
a936cf1ce4 | ||
|
|
5800546369 | ||
|
|
01adc8a2cd | ||
|
|
b1b33b2ae4 | ||
|
|
6506291e4e | ||
|
|
3471b314dd | ||
|
|
546d0a4922 | ||
|
|
c6989c2ef7 | ||
|
|
a5aa002752 | ||
|
|
b89490bca3 | ||
|
|
e33726f526 | ||
|
|
c238767750 | ||
|
|
116aeede2d | ||
|
|
662d80abea | ||
|
|
f6ddb3c5e7 | ||
|
|
6490e565d3 | ||
|
|
6b7ade8d61 | ||
|
|
9b77d7b5e2 | ||
|
|
1785088456 | ||
|
|
4dcd26a21f | ||
|
|
12e99a9d4c | ||
|
|
5e67a1f27b | ||
|
|
2a76e45dc5 | ||
|
|
6266883e81 | ||
|
|
aed9d15625 | ||
|
|
5551e82fea | ||
|
|
653a688fe6 | ||
|
|
dfc1dc2529 | ||
|
|
1e511acf37 | ||
|
|
141ee62af9 | ||
|
|
a5d202ffc8 | ||
|
|
f243ac7464 | ||
|
|
91ac9ca120 | ||
|
|
a56ba50cf9 | ||
|
|
fdaad55cc6 | ||
|
|
9d19214be9 | ||
|
|
038a6b9757 | ||
|
|
bad109ef8d | ||
|
|
5623e1342b | ||
|
|
6bad50c78b | ||
|
|
6929ffb865 | ||
|
|
2d7fdc0896 | ||
|
|
d1d73bcff6 | ||
|
|
bf1441223c | ||
|
|
fadca9a34a | ||
|
|
2ef3a0c157 | ||
|
|
c96a0a7bda | ||
|
|
fe6be686b7 | ||
|
|
05862ae991 | ||
|
|
6a6b6b94cf | ||
|
|
4701b1b67c | ||
|
|
f1b2d5881e | ||
|
|
efed07ac8b | ||
|
|
e5ff987392 | ||
|
|
8a24517fb9 | ||
|
|
a4c8bcab18 | ||
|
|
4fd8ada4ff | ||
|
|
7bf94ffe42 | ||
|
|
088205385f | ||
|
|
39c743631b | ||
|
|
603a95debb | ||
|
|
28a8adb26d | ||
|
|
e2bfd26bb3 |
29
.github/workflows/analysis.yml
vendored
29
.github/workflows/analysis.yml
vendored
@@ -3,11 +3,12 @@ name: "CodeQL"
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
codeql:
|
||||
name: 🐛 CodeQL
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
@@ -15,24 +16,30 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- name: ✋ Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: 'cpp'
|
||||
|
||||
- name: 📜 Restore cache
|
||||
uses: actions/cache@v2
|
||||
- name: 📜 Restore ccache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.ccache
|
||||
~/.cache/ccache
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build
|
||||
|
||||
- name: 📜 Restore CMakeCache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
build/CMakeCache.txt
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
@@ -42,7 +49,7 @@ jobs:
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=gcc-10 CXX=g++-10 cmake \
|
||||
CC=gcc-12 CXX=g++-12 cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
@@ -53,4 +60,4 @@ jobs:
|
||||
make -j 4 install
|
||||
|
||||
- name: 🗯️ Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
uses: github/codeql-action/analyze@v2
|
||||
247
.github/workflows/build.yml
vendored
247
.github/workflows/build.yml
vendored
@@ -2,7 +2,9 @@ name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["*"]
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
@@ -22,11 +24,33 @@ jobs:
|
||||
CCACHE_COMPRESS: "true"
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- name: 📜 Prepare Cache
|
||||
id: prep-ccache
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p "${CCACHE_DIR}"
|
||||
echo "::set-output name=dir::$CCACHE_DIR"
|
||||
|
||||
- name: 📜 Restore ccache
|
||||
uses: actions/cache@v3
|
||||
id: cache-ccache
|
||||
with:
|
||||
path: |
|
||||
${{ steps.prep-ccache.outputs.dir }}
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build
|
||||
|
||||
- name: 📜 Restore CMakeCache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
build/CMakeCache.txt
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: 🟦 Install msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
@@ -52,21 +76,6 @@ jobs:
|
||||
$USERPROFILE/.cargo/bin/rustup.exe target add x86_64-pc-windows-gnu
|
||||
$USERPROFILE/.cargo/bin/rustup.exe default nightly
|
||||
|
||||
- name: 📜 Prepare Cache
|
||||
id: prep-ccache
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p "${CCACHE_DIR}"
|
||||
echo "::set-output name=dir::$CCACHE_DIR"
|
||||
|
||||
- name: 📜 Restore Cache
|
||||
uses: actions/cache@v1
|
||||
id: cache-ccache
|
||||
with:
|
||||
path: ${{ steps.prep-ccache.outputs.dir }}
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: 🛠️ Build
|
||||
run: |
|
||||
mkdir -p build
|
||||
@@ -84,20 +93,22 @@ jobs:
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
|
||||
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
|
||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
||||
-DRUST_PATH="$USERPROFILE/.cargo/bin/" \
|
||||
..
|
||||
mingw32-make -j4 install
|
||||
cpack
|
||||
|
||||
- name: ⬆️ Upload Portable ZIP
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Windows Portable ZIP
|
||||
name: Windows Portable
|
||||
path: |
|
||||
build/install/*
|
||||
|
||||
- name: ⬆️ Upload Windows Installer
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Windows Installer
|
||||
path: |
|
||||
@@ -105,72 +116,89 @@ jobs:
|
||||
|
||||
# MacOS build
|
||||
macos:
|
||||
runs-on: macos-11.0
|
||||
runs-on: macos-11
|
||||
name: 🍎 macOS 11.0
|
||||
steps:
|
||||
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- name: 📜 Restore ccache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/Library/Caches/ccache
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build
|
||||
|
||||
|
||||
- name: 📜 Restore CMakeCache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
build/CMakeCache.txt
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
run: |
|
||||
brew bundle --no-lock --file dist/Brewfile
|
||||
|
||||
- name: 📜 Restore cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.ccache
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: 🛠️ Build
|
||||
run: |
|
||||
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" \
|
||||
MACOSX_DEPLOYMENT_TARGET="10.15" \
|
||||
cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCREATE_BUNDLE=ON \
|
||||
-DCREATE_PACKAGE=ON \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
MACOSX_DEPLOYMENT_TARGET="10.15" \
|
||||
cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCREATE_BUNDLE=ON \
|
||||
-DCREATE_PACKAGE=ON \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
||||
..
|
||||
make -j4 package
|
||||
|
||||
- name: ⬆️ Upload DMG
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: macOS DMG
|
||||
path: build/*.dmg
|
||||
|
||||
# Linux build
|
||||
linux:
|
||||
runs-on: ubuntu-20.04
|
||||
name: 🐧 Ubuntu 20.04
|
||||
runs-on: ubuntu-22.04
|
||||
name: 🐧 Ubuntu 22.04
|
||||
steps:
|
||||
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- name: 📜 Restore cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.ccache
|
||||
~/.cache/ccache
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build
|
||||
|
||||
- name: 📜 Restore other caches
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
build/CMakeCache.txt
|
||||
.flatpak-builder
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
run: |
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
@@ -197,17 +225,23 @@ jobs:
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=gcc-11 CXX=g++-11 cmake \
|
||||
CC=gcc-12 CXX=g++-12 cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
|
||||
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
|
||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
||||
-DRUST_PATH="$HOME/.cargo/bin/" \
|
||||
..
|
||||
make -j 4 install DESTDIR=AppDir
|
||||
|
||||
- name: 📜 Set version variable
|
||||
run: |
|
||||
echo "version=`cat VERSION`" >> $GITHUB_ENV
|
||||
|
||||
#- name: 📦 Bundle Flatpak
|
||||
# run: |
|
||||
# sudo apt install flatpak flatpak-builder
|
||||
@@ -217,45 +251,124 @@ jobs:
|
||||
# flatpak-builder --jobs=4 --repo=imhex _flatpak dist/net.werwolv.ImHex.yaml --ccache --keep-build-dirs
|
||||
# flatpak build-bundle imhex imhex.flatpak net.werwolv.ImHex stable
|
||||
|
||||
- name: ⬆️ Upload ELF
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Linux ELF
|
||||
path: |
|
||||
build/AppDir/*
|
||||
|
||||
- name: 📦 Bundle DEB
|
||||
run: |
|
||||
cp -r build/DEBIAN build/AppDir
|
||||
dpkg-deb --build build/AppDir
|
||||
mv build/AppDir.deb imhex.deb
|
||||
mv build/AppDir.deb imhex-${{env.version}}.deb
|
||||
rm -rf build/AppDir/DEBIAN
|
||||
|
||||
- name: 📦 Bundle AppImage
|
||||
run: |
|
||||
cd build
|
||||
appimage-builder --recipe ../dist/AppImageBuilder.yml
|
||||
mv ImHex-AppImage-x86_64.AppImage ../imhex.AppImage
|
||||
mv ImHex-AppImage-x86_64.AppImage ../imhex-${{env.version}}.AppImage
|
||||
cd ..
|
||||
|
||||
#- name: ⬆️ Upload Flatpak
|
||||
# uses: actions/upload-artifact@v2
|
||||
# uses: actions/upload-artifact@v3
|
||||
# with:
|
||||
# name: Linux Flatpak
|
||||
# path: |
|
||||
# imhex.flatpak
|
||||
|
||||
- name: ⬆️ Upload DEB
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Linux DEB
|
||||
path: |
|
||||
imhex.deb
|
||||
name: Linux DEB (Ubuntu 22.04)
|
||||
path: '*.deb'
|
||||
|
||||
- name: ⬆️ Upload AppImage
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Linux AppImage
|
||||
path: |
|
||||
imhex.AppImage
|
||||
path: '*.AppImage'
|
||||
|
||||
archlinux-build:
|
||||
name: 🐧 ArchLinux
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container:
|
||||
image: archlinux:base-devel
|
||||
|
||||
steps:
|
||||
- name: ⬇️ Update all packages
|
||||
run: |
|
||||
pacman -Syyu --noconfirm
|
||||
|
||||
- name: ⬇️ Install setup dependencies
|
||||
run: |
|
||||
pacman -Syu git ccache --noconfirm
|
||||
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: ⬇️ Install ImHex dependencies
|
||||
run: |
|
||||
dist/get_deps_archlinux.sh --noconfirm
|
||||
|
||||
- name: 📜 Restore ccache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cache/ccache
|
||||
key: archlinux-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: archlinux-${{ secrets.CACHE_VERSION }}-build
|
||||
|
||||
- name: 📜 Restore CMakeCache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
build/CMakeCache.txt
|
||||
key: archlinux-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: 🛠️ Build
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=gcc CXX=g++ cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
|
||||
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
|
||||
-DRUST_PATH="$HOME/.cargo/bin/" \
|
||||
..
|
||||
make -j 4 install DESTDIR=installDir
|
||||
|
||||
- name: 📜 Set version variable
|
||||
run: |
|
||||
echo "version=`cat VERSION`" >> $GITHUB_ENV
|
||||
|
||||
- name: ✒️ Prepare PKGBUILD
|
||||
run: |
|
||||
cp dist/Arch/PKGBUILD build
|
||||
sed -i 's/%version%/${{env.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
|
||||
run: |
|
||||
cd build
|
||||
|
||||
# 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.version}}-ArchLinux.pkg.tar.zst -C installDir .
|
||||
|
||||
chmod -R 777 .
|
||||
|
||||
sudo -u nobody makepkg
|
||||
|
||||
# Remplace the old file
|
||||
rm imhex-${{env.version}}-ArchLinux.pkg.tar.zst
|
||||
mv *.pkg.tar.zst imhex-${{env.version}}-ArchLinux.pkg.tar.zst
|
||||
|
||||
- name: ⬆️ Upload imhex-archlinux.pkg.tar.zst
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ArchLinux .pkg.tar.zst
|
||||
path: |
|
||||
build/imhex-${{env.version}}-ArchLinux.pkg.tar.zst
|
||||
|
||||
|
||||
92
.github/workflows/release.yml
vendored
Normal file
92
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
name: Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
name: Release
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: ImHex
|
||||
submodules: recursive
|
||||
|
||||
- name: 📜 Verify version and set version variable
|
||||
run: |
|
||||
project_version=`cat ImHex/VERSION`
|
||||
tag_version="${{github.event.release.tag_name}}"
|
||||
tag_version="${tag_version:1}"
|
||||
if [ "$project_version" != "$tag_version" ]; then
|
||||
echo "::warning::$project_version and $tag_version are not the same ! Refusing to populate release"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "version=$project_version" >> $GITHUB_ENV
|
||||
|
||||
- name: 🗜️ Create tarball from sources with dependencies
|
||||
run: tar -cvf Full.Sources.tar.gz ImHex
|
||||
|
||||
- name: ⬇️ Download artifacts from latest workflow
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
github_token: ${{secrets.GITHUB_TOKEN}}
|
||||
workflow: build.yml
|
||||
branch: ${{ github.event.release.target_commitish }}
|
||||
workflow_conclusion: success
|
||||
skip_unpack: true
|
||||
|
||||
- name: 🗜️ Unzip files when needed
|
||||
run: |
|
||||
for zipfile in ./*.zip
|
||||
do
|
||||
if [ `zipinfo -1 "$zipfile" | wc -l` -eq 1 ];
|
||||
then
|
||||
echo "unzipping $zipfile"
|
||||
unzip "$zipfile"
|
||||
rm "$zipfile"
|
||||
else
|
||||
echo "keeping $zipfile zipped"
|
||||
fi
|
||||
done
|
||||
|
||||
- name: 🟩 Rename Windows Portable Zip
|
||||
run: mv "Windows Portable.zip" imhex-${{env.version}}-Windows-Portable.zip
|
||||
|
||||
- name: ⬆️ Upload everything to release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
files: '*'
|
||||
|
||||
- name: ✒️ Prepare PKGBUILD
|
||||
run: |
|
||||
cp ImHex/dist/Arch/PKGBUILD .
|
||||
|
||||
hash=`md5sum imhex-${{env.version}}-ArchLinux.pkg.tar.zst | cut -d ' ' -f 1`
|
||||
|
||||
sed -i 's/%version%/${{env.version}}/g' PKGBUILD
|
||||
sed -i "s/(SKIP)/($hash)/g" PKGBUILD
|
||||
|
||||
- name: ⬆️ Publish AUR package
|
||||
|
||||
# I couldn't make the condition in the env directly for some reason
|
||||
env:
|
||||
MY_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
||||
if: "${{ env.MY_KEY != '' }}"
|
||||
|
||||
uses: KSXGitHub/github-actions-deploy-aur@v2
|
||||
with:
|
||||
pkgname: imhex-bin
|
||||
pkgbuild: ./PKGBUILD
|
||||
commit_username: iTrooz
|
||||
commit_email: itrooz@protonmail.com
|
||||
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
||||
commit_message: Bump to version ${{env.version}}
|
||||
ssh_keyscan_types: rsa,dsa,ecdsa,ed25519
|
||||
26
.github/workflows/tests.yml
vendored
26
.github/workflows/tests.yml
vendored
@@ -5,11 +5,12 @@ on:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: 🧪 Unit Tests
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
@@ -17,19 +18,26 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- name: 📜 Restore cache
|
||||
uses: actions/cache@v2
|
||||
- name: 📜 Restore ccache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.ccache
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
~/.cache/ccache
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build
|
||||
|
||||
|
||||
- name: 📜 Restore CMakeCache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
build/CMakeCache.txt
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
@@ -39,7 +47,7 @@ jobs:
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=gcc-10 CXX=g++-10 cmake \
|
||||
CC=gcc-12 CXX=g++-12 cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# Updating the version here will update it throughout ImHex as well
|
||||
set(IMHEX_VERSION "1.18.0")
|
||||
file(READ "VERSION" IMHEX_VERSION)
|
||||
project(imhex VERSION ${IMHEX_VERSION})
|
||||
message("Project version ${IMHEX_VERSION}")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(IMHEX_BASE_FOLDER ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
@@ -36,6 +37,3 @@ add_subdirectory(tests EXCLUDE_FROM_ALL)
|
||||
|
||||
# Configure packaging
|
||||
createPackage()
|
||||
|
||||
# Download and install all current files from the ImHex-Patterns repo
|
||||
downloadImHexPatternsFiles()
|
||||
|
||||
91
README.md
91
README.md
@@ -127,103 +127,16 @@ Nightlies are available via GitHub Actions [here](https://github.com/WerWolv/ImH
|
||||
- MacOS • __x86_64__
|
||||
- [DMG](https://nightly.link/WerWolv/ImHex/workflows/build/master/macOS%20DMG.zip)
|
||||
- Linux • __x86_64__
|
||||
- [ELF](https://nightly.link/WerWolv/ImHex/workflows/build/master/Linux%20ELF.zip)
|
||||
- [DEB](https://nightly.link/WerWolv/ImHex/workflows/build/master/Linux%20DEB.zip)
|
||||
- [Flatpak](https://nightly.link/WerWolv/ImHex/workflows/build/master/Linux%20Flatpak.zip)
|
||||
- [AppImage](https://nightly.link/WerWolv/ImHex/workflows/build/master/Linux%20AppImage.zip)
|
||||
|
||||
## Compiling
|
||||
|
||||
You need a C++20 compatible compiler such as GCC 10.2.0 to compile ImHex.
|
||||
To compile ImHex, a C++20 compiler is required. Releases are all mainly built using GCC, however on macOS, clang is also required to compile some ObjC code.
|
||||
|
||||
Many dependencies are bundled into the repository using submodules so make sure to clone it using the `--recurse-submodules` option.
|
||||
All dependencies that aren't bundled, can be installed using the dependency installer scripts found in the `/dist` folder.
|
||||
|
||||
For working examples
|
||||
|
||||
### Windows
|
||||
|
||||
On Windows, ImHex is built through msys2 / mingw. To install all dependencies, open a mys2 window and run the PKGCONFIG script in the [dist/msys2](dist/msys2) folder.
|
||||
After all the dependencies are installed, run the following commands to build ImHex:
|
||||
|
||||
```sh
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
make -j
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
To create a standalone zipfile on Windows, get the Python standard library (e.g. from https://github.com/python/cpython/tree/master/Lib) and place the files and folders in `lib/python3.8` next to your built executable. Don't forget to also copy the `libpython3.8.dll` and `libwinpthread-1.dll` from your mingw setup next to the executable.
|
||||
|
||||
- Copy the files inside the `/resources/lib/python` folder into the `lib` folder next to your built executable.
|
||||
- Place your magic databases in the `magic` folder next to your built executable
|
||||
- Place your patterns in the `pattern` folder next to your built executable
|
||||
- Place your include pattern files in the `include` folder next to your built executable
|
||||
|
||||
### macOS
|
||||
|
||||
To build ImHex on macOS, run the following commands:
|
||||
|
||||
```sh
|
||||
brew bundle --no-lock --file dist/Brewfile
|
||||
mkdir build
|
||||
cd build
|
||||
CC=$(brew --prefix llvm)/bin/clang CXX=$(brew --prefix llvm)/bin/clang++ PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
make -j
|
||||
```
|
||||
|
||||
Install the ImHex executable as well as libimhex.dylib to wherever ImHex should be installed.
|
||||
|
||||
All other files belong in `~/Library/Application Support/imhex`:
|
||||
```
|
||||
Patterns: ~/Library/Application Support/imhex/patterns
|
||||
Pattern Includes: ~/Library/Application Support/imhex/includes
|
||||
Magic files: ~/Library/Application Support/imhex/magic
|
||||
Python: ~/Library/Application Support/imhex/lib/pythonX.X
|
||||
Plugins: ~/Library/Application Support/imhex/plugins
|
||||
Configuration: ~/Library/Application Support/imhex/config
|
||||
Resources: ~/Library/Application Support/imhex/resources
|
||||
```
|
||||
|
||||
If the build fails while trying to find the macOS libraries, make sure you have
|
||||
XCode installed with `xcode-select --install`. Homebrew will also help get the
|
||||
most recent SDK installed and configured with `brew doctor`.
|
||||
|
||||
### Linux
|
||||
|
||||
Dependency installation scripts are available for many common Linux distributions in the [/dist](dist) folder.
|
||||
After all the dependencies are installed, run the following commands to build ImHex:
|
||||
|
||||
```sh
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
make -j
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Put the ImHex executable into the `/usr/bin` folder.
|
||||
Put libimhex.so into the `/usr/lib` folder.
|
||||
Configuration files go to `/etc/xdg/imhex` or `~/.config/imhex`.
|
||||
All other files belong in `/usr/share/imhex` or `~/.local/share/imhex`:
|
||||
|
||||
```
|
||||
Patterns: /usr/share/imhex/patterns
|
||||
Pattern Includes: /usr/share/imhex/includes
|
||||
Magic files: /usr/share/imhex/magic
|
||||
Python: /usr/share/imhex/lib/pythonX.X
|
||||
Plugins: /usr/share/imhex/plugins
|
||||
Configuration: /etc/xdg/imhex/config
|
||||
Resources: /usr/share/imhex/resources
|
||||
```
|
||||
|
||||
All paths follow the XDG Base Directories standard, and can thus be modified
|
||||
with the environment variables `XDG_CONFIG_HOME`, `XDG_CONFIG_DIRS`,
|
||||
`XDG_DATA_HOME` and `XDG_DATA_DIRS`.
|
||||
|
||||
## Credits
|
||||
|
||||
### Contributors
|
||||
@@ -231,6 +144,8 @@ with the environment variables `XDG_CONFIG_HOME`, `XDG_CONFIG_DIRS`,
|
||||
- [Mary](https://github.com/Thog) for her immense help porting ImHex to MacOS and help during development
|
||||
- [Roblabla](https://github.com/Roblabla) for adding MSI Installer support to ImHex
|
||||
- [jam1garner](https://github.com/jam1garner) and [raytwo](https://github.com/raytwo) for their help with adding Rust support to plugins
|
||||
- [Mailaender](https://github.com/Mailaender) for getting ImHex onto Flathub
|
||||
- [iTrooz](https://github.com/iTrooz) for many improvements related to release packaging and the GitHub Action runners.
|
||||
- Everybody else who has reported issues on Discord or GitHub that I had great conversations with :)
|
||||
|
||||
### Libraries
|
||||
|
||||
@@ -70,19 +70,18 @@ macro(detectOS)
|
||||
set(CMAKE_INSTALL_BINDIR ".")
|
||||
set(CMAKE_INSTALL_LIBDIR ".")
|
||||
set(PLUGINS_INSTALL_LOCATION "plugins")
|
||||
set(MAGIC_INSTALL_LOCATION "magic")
|
||||
elseif (APPLE)
|
||||
add_compile_definitions(OS_MACOS)
|
||||
set(CMAKE_INSTALL_BINDIR ".")
|
||||
set(CMAKE_INSTALL_LIBDIR ".")
|
||||
set(PLUGINS_INSTALL_LOCATION "plugins")
|
||||
set(MAGIC_INSTALL_LOCATION "magic")
|
||||
enable_language(OBJC)
|
||||
enable_language(OBJCXX)
|
||||
elseif (UNIX AND NOT APPLE)
|
||||
add_compile_definitions(OS_LINUX)
|
||||
set(CMAKE_INSTALL_BINDIR "bin")
|
||||
set(CMAKE_INSTALL_LIBDIR "lib")
|
||||
set(PLUGINS_INSTALL_LOCATION "share/imhex/plugins")
|
||||
set(MAGIC_INSTALL_LOCATION "share/imhex/magic")
|
||||
else ()
|
||||
message(FATAL_ERROR "Unknown / unsupported system!")
|
||||
endif()
|
||||
@@ -133,14 +132,14 @@ macro(configurePackingResources)
|
||||
set(MACOSX_BUNDLE_INFO_STRING "WerWolv")
|
||||
set(MACOSX_BUNDLE_BUNDLE_NAME "ImHex")
|
||||
set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||
set(MACOSX_BUNDLE_GUI_IDENTIFIER "WerWolv.ImHex")
|
||||
set(MACOSX_BUNDLE_GUI_IDENTIFIER "net.WerWolv.ImHex")
|
||||
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_VERSION}-${GIT_COMMIT_HASH}")
|
||||
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
||||
set(MACOSX_BUNDLE_COPYRIGHT "Copyright © 2020 WerWolv and Thog. All rights reserved." )
|
||||
if ("${CMAKE_GENERATOR}" STREQUAL "Xcode")
|
||||
set ( bundle_path "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/imhex.app" )
|
||||
set ( bundle_path "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/ImHex.app" )
|
||||
else ()
|
||||
set ( bundle_path "${CMAKE_BINARY_DIR}/imhex.app" )
|
||||
set ( bundle_path "${CMAKE_BINARY_DIR}/ImHex.app" )
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@@ -151,11 +150,11 @@ macro(createPackage)
|
||||
foreach (plugin IN LISTS PLUGINS)
|
||||
add_subdirectory("plugins/${plugin}")
|
||||
if (TARGET ${plugin})
|
||||
set_target_properties(${plugin} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
|
||||
set_target_properties(${plugin} PROPERTIES CARGO_BUILD_TARGET_DIR ${CMAKE_BINARY_DIR}/plugins)
|
||||
|
||||
get_target_property(IS_RUST_PROJECT ${plugin} RUST_PROJECT)
|
||||
|
||||
set_target_properties(${plugin} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
|
||||
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
|
||||
|
||||
if (IS_RUST_PROJECT)
|
||||
set_target_properties(${plugin} PROPERTIES CARGO_BUILD_TARGET_DIR ${CMAKE_BINARY_DIR}/plugins)
|
||||
|
||||
@@ -163,7 +162,6 @@ macro(createPackage)
|
||||
|
||||
install(FILES "${PLUGIN_LOCATION}/../${plugin}.hexplug" DESTINATION "${PLUGINS_INSTALL_LOCATION}")
|
||||
else ()
|
||||
set_target_properties(${plugin} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
|
||||
if (WIN32)
|
||||
install(TARGETS ${plugin} RUNTIME DESTINATION ${PLUGINS_INSTALL_LOCATION})
|
||||
elseif (APPLE)
|
||||
@@ -181,7 +179,6 @@ macro(createPackage)
|
||||
endif ()
|
||||
endforeach()
|
||||
|
||||
install(FILES "$<TARGET_FILE:libimhex>" DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
set_target_properties(libimhex PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
if (WIN32)
|
||||
@@ -218,12 +215,19 @@ macro(createPackage)
|
||||
)
|
||||
endforeach()
|
||||
]])
|
||||
|
||||
install(FILES "$<TARGET_FILE:libimhex>" DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
downloadImHexPatternsFiles("./")
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/dist/DEBIAN/control.in ${CMAKE_BINARY_DIR}/DEBIAN/control)
|
||||
|
||||
configure_file(${CMAKE_SOURCE_DIR}/dist/DEBIAN/control.in ${CMAKE_BINARY_DIR}/DEBIAN/control)
|
||||
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/resources/icon.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.png)
|
||||
install(FILES "$<TARGET_FILE:libimhex>" DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
downloadImHexPatternsFiles("./share/imhex")
|
||||
endif()
|
||||
|
||||
|
||||
if (CREATE_BUNDLE)
|
||||
include(PostprocessBundle)
|
||||
|
||||
@@ -234,20 +238,21 @@ macro(createPackage)
|
||||
add_custom_target(build-time-make-plugins-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${bundle_path}/Contents/MacOS/plugins")
|
||||
add_custom_target(build-time-make-resources-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${bundle_path}/Contents/Resources")
|
||||
|
||||
downloadImHexPatternsFiles("${bundle_path}/Contents/MacOS")
|
||||
|
||||
install(FILES ${IMHEX_ICON} DESTINATION "${bundle_path}/Contents/Resources")
|
||||
install(TARGETS main BUNDLE DESTINATION ".")
|
||||
install(FILES $<TARGET_FILE:main> DESTINATION "${bundle_path}")
|
||||
|
||||
# Update library references to make the bundle portable
|
||||
postprocess_bundle(imhex_all main)
|
||||
|
||||
# Enforce DragNDrop packaging.
|
||||
set(CPACK_GENERATOR "DragNDrop")
|
||||
|
||||
install(TARGETS main BUNDLE DESTINATION .)
|
||||
else()
|
||||
install(TARGETS main RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
|
||||
|
||||
if (CREATE_PACKAGE)
|
||||
include(apple)
|
||||
include(CPack)
|
||||
@@ -283,7 +288,7 @@ macro(detectBadClone)
|
||||
endmacro()
|
||||
|
||||
|
||||
function(downloadImHexPatternsFiles)
|
||||
function(downloadImHexPatternsFiles dest)
|
||||
FetchContent_Declare(
|
||||
imhex_patterns
|
||||
GIT_REPOSITORY https://github.com/WerWolv/ImHex-Patterns.git
|
||||
@@ -294,7 +299,7 @@ function(downloadImHexPatternsFiles)
|
||||
|
||||
set(PATTERNS_FOLDERS_TO_INSTALL constants encodings includes patterns magic)
|
||||
foreach (FOLDER ${PATTERNS_FOLDERS_TO_INSTALL})
|
||||
install(DIRECTORY "${imhex_patterns_SOURCE_DIR}/${FOLDER}" DESTINATION "./")
|
||||
install(DIRECTORY "${imhex_patterns_SOURCE_DIR}/${FOLDER}" DESTINATION ${dest})
|
||||
endforeach()
|
||||
|
||||
endfunction()
|
||||
65
dist/AppImageBuilder.yml
vendored
65
dist/AppImageBuilder.yml
vendored
@@ -1,21 +1,7 @@
|
||||
# appimage-builder recipe see https://appimage-builder.readthedocs.io for details
|
||||
version: 1
|
||||
script:
|
||||
- rm -rf AppDir | true
|
||||
- CC=gcc-11 CXX=g++11 cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
||||
- make -j3 install DESTDIR=AppDir
|
||||
- mv AppDir/usr/share/imhex/plugins AppDir/usr/bin/plugins
|
||||
- mv AppDir/usr/constants AppDir/usr/bin/constants
|
||||
- mv AppDir/usr/encodings AppDir/usr/bin/encodings
|
||||
- mv AppDir/usr/includes AppDir/usr/bin/includes
|
||||
- mv AppDir/usr/magic AppDir/usr/bin/magic
|
||||
- mv AppDir/usr/patterns AppDir/usr/bin/patterns
|
||||
- mkdir -p AppDir/usr/share/icons/hicolor/512x512
|
||||
- cp AppDir/usr/share/pixmaps/imhex.png AppDir/usr/share/icons/hicolor/512x512/imhex.png
|
||||
|
||||
|
||||
AppDir:
|
||||
path: ./AppDir
|
||||
path: .AppDir
|
||||
app_info:
|
||||
id: imhex
|
||||
name: ImHex
|
||||
@@ -28,18 +14,20 @@ AppDir:
|
||||
- amd64
|
||||
allow_unauthenticated: true
|
||||
sources:
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ impish main restricted
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ impish-updates main restricted
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ impish universe
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ impish-updates universe
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ impish multiverse
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ impish-updates multiverse
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ impish-backports main restricted
|
||||
- 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://.archive.ubuntu.com/ubuntu/ jammy-backports main restricted
|
||||
universe multiverse
|
||||
- sourceline: deb http://security.ubuntu.com/ubuntu impish-security main restricted
|
||||
- sourceline: deb http://security.ubuntu.com/ubuntu impish-security universe
|
||||
- sourceline: deb http://security.ubuntu.com/ubuntu impish-security 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:
|
||||
- adwaita-icon-theme-full
|
||||
- librsvg2-common
|
||||
- libbz2-1.0:amd64
|
||||
- libcap2:amd64
|
||||
- libdbus-1-3:amd64
|
||||
@@ -53,7 +41,7 @@ AppDir:
|
||||
include:
|
||||
- /lib/x86_64-linux-gnu/libGLX.so.0
|
||||
- /lib/x86_64-linux-gnu/libGLdispatch.so.0
|
||||
- /lib/x86_64-linux-gnu/libLLVM-12.so.1
|
||||
- /lib/x86_64-linux-gnu/libLLVM-13.so.1
|
||||
- /lib/x86_64-linux-gnu/libOpenGL.so.0
|
||||
- /lib/x86_64-linux-gnu/libX11.so.6
|
||||
- /lib/x86_64-linux-gnu/libXau.so.6
|
||||
@@ -81,7 +69,7 @@ AppDir:
|
||||
- /lib/x86_64-linux-gnu/libedit.so.2
|
||||
- /lib/x86_64-linux-gnu/libelf.so.1
|
||||
- /lib/x86_64-linux-gnu/libepoxy.so.0
|
||||
- /lib/x86_64-linux-gnu/libffi.so.7
|
||||
- /lib/x86_64-linux-gnu/libffi.so.8
|
||||
- /lib/x86_64-linux-gnu/libfontconfig.so.1
|
||||
- /lib/x86_64-linux-gnu/libfreetype.so.6
|
||||
- /lib/x86_64-linux-gnu/libfribidi.so.0
|
||||
@@ -93,31 +81,42 @@ AppDir:
|
||||
- /lib/x86_64-linux-gnu/libglfw.so.3
|
||||
- /lib/x86_64-linux-gnu/libglib-2.0.so.0
|
||||
- /lib/x86_64-linux-gnu/libgmodule-2.0.so.0
|
||||
- /lib/x86_64-linux-gnu/libgmp.so.10
|
||||
- /lib/x86_64-linux-gnu/libgnutls.so.30
|
||||
- /lib/x86_64-linux-gnu/libgobject-2.0.so.0
|
||||
- /lib/x86_64-linux-gnu/libgraphite2.so.3
|
||||
- /lib/x86_64-linux-gnu/libgtk-3.so.0
|
||||
- /lib/x86_64-linux-gnu/libharfbuzz.so.0
|
||||
- /lib/x86_64-linux-gnu/libicudata.so.66
|
||||
- /lib/x86_64-linux-gnu/libicuuc.so.66
|
||||
- /lib/x86_64-linux-gnu/libhogweed.so.6
|
||||
- /lib/x86_64-linux-gnu/libicudata.so.70
|
||||
- /lib/x86_64-linux-gnu/libicuuc.so.70
|
||||
- /lib/x86_64-linux-gnu/libidn2.so.0
|
||||
- /lib/x86_64-linux-gnu/libjpeg.so.8
|
||||
- /lib/x86_64-linux-gnu/liblber-2.5.so.0
|
||||
- /lib/x86_64-linux-gnu/libldap-2.5.so.0
|
||||
- /lib/x86_64-linux-gnu/liblz4.so.1
|
||||
- /lib/x86_64-linux-gnu/libmagic.so.1
|
||||
- /lib/x86_64-linux-gnu/libmbedcrypto.so.3
|
||||
- /lib/x86_64-linux-gnu/libmbedtls.so.12
|
||||
- /lib/x86_64-linux-gnu/libmbedx509.so.0
|
||||
- /lib/x86_64-linux-gnu/libmbedcrypto.so.7
|
||||
- /lib/x86_64-linux-gnu/libmbedtls.so.14
|
||||
- /lib/x86_64-linux-gnu/libmbedx509.so.1
|
||||
- /lib/x86_64-linux-gnu/libmd.so.0
|
||||
- /lib/x86_64-linux-gnu/libmount.so.1
|
||||
- /lib/x86_64-linux-gnu/libnettle.so.8
|
||||
- /lib/x86_64-linux-gnu/libp11-kit.so.0
|
||||
- /lib/x86_64-linux-gnu/libpango-1.0.so.0
|
||||
- /lib/x86_64-linux-gnu/libpangocairo-1.0.so.0
|
||||
- /lib/x86_64-linux-gnu/libpangoft2-1.0.so.0
|
||||
- /lib/x86_64-linux-gnu/libpcre2-8.so.0
|
||||
- /lib/x86_64-linux-gnu/libpixman-1.so.0
|
||||
- /lib/x86_64-linux-gnu/libpng16.so.16
|
||||
- /lib/x86_64-linux-gnu/libpython3.8.so.1.0
|
||||
- /lib/x86_64-linux-gnu/libpython3.10.so.1.0
|
||||
- /lib/x86_64-linux-gnu/libsasl2.so.2
|
||||
- /lib/x86_64-linux-gnu/libsensors.so.5
|
||||
- /lib/x86_64-linux-gnu/libstdc++.so.6
|
||||
- /lib/x86_64-linux-gnu/libsystemd.so.0
|
||||
- /lib/x86_64-linux-gnu/libtasn1.so.6
|
||||
- /lib/x86_64-linux-gnu/libthai.so.0
|
||||
- /lib/x86_64-linux-gnu/libunistring.so.2
|
||||
- /lib/x86_64-linux-gnu/libuuid.so.1
|
||||
- /lib/x86_64-linux-gnu/libvulkan.so.1
|
||||
- /lib/x86_64-linux-gnu/libwayland-client.so.0
|
||||
|
||||
38
dist/Arch/PKGBUILD
vendored
Normal file
38
dist/Arch/PKGBUILD
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
# Maintainer: iTrooz_ <itrooz at protonmail dot com>
|
||||
pkgname=imhex-bin
|
||||
pkgver=%version%
|
||||
pkgrel=1
|
||||
pkgdesc="A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM. "
|
||||
arch=("x86_64")
|
||||
url="https://github.com/WerWolv/ImHex"
|
||||
repo=$url
|
||||
license=('GPL 2.0')
|
||||
groups=()
|
||||
depends=(glfw mbedtls python freetype2 libglvnd gtk3)
|
||||
makedepends=(git)
|
||||
checkdepends=()
|
||||
optdepends=()
|
||||
provides=(imhex)
|
||||
conflicts=(imhex)
|
||||
replaces=()
|
||||
backup=()
|
||||
options=()
|
||||
source=($repo"/releases/download/v$pkgver/imhex-$pkgver-ArchLinux.pkg.tar.zst")
|
||||
noextract=()
|
||||
md5sums=(SKIP)
|
||||
validpgpkeys=()
|
||||
|
||||
package() {
|
||||
tar -xf imhex-$pkgver-ArchLinux.pkg.tar.zst
|
||||
|
||||
install -DT $srcdir/usr/bin/imhex $pkgdir/usr/bin/imhex
|
||||
install -DT $srcdir/usr/lib/libimhex.so $pkgdir/usr/lib/libimhex.so
|
||||
|
||||
for plugin in $srcdir/usr/share/imhex/plugins/*.hexplug;
|
||||
do
|
||||
install -DT $plugin $pkgdir/usr/share/imhex/plugins/`basename $plugin`
|
||||
done
|
||||
|
||||
cp -r $srcdir/usr/share/imhex/{constants,encodings,includes,magic,patterns} $pkgdir/usr/share/imhex
|
||||
install -d $pkgdir/usr/share/imhex
|
||||
}
|
||||
3
dist/Brewfile
vendored
3
dist/Brewfile
vendored
@@ -7,6 +7,5 @@ brew "python3"
|
||||
brew "freetype2"
|
||||
brew "libmagic"
|
||||
brew "pkg-config"
|
||||
|
||||
# TODO: Remove this when XCode version of clang will support the same level as LLVM 10
|
||||
brew "llvm"
|
||||
brew "gcc@12"
|
||||
|
||||
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: libglfw3-dev, libmagic-dev, libmbedtls-dev, libcapstone-dev, python3-dev, libfreetype-dev, libgtk-3-dev, libldap2-dev
|
||||
Depends: libglfw3, libmagic1, libmbedtls14, libpython3.10, libfreetype6, libopengl0, libgtk-3-0
|
||||
Maintainer: WerWolv <hey@werwolv.net>
|
||||
Description: ImHex Hex Editor
|
||||
A Hex Editor for Reverse Engineers, Programmers and
|
||||
|
||||
41
dist/compiling/linux.md
vendored
Normal file
41
dist/compiling/linux.md
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
### Compiling ImHex on Linux
|
||||
|
||||
Dependency installation scripts are available for many common Linux distributions in the [/dist](dist) folder.
|
||||
After all the dependencies are installed, run the following commands to build ImHex:
|
||||
|
||||
```sh
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=gcc-12 CXX=g++-12 cmake \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
|
||||
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
|
||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
||||
-DRUST_PATH="$HOME/.cargo/bin/" \
|
||||
..
|
||||
make -j 4 install
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Put the ImHex executable into the `/usr/bin` folder.
|
||||
Put libimhex.so into the `/usr/lib` folder.
|
||||
Configuration files go to `/usr/etc/imhex` or `~/.config/imhex`.
|
||||
All other files belong in `/usr/share/imhex` or `~/.local/share/imhex`:
|
||||
|
||||
```
|
||||
Patterns: /usr/share/imhex/patterns
|
||||
Pattern Includes: /usr/share/imhex/includes
|
||||
Magic files: /usr/share/imhex/magic
|
||||
Python: /usr/share/imhex/lib/pythonX.X
|
||||
Plugins: /usr/share/imhex/plugins
|
||||
Configuration: /etc/xdg/imhex/config
|
||||
```
|
||||
|
||||
All paths follow the XDG Base Directories standard, and can thus be modified
|
||||
with the environment variables `XDG_CONFIG_HOME`, `XDG_CONFIG_DIRS`,
|
||||
`XDG_DATA_HOME` and `XDG_DATA_DIRS`.
|
||||
41
dist/compiling/macOS.md
vendored
Normal file
41
dist/compiling/macOS.md
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
### Compiling ImHex on macOS
|
||||
|
||||
To build ImHex on macOS, run the following commands:
|
||||
|
||||
```sh
|
||||
brew bundle --no-lock --file dist/Brewfile
|
||||
mkdir -p build
|
||||
cd build
|
||||
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" \
|
||||
MACOSX_DEPLOYMENT_TARGET="10.15" \
|
||||
cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCREATE_BUNDLE=ON \
|
||||
-DCREATE_PACKAGE=ON \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
||||
..
|
||||
make -j4 package
|
||||
```
|
||||
|
||||
Open the generated .dmg file and drag-n-drop the ImHex executable to the Applications folder
|
||||
|
||||
All other files belong in `~/Library/Application Support/imhex`:
|
||||
```
|
||||
Patterns: ~/Library/Application Support/imhex/patterns
|
||||
Pattern Includes: ~/Library/Application Support/imhex/includes
|
||||
Magic files: ~/Library/Application Support/imhex/magic
|
||||
Python: ~/Library/Application Support/imhex/lib/pythonX.X
|
||||
Plugins: ~/Library/Application Support/imhex/plugins
|
||||
Configuration: ~/Library/Application Support/imhex/config
|
||||
```
|
||||
|
||||
If the build fails while trying to find the macOS libraries, make sure you have
|
||||
XCode installed with `xcode-select --install`. Homebrew will also help get the
|
||||
most recent SDK installed and configured with `brew doctor`.
|
||||
23
dist/compiling/windows.md
vendored
Normal file
23
dist/compiling/windows.md
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
### Compiling ImHex on Windows
|
||||
|
||||
On Windows, ImHex is built through msys2 / mingw. To install all dependencies, open a mys2 window and run the PKGCONFIG script in the [dist/msys2](dist/msys2) folder.
|
||||
After all the dependencies are installed, run the following commands to build ImHex:
|
||||
|
||||
```sh
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G "MinGW Makefiles" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
|
||||
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
|
||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
||||
-DRUST_PATH="$USERPROFILE/.cargo/bin/" \
|
||||
..
|
||||
mingw32-make -j install
|
||||
```
|
||||
|
||||
ImHex will look for any extra resources either in various folders directly next to the executable or in `%localappdata%/imhex`
|
||||
2
dist/get_deps_archlinux.sh
vendored
2
dist/get_deps_archlinux.sh
vendored
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
pacman -S --needed \
|
||||
pacman -S $@ --needed \
|
||||
cmake \
|
||||
gcc \
|
||||
lld \
|
||||
|
||||
13
dist/get_deps_debian.sh
vendored
13
dist/get_deps_debian.sh
vendored
@@ -1,9 +1,5 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
echo "As of 2020-12, Debian stable does not include g++-10, needs debian testing or unstable."
|
||||
|
||||
# Tested on 2020-12-09 with Docker image bitnami/minideb:unstable
|
||||
|
||||
# Install pkgconf (adds minimum dependencies) only if the equivalent pkf-config is not already installed.
|
||||
if ! which pkg-config
|
||||
then
|
||||
@@ -12,8 +8,8 @@ fi
|
||||
|
||||
apt install -y \
|
||||
build-essential \
|
||||
gcc-11 \
|
||||
g++-11 \
|
||||
gcc-12 \
|
||||
g++-12 \
|
||||
lld \
|
||||
${PKGCONF:-} \
|
||||
cmake \
|
||||
@@ -25,7 +21,4 @@ apt install -y \
|
||||
libmbedtls-dev \
|
||||
python3-dev \
|
||||
libfreetype-dev \
|
||||
libgtk-3-dev \
|
||||
|
||||
echo "Please consider this before running cmake (useful on e.g. Ubuntu 20.04):"
|
||||
echo "export CXX=g++-11"
|
||||
libgtk-3-dev
|
||||
2
lib/external/imgui/source/TextEditor.cpp
vendored
2
lib/external/imgui/source/TextEditor.cpp
vendored
@@ -821,7 +821,7 @@ void TextEditor::Render() {
|
||||
ImGui::Text("Error at line %d:", errorIt->first);
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::Separator();
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 0.2f, 1.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.5f, 0.5f, 0.2f, 1.0f));
|
||||
ImGui::Text("%s", errorIt->second.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::EndTooltip();
|
||||
|
||||
58
lib/external/imgui/source/imgui_impl_glfw.cpp
vendored
58
lib/external/imgui/source/imgui_impl_glfw.cpp
vendored
@@ -47,6 +47,7 @@
|
||||
// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h"
|
||||
#include "imgui_impl_glfw.h"
|
||||
|
||||
// GLFW
|
||||
@@ -136,6 +137,51 @@ static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text)
|
||||
glfwSetClipboardString((GLFWwindow*)user_data, text);
|
||||
}
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
static const char* ImGui_ImplWin_GetClipboardText(void*)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
g.ClipboardHandlerData.clear();
|
||||
if (!::OpenClipboard(NULL))
|
||||
return NULL;
|
||||
HANDLE wbuf_handle = ::GetClipboardData(CF_UNICODETEXT);
|
||||
if (wbuf_handle == NULL)
|
||||
{
|
||||
::CloseClipboard();
|
||||
return NULL;
|
||||
}
|
||||
if (const WCHAR* wbuf_global = (const WCHAR*)::GlobalLock(wbuf_handle))
|
||||
{
|
||||
int buf_len = ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, NULL, 0, NULL, NULL);
|
||||
g.ClipboardHandlerData.resize(buf_len);
|
||||
::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, g.ClipboardHandlerData.Data, buf_len, NULL, NULL);
|
||||
}
|
||||
::GlobalUnlock(wbuf_handle);
|
||||
::CloseClipboard();
|
||||
return g.ClipboardHandlerData.Data;
|
||||
}
|
||||
|
||||
static void ImGui_ImplWin_SetClipboardText(void*, const char* text)
|
||||
{
|
||||
if (!::OpenClipboard(NULL))
|
||||
return;
|
||||
const int wbuf_length = ::MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0);
|
||||
HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(WCHAR));
|
||||
if (wbuf_handle == NULL)
|
||||
{
|
||||
::CloseClipboard();
|
||||
return;
|
||||
}
|
||||
WCHAR* wbuf_global = (WCHAR*)::GlobalLock(wbuf_handle);
|
||||
::MultiByteToWideChar(CP_UTF8, 0, text, -1, wbuf_global, wbuf_length);
|
||||
::GlobalUnlock(wbuf_handle);
|
||||
::EmptyClipboard();
|
||||
if (::SetClipboardData(CF_UNICODETEXT, wbuf_handle) == NULL)
|
||||
::GlobalFree(wbuf_handle);
|
||||
::CloseClipboard();
|
||||
}
|
||||
#endif
|
||||
|
||||
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
|
||||
{
|
||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
||||
@@ -271,9 +317,15 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||
io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y;
|
||||
io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z;
|
||||
|
||||
io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
|
||||
io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
|
||||
io.ClipboardUserData = bd->Window;
|
||||
#if defined(OS_WINDOWS)
|
||||
io.SetClipboardTextFn = ImGui_ImplWin_SetClipboardText;
|
||||
io.GetClipboardTextFn = ImGui_ImplWin_GetClipboardText;
|
||||
io.ClipboardUserData = bd->Window;
|
||||
#else
|
||||
io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
|
||||
io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
|
||||
io.ClipboardUserData = bd->Window;
|
||||
#endif
|
||||
|
||||
// Create mouse cursors
|
||||
// (By design, on X11 cursors are user configurable and some cursors may be missing. When a cursor doesn't exist,
|
||||
|
||||
2
lib/external/libromfs
vendored
2
lib/external/libromfs
vendored
Submodule lib/external/libromfs updated: f14e88a727...12063078f0
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
Submodule lib/external/pattern_language updated: 99f3be2cc2...5ab770490e
8
lib/libimhex-rs/Cargo.lock
generated
8
lib/libimhex-rs/Cargo.lock
generated
@@ -568,9 +568,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.4"
|
||||
version = "1.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
|
||||
checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -579,9 +579,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.25"
|
||||
version = "0.6.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
|
||||
@@ -10,6 +10,7 @@ set_target_properties(imgui PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../external/microtar ${CMAKE_CURRENT_BINARY_DIR}/external/microtar EXCLUDE_FROM_ALL)
|
||||
set_target_properties(microtar PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
set(NFD_PORTAL ON CACHE BOOL "Use Portals for Linux file dialogs" FORCE)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../external/nativefiledialog ${CMAKE_CURRENT_BINARY_DIR}/external/nativefiledialog EXCLUDE_FROM_ALL)
|
||||
set_target_properties(nfd PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
@@ -123,14 +124,14 @@ set(LIBIMHEX_SOURCES
|
||||
source/helpers/patches.cpp
|
||||
source/helpers/project_file_handler.cpp
|
||||
source/helpers/encoding_file.cpp
|
||||
source/helpers/loader_script_handler.cpp
|
||||
source/helpers/logger.cpp
|
||||
source/helpers/tar.cpp
|
||||
|
||||
source/providers/provider.cpp
|
||||
|
||||
source/ui/imgui_imhex_extensions.cpp
|
||||
source/ui/view.cpp
|
||||
)
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
set(OSX_11_0_SDK_PATH /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk)
|
||||
@@ -142,7 +143,9 @@ if (APPLE)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
set(LIBIMHEX_SOURCES ${LIBIMHEX_SOURCES} source/helpers/fs_macos.mm)
|
||||
set(LIBIMHEX_SOURCES ${LIBIMHEX_SOURCES}
|
||||
source/helpers/fs_macos.m
|
||||
source/helpers/utils_macos.m)
|
||||
endif ()
|
||||
|
||||
add_compile_definitions(IMHEX_PROJECT_NAME="${PROJECT_NAME}")
|
||||
|
||||
@@ -3,46 +3,8 @@
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
#include <hex/helpers/types.hpp>
|
||||
#include <hex/helpers/intrinsics.hpp>
|
||||
|
||||
constexpr static const auto ImHexApiURL = "https://api.werwolv.net/imhex";
|
||||
constexpr static const auto GitHubApiURL = "https://api.github.com/repos/WerWolv/ImHex";
|
||||
|
||||
using u8 = std::uint8_t;
|
||||
using u16 = std::uint16_t;
|
||||
using u32 = std::uint32_t;
|
||||
using u64 = std::uint64_t;
|
||||
using u128 = __uint128_t;
|
||||
|
||||
using i8 = std::int8_t;
|
||||
using i16 = std::int16_t;
|
||||
using i32 = std::int32_t;
|
||||
using i64 = std::int64_t;
|
||||
using i128 = __int128_t;
|
||||
|
||||
using color_t = u32;
|
||||
|
||||
namespace hex {
|
||||
|
||||
struct Region {
|
||||
u64 address;
|
||||
size_t size;
|
||||
|
||||
[[nodiscard]] constexpr bool isWithin(const Region &other) const {
|
||||
return (this->address >= other.address) && ((this->address + this->size) <= (other.address + other.size));
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool overlaps(const Region &other) const {
|
||||
return ((this->address + this->size) >= other.address) && (this->address < (other.address + other.size));
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr u64 getStartAddress() const {
|
||||
return this->address;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr u64 getEndAddress() const {
|
||||
return this->address + this->size - 1;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
template<hex::derived_from<View> T, typename... Args>
|
||||
template<std::derived_from<View> T, typename... Args>
|
||||
void add(Args &&...args) {
|
||||
return impl::add(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
@@ -234,7 +234,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
template<hex::derived_from<dp::Node> T, typename... Args>
|
||||
template<std::derived_from<dp::Node> T, typename... Args>
|
||||
void add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, Args &&...args) {
|
||||
add(impl::Entry { unlocalizedCategory.c_str(), unlocalizedName.c_str(), [=] {
|
||||
auto node = new T(std::forward<Args>(args)...);
|
||||
@@ -326,7 +326,7 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
template<hex::derived_from<hex::prv::Provider> T>
|
||||
template<std::derived_from<hex::prv::Provider> T>
|
||||
void add(const std::string &unlocalizedName, bool addToList = true) {
|
||||
(void)EventManager::subscribe<RequestCreateProvider>([expectedName = unlocalizedName](const std::string &name, hex::prv::Provider **provider) {
|
||||
if (name != expectedName) return;
|
||||
@@ -415,12 +415,80 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
template<hex::derived_from<DataVisualizer> T, typename... Args>
|
||||
template<std::derived_from<DataVisualizer> T, typename... Args>
|
||||
void addDataVisualizer(const std::string &unlocalizedName, Args &&...args) {
|
||||
return impl::addDataVisualizer(unlocalizedName, new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Hashes {
|
||||
|
||||
class Hash {
|
||||
public:
|
||||
Hash(std::string unlocalizedName) : m_unlocalizedName(std::move(unlocalizedName)) {}
|
||||
|
||||
class Function {
|
||||
public:
|
||||
using Callback = std::function<std::vector<u8>(const Region&, prv::Provider *)>;
|
||||
|
||||
Function(const Hash *type, std::string name, Callback callback)
|
||||
: m_type(type), m_name(std::move(name)), m_callback(std::move(callback)) {
|
||||
|
||||
}
|
||||
|
||||
[[nodiscard]] const Hash *getType() const { return this->m_type; }
|
||||
[[nodiscard]] const std::string &getName() const { return this->m_name; }
|
||||
|
||||
const std::vector<u8>& get(const Region& region, prv::Provider *provider) {
|
||||
if (this->m_cache.empty()) {
|
||||
this->m_cache = this->m_callback(region, provider);
|
||||
}
|
||||
|
||||
return this->m_cache;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
this->m_cache.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
const Hash *m_type;
|
||||
std::string m_name;
|
||||
Callback m_callback;
|
||||
|
||||
std::vector<u8> m_cache;
|
||||
};
|
||||
|
||||
virtual void draw() { }
|
||||
[[nodiscard]] virtual Function create(std::string name) = 0;
|
||||
|
||||
[[nodiscard]] const std::string &getUnlocalizedName() const {
|
||||
return this->m_unlocalizedName;
|
||||
}
|
||||
|
||||
protected:
|
||||
[[nodiscard]] Function create(const std::string &name, const Function::Callback &callback) const {
|
||||
return { this, name, callback };
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_unlocalizedName;
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
std::vector<Hash*> &getHashes();
|
||||
|
||||
void add(Hash* hash);
|
||||
}
|
||||
|
||||
template<typename T, typename ... Args>
|
||||
void add(Args && ... args) {
|
||||
impl::add(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -129,6 +129,12 @@ namespace hex {
|
||||
EVENT_DEF(RequestOpenPopup, std::string);
|
||||
EVENT_DEF(RequestCreateProvider, std::string, hex::prv::Provider **);
|
||||
|
||||
EVENT_DEF(RequestShowInfoPopup, std::string);
|
||||
EVENT_DEF(RequestShowErrorPopup, std::string);
|
||||
EVENT_DEF(RequestShowFatalErrorPopup, std::string);
|
||||
EVENT_DEF(RequestShowYesNoQuestionPopup, std::string, std::function<void()>, std::function<void()>);
|
||||
EVENT_DEF(RequestShowFileChooserPopup, std::vector<std::fs::path>, std::vector<nfdfilteritem_t>, std::function<void(std::fs::path)>);
|
||||
|
||||
EVENT_DEF(QuerySelection, std::optional<Region> &);
|
||||
|
||||
}
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <hex/helpers/concepts.hpp>
|
||||
#include <hex/api/task.hpp>
|
||||
#include <hex/api/keybinding.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
using ImGuiID = unsigned int;
|
||||
struct ImVec2;
|
||||
@@ -127,7 +128,7 @@ namespace hex {
|
||||
|
||||
void add(prv::Provider *provider);
|
||||
|
||||
template<hex::derived_from<prv::Provider> T>
|
||||
template<std::derived_from<prv::Provider> T>
|
||||
void add(auto &&...args) {
|
||||
add(new T(std::forward<decltype(args)>(args)...));
|
||||
}
|
||||
@@ -158,6 +159,11 @@ namespace hex {
|
||||
void setProgramArguments(int argc, char **argv, char **envp);
|
||||
|
||||
void setBorderlessWindowMode(bool enabled);
|
||||
|
||||
void setCustomFontPath(const std::fs::path &path);
|
||||
void setFontSize(float size);
|
||||
|
||||
void setGPUVendor(const std::string &vendor);
|
||||
}
|
||||
|
||||
struct ProgramArguments {
|
||||
@@ -166,6 +172,12 @@ namespace hex {
|
||||
char **envp;
|
||||
};
|
||||
|
||||
enum class Theme {
|
||||
Dark = 1,
|
||||
Light = 2,
|
||||
Classic = 3
|
||||
};
|
||||
|
||||
const ProgramArguments &getProgramArguments();
|
||||
|
||||
float getTargetFPS();
|
||||
@@ -181,6 +193,19 @@ namespace hex {
|
||||
|
||||
std::map<std::string, std::string> &getInitArguments();
|
||||
|
||||
const std::fs::path &getCustomFontPath();
|
||||
float getFontSize();
|
||||
|
||||
void setTheme(Theme theme);
|
||||
Theme getTheme();
|
||||
|
||||
void enableSystemThemeDetection(bool enabled);
|
||||
bool usesSystemThemeDetection();
|
||||
|
||||
const std::vector<std::fs::path> &getAdditionalFolderPaths();
|
||||
void setAdditionalFolderPaths(const std::vector<std::fs::path> &paths);
|
||||
|
||||
const std::string &getGPUVendor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
struct ImGuiContext;
|
||||
|
||||
namespace hex {
|
||||
@@ -39,7 +45,11 @@ namespace hex {
|
||||
using SetImGuiContextFunc = void (*)(ImGuiContext *);
|
||||
using IsBuiltinPluginFunc = bool (*)();
|
||||
|
||||
void *m_handle = nullptr;
|
||||
#if defined(OS_WINDOWS)
|
||||
HMODULE m_handle = nullptr;
|
||||
#else
|
||||
void *m_handle = nullptr;
|
||||
#endif
|
||||
std::fs::path m_path;
|
||||
|
||||
mutable bool m_initialized = false;
|
||||
|
||||
@@ -5,151 +5,7 @@
|
||||
#include <type_traits>
|
||||
#include <memory>
|
||||
|
||||
namespace hex {
|
||||
|
||||
template<typename>
|
||||
struct is_integral_helper : public std::false_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<u8> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<i8> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<u16> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<i16> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<u32> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<i32> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<u64> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<i64> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<u128> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<i128> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<bool> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<char> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<char8_t> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<char16_t> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<char32_t> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<wchar_t> : public std::true_type { };
|
||||
|
||||
template<typename T>
|
||||
struct is_integral : public is_integral_helper<std::remove_cvref_t<T>>::type { };
|
||||
|
||||
|
||||
template<typename>
|
||||
struct is_signed_helper : public std::false_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<i8> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<i16> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<i32> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<i64> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<i128> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<char> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<float> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<double> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<long double> : public std::true_type { };
|
||||
|
||||
template<typename T>
|
||||
struct is_signed : public is_signed_helper<std::remove_cvref_t<T>>::type { };
|
||||
|
||||
|
||||
template<typename>
|
||||
struct is_floating_point_helper : public std::false_type { };
|
||||
|
||||
template<>
|
||||
struct is_floating_point_helper<float> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_floating_point_helper<double> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_floating_point_helper<long double> : public std::true_type { };
|
||||
|
||||
template<typename T>
|
||||
struct is_floating_point : public is_floating_point_helper<std::remove_cvref_t<T>>::type { };
|
||||
|
||||
}
|
||||
|
||||
#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 12000
|
||||
#if __has_include(<concepts>)
|
||||
// Make sure we break when derived_from is implemented in libc++. Then we can fix a compatibility version above
|
||||
#include <concepts>
|
||||
#endif
|
||||
// libcxx 12 still doesn't have many default concepts implemented, as a result we need to define it ourself using clang built-ins.
|
||||
// [concept.derived] (patch from https://reviews.llvm.org/D74292)
|
||||
namespace hex {
|
||||
template<class _Dp, class _Bp>
|
||||
concept derived_from =
|
||||
__is_base_of(_Bp, _Dp) && __is_convertible_to(const volatile _Dp *, const volatile _Bp *);
|
||||
}
|
||||
|
||||
#else
|
||||
// Assume supported
|
||||
#include <concepts>
|
||||
namespace hex {
|
||||
using std::derived_from;
|
||||
}
|
||||
#endif
|
||||
|
||||
// [concepts.arithmetic]
|
||||
namespace hex {
|
||||
|
||||
template<class T>
|
||||
concept integral = hex::is_integral<T>::value;
|
||||
|
||||
template<class T>
|
||||
concept signed_integral = integral<T> && hex::is_signed<T>::value;
|
||||
|
||||
template<class T>
|
||||
concept unsigned_integral = integral<T> && !signed_integral<T>;
|
||||
|
||||
template<class T>
|
||||
concept floating_point = std::is_floating_point<T>::value;
|
||||
|
||||
}
|
||||
#include <concepts>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -159,11 +15,6 @@ namespace hex {
|
||||
template<typename T, size_t Size>
|
||||
concept has_size = sizeof(T) == Size;
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace hex {
|
||||
|
||||
template<typename T>
|
||||
class Cloneable {
|
||||
public:
|
||||
|
||||
@@ -2,9 +2,19 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
// TODO: Workaround for weird issue picked up by GCC 12.1.0 and later. This seems like a compiler bug mentioned in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98465
|
||||
#pragma GCC diagnostic push
|
||||
|
||||
#if (__GNUC__ >= 12)
|
||||
#pragma GCC diagnostic ignored "-Wrestrict"
|
||||
#pragma GCC diagnostic ignored "-Wstringop-overread"
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/file.hpp>
|
||||
|
||||
@@ -47,10 +47,12 @@ namespace hex::fs {
|
||||
size_t readBuffer(u8 *buffer, size_t size);
|
||||
std::vector<u8> readBytes(size_t numBytes = 0);
|
||||
std::string readString(size_t numBytes = 0);
|
||||
std::u8string readU8String(size_t numBytes = 0);
|
||||
|
||||
void write(const u8 *buffer, size_t size);
|
||||
void write(const std::vector<u8> &bytes);
|
||||
void write(const std::string &string);
|
||||
void write(const std::u8string &string);
|
||||
|
||||
[[nodiscard]] size_t getSize() const;
|
||||
void setSize(u64 size);
|
||||
|
||||
@@ -50,6 +50,12 @@ namespace hex::fs {
|
||||
return std::filesystem::remove(path, error) && !error;
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
static inline bool removeAll(const std::fs::path &path) {
|
||||
std::error_code error;
|
||||
return std::filesystem::remove_all(path, error) && !error;
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
static inline uintmax_t getFileSize(const std::fs::path &path) {
|
||||
std::error_code error;
|
||||
@@ -61,6 +67,8 @@ namespace hex::fs {
|
||||
|
||||
bool isPathWritable(const std::fs::path &path);
|
||||
|
||||
std::fs::path toShortPath(const std::fs::path &path);
|
||||
|
||||
enum class DialogMode
|
||||
{
|
||||
Open,
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
namespace hex {
|
||||
std::string getMacExecutableDirectoryPath();
|
||||
std::string getMacApplicationSupportDirectoryPath();
|
||||
}
|
||||
#endif
|
||||
12
lib/libimhex/include/hex/helpers/fs_macos.hpp
Normal file
12
lib/libimhex/include/hex/helpers/fs_macos.hpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
extern "C" char * getMacExecutableDirectoryPath();
|
||||
extern "C" char * getMacApplicationSupportDirectoryPath();
|
||||
|
||||
extern "C" void macFree(void *ptr);
|
||||
|
||||
#endif
|
||||
@@ -1,38 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
struct _object;
|
||||
typedef struct _object PyObject;
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace prv {
|
||||
class Provider;
|
||||
}
|
||||
|
||||
class LoaderScript {
|
||||
public:
|
||||
LoaderScript() = delete;
|
||||
|
||||
static bool processFile(const std::fs::path &scriptPath);
|
||||
|
||||
static void setFilePath(const std::fs::path &filePath) { LoaderScript::s_filePath = filePath; }
|
||||
static void setDataProvider(prv::Provider *provider) { LoaderScript::s_dataProvider = provider; }
|
||||
|
||||
private:
|
||||
static inline std::fs::path s_filePath;
|
||||
static inline prv::Provider *s_dataProvider;
|
||||
|
||||
static PyObject *Py_getFilePath(PyObject *self, PyObject *args);
|
||||
static PyObject *Py_addPatch(PyObject *self, PyObject *args);
|
||||
static PyObject *Py_addBookmark(PyObject *self, PyObject *args);
|
||||
|
||||
static PyObject *Py_addStruct(PyObject *self, PyObject *args);
|
||||
static PyObject *Py_addUnion(PyObject *self, PyObject *args);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -49,6 +49,8 @@ namespace hex {
|
||||
|
||||
void cancel() { this->m_shouldCancel = true; }
|
||||
|
||||
static void setProxy(const std::string &url);
|
||||
|
||||
private:
|
||||
void setCommonSettings(std::string &response, const std::string &url, u32 timeout = 2000, const std::map<std::string, std::string> &extraHeaders = {}, const std::string &body = {});
|
||||
std::optional<i32> execute();
|
||||
@@ -62,6 +64,8 @@ namespace hex {
|
||||
std::mutex m_transmissionActive;
|
||||
float m_progress = 0.0F;
|
||||
bool m_shouldCancel = false;
|
||||
|
||||
static std::string s_proxyUrl;
|
||||
};
|
||||
|
||||
}
|
||||
35
lib/libimhex/include/hex/helpers/tar.hpp
Normal file
35
lib/libimhex/include/hex/helpers/tar.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
#include <microtar.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
class Tar {
|
||||
public:
|
||||
enum class Mode {
|
||||
Read,
|
||||
Write,
|
||||
Create
|
||||
};
|
||||
|
||||
Tar() = default;
|
||||
Tar(const std::fs::path &path, Mode mode);
|
||||
~Tar();
|
||||
|
||||
std::vector<u8> read(const std::fs::path &path);
|
||||
void write(const std::fs::path &path, const std::vector<u8> &data);
|
||||
|
||||
std::vector<std::fs::path> listEntries();
|
||||
|
||||
void extract(const std::fs::path &path, const std::fs::path &outputPath);
|
||||
void extractAll(const std::fs::path &outputPath);
|
||||
|
||||
private:
|
||||
mtar_t m_ctx = { };
|
||||
};
|
||||
|
||||
}
|
||||
44
lib/libimhex/include/hex/helpers/types.hpp
Normal file
44
lib/libimhex/include/hex/helpers/types.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
using u8 = std::uint8_t;
|
||||
using u16 = std::uint16_t;
|
||||
using u32 = std::uint32_t;
|
||||
using u64 = std::uint64_t;
|
||||
using u128 = __uint128_t;
|
||||
|
||||
using i8 = std::int8_t;
|
||||
using i16 = std::int16_t;
|
||||
using i32 = std::int32_t;
|
||||
using i64 = std::int64_t;
|
||||
using i128 = __int128_t;
|
||||
|
||||
using color_t = u32;
|
||||
|
||||
namespace hex {
|
||||
|
||||
struct Region {
|
||||
u64 address;
|
||||
size_t size;
|
||||
|
||||
[[nodiscard]] constexpr bool isWithin(const Region &other) const {
|
||||
return (this->getStartAddress() >= other.getStartAddress()) && (this->getEndAddress() <= other.getEndAddress());
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool overlaps(const Region &other) const {
|
||||
return (this->getEndAddress() >= other.getStartAddress()) && (this->getStartAddress() < other.getEndAddress());
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr u64 getStartAddress() const {
|
||||
return this->address;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr u64 getEndAddress() const {
|
||||
return this->address + this->size - 1;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr size_t getSize() const {
|
||||
return this->size;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -43,7 +43,7 @@ namespace hex {
|
||||
std::string encodeByteString(const std::vector<u8> &bytes);
|
||||
std::vector<u8> decodeByteString(const std::string &string);
|
||||
|
||||
[[nodiscard]] constexpr inline u64 extract(u8 from, u8 to, const hex::unsigned_integral auto &value) {
|
||||
[[nodiscard]] constexpr inline u64 extract(u8 from, u8 to, const std::unsigned_integral auto &value) {
|
||||
if (from < to) std::swap(from, to);
|
||||
|
||||
using ValueType = std::remove_cvref_t<decltype(value)>;
|
||||
@@ -72,6 +72,18 @@ namespace hex {
|
||||
return (value ^ mask) - mask;
|
||||
}
|
||||
|
||||
template<std::integral T>
|
||||
constexpr inline T swapBitOrder(size_t numBits, T value) {
|
||||
T result = 0x00;
|
||||
|
||||
for (size_t bit = 0; bit < numBits; bit++) {
|
||||
result <<= 1;
|
||||
result |= (value & (1 << bit)) != 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class... Ts>
|
||||
struct overloaded : Ts... { using Ts::operator()...; };
|
||||
template<class... Ts>
|
||||
@@ -188,7 +200,7 @@ namespace hex {
|
||||
return T(1) << bit_width(T(x - 1));
|
||||
}
|
||||
|
||||
template<hex::integral T, hex::integral U>
|
||||
template<std::integral T, std::integral U>
|
||||
auto powi(T base, U exp) {
|
||||
using ResultType = decltype(T{} * U{});
|
||||
|
||||
@@ -252,7 +264,7 @@ namespace hex {
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::string toBinaryString(hex::unsigned_integral auto number) {
|
||||
inline std::string toBinaryString(std::unsigned_integral auto number) {
|
||||
if (number == 0) return "0";
|
||||
|
||||
std::string result;
|
||||
@@ -305,7 +317,7 @@ namespace hex {
|
||||
return *value;
|
||||
}
|
||||
|
||||
template<hex::integral T>
|
||||
template<std::integral T>
|
||||
T alignTo(T value, T alignment) {
|
||||
T remainder = value % alignment;
|
||||
|
||||
|
||||
10
lib/libimhex/include/hex/helpers/utils_macos.hpp
Normal file
10
lib/libimhex/include/hex/helpers/utils_macos.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
|
||||
#include <string>
|
||||
|
||||
extern "C" void openWebpageMacos(const char *url);
|
||||
extern "C" bool isMacosSystemDarkModeEnabled();
|
||||
|
||||
#endif
|
||||
@@ -35,6 +35,7 @@ namespace hex::prv {
|
||||
|
||||
virtual void resize(size_t newSize);
|
||||
virtual void insert(u64 offset, size_t size);
|
||||
virtual void remove(u64 offset, size_t size);
|
||||
|
||||
virtual void save();
|
||||
virtual void saveAs(const std::fs::path &path);
|
||||
|
||||
@@ -74,7 +74,8 @@ namespace ImGui {
|
||||
bool ToolBarButton(const char *symbol, ImVec4 color);
|
||||
bool IconButton(const char *symbol, ImVec4 color, ImVec2 size_arg = ImVec2(0, 0));
|
||||
|
||||
bool InputIntegerPrefix(const char* label, const char *prefix, u64 *value, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||
bool InputIntegerPrefix(const char* label, const char *prefix, void *value, ImGuiDataType type, 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);
|
||||
|
||||
inline bool HasSecondPassed() {
|
||||
@@ -134,4 +135,6 @@ namespace ImGui {
|
||||
bool InputScalarCallback(const char* label, ImGuiDataType data_type, void* p_data, const char* format, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data);
|
||||
|
||||
void HideTooltip();
|
||||
|
||||
bool BitCheckbox(const char* label, bool* v);
|
||||
}
|
||||
@@ -34,11 +34,9 @@ namespace hex {
|
||||
[[nodiscard]] virtual bool isAvailable() const;
|
||||
[[nodiscard]] virtual bool shouldProcess() const { return this->isAvailable() && this->getWindowOpenState(); }
|
||||
|
||||
static void drawCommonInterfaces();
|
||||
|
||||
static void showMessagePopup(const std::string &message);
|
||||
static void showErrorPopup(const std::string &errorMessage);
|
||||
static void showFatalPopup(const std::string &errorMessage);
|
||||
static void showInfoPopup(const std::string &message);
|
||||
static void showErrorPopup(const std::string &message);
|
||||
static void showFatalPopup(const std::string &message);
|
||||
static void showYesNoQuestionPopup(const std::string &message, const std::function<void()> &yesCallback, const std::function<void()> &noCallback);
|
||||
|
||||
static void showFileChooserPopup(const std::vector<std::fs::path> &paths, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback);
|
||||
@@ -71,15 +69,6 @@ namespace hex {
|
||||
bool m_windowOpen = false;
|
||||
std::map<Shortcut, std::function<void()>> m_shortcuts;
|
||||
|
||||
static std::string s_popupMessage;
|
||||
|
||||
static std::function<void()> s_yesCallback, s_noCallback;
|
||||
|
||||
static u32 s_selectableFileIndex;
|
||||
static std::vector<std::fs::path> s_selectableFiles;
|
||||
static std::function<void(std::fs::path)> s_selectableFileOpenCallback;
|
||||
static std::vector<nfdfilteritem_t> s_selectableFilesValidExtensions;
|
||||
|
||||
static ImFontAtlas *s_fontAtlas;
|
||||
static ImFontConfig s_fontConfig;
|
||||
|
||||
|
||||
@@ -538,7 +538,7 @@ namespace hex {
|
||||
|
||||
namespace ContentRegistry::HexEditor {
|
||||
|
||||
const int DataVisualizer::TextInputFlags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_NoHorizontalScroll | ImGuiInputTextFlags_EnterReturnsTrue;
|
||||
const int DataVisualizer::TextInputFlags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoHorizontalScroll;
|
||||
|
||||
bool DataVisualizer::drawDefaultEditingTextBox(u64 address, const char *format, ImGuiDataType dataType, u8 *data, ImGuiInputTextFlags flags) const {
|
||||
struct UserData {
|
||||
@@ -582,4 +582,18 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::Hashes {
|
||||
|
||||
std::vector<Hash *> &impl::getHashes() {
|
||||
static std::vector<Hash *> hashes;
|
||||
|
||||
return hashes;
|
||||
}
|
||||
|
||||
void impl::add(Hash *hash) {
|
||||
getHashes().push_back(hash);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
|
||||
#include <hex/api/event.hpp>
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <utility>
|
||||
|
||||
#include <utility>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace ImHexApi::Common {
|
||||
@@ -231,7 +234,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
bool isValid() {
|
||||
return !s_providers.empty();
|
||||
return !s_providers.empty() && s_currentProvider < s_providers.size();
|
||||
}
|
||||
|
||||
void add(prv::Provider *provider) {
|
||||
@@ -246,7 +249,7 @@ namespace hex {
|
||||
|
||||
s_providers.erase(it);
|
||||
|
||||
if (it - s_providers.begin() == s_currentProvider)
|
||||
if (it - s_providers.begin() == s_currentProvider && !s_providers.empty())
|
||||
setCurrentProvider(0);
|
||||
|
||||
delete provider;
|
||||
@@ -315,6 +318,21 @@ namespace hex {
|
||||
s_borderlessWindowMode = enabled;
|
||||
}
|
||||
|
||||
static std::fs::path s_customFontPath;
|
||||
void setCustomFontPath(const std::fs::path &path) {
|
||||
s_customFontPath = path;
|
||||
}
|
||||
|
||||
static float s_fontSize;
|
||||
void setFontSize(float size) {
|
||||
s_fontSize = size;
|
||||
}
|
||||
|
||||
static std::string s_gpuVendor;
|
||||
void setGPUVendor(const std::string &vendor) {
|
||||
s_gpuVendor = vendor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -360,6 +378,54 @@ namespace hex {
|
||||
|
||||
return initArgs;
|
||||
}
|
||||
|
||||
const std::fs::path &getCustomFontPath() {
|
||||
return impl::s_customFontPath;
|
||||
}
|
||||
|
||||
float getFontSize() {
|
||||
return impl::s_fontSize;
|
||||
}
|
||||
|
||||
|
||||
static Theme s_theme;
|
||||
static bool s_systemThemeDetection;
|
||||
|
||||
void setTheme(Theme theme) {
|
||||
s_theme = theme;
|
||||
|
||||
EventManager::post<EventSettingsChanged>();
|
||||
}
|
||||
|
||||
Theme getTheme() {
|
||||
return s_theme;
|
||||
}
|
||||
|
||||
|
||||
void enableSystemThemeDetection(bool enabled) {
|
||||
s_systemThemeDetection = enabled;
|
||||
|
||||
EventManager::post<EventSettingsChanged>();
|
||||
}
|
||||
|
||||
bool usesSystemThemeDetection() {
|
||||
return s_systemThemeDetection;
|
||||
}
|
||||
|
||||
|
||||
static std::vector<std::fs::path> s_additionalFolderPaths;
|
||||
const std::vector<std::fs::path> &getAdditionalFolderPaths() {
|
||||
return s_additionalFolderPaths;
|
||||
}
|
||||
|
||||
void setAdditionalFolderPaths(const std::vector<std::fs::path> &paths) {
|
||||
s_additionalFolderPaths = paths;
|
||||
}
|
||||
|
||||
|
||||
const std::string &getGPUVendor() {
|
||||
return impl::s_gpuVendor;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,17 +3,26 @@
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
#include <dlfcn.h>
|
||||
#include <system_error>
|
||||
|
||||
namespace hex {
|
||||
|
||||
Plugin::Plugin(const std::fs::path &path) : m_path(path) {
|
||||
this->m_handle = dlopen(path.string().c_str(), RTLD_LAZY);
|
||||
#if defined(OS_WINDOWS)
|
||||
this->m_handle = LoadLibraryW(path.c_str());
|
||||
|
||||
if (this->m_handle == nullptr) {
|
||||
log::error("dlopen failed: {}", dlerror());
|
||||
return;
|
||||
}
|
||||
if (this->m_handle == nullptr) {
|
||||
log::error("LoadLibraryW failed: {}!", std::system_category().message(::GetLastError()));
|
||||
return;
|
||||
}
|
||||
#else
|
||||
this->m_handle = dlopen(path.string().c_str(), RTLD_LAZY);
|
||||
|
||||
if (this->m_handle == nullptr) {
|
||||
log::error("dlopen failed: {}!", dlerror());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto pluginName = std::fs::path(path).stem().string();
|
||||
|
||||
@@ -49,8 +58,13 @@ namespace hex {
|
||||
}
|
||||
|
||||
Plugin::~Plugin() {
|
||||
if (this->m_handle != nullptr)
|
||||
dlclose(this->m_handle);
|
||||
#if defined(OS_WINDOWS)
|
||||
if (this->m_handle != nullptr)
|
||||
FreeLibrary(this->m_handle);
|
||||
#else
|
||||
if (this->m_handle != nullptr)
|
||||
dlclose(this->m_handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Plugin::initializePlugin() const {
|
||||
@@ -120,7 +134,11 @@ namespace hex {
|
||||
|
||||
|
||||
void *Plugin::getPluginFunction(const std::string &symbol) {
|
||||
return dlsym(this->m_handle, symbol.c_str());
|
||||
#if defined(OS_WINDOWS)
|
||||
return reinterpret_cast<void *>(GetProcAddress(this->m_handle, symbol.c_str()));
|
||||
#else
|
||||
return dlsym(this->m_handle, symbol.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -135,7 +153,7 @@ namespace hex {
|
||||
|
||||
for (auto &pluginPath : std::fs::directory_iterator(pluginFolder)) {
|
||||
if (pluginPath.is_regular_file() && pluginPath.path().extension() == ".hexplug")
|
||||
PluginManager::s_plugins.emplace_back(pluginPath.path().string());
|
||||
PluginManager::s_plugins.emplace_back(pluginPath.path());
|
||||
}
|
||||
|
||||
if (PluginManager::s_plugins.empty())
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/concepts.hpp>
|
||||
|
||||
#include <mbedtls/version.h>
|
||||
#include <mbedtls/base64.h>
|
||||
@@ -15,7 +16,6 @@
|
||||
|
||||
#include <array>
|
||||
#include <span>
|
||||
#include <concepts>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
@@ -1,16 +1,28 @@
|
||||
#include <hex/helpers/file.hpp>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace hex::fs {
|
||||
|
||||
File::File(const std::fs::path &path, Mode mode) noexcept : m_path(path) {
|
||||
if (mode == File::Mode::Read)
|
||||
this->m_file = fopen64(path.string().c_str(), "rb");
|
||||
else if (mode == File::Mode::Write)
|
||||
this->m_file = fopen64(path.string().c_str(), "r+b");
|
||||
#if defined(OS_WINDOWS)
|
||||
if (mode == File::Mode::Read)
|
||||
this->m_file = _wfopen(path.c_str(), L"rb");
|
||||
else if (mode == File::Mode::Write)
|
||||
this->m_file = _wfopen(path.c_str(), L"r+b");
|
||||
|
||||
if (mode == File::Mode::Create || (mode == File::Mode::Write && this->m_file == nullptr))
|
||||
this->m_file = fopen64(path.string().c_str(), "w+b");
|
||||
if (mode == File::Mode::Create || (mode == File::Mode::Write && this->m_file == nullptr))
|
||||
this->m_file = _wfopen(path.c_str(), L"w+b");
|
||||
#else
|
||||
if (mode == File::Mode::Read)
|
||||
this->m_file = fopen64(path.string().c_str(), "rb");
|
||||
else if (mode == File::Mode::Write)
|
||||
this->m_file = fopen64(path.string().c_str(), "r+b");
|
||||
|
||||
if (mode == File::Mode::Create || (mode == File::Mode::Write && this->m_file == nullptr))
|
||||
this->m_file = fopen64(path.string().c_str(), "w+b");
|
||||
#endif
|
||||
}
|
||||
|
||||
File::File() noexcept {
|
||||
@@ -77,7 +89,22 @@ namespace hex::fs {
|
||||
if (bytes.empty())
|
||||
return "";
|
||||
|
||||
return { reinterpret_cast<char *>(bytes.data()), bytes.size() };
|
||||
auto cString = reinterpret_cast<const char *>(bytes.data());
|
||||
return { cString, std::min(bytes.size(), std::strlen(cString)) };
|
||||
}
|
||||
|
||||
std::u8string File::readU8String(size_t numBytes) {
|
||||
if (!isValid()) return {};
|
||||
|
||||
if (getSize() == 0) return {};
|
||||
|
||||
auto bytes = readBytes(numBytes);
|
||||
|
||||
if (bytes.empty())
|
||||
return u8"";
|
||||
|
||||
auto cString = reinterpret_cast<const char8_t *>(bytes.data());
|
||||
return { cString, std::min(bytes.size(), std::strlen(reinterpret_cast<const char*>(bytes.data()))) };
|
||||
}
|
||||
|
||||
void File::write(const u8 *buffer, size_t size) {
|
||||
@@ -98,6 +125,12 @@ namespace hex::fs {
|
||||
std::fwrite(string.data(), string.size(), 1, this->m_file);
|
||||
}
|
||||
|
||||
void File::write(const std::u8string &string) {
|
||||
if (!isValid()) return;
|
||||
|
||||
std::fwrite(string.data(), string.size(), 1, this->m_file);
|
||||
}
|
||||
|
||||
size_t File::getSize() const {
|
||||
if (!isValid()) return 0;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/helpers/fs_macos.h>
|
||||
#include <hex/helpers/fs_macos.hpp>
|
||||
#include <hex/helpers/file.hpp>
|
||||
#include <hex/helpers/intrinsics.hpp>
|
||||
|
||||
@@ -22,8 +22,8 @@ namespace hex::fs {
|
||||
|
||||
std::optional<std::fs::path> getExecutablePath() {
|
||||
#if defined(OS_WINDOWS)
|
||||
std::string exePath(MAX_PATH, '\0');
|
||||
if (GetModuleFileName(nullptr, exePath.data(), exePath.length()) == 0)
|
||||
std::wstring exePath(MAX_PATH, '\0');
|
||||
if (GetModuleFileNameW(nullptr, exePath.data(), exePath.length()) == 0)
|
||||
return std::nullopt;
|
||||
|
||||
return exePath;
|
||||
@@ -34,7 +34,15 @@ namespace hex::fs {
|
||||
|
||||
return exePath;
|
||||
#elif defined(OS_MACOS)
|
||||
return getMacExecutableDirectoryPath();
|
||||
std::string result;
|
||||
|
||||
{
|
||||
auto string = getMacExecutableDirectoryPath();
|
||||
result = string;
|
||||
macFree(string);
|
||||
}
|
||||
|
||||
return result;
|
||||
#else
|
||||
return std::nullopt;
|
||||
#endif
|
||||
@@ -92,8 +100,7 @@ namespace hex::fs {
|
||||
std::vector<std::fs::path> getDefaultPaths(ImHexPath path, bool listNonExisting) {
|
||||
std::vector<std::fs::path> result;
|
||||
const auto exePath = getExecutablePath();
|
||||
const std::string settingName { "hex.builtin.setting.folders" };
|
||||
auto userDirs = ContentRegistry::Settings::read(settingName, settingName, std::vector<std::string> {});
|
||||
auto userDirs = ImHexApi::System::getAdditionalFolderPaths();
|
||||
|
||||
[[maybe_unused]]
|
||||
auto addUserDirs = [&userDirs](auto &paths) {
|
||||
@@ -105,11 +112,11 @@ namespace hex::fs {
|
||||
#if defined(OS_WINDOWS)
|
||||
std::fs::path appDataDir;
|
||||
{
|
||||
LPWSTR wAppDataPath = nullptr;
|
||||
PWSTR wAppDataPath = nullptr;
|
||||
if (!SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &wAppDataPath)))
|
||||
throw std::runtime_error("Failed to get APPDATA folder path");
|
||||
|
||||
appDataDir = wAppDataPath;
|
||||
appDataDir = std::wstring(wAppDataPath);
|
||||
CoTaskMemFree(wAppDataPath);
|
||||
}
|
||||
|
||||
@@ -122,60 +129,60 @@ namespace hex::fs {
|
||||
case ImHexPath::Patterns:
|
||||
addUserDirs(paths);
|
||||
std::transform(paths.begin(), paths.end(), std::back_inserter(result), [](auto &path) {
|
||||
return (path / "patterns").string();
|
||||
return path / "patterns";
|
||||
});
|
||||
break;
|
||||
case ImHexPath::PatternsInclude:
|
||||
addUserDirs(paths);
|
||||
std::transform(paths.begin(), paths.end(), std::back_inserter(result), [](auto &path) {
|
||||
return (path / "includes").string();
|
||||
return path / "includes";
|
||||
});
|
||||
break;
|
||||
case ImHexPath::Magic:
|
||||
addUserDirs(paths);
|
||||
std::transform(paths.begin(), paths.end(), std::back_inserter(result), [](auto &path) {
|
||||
return (path / "magic").string();
|
||||
return path / "magic";
|
||||
});
|
||||
break;
|
||||
case ImHexPath::Python:
|
||||
addUserDirs(paths);
|
||||
std::transform(paths.begin(), paths.end(), std::back_inserter(result), [](auto &path) {
|
||||
return (path / "python").string();
|
||||
return path / "python";
|
||||
});
|
||||
break;
|
||||
case ImHexPath::Plugins:
|
||||
std::transform(paths.begin(), paths.end(), std::back_inserter(result), [](auto &path) {
|
||||
return (path / "plugins").string();
|
||||
return path / "plugins";
|
||||
});
|
||||
break;
|
||||
case ImHexPath::Yara:
|
||||
addUserDirs(paths);
|
||||
std::transform(paths.begin(), paths.end(), std::back_inserter(result), [](auto &path) {
|
||||
return (path / "yara").string();
|
||||
return path / "yara";
|
||||
});
|
||||
break;
|
||||
case ImHexPath::Config:
|
||||
return { (appDataDir / "imhex" / "config").string() };
|
||||
return { appDataDir / "imhex" / "config" };
|
||||
case ImHexPath::Resources:
|
||||
std::transform(paths.begin(), paths.end(), std::back_inserter(result), [](auto &path) {
|
||||
return (path / "resources").string();
|
||||
return path / "resources";
|
||||
});
|
||||
break;
|
||||
case ImHexPath::Constants:
|
||||
addUserDirs(paths);
|
||||
std::transform(paths.begin(), paths.end(), std::back_inserter(result), [](auto &path) {
|
||||
return (path / "constants").string();
|
||||
return path / "constants";
|
||||
});
|
||||
break;
|
||||
case ImHexPath::Encodings:
|
||||
addUserDirs(paths);
|
||||
std::transform(paths.begin(), paths.end(), std::back_inserter(result), [](auto &path) {
|
||||
return (path / "encodings").string();
|
||||
return path / "encodings";
|
||||
});
|
||||
break;
|
||||
case ImHexPath::Logs:
|
||||
std::transform(paths.begin(), paths.end(), std::back_inserter(result), [](auto &path) {
|
||||
return (path / "logs").string();
|
||||
return path / "logs";
|
||||
});
|
||||
break;
|
||||
default:
|
||||
@@ -183,25 +190,31 @@ namespace hex::fs {
|
||||
}
|
||||
#elif defined(OS_MACOS)
|
||||
// Get path to special directories
|
||||
const std::fs::path applicationSupportDir(getMacApplicationSupportDirectoryPath());
|
||||
std::string applicationSupportDir;
|
||||
{
|
||||
auto string = getMacApplicationSupportDirectoryPath();
|
||||
applicationSupportDir = string;
|
||||
macFree(string);
|
||||
}
|
||||
const std::fs::path applicationSupportDirPath(applicationSupportDir);
|
||||
|
||||
std::vector<std::fs::path> paths = { applicationSupportDir };
|
||||
std::vector<std::fs::path> paths = { applicationSupportDirPath };
|
||||
|
||||
if (exePath)
|
||||
paths.push_back(exePath->parent_path());
|
||||
if (exePath.has_value())
|
||||
paths.push_back(exePath.value());
|
||||
|
||||
switch (path) {
|
||||
case ImHexPath::Patterns:
|
||||
result.push_back((applicationSupportDir / "patterns").string());
|
||||
result.push_back((applicationSupportDirPath / "patterns").string());
|
||||
break;
|
||||
case ImHexPath::PatternsInclude:
|
||||
result.push_back((applicationSupportDir / "includes").string());
|
||||
result.push_back((applicationSupportDirPath / "includes").string());
|
||||
break;
|
||||
case ImHexPath::Magic:
|
||||
result.push_back((applicationSupportDir / "magic").string());
|
||||
result.push_back((applicationSupportDirPath / "magic").string());
|
||||
break;
|
||||
case ImHexPath::Python:
|
||||
result.push_back((applicationSupportDir / "python").string());
|
||||
result.push_back((applicationSupportDirPath / "python").string());
|
||||
break;
|
||||
case ImHexPath::Plugins:
|
||||
std::transform(paths.begin(), paths.end(), std::back_inserter(result), [](auto &path) {
|
||||
@@ -209,22 +222,22 @@ namespace hex::fs {
|
||||
});
|
||||
break;
|
||||
case ImHexPath::Yara:
|
||||
result.push_back((applicationSupportDir / "yara").string());
|
||||
result.push_back((applicationSupportDirPath / "yara").string());
|
||||
break;
|
||||
case ImHexPath::Config:
|
||||
result.push_back((applicationSupportDir / "config").string());
|
||||
result.push_back((applicationSupportDirPath / "config").string());
|
||||
break;
|
||||
case ImHexPath::Resources:
|
||||
result.push_back((applicationSupportDir / "resources").string());
|
||||
result.push_back((applicationSupportDirPath / "resources").string());
|
||||
break;
|
||||
case ImHexPath::Constants:
|
||||
result.push_back((applicationSupportDir / "constants").string());
|
||||
result.push_back((applicationSupportDirPath / "constants").string());
|
||||
break;
|
||||
case ImHexPath::Encodings:
|
||||
result.push_back((applicationSupportDir / "encodings").string());
|
||||
result.push_back((applicationSupportDirPath / "encodings").string());
|
||||
break;
|
||||
case ImHexPath::Logs:
|
||||
result.push_back((applicationSupportDir / "logs").string());
|
||||
result.push_back((applicationSupportDirPath / "logs").string());
|
||||
break;
|
||||
default:
|
||||
hex::unreachable();
|
||||
@@ -299,4 +312,20 @@ namespace hex::fs {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::fs::path toShortPath(const std::fs::path &path) {
|
||||
#if defined(OS_WINDOWS)
|
||||
size_t size = GetShortPathNameW(path.c_str(), nullptr, 0) * sizeof(TCHAR);
|
||||
if (size == 0)
|
||||
return path;
|
||||
|
||||
std::wstring newPath(size, 0x00);
|
||||
GetShortPathNameW(path.c_str(), newPath.data(), newPath.size());
|
||||
|
||||
return newPath;
|
||||
#else
|
||||
return path;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
44
lib/libimhex/source/helpers/fs_macos.m
Normal file
44
lib/libimhex/source/helpers/fs_macos.m
Normal file
@@ -0,0 +1,44 @@
|
||||
#if defined(OS_MACOS)
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
char* getMacExecutableDirectoryPath() {
|
||||
@autoreleasepool {
|
||||
const char *pathString = [[[[[NSBundle mainBundle] executableURL] URLByDeletingLastPathComponent] path] UTF8String];
|
||||
|
||||
char *result = malloc(strlen(pathString) + 1);
|
||||
strcpy(result, pathString);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
char* getMacApplicationSupportDirectoryPath() {
|
||||
@autoreleasepool {
|
||||
NSError* error = nil;
|
||||
NSURL* dirUrl = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory
|
||||
inDomain:NSUserDomainMask
|
||||
appropriateForURL:nil
|
||||
create:YES
|
||||
error:&error];
|
||||
|
||||
if (error != nil) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *pathString = [[[dirUrl URLByAppendingPathComponent:(@"imhex")] path] UTF8String];
|
||||
|
||||
char *result = malloc(strlen(pathString) + 1);
|
||||
strcpy(result, pathString);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void macFree(void *ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,30 +0,0 @@
|
||||
#if defined(OS_MACOS)
|
||||
#include <hex/helpers/fs_macos.h>
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
namespace hex {
|
||||
std::string getMacExecutableDirectoryPath() {
|
||||
@autoreleasepool {
|
||||
return {[[[[[NSBundle mainBundle] executableURL] URLByDeletingLastPathComponent] path] UTF8String]};
|
||||
}
|
||||
}
|
||||
|
||||
std::string getMacApplicationSupportDirectoryPath() {
|
||||
@autoreleasepool {
|
||||
NSError* error = nil;
|
||||
NSURL* dirUrl = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory
|
||||
inDomain:NSUserDomainMask
|
||||
appropriateForURL:nil
|
||||
create:YES
|
||||
error:&error];
|
||||
|
||||
if (error != nil) {
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
return {[[[dirUrl URLByAppendingPathComponent:(@"imhex")] path] UTF8String]};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,248 +0,0 @@
|
||||
#include <hex/helpers/loader_script_handler.hpp>
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/file.hpp>
|
||||
#include <hex/ui/view.hpp>
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/helpers/intrinsics.hpp>
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include <Python.h>
|
||||
#include <structmember.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
|
||||
namespace hex {
|
||||
|
||||
PyObject *LoaderScript::Py_getFilePath(PyObject *self, PyObject *args) {
|
||||
hex::unused(self, args);
|
||||
|
||||
return PyUnicode_FromString(LoaderScript::s_filePath.string().c_str());
|
||||
}
|
||||
|
||||
PyObject *LoaderScript::Py_addPatch(PyObject *self, PyObject *args) {
|
||||
hex::unused(self);
|
||||
|
||||
u64 address;
|
||||
u8 *patches;
|
||||
Py_ssize_t count;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "K|y#", &address, &patches, &count)) {
|
||||
PyErr_BadArgument();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (patches == nullptr || count == 0) {
|
||||
PyErr_SetString(PyExc_TypeError, "Invalid patch provided");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (address >= LoaderScript::s_dataProvider->getActualSize()) {
|
||||
PyErr_SetString(PyExc_IndexError, "address out of range");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LoaderScript::s_dataProvider->write(address, patches, count);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyObject *LoaderScript::Py_addBookmark(PyObject *self, PyObject *args) {
|
||||
hex::unused(self);
|
||||
|
||||
u64 address;
|
||||
size_t size;
|
||||
|
||||
char *name = nullptr;
|
||||
char *comment = nullptr;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "K|n|s|s", &address, &size, &name, &comment)) {
|
||||
PyErr_BadArgument();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (name == nullptr || comment == nullptr) {
|
||||
PyErr_SetString(PyExc_IndexError, "address out of range");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ImHexApi::Bookmarks::add(address, size, name, comment);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *createStructureType(const std::string &keyword, PyObject *args) {
|
||||
if (args == nullptr) {
|
||||
PyErr_BadArgument();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto type = PyTuple_GetItem(args, 0);
|
||||
if (type == nullptr) {
|
||||
PyErr_BadArgument();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto instance = PyObject_CallObject(type, nullptr);
|
||||
if (instance == nullptr) {
|
||||
PyErr_BadArgument();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ON_SCOPE_EXIT { Py_DECREF(instance); };
|
||||
|
||||
if (instance->ob_type->tp_base == nullptr || instance->ob_type->tp_base->tp_name != "ImHexType"s) {
|
||||
PyErr_SetString(PyExc_TypeError, "class type must extend from ImHexType");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto dict = instance->ob_type->tp_dict;
|
||||
if (dict == nullptr) {
|
||||
PyErr_BadArgument();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto annotations = PyDict_GetItemString(dict, "__annotations__");
|
||||
if (annotations == nullptr) {
|
||||
PyErr_BadArgument();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto list = PyDict_Items(annotations);
|
||||
if (list == nullptr) {
|
||||
PyErr_BadArgument();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ON_SCOPE_EXIT { Py_DECREF(list); };
|
||||
|
||||
std::string code = keyword + " " + instance->ob_type->tp_name + " {\n";
|
||||
|
||||
for (Py_ssize_t i = 0; i < PyList_Size(list); i++) {
|
||||
auto item = PyList_GetItem(list, i);
|
||||
if (item == nullptr) {
|
||||
PyErr_SetString(PyExc_TypeError, "failed to get item from list");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto memberName = PyUnicode_AsUTF8(PyTuple_GetItem(item, 0));
|
||||
if (memberName == nullptr) {
|
||||
PyErr_SetString(PyExc_TypeError, "invalid member name");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto memberType = PyTuple_GetItem(item, 1);
|
||||
if (!PyTuple_Check(memberType) || memberType == nullptr) {
|
||||
PyErr_SetString(PyExc_TypeError, "member needs to have a annotation extending from ImHexType");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Array already is an object
|
||||
if (memberType->ob_type->tp_name == "array"s) {
|
||||
|
||||
auto arrayType = PyObject_GetAttrString(memberType, "array_type");
|
||||
if (arrayType == nullptr) {
|
||||
PyErr_BadArgument();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
code += " "s + arrayType->ob_type->tp_name + " " + memberName;
|
||||
|
||||
auto arraySize = PyObject_GetAttrString(memberType, "size");
|
||||
if (arraySize == nullptr) {
|
||||
PyErr_BadArgument();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (PyUnicode_Check(arraySize))
|
||||
code += "["s + PyUnicode_AsUTF8(arraySize) + "];\n";
|
||||
else if (PyLong_Check(arraySize))
|
||||
code += "["s + std::to_string(PyLong_AsLong(arraySize)) + "];\n";
|
||||
} else {
|
||||
auto memberTypeInstance = PyObject_CallObject(memberType, nullptr);
|
||||
if (memberTypeInstance == nullptr || memberTypeInstance->ob_type->tp_base == nullptr || memberTypeInstance->ob_type->tp_base->tp_name != "ImHexType"s) {
|
||||
PyErr_SetString(PyExc_TypeError, "member needs to have a annotation extending from ImHexType");
|
||||
if (memberTypeInstance != nullptr)
|
||||
Py_DECREF(memberTypeInstance);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
code += " "s + memberTypeInstance->ob_type->tp_name + " "s + memberName + ";\n";
|
||||
|
||||
Py_DECREF(memberTypeInstance);
|
||||
}
|
||||
}
|
||||
|
||||
code += "};\n";
|
||||
|
||||
EventManager::post<RequestSetPatternLanguageCode>(code);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyObject *LoaderScript::Py_addStruct(PyObject *self, PyObject *args) {
|
||||
hex::unused(self);
|
||||
|
||||
return createStructureType("struct", args);
|
||||
}
|
||||
|
||||
PyObject *LoaderScript::Py_addUnion(PyObject *self, PyObject *args) {
|
||||
hex::unused(self);
|
||||
|
||||
return createStructureType("union", args);
|
||||
}
|
||||
|
||||
bool LoaderScript::processFile(const std::fs::path &scriptPath) {
|
||||
Py_SetProgramName(Py_DecodeLocale("ImHex", nullptr));
|
||||
|
||||
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Python)) {
|
||||
if (fs::exists(std::fs::path(dir / "lib" / "python" PYTHON_VERSION_MAJOR_MINOR))) {
|
||||
Py_SetPythonHome(Py_DecodeLocale(dir.string().c_str(), nullptr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PyImport_AppendInittab("_imhex", []() -> PyObject * {
|
||||
static PyMethodDef ImHexMethods[] = {
|
||||
{"get_file_path", &LoaderScript::Py_getFilePath, METH_NOARGS, "Returns the path of the file being loaded."},
|
||||
{ "patch", &LoaderScript::Py_addPatch, METH_VARARGS, "Patches a region of memory" },
|
||||
{ "add_bookmark", &LoaderScript::Py_addBookmark, METH_VARARGS, "Adds a bookmark" },
|
||||
{ "add_struct", &LoaderScript::Py_addStruct, METH_VARARGS, "Adds a struct" },
|
||||
{ "add_union", &LoaderScript::Py_addUnion, METH_VARARGS, "Adds a union" },
|
||||
{ nullptr, nullptr, 0, nullptr }
|
||||
};
|
||||
|
||||
static PyModuleDef ImHexModule = {
|
||||
PyModuleDef_HEAD_INIT, "imhex", nullptr, -1, ImHexMethods, nullptr, nullptr, nullptr, nullptr
|
||||
};
|
||||
|
||||
auto module = PyModule_Create(&ImHexModule);
|
||||
if (module == nullptr)
|
||||
return nullptr;
|
||||
|
||||
return module;
|
||||
});
|
||||
|
||||
Py_Initialize();
|
||||
|
||||
{
|
||||
auto sysPath = PySys_GetObject("path");
|
||||
auto path = PyUnicode_FromString("lib");
|
||||
|
||||
PyList_Insert(sysPath, 0, path);
|
||||
}
|
||||
|
||||
fs::File scriptFile(scriptPath, fs::File::Mode::Read);
|
||||
PyRun_SimpleFile(scriptFile.getHandle(), scriptFile.getPath().string().c_str());
|
||||
|
||||
Py_Finalize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,8 +26,9 @@ namespace hex::magic {
|
||||
std::error_code error;
|
||||
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Magic)) {
|
||||
for (const auto &entry : std::fs::directory_iterator(dir, error)) {
|
||||
if (entry.is_regular_file() && ((sourceFiles && entry.path().extension().empty()) || (!sourceFiles && entry.path().extension() == ".mgc")))
|
||||
magicFiles += entry.path().string() + MAGIC_PATH_SEPARATOR;
|
||||
if (entry.is_regular_file() && ((sourceFiles && entry.path().extension().empty()) || (!sourceFiles && entry.path().extension() == ".mgc"))) {
|
||||
magicFiles += fs::toShortPath(entry.path()).string() + MAGIC_PATH_SEPARATOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <hex/helpers/file.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
#include <hex/api/content_registry.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
#include <cstdio>
|
||||
|
||||
@@ -113,6 +115,8 @@ namespace hex {
|
||||
curl_easy_setopt(this->m_ctx, CURLOPT_SSLCERTTYPE, "PEM");
|
||||
curl_easy_setopt(this->m_ctx, CURLOPT_SSL_CTX_FUNCTION, sslCtxFunction);
|
||||
#endif
|
||||
|
||||
curl_easy_setopt(this->m_ctx, CURLOPT_PROXY, Net::s_proxyUrl.c_str());
|
||||
}
|
||||
|
||||
std::optional<i32> Net::execute() {
|
||||
@@ -241,4 +245,10 @@ namespace hex {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string Net::s_proxyUrl;
|
||||
|
||||
void Net::setProxy(const std::string &url) {
|
||||
Net::s_proxyUrl = url;
|
||||
}
|
||||
|
||||
}
|
||||
99
lib/libimhex/source/helpers/tar.cpp
Normal file
99
lib/libimhex/source/helpers/tar.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#include <hex/helpers/tar.hpp>
|
||||
#include <hex/helpers/literals.hpp>
|
||||
#include <hex/helpers/file.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
using namespace hex::literals;
|
||||
|
||||
Tar::Tar(const std::fs::path &path, Mode mode) {
|
||||
if (mode == Tar::Mode::Read)
|
||||
mtar_open(&this->m_ctx, path.string().c_str(), "r");
|
||||
else if (mode == Tar::Mode::Write)
|
||||
mtar_open(&this->m_ctx, path.string().c_str(), "a");
|
||||
else if (mode == Tar::Mode::Create)
|
||||
mtar_open(&this->m_ctx, path.string().c_str(), "w");
|
||||
}
|
||||
|
||||
Tar::~Tar() {
|
||||
mtar_finalize(&this->m_ctx);
|
||||
mtar_close(&this->m_ctx);
|
||||
}
|
||||
|
||||
std::vector<std::fs::path> Tar::listEntries() {
|
||||
std::vector<std::fs::path> result;
|
||||
|
||||
const std::string PaxHeaderName = "@PaxHeader";
|
||||
mtar_header_t header;
|
||||
while (mtar_read_header(&this->m_ctx, &header) != MTAR_ENULLRECORD) {
|
||||
if (header.name != PaxHeaderName) {
|
||||
result.emplace_back(header.name);
|
||||
}
|
||||
|
||||
mtar_next(&this->m_ctx);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<u8> Tar::read(const std::fs::path &path) {
|
||||
mtar_header_t header;
|
||||
mtar_find(&this->m_ctx, path.string().c_str(), &header);
|
||||
|
||||
std::vector<u8> result(header.size, 0x00);
|
||||
mtar_read_data(&this->m_ctx, result.data(), result.size());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Tar::write(const std::fs::path &path, const std::vector<u8> &data) {
|
||||
if (path.has_parent_path()) {
|
||||
std::fs::path pathPart;
|
||||
for (const auto &part : path.parent_path()) {
|
||||
pathPart /= part;
|
||||
mtar_write_dir_header(&this->m_ctx, pathPart.string().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
mtar_write_file_header(&this->m_ctx, path.string().c_str(), data.size());
|
||||
mtar_write_data(&this->m_ctx, data.data(), data.size());
|
||||
}
|
||||
|
||||
static void writeFile(mtar_t *ctx, mtar_header_t *header, const std::fs::path &path) {
|
||||
constexpr static u64 BufferSize = 1_MiB;
|
||||
|
||||
fs::File outputFile(path, fs::File::Mode::Create);
|
||||
|
||||
std::vector<u8> buffer;
|
||||
for (u64 offset = 0; offset < header->size; offset += BufferSize) {
|
||||
buffer.resize(std::min<u64>(BufferSize, header->size - offset));
|
||||
|
||||
mtar_read_data(ctx, buffer.data(), buffer.size());
|
||||
outputFile.write(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void Tar::extract(const std::fs::path &path, const std::fs::path &outputPath) {
|
||||
mtar_header_t header;
|
||||
mtar_find(&this->m_ctx, path.string().c_str(), &header);
|
||||
|
||||
writeFile(&this->m_ctx, &header, outputPath);
|
||||
}
|
||||
|
||||
void Tar::extractAll(const std::fs::path &outputPath) {
|
||||
mtar_header_t header;
|
||||
while (mtar_read_header(&this->m_ctx, &header) != MTAR_ENULLRECORD) {
|
||||
const auto filePath = std::fs::absolute(outputPath / std::fs::path(header.name));
|
||||
|
||||
if (filePath.filename() != "@PaxHeader") {
|
||||
|
||||
std::fs::create_directories(filePath.parent_path());
|
||||
|
||||
writeFile(&this->m_ctx, &header, filePath);
|
||||
}
|
||||
|
||||
mtar_next(&this->m_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include <cstdio>
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
#include <filesystem>
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
|
||||
@@ -18,13 +16,10 @@
|
||||
#elif defined(OS_LINUX)
|
||||
#include <unistd.h>
|
||||
#elif defined(OS_MACOS)
|
||||
#include <CoreFoundation/CFBundle.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <hex/helpers/utils_macos.hpp>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/helpers/file.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
long double operator""_scaled(long double value) {
|
||||
@@ -83,29 +78,34 @@ namespace hex {
|
||||
break;
|
||||
}
|
||||
|
||||
std::string result = hex::format("{0:.2f}", value);
|
||||
std::string result;
|
||||
|
||||
if (unitIndex == 0)
|
||||
result = hex::format("{0:}", value);
|
||||
else
|
||||
result = hex::format("{0:.2f}", value);
|
||||
|
||||
switch (unitIndex) {
|
||||
case 0:
|
||||
result += " Bytes";
|
||||
result += ((value == 1) ? " Byte" : " Bytes");
|
||||
break;
|
||||
case 1:
|
||||
result += " kB";
|
||||
result += " kiB";
|
||||
break;
|
||||
case 2:
|
||||
result += " MB";
|
||||
result += " MiB";
|
||||
break;
|
||||
case 3:
|
||||
result += " GB";
|
||||
result += " GiB";
|
||||
break;
|
||||
case 4:
|
||||
result += " TB";
|
||||
result += " TiB";
|
||||
break;
|
||||
case 5:
|
||||
result += " PB";
|
||||
result += " PiB";
|
||||
break;
|
||||
case 6:
|
||||
result += " EB";
|
||||
result += " EiB";
|
||||
break;
|
||||
default:
|
||||
result = "A lot!";
|
||||
@@ -204,11 +204,15 @@ namespace hex {
|
||||
}
|
||||
|
||||
std::vector<std::string> splitString(const std::string &string, const std::string &delimiter) {
|
||||
size_t start = 0, end;
|
||||
size_t start = 0, end = 0;
|
||||
std::string token;
|
||||
std::vector<std::string> res;
|
||||
|
||||
while ((end = string.find(delimiter, start)) != std::string::npos) {
|
||||
size_t size = end - start;
|
||||
if (start + size > string.length())
|
||||
break;
|
||||
|
||||
token = string.substr(start, end - start);
|
||||
start = end + delimiter.length();
|
||||
res.push_back(token);
|
||||
@@ -248,13 +252,14 @@ namespace hex {
|
||||
|
||||
void runCommand(const std::string &command) {
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
auto result = system(hex::format("start {0}", command).c_str());
|
||||
#elif defined(OS_MACOS)
|
||||
auto result = system(hex::format("open {0}", command).c_str());
|
||||
#elif defined(OS_LINUX)
|
||||
auto result = system(hex::format("xdg-open {0}", command).c_str());
|
||||
#endif
|
||||
#if defined(OS_WINDOWS)
|
||||
auto result = system(hex::format("start {0}", command).c_str());
|
||||
#elif defined(OS_MACOS)
|
||||
auto result = system(hex::format("open {0}", command).c_str());
|
||||
#elif defined(OS_LINUX)
|
||||
auto result = system(hex::format("xdg-open {0}", command).c_str());
|
||||
#endif
|
||||
|
||||
hex::unused(result);
|
||||
}
|
||||
|
||||
@@ -263,18 +268,16 @@ namespace hex {
|
||||
if (url.find("://") == std::string::npos)
|
||||
url = "https://" + url;
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
ShellExecute(nullptr, "open", url.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
|
||||
#elif defined(OS_MACOS)
|
||||
CFURLRef urlRef = CFURLCreateWithBytes(nullptr, reinterpret_cast<u8 *>(url.data()), url.length(), kCFStringEncodingASCII, nullptr);
|
||||
LSOpenCFURLRef(urlRef, nullptr);
|
||||
CFRelease(urlRef);
|
||||
#elif defined(OS_LINUX)
|
||||
auto result = system(hex::format("xdg-open {0}", url).c_str());
|
||||
hex::unused(result);
|
||||
#else
|
||||
#warning "Unknown OS, can't open webpages"
|
||||
#endif
|
||||
#if defined(OS_WINDOWS)
|
||||
ShellExecute(nullptr, "open", url.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
|
||||
#elif defined(OS_MACOS)
|
||||
openWebpageMacos(url.c_str());
|
||||
#elif defined(OS_LINUX)
|
||||
auto result = system(hex::format("xdg-open {0}", url).c_str());
|
||||
hex::unused(result);
|
||||
#else
|
||||
#warning "Unknown OS, can't open webpages"
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string encodeByteString(const std::vector<u8> &bytes) {
|
||||
|
||||
28
lib/libimhex/source/helpers/utils_macos.m
Normal file
28
lib/libimhex/source/helpers/utils_macos.m
Normal file
@@ -0,0 +1,28 @@
|
||||
#if defined(OS_MACOS)
|
||||
|
||||
#include <CoreFoundation/CFBundle.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <Foundation/NSUserDefaults.h>
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void openWebpageMacos(const char *url) {
|
||||
CFURLRef urlRef = CFURLCreateWithBytes(NULL, (uint8_t*)(url), strlen(url), kCFStringEncodingASCII, NULL);
|
||||
LSOpenCFURLRef(urlRef, NULL);
|
||||
CFRelease(urlRef);
|
||||
}
|
||||
|
||||
bool isMacosSystemDarkModeEnabled() {
|
||||
NSString * appleInterfaceStyle = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
|
||||
|
||||
if (appleInterfaceStyle && [appleInterfaceStyle length] > 0) {
|
||||
return [[appleInterfaceStyle lowercaseString] containsString:@"dark"];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -2,25 +2,17 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/event.hpp>
|
||||
#include <hex/ui/view.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include <pl/pattern_language.hpp>
|
||||
|
||||
namespace hex::prv {
|
||||
|
||||
Provider::Provider() {
|
||||
this->m_patches.emplace_back();
|
||||
this->m_patternLanguageRuntime = ContentRegistry::PatternLanguage::createDefaultRuntime(this);
|
||||
|
||||
if (this->hasLoadInterface())
|
||||
EventManager::post<RequestOpenPopup>(View::toWindowName("hex.builtin.view.provider_settings.load_popup"));
|
||||
}
|
||||
|
||||
Provider::~Provider() {
|
||||
@@ -63,6 +55,22 @@ namespace hex::prv {
|
||||
patches.insert({ address + size, value });
|
||||
}
|
||||
|
||||
void Provider::remove(u64 offset, size_t size) {
|
||||
auto &patches = getPatches();
|
||||
|
||||
std::vector<std::pair<u64, u8>> patchesToMove;
|
||||
|
||||
for (auto &[address, value] : patches) {
|
||||
if (address > offset)
|
||||
patchesToMove.emplace_back(address, value);
|
||||
}
|
||||
|
||||
for (const auto &[address, value] : patchesToMove)
|
||||
patches.erase(address);
|
||||
for (const auto &[address, value] : patchesToMove)
|
||||
patches.insert({ address - size, value });
|
||||
}
|
||||
|
||||
void Provider::applyOverlays(u64 offset, void *buffer, size_t size) {
|
||||
for (auto &overlay : this->m_overlays) {
|
||||
auto overlayOffset = overlay->getAddress();
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace ImGui {
|
||||
if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) {
|
||||
auto &string = *static_cast<std::string *>(data->UserData);
|
||||
|
||||
string.resize(data->BufSize);
|
||||
string.resize(data->BufTextLen);
|
||||
data->Buf = string.data();
|
||||
}
|
||||
|
||||
@@ -487,7 +487,7 @@ namespace ImGui {
|
||||
return pressed;
|
||||
}
|
||||
|
||||
bool InputIntegerPrefix(const char *label, const char *prefix, u64 *value, ImGuiInputTextFlags flags) {
|
||||
bool InputIntegerPrefix(const char *label, const char *prefix, void *value, ImGuiDataType type, ImGuiInputTextFlags flags) {
|
||||
auto window = ImGui::GetCurrentWindow();
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const ImGuiStyle &style = GImGui->Style;
|
||||
@@ -500,7 +500,7 @@ namespace ImGui {
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + frame_size.x);
|
||||
|
||||
char buf[64];
|
||||
DataTypeFormatString(buf, IM_ARRAYSIZE(buf), ImGuiDataType_U64, value, "%llX");
|
||||
DataTypeFormatString(buf, IM_ARRAYSIZE(buf), type, value, "%llX");
|
||||
|
||||
bool value_changed = false;
|
||||
if (InputTextEx(label, nullptr, buf, IM_ARRAYSIZE(buf), ImVec2(CalcItemWidth() - frame_size.x, label_size.y + style.FramePadding.y * 2.0f), flags))
|
||||
@@ -519,8 +519,12 @@ namespace ImGui {
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
bool InputHexadecimal(const char *label, u32 *value, ImGuiInputTextFlags flags) {
|
||||
return InputIntegerPrefix(label, "0x", value, ImGuiDataType_U32, flags | ImGuiInputTextFlags_CharsHexadecimal);
|
||||
}
|
||||
|
||||
bool InputHexadecimal(const char *label, u64 *value, ImGuiInputTextFlags flags) {
|
||||
return InputIntegerPrefix(label, "0x", value, flags | ImGuiInputTextFlags_CharsHexadecimal);
|
||||
return InputIntegerPrefix(label, "0x", value, ImGuiDataType_U64, flags | ImGuiInputTextFlags_CharsHexadecimal);
|
||||
}
|
||||
|
||||
void SmallProgressBar(float fraction, float yOffset) {
|
||||
@@ -590,4 +594,47 @@ namespace ImGui {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool BitCheckbox(const char* label, bool* v) {
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
|
||||
const ImVec2 size = ImVec2(CalcTextSize("0").x + style.FramePadding.x * 2, GetFrameHeight());
|
||||
const ImVec2 pos = window->DC.CursorPos;
|
||||
const ImRect total_bb(pos, pos + size);
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!ItemAdd(total_bb, id))
|
||||
{
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hovered, held;
|
||||
bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
|
||||
if (pressed)
|
||||
{
|
||||
*v = !(*v);
|
||||
MarkItemEdited(id);
|
||||
}
|
||||
|
||||
const ImRect check_bb(pos, pos + size);
|
||||
RenderNavHighlight(total_bb, id);
|
||||
RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
|
||||
|
||||
RenderText(check_bb.Min + style.FramePadding, *v ? "1" : "0");
|
||||
|
||||
ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y);
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(label_pos, label);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
|
||||
return pressed;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,15 +8,6 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
std::string View::s_popupMessage;
|
||||
|
||||
std::function<void()> View::s_yesCallback, View::s_noCallback;
|
||||
|
||||
u32 View::s_selectableFileIndex;
|
||||
std::vector<std::fs::path> View::s_selectableFiles;
|
||||
std::function<void(std::fs::path)> View::s_selectableFileOpenCallback;
|
||||
std::vector<nfdfilteritem_t> View::s_selectableFilesValidExtensions;
|
||||
|
||||
ImFontAtlas *View::s_fontAtlas;
|
||||
ImFontConfig View::s_fontConfig;
|
||||
|
||||
@@ -26,123 +17,21 @@ namespace hex {
|
||||
return ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isAvailable();
|
||||
}
|
||||
|
||||
void View::drawCommonInterfaces() {
|
||||
auto windowSize = ImHexApi::System::getMainWindowSize();
|
||||
|
||||
ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300)));
|
||||
if (ImGui::BeginPopupModal("hex.builtin.common.info"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::TextFormattedWrapped("{}", s_popupMessage.c_str());
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("hex.builtin.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape))
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
||||
ImGui::SetWindowPos((windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing);
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300)));
|
||||
if (ImGui::BeginPopupModal("hex.builtin.common.error"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::TextFormattedWrapped("{}", s_popupMessage.c_str());
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("hex.builtin.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape))
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
||||
ImGui::SetWindowPos((windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing);
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300)));
|
||||
if (ImGui::BeginPopupModal("hex.builtin.common.fatal"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::TextFormattedWrapped("{}", s_popupMessage.c_str());
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("hex.builtin.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape)) {
|
||||
ImHexApi::Common::closeImHex();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::SetWindowPos((windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing);
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300)));
|
||||
if (ImGui::BeginPopupModal("hex.builtin.common.question"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::TextFormattedWrapped("{}", s_popupMessage.c_str());
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
|
||||
View::confirmButtons(
|
||||
"hex.builtin.common.yes"_lang, "hex.builtin.common.no"_lang, [] {
|
||||
s_yesCallback();
|
||||
ImGui::CloseCurrentPopup(); }, [] {
|
||||
s_noCallback();
|
||||
ImGui::CloseCurrentPopup(); });
|
||||
|
||||
ImGui::SetWindowPos((windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing);
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
bool opened = true;
|
||||
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
|
||||
if (ImGui::BeginPopupModal("hex.builtin.common.choose_file"_lang, &opened, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
|
||||
if (ImGui::BeginListBox("##files", ImVec2(300_scaled, 0))) {
|
||||
|
||||
u32 index = 0;
|
||||
for (auto &path : View::s_selectableFiles) {
|
||||
if (ImGui::Selectable(path.filename().string().c_str(), index == View::s_selectableFileIndex))
|
||||
View::s_selectableFileIndex = index;
|
||||
index++;
|
||||
}
|
||||
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
|
||||
if (ImGui::Button("hex.builtin.common.open"_lang)) {
|
||||
View::s_selectableFileOpenCallback(View::s_selectableFiles[View::s_selectableFileIndex]);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("hex.builtin.common.browse"_lang)) {
|
||||
fs::openFileBrowser(fs::DialogMode::Open, View::s_selectableFilesValidExtensions, [](const auto &path) {
|
||||
View::s_selectableFileOpenCallback(path);
|
||||
ImGui::CloseCurrentPopup();
|
||||
});
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
void View::showInfoPopup(const std::string &message) {
|
||||
EventManager::post<RequestShowInfoPopup>(message);
|
||||
}
|
||||
|
||||
void View::showMessagePopup(const std::string &message) {
|
||||
s_popupMessage = message;
|
||||
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.info"_lang); });
|
||||
void View::showErrorPopup(const std::string &message) {
|
||||
EventManager::post<RequestShowErrorPopup>(message);
|
||||
}
|
||||
|
||||
void View::showErrorPopup(const std::string &errorMessage) {
|
||||
s_popupMessage = errorMessage;
|
||||
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.error"_lang); });
|
||||
}
|
||||
|
||||
void View::showFatalPopup(const std::string &errorMessage) {
|
||||
s_popupMessage = errorMessage;
|
||||
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.fatal"_lang); });
|
||||
void View::showFatalPopup(const std::string &message) {
|
||||
EventManager::post<RequestShowFatalErrorPopup>(message);
|
||||
}
|
||||
|
||||
void View::showYesNoQuestionPopup(const std::string &message, const std::function<void()> &yesCallback, const std::function<void()> &noCallback) {
|
||||
s_popupMessage = message;
|
||||
EventManager::post<RequestShowYesNoQuestionPopup>(message, yesCallback, noCallback);
|
||||
|
||||
s_yesCallback = yesCallback;
|
||||
s_noCallback = noCallback;
|
||||
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.question"_lang); });
|
||||
}
|
||||
|
||||
void View::showFileChooserPopup(const std::vector<std::fs::path> &paths, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback) {
|
||||
@@ -151,12 +40,7 @@ namespace hex {
|
||||
callback(path);
|
||||
});
|
||||
} else {
|
||||
View::s_selectableFileIndex = 0;
|
||||
View::s_selectableFiles = paths;
|
||||
View::s_selectableFilesValidExtensions = validExtensions;
|
||||
View::s_selectableFileOpenCallback = callback;
|
||||
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.choose_file"_lang); });
|
||||
EventManager::post<RequestShowFileChooserPopup>(paths, validExtensions, callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +23,6 @@ namespace hex::init {
|
||||
this->m_tasks.emplace_back(taskName, task);
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::string &getGPUVendor() const { return this->m_gpuVendor; }
|
||||
|
||||
private:
|
||||
GLFWwindow *m_window;
|
||||
std::mutex m_progressMutex;
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace hex::init {
|
||||
this->initGLFW();
|
||||
this->initImGui();
|
||||
|
||||
this->m_gpuVendor = reinterpret_cast<const char *>(glGetString(GL_VENDOR));
|
||||
ImHexApi::System::impl::setGPUVendor(reinterpret_cast<const char *>(glGetString(GL_VENDOR)));
|
||||
}
|
||||
|
||||
WindowSplash::~WindowSplash() {
|
||||
@@ -173,18 +173,20 @@ namespace hex::init {
|
||||
|
||||
auto meanScale = std::midpoint(xScale, yScale);
|
||||
|
||||
// On Macs with a retina display (basically all modern ones we care about), the OS reports twice
|
||||
// the actual monitor scale for some obscure reason. Get rid of this here so ImHex doesn't look
|
||||
// extremely huge with native scaling on macOS.
|
||||
#if defined(OS_MACOS)
|
||||
meanScale /= 2;
|
||||
#endif
|
||||
// On Macs with a retina display (basically all modern ones we care about), the OS reports twice
|
||||
// the actual monitor scale for some obscure reason. Get rid of this here so ImHex doesn't look
|
||||
// extremely huge with native scaling on macOS.
|
||||
#if defined(OS_MACOS)
|
||||
meanScale /= 2;
|
||||
#endif
|
||||
|
||||
if (meanScale <= 0.0) {
|
||||
meanScale = 1.0;
|
||||
}
|
||||
|
||||
ImHexApi::System::impl::setGlobalScale(meanScale);
|
||||
} else {
|
||||
ImHexApi::System::impl::setGlobalScale(1.0);
|
||||
}
|
||||
|
||||
this->m_window = glfwCreateWindow(640_scaled, 400_scaled, "Starting ImHex...", nullptr, nullptr);
|
||||
|
||||
@@ -93,23 +93,6 @@ namespace hex::init {
|
||||
auto fonts = IM_NEW(ImFontAtlas)();
|
||||
ImFontConfig cfg = {};
|
||||
|
||||
std::fs::path fontFile = ContentRegistry::Settings::read("hex.builtin.setting.font", "hex.builtin.setting.font.font_path", "");
|
||||
if (!fs::exists(fontFile))
|
||||
fontFile.clear();
|
||||
|
||||
// If no custom font has been specified, search for a file called "font.ttf" in one of the resource folders
|
||||
if (fontFile.empty()) {
|
||||
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Resources)) {
|
||||
auto path = dir / "font.ttf";
|
||||
if (fs::exists(path)) {
|
||||
log::info("Loading custom front from {}", path.string());
|
||||
|
||||
fontFile = path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImVector<ImWchar> ranges;
|
||||
{
|
||||
ImFontGlyphRangesBuilder glyphRangesBuilder;
|
||||
@@ -135,7 +118,8 @@ namespace hex::init {
|
||||
0x0100, 0xFFF0, 0
|
||||
};
|
||||
|
||||
float fontSize = 13.0F * ImHexApi::System::getGlobalScale();
|
||||
auto fontFile = ImHexApi::System::getCustomFontPath();
|
||||
float fontSize = ImHexApi::System::getFontSize();
|
||||
if (fontFile.empty()) {
|
||||
// Load default font if no custom one has been specified
|
||||
|
||||
@@ -147,8 +131,6 @@ namespace hex::init {
|
||||
} else {
|
||||
// Load custom font
|
||||
|
||||
fontSize = ContentRegistry::Settings::read("hex.builtin.setting.font", "hex.builtin.setting.font.font_size", 13) * ImHexApi::System::getGlobalScale();
|
||||
|
||||
cfg.OversampleH = cfg.OversampleV = 1, cfg.PixelSnapH = true;
|
||||
cfg.SizePixels = fontSize;
|
||||
|
||||
@@ -170,6 +152,10 @@ namespace hex::init {
|
||||
}
|
||||
|
||||
bool deleteSharedData() {
|
||||
while (ImHexApi::Provider::isValid())
|
||||
ImHexApi::Provider::remove(ImHexApi::Provider::get());
|
||||
ContentRegistry::Provider::getEntries().clear();
|
||||
|
||||
ImHexApi::System::getInitArguments().clear();
|
||||
ImHexApi::Tasks::getDeferredCalls().clear();
|
||||
ImHexApi::HexEditor::impl::getBackgroundHighlights().clear();
|
||||
@@ -177,20 +163,23 @@ namespace hex::init {
|
||||
ImHexApi::HexEditor::impl::getBackgroundHighlightingFunctions().clear();
|
||||
ImHexApi::HexEditor::impl::getForegroundHighlightingFunctions().clear();
|
||||
ImHexApi::HexEditor::impl::getTooltips().clear();
|
||||
|
||||
while (ImHexApi::Provider::isValid())
|
||||
ImHexApi::Provider::remove(ImHexApi::Provider::get());
|
||||
ContentRegistry::Provider::getEntries().clear();
|
||||
ImHexApi::HexEditor::impl::getTooltipFunctions().clear();
|
||||
|
||||
ContentRegistry::Settings::getEntries().clear();
|
||||
ContentRegistry::Settings::getSettingsData().clear();
|
||||
|
||||
ContentRegistry::CommandPaletteCommands::getEntries().clear();
|
||||
ContentRegistry::PatternLanguage::getFunctions().clear();
|
||||
|
||||
for (auto &[name, view] : ContentRegistry::Views::getEntries())
|
||||
delete view;
|
||||
ContentRegistry::Views::getEntries().clear();
|
||||
ContentRegistry::PatternLanguage::getFunctions().clear();
|
||||
ContentRegistry::PatternLanguage::getPragmas().clear();
|
||||
|
||||
{
|
||||
auto &views = ContentRegistry::Views::getEntries();
|
||||
for (auto &[name, view] : views)
|
||||
delete view;
|
||||
views.clear();
|
||||
}
|
||||
|
||||
|
||||
ContentRegistry::Tools::getEntries().clear();
|
||||
ContentRegistry::DataInspector::getEntries().clear();
|
||||
@@ -217,6 +206,13 @@ namespace hex::init {
|
||||
ContentRegistry::DataFormatter::getEntries().clear();
|
||||
ContentRegistry::FileHandler::getEntries().clear();
|
||||
|
||||
{
|
||||
auto &visualizers = ContentRegistry::HexEditor::impl::getVisualizers();
|
||||
for (auto &[name, visualizer] : visualizers)
|
||||
delete visualizer;
|
||||
visualizers.clear();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -289,28 +285,6 @@ namespace hex::init {
|
||||
return false;
|
||||
}
|
||||
|
||||
float interfaceScaling = 1.0F;
|
||||
switch (ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.scaling", 0)) {
|
||||
default:
|
||||
case 0:
|
||||
// Native scaling
|
||||
break;
|
||||
case 1:
|
||||
interfaceScaling = 0.5F;
|
||||
break;
|
||||
case 2:
|
||||
interfaceScaling = 1.0F;
|
||||
break;
|
||||
case 3:
|
||||
interfaceScaling = 1.5F;
|
||||
break;
|
||||
case 4:
|
||||
interfaceScaling = 2.0F;
|
||||
break;
|
||||
}
|
||||
|
||||
ImHexApi::System::impl::setGlobalScale(interfaceScaling);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,17 +25,6 @@ int main(int argc, char **argv, char **envp) {
|
||||
|
||||
init::WindowSplash splashWindow;
|
||||
|
||||
// Intel's OpenGL driver has weird bugs that cause the drawn window to be offset to the bottom right.
|
||||
// This can be fixed by either using Mesa3D's OpenGL Software renderer or by simply disabling it.
|
||||
// If you want to try if it works anyways on your GPU, set the hex.builtin.setting.interface.force_borderless_window_mode setting to 1
|
||||
if (ImHexApi::System::isBorderlessWindowModeEnabled()) {
|
||||
bool isIntelGPU = hex::containsIgnoreCase(splashWindow.getGPUVendor(), "Intel");
|
||||
ImHexApi::System::impl::setBorderlessWindowMode(!isIntelGPU);
|
||||
|
||||
if (isIntelGPU)
|
||||
log::warn("Intel GPU detected! Intel's OpenGL driver has bugs that can cause issues when using ImHex. If you experience any rendering bugs, please try the Mesa3D Software Renderer");
|
||||
}
|
||||
|
||||
for (const auto &[name, task] : init::getInitTasks())
|
||||
splashWindow.addStartupTask(name, task);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/event.hpp>
|
||||
|
||||
@@ -21,7 +22,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
void Window::setupNativeWindow() {
|
||||
bool themeFollowSystem = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color") == 0;
|
||||
bool themeFollowSystem = ImHexApi::System::usesSystemThemeDetection();
|
||||
EventManager::subscribe<EventOSThemeChanged>(this, [themeFollowSystem] {
|
||||
if (!themeFollowSystem) return;
|
||||
|
||||
@@ -38,7 +39,7 @@ namespace hex {
|
||||
auto exitCode = WEXITSTATUS(pclose(pipe));
|
||||
if (exitCode != 0) return;
|
||||
|
||||
EventManager::post<RequestChangeTheme>(hex::containsIgnoreCase(result, "dark") ? 1 : 2);
|
||||
EventManager::post<RequestChangeTheme>(hex::containsIgnoreCase(result, "light") ? 2 : 1);
|
||||
});
|
||||
|
||||
if (themeFollowSystem)
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/event.hpp>
|
||||
|
||||
#include <hex/helpers/utils_macos.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
@@ -19,12 +21,14 @@ namespace hex {
|
||||
}
|
||||
|
||||
void Window::setupNativeWindow() {
|
||||
bool themeFollowSystem = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color") == 0;
|
||||
bool themeFollowSystem = ImHexApi::System::usesSystemThemeDetection();
|
||||
EventManager::subscribe<EventOSThemeChanged>(this, [themeFollowSystem] {
|
||||
if (!themeFollowSystem) return;
|
||||
|
||||
// TODO: Implement this when MacOS build is working again
|
||||
EventManager::post<RequestChangeTheme>(1);
|
||||
if (!isMacosSystemDarkModeEnabled())
|
||||
EventManager::post<RequestChangeTheme>(2);
|
||||
else
|
||||
EventManager::post<RequestChangeTheme>(1);
|
||||
});
|
||||
|
||||
if (themeFollowSystem)
|
||||
|
||||
@@ -348,11 +348,12 @@ namespace hex {
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Plugins, true)) {
|
||||
const auto filePath = path / "builtin.hexplug";
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(path.string().c_str());
|
||||
ImGui::TextUnformatted(filePath.string().c_str());
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(fs::exists(path) ? ICON_VS_CHECK : ICON_VS_CLOSE);
|
||||
ImGui::TextUnformatted(fs::exists(filePath) ? ICON_VS_CHECK : ICON_VS_CLOSE);
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
@@ -420,8 +421,6 @@ namespace hex {
|
||||
calls.clear();
|
||||
}
|
||||
|
||||
View::drawCommonInterfaces();
|
||||
|
||||
for (auto &[name, view] : ContentRegistry::Views::getEntries()) {
|
||||
ImGui::GetCurrentContext()->NextWindowData.ClearFlags();
|
||||
|
||||
@@ -653,8 +652,9 @@ namespace hex {
|
||||
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_NavEnableKeyboard;
|
||||
|
||||
{
|
||||
if (glfwGetPrimaryMonitor() != nullptr) {
|
||||
auto sessionType = hex::getEnvironmentVariable("XDG_SESSION_TYPE");
|
||||
|
||||
if (!sessionType || !hex::containsIgnoreCase(*sessionType, "wayland"))
|
||||
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ add_library(${PROJECT_NAME} SHARED
|
||||
source/content/welcome_screen.cpp
|
||||
source/content/data_visualizers.cpp
|
||||
source/content/events.cpp
|
||||
source/content/hashes.cpp
|
||||
|
||||
source/content/providers/file_provider.cpp
|
||||
source/content/providers/gdb_provider.cpp
|
||||
@@ -57,6 +58,7 @@ add_library(${PROJECT_NAME} SHARED
|
||||
source/lang/it_IT.cpp
|
||||
source/lang/zh_CN.cpp
|
||||
source/lang/ja_JP.cpp
|
||||
source/lang/pt_BR.cpp
|
||||
)
|
||||
|
||||
# Add additional include directories here #
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace hex::plugin::builtin::prv {
|
||||
|
||||
void resize(size_t newSize) override;
|
||||
void insert(u64 offset, size_t size) override;
|
||||
void remove(u64 offset, size_t size) override;
|
||||
|
||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||
void writeRaw(u64 offset, const void *buffer, size_t size) override;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/content_registry.hpp>
|
||||
|
||||
#include <hex/ui/view.hpp>
|
||||
|
||||
#include <array>
|
||||
@@ -16,35 +18,10 @@ namespace hex::plugin::builtin {
|
||||
void drawContent() override;
|
||||
|
||||
private:
|
||||
enum class HashFunctions
|
||||
{
|
||||
Crc8,
|
||||
Crc16,
|
||||
Crc32,
|
||||
Md5,
|
||||
Sha1,
|
||||
Sha224,
|
||||
Sha256,
|
||||
Sha384,
|
||||
Sha512
|
||||
};
|
||||
ContentRegistry::Hashes::Hash *m_selectedHash = nullptr;
|
||||
std::string m_newHashName;
|
||||
|
||||
bool m_shouldInvalidate = true;
|
||||
int m_currHashFunction = 0;
|
||||
u64 m_hashRegion[2] = { 0 };
|
||||
bool m_shouldMatchSelection = false;
|
||||
|
||||
static constexpr std::array hashFunctionNames {
|
||||
std::pair {HashFunctions::Crc8, "CRC8" },
|
||||
std::pair { HashFunctions::Crc16, "CRC16" },
|
||||
std::pair { HashFunctions::Crc32, "CRC32" },
|
||||
std::pair { HashFunctions::Md5, "MD5" },
|
||||
std::pair { HashFunctions::Sha1, "SHA-1" },
|
||||
std::pair { HashFunctions::Sha224, "SHA-224"},
|
||||
std::pair { HashFunctions::Sha256, "SHA-256"},
|
||||
std::pair { HashFunctions::Sha384, "SHA-384"},
|
||||
std::pair { HashFunctions::Sha512, "SHA-512"},
|
||||
};
|
||||
std::vector<ContentRegistry::Hashes::Hash::Function> m_hashFunctions;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ namespace hex::plugin::builtin {
|
||||
private:
|
||||
constexpr static auto InvalidSelection = std::numeric_limits<u64>::max();
|
||||
|
||||
void openFile(const std::fs::path &path);
|
||||
void registerShortcuts();
|
||||
void registerEvents();
|
||||
void registerMenuItems();
|
||||
@@ -31,15 +30,23 @@ namespace hex::plugin::builtin {
|
||||
|
||||
public:
|
||||
void setSelection(const Region ®ion) { this->setSelection(region.getStartAddress(), region.getEndAddress()); }
|
||||
void setSelection(i128 start, i128 end) {
|
||||
if (!ImHexApi::Provider::isValid()) return;
|
||||
void setSelection(u128 start, u128 end) {
|
||||
if (!ImHexApi::Provider::isValid())
|
||||
return;
|
||||
if (start == InvalidSelection && end == InvalidSelection)
|
||||
return;
|
||||
|
||||
if (start == InvalidSelection)
|
||||
start = end;
|
||||
if (end == InvalidSelection)
|
||||
end = start;
|
||||
|
||||
const size_t maxAddress = ImHexApi::Provider::get()->getActualSize() - 1;
|
||||
|
||||
this->m_selectionChanged = this->m_selectionStart != start || this->m_selectionEnd != end;
|
||||
|
||||
this->m_selectionStart = std::clamp<decltype(start)>(start, 0, maxAddress);
|
||||
this->m_selectionEnd = std::clamp<decltype(end)>(end, 0, maxAddress);
|
||||
this->m_selectionStart = std::clamp<u128>(start, 0, maxAddress);
|
||||
this->m_selectionEnd = std::clamp<u128>(end, 0, maxAddress);
|
||||
|
||||
if (this->m_selectionChanged) {
|
||||
EventManager::post<EventRegionSelected>(this->getSelection());
|
||||
@@ -66,6 +73,10 @@ namespace hex::plugin::builtin {
|
||||
this->m_shouldScrollToSelection = true;
|
||||
}
|
||||
|
||||
void jumpIfOffScreen() {
|
||||
this->m_shouldJumpWhenOffScreen = true;
|
||||
}
|
||||
|
||||
public:
|
||||
class Popup {
|
||||
public:
|
||||
@@ -105,6 +116,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
bool m_shouldJumpToSelection = false;
|
||||
bool m_shouldScrollToSelection = false;
|
||||
bool m_shouldJumpWhenOffScreen = false;
|
||||
|
||||
bool m_selectionChanged = false;
|
||||
u64 m_selectionStart = InvalidSelection;
|
||||
@@ -115,6 +127,7 @@ namespace hex::plugin::builtin {
|
||||
std::optional<u64> m_editingAddress;
|
||||
bool m_shouldModifyValue = false;
|
||||
bool m_enteredEditingMode = false;
|
||||
bool m_shouldUpdateEditingValue = false;
|
||||
std::vector<u8> m_editingBytes;
|
||||
|
||||
color_t m_selectionColor = 0x00;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace hex::plugin::builtin {
|
||||
void drawContent() override;
|
||||
|
||||
private:
|
||||
pl::PatternLanguage *m_parserRuntime;
|
||||
std::unique_ptr<pl::PatternLanguage> m_parserRuntime;
|
||||
|
||||
std::vector<std::fs::path> m_possiblePatternFiles;
|
||||
u32 m_selectedPatternFile = 0;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace hex::plugin::builtin {
|
||||
u32 tooltipId;
|
||||
};
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> m_rules;
|
||||
std::vector<std::pair<std::fs::path, std::fs::path>> m_rules;
|
||||
std::vector<YaraMatch> m_matches;
|
||||
u32 m_selectedRule = 0;
|
||||
bool m_matching = false;
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
namespace hex {
|
||||
|
||||
template<typename T>
|
||||
concept ArrayPattern = requires(T pattern, std::function<void(int, pl::Pattern&)> fn) {
|
||||
{ pattern.forEachArrayEntry(fn) } -> std::same_as<void>;
|
||||
concept ArrayPattern = requires(u64 displayEnd, T pattern, std::function<void(int, pl::Pattern&)> fn) {
|
||||
{ pattern.forEachArrayEntry(displayEnd, fn) } -> std::same_as<void>;
|
||||
};
|
||||
|
||||
class PatternDrawer : public pl::PatternVisitor {
|
||||
@@ -48,7 +48,7 @@ namespace hex {
|
||||
|
||||
if (opened) {
|
||||
auto& displayEnd = this->getDisplayEnd(pattern);
|
||||
pattern.forEachArrayEntry([&] (u64 idx, auto &entry){
|
||||
pattern.forEachArrayEntry(displayEnd, [&] (u64 idx, auto &entry){
|
||||
this->drawArrayNode(idx, displayEnd, entry);
|
||||
});
|
||||
}
|
||||
@@ -57,7 +57,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
bool drawArrayRoot(pl::Pattern& pattern, size_t entryCount, bool isInlined);
|
||||
void drawArrayNode(u64 idx, u64 displayEnd, pl::Pattern& pattern);
|
||||
void drawArrayNode(u64 idx, u64& displayEnd, pl::Pattern& pattern);
|
||||
void drawArrayEnd(pl::Pattern& pattern, bool opened);
|
||||
|
||||
void drawCommentTooltip(const pl::Pattern &pattern) const;
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace hex::plugin::builtin {
|
||||
[](auto buffer, auto endian, auto style) {
|
||||
hex::unused(endian, style);
|
||||
|
||||
std::string binary = hex::format("0b{:b}", buffer[0]);
|
||||
std::string binary = hex::format("0b{:08b}", buffer[0]);
|
||||
|
||||
return [binary] {
|
||||
ImGui::TextUnformatted(binary.c_str());
|
||||
@@ -314,7 +314,7 @@ namespace hex::plugin::builtin {
|
||||
return [value] { ImGui::TextFormatted("'{0}'", value.c_str()); return value; };
|
||||
},
|
||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter("");
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter("Invalid");
|
||||
|
||||
std::vector<u8> bytes;
|
||||
auto wideString = converter.from_bytes(value.c_str());
|
||||
|
||||
@@ -777,7 +777,16 @@ namespace hex::plugin::builtin {
|
||||
NodeVisualizerDigram() : Node("hex.builtin.nodes.visualizer.digram.header", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "hex.builtin.nodes.common.input") }) { }
|
||||
|
||||
void drawNode() override {
|
||||
const auto viewSize = scaled({ 200, 200 });
|
||||
drawDigram(scaled({ 200, 200 }));
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
drawDigram(scaled({ 600, 600 }));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
void drawDigram(const ImVec2 &viewSize) {
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImU32(ImColor(0, 0, 0)));
|
||||
if (ImGui::BeginChild("##visualizer", viewSize, true)) {
|
||||
auto drawList = ImGui::GetWindowDrawList();
|
||||
@@ -860,7 +869,15 @@ namespace hex::plugin::builtin {
|
||||
NodeVisualizerLayeredDistribution() : Node("hex.builtin.nodes.visualizer.layered_dist.header", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "hex.builtin.nodes.common.input") }) { }
|
||||
|
||||
void drawNode() override {
|
||||
const auto viewSize = scaled({ 200, 200 });
|
||||
drawLayeredDistribution(scaled({ 200, 200 }));
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
drawLayeredDistribution(scaled({ 600, 600 }));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
void drawLayeredDistribution(const ImVec2 &viewSize) {
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImU32(ImColor(0, 0, 0)));
|
||||
if (ImGui::BeginChild("##visualizer", viewSize, true)) {
|
||||
auto drawList = ImGui::GetWindowDrawList();
|
||||
@@ -944,6 +961,11 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void drawNode() override {
|
||||
ImGui::Image(this->m_texture, scaled(ImVec2(this->m_texture.aspectRatio() * 200, 200)));
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Image(this->m_texture, scaled(ImVec2(this->m_texture.aspectRatio() * 600, 600)));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
void process() override {
|
||||
@@ -964,8 +986,18 @@ namespace hex::plugin::builtin {
|
||||
NodeVisualizerByteDistribution() : Node("hex.builtin.nodes.visualizer.byte_distribution.header", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "hex.builtin.nodes.common.input") }) { }
|
||||
|
||||
void drawNode() override {
|
||||
drawPlot(scaled({ 400, 300 }));
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
drawPlot(scaled({ 700, 550 }));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
void drawPlot(const ImVec2 &viewSize) {
|
||||
ImPlot::SetNextPlotLimits(0, 256, 0.5, float(*std::max_element(this->m_counts.begin(), this->m_counts.end())) * 1.1F, ImGuiCond_Always);
|
||||
if (ImPlot::BeginPlot("##distribution", "Address", "Count", scaled(ImVec2(400, 300)), ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect, ImPlotAxisFlags_Lock, ImPlotAxisFlags_Lock | ImPlotAxisFlags_LogScale, ImPlotAxisFlags_NoLabel | ImPlotAxisFlags_NoTickLabels, ImPlotAxisFlags_NoLabel | ImPlotAxisFlags_NoTickLabels)) {
|
||||
if (ImPlot::BeginPlot("##distribution", "Address", "Count", viewSize, ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect, ImPlotAxisFlags_Lock, ImPlotAxisFlags_Lock | ImPlotAxisFlags_LogScale, ImPlotAxisFlags_NoLabel | ImPlotAxisFlags_NoTickLabels, ImPlotAxisFlags_NoLabel | ImPlotAxisFlags_NoTickLabels)) {
|
||||
static auto x = [] {
|
||||
std::array<ImU64, 256> result { 0 };
|
||||
std::iota(result.begin(), result.end(), 0);
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace hex::plugin::builtin {
|
||||
else static_assert(hex::always_false<T>::value, "Invalid data type!");
|
||||
}
|
||||
|
||||
template<hex::integral T>
|
||||
template<std::integral T>
|
||||
class DataVisualizerHexadecimal : public hex::ContentRegistry::HexEditor::DataVisualizer {
|
||||
public:
|
||||
DataVisualizerHexadecimal() : DataVisualizer(ByteCount, CharCount) { }
|
||||
@@ -114,7 +114,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
};
|
||||
|
||||
template<hex::integral T>
|
||||
template<std::integral T>
|
||||
class DataVisualizerDecimal : public hex::ContentRegistry::HexEditor::DataVisualizer {
|
||||
public:
|
||||
DataVisualizerDecimal() : DataVisualizer(ByteCount, CharCount) { }
|
||||
@@ -123,7 +123,7 @@ namespace hex::plugin::builtin {
|
||||
hex::unused(address, upperCase);
|
||||
|
||||
if (size == ByteCount) {
|
||||
if (hex::is_signed<T>::value)
|
||||
if (std::is_signed<T>::value)
|
||||
ImGui::Text(getFormatString(), static_cast<i64>(*reinterpret_cast<const T*>(data)));
|
||||
else
|
||||
ImGui::Text(getFormatString(), static_cast<u64>(*reinterpret_cast<const T*>(data)));
|
||||
@@ -153,14 +153,14 @@ namespace hex::plugin::builtin {
|
||||
constexpr static inline auto ByteCount = sizeof(T);
|
||||
constexpr static inline auto CharCount = std::numeric_limits<T>::digits10 + 2;
|
||||
|
||||
const static inline auto FormatString = hex::format("%{}{}", CharCount, hex::is_signed<T>::value ? "lld" : "llu");
|
||||
const static inline auto FormatString = hex::format("%{}{}", CharCount, std::is_signed<T>::value ? "lld" : "llu");
|
||||
|
||||
const char *getFormatString() {
|
||||
return FormatString.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
template<hex::floating_point T>
|
||||
template<std::floating_point T>
|
||||
class DataVisualizerFloatingPoint : public hex::ContentRegistry::HexEditor::DataVisualizer {
|
||||
public:
|
||||
DataVisualizerFloatingPoint() : DataVisualizer(ByteCount, CharCount) { }
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
#include <hex/api/event.hpp>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/ui/view.hpp>
|
||||
#include <hex/helpers/project_file_handler.hpp>
|
||||
#include <hex/api/localization.hpp>
|
||||
#include <hex/helpers/file.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
@@ -86,6 +89,11 @@ namespace hex::plugin::builtin {
|
||||
EventManager::subscribe<EventProviderChanged>([](auto, auto) {
|
||||
EventManager::post<EventHighlightingChanged>();
|
||||
});
|
||||
|
||||
EventManager::subscribe<EventProviderCreated>([](hex::prv::Provider *provider) {
|
||||
if (provider->hasLoadInterface())
|
||||
EventManager::post<RequestOpenPopup>(View::toWindowName("hex.builtin.view.provider_settings.load_popup"));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
140
plugins/builtin/source/content/hashes.cpp
Normal file
140
plugins/builtin/source/content/hashes.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/localization.hpp>
|
||||
#include <hex/helpers/crypto.hpp>
|
||||
|
||||
#include <hex/ui/imgui_imhex_extensions.h>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class HashMD5 : public ContentRegistry::Hashes::Hash {
|
||||
public:
|
||||
HashMD5() : Hash("hex.builtin.hash.md5") {}
|
||||
|
||||
Function create(std::string name) override {
|
||||
return Hash::create(name, [](const Region& region, prv::Provider *provider) -> std::vector<u8> {
|
||||
auto array = crypt::md5(provider, region.address, region.size);
|
||||
|
||||
return { array.begin(), array.end() };
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class HashSHA1 : public ContentRegistry::Hashes::Hash {
|
||||
public:
|
||||
HashSHA1() : Hash("hex.builtin.hash.sha1") {}
|
||||
|
||||
Function create(std::string name) override {
|
||||
return Hash::create(name, [](const Region& region, prv::Provider *provider) -> std::vector<u8> {
|
||||
auto array = crypt::sha1(provider, region.address, region.size);
|
||||
|
||||
return { array.begin(), array.end() };
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class HashSHA224 : public ContentRegistry::Hashes::Hash {
|
||||
public:
|
||||
HashSHA224() : Hash("hex.builtin.hash.sha224") {}
|
||||
|
||||
Function create(std::string name) override {
|
||||
return Hash::create(name, [](const Region& region, prv::Provider *provider) -> std::vector<u8> {
|
||||
auto array = crypt::sha224(provider, region.address, region.size);
|
||||
|
||||
return { array.begin(), array.end() };
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class HashSHA256 : public ContentRegistry::Hashes::Hash {
|
||||
public:
|
||||
HashSHA256() : Hash("hex.builtin.hash.sha256") {}
|
||||
|
||||
Function create(std::string name) override {
|
||||
return Hash::create(name, [](const Region& region, prv::Provider *provider) -> std::vector<u8> {
|
||||
auto array = crypt::sha256(provider, region.address, region.size);
|
||||
|
||||
return { array.begin(), array.end() };
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class HashSHA384 : public ContentRegistry::Hashes::Hash {
|
||||
public:
|
||||
HashSHA384() : Hash("hex.builtin.hash.sha384") {}
|
||||
|
||||
Function create(std::string name) override {
|
||||
return Hash::create(name, [](const Region& region, prv::Provider *provider) -> std::vector<u8> {
|
||||
auto array = crypt::sha384(provider, region.address, region.size);
|
||||
|
||||
return { array.begin(), array.end() };
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class HashSHA512 : public ContentRegistry::Hashes::Hash {
|
||||
public:
|
||||
HashSHA512() : Hash("hex.builtin.hash.sha512") {}
|
||||
|
||||
Function create(std::string name) override {
|
||||
return Hash::create(name, [](const Region& region, prv::Provider *provider) -> std::vector<u8> {
|
||||
auto array = crypt::sha512(provider, region.address, region.size);
|
||||
|
||||
return { array.begin(), array.end() };
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class HashCRC : public ContentRegistry::Hashes::Hash {
|
||||
public:
|
||||
using CRCFunction = T(*)(prv::Provider*&, u64, size_t, u32, u32, u32, bool, bool);
|
||||
HashCRC(const std::string &name, const CRCFunction &crcFunction, u32 polynomial, u32 initialValue, u32 xorOut)
|
||||
: Hash(name), m_crcFunction(crcFunction), m_polynomial(polynomial), m_initialValue(initialValue), m_xorOut(xorOut) {}
|
||||
|
||||
void draw() override {
|
||||
ImGui::InputHexadecimal("hex.builtin.hash.crc.poly"_lang, &this->m_polynomial);
|
||||
ImGui::InputHexadecimal("hex.builtin.hash.crc.iv"_lang, &this->m_initialValue);
|
||||
ImGui::InputHexadecimal("hex.builtin.hash.crc.xor_out"_lang, &this->m_xorOut);
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::Checkbox("hex.builtin.hash.crc.refl_in"_lang, &this->m_reflectIn);
|
||||
ImGui::Checkbox("hex.builtin.hash.crc.refl_out"_lang, &this->m_reflectOut);
|
||||
}
|
||||
|
||||
Function create(std::string name) override {
|
||||
return Hash::create(name, [hash = *this](const Region& region, prv::Provider *provider) -> std::vector<u8> {
|
||||
auto result = hash.m_crcFunction(provider, region.address, region.size, hash.m_polynomial, hash.m_initialValue, hash.m_xorOut, hash.m_reflectIn, hash.m_reflectOut);
|
||||
|
||||
std::vector<u8> bytes(sizeof(result), 0x00);
|
||||
std::memcpy(bytes.data(), &result, bytes.size());
|
||||
|
||||
return bytes;
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
CRCFunction m_crcFunction;
|
||||
|
||||
u32 m_polynomial;
|
||||
u32 m_initialValue;
|
||||
u32 m_xorOut;
|
||||
bool m_reflectIn = false, m_reflectOut = false;
|
||||
};
|
||||
|
||||
void registerHashes() {
|
||||
ContentRegistry::Hashes::add<HashMD5>();
|
||||
|
||||
ContentRegistry::Hashes::add<HashSHA1>();
|
||||
ContentRegistry::Hashes::add<HashSHA224>();
|
||||
ContentRegistry::Hashes::add<HashSHA256>();
|
||||
ContentRegistry::Hashes::add<HashSHA384>();
|
||||
ContentRegistry::Hashes::add<HashSHA512>();
|
||||
|
||||
ContentRegistry::Hashes::add<HashCRC<u16>>("hex.builtin.hash.crc8", crypt::crc8, 0x07, 0x0000, 0x0000);
|
||||
ContentRegistry::Hashes::add<HashCRC<u16>>("hex.builtin.hash.crc16", crypt::crc16, 0x8005, 0x0000, 0x0000);
|
||||
ContentRegistry::Hashes::add<HashCRC<u32>>("hex.builtin.hash.crc32", crypt::crc32, 0x04C1'1DB7, 0xFFFF'FFFF, 0xFFFF'FFFF);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -125,7 +125,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) {
|
||||
std::thread([path] {
|
||||
auto task = ImHexApi::Tasks::createTask("hex.common.processing", 0);
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.common.processing", 0);
|
||||
|
||||
auto patchData = fs::File(path, fs::File::Mode::Read).readBytes();
|
||||
auto patch = hex::loadIPSPatch(patchData);
|
||||
@@ -149,7 +149,7 @@ namespace hex::plugin::builtin {
|
||||
if (ImGui::MenuItem("hex.builtin.menu.file.import.ips32"_lang, nullptr, false)) {
|
||||
fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) {
|
||||
std::thread([path] {
|
||||
auto task = ImHexApi::Tasks::createTask("hex.common.processing", 0);
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.common.processing", 0);
|
||||
|
||||
auto patchData = fs::File(path, fs::File::Mode::Read).readBytes();
|
||||
auto patch = hex::loadIPS32Patch(patchData);
|
||||
@@ -185,7 +185,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
std::thread([patches] {
|
||||
auto task = ImHexApi::Tasks::createTask("hex.common.processing", 0);
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.common.processing", 0);
|
||||
|
||||
auto data = generateIPSPatch(patches);
|
||||
|
||||
@@ -212,7 +212,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
std::thread([patches] {
|
||||
auto task = ImHexApi::Tasks::createTask("hex.common.processing", 0);
|
||||
auto task = ImHexApi::Tasks::createTask("hex.builtin.common.processing", 0);
|
||||
|
||||
auto data = generateIPS32Patch(patches);
|
||||
|
||||
@@ -257,7 +257,7 @@ namespace hex::plugin::builtin {
|
||||
if (ImGui::MenuItem("hex.builtin.menu.edit.bookmark"_lang, nullptr, false, selection.has_value() && providerValid)) {
|
||||
auto base = provider->getBaseAddress();
|
||||
|
||||
ImHexApi::Bookmarks::add(base + selection->getStartAddress(), selection->getEndAddress(), {}, {});
|
||||
ImHexApi::Bookmarks::add(base + selection->getStartAddress(), selection->size, {}, {});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,248 +1,18 @@
|
||||
#include <hex/api/content_registry.hpp>
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/net.hpp>
|
||||
#include <hex/helpers/file.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
#include <pl/token.hpp>
|
||||
#include <pl/log_console.hpp>
|
||||
#include <pl/evaluator.hpp>
|
||||
#include <pl/patterns/pattern.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/args.h>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
std::string format(const auto ¶ms) {
|
||||
auto format = pl::Token::literalToString(params[0], true);
|
||||
std::string message;
|
||||
|
||||
fmt::dynamic_format_arg_store<fmt::format_context> formatArgs;
|
||||
|
||||
for (u32 i = 1; i < params.size(); i++) {
|
||||
auto ¶m = params[i];
|
||||
|
||||
std::visit(overloaded {
|
||||
[&](pl::Pattern *value) {
|
||||
formatArgs.push_back(value->toString());
|
||||
},
|
||||
[&](auto &&value) {
|
||||
formatArgs.push_back(value);
|
||||
} },
|
||||
param);
|
||||
}
|
||||
|
||||
try {
|
||||
return fmt::vformat(format, formatArgs);
|
||||
} catch (fmt::format_error &error) {
|
||||
pl::LogConsole::abortEvaluation(hex::format("format error: {}", error.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void registerPatternLanguageFunctions() {
|
||||
using namespace pl;
|
||||
using FunctionParameterCount = pl::api::FunctionParameterCount;
|
||||
|
||||
pl::api::Namespace nsStd = { "builtin", "std" };
|
||||
{
|
||||
/* print(format, args...) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStd, "print", FunctionParameterCount::moreThan(0), [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
ctx->getConsole().log(LogConsole::Level::Info, format(params));
|
||||
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
/* format(format, args...) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStd, "format", FunctionParameterCount::moreThan(0), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return format(params);
|
||||
});
|
||||
|
||||
/* env(name) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStd, "env", FunctionParameterCount::exactly(1), [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
auto name = Token::literalToString(params[0], false);
|
||||
|
||||
auto env = ctx->getEnvVariable(name);
|
||||
if (env)
|
||||
return env;
|
||||
else {
|
||||
ctx->getConsole().log(LogConsole::Level::Warning, hex::format("environment variable '{}' does not exist", name));
|
||||
return "";
|
||||
}
|
||||
});
|
||||
|
||||
/* pack_size(...) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStd, "sizeof_pack", FunctionParameterCount::atLeast(0), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return u128(params.size());
|
||||
});
|
||||
|
||||
/* error(message) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStd, "error", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
LogConsole::abortEvaluation(Token::literalToString(params[0], true));
|
||||
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
/* warning(message) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStd, "warning", FunctionParameterCount::exactly(1), [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
ctx->getConsole().log(LogConsole::Level::Warning, Token::literalToString(params[0], true));
|
||||
|
||||
return std::nullopt;
|
||||
});
|
||||
}
|
||||
|
||||
api::Namespace nsStdMem = { "builtin", "std", "mem" };
|
||||
{
|
||||
|
||||
/* base_address() */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMem, "base_address", FunctionParameterCount::none(), [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
hex::unused(params);
|
||||
|
||||
return u128(ctx->getDataBaseAddress());
|
||||
});
|
||||
|
||||
/* size() */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMem, "size", FunctionParameterCount::none(), [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
hex::unused(params);
|
||||
|
||||
return u128(ctx->getDataSize());
|
||||
});
|
||||
|
||||
/* find_sequence_in_range(occurrence_index, start_offset, end_offset, bytes...) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMem, "find_sequence_in_range", FunctionParameterCount::moreThan(3), [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
auto occurrenceIndex = Token::literalToUnsigned(params[0]);
|
||||
auto offsetFrom = Token::literalToUnsigned(params[1]);
|
||||
auto offsetTo = Token::literalToUnsigned(params[2]);
|
||||
|
||||
std::vector<u8> sequence;
|
||||
for (u32 i = 3; i < params.size(); i++) {
|
||||
auto byte = Token::literalToUnsigned(params[i]);
|
||||
|
||||
if (byte > 0xFF)
|
||||
LogConsole::abortEvaluation(hex::format("byte #{} value out of range: {} > 0xFF", i, u64(byte)));
|
||||
|
||||
sequence.push_back(u8(byte & 0xFF));
|
||||
}
|
||||
|
||||
std::vector<u8> bytes(sequence.size(), 0x00);
|
||||
u32 occurrences = 0;
|
||||
const u64 bufferSize = ctx->getDataSize();
|
||||
const u64 endOffset = offsetTo <= offsetFrom ? bufferSize : std::min(bufferSize, u64(offsetTo));
|
||||
for (u64 offset = offsetFrom; offset < endOffset - sequence.size(); offset++) {
|
||||
ctx->readData(offset, bytes.data(), bytes.size());
|
||||
|
||||
if (bytes == sequence) {
|
||||
if (occurrences < occurrenceIndex) {
|
||||
occurrences++;
|
||||
continue;
|
||||
}
|
||||
|
||||
return u128(offset);
|
||||
}
|
||||
}
|
||||
|
||||
return i128(-1);
|
||||
});
|
||||
|
||||
/* read_unsigned(address, size) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMem, "read_unsigned", FunctionParameterCount::exactly(2), [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
auto address = Token::literalToUnsigned(params[0]);
|
||||
auto size = Token::literalToUnsigned(params[1]);
|
||||
|
||||
if (size > 16)
|
||||
LogConsole::abortEvaluation("read size out of range");
|
||||
|
||||
u128 result = 0;
|
||||
ctx->readData(address, &result, size);
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
/* read_signed(address, size) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMem, "read_signed", FunctionParameterCount::exactly(2), [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
auto address = Token::literalToUnsigned(params[0]);
|
||||
auto size = Token::literalToUnsigned(params[1]);
|
||||
|
||||
if (size > 16)
|
||||
LogConsole::abortEvaluation("read size out of range");
|
||||
|
||||
i128 value;
|
||||
ctx->readData(address, &value, size);
|
||||
return hex::signExtend(size * 8, value);
|
||||
});
|
||||
|
||||
/* read_string(address, size) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMem, "read_string", FunctionParameterCount::exactly(2), [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
auto address = Token::literalToUnsigned(params[0]);
|
||||
auto size = Token::literalToUnsigned(params[1]);
|
||||
|
||||
std::string result(size, '\x00');
|
||||
ctx->readData(address, result.data(), size);
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
api::Namespace nsStdString = { "builtin", "std", "string" };
|
||||
{
|
||||
/* length(string) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdString, "length", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
auto string = Token::literalToString(params[0], false);
|
||||
|
||||
return u128(string.length());
|
||||
});
|
||||
|
||||
/* at(string, index) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdString, "at", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
auto string = Token::literalToString(params[0], false);
|
||||
auto index = Token::literalToSigned(params[1]);
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
const auto signIndex = index >> (sizeof(index) * 8 - 1);
|
||||
const auto absIndex = (index ^ signIndex) - signIndex;
|
||||
#else
|
||||
const auto absIndex = std::abs(index);
|
||||
#endif
|
||||
|
||||
if (absIndex > string.length())
|
||||
LogConsole::abortEvaluation("character index out of range");
|
||||
|
||||
if (index >= 0)
|
||||
return char(string[index]);
|
||||
else
|
||||
return char(string[string.length() - -index]);
|
||||
});
|
||||
|
||||
/* substr(string, pos, count) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdString, "substr", FunctionParameterCount::exactly(3), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
auto string = Token::literalToString(params[0], false);
|
||||
auto pos = Token::literalToUnsigned(params[1]);
|
||||
auto size = Token::literalToUnsigned(params[2]);
|
||||
|
||||
if (pos > string.length())
|
||||
LogConsole::abortEvaluation("character index out of range");
|
||||
|
||||
return string.substr(pos, size);
|
||||
});
|
||||
|
||||
/* parse_int(string, base) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdString, "parse_int", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
auto string = Token::literalToString(params[0], false);
|
||||
auto base = Token::literalToUnsigned(params[1]);
|
||||
|
||||
return i128(std::strtoll(string.c_str(), nullptr, base));
|
||||
});
|
||||
|
||||
/* parse_float(string) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdString, "parse_float", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
auto string = Token::literalToString(params[0], false);
|
||||
|
||||
return double(std::strtod(string.c_str(), nullptr));
|
||||
});
|
||||
}
|
||||
|
||||
api::Namespace nsStdHttp = { "builtin", "std", "http" };
|
||||
{
|
||||
/* get(url) */
|
||||
@@ -253,267 +23,5 @@ namespace hex::plugin::builtin {
|
||||
return net.getString(url).get().body;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
api::Namespace nsStdFile = { "builtin", "std", "file" };
|
||||
{
|
||||
static u32 fileCounter = 0;
|
||||
static std::map<u32, fs::File> openFiles;
|
||||
|
||||
/* open(path, mode) */
|
||||
ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "open", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
const auto path = Token::literalToString(params[0], false);
|
||||
const auto modeEnum = Token::literalToUnsigned(params[1]);
|
||||
|
||||
fs::File::Mode mode;
|
||||
switch (modeEnum) {
|
||||
case 1:
|
||||
mode = fs::File::Mode::Read;
|
||||
break;
|
||||
case 2:
|
||||
mode = fs::File::Mode::Write;
|
||||
break;
|
||||
case 3:
|
||||
mode = fs::File::Mode::Create;
|
||||
break;
|
||||
default:
|
||||
LogConsole::abortEvaluation("invalid file open mode");
|
||||
}
|
||||
|
||||
fs::File file(path, mode);
|
||||
|
||||
if (!file.isValid())
|
||||
LogConsole::abortEvaluation(hex::format("failed to open file {}", path));
|
||||
|
||||
fileCounter++;
|
||||
openFiles.emplace(std::pair { fileCounter, std::move(file) });
|
||||
|
||||
return u128(fileCounter);
|
||||
});
|
||||
|
||||
/* close(file) */
|
||||
ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "close", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
const auto file = Token::literalToUnsigned(params[0]);
|
||||
|
||||
if (!openFiles.contains(file))
|
||||
LogConsole::abortEvaluation("failed to access invalid file");
|
||||
|
||||
openFiles.erase(file);
|
||||
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
/* read(file, size) */
|
||||
ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "read", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
const auto file = Token::literalToUnsigned(params[0]);
|
||||
const auto size = Token::literalToUnsigned(params[1]);
|
||||
|
||||
if (!openFiles.contains(file))
|
||||
LogConsole::abortEvaluation("failed to access invalid file");
|
||||
|
||||
return openFiles[file].readString(size);
|
||||
});
|
||||
|
||||
/* write(file, data) */
|
||||
ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "write", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
const auto file = Token::literalToUnsigned(params[0]);
|
||||
const auto data = Token::literalToString(params[1], true);
|
||||
|
||||
if (!openFiles.contains(file))
|
||||
LogConsole::abortEvaluation("failed to access invalid file");
|
||||
|
||||
openFiles[file].write(data);
|
||||
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
/* seek(file, offset) */
|
||||
ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "seek", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
const auto file = Token::literalToUnsigned(params[0]);
|
||||
const auto offset = Token::literalToUnsigned(params[1]);
|
||||
|
||||
if (!openFiles.contains(file))
|
||||
LogConsole::abortEvaluation("failed to access invalid file");
|
||||
|
||||
openFiles[file].seek(offset);
|
||||
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
/* size(file) */
|
||||
ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "size", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
const auto file = Token::literalToUnsigned(params[0]);
|
||||
|
||||
if (!openFiles.contains(file))
|
||||
LogConsole::abortEvaluation("failed to access invalid file");
|
||||
|
||||
return u128(openFiles[file].getSize());
|
||||
});
|
||||
|
||||
/* resize(file, size) */
|
||||
ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "resize", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
const auto file = Token::literalToUnsigned(params[0]);
|
||||
const auto size = Token::literalToUnsigned(params[1]);
|
||||
|
||||
if (!openFiles.contains(file))
|
||||
LogConsole::abortEvaluation("failed to access invalid file");
|
||||
|
||||
openFiles[file].setSize(size);
|
||||
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
/* flush(file) */
|
||||
ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "flush", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
const auto file = Token::literalToUnsigned(params[0]);
|
||||
|
||||
if (!openFiles.contains(file))
|
||||
LogConsole::abortEvaluation("failed to access invalid file");
|
||||
|
||||
openFiles[file].flush();
|
||||
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
/* remove(file) */
|
||||
ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "remove", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
const auto file = Token::literalToUnsigned(params[0]);
|
||||
|
||||
if (!openFiles.contains(file))
|
||||
LogConsole::abortEvaluation("failed to access invalid file");
|
||||
|
||||
openFiles[file].remove();
|
||||
|
||||
return std::nullopt;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
api::Namespace nsStdMath = { "builtin", "std", "math" };
|
||||
{
|
||||
/* floor(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "floor", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::floor(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* ceil(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "ceil", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::ceil(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* round(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "round", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::round(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* trunc(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "trunc", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::trunc(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
|
||||
/* log10(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "log10", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::log10(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* log2(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "log2", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::log2(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* ln(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "ln", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::log(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
|
||||
/* fmod(x, y) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "fmod", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::fmod(Token::literalToFloatingPoint(params[0]), Token::literalToFloatingPoint(params[1]));
|
||||
});
|
||||
|
||||
/* pow(base, exp) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "pow", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::pow(Token::literalToFloatingPoint(params[0]), Token::literalToFloatingPoint(params[1]));
|
||||
});
|
||||
|
||||
/* sqrt(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "sqrt", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::sqrt(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* cbrt(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "cbrt", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::cbrt(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
|
||||
/* sin(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "sin", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::sin(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* cos(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "cos", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::cos(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* tan(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "tan", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::tan(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* asin(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "asin", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::asin(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* acos(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "acos", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::acos(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* atan(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "atan", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::atan(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* atan2(y, x) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "atan", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::atan2(Token::literalToFloatingPoint(params[0]), Token::literalToFloatingPoint(params[1]));
|
||||
});
|
||||
|
||||
|
||||
/* sinh(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "sinh", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::sinh(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* cosh(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "cosh", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::cosh(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* tanh(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "tanh", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::tanh(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* asinh(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "asinh", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::asinh(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* acosh(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "acosh", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::acosh(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
|
||||
/* atanh(value) */
|
||||
ContentRegistry::PatternLanguage::addFunction(nsStdMath, "atanh", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||
return std::atanh(Token::literalToFloatingPoint(params[0]));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace hex::plugin::builtin::prv {
|
||||
|
||||
auto position = oldSize;
|
||||
while (position > offset) {
|
||||
size_t readSize = (position >= (offset + buffer.size())) ? buffer.size() : (position - offset);
|
||||
const auto readSize = std::min<size_t>(position - offset, buffer.size());
|
||||
|
||||
position -= readSize;
|
||||
|
||||
@@ -135,6 +135,28 @@ namespace hex::plugin::builtin::prv {
|
||||
Provider::insert(offset, size);
|
||||
}
|
||||
|
||||
void FileProvider::remove(u64 offset, size_t size) {
|
||||
auto oldSize = this->getActualSize();
|
||||
this->resize(oldSize + size);
|
||||
|
||||
std::vector<u8> buffer(0x1000);
|
||||
|
||||
const auto newSize = oldSize - size;
|
||||
auto position = offset;
|
||||
while (position < newSize) {
|
||||
const auto readSize = std::min<size_t>(newSize - position, buffer.size());
|
||||
|
||||
this->readRaw(position + size, buffer.data(), readSize);
|
||||
this->writeRaw(position, buffer.data(), readSize);
|
||||
|
||||
position += readSize;
|
||||
}
|
||||
|
||||
this->resize(newSize);
|
||||
|
||||
Provider::insert(offset, size);
|
||||
}
|
||||
|
||||
size_t FileProvider::getRealTimeSize() {
|
||||
#if defined(OS_LINUX)
|
||||
if (struct stat newStats; (this->m_fileStatsValid = fstat(this->m_file, &newStats) == 0)) {
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
|
||||
#include <hex/api/localization.hpp>
|
||||
|
||||
#include <hex/helpers/net.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <hex/ui/imgui_imhex_extensions.h>
|
||||
#include <fonts/codicons_font.h>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
@@ -52,6 +55,11 @@ namespace hex::plugin::builtin {
|
||||
|
||||
if (ImGui::Combo(name.data(), &selection, themes, IM_ARRAYSIZE(themes))) {
|
||||
setting = selection;
|
||||
|
||||
ImHexApi::System::enableSystemThemeDetection(selection == 0);
|
||||
if (selection != 0)
|
||||
ImHexApi::System::setTheme(static_cast<ImHexApi::System::Theme>(selection));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -306,17 +314,34 @@ namespace hex::plugin::builtin {
|
||||
ContentRegistry::Settings::add(dirsSetting, dirsSetting, std::vector<std::string> {}, [](auto name, nlohmann::json &setting) {
|
||||
hex::unused(name);
|
||||
|
||||
static std::vector<std::string> folders = setting;
|
||||
static size_t currentItemIndex = 0;
|
||||
static size_t currentItemIndex = 0;
|
||||
static std::vector<std::fs::path> folders = [&setting]{
|
||||
std::vector<std::fs::path> result;
|
||||
|
||||
std::vector<std::u8string> paths = setting;
|
||||
for (const auto &path : paths)
|
||||
result.emplace_back(path);
|
||||
|
||||
return result;
|
||||
}();
|
||||
|
||||
bool result = false;
|
||||
|
||||
auto writeSetting = [&setting]{
|
||||
std::vector<std::u8string> folderStrings;
|
||||
for (const auto &folder : folders)
|
||||
folderStrings.push_back(folder.u8string());
|
||||
setting = folderStrings;
|
||||
|
||||
ImHexApi::System::setAdditionalFolderPaths(folders);
|
||||
};
|
||||
|
||||
if (!ImGui::BeginListBox("", ImVec2(-38, -FLT_MIN))) {
|
||||
return false;
|
||||
} else {
|
||||
for (size_t n = 0; n < folders.size(); n++) {
|
||||
const bool isSelected = (currentItemIndex == n);
|
||||
if (ImGui::Selectable(folders.at(n).c_str(), isSelected)) { currentItemIndex = n; }
|
||||
if (ImGui::Selectable(folders.at(n).string().c_str(), isSelected)) { currentItemIndex = n; }
|
||||
if (isSelected) { ImGui::SetItemDefaultFocus(); }
|
||||
}
|
||||
ImGui::EndListBox();
|
||||
@@ -326,11 +351,12 @@ namespace hex::plugin::builtin {
|
||||
|
||||
if (ImGui::IconButton(ICON_VS_NEW_FOLDER, ImGui::GetCustomColorVec4(ImGuiCustomCol_DescButton), ImVec2(30, 30))) {
|
||||
fs::openFileBrowser(fs::DialogMode::Folder, {}, [&](const std::fs::path &path) {
|
||||
auto pathStr = path.string();
|
||||
|
||||
if (std::find(folders.begin(), folders.end(), pathStr) == folders.end()) {
|
||||
folders.emplace_back(pathStr);
|
||||
ContentRegistry::Settings::write(dirsSetting, dirsSetting, folders);
|
||||
if (std::find(folders.begin(), folders.end(), path) == folders.end()) {
|
||||
folders.emplace_back(path);
|
||||
|
||||
writeSetting();
|
||||
|
||||
result = true;
|
||||
}
|
||||
});
|
||||
@@ -340,7 +366,9 @@ namespace hex::plugin::builtin {
|
||||
if (ImGui::IconButton(ICON_VS_REMOVE_CLOSE, ImGui::GetCustomColorVec4(ImGuiCustomCol_DescButton), ImVec2(30, 30))) {
|
||||
if (!folders.empty()) {
|
||||
folders.erase(std::next(folders.begin(), currentItemIndex));
|
||||
ContentRegistry::Settings::write(dirsSetting, dirsSetting, folders);
|
||||
|
||||
writeSetting();
|
||||
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
@@ -350,6 +378,112 @@ namespace hex::plugin::builtin {
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
/* Proxy */
|
||||
|
||||
static const std::string proxySetting { "hex.builtin.setting.proxy" };
|
||||
|
||||
// init hex::Net proxy url
|
||||
hex::Net::setProxy(ContentRegistry::Settings::read(proxySetting, "hex.builtin.setting.proxy.url", ""));
|
||||
|
||||
ContentRegistry::Settings::addCategoryDescription(proxySetting, "hex.builtin.setting.proxy.description");
|
||||
|
||||
ContentRegistry::Settings::add(
|
||||
proxySetting, "hex.builtin.setting.proxy.url", "", [](auto name, nlohmann::json &setting) {
|
||||
static std::string proxyUrl = static_cast<std::string>(setting);
|
||||
static bool enableProxy = !proxyUrl.empty();
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (ImGui::Checkbox("hex.builtin.setting.proxy.enable"_lang, &enableProxy)) {
|
||||
setting = enableProxy ? proxyUrl : "";
|
||||
hex::Net::setProxy(enableProxy ? proxyUrl : "");
|
||||
result = true;
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(!enableProxy);
|
||||
if (ImGui::InputText("##proxy_url", proxyUrl)) {
|
||||
setting = proxyUrl;
|
||||
hex::Net::setProxy(proxyUrl);
|
||||
result = true;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::InfoTooltip("hex.builtin.setting.proxy.url.tooltip"_lang);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::TextFormatted("{}", name);
|
||||
return result;
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
||||
|
||||
static void loadInterfaceScalingSetting() {
|
||||
float interfaceScaling = 1.0F;
|
||||
switch (ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.scaling", 0)) {
|
||||
default:
|
||||
case 0:
|
||||
// Native scaling
|
||||
break;
|
||||
case 1:
|
||||
interfaceScaling = 0.5F;
|
||||
break;
|
||||
case 2:
|
||||
interfaceScaling = 1.0F;
|
||||
break;
|
||||
case 3:
|
||||
interfaceScaling = 1.5F;
|
||||
break;
|
||||
case 4:
|
||||
interfaceScaling = 2.0F;
|
||||
break;
|
||||
}
|
||||
|
||||
ImHexApi::System::impl::setGlobalScale(interfaceScaling);
|
||||
}
|
||||
|
||||
static void loadFontSettings() {
|
||||
std::fs::path fontFile = ContentRegistry::Settings::read("hex.builtin.setting.font", "hex.builtin.setting.font.font_path", "");
|
||||
if (!fs::exists(fontFile))
|
||||
fontFile.clear();
|
||||
|
||||
// If no custom font has been specified, search for a file called "font.ttf" in one of the resource folders
|
||||
if (fontFile.empty()) {
|
||||
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Resources)) {
|
||||
auto path = dir / "font.ttf";
|
||||
if (fs::exists(path)) {
|
||||
log::info("Loading custom front from {}", path.string());
|
||||
|
||||
fontFile = path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If a custom font has been loaded now, also load the font size
|
||||
float fontSize = 13.0F * ImHexApi::System::getGlobalScale();
|
||||
if (!fontFile.empty()) {
|
||||
ImHexApi::System::impl::setCustomFontPath(fontFile);
|
||||
|
||||
fontSize = ContentRegistry::Settings::read("hex.builtin.setting.font", "hex.builtin.setting.font.font_size", 13) * ImHexApi::System::getGlobalScale();
|
||||
}
|
||||
|
||||
ImHexApi::System::impl::setFontSize(fontSize);
|
||||
}
|
||||
|
||||
static void loadThemeSettings() {
|
||||
auto theme = ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.color", static_cast<i64>(ImHexApi::System::Theme::Dark));
|
||||
|
||||
ImHexApi::System::enableSystemThemeDetection(theme == 0);
|
||||
ImHexApi::System::setTheme(static_cast<ImHexApi::System::Theme>(theme));
|
||||
}
|
||||
|
||||
void loadSettings() {
|
||||
loadInterfaceScalingSetting();
|
||||
loadFontSettings();
|
||||
loadThemeSettings();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,21 +1,25 @@
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/localization.hpp>
|
||||
|
||||
#include <hex/ui/view.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/api/localization.hpp>
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
#include <codicons_font.h>
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <hex/ui/imgui_imhex_extensions.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
static std::string s_popupMessage;
|
||||
static std::function<void()> s_yesCallback, s_noCallback;
|
||||
static u32 s_selectableFileIndex;
|
||||
static std::vector<std::fs::path> s_selectableFiles;
|
||||
static std::function<void(std::fs::path)> s_selectableFileOpenCallback;
|
||||
static std::vector<nfdfilteritem_t> s_selectableFilesValidExtensions;
|
||||
|
||||
static void drawGlobalPopups() {
|
||||
|
||||
// "Are you sure you want to exit?" Popup
|
||||
@@ -32,10 +36,141 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
auto windowSize = ImHexApi::System::getMainWindowSize();
|
||||
|
||||
// Info popup
|
||||
ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300)));
|
||||
if (ImGui::BeginPopupModal("hex.builtin.common.info"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::TextFormattedWrapped("{}", s_popupMessage.c_str());
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("hex.builtin.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape))
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
||||
ImGui::SetWindowPos((windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing);
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// Error popup
|
||||
ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300)));
|
||||
if (ImGui::BeginPopupModal("hex.builtin.common.error"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::TextFormattedWrapped("{}", s_popupMessage.c_str());
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("hex.builtin.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape))
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
||||
ImGui::SetWindowPos((windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing);
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// Fatal error popup
|
||||
ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300)));
|
||||
if (ImGui::BeginPopupModal("hex.builtin.common.fatal"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::TextFormattedWrapped("{}", s_popupMessage.c_str());
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("hex.builtin.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape)) {
|
||||
ImHexApi::Common::closeImHex();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::SetWindowPos((windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing);
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// Yes/No question popup
|
||||
ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300)));
|
||||
if (ImGui::BeginPopupModal("hex.builtin.common.question"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::TextFormattedWrapped("{}", s_popupMessage.c_str());
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
|
||||
View::confirmButtons(
|
||||
"hex.builtin.common.yes"_lang, "hex.builtin.common.no"_lang, [] {
|
||||
s_yesCallback();
|
||||
ImGui::CloseCurrentPopup(); }, [] {
|
||||
s_noCallback();
|
||||
ImGui::CloseCurrentPopup(); });
|
||||
|
||||
ImGui::SetWindowPos((windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing);
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// File chooser popup
|
||||
bool opened = true;
|
||||
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
|
||||
if (ImGui::BeginPopupModal("hex.builtin.common.choose_file"_lang, &opened, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
|
||||
if (ImGui::BeginListBox("##files", ImVec2(300_scaled, 0))) {
|
||||
|
||||
u32 index = 0;
|
||||
for (auto &path : s_selectableFiles) {
|
||||
if (ImGui::Selectable(path.filename().string().c_str(), index == s_selectableFileIndex))
|
||||
s_selectableFileIndex = index;
|
||||
index++;
|
||||
}
|
||||
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
|
||||
if (ImGui::Button("hex.builtin.common.open"_lang)) {
|
||||
s_selectableFileOpenCallback(s_selectableFiles[s_selectableFileIndex]);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("hex.builtin.common.browse"_lang)) {
|
||||
fs::openFileBrowser(fs::DialogMode::Open, s_selectableFilesValidExtensions, [](const auto &path) {
|
||||
s_selectableFileOpenCallback(path);
|
||||
ImGui::CloseCurrentPopup();
|
||||
});
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void addGlobalUIItems() {
|
||||
EventManager::subscribe<EventFrameEnd>(drawGlobalPopups);
|
||||
|
||||
EventManager::subscribe<RequestShowInfoPopup>([](const std::string &message) {
|
||||
s_popupMessage = message;
|
||||
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.info"_lang); });
|
||||
});
|
||||
|
||||
EventManager::subscribe<RequestShowErrorPopup>([](const std::string &message) {
|
||||
s_popupMessage = message;
|
||||
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.error"_lang); });
|
||||
});
|
||||
|
||||
EventManager::subscribe<RequestShowFatalErrorPopup>([](const std::string &message) {
|
||||
s_popupMessage = message;
|
||||
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.fatal"_lang); });
|
||||
});
|
||||
|
||||
EventManager::subscribe<RequestShowYesNoQuestionPopup>([](const std::string &message, const std::function<void()> &yesCallback, const std::function<void()> &noCallback) {
|
||||
s_popupMessage = message;
|
||||
|
||||
s_yesCallback = yesCallback;
|
||||
s_noCallback = noCallback;
|
||||
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.question"_lang); });
|
||||
});
|
||||
|
||||
EventManager::subscribe<RequestShowFileChooserPopup>([](const std::vector<std::fs::path> &paths, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback) {
|
||||
s_selectableFileIndex = 0;
|
||||
s_selectableFiles = paths;
|
||||
s_selectableFilesValidExtensions = validExtensions;
|
||||
s_selectableFileOpenCallback = callback;
|
||||
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.choose_file"_lang); });
|
||||
});
|
||||
}
|
||||
|
||||
void addFooterItems() {
|
||||
@@ -182,4 +317,17 @@ namespace hex::plugin::builtin {
|
||||
|
||||
}
|
||||
|
||||
void handleBorderlessWindowMode() {
|
||||
// Intel's OpenGL driver has weird bugs that cause the drawn window to be offset to the bottom right.
|
||||
// This can be fixed by either using Mesa3D's OpenGL Software renderer or by simply disabling it.
|
||||
// If you want to try if it works anyways on your GPU, set the hex.builtin.setting.interface.force_borderless_window_mode setting to 1
|
||||
if (ImHexApi::System::isBorderlessWindowModeEnabled()) {
|
||||
bool isIntelGPU = hex::containsIgnoreCase(ImHexApi::System::getGPUVendor(), "Intel");
|
||||
ImHexApi::System::impl::setBorderlessWindowMode(!isIntelGPU);
|
||||
|
||||
if (isIntelGPU)
|
||||
log::warn("Intel GPU detected! Intel's OpenGL driver has bugs that can cause issues when using ImHex. If you experience any rendering bugs, please try the Mesa3D Software Renderer");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -55,7 +55,7 @@ namespace hex::plugin::builtin {
|
||||
this->m_logoTexture = ImGui::LoadImageFromMemory(reinterpret_cast<const ImU8 *>(logo.data()), logo.size());
|
||||
}
|
||||
|
||||
ImGui::Image(this->m_logoTexture.textureId, scaled(this->m_logoTexture.size()));
|
||||
ImGui::Image(this->m_logoTexture.textureId, scaled({ 64, 64 }));
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::TextFormatted("ImHex Hex Editor v{} by WerWolv - " ICON_FA_CODE_BRANCH, IMHEX_VERSION);
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGui::BeginTooltip();
|
||||
|
||||
if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) {
|
||||
if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, u32(hoverColor));
|
||||
|
||||
bool open = true;
|
||||
if (ImGui::CollapsingHeader(name.c_str(), &open)) {
|
||||
if (ImGui::CollapsingHeader(hex::format("{}###bookmark", name).c_str(), &open)) {
|
||||
ImGui::TextUnformatted("hex.builtin.view.bookmarks.title.info"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::TextFormatted("hex.builtin.view.bookmarks.address"_lang, region.address, region.address + region.size - 1, region.size);
|
||||
|
||||
@@ -28,15 +28,24 @@ namespace hex::plugin::builtin {
|
||||
if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape)))
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
||||
ImGui::PushItemWidth(-1);
|
||||
if (ImGui::InputText(
|
||||
"##command_input", this->m_commandBuffer.data(), this->m_commandBuffer.size(), ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_EnterReturnsTrue, [](ImGuiInputTextCallbackData *callbackData) -> int {
|
||||
auto _this = static_cast<ViewCommandPalette *>(callbackData->UserData);
|
||||
_this->m_lastResults = _this->getCommandResults(callbackData->Buf);
|
||||
if (this->m_focusInputTextBox) {
|
||||
auto textState = ImGui::GetInputTextState(ImGui::GetID("##command_input"));
|
||||
if (textState != nullptr) {
|
||||
textState->Stb.cursor = strlen(this->m_commandBuffer.data());
|
||||
}
|
||||
|
||||
return 0;
|
||||
},
|
||||
this)) {
|
||||
ImGui::SetKeyboardFocusHere(0);
|
||||
this->m_focusInputTextBox = false;
|
||||
}
|
||||
|
||||
ImGui::PushItemWidth(-1);
|
||||
if (ImGui::InputText("##command_input", this->m_commandBuffer.data(), this->m_commandBuffer.size(), ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_EnterReturnsTrue,
|
||||
[](ImGuiInputTextCallbackData *callbackData) -> int {
|
||||
auto _this = static_cast<ViewCommandPalette *>(callbackData->UserData);
|
||||
_this->m_lastResults = _this->getCommandResults(callbackData->Buf);
|
||||
|
||||
return 0;
|
||||
}, this)) {
|
||||
if (!this->m_lastResults.empty()) {
|
||||
auto &[displayResult, matchedCommand, callback] = this->m_lastResults.front();
|
||||
callback(matchedCommand);
|
||||
@@ -52,16 +61,6 @@ namespace hex::plugin::builtin {
|
||||
this->m_justOpened = false;
|
||||
}
|
||||
|
||||
if (this->m_focusInputTextBox) {
|
||||
auto textState = ImGui::GetInputTextState(ImGui::GetID("##command_input"));
|
||||
if (textState != nullptr) {
|
||||
textState->Stb.cursor = strlen(this->m_commandBuffer.data());
|
||||
}
|
||||
|
||||
ImGui::SetKeyboardFocusHere(0);
|
||||
this->m_focusInputTextBox = false;
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
for (const auto &[displayResult, matchedCommand, callback] : this->m_lastResults) {
|
||||
|
||||
@@ -1,294 +1,180 @@
|
||||
#include "content/views/view_hashes.hpp"
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/helpers/crypto.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewHashes::ViewHashes() : View("hex.builtin.view.hashes.name") {
|
||||
EventManager::subscribe<EventDataChanged>(this, [this]() {
|
||||
this->m_shouldInvalidate = true;
|
||||
EventManager::subscribe<EventRegionSelected>(this, [this](const Region &) {
|
||||
for (auto &function : this->m_hashFunctions)
|
||||
function.reset();
|
||||
});
|
||||
|
||||
EventManager::subscribe<EventRegionSelected>(this, [this](Region region) {
|
||||
if (this->m_shouldMatchSelection) {
|
||||
if (region.address == size_t(-1)) {
|
||||
this->m_hashRegion[0] = this->m_hashRegion[1] = 0;
|
||||
} else {
|
||||
this->m_hashRegion[0] = region.address;
|
||||
this->m_hashRegion[1] = region.size;
|
||||
ImHexApi::HexEditor::addTooltipProvider([this](u64 address, const u8 *data, size_t size) {
|
||||
hex::unused(data);
|
||||
|
||||
auto selection = ImHexApi::HexEditor::getSelection();
|
||||
|
||||
if (ImGui::GetIO().KeyShift) {
|
||||
if (!this->m_hashFunctions.empty() && selection.has_value() && selection->overlaps(Region { address, size })) {
|
||||
ImGui::BeginTooltip();
|
||||
|
||||
if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.name"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Indent();
|
||||
if (ImGui::BeginTable("##hashes_tooltip", 3, ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit)) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
for (auto &function : this->m_hashFunctions) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextFormatted("{}", function.getName());
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextFormatted(" ");
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (provider != nullptr)
|
||||
ImGui::TextFormatted("{}", crypt::encode16(function.get(*selection, provider)));
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::Unindent();
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
this->m_shouldInvalidate = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ViewHashes::~ViewHashes() {
|
||||
EventManager::unsubscribe<EventDataChanged>(this);
|
||||
EventManager::unsubscribe<EventRegionSelected>(this);
|
||||
}
|
||||
|
||||
|
||||
template<size_t Size>
|
||||
static void formatBigHexInt(std::array<u8, Size> dataArray, char *buffer, size_t bufferSize) {
|
||||
for (size_t i = 0; i < dataArray.size(); i++)
|
||||
snprintf(buffer + 2 * i, bufferSize - 2 * i, "%02X", dataArray[i]);
|
||||
}
|
||||
|
||||
void ViewHashes::drawContent() {
|
||||
const auto &hashes = ContentRegistry::Hashes::impl::getHashes();
|
||||
|
||||
if (this->m_selectedHash == nullptr && !hashes.empty()) {
|
||||
this->m_selectedHash = hashes.front();
|
||||
}
|
||||
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.hashes.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
if (ImGui::BeginChild("##scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav)) {
|
||||
if (ImGui::BeginCombo("hex.builtin.view.hashes.function"_lang, this->m_selectedHash != nullptr ? LangEntry(this->m_selectedHash->getUnlocalizedName()) : "")) {
|
||||
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
if (ImHexApi::Provider::isValid() && provider->isAvailable()) {
|
||||
|
||||
ImGui::TextUnformatted("hex.builtin.common.region"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::InputScalarN("##nolabel", ImGuiDataType_U64, this->m_hashRegion, 2, nullptr, nullptr, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::Checkbox("hex.builtin.common.match_selection"_lang, &this->m_shouldMatchSelection);
|
||||
if (ImGui::IsItemEdited()) {
|
||||
// Force execution of Region Selection Event
|
||||
ImHexApi::HexEditor::setSelection(0, 0);
|
||||
this->m_shouldInvalidate = true;
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.settings"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::BeginCombo("hex.builtin.view.hashes.function"_lang, hashFunctionNames[this->m_currHashFunction].second, 0)) {
|
||||
for (size_t i = 0; i < hashFunctionNames.size(); i++) {
|
||||
bool is_selected = (static_cast<size_t>(this->m_currHashFunction) == i);
|
||||
if (ImGui::Selectable(hashFunctionNames[i].second, is_selected))
|
||||
this->m_currHashFunction = i;
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus(); // Set the initial focus when opening the combo (scrolling + for keyboard navigation support in the upcoming navigation branch)
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
this->m_shouldInvalidate = true;
|
||||
}
|
||||
|
||||
size_t dataSize = provider->getSize();
|
||||
if (this->m_hashRegion[1] >= provider->getBaseAddress() + dataSize)
|
||||
this->m_hashRegion[1] = provider->getBaseAddress() + dataSize;
|
||||
|
||||
|
||||
switch (hashFunctionNames[this->m_currHashFunction].first) {
|
||||
case HashFunctions::Crc8:
|
||||
{
|
||||
static int polynomial = 0x07, init = 0x0000, xorout = 0x0000;
|
||||
static bool reflectIn = false, reflectOut = false;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.iv"_lang, &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.xorout"_lang, &xorout, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::Checkbox("hex.builtin.common.reflectIn"_lang, &reflectIn);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::Checkbox("hex.builtin.common.reflectOut"_lang, &reflectOut);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.poly"_lang, &polynomial, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
static u8 result = 0;
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::crc8(provider, this->m_hashRegion[0], this->m_hashRegion[1], polynomial, init, xorout, reflectIn, reflectOut);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%02X", result);
|
||||
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
case HashFunctions::Crc16:
|
||||
{
|
||||
static int polynomial = 0x8005, init = 0x0000, xorout = 0x0000;
|
||||
static bool reflectIn = false, reflectOut = false;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.iv"_lang, &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.xorout"_lang, &xorout, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::Checkbox("hex.builtin.common.reflectIn"_lang, &reflectIn);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::Checkbox("hex.builtin.common.reflectOut"_lang, &reflectOut);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.poly"_lang, &polynomial, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
static u16 result = 0;
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::crc16(provider, this->m_hashRegion[0], this->m_hashRegion[1], polynomial, init, xorout, reflectIn, reflectOut);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%04X", result);
|
||||
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
case HashFunctions::Crc32:
|
||||
{
|
||||
static int polynomial = 0x04C11DB7, init = 0xFFFFFFFF, xorout = 0xFFFFFFFF;
|
||||
static bool reflectIn = true, reflectOut = true;
|
||||
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.iv"_lang, &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.xorout"_lang, &xorout, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::Checkbox("hex.builtin.common.reflectIn"_lang, &reflectIn);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::Checkbox("hex.builtin.common.reflectOut"_lang, &reflectOut);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.poly"_lang, &polynomial, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
static u32 result = 0;
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::crc32(provider, this->m_hashRegion[0], this->m_hashRegion[1], polynomial, init, xorout, reflectIn, reflectOut);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%08X", result);
|
||||
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
case HashFunctions::Md5:
|
||||
{
|
||||
static std::array<u8, 16> result = { 0 };
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::md5(provider, this->m_hashRegion[0], this->m_hashRegion[1]);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
formatBigHexInt(result, buffer, sizeof(buffer));
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
case HashFunctions::Sha1:
|
||||
{
|
||||
static std::array<u8, 20> result = { 0 };
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::sha1(provider, this->m_hashRegion[0], this->m_hashRegion[1]);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
formatBigHexInt(result, buffer, sizeof(buffer));
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
case HashFunctions::Sha224:
|
||||
{
|
||||
static std::array<u8, 28> result = { 0 };
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::sha224(provider, this->m_hashRegion[0], this->m_hashRegion[1]);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
formatBigHexInt(result, buffer, sizeof(buffer));
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
case HashFunctions::Sha256:
|
||||
{
|
||||
static std::array<u8, 32> result;
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::sha256(provider, this->m_hashRegion[0], this->m_hashRegion[1]);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
formatBigHexInt(result, buffer, sizeof(buffer));
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
case HashFunctions::Sha384:
|
||||
{
|
||||
static std::array<u8, 48> result;
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::sha384(provider, this->m_hashRegion[0], this->m_hashRegion[1]);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
formatBigHexInt(result, buffer, sizeof(buffer));
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
case HashFunctions::Sha512:
|
||||
{
|
||||
static std::array<u8, 64> result;
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::sha512(provider, this->m_hashRegion[0], this->m_hashRegion[1]);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
formatBigHexInt(result, buffer, sizeof(buffer));
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
for (const auto hash : hashes) {
|
||||
if (ImGui::Selectable(LangEntry(hash->getUnlocalizedName()), this->m_selectedHash == hash)) {
|
||||
this->m_selectedHash = hash;
|
||||
this->m_newHashName.clear();
|
||||
}
|
||||
}
|
||||
|
||||
this->m_shouldInvalidate = false;
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (this->m_newHashName.empty() && this->m_selectedHash != nullptr)
|
||||
this->m_newHashName = hex::format("{} {}", LangEntry(this->m_selectedHash->getUnlocalizedName()), static_cast<const char *>("hex.builtin.view.hashes.hash"_lang));
|
||||
|
||||
if (ImGui::BeginChild("##settings", ImVec2(ImGui::GetContentRegionAvailWidth(), 200_scaled), true)) {
|
||||
if (this->m_selectedHash != nullptr) {
|
||||
auto startPos = ImGui::GetCursorPosY();
|
||||
this->m_selectedHash->draw();
|
||||
|
||||
// Check if no elements have been added
|
||||
if (startPos == ImGui::GetCursorPosY()) {
|
||||
ImGui::TextFormattedCentered("hex.builtin.view.hashes.no_settings"_lang);
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::InputText("##Name", this->m_newHashName);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginDisabled(this->m_newHashName.empty() || this->m_selectedHash == nullptr);
|
||||
if (ImGui::IconButton(ICON_VS_ADD, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||
if (this->m_selectedHash != nullptr)
|
||||
this->m_hashFunctions.push_back(this->m_selectedHash->create(this->m_newHashName));
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (ImGui::BeginTable("##hashes", 3, ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Borders, ImVec2(ImGui::GetContentRegionAvailWidth(), ImGui::GetTextLineHeightWithSpacing() * 10))) {
|
||||
ImGui::TableSetupColumn("hex.builtin.view.hashes.name"_lang);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.hashes.type"_lang);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.hashes.result"_lang, ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
auto selection = ImHexApi::HexEditor::getSelection();
|
||||
|
||||
std::optional<u32> indexToRemove;
|
||||
for (u32 i = 0; i < this->m_hashFunctions.size(); i++) {
|
||||
auto &function = this->m_hashFunctions[i];
|
||||
|
||||
ImGui::PushID(i);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Header, 0x00);
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderActive, 0x00);
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, 0x00);
|
||||
ImGui::Selectable(function.getName().c_str(), false);
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
{
|
||||
const auto ContextMenuId = hex::format("Context Menu {}", i);
|
||||
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Right))
|
||||
ImGui::OpenPopup(ContextMenuId.c_str());
|
||||
|
||||
if (ImGui::BeginPopup(ContextMenuId.c_str())) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hashes.remove"_lang))
|
||||
indexToRemove = i;
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextFormatted("{}", LangEntry(function.getType()->getUnlocalizedName()));
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
std::string result;
|
||||
if (provider != nullptr && selection.has_value())
|
||||
result = crypt::encode16(function.get(*selection, provider));
|
||||
else
|
||||
result = "???";
|
||||
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth());
|
||||
ImGui::InputText("##result", result, ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
if (indexToRemove.has_value()) {
|
||||
this->m_hashFunctions.erase(this->m_hashFunctions.begin() + indexToRemove.value());
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextWrapped("%s", static_cast<const char *>("hex.builtin.view.hashes.hover_info"_lang));
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
@@ -199,11 +199,7 @@ namespace hex::plugin::builtin {
|
||||
reader.seek(this->m_searchPosition.value_or(editor->getSelection().getEndAddress()));
|
||||
|
||||
constexpr static auto searchFunction = [](const auto &haystackBegin, const auto &haystackEnd, const auto &needleBegin, const auto &needleEnd) {
|
||||
#if defined(OS_MACOS)
|
||||
return std::search(haystackBegin, haystackEnd, needleBegin, needleEnd);
|
||||
#else
|
||||
return std::search(haystackBegin, haystackEnd, std::boyer_moore_horspool_searcher(needleBegin, needleEnd));
|
||||
#endif
|
||||
return std::search(haystackBegin, haystackEnd, std::boyer_moore_horspool_searcher(needleBegin, needleEnd));
|
||||
};
|
||||
|
||||
if (!backwards) {
|
||||
@@ -275,9 +271,7 @@ namespace hex::plugin::builtin {
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
ImGui::TextUnformatted("hex.builtin.view.hex_editor.menu.edit.resize"_lang);
|
||||
|
||||
if (ImGui::InputHexadecimal("##resize", &this->m_size, ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
resize(static_cast<size_t>(this->m_size));
|
||||
}
|
||||
ImGui::InputHexadecimal("##resize", &this->m_size);
|
||||
|
||||
View::confirmButtons("hex.builtin.common.set"_lang, "hex.builtin.common.cancel"_lang,
|
||||
[&, this]{
|
||||
@@ -306,12 +300,8 @@ namespace hex::plugin::builtin {
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
ImGui::TextUnformatted("hex.builtin.view.hex_editor.menu.edit.insert"_lang);
|
||||
|
||||
if (ImGui::InputHexadecimal("hex.common.address"_lang, &this->m_address, ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
insert(this->m_address, static_cast<size_t>(this->m_size));
|
||||
}
|
||||
if (ImGui::InputHexadecimal("hex.common.size"_lang, &this->m_size, ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
insert(this->m_address, static_cast<size_t>(this->m_size));
|
||||
}
|
||||
ImGui::InputHexadecimal("hex.builtin.common.address"_lang, &this->m_address);
|
||||
ImGui::InputHexadecimal("hex.builtin.common.size"_lang, &this->m_size);
|
||||
|
||||
View::confirmButtons("hex.builtin.common.set"_lang, "hex.builtin.common.cancel"_lang,
|
||||
[&, this]{
|
||||
@@ -334,6 +324,37 @@ namespace hex::plugin::builtin {
|
||||
u64 m_size;
|
||||
};
|
||||
|
||||
class PopupRemove : public ViewHexEditor::Popup {
|
||||
public:
|
||||
PopupRemove(u64 address, size_t size) : m_address(address), m_size(size) {}
|
||||
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
ImGui::TextUnformatted("hex.builtin.view.hex_editor.menu.edit.remove"_lang);
|
||||
|
||||
ImGui::InputHexadecimal("hex.builtin.common.address"_lang, &this->m_address);
|
||||
ImGui::InputHexadecimal("hex.builtin.common.size"_lang, &this->m_size);
|
||||
|
||||
View::confirmButtons("hex.builtin.common.set"_lang, "hex.builtin.common.cancel"_lang,
|
||||
[&, this]{
|
||||
remove(this->m_address, static_cast<size_t>(this->m_size));
|
||||
editor->closePopup();
|
||||
},
|
||||
[&]{
|
||||
editor->closePopup();
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
static void remove(u64 address, size_t size) {
|
||||
if (ImHexApi::Provider::isValid())
|
||||
ImHexApi::Provider::get()->remove(address, size);
|
||||
}
|
||||
|
||||
private:
|
||||
u64 m_address;
|
||||
u64 m_size;
|
||||
};
|
||||
|
||||
ViewHexEditor::ViewHexEditor() : View("hex.builtin.view.hex_editor.name") {
|
||||
this->m_currDataVisualizer = ContentRegistry::HexEditor::impl::getVisualizers()["hex.builtin.visualizer.hexadecimal.8bit"];
|
||||
|
||||
@@ -427,6 +448,10 @@ namespace hex::plugin::builtin {
|
||||
return { std::string(decoded), advance, color };
|
||||
}
|
||||
|
||||
static auto getCellPosition() {
|
||||
return ImGui::GetCursorScreenPos() - ImGui::GetStyle().CellPadding;
|
||||
}
|
||||
|
||||
static void drawTooltip(u64 address, const u8 *data, size_t size) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, scaled(ImVec2(5, 5)));
|
||||
|
||||
@@ -439,7 +464,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::BeginTooltip();
|
||||
|
||||
for (const auto &[id, tooltip] : tooltips) {
|
||||
if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) {
|
||||
if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
@@ -465,6 +490,13 @@ namespace hex::plugin::builtin {
|
||||
void ViewHexEditor::drawCell(u64 address, u8 *data, size_t size, bool hovered) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
if (this->m_shouldUpdateEditingValue) {
|
||||
this->m_shouldUpdateEditingValue = false;
|
||||
|
||||
this->m_editingBytes.resize(size);
|
||||
std::memcpy(this->m_editingBytes.data(), data, size);
|
||||
}
|
||||
|
||||
if (this->m_editingAddress != address) {
|
||||
this->m_currDataVisualizer->draw(address, data, size, this->m_upperCaseHex);
|
||||
|
||||
@@ -484,8 +516,9 @@ namespace hex::plugin::builtin {
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
ImGui::CaptureKeyboardFromApp(true);
|
||||
|
||||
if (this->m_currDataVisualizer->drawEditing(address, this->m_editingBytes.data(), this->m_editingBytes.size(), this->m_upperCaseHex, this->m_enteredEditingMode) || this->m_shouldModifyValue) {
|
||||
provider->write(address, this->m_editingBytes.data(), this->m_editingBytes.size());
|
||||
if (this->m_currDataVisualizer->drawEditing(*this->m_editingAddress, this->m_editingBytes.data(), this->m_editingBytes.size(), this->m_upperCaseHex, this->m_enteredEditingMode) || this->m_shouldModifyValue) {
|
||||
|
||||
provider->write(*this->m_editingAddress, this->m_editingBytes.data(), this->m_editingBytes.size());
|
||||
|
||||
if (!this->m_selectionChanged && !ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
|
||||
auto nextEditingAddress = *this->m_editingAddress + this->m_currDataVisualizer->getBytesPerCell();
|
||||
@@ -500,6 +533,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
this->m_shouldModifyValue = false;
|
||||
this->m_shouldUpdateEditingValue = true;
|
||||
}
|
||||
|
||||
this->m_enteredEditingMode = false;
|
||||
@@ -653,24 +687,29 @@ namespace hex::plugin::builtin {
|
||||
const auto cellBytes = std::min<u64>(validBytes, bytesPerCell);
|
||||
|
||||
// Query cell colors
|
||||
const auto foregroundColor = queryForegroundColor(byteAddress, &bytes[x], cellBytes);
|
||||
const auto backgroundColor = [&]{
|
||||
auto color = queryBackgroundColor(byteAddress, &bytes[x], cellBytes);
|
||||
if (x < validBytes) {
|
||||
const auto foregroundColor = queryForegroundColor(byteAddress, &bytes[x], cellBytes);
|
||||
const auto backgroundColor = [&]{
|
||||
auto color = queryBackgroundColor(byteAddress, &bytes[x], cellBytes);
|
||||
|
||||
if ((byteAddress >= selectionMin && byteAddress <= selectionMax)) {
|
||||
if (color.has_value())
|
||||
color = (ImAlphaBlendColors(color.value(), this->m_selectionColor)) & 0x00FFFFFF;
|
||||
else
|
||||
color = this->m_selectionColor;
|
||||
}
|
||||
|
||||
if ((byteAddress >= selectionMin && byteAddress <= selectionMax)) {
|
||||
if (color.has_value())
|
||||
color = ((ImAlphaBlendColors(color.value(), this->m_selectionColor)) & 0x00FFFFFF) | (this->m_selectionColor & 0xFF000000);
|
||||
else
|
||||
color = this->m_selectionColor;
|
||||
}
|
||||
color = *color | (this->m_selectionColor & 0xFF000000);
|
||||
|
||||
return color;
|
||||
}();
|
||||
return color;
|
||||
}();
|
||||
|
||||
cellColors.emplace_back(
|
||||
foregroundColor,
|
||||
backgroundColor
|
||||
);
|
||||
cellColors.emplace_back(
|
||||
foregroundColor,
|
||||
backgroundColor
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -685,7 +724,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (x < validBytes) {
|
||||
auto cellStartPos = (ImGui::GetWindowPos() + ImGui::GetCursorPos()) - ImGui::GetStyle().CellPadding - ImVec2(ImGui::GetScrollX(), ImGui::GetScrollY());
|
||||
auto cellStartPos = getCellPosition();
|
||||
auto cellSize = (CharacterSize * ImVec2(this->m_currDataVisualizer->getMaxCharsPerCell(), 1) + (ImVec2(3, 2) * ImGui::GetStyle().CellPadding) - ImVec2(1, 0) * ImGui::GetStyle().CellPadding) + ImVec2(1, 0);
|
||||
|
||||
auto [foregroundColor, backgroundColor] = cellColors[x];
|
||||
@@ -707,7 +746,7 @@ namespace hex::plugin::builtin {
|
||||
this->drawSelectionFrame(x, y, byteAddress, bytesPerCell, cellStartPos, cellSize);
|
||||
}
|
||||
|
||||
const bool cellHovered = ImGui::IsMouseHoveringRect(cellStartPos, cellStartPos + cellSize, false);
|
||||
const bool cellHovered = ImGui::IsMouseHoveringRect(cellStartPos, cellStartPos + cellSize, true);
|
||||
|
||||
this->handleSelection(byteAddress, bytesPerCell, &bytes[x], cellHovered);
|
||||
|
||||
@@ -742,26 +781,26 @@ namespace hex::plugin::builtin {
|
||||
|
||||
const u64 byteAddress = y * this->m_bytesPerRow + x + provider->getBaseAddress() + provider->getCurrentPageAddress();
|
||||
|
||||
const auto cellStartPos = (ImGui::GetWindowPos() + ImGui::GetCursorPos()) - ImGui::GetStyle().CellPadding - ImVec2(ImGui::GetScrollX(), ImGui::GetScrollY());
|
||||
const auto cellStartPos = getCellPosition();
|
||||
const auto cellSize = CharacterSize;
|
||||
|
||||
const bool cellHovered = ImGui::IsMouseHoveringRect(cellStartPos, cellStartPos + cellSize, false);
|
||||
|
||||
this->handleSelection(byteAddress, bytesPerCell, &bytes[x], cellHovered);
|
||||
|
||||
auto [foregroundColor, backgroundColor] = cellColors[x / bytesPerCell];
|
||||
|
||||
// Draw highlights and selection
|
||||
if (backgroundColor.has_value()) {
|
||||
auto drawList = ImGui::GetWindowDrawList();
|
||||
|
||||
// Draw background color
|
||||
drawList->AddRectFilled(cellStartPos, cellStartPos + cellSize, backgroundColor.value());
|
||||
|
||||
this->drawSelectionFrame(x, y, byteAddress, 1, cellStartPos, cellSize);
|
||||
}
|
||||
const bool cellHovered = ImGui::IsMouseHoveringRect(cellStartPos, cellStartPos + cellSize, true);
|
||||
|
||||
if (x < validBytes) {
|
||||
this->handleSelection(byteAddress, bytesPerCell, &bytes[x], cellHovered);
|
||||
|
||||
auto [foregroundColor, backgroundColor] = cellColors[x / bytesPerCell];
|
||||
|
||||
// Draw highlights and selection
|
||||
if (backgroundColor.has_value()) {
|
||||
auto drawList = ImGui::GetWindowDrawList();
|
||||
|
||||
// Draw background color
|
||||
drawList->AddRectFilled(cellStartPos, cellStartPos + cellSize, backgroundColor.value());
|
||||
|
||||
this->drawSelectionFrame(x, y, byteAddress, 1, cellStartPos, cellSize);
|
||||
}
|
||||
|
||||
if (std::isprint(bytes[x]))
|
||||
ImGui::TextFormatted("{:c}", bytes[x]);
|
||||
else
|
||||
@@ -797,25 +836,28 @@ namespace hex::plugin::builtin {
|
||||
for (const auto &[address, data] : encodingData) {
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
const auto cellStartPos = (ImGui::GetWindowPos() + ImGui::GetCursorPos()) - ImGui::GetStyle().CellPadding - ImVec2(ImGui::GetScrollX(), ImGui::GetScrollY());
|
||||
const auto cellStartPos = getCellPosition();
|
||||
const auto cellSize = CharacterSize * data.advance;
|
||||
const bool cellHovered = ImGui::IsMouseHoveringRect(cellStartPos, cellStartPos + cellSize, false);
|
||||
const bool cellHovered = ImGui::IsMouseHoveringRect(cellStartPos, cellStartPos + cellSize, true);
|
||||
|
||||
auto [foregroundColor, backgroundColor] = cellColors[address % this->m_bytesPerRow];
|
||||
const auto x = address % this->m_bytesPerRow;
|
||||
if (x < validBytes) {
|
||||
auto [foregroundColor, backgroundColor] = cellColors[x];
|
||||
|
||||
// Draw highlights and selection
|
||||
if (backgroundColor.has_value()) {
|
||||
auto drawList = ImGui::GetWindowDrawList();
|
||||
// Draw highlights and selection
|
||||
if (backgroundColor.has_value()) {
|
||||
auto drawList = ImGui::GetWindowDrawList();
|
||||
|
||||
// Draw background color
|
||||
drawList->AddRectFilled(cellStartPos, cellStartPos + cellSize, backgroundColor.value());
|
||||
// Draw background color
|
||||
drawList->AddRectFilled(cellStartPos, cellStartPos + cellSize, backgroundColor.value());
|
||||
|
||||
this->drawSelectionFrame(address % this->m_bytesPerRow, y, address, 1, cellStartPos, cellSize);
|
||||
this->drawSelectionFrame(x, y, address, 1, cellStartPos, cellSize);
|
||||
}
|
||||
|
||||
ImGui::TextFormattedColored(data.color, "{}", data.displayValue);
|
||||
|
||||
this->handleSelection(address, data.advance, &bytes[address % this->m_bytesPerRow], cellHovered);
|
||||
}
|
||||
|
||||
ImGui::TextFormattedColored(data.color, "{}", data.displayValue);
|
||||
|
||||
this->handleSelection(address, data.advance, &bytes[address % this->m_bytesPerRow], cellHovered);
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
@@ -827,8 +869,8 @@ namespace hex::plugin::builtin {
|
||||
// Scroll to the cursor if it's either at the top or bottom edge of the screen
|
||||
if (this->m_shouldScrollToSelection && (this->m_selectionEnd != InvalidSelection) && (this->m_selectionStart != InvalidSelection)) {
|
||||
// Make sure simply clicking on a byte at the edge of the screen won't cause scrolling
|
||||
if ((ImGui::IsMouseDown(ImGuiMouseButton_Left) && this->m_selectionStart != this->m_selectionEnd) || (!ImGui::IsMouseDown(ImGuiMouseButton_Left))) {
|
||||
auto fractionPerLine = 1.0 / this->m_visibleRowCount;
|
||||
if ((ImGui::IsMouseDown(ImGuiMouseButton_Left) && this->m_selectionStart != this->m_selectionEnd)) {
|
||||
auto fractionPerLine = 1.0 / (this->m_visibleRowCount + 1);
|
||||
|
||||
if (y == clipper.DisplayStart + 2) {
|
||||
if (i128(this->m_selectionEnd - provider->getBaseAddress() - provider->getCurrentPageAddress()) <= (i64(clipper.DisplayStart + 2) * this->m_bytesPerRow)) {
|
||||
@@ -845,27 +887,38 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
// If the cursor is off-screen, directly jump to the byte
|
||||
{
|
||||
const auto newSelection = this->getSelection();
|
||||
if (newSelection.getStartAddress() < u64(clipper.DisplayStart * this->m_bytesPerRow))
|
||||
if (this->m_shouldJumpWhenOffScreen) {
|
||||
this->m_shouldJumpWhenOffScreen = false;
|
||||
|
||||
const auto pageAddress = provider->getCurrentPageAddress() + provider->getBaseAddress();
|
||||
auto newSelection = this->getSelection();
|
||||
newSelection.address -= pageAddress;
|
||||
|
||||
if ((newSelection.getStartAddress()) < u64(clipper.DisplayStart * this->m_bytesPerRow))
|
||||
this->jumpToSelection();
|
||||
if (newSelection.getEndAddress() > u64(clipper.DisplayEnd * this->m_bytesPerRow))
|
||||
if ((newSelection.getEndAddress()) > u64(clipper.DisplayEnd * this->m_bytesPerRow))
|
||||
this->jumpToSelection();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle jumping to selection
|
||||
if (this->m_shouldJumpToSelection) {
|
||||
this->m_shouldJumpToSelection = false;
|
||||
|
||||
const auto pageAddress = provider->getCurrentPageAddress() + provider->getBaseAddress();
|
||||
auto newSelection = this->getSelection();
|
||||
newSelection.address -= pageAddress;
|
||||
|
||||
ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + (static_cast<long double>(newSelection.getStartAddress()) / this->m_bytesPerRow) * CharacterSize.y, 0.5);
|
||||
}
|
||||
|
||||
} else {
|
||||
ImGui::TextFormattedCentered("hex.builtin.view.hex_editor.no_bytes"_lang);
|
||||
}
|
||||
|
||||
// Handle jumping to selection
|
||||
if (this->m_shouldJumpToSelection) {
|
||||
this->m_shouldJumpToSelection = false;
|
||||
ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + (float(this->m_selectionStart) / this->m_bytesPerRow) * CharacterSize.y, 0.5);
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
@@ -914,7 +967,7 @@ namespace hex::plugin::builtin {
|
||||
auto selection = this->getSelection();
|
||||
std::string value;
|
||||
if (this->isSelectionValid())
|
||||
value = hex::format("0x{0:08X} - 0x{1:08X} ({0} - {1})", selection.getStartAddress(), selection.getEndAddress());
|
||||
value = hex::format("0x{0:08X} - 0x{1:08X} ({2})", selection.getStartAddress(), selection.getEndAddress(), hex::toByteString(selection.getSize()));
|
||||
else
|
||||
value = std::string("hex.builtin.view.hex_editor.selection.none"_lang);
|
||||
|
||||
@@ -930,8 +983,8 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1014,7 +1067,7 @@ namespace hex::plugin::builtin {
|
||||
if (clipboard.length() % 2 != 0) return;
|
||||
|
||||
// Convert hex string to bytes
|
||||
std::vector<u8> buffer = hex::decodeByteString(clipboard);
|
||||
std::vector<u8> buffer = crypt::decode16(clipboard);
|
||||
|
||||
// Write bytes
|
||||
provider->write(selection.getStartAddress() + provider->getBaseAddress() + provider->getCurrentPageAddress(), buffer.data(), std::min(selection.size, buffer.size()));
|
||||
@@ -1059,24 +1112,28 @@ namespace hex::plugin::builtin {
|
||||
auto pos = this->m_selectionEnd - this->m_bytesPerRow;
|
||||
this->setSelection(pos, pos);
|
||||
this->scrollToSelection();
|
||||
this->jumpIfOffScreen();
|
||||
}
|
||||
});
|
||||
ShortcutManager::addShortcut(this, Keys::Down, [this] {
|
||||
auto pos = this->m_selectionEnd + this->m_bytesPerRow;
|
||||
this->setSelection(pos, pos);
|
||||
this->scrollToSelection();
|
||||
this->jumpIfOffScreen();
|
||||
});
|
||||
ShortcutManager::addShortcut(this, Keys::Left, [this] {
|
||||
if (this->m_selectionEnd > 0) {
|
||||
auto pos = this->m_selectionEnd - 1;
|
||||
this->setSelection(pos, pos);
|
||||
this->scrollToSelection();
|
||||
this->jumpIfOffScreen();
|
||||
}
|
||||
});
|
||||
ShortcutManager::addShortcut(this, Keys::Right, [this] {
|
||||
auto pos = this->m_selectionEnd + 1;
|
||||
this->setSelection(pos, pos);
|
||||
this->scrollToSelection();
|
||||
this->jumpIfOffScreen();
|
||||
});
|
||||
|
||||
ShortcutManager::addShortcut(this, Keys::PageUp, [this] {
|
||||
@@ -1085,32 +1142,56 @@ namespace hex::plugin::builtin {
|
||||
auto pos = this->m_selectionEnd - visibleByteCount;
|
||||
this->setSelection(pos, pos);
|
||||
this->scrollToSelection();
|
||||
this->jumpIfOffScreen();
|
||||
}
|
||||
});
|
||||
ShortcutManager::addShortcut(this, Keys::PageDown, [this] {
|
||||
auto pos = this->m_selectionEnd + (this->m_bytesPerRow * this->m_visibleRowCount);
|
||||
this->setSelection(pos, pos);
|
||||
this->scrollToSelection();
|
||||
this->jumpIfOffScreen();
|
||||
});
|
||||
|
||||
// Move selection around
|
||||
ShortcutManager::addShortcut(this, SHIFT + Keys::Up, [this] {
|
||||
this->setSelection(this->m_selectionEnd - this->m_bytesPerRow, this->m_selectionEnd);
|
||||
this->m_selectionStart = std::max<u64>(this->m_selectionStart, this->m_bytesPerRow);
|
||||
|
||||
this->setSelection(this->m_selectionStart - this->m_bytesPerRow, this->m_selectionEnd);
|
||||
this->scrollToSelection();
|
||||
this->jumpIfOffScreen();
|
||||
});
|
||||
ShortcutManager::addShortcut(this, SHIFT + Keys::Down, [this] {
|
||||
this->setSelection(this->m_selectionEnd + this->m_bytesPerRow, this->m_selectionEnd);
|
||||
this->setSelection(this->m_selectionStart + this->m_bytesPerRow, this->m_selectionEnd);
|
||||
this->scrollToSelection();
|
||||
this->jumpIfOffScreen();
|
||||
|
||||
});
|
||||
ShortcutManager::addShortcut(this, SHIFT + Keys::Left, [this] {
|
||||
this->setSelection(this->m_selectionEnd - 1, this->m_selectionEnd);
|
||||
this->scrollToSelection();
|
||||
this->m_selectionStart = std::max<u64>(this->m_selectionStart, 1);
|
||||
|
||||
this->setSelection(this->m_selectionStart - 1, this->m_selectionEnd);
|
||||
this->scrollToSelection();
|
||||
this->jumpIfOffScreen();
|
||||
});
|
||||
ShortcutManager::addShortcut(this, SHIFT + Keys::Right, [this] {
|
||||
this->setSelection(this->m_selectionEnd + 1, this->m_selectionEnd);
|
||||
this->setSelection(this->m_selectionStart + 1, this->m_selectionEnd);
|
||||
this->scrollToSelection();
|
||||
this->jumpIfOffScreen();
|
||||
});
|
||||
ShortcutManager::addShortcut(this, Keys::PageUp, [this] {
|
||||
u64 visibleByteCount = this->m_bytesPerRow * this->m_visibleRowCount;
|
||||
if (this->m_selectionEnd >= visibleByteCount) {
|
||||
auto pos = this->m_selectionEnd - visibleByteCount;
|
||||
this->setSelection(pos, this->m_selectionEnd);
|
||||
this->scrollToSelection();
|
||||
this->jumpIfOffScreen();
|
||||
}
|
||||
});
|
||||
ShortcutManager::addShortcut(this, Keys::PageDown, [this] {
|
||||
auto pos = this->m_selectionEnd + (this->m_bytesPerRow * this->m_visibleRowCount);
|
||||
this->setSelection(pos, this->m_selectionEnd);
|
||||
this->scrollToSelection();
|
||||
this->jumpIfOffScreen();
|
||||
});
|
||||
|
||||
ShortcutManager::addShortcut(this, CTRL + Keys::G, [this] {
|
||||
@@ -1338,6 +1419,10 @@ namespace hex::plugin::builtin {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.insert"_lang, nullptr, false, providerValid && provider->isResizable())) {
|
||||
this->openPopup<PopupInsert>(this->getSelection().getStartAddress(), 0x00);
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.remove"_lang, nullptr, false, providerValid && provider->isResizable())) {
|
||||
this->openPopup<PopupRemove>(this->getSelection().getStartAddress(), 0x00);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace hex::plugin::builtin {
|
||||
ContentRegistry::FileHandler::add({ ".mgc" }, [](const auto &path) {
|
||||
for (const auto &destPath : fs::getDefaultPaths(fs::ImHexPath::Magic)) {
|
||||
if (fs::copyFile(path, destPath / path.filename(), std::fs::copy_options::overwrite_existing)) {
|
||||
View::showMessagePopup("hex.builtin.view.information.magic_db_added"_lang);
|
||||
View::showInfoPopup("hex.builtin.view.information.magic_db_added"_lang);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,16 +21,15 @@ namespace hex::plugin::builtin {
|
||||
static bool initialized = false;
|
||||
static TextEditor::LanguageDefinition langDef;
|
||||
if (!initialized) {
|
||||
static const char *const keywords[] = {
|
||||
static constexpr std::array keywords = {
|
||||
"using", "struct", "union", "enum", "bitfield", "be", "le", "if", "else", "false", "true", "this", "parent", "addressof", "sizeof", "$", "while", "for", "fn", "return", "break", "continue", "namespace", "in", "out"
|
||||
};
|
||||
for (auto &k : keywords)
|
||||
langDef.mKeywords.insert(k);
|
||||
|
||||
static const char *const builtInTypes[] = {
|
||||
static constexpr std::array builtInTypes = {
|
||||
"u8", "u16", "u32", "u64", "u128", "s8", "s16", "s32", "s64", "s128", "float", "double", "char", "char16", "bool", "padding", "str", "auto"
|
||||
};
|
||||
|
||||
for (const auto name : builtInTypes) {
|
||||
TextEditor::Identifier id;
|
||||
id.mDeclaration = "";
|
||||
@@ -76,7 +75,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
|
||||
ViewPatternEditor::ViewPatternEditor() : View("hex.builtin.view.pattern_editor.name") {
|
||||
this->m_parserRuntime = new pl::PatternLanguage();
|
||||
this->m_parserRuntime = ContentRegistry::PatternLanguage::createDefaultRuntime(nullptr);
|
||||
|
||||
this->m_textEditor.SetLanguageDefinition(PatternLanguage());
|
||||
this->m_textEditor.SetShowWhitespaces(false);
|
||||
@@ -133,7 +132,7 @@ namespace hex::plugin::builtin {
|
||||
if (!entry.is_regular_file())
|
||||
continue;
|
||||
|
||||
fs::File file(entry.path().string(), fs::File::Mode::Read);
|
||||
fs::File file(entry.path(), fs::File::Mode::Read);
|
||||
if (!file.isValid())
|
||||
continue;
|
||||
|
||||
@@ -231,55 +230,51 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
|
||||
|
||||
ImHexApi::HexEditor::addBackgroundHighlightingProvider([](u64 address, const u8 *data, size_t size) -> std::optional<color_t> {
|
||||
ImHexApi::HexEditor::addBackgroundHighlightingProvider([this](u64 address, const u8 *data, size_t size) -> std::optional<color_t> {
|
||||
hex::unused(data, size);
|
||||
|
||||
const auto &patterns = ImHexApi::Provider::get()->getPatternLanguageRuntime().getPatterns();
|
||||
for (const auto &pattern : patterns) {
|
||||
auto child = pattern->getPattern(address);
|
||||
if (child != nullptr) {
|
||||
return child->getColor();
|
||||
}
|
||||
}
|
||||
if (this->m_runningEvaluators != 0)
|
||||
return std::nullopt;
|
||||
|
||||
return std::nullopt;
|
||||
const auto pattern = ImHexApi::Provider::get()->getPatternLanguageRuntime().getPattern(address);
|
||||
if (pattern != nullptr)
|
||||
return pattern->getColor();
|
||||
else
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
ImHexApi::HexEditor::addTooltipProvider([this](u64 address, const u8 *data, size_t size) {
|
||||
hex::unused(data, size);
|
||||
|
||||
auto &patterns = ImHexApi::Provider::get()->getPatternLanguageRuntime().getPatterns();
|
||||
for (auto &pattern : patterns) {
|
||||
auto child = pattern->getPattern(address);
|
||||
if (child != nullptr) {
|
||||
ImGui::BeginTooltip();
|
||||
auto pattern = ImHexApi::Provider::get()->getPatternLanguageRuntime().getPattern(address);
|
||||
if (pattern != nullptr) {
|
||||
ImGui::BeginTooltip();
|
||||
|
||||
if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
this->drawPatternTooltip(child);
|
||||
this->drawPatternTooltip(pattern);
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_TableRowBg, pattern->getColor());
|
||||
ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, pattern->getColor());
|
||||
ImGui::EndTable();
|
||||
ImGui::PopStyleColor(2);
|
||||
}
|
||||
ImGui::EndTooltip();
|
||||
auto tooltipColor = (pattern->getColor() & 0x00FF'FFFF) | 0x7000'0000;
|
||||
ImGui::PushStyleColor(ImGuiCol_TableRowBg, tooltipColor);
|
||||
ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, tooltipColor);
|
||||
ImGui::EndTable();
|
||||
ImGui::PopStyleColor(2);
|
||||
}
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ViewPatternEditor::~ViewPatternEditor() {
|
||||
delete this->m_parserRuntime;
|
||||
|
||||
EventManager::unsubscribe<EventProjectFileStore>(this);
|
||||
EventManager::unsubscribe<EventProjectFileLoad>(this);
|
||||
EventManager::unsubscribe<RequestSetPatternLanguageCode>(this);
|
||||
EventManager::unsubscribe<EventFileLoaded>(this);
|
||||
EventManager::unsubscribe<RequestChangeTheme>(this);
|
||||
EventManager::unsubscribe<EventFileUnloaded>(this);
|
||||
EventManager::unsubscribe<RequestChangeTheme>(this);
|
||||
EventManager::unsubscribe<EventProviderChanged>(this);
|
||||
}
|
||||
|
||||
void ViewPatternEditor::drawContent() {
|
||||
@@ -704,6 +699,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
this->evaluatePattern(code);
|
||||
this->m_textEditor.SetText(code);
|
||||
this->parsePattern(code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -711,6 +707,7 @@ namespace hex::plugin::builtin {
|
||||
if (!ImHexApi::Provider::isValid()) return;
|
||||
|
||||
ImHexApi::Provider::get()->getPatternLanguageRuntime().reset();
|
||||
this->parsePattern("");
|
||||
}
|
||||
|
||||
|
||||
@@ -788,6 +785,8 @@ namespace hex::plugin::builtin {
|
||||
this->m_lastEvaluationError = runtime.getError();
|
||||
}
|
||||
|
||||
runtime.flattenPatterns();
|
||||
|
||||
this->m_lastEvaluationLog = runtime.getConsoleLog();
|
||||
this->m_lastEvaluationOutVars = runtime.getOutVariables();
|
||||
this->m_runningEvaluators--;
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace hex::plugin::builtin {
|
||||
if (ImGui::BeginTabItem(LangEntry(category))) {
|
||||
const std::string &categoryDesc = descriptions.count(category) ? descriptions.at(category) : category.name;
|
||||
LangEntry descriptionEntry{categoryDesc};
|
||||
ImGui::TextUnformatted(descriptionEntry);
|
||||
ImGui::TextWrapped("%s", static_cast<const char*>(descriptionEntry));
|
||||
ImGui::InfoTooltip(descriptionEntry);
|
||||
ImGui::Separator();
|
||||
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
#include <hex/helpers/magic.hpp>
|
||||
#include <hex/helpers/file.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/tar.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <microtar.h>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
@@ -76,34 +76,8 @@ namespace hex::plugin::builtin {
|
||||
entry.hasUpdate = false;
|
||||
|
||||
if (entry.isFolder) {
|
||||
mtar_t ctx;
|
||||
mtar_open(&ctx, this->m_downloadPath.string().c_str(), "r");
|
||||
|
||||
mtar_header_t header;
|
||||
auto extractBasePath = this->m_downloadPath.parent_path() / this->m_downloadPath.stem();
|
||||
while (mtar_read_header(&ctx, &header) != MTAR_ENULLRECORD) {
|
||||
auto filePath = extractBasePath / std::fs::path(header.name);
|
||||
if (filePath.filename() == "@PaxHeader") {
|
||||
mtar_next(&ctx);
|
||||
continue;
|
||||
}
|
||||
|
||||
fs::createDirectories(filePath.parent_path());
|
||||
fs::File outputFile(filePath.string(), fs::File::Mode::Create);
|
||||
|
||||
std::vector<u8> buffer(0x10000);
|
||||
for (u64 offset = 0; offset < header.size; offset += buffer.size()) {
|
||||
auto readSize = std::min<u64>(buffer.size(), header.size - offset);
|
||||
mtar_read_data(&ctx, buffer.data(), readSize);
|
||||
|
||||
buffer.resize(readSize);
|
||||
outputFile.write(buffer);
|
||||
}
|
||||
mtar_next(&ctx);
|
||||
}
|
||||
|
||||
mtar_finalize(&ctx);
|
||||
mtar_close(&ctx);
|
||||
Tar tar(this->m_downloadPath, Tar::Mode::Read);
|
||||
tar.extractAll(this->m_downloadPath.parent_path() / this->m_downloadPath.stem());
|
||||
}
|
||||
|
||||
downloadDoneCallback(entry);
|
||||
@@ -257,12 +231,15 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
bool ViewStore::remove(fs::ImHexPath pathType, const std::string &fileName) {
|
||||
bool removed = false;
|
||||
bool removed = true;
|
||||
for (const auto &path : fs::getDefaultPaths(pathType)) {
|
||||
bool removedFile = fs::remove(path / std::fs::path(fileName));
|
||||
bool removedFolder = fs::remove(path / std::fs::path(fileName).stem());
|
||||
const auto filePath = path / fileName;
|
||||
const auto folderPath = (path / std::fs::path(fileName).stem());
|
||||
|
||||
removed = removed || removedFile || removedFolder;
|
||||
fs::remove(filePath);
|
||||
fs::removeAll(folderPath);
|
||||
|
||||
removed = removed && !fs::exists(filePath) && !fs::exists(folderPath);
|
||||
}
|
||||
|
||||
return removed;
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace hex::plugin::builtin {
|
||||
if (this->m_minimumLength < 1)
|
||||
this->m_minimumLength = 1;
|
||||
|
||||
ImGui::Checkbox("Regex", &this->m_regex);
|
||||
ImGui::Checkbox("hex.builtin.view.strings.regex"_lang, &this->m_regex);
|
||||
|
||||
bool filterError = this->m_regex && !this->m_pattern_parsed;
|
||||
if (filterError)
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace hex::plugin::builtin {
|
||||
ContentRegistry::FileHandler::add({ ".yar" }, [](const auto &path) {
|
||||
for (const auto &destPath : fs::getDefaultPaths(fs::ImHexPath::Yara)) {
|
||||
if (fs::copyFile(path, destPath / path.filename(), std::fs::copy_options::overwrite_existing)) {
|
||||
View::showMessagePopup("hex.builtin.view.yara.rule_added"_lang);
|
||||
View::showInfoPopup("hex.builtin.view.yara.rule_added"_lang);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -46,10 +46,10 @@ namespace hex::plugin::builtin {
|
||||
} else {
|
||||
ImGui::BeginDisabled(this->m_matching);
|
||||
{
|
||||
if (ImGui::BeginCombo("hex.builtin.view.yara.header.rules"_lang, this->m_rules[this->m_selectedRule].first.c_str())) {
|
||||
if (ImGui::BeginCombo("hex.builtin.view.yara.header.rules"_lang, this->m_rules[this->m_selectedRule].first.string().c_str())) {
|
||||
for (u32 i = 0; i < this->m_rules.size(); i++) {
|
||||
const bool selected = (this->m_selectedRule == i);
|
||||
if (ImGui::Selectable(this->m_rules[i].first.c_str(), selected))
|
||||
if (ImGui::Selectable(this->m_rules[i].first.string().c_str(), selected))
|
||||
this->m_selectedRule = i;
|
||||
|
||||
if (selected)
|
||||
@@ -162,7 +162,7 @@ namespace hex::plugin::builtin {
|
||||
std::error_code error;
|
||||
for (const auto &entry : std::fs::recursive_directory_iterator(path, error)) {
|
||||
if (entry.is_regular_file() && entry.path().extension() == ".yar") {
|
||||
this->m_rules.emplace_back(std::fs::relative(entry.path(), std::fs::path(path)).string(), entry.path().string());
|
||||
this->m_rules.emplace_back(std::fs::relative(entry.path(), path), entry.path());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,7 +207,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
delete[] ptr;
|
||||
},
|
||||
this->m_rules[this->m_selectedRule].second.data());
|
||||
fs::toShortPath(this->m_rules[this->m_selectedRule].second).string().data());
|
||||
|
||||
|
||||
fs::File file(this->m_rules[this->m_selectedRule].second, fs::File::Mode::Read);
|
||||
|
||||
@@ -215,11 +215,14 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.view.disassembler.disassembly.bytes", "Byte" },
|
||||
|
||||
{ "hex.builtin.view.hashes.name", "Hashes" },
|
||||
{ "hex.builtin.view.hashes.settings", "Einstellungen" },
|
||||
{ "hex.builtin.view.hashes.function", "Hash Funktion" },
|
||||
{ "hex.builtin.view.hashes.iv", "Startwert" },
|
||||
{ "hex.builtin.view.hashes.poly", "Polynomial" },
|
||||
{ "hex.builtin.view.hashes.hash", "Hash" },
|
||||
{ "hex.builtin.view.hashes.no_settings", "Keine Einstellungen verfügbar" },
|
||||
{ "hex.builtin.view.hashes.function", "Hashfunktion" },
|
||||
{ "hex.builtin.view.hashes.name", "Name" },
|
||||
{ "hex.builtin.view.hashes.type", "Typ" },
|
||||
{ "hex.builtin.view.hashes.result", "Resultat" },
|
||||
{ "hex.builtin.view.hashes.remove", "Hash entfernen" },
|
||||
{ "hex.builtin.view.hashes.hover_info", "Bewege die Maus über die seketierten Bytes im Hex Editor und halte SHIFT gedrückt, um die Hashes dieser Region anzuzeigen." },
|
||||
|
||||
{ "hex.builtin.view.help.name", "Hilfe" },
|
||||
{ "hex.builtin.view.help.about.name", "Über ImHex" },
|
||||
@@ -331,6 +334,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.view.strings.copy", "String kopieren" },
|
||||
{ "hex.builtin.view.strings.demangle", "Demangle" },
|
||||
{ "hex.builtin.view.strings.min_length", "Minimallänge" },
|
||||
{ "hex.builtin.view.strings.regex", "Regex" },
|
||||
{ "hex.builtin.view.strings.filter", "Filter" },
|
||||
{ "hex.builtin.view.strings.extract", "Extrahieren" },
|
||||
{ "hex.builtin.view.strings.regex_error", "Ungültiges Regex" },
|
||||
@@ -641,6 +645,20 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.tools.file_tools.combiner.error.open_output", "Erstellen der Zieldatei fehlgeschlagen" },
|
||||
{ "hex.builtin.tools.file_tools.combiner.open_input", "Öffnen der Inputdatei {0} fehlgeschlagen" },
|
||||
{ "hex.builtin.tools.file_tools.combiner.success", "Dateien erfolgreich kombiniert!" },
|
||||
{ "hex.builtin.tools.ieee756", "IEEE 756 Fliesskommazahl Tester" },
|
||||
{ "hex.builtin.tools.ieee756.sign", "Vorzeichen" },
|
||||
{ "hex.builtin.tools.ieee756.exponent", "Exponent" },
|
||||
{ "hex.builtin.tools.ieee756.mantissa", "Mantisse" },
|
||||
{ "hex.builtin.tools.ieee756.exponent_size", "Exponentengrösse" },
|
||||
{ "hex.builtin.tools.ieee756.mantissa_size", "Mantissengrösse" },
|
||||
{ "hex.builtin.tools.ieee756.half_precision", "Half Precision" },
|
||||
{ "hex.builtin.tools.ieee756.singe_precision", "Single Precision" },
|
||||
{ "hex.builtin.tools.ieee756.double_precision", "Double Precision" },
|
||||
{ "hex.builtin.tools.ieee756.type", "Typ" },
|
||||
{ "hex.builtin.tools.ieee756.formula", "Formel" },
|
||||
{ "hex.builtin.tools.ieee756.result.title", "Resultat" },
|
||||
{ "hex.builtin.tools.ieee756.result.float", "Fliesskomma Resultat" },
|
||||
{ "hex.builtin.tools.ieee756.result.hex", "Hexadezimal Resultat" },
|
||||
|
||||
{ "hex.builtin.setting.imhex", "ImHex" },
|
||||
{ "hex.builtin.setting.imhex.recent_files", "Kürzlich geöffnete Dateien" },
|
||||
@@ -678,6 +696,11 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.setting.font", "Schriftart" },
|
||||
{ "hex.builtin.setting.font.font_path", "Eigene Schriftart" },
|
||||
{ "hex.builtin.setting.font.font_size", "Schriftgrösse" },
|
||||
//{ "hex.builtin.setting.proxy", "Proxy" },
|
||||
//{ "hex.builtin.setting.proxy.description", "Proxy will take effect on store, wikipedia or any other plugin immediately." },
|
||||
//{ "hex.builtin.setting.proxy.enable", "Enable Proxy" },
|
||||
//{ "hex.builtin.setting.proxy.url", "Proxy URL" },
|
||||
//{ "hex.builtin.setting.proxy.url.tooltip", "http(s):// or socks5:// (e.g., http://127.0.0.1:1080)" },
|
||||
|
||||
{ "hex.builtin.provider.file.path", "Dateipfad" },
|
||||
{ "hex.builtin.provider.file.size", "Größe" },
|
||||
@@ -715,6 +738,21 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.visualizer.floating_point.64bit", "Floating Point (64 bits)" },
|
||||
{ "hex.builtin.visualizer.hexii", "HexII" },
|
||||
{ "hex.builtin.visualizer.rgba8", "RGBA8 Farbe" },
|
||||
|
||||
{ "hex.builtin.hash.md5", "MD5" },
|
||||
{ "hex.builtin.hash.sha1", "SHA1" },
|
||||
{ "hex.builtin.hash.sha224", "SHA224" },
|
||||
{ "hex.builtin.hash.sha256", "SHA256" },
|
||||
{ "hex.builtin.hash.sha384", "SHA384" },
|
||||
{ "hex.builtin.hash.sha512", "SHA512" },
|
||||
{ "hex.builtin.hash.crc8", "CRC8" },
|
||||
{ "hex.builtin.hash.crc16", "CRC16" },
|
||||
{ "hex.builtin.hash.crc32", "CRC32" },
|
||||
{ "hex.builtin.hash.crc.poly", "Polynom" },
|
||||
{ "hex.builtin.hash.crc.iv", "Initialwert" },
|
||||
{ "hex.builtin.hash.crc.xor_out", "XOR Out" },
|
||||
{ "hex.builtin.hash.crc.refl_in", "Reflect In" },
|
||||
{ "hex.builtin.hash.crc.refl_out", "Reflect Out" },
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.common.open", "Open" },
|
||||
{ "hex.builtin.common.browse", "Browse..." },
|
||||
{ "hex.builtin.common.choose_file", "Choose file" },
|
||||
{ "hex.common.processing", "Processing" },
|
||||
{ "hex.builtin.common.processing", "Processing" },
|
||||
|
||||
{ "hex.builtin.popup.exit_application.title", "Exit Application?" },
|
||||
{ "hex.builtin.popup.exit_application.desc", "You have unsaved changes made to your Project.\nAre you sure you want to exit?" },
|
||||
@@ -218,14 +218,14 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.view.disassembler.disassembly.bytes", "Byte" },
|
||||
|
||||
{ "hex.builtin.view.hashes.name", "Hashes" },
|
||||
{ "hex.builtin.view.hashes.settings", "Settings" },
|
||||
{ "hex.builtin.view.hashes.hash", "Hash" },
|
||||
{ "hex.builtin.view.hashes.no_settings", "No settings available" },
|
||||
{ "hex.builtin.view.hashes.function", "Hash function" },
|
||||
{ "hex.builtin.view.hashes.iv", "Initial value" },
|
||||
{ "hex.builtin.view.hashes.xorout", "Final XOR value" },
|
||||
{ "hex.builtin.common.reflectIn", "Reflect input" },
|
||||
{ "hex.builtin.common.reflectOut", "Reflect output" },
|
||||
{ "hex.builtin.view.hashes.poly", "Polynomial" },
|
||||
{ "hex.builtin.view.hashes.name", "Name" },
|
||||
{ "hex.builtin.view.hashes.type", "Type" },
|
||||
{ "hex.builtin.view.hashes.result", "Result" },
|
||||
{ "hex.builtin.view.hashes.remove", "Remove hash" },
|
||||
{ "hex.builtin.view.hashes.hover_info", "Hover over the Hex Editor selection and hold down SHIFT to view the hashes of that region." },
|
||||
|
||||
{ "hex.builtin.view.help.name", "Help" },
|
||||
{ "hex.builtin.view.help.about.name", "About" },
|
||||
@@ -278,6 +278,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.view.hex_editor.menu.edit.set_base", "Set base address" },
|
||||
{ "hex.builtin.view.hex_editor.menu.edit.resize", "Resize..." },
|
||||
{ "hex.builtin.view.hex_editor.menu.edit.insert", "Insert..." },
|
||||
{ "hex.builtin.view.hex_editor.menu.edit.remove", "Remove..." },
|
||||
|
||||
{ "hex.builtin.view.information.name", "Data Information" },
|
||||
{ "hex.builtin.view.information.control", "Control" },
|
||||
@@ -335,6 +336,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.view.strings.copy", "Copy string" },
|
||||
{ "hex.builtin.view.strings.demangle", "Demangle" },
|
||||
{ "hex.builtin.view.strings.min_length", "Minimum length" },
|
||||
{ "hex.builtin.view.strings.regex", "Regex" },
|
||||
{ "hex.builtin.view.strings.filter", "Filter" },
|
||||
{ "hex.builtin.view.strings.extract", "Extract" },
|
||||
{ "hex.builtin.view.strings.regex_error", "Invalid regex" },
|
||||
@@ -645,6 +647,20 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.tools.file_tools.combiner.error.open_output", "Failed to create output file" },
|
||||
{ "hex.builtin.tools.file_tools.combiner.open_input", "Failed to open input file {0}" },
|
||||
{ "hex.builtin.tools.file_tools.combiner.success", "Files combined successfully!" },
|
||||
{ "hex.builtin.tools.ieee756", "IEEE 756 Floating Point Tester" },
|
||||
{ "hex.builtin.tools.ieee756.sign", "Sign" },
|
||||
{ "hex.builtin.tools.ieee756.exponent", "Exponent" },
|
||||
{ "hex.builtin.tools.ieee756.mantissa", "Mantissa" },
|
||||
{ "hex.builtin.tools.ieee756.exponent_size", "Exponent Size" },
|
||||
{ "hex.builtin.tools.ieee756.mantissa_size", "Mantissa Size" },
|
||||
{ "hex.builtin.tools.ieee756.half_precision", "Half Precision" },
|
||||
{ "hex.builtin.tools.ieee756.singe_precision", "Single Precision" },
|
||||
{ "hex.builtin.tools.ieee756.double_precision", "Double Precision" },
|
||||
{ "hex.builtin.tools.ieee756.type", "Type" },
|
||||
{ "hex.builtin.tools.ieee756.formula", "Formula" },
|
||||
{ "hex.builtin.tools.ieee756.result.title", "Result" },
|
||||
{ "hex.builtin.tools.ieee756.result.float", "Floating Point Result" },
|
||||
{ "hex.builtin.tools.ieee756.result.hex", "Hexadecimal Result" },
|
||||
|
||||
{ "hex.builtin.setting.imhex", "ImHex" },
|
||||
{ "hex.builtin.setting.imhex.recent_files", "Recent Files" },
|
||||
@@ -682,6 +698,11 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.setting.font", "Font" },
|
||||
{ "hex.builtin.setting.font.font_path", "Custom Font Path" },
|
||||
{ "hex.builtin.setting.font.font_size", "Font Size" },
|
||||
{ "hex.builtin.setting.proxy", "Proxy" },
|
||||
{ "hex.builtin.setting.proxy.description", "Proxy will take effect on store, wikipedia or any other plugin immediately." },
|
||||
{ "hex.builtin.setting.proxy.enable", "Enable Proxy" },
|
||||
{ "hex.builtin.setting.proxy.url", "Proxy URL" },
|
||||
{ "hex.builtin.setting.proxy.url.tooltip", "http(s):// or socks5:// (e.g., http://127.0.0.1:1080)" },
|
||||
|
||||
{ "hex.builtin.provider.file.path", "File path" },
|
||||
{ "hex.builtin.provider.file.size", "Size" },
|
||||
@@ -719,6 +740,21 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.visualizer.floating_point.64bit", "Floating Point (64 bits)" },
|
||||
{ "hex.builtin.visualizer.hexii", "HexII" },
|
||||
{ "hex.builtin.visualizer.rgba8", "RGBA8 Color" },
|
||||
|
||||
{ "hex.builtin.hash.md5", "MD5" },
|
||||
{ "hex.builtin.hash.sha1", "SHA1" },
|
||||
{ "hex.builtin.hash.sha224", "SHA224" },
|
||||
{ "hex.builtin.hash.sha256", "SHA256" },
|
||||
{ "hex.builtin.hash.sha384", "SHA384" },
|
||||
{ "hex.builtin.hash.sha512", "SHA512" },
|
||||
{ "hex.builtin.hash.crc8", "CRC8" },
|
||||
{ "hex.builtin.hash.crc16", "CRC16" },
|
||||
{ "hex.builtin.hash.crc32", "CRC32" },
|
||||
{ "hex.builtin.hash.crc.poly", "Polynomial" },
|
||||
{ "hex.builtin.hash.crc.iv", "Initial Value" },
|
||||
{ "hex.builtin.hash.crc.xor_out", "XOR Out" },
|
||||
{ "hex.builtin.hash.crc.refl_in", "Reflect In" },
|
||||
{ "hex.builtin.hash.crc.refl_out", "Reflect Out" },
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.common.open", "Apri" },
|
||||
{ "hex.builtin.common.browse", "Esplora..." },
|
||||
{ "hex.builtin.common.choose_file", "Scegli file" },
|
||||
//{ "hex.common.processing", "Processing" },
|
||||
//{ "hex.builtin.common.processing", "Processing" },
|
||||
|
||||
{ "hex.builtin.popup.exit_application.title", "Uscire dall'applicazione?" },
|
||||
{ "hex.builtin.popup.exit_application.desc", "Hai delle modifiche non salvate nel tuo progetto.\nSei sicuro di voler uscire?" },
|
||||
@@ -216,11 +216,15 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.view.disassembler.disassembly.bytes", "Byte" },
|
||||
|
||||
{ "hex.builtin.view.hashes.name", "Hash" },
|
||||
{ "hex.builtin.view.hashes.settings", "Impostazioni" },
|
||||
{ "hex.builtin.view.hashes.hash", "Hash" },
|
||||
//{ "hex.builtin.view.hashes.no_settings", "No settings available" },
|
||||
{ "hex.builtin.view.hashes.function", "Funzioni di Hash" },
|
||||
{ "hex.builtin.view.hashes.iv", "Valore Iniziale" },
|
||||
{ "hex.builtin.view.hashes.poly", "Polinomio" },
|
||||
//{ "hex.builtin.view.hashes.name", "Name" },
|
||||
//{ "hex.builtin.view.hashes.type", "Type" },
|
||||
{ "hex.builtin.view.hashes.result", "Risultato" },
|
||||
//{ "hex.builtin.view.hashes.remove", "Remove hash" },
|
||||
//{ "hex.builtin.view.hashes.hover_info", "Hover over the Hex Editor selection and hold down SHIFT to view the hashes of that region." },
|
||||
|
||||
|
||||
{ "hex.builtin.view.help.name", "Aiuto" },
|
||||
{ "hex.builtin.view.help.about.name", "Riguardo ImHex" },
|
||||
@@ -334,6 +338,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.view.strings.copy", "Copia stringa" },
|
||||
{ "hex.builtin.view.strings.demangle", "Demangle" },
|
||||
{ "hex.builtin.view.strings.min_length", "Lunghezza minima" },
|
||||
//{ "hex.builtin.view.strings.regex", "Regex" },
|
||||
{ "hex.builtin.view.strings.filter", "Filtro" },
|
||||
{ "hex.builtin.view.strings.extract", "Estrai" },
|
||||
{ "hex.builtin.view.strings.searching", "Sto cercando..." },
|
||||
@@ -646,6 +651,20 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.tools.file_tools.combiner.error.open_output", "Impossibile creare file di output" },
|
||||
{ "hex.builtin.tools.file_tools.combiner.open_input", "Impossibile aprire file di input {0}" },
|
||||
{ "hex.builtin.tools.file_tools.combiner.success", "File combinato con successo!" },
|
||||
//{ "hex.builtin.tools.ieee756", "IEEE 756 Floating Point Tester" },
|
||||
//{ "hex.builtin.tools.ieee756.sign", "Sign" },
|
||||
//{ "hex.builtin.tools.ieee756.exponent", "Exponent" },
|
||||
//{ "hex.builtin.tools.ieee756.mantissa", "Mantissa" },
|
||||
//{ "hex.builtin.tools.ieee756.exponent_size", "Exponent Size" },
|
||||
//{ "hex.builtin.tools.ieee756.mantissa_size", "Mantissa Size" },
|
||||
//{ "hex.builtin.tools.ieee756.half_precision", "Half Precision" },
|
||||
//{ "hex.builtin.tools.ieee756.singe_precision", "Single Precision" },
|
||||
//{ "hex.builtin.tools.ieee756.double_precision", "Double Precision" },
|
||||
//{ "hex.builtin.tools.ieee756.type", "Type" },
|
||||
//{ "hex.builtin.tools.ieee756.formula", "Formula" },
|
||||
//{ "hex.builtin.tools.ieee756.result.title", "Result" },
|
||||
//{ "hex.builtin.tools.ieee756.result.float", "Floating Point Result" },
|
||||
//{ "hex.builtin.tools.ieee756.result.hex", "Hexadecimal Result" },
|
||||
|
||||
{ "hex.builtin.setting.imhex", "ImHex" },
|
||||
{ "hex.builtin.setting.imhex.recent_files", "File recenti" },
|
||||
@@ -683,6 +702,11 @@ namespace hex::plugin::builtin {
|
||||
//{ "hex.builtin.setting.font", "Font" },
|
||||
//{ "hex.builtin.setting.font.font_path", "Custom Font Path" },
|
||||
//{ "hex.builtin.setting.font.font_size", "Font Size" },
|
||||
//{ "hex.builtin.setting.proxy", "Proxy" },
|
||||
//{ "hex.builtin.setting.proxy.description", "Proxy will take effect on store, wikipedia or any other plugin immediately." },
|
||||
//{ "hex.builtin.setting.proxy.enable", "Enable Proxy" },
|
||||
//{ "hex.builtin.setting.proxy.url", "Proxy URL" },
|
||||
//{ "hex.builtin.setting.proxy.url.tooltip", "http(s):// or socks5:// (e.g., http://127.0.0.1:1080)" },
|
||||
|
||||
{ "hex.builtin.provider.file.path", "Percorso del File" },
|
||||
{ "hex.builtin.provider.file.size", "Dimensione" },
|
||||
@@ -720,6 +744,21 @@ namespace hex::plugin::builtin {
|
||||
//{ "hex.builtin.visualizer.floating_point.64bit", "Floating Point (64 bits)" },
|
||||
//{ "hex.builtin.visualizer.hexii", "HexII" },
|
||||
//{ "hex.builtin.visualizer.rgba8", "RGBA8 Color" },
|
||||
|
||||
{ "hex.builtin.hash.md5", "MD5" },
|
||||
{ "hex.builtin.hash.sha1", "SHA1" },
|
||||
{ "hex.builtin.hash.sha224", "SHA224" },
|
||||
{ "hex.builtin.hash.sha256", "SHA256" },
|
||||
{ "hex.builtin.hash.sha384", "SHA384" },
|
||||
{ "hex.builtin.hash.sha512", "SHA512" },
|
||||
{ "hex.builtin.hash.crc8", "CRC8" },
|
||||
{ "hex.builtin.hash.crc16", "CRC16" },
|
||||
{ "hex.builtin.hash.crc32", "CRC32" },
|
||||
{ "hex.builtin.hash.crc.poly", "Polinomio" },
|
||||
{ "hex.builtin.hash.crc.iv", "Valore Iniziale" },
|
||||
//{ "hex.builtin.hash.crc.xor_out", "XOR Out" },
|
||||
//{ "hex.builtin.hash.crc.refl_in", "Reflect In" },
|
||||
//{ "hex.builtin.hash.crc.refl_out", "Reflect Out" },
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.common.open", "開く" },
|
||||
{ "hex.builtin.common.browse", "ファイルを参照..." },
|
||||
{ "hex.builtin.common.choose_file", "ファイルを選択" },
|
||||
// { "hex.common.processing", "Processing" },
|
||||
// { "hex.builtin.common.processing", "Processing" },
|
||||
|
||||
{ "hex.builtin.popup.exit_application.title", "アプリケーションを終了しますか?" },
|
||||
{ "hex.builtin.popup.exit_application.desc", "プロジェクトに保存されていない変更があります。\n終了してもよろしいですか?" },
|
||||
@@ -218,14 +218,14 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.view.disassembler.disassembly.bytes", "バイト" },
|
||||
|
||||
{ "hex.builtin.view.hashes.name", "ハッシュ" },
|
||||
{ "hex.builtin.view.hashes.settings", "設定" },
|
||||
//{ "hex.builtin.view.hashes.hash", "Hash" },
|
||||
//{ "hex.builtin.view.hashes.no_settings", "No settings available" },
|
||||
{ "hex.builtin.view.hashes.function", "ハッシュ関数" },
|
||||
{ "hex.builtin.view.hashes.iv", "初期値" },
|
||||
{ "hex.builtin.view.hashes.xorout", "最終XOR値" },
|
||||
{ "hex.builtin.common.reflectIn", "入力を反映" },
|
||||
{ "hex.builtin.common.reflectOut", "出力を反映" },
|
||||
{ "hex.builtin.view.hashes.poly", "多項式" },
|
||||
//{ "hex.builtin.view.hashes.name", "Name" },
|
||||
//{ "hex.builtin.view.hashes.type", "Type" },
|
||||
{ "hex.builtin.view.hashes.result", "結果" },
|
||||
//{ "hex.builtin.view.hashes.remove", "Remove hash" },
|
||||
//{ "hex.builtin.view.hashes.hover_info", "Hover over the Hex Editor selection and hold down SHIFT to view the hashes of that region." },
|
||||
|
||||
{ "hex.builtin.view.help.name", "ヘルプ" },
|
||||
{ "hex.builtin.view.help.about.name", "このソフトについて" },
|
||||
@@ -337,6 +337,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.view.strings.copy", "文字列をコピー" },
|
||||
{ "hex.builtin.view.strings.demangle", "デマングル" },
|
||||
{ "hex.builtin.view.strings.min_length", "最小の長さ" },
|
||||
//{ "hex.builtin.view.strings.regex", "Regex" },
|
||||
{ "hex.builtin.view.strings.filter", "フィルタ" },
|
||||
{ "hex.builtin.view.strings.extract", "抽出" },
|
||||
{ "hex.builtin.view.strings.regex_error", "無効な正規表現" },
|
||||
@@ -646,6 +647,20 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.tools.file_tools.combiner.error.open_output", "出力ファイルを作成できませんでした" },
|
||||
{ "hex.builtin.tools.file_tools.combiner.open_input", "入力ファイル {0} を開けませんでした" },
|
||||
{ "hex.builtin.tools.file_tools.combiner.success", "ファイルの結合に成功しました!" },
|
||||
//{ "hex.builtin.tools.ieee756", "IEEE 756 Floating Point Tester" },
|
||||
//{ "hex.builtin.tools.ieee756.sign", "Sign" },
|
||||
//{ "hex.builtin.tools.ieee756.exponent", "Exponent" },
|
||||
//{ "hex.builtin.tools.ieee756.mantissa", "Mantissa" },
|
||||
//{ "hex.builtin.tools.ieee756.exponent_size", "Exponent Size" },
|
||||
//{ "hex.builtin.tools.ieee756.mantissa_size", "Mantissa Size" },
|
||||
//{ "hex.builtin.tools.ieee756.half_precision", "Half Precision" },
|
||||
//{ "hex.builtin.tools.ieee756.singe_precision", "Single Precision" },
|
||||
//{ "hex.builtin.tools.ieee756.double_precision", "Double Precision" },
|
||||
//{ "hex.builtin.tools.ieee756.type", "Type" },
|
||||
//{ "hex.builtin.tools.ieee756.formula", "Formula" },
|
||||
//{ "hex.builtin.tools.ieee756.result.title", "Result" },
|
||||
//{ "hex.builtin.tools.ieee756.result.float", "Floating Point Result" },
|
||||
//{ "hex.builtin.tools.ieee756.result.hex", "Hexadecimal Result" },
|
||||
|
||||
{ "hex.builtin.setting.imhex", "ImHex" },
|
||||
{ "hex.builtin.setting.imhex.recent_files", "最近開いたファイル" },
|
||||
@@ -684,6 +699,11 @@ namespace hex::plugin::builtin {
|
||||
//{ "hex.builtin.setting.font", "Font" },
|
||||
//{ "hex.builtin.setting.font.font_path", "Custom Font Path" },
|
||||
//{ "hex.builtin.setting.font.font_size", "Font Size" },
|
||||
//{ "hex.builtin.setting.proxy", "Proxy" },
|
||||
//{ "hex.builtin.setting.proxy.description", "Proxy will take effect on store, wikipedia or any other plugin immediately." },
|
||||
//{ "hex.builtin.setting.proxy.enable", "Enable Proxy" },
|
||||
//{ "hex.builtin.setting.proxy.url", "Proxy URL" },
|
||||
//{ "hex.builtin.setting.proxy.url.tooltip", "http(s):// or socks5:// (e.g., http://127.0.0.1:1080)" },
|
||||
|
||||
{ "hex.builtin.provider.file.path", "ファイルパス" },
|
||||
{ "hex.builtin.provider.file.size", "サイズ" },
|
||||
@@ -721,6 +741,21 @@ namespace hex::plugin::builtin {
|
||||
//{ "hex.builtin.visualizer.floating_point.64bit", "Floating Point (64 bits)" },
|
||||
//{ "hex.builtin.visualizer.hexii", "HexII" },
|
||||
//{ "hex.builtin.visualizer.rgba8", "RGBA8 Color" },
|
||||
|
||||
{ "hex.builtin.hash.md5", "MD5" },
|
||||
{ "hex.builtin.hash.sha1", "SHA1" },
|
||||
{ "hex.builtin.hash.sha224", "SHA224" },
|
||||
{ "hex.builtin.hash.sha256", "SHA256" },
|
||||
{ "hex.builtin.hash.sha384", "SHA384" },
|
||||
{ "hex.builtin.hash.sha512", "SHA512" },
|
||||
{ "hex.builtin.hash.crc8", "CRC8" },
|
||||
{ "hex.builtin.hash.crc16", "CRC16" },
|
||||
{ "hex.builtin.hash.crc32", "CRC32" },
|
||||
{ "hex.builtin.hash.crc.poly", "多項式" },
|
||||
{ "hex.builtin.hash.crc.iv", "初期値" },
|
||||
{ "hex.builtin.hash.crc.xor_out", "最終XOR値" },
|
||||
{ "hex.builtin.hash.crc.refl_in", "入力を反映" },
|
||||
{ "hex.builtin.hash.crc.refl_out", "出力を反映" },
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user