mirror of https://github.com/WerWolv/ImHex
Compare commits
76 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
5500faa57e | |
|
|
89004574d3 | |
|
|
c11c05a399 | |
|
|
baa3329e7f | |
|
|
e696d384c2 | |
|
|
932c281223 | |
|
|
858fe0384e | |
|
|
e904cd749f | |
|
|
6b16f39be4 | |
|
|
021c7e5fdb | |
|
|
c161a5c71b | |
|
|
76ccdbccea | |
|
|
553ee89787 | |
|
|
cb6247b16e | |
|
|
cfac7ff0ba | |
|
|
49bbe7dc77 | |
|
|
07b6fa0e2e | |
|
|
67396f2009 | |
|
|
a20ff87cc9 | |
|
|
e02e57a729 | |
|
|
225dc53795 | |
|
|
e7404376db | |
|
|
d6aec341fe | |
|
|
3a3c2fb204 | |
|
|
e9b5cdbccf | |
|
|
3f30e63d95 | |
|
|
f9c6866c7b | |
|
|
388dccfd9f | |
|
|
1676342e28 | |
|
|
62732de227 | |
|
|
63e777c84c | |
|
|
ab95cdf3e5 | |
|
|
827b5b01dd | |
|
|
bfa9788099 | |
|
|
de25ce7fbb | |
|
|
21e61bfce6 | |
|
|
82e168c438 | |
|
|
48583a2b6e | |
|
|
0db0982fa7 | |
|
|
6a28ce9e4b | |
|
|
1db79f6117 | |
|
|
f234103320 | |
|
|
45c382a19a | |
|
|
fb7ef61d06 | |
|
|
2586645d02 | |
|
|
e23cb5509d | |
|
|
5cbd53ae7a | |
|
|
a4ee590875 | |
|
|
495608ed7c | |
|
|
4d10d9a195 | |
|
|
4914a34dd9 | |
|
|
ab0fb3131d | |
|
|
7922d3b3cb | |
|
|
6427f53b5a | |
|
|
994df0a3a4 | |
|
|
e6eee55810 | |
|
|
855e4c4913 | |
|
|
c2e07bf7b2 | |
|
|
77b9e3eac8 | |
|
|
790487eea6 | |
|
|
eb83354179 | |
|
|
9ba8754f97 | |
|
|
84346119b3 | |
|
|
2b3abd06db | |
|
|
8267aad79e | |
|
|
3f9ce561b9 | |
|
|
347fc3ed9f | |
|
|
0488c996e9 | |
|
|
37bfd97d93 | |
|
|
c8652b0576 | |
|
|
1208d2eb5e | |
|
|
ab34fed0c5 | |
|
|
0906e5f9cf | |
|
|
47b1c603b3 | |
|
|
4bda321e7a | |
|
|
691ff11fbc |
|
|
@ -95,7 +95,6 @@ jobs:
|
||||||
-DIMHEX_GENERATE_PDBS=ON \
|
-DIMHEX_GENERATE_PDBS=ON \
|
||||||
-DIMHEX_REPLACE_DWARF_WITH_PDB=ON \
|
-DIMHEX_REPLACE_DWARF_WITH_PDB=ON \
|
||||||
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" \
|
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" \
|
||||||
-DCPACK_WIX_VERSION="4" \
|
|
||||||
-DCPACK_WIX_ROOT="$(echo "$USERPROFILE" | tr '\\' '/')/.dotnet/tools" \
|
-DCPACK_WIX_ROOT="$(echo "$USERPROFILE" | tr '\\' '/')/.dotnet/tools" \
|
||||||
..
|
..
|
||||||
|
|
||||||
|
|
@ -166,6 +165,7 @@ jobs:
|
||||||
|
|
||||||
- name: ⬆️ Upload Windows Installer
|
- name: ⬆️ Upload Windows Installer
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
id: upload-installer
|
||||||
with:
|
with:
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
name: Windows Installer ${{ matrix.architecture_name }}
|
name: Windows Installer ${{ matrix.architecture_name }}
|
||||||
|
|
@ -279,7 +279,6 @@ jobs:
|
||||||
-DIMHEX_COMMIT_HASH_LONG="$env:GITHUB_SHA" `
|
-DIMHEX_COMMIT_HASH_LONG="$env:GITHUB_SHA" `
|
||||||
-DIMHEX_COMMIT_BRANCH="$($env:GITHUB_REF -replace '.*/', '')" `
|
-DIMHEX_COMMIT_BRANCH="$($env:GITHUB_REF -replace '.*/', '')" `
|
||||||
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" `
|
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" `
|
||||||
-DCPACK_WIX_VERSION="4" `
|
|
||||||
-DCPACK_WIX_ROOT="$($env:USERPROFILE -replace '\\','/')/.dotnet/tools" `
|
-DCPACK_WIX_ROOT="$($env:USERPROFILE -replace '\\','/')/.dotnet/tools" `
|
||||||
.
|
.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,43 @@ jobs:
|
||||||
git fetch --tags --recurse-submodules=no
|
git fetch --tags --recurse-submodules=no
|
||||||
git log nightly..origin/master --oneline --no-merges --pretty=format:'* %s' >> changelog.md
|
git log nightly..origin/master --oneline --no-merges --pretty=format:'* %s' >> changelog.md
|
||||||
|
|
||||||
|
- name: ⬆️ Upload Unsigned x86_64 Windows Installer
|
||||||
|
if: false
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
id: upload-installer-x86_64
|
||||||
|
with:
|
||||||
|
if-no-files-found: error
|
||||||
|
name: Windows Installer ${{ matrix.architecture_name }}
|
||||||
|
path: |
|
||||||
|
imhex-*-x86_64.msi
|
||||||
|
|
||||||
|
- name: ⬆️ Upload Unsigned ARM64 Windows Installer
|
||||||
|
if: false
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
id: upload-installer-arm64
|
||||||
|
with:
|
||||||
|
if-no-files-found: error
|
||||||
|
name: Windows Installer ${{ matrix.architecture_name }}
|
||||||
|
path: |
|
||||||
|
imhex-*-arm64.msi
|
||||||
|
|
||||||
|
- name: 🗑️ Delete unsigned installers
|
||||||
|
if: false
|
||||||
|
run: |
|
||||||
|
rm imhex-*.msi
|
||||||
|
|
||||||
|
- name: 🗝️ Sign Installer
|
||||||
|
if: false
|
||||||
|
uses: signpath/github-action-submit-signing-request@v1
|
||||||
|
with:
|
||||||
|
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
|
||||||
|
organization-id: 'f605a0e8-86cd-411c-bb6f-e05025afcc33'
|
||||||
|
project-slug: 'ImHex'
|
||||||
|
signing-policy-slug: 'release-signing'
|
||||||
|
github-artifact-id: '${{ steps.upload-installer.outputs.artifact-id }}'
|
||||||
|
wait-for-completion: true
|
||||||
|
output-artifact-directory: '.'
|
||||||
|
|
||||||
- name: 📦 Update Pre-Release
|
- name: 📦 Update Pre-Release
|
||||||
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
|
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
|
||||||
run: |
|
run: |
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,12 @@ on:
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
commit_hash:
|
||||||
|
type: string
|
||||||
|
description: 'The commit hash to build (defaults to the latest commit on the default branch)'
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release-update-repos:
|
release-update-repos:
|
||||||
|
|
@ -41,6 +47,7 @@ jobs:
|
||||||
tag: ImHex-v${{ env.IMHEX_VERSION }}
|
tag: ImHex-v${{ env.IMHEX_VERSION }}
|
||||||
repo: PatternLanguage
|
repo: PatternLanguage
|
||||||
token: ${{ secrets.RELEASE_TOKEN }}
|
token: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
skipIfReleaseExists: true
|
||||||
|
|
||||||
- name: 🎫 Create ImHex-Patterns release
|
- name: 🎫 Create ImHex-Patterns release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
|
|
@ -51,6 +58,7 @@ jobs:
|
||||||
tag: ImHex-v${{ env.IMHEX_VERSION }}
|
tag: ImHex-v${{ env.IMHEX_VERSION }}
|
||||||
repo: ImHex-Patterns
|
repo: ImHex-Patterns
|
||||||
token: ${{ secrets.RELEASE_TOKEN }}
|
token: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
skipIfReleaseExists: true
|
||||||
|
|
||||||
- name: 🎫 Create imhex-download-sdk release
|
- name: 🎫 Create imhex-download-sdk release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
|
|
@ -61,11 +69,13 @@ jobs:
|
||||||
tag: v${{ env.IMHEX_VERSION }}
|
tag: v${{ env.IMHEX_VERSION }}
|
||||||
repo: imhex-download-sdk
|
repo: imhex-download-sdk
|
||||||
token: ${{ secrets.RELEASE_TOKEN }}
|
token: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
skipIfReleaseExists: true
|
||||||
|
|
||||||
release-upload-artifacts:
|
release-upload-artifacts:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
name: Release Upload Artifacts
|
name: Release Upload Artifacts
|
||||||
|
outputs:
|
||||||
|
IMHEX_VERSION: ${{ steps.verify_version.outputs.IMHEX_VERSION }}
|
||||||
steps:
|
steps:
|
||||||
- name: 🧰 Checkout
|
- name: 🧰 Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
@ -74,6 +84,7 @@ jobs:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: 📜 Verify version and set version variable
|
- name: 📜 Verify version and set version variable
|
||||||
|
id: verify_version
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
project_version=`cat ImHex/VERSION`
|
project_version=`cat ImHex/VERSION`
|
||||||
|
|
@ -85,6 +96,7 @@ jobs:
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "IMHEX_VERSION=$project_version" >> $GITHUB_ENV
|
echo "IMHEX_VERSION=$project_version" >> $GITHUB_ENV
|
||||||
|
echo "IMHEX_VERSION=$project_version" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: 🗜️ Create tarball from sources with dependencies
|
- name: 🗜️ Create tarball from sources with dependencies
|
||||||
run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex
|
run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex
|
||||||
|
|
@ -97,6 +109,7 @@ jobs:
|
||||||
branch: ${{ github.event.release.target_commitish }}
|
branch: ${{ github.event.release.target_commitish }}
|
||||||
workflow_conclusion: success
|
workflow_conclusion: success
|
||||||
skip_unpack: true
|
skip_unpack: true
|
||||||
|
commit: ${{ github.event.inputs.commit_hash }}
|
||||||
|
|
||||||
- name: 🗜️ Unzip files when needed
|
- name: 🗜️ Unzip files when needed
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -115,25 +128,80 @@ jobs:
|
||||||
|
|
||||||
- name: 🟩 Rename artifacts when needed
|
- name: 🟩 Rename artifacts when needed
|
||||||
run: |
|
run: |
|
||||||
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip
|
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip || true
|
||||||
mv "Windows Portable arm64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-arm64.zip
|
mv "Windows Portable arm64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-arm64.zip || true
|
||||||
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip
|
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip || true
|
||||||
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-Web.zip
|
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-Web.zip || true
|
||||||
rm artifact.tar || true
|
rm artifact.tar || true
|
||||||
|
|
||||||
|
- name: ⬆️ Upload Unsigned x86_64 Windows Installer
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
id: upload-installer-x86_64
|
||||||
|
with:
|
||||||
|
if-no-files-found: error
|
||||||
|
name: Windows Installer ${{ matrix.architecture_name }}
|
||||||
|
path: |
|
||||||
|
imhex-*-x86_64.msi
|
||||||
|
|
||||||
|
- name: ⬆️ Upload Unsigned ARM64 Windows Installer
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
id: upload-installer-arm64
|
||||||
|
with:
|
||||||
|
if-no-files-found: error
|
||||||
|
name: Windows Installer ${{ matrix.architecture_name }}
|
||||||
|
path: |
|
||||||
|
imhex-*-arm64.msi
|
||||||
|
|
||||||
|
- name: 🗑️ Delete unsigned installers
|
||||||
|
run: |
|
||||||
|
rm imhex-*.msi
|
||||||
|
|
||||||
|
- name: 🗝️ Sign x86_64 Installer
|
||||||
|
uses: signpath/github-action-submit-signing-request@v1
|
||||||
|
with:
|
||||||
|
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
|
||||||
|
organization-id: 'f605a0e8-86cd-411c-bb6f-e05025afcc33'
|
||||||
|
project-slug: 'ImHex'
|
||||||
|
signing-policy-slug: 'release-signing'
|
||||||
|
github-artifact-id: '${{ steps.upload-installer-x86_64.outputs.artifact-id }}'
|
||||||
|
wait-for-completion: true
|
||||||
|
output-artifact-directory: '.'
|
||||||
|
|
||||||
|
- name: 🗝️ Sign ARM64 Installer
|
||||||
|
uses: signpath/github-action-submit-signing-request@v1
|
||||||
|
with:
|
||||||
|
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
|
||||||
|
organization-id: 'f605a0e8-86cd-411c-bb6f-e05025afcc33'
|
||||||
|
project-slug: 'ImHex'
|
||||||
|
signing-policy-slug: 'release-signing'
|
||||||
|
github-artifact-id: '${{ steps.upload-installer-arm64.outputs.artifact-id }}'
|
||||||
|
wait-for-completion: true
|
||||||
|
output-artifact-directory: '.'
|
||||||
|
|
||||||
- name: ⬆️ Upload everything to release
|
- name: ⬆️ Upload everything to release
|
||||||
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
|
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
|
||||||
with:
|
with:
|
||||||
files: '*'
|
files: '*'
|
||||||
|
|
||||||
|
release-update-aur:
|
||||||
|
name: Release update AUR package
|
||||||
|
needs: release-upload-artifacts
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: ⬇️ Download artifacts
|
||||||
|
run: |
|
||||||
|
tagname=${GITHUB_REF#refs/tags/}
|
||||||
|
version=${tagname#v}
|
||||||
|
wget https://github.com/WerWolv/ImHex/releases/download/${tagname}/imhex-${version}-ArchLinux-x86_64.pkg.tar.zst
|
||||||
|
|
||||||
- name: ✒️ Prepare PKGBUILD
|
- name: ✒️ Prepare PKGBUILD
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
cp ImHex/dist/Arch/PKGBUILD .
|
cp ImHex/dist/Arch/PKGBUILD .
|
||||||
|
|
||||||
hash=`md5sum imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst | cut -d ' ' -f 1`
|
hash=`md5sum imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst | cut -d ' ' -f 1`
|
||||||
|
|
||||||
sed -i 's/%version%/${{ env.IMHEX_VERSION }}/g' PKGBUILD
|
sed -i 's/%version%/${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}/g' PKGBUILD
|
||||||
sed -i "s/(SKIP)/($hash)/g" PKGBUILD
|
sed -i "s/(SKIP)/($hash)/g" PKGBUILD
|
||||||
|
|
||||||
- name: ⬆️ Publish AUR package
|
- name: ⬆️ Publish AUR package
|
||||||
|
|
@ -149,7 +217,7 @@ jobs:
|
||||||
commit_username: iTrooz
|
commit_username: iTrooz
|
||||||
commit_email: itrooz@protonmail.com
|
commit_email: itrooz@protonmail.com
|
||||||
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
||||||
commit_message: Bump to version ${{ env.IMHEX_VERSION }}
|
commit_message: Bump to version ${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}
|
||||||
ssh_keyscan_types: rsa,ecdsa,ed25519
|
ssh_keyscan_types: rsa,ecdsa,ed25519
|
||||||
|
|
||||||
release-update-winget:
|
release-update-winget:
|
||||||
|
|
@ -161,6 +229,7 @@ jobs:
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
|
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
|
||||||
|
|
||||||
- name: ⬆️ Update winget manifest
|
- name: ⬆️ Update winget manifest
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
env:
|
env:
|
||||||
|
|
@ -193,7 +262,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
||||||
with:
|
with:
|
||||||
snap: imhex-${{ env.IMHEX_VERSION }}-x86_64.snap
|
snap: imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-x86_64.snap
|
||||||
release: stable
|
release: stable
|
||||||
|
|
||||||
- name: ⬆️ Publish arm64 Snap package
|
- name: ⬆️ Publish arm64 Snap package
|
||||||
|
|
@ -202,5 +271,5 @@ jobs:
|
||||||
env:
|
env:
|
||||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
||||||
with:
|
with:
|
||||||
snap: imhex-${{ env.IMHEX_VERSION }}-arm64.snap
|
snap: imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-arm64.snap
|
||||||
release: stable
|
release: stable
|
||||||
|
|
@ -1,33 +1,38 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
option(IMHEX_PLUGINS_IN_SHARE "Put the plugins in share/imhex/plugins instead of lib[..]/imhex/plugins (Linux only)" OFF)
|
## General
|
||||||
option(IMHEX_STRIP_RELEASE "Strip the release builds" ON )
|
option(IMHEX_STRIP_RELEASE "Strip the release builds" ON )
|
||||||
option(IMHEX_OFFLINE_BUILD "Enable offline build" OFF)
|
option(IMHEX_OFFLINE_BUILD "Enable offline build" OFF)
|
||||||
option(IMHEX_IGNORE_BAD_CLONE "Disable the bad clone prevention checks" OFF)
|
option(IMHEX_IGNORE_BAD_CLONE "Disable the bad clone prevention checks" OFF)
|
||||||
option(IMHEX_PATTERNS_PULL_MASTER "Download latest files from master branch of the ImHex-Patterns repo" OFF)
|
option(IMHEX_PATTERNS_PULL_MASTER "Download latest files from master branch of the ImHex-Patterns repo" OFF)
|
||||||
option(IMHEX_IGNORE_BAD_COMPILER "Allow compiling with an unsupported compiler" OFF)
|
option(IMHEX_IGNORE_BAD_COMPILER "Allow compiling with an unsupported compiler" OFF)
|
||||||
option(IMHEX_USE_GTK_FILE_PICKER "Use GTK file picker instead of xdg-desktop-portals (Linux only)" OFF)
|
option(IMHEX_USE_GTK_FILE_PICKER "Use GTK file picker instead of xdg-desktop-portals (Linux only)" OFF)
|
||||||
option(IMHEX_DISABLE_STACKTRACE "Disables support for printing stack traces" OFF)
|
|
||||||
option(IMHEX_BUNDLE_DOTNET "Bundle .NET runtime" ON )
|
option(IMHEX_BUNDLE_DOTNET "Bundle .NET runtime" ON )
|
||||||
option(IMHEX_ENABLE_LTO "Enables Link Time Optimizations if possible" OFF)
|
option(IMHEX_ENABLE_LTO "Enables Link Time Optimizations if possible" OFF)
|
||||||
option(IMHEX_USE_DEFAULT_BUILD_SETTINGS "Use default build settings" OFF)
|
option(IMHEX_USE_DEFAULT_BUILD_SETTINGS "Use default build settings" OFF)
|
||||||
option(IMHEX_STRICT_WARNINGS "Enable most available warnings and treat them as errors" ON )
|
|
||||||
option(IMHEX_BUILD_HARDENING "Enable hardening flags for build" ON )
|
option(IMHEX_BUILD_HARDENING "Enable hardening flags for build" ON )
|
||||||
option(IMHEX_STATIC_LINK_PLUGINS "Statically link all plugins into the main executable" OFF)
|
|
||||||
option(IMHEX_GENERATE_PACKAGE "Specify if a native package should be built. (Windows and MacOS only)" OFF)
|
option(IMHEX_GENERATE_PACKAGE "Specify if a native package should be built. (Windows and MacOS only)" OFF)
|
||||||
option(IMHEX_ENABLE_UNITY_BUILD "Enables building ImHex as a unity build." OFF)
|
option(IMHEX_ENABLE_UNITY_BUILD "Enables building ImHex as a unity build." OFF)
|
||||||
option(IMHEX_GENERATE_PDBS "Enable generating PDB files in non-debug builds (Windows only)" OFF)
|
|
||||||
option(IMHEX_REPLACE_DWARF_WITH_PDB "Remove DWARF information from binaries when generating PDBS (Windows only)" OFF)
|
|
||||||
option(IMHEX_ENABLE_STD_ASSERTS "Enable debug asserts in the C++ std library. (Breaks Plugin ABI!)" OFF)
|
|
||||||
option(IMHEX_ENABLE_UNIT_TESTS "Enable building unit tests" ON )
|
|
||||||
option(IMHEX_ENABLE_PLUGIN_TESTS "Enable building plugin tests" ON )
|
|
||||||
option(IMHEX_ENABLE_IMGUI_TEST_ENGINE "Enable the ImGui Test Engine" OFF)
|
|
||||||
option(IMHEX_ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF)
|
option(IMHEX_ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF)
|
||||||
option(IMHEX_COMPRESS_DEBUG_INFO "Compress debug information" ON )
|
|
||||||
option(IMHEX_ENABLE_CXX_MODULES "Enable C++20 Module compilation. Testing only!" OFF)
|
option(IMHEX_ENABLE_CXX_MODULES "Enable C++20 Module compilation. Testing only!" OFF)
|
||||||
option(IMHEX_ENABLE_CPPCHECK "Enable cppcheck static analysis" OFF)
|
option(IMHEX_ENABLE_CPPCHECK "Enable cppcheck static analysis" OFF)
|
||||||
option(IMHEX_BUNDLE_PLUGIN_SDK "Enable bundling of Plugin SDK into install package" ON )
|
option(IMHEX_BUNDLE_PLUGIN_SDK "Enable bundling of Plugin SDK into install package" ON )
|
||||||
|
## Testing
|
||||||
|
option(IMHEX_ENABLE_UNIT_TESTS "Enable building unit tests" ON )
|
||||||
|
option(IMHEX_ENABLE_IMGUI_TEST_ENGINE "Enable the ImGui Test Engine" OFF)
|
||||||
|
option(IMHEX_ENABLE_STD_ASSERTS "Enable debug asserts in the C++ std library. (Breaks Plugin ABI!)" OFF)
|
||||||
|
## Debug info
|
||||||
|
option(IMHEX_COMPRESS_DEBUG_INFO "Compress debug information" ON )
|
||||||
|
option(IMHEX_GENERATE_PDBS "Enable generating PDB files in non-debug builds (Windows only)" OFF)
|
||||||
|
option(IMHEX_REPLACE_DWARF_WITH_PDB "Remove DWARF information from binaries when generating PDBS (Windows only)" OFF)
|
||||||
|
option(IMHEX_STRICT_WARNINGS "Enable most available warnings and treat them as errors" ON )
|
||||||
|
option(IMHEX_DISABLE_STACKTRACE "Disables support for printing stack traces" OFF)
|
||||||
|
## Plugins
|
||||||
|
option(IMHEX_STATIC_LINK_PLUGINS "Statically link all plugins into the main executable" OFF)
|
||||||
|
option(IMHEX_ENABLE_PLUGIN_TESTS "Enable building plugin tests" ON )
|
||||||
|
option(IMHEX_INCLUDE_PLUGINS "Semicolon-separated list of plugins to include in the build (empty = build all)" "" )
|
||||||
|
option(IMHEX_EXCLUDE_PLUGINS "Semicolon-separated list of plugins to exclude from the build" "" )
|
||||||
|
|
||||||
set(IMHEX_BASE_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}")
|
set(IMHEX_BASE_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
set(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules")
|
set(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules")
|
||||||
|
|
|
||||||
|
|
@ -175,15 +175,11 @@ macro(detectOS)
|
||||||
endif()
|
endif()
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
if(IMHEX_PLUGINS_IN_SHARE)
|
|
||||||
set(PLUGINS_INSTALL_LOCATION "share/imhex/plugins")
|
|
||||||
else()
|
|
||||||
set(PLUGINS_INSTALL_LOCATION "${CMAKE_INSTALL_LIBDIR}/imhex/plugins")
|
set(PLUGINS_INSTALL_LOCATION "${CMAKE_INSTALL_LIBDIR}/imhex/plugins")
|
||||||
|
|
||||||
# Add System plugin location for plugins to be loaded from
|
# Add System plugin location for plugins to be loaded from
|
||||||
# IMPORTANT: This does not work for Sandboxed or portable builds such as the Flatpak or AppImage release
|
# IMPORTANT: This does not work for Sandboxed or portable builds such as the Flatpak or AppImage release
|
||||||
add_compile_definitions(SYSTEM_PLUGINS_LOCATION="${CMAKE_INSTALL_FULL_LIBDIR}/imhex")
|
add_compile_definitions(SYSTEM_PLUGINS_LOCATION="${CMAKE_INSTALL_FULL_LIBDIR}/imhex")
|
||||||
endif()
|
|
||||||
|
|
||||||
else ()
|
else ()
|
||||||
message(FATAL_ERROR "Unknown / unsupported system!")
|
message(FATAL_ERROR "Unknown / unsupported system!")
|
||||||
|
|
@ -205,11 +201,14 @@ macro(configurePackingResources)
|
||||||
set(CPACK_GENERATOR "WIX")
|
set(CPACK_GENERATOR "WIX")
|
||||||
set(CPACK_PACKAGE_NAME "ImHex")
|
set(CPACK_PACKAGE_NAME "ImHex")
|
||||||
set(CPACK_PACKAGE_VENDOR "WerWolv")
|
set(CPACK_PACKAGE_VENDOR "WerWolv")
|
||||||
|
set(CPACK_WIX_VERSION 4)
|
||||||
set(CPACK_WIX_UPGRADE_GUID "05000E99-9659-42FD-A1CF-05C554B39285")
|
set(CPACK_WIX_UPGRADE_GUID "05000E99-9659-42FD-A1CF-05C554B39285")
|
||||||
set(CPACK_WIX_PRODUCT_ICON "${PROJECT_SOURCE_DIR}/resources/dist/windows/icon.ico")
|
set(CPACK_WIX_PRODUCT_ICON "${PROJECT_SOURCE_DIR}/resources/dist/windows/icon.ico")
|
||||||
set(CPACK_WIX_UI_BANNER "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_banner.png")
|
set(CPACK_WIX_UI_BANNER "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_banner.png")
|
||||||
set(CPACK_WIX_UI_DIALOG "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_dialog.png")
|
set(CPACK_WIX_UI_DIALOG "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_dialog.png")
|
||||||
set(CPACK_WIX_CULTURES "en-US;de-DE;ja-JP;it-IT;pt-BR;zh-CN;zh-TW;ru-RU")
|
set(CPACK_WIX_CULTURES "en-US;de-DE;ja-JP;it-IT;pt-BR;zh-CN;zh-TW;ru-RU")
|
||||||
|
set(CPACK_WIX_PATCH_FILE "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_patch.xml")
|
||||||
|
|
||||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "ImHex")
|
set(CPACK_PACKAGE_INSTALL_DIRECTORY "ImHex")
|
||||||
set_property(INSTALL "$<TARGET_FILE_NAME:main>"
|
set_property(INSTALL "$<TARGET_FILE_NAME:main>"
|
||||||
PROPERTY CPACK_START_MENU_SHORTCUTS "ImHex"
|
PROPERTY CPACK_START_MENU_SHORTCUTS "ImHex"
|
||||||
|
|
@ -312,7 +311,7 @@ macro(createPackage)
|
||||||
POST_EXCLUDE_REGEXES ".*system32/.*\\.dll"
|
POST_EXCLUDE_REGEXES ".*system32/.*\\.dll"
|
||||||
)
|
)
|
||||||
|
|
||||||
if(_c_deps_FILENAMES AND NOT _c_deps STREQUAL "")
|
if(_c_deps_FILENAMES AND _c_deps AND NOT (_c_deps STREQUAL ""))
|
||||||
message(WARNING "Conflicting dependencies for library: \"${_c_deps}\"!")
|
message(WARNING "Conflicting dependencies for library: \"${_c_deps}\"!")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
@ -587,7 +586,9 @@ endfunction()
|
||||||
macro(detectBundledPlugins)
|
macro(detectBundledPlugins)
|
||||||
file(GLOB PLUGINS_DIRS "plugins/*")
|
file(GLOB PLUGINS_DIRS "plugins/*")
|
||||||
|
|
||||||
if (NOT DEFINED IMHEX_INCLUDE_PLUGINS)
|
if (IMHEX_INCLUDE_PLUGINS)
|
||||||
|
set(PLUGINS ${IMHEX_INCLUDE_PLUGINS})
|
||||||
|
else()
|
||||||
foreach(PLUGIN_DIR ${PLUGINS_DIRS})
|
foreach(PLUGIN_DIR ${PLUGINS_DIRS})
|
||||||
if (EXISTS "${PLUGIN_DIR}/CMakeLists.txt")
|
if (EXISTS "${PLUGIN_DIR}/CMakeLists.txt")
|
||||||
get_filename_component(PLUGIN_NAME ${PLUGIN_DIR} NAME)
|
get_filename_component(PLUGIN_NAME ${PLUGIN_DIR} NAME)
|
||||||
|
|
@ -596,8 +597,6 @@ macro(detectBundledPlugins)
|
||||||
endif ()
|
endif ()
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
else()
|
|
||||||
set(PLUGINS ${IMHEX_INCLUDE_PLUGINS})
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
foreach(PLUGIN_NAME ${PLUGINS})
|
foreach(PLUGIN_NAME ${PLUGINS})
|
||||||
|
|
@ -608,9 +607,13 @@ macro(detectBundledPlugins)
|
||||||
message(FATAL_ERROR "No bundled plugins enabled")
|
message(FATAL_ERROR "No bundled plugins enabled")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT ("builtin" IN_LIST PLUGINS))
|
set(REQUIRED_PLUGINS builtin fonts ui)
|
||||||
message(FATAL_ERROR "The 'builtin' plugin is required for ImHex to work!")
|
foreach(PLUGIN ${REQUIRED_PLUGINS})
|
||||||
endif ()
|
list(FIND PLUGINS ${PLUGIN} PLUGIN_INDEX)
|
||||||
|
if (PLUGIN_INDEX EQUAL -1)
|
||||||
|
message(FATAL_ERROR "Required plugin '${PLUGIN}' is not enabled!")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
macro(setVariableInParent variable value)
|
macro(setVariableInParent variable value)
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ AppDir:
|
||||||
- "{{ARCHITECTURE_PACKAGE}}"
|
- "{{ARCHITECTURE_PACKAGE}}"
|
||||||
allow_unauthenticated: true
|
allow_unauthenticated: true
|
||||||
sources:
|
sources:
|
||||||
- sourceline: 'deb [arch=amd64] http://us.archive.ubuntu.com/ubuntu/ noble main restricted universe multiverse'
|
- sourceline: 'deb [arch=amd64] https://us.archive.ubuntu.com/ubuntu/ noble main restricted universe multiverse'
|
||||||
- sourceline: 'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ noble main restricted universe multiverse'
|
- sourceline: 'deb [arch=arm64] https://ports.ubuntu.com/ubuntu-ports/ noble main restricted universe multiverse'
|
||||||
include:
|
include:
|
||||||
- libgdk-pixbuf2.0-0
|
- libgdk-pixbuf2.0-0
|
||||||
- libgdk-pixbuf2.0-common
|
- libgdk-pixbuf2.0-common
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@ ARG LTO=ON
|
||||||
ARG BUILD_TYPE=RelWithDebInfo
|
ARG BUILD_TYPE=RelWithDebInfo
|
||||||
ARG GIT_COMMIT_HASH
|
ARG GIT_COMMIT_HASH
|
||||||
ARG GIT_BRANCH
|
ARG GIT_BRANCH
|
||||||
ARG ARCHITECTURE_PACKAGE
|
ARG ARCHITECTURE_PACKAGE=x86_64
|
||||||
ARG ARCHITECTURE_FILE_NAME
|
ARG ARCHITECTURE_FILE_NAME=amd64
|
||||||
ARG ARCHITECTURE_APPIMAGE_BUILDER
|
ARG ARCHITECTURE_APPIMAGE_BUILDER=x86_64
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
|
|
||||||
# Ubuntu sh doesnt support string substitution
|
# Ubuntu sh doesnt support string substitution
|
||||||
|
|
@ -51,7 +51,9 @@ CC=gcc-14 CXX=g++-14 cmake -G "Ninja" \
|
||||||
-DIMHEX_COMMIT_HASH_LONG="${GIT_COMMIT_HASH}" \
|
-DIMHEX_COMMIT_HASH_LONG="${GIT_COMMIT_HASH}" \
|
||||||
-DIMHEX_COMMIT_BRANCH="${GIT_BRANCH}" \
|
-DIMHEX_COMMIT_BRANCH="${GIT_BRANCH}" \
|
||||||
-DIMHEX_ENABLE_LTO=${LTO} \
|
-DIMHEX_ENABLE_LTO=${LTO} \
|
||||||
-DIMHEX_PLUGINS_IN_SHARE=ON \
|
-DIMHEX_BUNDLE_PLUGIN_SDK=OFF \
|
||||||
|
`# To prevent using a libdir with an architecture-specific name` \
|
||||||
|
-DCMAKE_INSTALL_LIBDIR="lib" \
|
||||||
/imhex
|
/imhex
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ Section: editors
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Architecture: amd64
|
Architecture: amd64
|
||||||
License: GNU GPL-2
|
License: GNU GPL-2
|
||||||
Depends: libfontconfig1, libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal, libssh2-1, md4c
|
Depends: libfontconfig1, libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal, libssh2-1, libmd4c0
|
||||||
Maintainer: WerWolv <hey@werwolv.net>
|
Maintainer: WerWolv <hey@werwolv.net>
|
||||||
Description: ImHex Hex Editor
|
Description: ImHex Hex Editor
|
||||||
A Hex Editor for Reverse Engineers, Programmers and
|
A Hex Editor for Reverse Engineers, Programmers and
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="ImHex" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" WORKING_DIR="file://$CMakeCurrentBuildDir$" PASS_PARENT_ENVS_2="true" PROJECT_NAME="ImHex" TARGET_NAME="imhex_all" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="ImHex" RUN_TARGET_NAME="main">
|
<configuration default="false" name="ImHex" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS=".ninja_log" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" WORKING_DIR="file://$CMakeCurrentBuildDir$" PASS_PARENT_ENVS_2="true" PROJECT_NAME="ImHex" TARGET_NAME="imhex_all" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="ImHex" RUN_TARGET_NAME="main">
|
||||||
<envs>
|
<envs>
|
||||||
<env name="NO_DEBUG_BANNER" value="1" />
|
<env name="NO_DEBUG_BANNER" value="1" />
|
||||||
</envs>
|
</envs>
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,7 @@ modules:
|
||||||
- -DUSE_SYSTEM_FMT=ON
|
- -DUSE_SYSTEM_FMT=ON
|
||||||
- -DUSE_SYSTEM_YARA=ON
|
- -DUSE_SYSTEM_YARA=ON
|
||||||
- -DIMHEX_OFFLINE_BUILD=ON
|
- -DIMHEX_OFFLINE_BUILD=ON
|
||||||
|
- -DIMHEX_BUNDLE_PLUGIN_SDK=OFF
|
||||||
- -DCMAKE_INSTALL_LIBDIR=lib
|
- -DCMAKE_INSTALL_LIBDIR=lib
|
||||||
- -DCMAKE_INSTALL_RPATH='$ORIGIN/../lib:$ORIGIN/../lib64'
|
- -DCMAKE_INSTALL_RPATH='$ORIGIN/../lib:$ORIGIN/../lib64'
|
||||||
sources:
|
sources:
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ parts:
|
||||||
- -DCMAKE_C_COMPILER_LAUNCHER=${CCACHE}
|
- -DCMAKE_C_COMPILER_LAUNCHER=${CCACHE}
|
||||||
- -DCMAKE_CXX_COMPILER_LAUNCHER=${CCACHE}
|
- -DCMAKE_CXX_COMPILER_LAUNCHER=${CCACHE}
|
||||||
- -DIMHEX_PATTERNS_PULL_MASTER=ON
|
- -DIMHEX_PATTERNS_PULL_MASTER=ON
|
||||||
|
- -DIMHEX_BUNDLE_PLUGIN_SDK=OFF
|
||||||
cmake-generator: Ninja
|
cmake-generator: Ninja
|
||||||
build-packages:
|
build-packages:
|
||||||
- cmake
|
- cmake
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ FROM emscripten/emsdk:4.0.21 AS build
|
||||||
|
|
||||||
# Used to invalidate layer cache but not mount cache
|
# Used to invalidate layer cache but not mount cache
|
||||||
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493
|
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493
|
||||||
ARG UNIQUEKEY 1
|
ARG UNIQUEKEY=1
|
||||||
|
|
||||||
RUN apt update
|
RUN apt update
|
||||||
RUN apt install -y git ccache autoconf automake libtool pkg-config ninja-build
|
RUN apt install -y git ccache autoconf automake libtool pkg-config ninja-build
|
||||||
|
|
@ -12,13 +12,13 @@ RUN <<EOF
|
||||||
# Note: we are a patch on the libmagic port
|
# Note: we are a patch on the libmagic port
|
||||||
set -xe
|
set -xe
|
||||||
|
|
||||||
git clone https://github.com/microsoft/vcpkg /vcpkg
|
git clone --depth 1 https://github.com/microsoft/vcpkg /vcpkg
|
||||||
git -C /vcpkg pull
|
|
||||||
/vcpkg/bootstrap-vcpkg.sh
|
/vcpkg/bootstrap-vcpkg.sh
|
||||||
sed -i 's/vcpkg_install_make(${EXTRA_ARGS})/vcpkg_install_make(${EXTRA_ARGS} SUBPATH src)/g' /vcpkg/ports/libmagic/portfile.cmake
|
sed -i 's/vcpkg_install_make(${EXTRA_ARGS})/vcpkg_install_make(${EXTRA_ARGS} SUBPATH src)/g' /vcpkg/ports/libmagic/portfile.cmake
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Patch vcpkg build instructions to add -pthread
|
# Patch vcpkg build instructions to add -pthread flag
|
||||||
|
# Even dependencies must be built with -pthread to be able to use USE_PTHREADS=1
|
||||||
RUN <<EOF
|
RUN <<EOF
|
||||||
set -xe
|
set -xe
|
||||||
|
|
||||||
|
|
@ -50,6 +50,7 @@ ENV CCACHE_DIR=/cache/ccache
|
||||||
|
|
||||||
RUN mkdir /build
|
RUN mkdir /build
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
|
ARG BUILD_TYPE=Release
|
||||||
RUN --mount=type=cache,target=/cache \
|
RUN --mount=type=cache,target=/cache \
|
||||||
--mount=type=bind,source=.,target=/imhex <<EOF
|
--mount=type=bind,source=.,target=/imhex <<EOF
|
||||||
|
|
||||||
|
|
@ -70,7 +71,7 @@ ccache -zs
|
||||||
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
|
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
|
||||||
-DLIBROMFS_COMPRESS_RESOURCES=OFF \
|
-DLIBROMFS_COMPRESS_RESOURCES=OFF \
|
||||||
-DIMHEX_ENABLE_PLUGIN_TESTS=OFF \
|
-DIMHEX_ENABLE_PLUGIN_TESTS=OFF \
|
||||||
-DCMAKE_BUILD_TYPE=Release
|
-DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
||||||
|
|
||||||
ninja -j $JOBS
|
ninja -j $JOBS
|
||||||
|
|
||||||
|
|
@ -106,3 +107,4 @@ COPY --from=build [ \
|
||||||
|
|
||||||
FROM nginx
|
FROM nginx
|
||||||
COPY --from=raw . /usr/share/nginx/html
|
COPY --from=raw . /usr/share/nginx/html
|
||||||
|
RUN chmod -R 755 /usr/share/nginx/html
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
# docker compose -f dist/web/compose.yml up --build
|
# docker compose -f dist/web/compose.yml up --build
|
||||||
version: '3'
|
|
||||||
services:
|
services:
|
||||||
imhex_web:
|
imhex_web:
|
||||||
image: imhex_web:latest
|
image: imhex_web:latest
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 5be84628dc4d7da6281c943888497f8b886b7f5a
|
Subproject commit b0c9416568475a784838e3af8b0021a542e47cd7
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 33057885fdb8802245260e8b8de4eecf1819dc60
|
Subproject commit a06da46a3cf1694ccc785d21a37a2dca08deb56a
|
||||||
|
|
@ -57,6 +57,9 @@ set(LIBIMHEX_SOURCES
|
||||||
source/ui/toast.cpp
|
source/ui/toast.cpp
|
||||||
source/ui/banner.cpp
|
source/ui/banner.cpp
|
||||||
|
|
||||||
|
source/mcp/client.cpp
|
||||||
|
source/mcp/server.cpp
|
||||||
|
|
||||||
source/subcommands/subcommands.cpp
|
source/subcommands/subcommands.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <hex/mcp/server.hpp>
|
||||||
|
|
||||||
EXPORT_MODULE namespace hex {
|
EXPORT_MODULE namespace hex {
|
||||||
|
|
||||||
/* Network Communication Interface Registry. Allows adding new communication interface endpoints */
|
/* Network Communication Interface Registry. Allows adding new communication interface endpoints */
|
||||||
|
|
@ -22,4 +24,19 @@ EXPORT_MODULE namespace hex {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ContentRegistry::MCP {
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
mcp::Server& getMcpServerInstance();
|
||||||
|
|
||||||
|
void setEnabled(bool enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEnabled();
|
||||||
|
bool isConnected();
|
||||||
|
|
||||||
|
void registerTool(std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json ¶ms)> function);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <bit>
|
||||||
|
|
||||||
EXPORT_MODULE namespace hex {
|
EXPORT_MODULE namespace hex {
|
||||||
|
|
||||||
|
|
@ -22,8 +23,10 @@ EXPORT_MODULE namespace hex {
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
|
struct DoNotUseThisByItselfTag {};
|
||||||
|
|
||||||
using DisplayFunction = std::function<std::string()>;
|
using DisplayFunction = std::function<std::string()>;
|
||||||
using EditingFunction = std::function<std::vector<u8>(std::string, std::endian)>;
|
using EditingFunction = std::function<std::optional<std::vector<u8>>(std::string&, std::endian, DoNotUseThisByItselfTag)>;
|
||||||
using GeneratorFunction = std::function<DisplayFunction(const std::vector<u8> &, std::endian, NumberDisplayStyle)>;
|
using GeneratorFunction = std::function<DisplayFunction(const std::vector<u8> &, std::endian, NumberDisplayStyle)>;
|
||||||
|
|
||||||
struct Entry {
|
struct Entry {
|
||||||
|
|
@ -38,6 +41,35 @@ EXPORT_MODULE namespace hex {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace EditWidget {
|
||||||
|
|
||||||
|
class Widget {
|
||||||
|
public:
|
||||||
|
using Function = std::function<std::vector<u8>(const std::string&, std::endian)>;
|
||||||
|
|
||||||
|
explicit Widget(const Function &function) : m_function(function) {}
|
||||||
|
|
||||||
|
virtual ~Widget() = default;
|
||||||
|
virtual std::optional<std::vector<u8>> draw(std::string &value, std::endian endian) = 0;
|
||||||
|
std::optional<std::vector<u8>> operator()(std::string &value, std::endian endian, impl::DoNotUseThisByItselfTag) {
|
||||||
|
return draw(value, endian);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<u8> getBytes(const std::string &value, std::endian endian) const {
|
||||||
|
return m_function(value, endian);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Function m_function;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TextInput : Widget {
|
||||||
|
explicit TextInput(const Function &function) : Widget(function) {}
|
||||||
|
std::optional<std::vector<u8>> draw(std::string &value, std::endian endian) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adds a new entry to the data inspector
|
* @brief Adds a new entry to the data inspector
|
||||||
* @param unlocalizedName The unlocalized name of the entry
|
* @param unlocalizedName The unlocalized name of the entry
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ EXPORT_MODULE namespace hex {
|
||||||
|
|
||||||
void addProviderName(const UnlocalizedString &unlocalizedName, const char *icon);
|
void addProviderName(const UnlocalizedString &unlocalizedName, const char *icon);
|
||||||
|
|
||||||
using ProviderCreationFunction = std::function<std::unique_ptr<prv::Provider>()>;
|
using ProviderCreationFunction = std::function<std::shared_ptr<prv::Provider>()>;
|
||||||
void add(const std::string &typeName, ProviderCreationFunction creationFunction);
|
void add(const std::string &typeName, ProviderCreationFunction creationFunction);
|
||||||
|
|
||||||
struct Entry {
|
struct Entry {
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,14 @@ EXPORT_MODULE namespace hex {
|
||||||
nlohmann::json store() override { return {}; }
|
nlohmann::json store() override { return {}; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Spacer : public Widget {
|
||||||
|
public:
|
||||||
|
bool draw(const std::string &name) override;
|
||||||
|
|
||||||
|
void load(const nlohmann::json &) override {}
|
||||||
|
nlohmann::json store() override { return {}; }
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace hex {
|
||||||
* This event is responsible for (optionally) initializing the provider and calling EventProviderOpened
|
* This event is responsible for (optionally) initializing the provider and calling EventProviderOpened
|
||||||
* (although the event can also be called manually without problem)
|
* (although the event can also be called manually without problem)
|
||||||
*/
|
*/
|
||||||
EVENT_DEF(EventProviderCreated, prv::Provider *);
|
EVENT_DEF(EventProviderCreated, std::shared_ptr<prv::Provider>);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called as a continuation of EventProviderCreated
|
* @brief Called as a continuation of EventProviderCreated
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,12 @@ namespace hex {
|
||||||
/**
|
/**
|
||||||
* @brief Creates a provider from its unlocalized name, and add it to the provider list
|
* @brief Creates a provider from its unlocalized name, and add it to the provider list
|
||||||
*/
|
*/
|
||||||
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, hex::prv::Provider **);
|
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, std::shared_ptr<hex::prv::Provider> *);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Used internally when opening a provider through the API
|
||||||
|
*/
|
||||||
|
EVENT_DEF(RequestOpenProvider, std::shared_ptr<prv::Provider>);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Move the data from all PerProvider instances from one provider to another
|
* @brief Move the data from all PerProvider instances from one provider to another
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ EXPORT_MODULE namespace hex {
|
||||||
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
|
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
|
||||||
* @param select Whether to select the provider after adding it
|
* @param select Whether to select the provider after adding it
|
||||||
*/
|
*/
|
||||||
void add(std::unique_ptr<prv::Provider> &&provider, bool skipLoadInterface = false, bool select = true);
|
void add(std::shared_ptr<prv::Provider> &&provider, bool skipLoadInterface = false, bool select = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new provider and adds it to the list of providers
|
* @brief Creates a new provider and adds it to the list of providers
|
||||||
|
|
@ -111,12 +111,18 @@ EXPORT_MODULE namespace hex {
|
||||||
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
|
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
|
||||||
* @param select Whether to select the provider after adding it
|
* @param select Whether to select the provider after adding it
|
||||||
*/
|
*/
|
||||||
prv::Provider* createProvider(
|
std::shared_ptr<prv::Provider> createProvider(
|
||||||
const UnlocalizedString &unlocalizedName,
|
const UnlocalizedString &unlocalizedName,
|
||||||
bool skipLoadInterface = false,
|
bool skipLoadInterface = false,
|
||||||
bool select = true
|
bool select = true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Opens a provider, making its data available to ImHex and handling any error that may occur
|
||||||
|
* @param provider The provider to open
|
||||||
|
*/
|
||||||
|
void openProvider(std::shared_ptr<prv::Provider> provider);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <source_location>
|
#include <source_location>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <hex/trace/exceptions.hpp>
|
||||||
|
|
||||||
EXPORT_MODULE namespace hex {
|
EXPORT_MODULE namespace hex {
|
||||||
|
|
||||||
|
|
@ -94,7 +95,12 @@ EXPORT_MODULE namespace hex {
|
||||||
std::atomic_flag m_hadException;
|
std::atomic_flag m_hadException;
|
||||||
std::string m_exceptionMessage;
|
std::string m_exceptionMessage;
|
||||||
|
|
||||||
struct TaskInterruptor { virtual ~TaskInterruptor() = default; };
|
struct TaskInterruptor {
|
||||||
|
TaskInterruptor() {
|
||||||
|
trace::disableExceptionCaptureForCurrentThread();
|
||||||
|
}
|
||||||
|
virtual ~TaskInterruptor() = default;
|
||||||
|
};
|
||||||
|
|
||||||
friend class TaskHolder;
|
friend class TaskHolder;
|
||||||
friend class TaskManager;
|
friend class TaskManager;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ EXPORT_MODULE namespace hex {
|
||||||
Right = 8
|
Right = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using DrawFunction = std::function<void()>;
|
||||||
|
|
||||||
struct Tutorial {
|
struct Tutorial {
|
||||||
Tutorial() = delete;
|
Tutorial() = delete;
|
||||||
Tutorial(const UnlocalizedString &unlocalizedName, const UnlocalizedString &unlocalizedDescription) :
|
Tutorial(const UnlocalizedString &unlocalizedName, const UnlocalizedString &unlocalizedDescription) :
|
||||||
|
|
@ -101,6 +103,7 @@ EXPORT_MODULE namespace hex {
|
||||||
std::vector<Highlight> m_highlights;
|
std::vector<Highlight> m_highlights;
|
||||||
std::optional<Message> m_message;
|
std::optional<Message> m_message;
|
||||||
std::function<void()> m_onAppear, m_onComplete;
|
std::function<void()> m_onAppear, m_onComplete;
|
||||||
|
DrawFunction m_drawFunction;
|
||||||
};
|
};
|
||||||
|
|
||||||
Step& addStep();
|
Step& addStep();
|
||||||
|
|
@ -166,6 +169,8 @@ EXPORT_MODULE namespace hex {
|
||||||
*/
|
*/
|
||||||
static void reset();
|
static void reset();
|
||||||
|
|
||||||
|
static void setRenderer(std::function<DrawFunction(const std::string &)> renderer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TutorialManager() = delete;
|
TutorialManager() = delete;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,10 @@
|
||||||
static_assert(false, "Debug variables are only intended for use during development.");
|
static_assert(false, "Debug variables are only intended for use during development.");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace hex::trace {
|
||||||
|
struct StackTraceResult;
|
||||||
|
}
|
||||||
|
|
||||||
namespace hex::dbg {
|
namespace hex::dbg {
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
@ -47,4 +51,6 @@ namespace hex::dbg {
|
||||||
bool debugModeEnabled();
|
bool debugModeEnabled();
|
||||||
void setDebugModeEnabled(bool enabled);
|
void setDebugModeEnabled(bool enabled);
|
||||||
|
|
||||||
|
void printStackTrace(const trace::StackTraceResult &stackTrace);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace hex::mcp {
|
||||||
|
|
||||||
|
class Client {
|
||||||
|
public:
|
||||||
|
Client() = default;
|
||||||
|
~Client() = default;
|
||||||
|
|
||||||
|
int run(std::istream &input, std::ostream &output);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <wolv/net/socket_server.hpp>
|
||||||
|
|
||||||
|
namespace hex::mcp {
|
||||||
|
|
||||||
|
class Server {
|
||||||
|
public:
|
||||||
|
constexpr static auto McpInternalPort = 19743;
|
||||||
|
|
||||||
|
Server();
|
||||||
|
~Server();
|
||||||
|
|
||||||
|
void listen();
|
||||||
|
void shutdown();
|
||||||
|
void disconnect();
|
||||||
|
bool isConnected();
|
||||||
|
|
||||||
|
void addPrimitive(std::string type, std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json ¶ms)> function);
|
||||||
|
|
||||||
|
private:
|
||||||
|
nlohmann::json handleInitialize();
|
||||||
|
void handleNotifications(const std::string &method, const nlohmann::json ¶ms);
|
||||||
|
|
||||||
|
struct Primitive {
|
||||||
|
nlohmann::json capabilities;
|
||||||
|
std::function<nlohmann::json(const nlohmann::json ¶ms)> function;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<std::string, std::map<std::string, Primitive>> m_primitives;
|
||||||
|
|
||||||
|
wolv::net::SocketServer m_server;
|
||||||
|
bool m_connected = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -21,7 +21,7 @@ namespace hex::prv {
|
||||||
CachedProvider(size_t cacheBlockSize = 4096, size_t maxBlocks = 1024);
|
CachedProvider(size_t cacheBlockSize = 4096, size_t maxBlocks = 1024);
|
||||||
~CachedProvider() override;
|
~CachedProvider() override;
|
||||||
|
|
||||||
bool open() override;
|
OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace hex::prv {
|
||||||
[[nodiscard]] bool isSavable() const override { return m_name.empty(); }
|
[[nodiscard]] bool isSavable() const override { return m_name.empty(); }
|
||||||
[[nodiscard]] bool isSavableAsRecent() const override { return false; }
|
[[nodiscard]] bool isSavableAsRecent() const override { return false; }
|
||||||
|
|
||||||
[[nodiscard]] bool open() override;
|
[[nodiscard]] OpenResult open() override;
|
||||||
void close() override { }
|
void close() override { }
|
||||||
|
|
||||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,21 @@ namespace hex::prv {
|
||||||
[[nodiscard]] virtual std::vector<Description> getDataDescription() const = 0;
|
[[nodiscard]] virtual std::vector<Description> getDataDescription() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class IProviderDataBackupable {
|
||||||
|
public:
|
||||||
|
explicit IProviderDataBackupable(Provider *provider);
|
||||||
|
virtual ~IProviderDataBackupable() = default;
|
||||||
|
|
||||||
|
void createBackupIfNeeded(const std::fs::path &inputFilePath);
|
||||||
|
private:
|
||||||
|
Provider *m_provider = nullptr;
|
||||||
|
bool m_backupCreated = false;
|
||||||
|
|
||||||
|
bool m_shouldCreateBackups = true;
|
||||||
|
u64 m_maxSize;
|
||||||
|
std::string m_backupExtension;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Represent the data source for a tab in the UI
|
* @brief Represent the data source for a tab in the UI
|
||||||
*/
|
*/
|
||||||
|
|
@ -79,6 +94,65 @@ namespace hex::prv {
|
||||||
public:
|
public:
|
||||||
constexpr static u64 MaxPageSize = 0xFFFF'FFFF'FFFF'FFFF;
|
constexpr static u64 MaxPageSize = 0xFFFF'FFFF'FFFF'FFFF;
|
||||||
|
|
||||||
|
class OpenResult {
|
||||||
|
public:
|
||||||
|
OpenResult() : m_result(std::monostate{}) {}
|
||||||
|
|
||||||
|
[[nodiscard]] static OpenResult failure(std::string errorMessage) {
|
||||||
|
OpenResult result;
|
||||||
|
result.m_result = std::move(errorMessage);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static OpenResult warning(std::string warningMessage) {
|
||||||
|
OpenResult result;
|
||||||
|
result.m_result = std::move(warningMessage);
|
||||||
|
result.m_warning = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static OpenResult redirect(Provider *provider) {
|
||||||
|
OpenResult result;
|
||||||
|
result.m_result = provider;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool isSuccess() const {
|
||||||
|
return std::holds_alternative<std::monostate>(m_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool isFailure() const {
|
||||||
|
return std::holds_alternative<std::string>(m_result) && !m_warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool isWarning() const {
|
||||||
|
return std::holds_alternative<std::string>(m_result) && m_warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool isRedirecting() const {
|
||||||
|
return std::holds_alternative<Provider*>(m_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Provider* getRedirectProvider() const {
|
||||||
|
if (std::holds_alternative<Provider*>(m_result)) {
|
||||||
|
return std::get<Provider*>(m_result);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::string_view getErrorMessage() const {
|
||||||
|
if (std::holds_alternative<std::string>(m_result)) {
|
||||||
|
return std::get<std::string>(m_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::variant<std::monostate, std::string, Provider*> m_result;
|
||||||
|
bool m_warning = false;
|
||||||
|
};
|
||||||
|
|
||||||
Provider();
|
Provider();
|
||||||
virtual ~Provider();
|
virtual ~Provider();
|
||||||
Provider(const Provider&) = delete;
|
Provider(const Provider&) = delete;
|
||||||
|
|
@ -94,7 +168,7 @@ namespace hex::prv {
|
||||||
* @note This is not related to the EventProviderOpened event
|
* @note This is not related to the EventProviderOpened event
|
||||||
* @return true if the provider was opened successfully, else false
|
* @return true if the provider was opened successfully, else false
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] virtual bool open() = 0;
|
[[nodiscard]] virtual OpenResult open() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Closes this provider
|
* @brief Closes this provider
|
||||||
|
|
@ -262,9 +336,6 @@ namespace hex::prv {
|
||||||
void skipLoadInterface() { m_skipLoadInterface = true; }
|
void skipLoadInterface() { m_skipLoadInterface = true; }
|
||||||
[[nodiscard]] bool shouldSkipLoadInterface() const { return m_skipLoadInterface; }
|
[[nodiscard]] bool shouldSkipLoadInterface() const { return m_skipLoadInterface; }
|
||||||
|
|
||||||
void setErrorMessage(const std::string &errorMessage) { m_errorMessage = errorMessage; }
|
|
||||||
[[nodiscard]] const std::string& getErrorMessage() const { return m_errorMessage; }
|
|
||||||
|
|
||||||
template<std::derived_from<undo::Operation> T>
|
template<std::derived_from<undo::Operation> T>
|
||||||
bool addUndoableOperation(auto && ... args) {
|
bool addUndoableOperation(auto && ... args) {
|
||||||
return m_undoRedoStack.add<T>(std::forward<decltype(args)...>(args)...);
|
return m_undoRedoStack.add<T>(std::forward<decltype(args)...>(args)...);
|
||||||
|
|
@ -296,8 +367,6 @@ namespace hex::prv {
|
||||||
*/
|
*/
|
||||||
bool m_skipLoadInterface = false;
|
bool m_skipLoadInterface = false;
|
||||||
|
|
||||||
std::string m_errorMessage = "Unspecified error";
|
|
||||||
|
|
||||||
u64 m_pageSize = MaxPageSize;
|
u64 m_pageSize = MaxPageSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -319,6 +319,7 @@ namespace ImGuiExt {
|
||||||
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
|
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
|
||||||
bool DimmedIconToggle(const char *icon, bool *v);
|
bool DimmedIconToggle(const char *icon, bool *v);
|
||||||
bool DimmedIconToggle(const char *iconOn, const char *iconOff, bool *v);
|
bool DimmedIconToggle(const char *iconOn, const char *iconOff, bool *v);
|
||||||
|
bool DimmedArrowButton(const char *id, ImGuiDir dir, ImVec2 size = ImVec2(ImGui::GetFrameHeight(), ImGui::GetFrameHeight()));
|
||||||
|
|
||||||
void TextOverlay(const char *text, ImVec2 pos, float maxWidth = -1);
|
void TextOverlay(const char *text, ImVec2 pos, float maxWidth = -1);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <hex/api/tutorial_manager.hpp>
|
|
||||||
|
|
||||||
namespace hex {
|
namespace hex {
|
||||||
|
|
||||||
|
|
@ -27,7 +26,7 @@ namespace hex {
|
||||||
* @brief Draws the view
|
* @brief Draws the view
|
||||||
* @note Do not override this method. Override drawContent() instead
|
* @note Do not override this method. Override drawContent() instead
|
||||||
*/
|
*/
|
||||||
virtual void draw() = 0;
|
virtual void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Draws the content of the view
|
* @brief Draws the content of the view
|
||||||
|
|
@ -126,6 +125,7 @@ namespace hex {
|
||||||
class Window;
|
class Window;
|
||||||
class Special;
|
class Special;
|
||||||
class Floating;
|
class Floating;
|
||||||
|
class Scrolling;
|
||||||
class Modal;
|
class Modal;
|
||||||
class FullScreen;
|
class FullScreen;
|
||||||
|
|
||||||
|
|
@ -153,16 +153,10 @@ namespace hex {
|
||||||
*/
|
*/
|
||||||
virtual void drawHelpText() = 0;
|
virtual void drawHelpText() = 0;
|
||||||
|
|
||||||
void draw() final {
|
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) override;
|
||||||
if (this->shouldDraw()) {
|
|
||||||
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
virtual bool allowScroll() const {
|
||||||
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
|
return false;
|
||||||
if (ImGui::Begin(title.c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse | this->getWindowFlags())) {
|
|
||||||
TutorialManager::setLastItemInteractiveHelpPopup([this]{ this->drawHelpText(); });
|
|
||||||
this->drawContent();
|
|
||||||
}
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -174,12 +168,7 @@ namespace hex {
|
||||||
public:
|
public:
|
||||||
explicit Special(UnlocalizedString unlocalizedName) : View(std::move(unlocalizedName), "") {}
|
explicit Special(UnlocalizedString unlocalizedName) : View(std::move(unlocalizedName), "") {}
|
||||||
|
|
||||||
void draw() final {
|
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||||
if (this->shouldDraw()) {
|
|
||||||
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
|
||||||
this->drawContent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -189,7 +178,24 @@ namespace hex {
|
||||||
public:
|
public:
|
||||||
explicit Floating(UnlocalizedString unlocalizedName, const char *icon) : Window(std::move(unlocalizedName), icon) {}
|
explicit Floating(UnlocalizedString unlocalizedName, const char *icon) : Window(std::move(unlocalizedName), icon) {}
|
||||||
|
|
||||||
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override { return ImGuiWindowFlags_NoDocking; }
|
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||||
|
|
||||||
|
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A view that draws all its content at once without any scrolling being done by the window itself
|
||||||
|
*/
|
||||||
|
class View::Scrolling : public View::Window {
|
||||||
|
public:
|
||||||
|
explicit Scrolling(UnlocalizedString unlocalizedName, const char *icon) : Window(std::move(unlocalizedName), icon) {}
|
||||||
|
|
||||||
|
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||||
|
|
||||||
|
bool allowScroll() const final {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
|
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -200,24 +206,7 @@ namespace hex {
|
||||||
public:
|
public:
|
||||||
explicit Modal(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon) {}
|
explicit Modal(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon) {}
|
||||||
|
|
||||||
void draw() final {
|
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||||
if (this->shouldDraw()) {
|
|
||||||
if (this->getWindowOpenState())
|
|
||||||
ImGui::OpenPopup(View::toWindowName(this->getUnlocalizedName()).c_str());
|
|
||||||
|
|
||||||
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
|
|
||||||
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
|
||||||
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
|
|
||||||
if (ImGui::BeginPopupModal(title.c_str(), this->hasCloseButton() ? &this->getWindowOpenState() : nullptr, ImGuiWindowFlags_NoCollapse | this->getWindowFlags())) {
|
|
||||||
this->drawContent();
|
|
||||||
|
|
||||||
ImGui::EndPopup();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::IsKeyPressed(ImGuiKey_Escape))
|
|
||||||
this->getWindowOpenState() = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] virtual bool hasCloseButton() const { return true; }
|
[[nodiscard]] virtual bool hasCloseButton() const { return true; }
|
||||||
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
|
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
|
||||||
|
|
@ -227,10 +216,7 @@ namespace hex {
|
||||||
public:
|
public:
|
||||||
explicit FullScreen() : View("FullScreen", "") {}
|
explicit FullScreen() : View("FullScreen", "") {}
|
||||||
|
|
||||||
void draw() final {
|
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||||
this->drawContent();
|
|
||||||
this->drawAlwaysVisibleContent();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -594,6 +594,12 @@ namespace hex {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Spacer::draw(const std::string& name) {
|
||||||
|
std::ignore = name;
|
||||||
|
ImGui::NewLine();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -864,6 +870,18 @@ namespace hex {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace EditWidget {
|
||||||
|
std::optional<std::vector<u8>> TextInput::draw(std::string &value, std::endian endian) {
|
||||||
|
if (ImGui::InputText("##InspectorLineEditing", value,
|
||||||
|
ImGuiInputTextFlags_EnterReturnsTrue |
|
||||||
|
ImGuiInputTextFlags_AutoSelectAll)) {
|
||||||
|
return getBytes(value, endian);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void add(const UnlocalizedString &unlocalizedName, size_t requiredSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction) {
|
void add(const UnlocalizedString &unlocalizedName, size_t requiredSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction) {
|
||||||
log::debug("Registered new data inspector format: {}", unlocalizedName.get());
|
log::debug("Registered new data inspector format: {}", unlocalizedName.get());
|
||||||
|
|
||||||
|
|
@ -1101,13 +1119,13 @@ namespace hex {
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
void add(const std::string &typeName, ProviderCreationFunction creationFunction) {
|
void add(const std::string &typeName, ProviderCreationFunction creationFunction) {
|
||||||
(void)RequestCreateProvider::subscribe([expectedName = typeName, creationFunction](const std::string &name, bool skipLoadInterface, bool selectProvider, prv::Provider **provider) {
|
(void)RequestCreateProvider::subscribe([expectedName = typeName, creationFunction](const std::string &name, bool skipLoadInterface, bool selectProvider, std::shared_ptr<prv::Provider> *provider) {
|
||||||
if (name != expectedName) return;
|
if (name != expectedName) return;
|
||||||
|
|
||||||
auto newProvider = creationFunction();
|
auto newProvider = creationFunction();
|
||||||
|
|
||||||
if (provider != nullptr) {
|
if (provider != nullptr) {
|
||||||
*provider = newProvider.get();
|
*provider = newProvider;
|
||||||
ImHexApi::Provider::add(std::move(newProvider), skipLoadInterface, selectProvider);
|
ImHexApi::Provider::add(std::move(newProvider), skipLoadInterface, selectProvider);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -1395,6 +1413,40 @@ namespace hex {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ContentRegistry::MCP {
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
|
||||||
|
mcp::Server& getMcpServerInstance() {
|
||||||
|
static AutoReset<std::unique_ptr<mcp::Server>> server;
|
||||||
|
|
||||||
|
if (*server == nullptr)
|
||||||
|
server = std::make_unique<mcp::Server>();
|
||||||
|
|
||||||
|
return **server;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool s_mcpEnabled = false;
|
||||||
|
void setEnabled(bool enabled) {
|
||||||
|
s_mcpEnabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEnabled() {
|
||||||
|
return impl::s_mcpEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isConnected() {
|
||||||
|
return impl::getMcpServerInstance().isConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerTool(std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json ¶ms)> function) {
|
||||||
|
impl::getMcpServerInstance().addPrimitive("tools", capabilities, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
namespace ContentRegistry::Experiments {
|
namespace ContentRegistry::Experiments {
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
|
||||||
|
|
@ -294,8 +294,8 @@ namespace hex {
|
||||||
namespace ImHexApi::Provider {
|
namespace ImHexApi::Provider {
|
||||||
|
|
||||||
static i64 s_currentProvider = -1;
|
static i64 s_currentProvider = -1;
|
||||||
static AutoReset<std::vector<std::unique_ptr<prv::Provider>>> s_providers;
|
static AutoReset<std::vector<std::shared_ptr<prv::Provider>>> s_providers;
|
||||||
static AutoReset<std::map<prv::Provider*, std::unique_ptr<prv::Provider>>> s_providersToRemove;
|
static AutoReset<std::map<prv::Provider*, std::shared_ptr<prv::Provider>>> s_providersToRemove;
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
|
|
@ -382,7 +382,7 @@ namespace hex {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(std::unique_ptr<prv::Provider> &&provider, bool skipLoadInterface, bool select) {
|
void add(std::shared_ptr<prv::Provider> &&provider, bool skipLoadInterface, bool select) {
|
||||||
std::scoped_lock lock(impl::s_providerMutex);
|
std::scoped_lock lock(impl::s_providerMutex);
|
||||||
|
|
||||||
if (TaskManager::getRunningTaskCount() > 0)
|
if (TaskManager::getRunningTaskCount() > 0)
|
||||||
|
|
@ -391,7 +391,7 @@ namespace hex {
|
||||||
if (skipLoadInterface)
|
if (skipLoadInterface)
|
||||||
provider->skipLoadInterface();
|
provider->skipLoadInterface();
|
||||||
|
|
||||||
EventProviderCreated::post(provider.get());
|
EventProviderCreated::post(provider);
|
||||||
s_providers->emplace_back(std::move(provider));
|
s_providers->emplace_back(std::move(provider));
|
||||||
|
|
||||||
if (select || s_providers->size() == 1)
|
if (select || s_providers->size() == 1)
|
||||||
|
|
@ -491,13 +491,17 @@ namespace hex {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
prv::Provider* createProvider(const UnlocalizedString &unlocalizedName, bool skipLoadInterface, bool select) {
|
std::shared_ptr<prv::Provider> createProvider(const UnlocalizedString &unlocalizedName, bool skipLoadInterface, bool select) {
|
||||||
prv::Provider* result = nullptr;
|
std::shared_ptr<prv::Provider> result = nullptr;
|
||||||
RequestCreateProvider::post(unlocalizedName, skipLoadInterface, select, &result);
|
RequestCreateProvider::post(unlocalizedName, skipLoadInterface, select, &result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void openProvider(std::shared_ptr<prv::Provider> provider) {
|
||||||
|
RequestOpenProvider::post(provider);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ImHexApi::System {
|
namespace ImHexApi::System {
|
||||||
|
|
|
||||||
|
|
@ -104,9 +104,21 @@ namespace hex {
|
||||||
|
|
||||||
for (const auto &entry : json.items()) {
|
for (const auto &entry : json.items()) {
|
||||||
auto value = entry.value().get<std::string>();
|
auto value = entry.value().get<std::string>();
|
||||||
|
|
||||||
|
// Skip empty values
|
||||||
if (value.empty())
|
if (value.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Handle references to files
|
||||||
|
if (value.starts_with("#@")) {
|
||||||
|
try {
|
||||||
|
value = path.callback(value.substr(2));
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
log::error("Failed to load localization file reference '{}': {}", entry.key(), e.what());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
localizations.try_emplace(LangConst::hash(entry.key()), std::move(value));
|
localizations.try_emplace(LangConst::hash(entry.key()), std::move(value));
|
||||||
}
|
}
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
#include <jthread.hpp>
|
#include <jthread.hpp>
|
||||||
|
#include <hex/helpers/debugging.hpp>
|
||||||
|
#include <hex/trace/exceptions.hpp>
|
||||||
|
|
||||||
#if defined(OS_WINDOWS)
|
#if defined(OS_WINDOWS)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
@ -310,6 +312,8 @@ namespace hex {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
trace::enableExceptionCaptureForCurrentThread();
|
||||||
|
|
||||||
// Set the thread name to the name of the task
|
// Set the thread name to the name of the task
|
||||||
TaskManager::setCurrentThreadName(Lang(task->m_unlocalizedName));
|
TaskManager::setCurrentThreadName(Lang(task->m_unlocalizedName));
|
||||||
|
|
||||||
|
|
@ -323,15 +327,21 @@ namespace hex {
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
log::error("Exception in task '{}': {}", task->m_unlocalizedName.get(), e.what());
|
log::error("Exception in task '{}': {}", task->m_unlocalizedName.get(), e.what());
|
||||||
|
|
||||||
|
dbg::printStackTrace(trace::getStackTrace());
|
||||||
|
|
||||||
// Handle the task throwing an uncaught exception
|
// Handle the task throwing an uncaught exception
|
||||||
task->exception(e.what());
|
task->exception(e.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
log::error("Exception in task '{}'", task->m_unlocalizedName.get());
|
log::error("Exception in task '{}'", task->m_unlocalizedName.get());
|
||||||
|
|
||||||
|
dbg::printStackTrace(trace::getStackTrace());
|
||||||
|
|
||||||
// Handle the task throwing an uncaught exception of unknown type
|
// Handle the task throwing an uncaught exception of unknown type
|
||||||
task->exception("Unknown Exception");
|
task->exception("Unknown Exception");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace::disableExceptionCaptureForCurrentThread();
|
||||||
|
|
||||||
s_currentTask = nullptr;
|
s_currentTask = nullptr;
|
||||||
task->finish();
|
task->finish();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ namespace hex {
|
||||||
ImGuiID s_activeHelpId;
|
ImGuiID s_activeHelpId;
|
||||||
bool s_helpHoverActive = false;
|
bool s_helpHoverActive = false;
|
||||||
|
|
||||||
|
AutoReset<std::function<std::function<void()>(const std::string &)>> s_renderer;
|
||||||
|
|
||||||
|
|
||||||
class IDStack {
|
class IDStack {
|
||||||
public:
|
public:
|
||||||
|
|
@ -126,6 +128,17 @@ namespace hex {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (*s_renderer == nullptr) {
|
||||||
|
*s_renderer = [](const std::string &message) {
|
||||||
|
return [message] {
|
||||||
|
ImGui::PushTextWrapPos(300_scaled);
|
||||||
|
ImGui::TextUnformatted(message.c_str());
|
||||||
|
ImGui::PopTextWrapPos();
|
||||||
|
ImGui::NewLine();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<std::string, TutorialManager::Tutorial>& TutorialManager::getTutorials() {
|
const std::map<std::string, TutorialManager::Tutorial>& TutorialManager::getTutorials() {
|
||||||
|
|
@ -333,30 +346,29 @@ namespace hex {
|
||||||
|
|
||||||
ImGui::SetNextWindowPos(position, ImGuiCond_Always, pivot);
|
ImGui::SetNextWindowPos(position, ImGuiCond_Always, pivot);
|
||||||
ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID);
|
ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID);
|
||||||
if (ImGui::Begin("##TutorialMessage", nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing)) {
|
ImGui::SetNextWindowSize(ImVec2(300_scaled, 0));
|
||||||
|
if (ImGui::Begin(message->unlocalizedTitle.empty() ? "##TutorialMessage" : Lang(message->unlocalizedTitle), nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoFocusOnAppearing)) {
|
||||||
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindowRead());
|
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindowRead());
|
||||||
|
|
||||||
if (!message->unlocalizedTitle.empty())
|
auto &step = s_currentTutorial->second.m_currentStep;
|
||||||
ImGuiExt::Header(Lang(message->unlocalizedTitle), true);
|
|
||||||
|
|
||||||
if (!message->unlocalizedMessage.empty()) {
|
if (!message->unlocalizedMessage.empty()) {
|
||||||
ImGui::PushTextWrapPos(300_scaled);
|
step->m_drawFunction();
|
||||||
ImGui::TextUnformatted(Lang(message->unlocalizedMessage));
|
ImGui::NewLine();
|
||||||
ImGui::PopTextWrapPos();
|
|
||||||
ImGui::NewLine();
|
ImGui::NewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::BeginDisabled(s_currentTutorial->second.m_currentStep == s_currentTutorial->second.m_steps.begin());
|
ImGui::BeginDisabled(step == s_currentTutorial->second.m_steps.begin());
|
||||||
if (ImGui::ArrowButton("Backwards", ImGuiDir_Left)) {
|
if (ImGuiExt::DimmedArrowButton("Backwards", ImGuiDir_Left)) {
|
||||||
s_currentTutorial->second.m_currentStep->advance(-1);
|
s_currentTutorial->second.m_currentStep->advance(-1);
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
ImGui::BeginDisabled(!message->allowSkip && s_currentTutorial->second.m_currentStep == s_currentTutorial->second.m_latestStep);
|
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - ImGui::GetFrameHeight() - ImGui::GetStyle().WindowPadding.x);
|
||||||
if (ImGui::ArrowButton("Forwards", ImGuiDir_Right)) {
|
ImGui::BeginDisabled(!message->allowSkip && step == s_currentTutorial->second.m_latestStep);
|
||||||
s_currentTutorial->second.m_currentStep->advance(1);
|
if (ImGuiExt::DimmedArrowButton("Forwards", ImGuiDir_Right)) {
|
||||||
|
step->advance(1);
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
}
|
}
|
||||||
|
|
@ -387,6 +399,10 @@ namespace hex {
|
||||||
s_highlightDisplays->clear();
|
s_highlightDisplays->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TutorialManager::setRenderer(std::function<DrawFunction(const std::string &)> renderer) {
|
||||||
|
s_renderer = std::move(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
TutorialManager::Tutorial::Step& TutorialManager::Tutorial::addStep() {
|
TutorialManager::Tutorial::Step& TutorialManager::Tutorial::addStep() {
|
||||||
auto &newStep = m_steps.emplace_back(this);
|
auto &newStep = m_steps.emplace_back(this);
|
||||||
m_currentStep = m_steps.end();
|
m_currentStep = m_steps.end();
|
||||||
|
|
@ -402,6 +418,9 @@ namespace hex {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_currentStep->addHighlights();
|
m_currentStep->addHighlights();
|
||||||
|
|
||||||
|
if (m_currentStep->m_message.has_value())
|
||||||
|
m_currentStep->m_drawFunction = (*s_renderer)(Lang(m_currentStep->m_message->unlocalizedMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TutorialManager::Tutorial::Step::addHighlights() const {
|
void TutorialManager::Tutorial::Step::addHighlights() const {
|
||||||
|
|
@ -426,8 +445,12 @@ namespace hex {
|
||||||
std::advance(m_parent->m_latestStep, steps);
|
std::advance(m_parent->m_latestStep, steps);
|
||||||
std::advance(m_parent->m_currentStep, steps);
|
std::advance(m_parent->m_currentStep, steps);
|
||||||
|
|
||||||
if (m_parent->m_currentStep != m_parent->m_steps.end())
|
if (m_parent->m_currentStep != m_parent->m_steps.end()) {
|
||||||
m_parent->m_currentStep->addHighlights();
|
m_parent->m_currentStep->addHighlights();
|
||||||
|
|
||||||
|
if (m_message.has_value())
|
||||||
|
m_parent->m_currentStep->m_drawFunction = (*s_renderer)(Lang(m_parent->m_currentStep->m_message->unlocalizedMessage));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
s_currentTutorial = s_tutorials->end();
|
s_currentTutorial = s_tutorials->end();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
#include <hex/helpers/debugging.hpp>
|
#include <hex/helpers/debugging.hpp>
|
||||||
|
#include <hex/helpers/logger.hpp>
|
||||||
|
#include <hex/trace/stacktrace.hpp>
|
||||||
|
|
||||||
namespace hex::dbg {
|
namespace hex::dbg {
|
||||||
|
|
||||||
|
|
@ -21,4 +23,23 @@ namespace hex::dbg {
|
||||||
s_debugMode = enabled;
|
s_debugMode = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[noreturn]] void assertionHandler(const char* file, int line, const char *function, const char* exprString) {
|
||||||
|
log::error("Assertion failed: {} at {}:{} => {}", exprString, file, line, function);
|
||||||
|
|
||||||
|
const auto stackTrace = trace::getStackTrace();
|
||||||
|
dbg::printStackTrace(stackTrace);
|
||||||
|
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void printStackTrace(const trace::StackTraceResult &stackTrace) {
|
||||||
|
log::fatal("Printing stacktrace using implementation '{}'", stackTrace.implementationName);
|
||||||
|
for (const auto &stackFrame : stackTrace.stackFrames) {
|
||||||
|
if (stackFrame.line == 0)
|
||||||
|
log::fatal(" ({}) | {}", stackFrame.file, stackFrame.function);
|
||||||
|
else
|
||||||
|
log::fatal(" ({}:{}) | {}", stackFrame.file, stackFrame.line, stackFrame.function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -97,6 +97,13 @@ namespace hex::paths {
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::fs::path> getPluginPaths() {
|
static std::vector<std::fs::path> getPluginPaths() {
|
||||||
|
// If running from an AppImage, only allow loaded plugins from inside it
|
||||||
|
#if defined(OS_LINUX)
|
||||||
|
if(const char* appdir = std::getenv("APPDIR")) { // check for AppImage environment
|
||||||
|
return {std::string(appdir) + "/usr/lib/imhex"};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
std::vector<std::fs::path> paths = getDataPaths(true);
|
std::vector<std::fs::path> paths = getDataPaths(true);
|
||||||
|
|
||||||
// Add the system plugin directory to the path if one was provided at compile time
|
// Add the system plugin directory to the path if one was provided at compile time
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <fmt/chrono.h>
|
#include <fmt/chrono.h>
|
||||||
|
#include <hex/helpers/debugging.hpp>
|
||||||
|
|
||||||
#if defined(OS_WINDOWS)
|
#if defined(OS_WINDOWS)
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
@ -149,14 +150,6 @@ namespace hex::log {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void assertionHandler(const char* exprString, const char* file, int line) {
|
|
||||||
log::error("Assertion failed: {} at {}:{}", exprString, file, line);
|
|
||||||
|
|
||||||
#if defined (DEBUG)
|
|
||||||
std::abort();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace color {
|
namespace color {
|
||||||
|
|
||||||
fmt::color debug() { return fmt::color::medium_sea_green; }
|
fmt::color debug() { return fmt::color::medium_sea_green; }
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace hex {
|
||||||
[[nodiscard]] bool isSavable() const override { return false; }
|
[[nodiscard]] bool isSavable() const override { return false; }
|
||||||
[[nodiscard]] bool isSavableAsRecent() const override { return false; }
|
[[nodiscard]] bool isSavableAsRecent() const override { return false; }
|
||||||
|
|
||||||
[[nodiscard]] bool open() override { return true; }
|
[[nodiscard]] OpenResult open() override { return {}; }
|
||||||
void close() override { }
|
void close() override { }
|
||||||
|
|
||||||
void readRaw(u64 offset, void *buffer, size_t size) override {
|
void readRaw(u64 offset, void *buffer, size_t size) override {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
#include <hex/mcp/client.hpp>
|
||||||
|
#include <hex/mcp/server.hpp>
|
||||||
|
|
||||||
|
#include <hex.hpp>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <hex/helpers/logger.hpp>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <wolv/net/socket_client.hpp>
|
||||||
|
|
||||||
|
namespace hex::mcp {
|
||||||
|
|
||||||
|
int Client::run(std::istream &input, std::ostream &output) {
|
||||||
|
wolv::net::SocketClient client(wolv::net::SocketClient::Type::TCP, true);
|
||||||
|
client.connect("127.0.0.1", Server::McpInternalPort);
|
||||||
|
|
||||||
|
if (!client.isConnected()) {
|
||||||
|
log::resumeLogging();
|
||||||
|
log::error("Cannot connect to ImHex. Do you have an instance running and is the MCP server enabled?");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
std::string request;
|
||||||
|
std::getline(input, request);
|
||||||
|
|
||||||
|
client.writeString(request);
|
||||||
|
auto response = client.readString();
|
||||||
|
if (!response.empty() && response.front() != 0x00)
|
||||||
|
output << response << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,226 @@
|
||||||
|
#include <hex/mcp/server.hpp>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <hex/helpers/logger.hpp>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <wolv/net/socket_client.hpp>
|
||||||
|
#include <hex/api/imhex_api/system.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace hex::mcp {
|
||||||
|
|
||||||
|
class JsonRpc {
|
||||||
|
public:
|
||||||
|
explicit JsonRpc(const std::string &request) : m_request(request) { }
|
||||||
|
|
||||||
|
struct MethodNotFoundException : std::exception {};
|
||||||
|
struct InvalidParametersException : std::exception {};
|
||||||
|
|
||||||
|
std::optional<std::string> execute(auto callback) {
|
||||||
|
try {
|
||||||
|
auto requestJson = nlohmann::json::parse(m_request);
|
||||||
|
|
||||||
|
if (requestJson.is_array()) {
|
||||||
|
return handleBatchedMessages(requestJson, callback).transform([](const auto &response) { return response.dump(); });
|
||||||
|
} else {
|
||||||
|
return handleMessage(requestJson, callback).transform([](const auto &response) { return response.dump(); });
|
||||||
|
}
|
||||||
|
} catch (const MethodNotFoundException &) {
|
||||||
|
return createErrorMessage(ErrorCode::MethodNotFound, "Method not found").dump();
|
||||||
|
} catch (const InvalidParametersException &) {
|
||||||
|
return createErrorMessage(ErrorCode::InvalidParams, "Invalid params").dump();
|
||||||
|
} catch (const nlohmann::json::parse_error &) {
|
||||||
|
return createErrorMessage(ErrorCode::ParseError, "Parse error").dump();
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
return createErrorMessage(ErrorCode::InternalError, e.what()).dump();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::optional<nlohmann::json> handleMessage(const nlohmann::json &request, auto callback) {
|
||||||
|
// Validate JSON-RPC request
|
||||||
|
if (!request.contains("jsonrpc") || request["jsonrpc"] != "2.0" ||
|
||||||
|
!request.contains("method") || !request["method"].is_string()) {
|
||||||
|
m_id = request.contains("id") ? std::optional(request["id"].get<int>()) : std::nullopt;
|
||||||
|
|
||||||
|
return createErrorMessage(ErrorCode::InvalidRequest, "Invalid Request").dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_id = request.contains("id") ? std::optional(request["id"].get<int>()) : std::nullopt;
|
||||||
|
|
||||||
|
// Execute the method
|
||||||
|
auto result = callback(request["method"].get<std::string>(), request.value("params", nlohmann::json::object()));
|
||||||
|
|
||||||
|
if (!m_id.has_value())
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
return createResponseMessage(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<nlohmann::json> handleBatchedMessages(const nlohmann::json &request, auto callback) {
|
||||||
|
if (!request.is_array()) {
|
||||||
|
return createErrorMessage(ErrorCode::InvalidRequest, "Invalid Request").dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json responses = nlohmann::json::array();
|
||||||
|
for (const auto &message : request) {
|
||||||
|
auto response = handleMessage(message, callback);
|
||||||
|
if (response.has_value())
|
||||||
|
responses.push_back(*response);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responses.empty())
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
return responses.dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ErrorCode {
|
||||||
|
ParseError = -32700,
|
||||||
|
InvalidRequest = -32600,
|
||||||
|
MethodNotFound = -32601,
|
||||||
|
InvalidParams = -32602,
|
||||||
|
InternalError = -32603,
|
||||||
|
};
|
||||||
|
|
||||||
|
nlohmann::json createDefaultMessage() {
|
||||||
|
nlohmann::json message;
|
||||||
|
message["jsonrpc"] = "2.0";
|
||||||
|
if (m_id.has_value())
|
||||||
|
message["id"] = m_id.value();
|
||||||
|
else
|
||||||
|
message["id"] = nullptr;
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json createErrorMessage(ErrorCode code, const std::string &message) {
|
||||||
|
auto json = createDefaultMessage();
|
||||||
|
json["error"] = {
|
||||||
|
{ "code", int(code) },
|
||||||
|
{ "message", message }
|
||||||
|
};
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json createResponseMessage(const nlohmann::json &result) {
|
||||||
|
auto json = createDefaultMessage();
|
||||||
|
json["result"] = result;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_request;
|
||||||
|
std::optional<int> m_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
Server::Server() : m_server(McpInternalPort, 1024, 1, true) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Server::~Server() {
|
||||||
|
this->shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::listen() {
|
||||||
|
m_server.accept([this](auto, const std::vector<u8> &data) -> std::vector<u8> {
|
||||||
|
std::string request(data.begin(), data.end());
|
||||||
|
|
||||||
|
log::debug("MCP ----> {}", request);
|
||||||
|
|
||||||
|
JsonRpc rpc(request);
|
||||||
|
auto response = rpc.execute([this](const std::string &method, const nlohmann::json ¶ms) -> nlohmann::json {
|
||||||
|
if (method == "initialize") {
|
||||||
|
return handleInitialize();
|
||||||
|
} else if (method.starts_with("notifications/")) {
|
||||||
|
handleNotifications(method.substr(14), params);
|
||||||
|
return {};
|
||||||
|
} else if (method.ends_with("/list")) {
|
||||||
|
auto primitiveName = method.substr(0, method.size() - 5);
|
||||||
|
if (m_primitives.contains(primitiveName)) {
|
||||||
|
nlohmann::json capabilitiesList = nlohmann::json::array();
|
||||||
|
for (const auto &[name, primitive] : m_primitives[primitiveName]) {
|
||||||
|
capabilitiesList.push_back(primitive.capabilities);
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json result;
|
||||||
|
result[primitiveName] = capabilitiesList;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} else if (method.ends_with("/call")) {
|
||||||
|
auto primitive = method.substr(0, method.size() - 5);
|
||||||
|
if (auto primitiveIt = m_primitives.find(primitive); primitiveIt != m_primitives.end()) {
|
||||||
|
auto name = params.value("name", "");
|
||||||
|
if (auto functionIt = primitiveIt->second.find(name); functionIt != primitiveIt->second.end()) {
|
||||||
|
return functionIt->second.function(params.value("arguments", nlohmann::json::object()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw JsonRpc::MethodNotFoundException();
|
||||||
|
});
|
||||||
|
|
||||||
|
log::debug("MCP <---- {}", response.value_or("<Nothing>"));
|
||||||
|
|
||||||
|
if (response.has_value())
|
||||||
|
return { response->begin(), response->end() };
|
||||||
|
else
|
||||||
|
return std::vector<u8>{ 0x00 };
|
||||||
|
}, [this](auto) {
|
||||||
|
log::info("MCP client disconnected");
|
||||||
|
m_connected = false;
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::shutdown() {
|
||||||
|
m_server.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::disconnect() {
|
||||||
|
m_server.disconnectClients();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::addPrimitive(std::string type, std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json ¶ms)> function) {
|
||||||
|
auto json = nlohmann::json::parse(capabilities);
|
||||||
|
auto name = json["name"].get<std::string>();
|
||||||
|
|
||||||
|
m_primitives[type][name] = {
|
||||||
|
json,
|
||||||
|
function
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nlohmann::json Server::handleInitialize() {
|
||||||
|
constexpr static auto ServerName = "ImHex";
|
||||||
|
constexpr static auto ProtocolVersion = "2025-06-18";
|
||||||
|
|
||||||
|
return {
|
||||||
|
{ "protocolVersion", ProtocolVersion },
|
||||||
|
{
|
||||||
|
"capabilities",
|
||||||
|
{
|
||||||
|
{ "tools", nlohmann::json::object() },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"serverInfo", {
|
||||||
|
{ "name", ServerName },
|
||||||
|
{ "version", ImHexApi::System::getImHexVersion().get() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::handleNotifications(const std::string &method, [[maybe_unused]] const nlohmann::json ¶ms) {
|
||||||
|
if (method == "initialized") {
|
||||||
|
m_connected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Server::isConnected() {
|
||||||
|
return m_connected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,9 +11,9 @@ namespace hex::prv {
|
||||||
clearCache();
|
clearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CachedProvider::open() {
|
Provider::OpenResult CachedProvider::open() {
|
||||||
clearCache();
|
clearCache();
|
||||||
return true;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void CachedProvider::close() {
|
void CachedProvider::close() {
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@
|
||||||
|
|
||||||
namespace hex::prv {
|
namespace hex::prv {
|
||||||
|
|
||||||
bool MemoryProvider::open() {
|
Provider::OpenResult MemoryProvider::open() {
|
||||||
if (m_data.empty()) {
|
if (m_data.empty()) {
|
||||||
m_data.resize(1);
|
m_data.resize(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
void MemoryProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,14 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <hex/api/content_registry/settings.hpp>
|
||||||
|
|
||||||
#include <hex/helpers/magic.hpp>
|
#include <hex/helpers/magic.hpp>
|
||||||
#include <wolv/io/file.hpp>
|
#include <wolv/io/file.hpp>
|
||||||
#include <wolv/literals.hpp>
|
#include <wolv/literals.hpp>
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <wolv/utils/string.hpp>
|
||||||
|
|
||||||
namespace hex::prv {
|
namespace hex::prv {
|
||||||
|
|
||||||
|
|
@ -24,6 +26,28 @@ namespace hex::prv {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IProviderDataBackupable::IProviderDataBackupable(Provider* provider) : m_provider(provider) {
|
||||||
|
m_shouldCreateBackups = ContentRegistry::Settings::read<bool>("hex.builtin.setting.general", "hex.builtin.setting.general.backups.file_backup.enable", true);
|
||||||
|
m_maxSize = ContentRegistry::Settings::read<u32>("hex.builtin.setting.general", "hex.builtin.setting.general.backups.file_backup.max_size", 1_MiB);
|
||||||
|
m_backupExtension = ContentRegistry::Settings::read<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.backups.file_backup.extension", ".bak");
|
||||||
|
}
|
||||||
|
|
||||||
|
void IProviderDataBackupable::createBackupIfNeeded(const std::fs::path &inputFilePath) {
|
||||||
|
if (!m_shouldCreateBackups || m_backupCreated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_provider->getActualSize() > m_maxSize)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const std::fs::path backupFilePath = wolv::util::toUTF8String(inputFilePath) + m_backupExtension;
|
||||||
|
if (wolv::io::fs::copyFile(inputFilePath, backupFilePath, std::fs::copy_options::overwrite_existing)) {
|
||||||
|
if (wolv::io::fs::exists(backupFilePath)) {
|
||||||
|
m_backupCreated = true;
|
||||||
|
log::info("Created backup of provider data at '{}'", backupFilePath.string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Provider::Provider() : m_undoRedoStack(this), m_id(s_idCounter++) {
|
Provider::Provider() : m_undoRedoStack(this), m_id(s_idCounter++) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1218,6 +1218,21 @@ namespace ImGuiExt {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DimmedArrowButton(const char *id, ImGuiDir dir, ImVec2 size) {
|
||||||
|
PushStyleColor(ImGuiCol_ButtonHovered, GetCustomColorU32(ImGuiCustomCol_DescButtonHovered));
|
||||||
|
PushStyleColor(ImGuiCol_Button, GetCustomColorU32(ImGuiCustomCol_DescButton));
|
||||||
|
PushStyleColor(ImGuiCol_Text, GetColorU32(ImGuiCol_ButtonActive));
|
||||||
|
PushStyleColor(ImGuiCol_ButtonActive, GetCustomColorU32(ImGuiCustomCol_DescButtonActive));
|
||||||
|
PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.5 * hex::ImHexApi::System::getGlobalScale());
|
||||||
|
|
||||||
|
bool res = ArrowButtonEx(id, dir, size);
|
||||||
|
|
||||||
|
PopStyleColor(4);
|
||||||
|
PopStyleVar(1);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size, ImVec2 iconOffset) {
|
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size, ImVec2 iconOffset) {
|
||||||
bool pushed = false;
|
bool pushed = false;
|
||||||
bool toggled = false;
|
bool toggled = false;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
#include <hex/ui/view.hpp>
|
#include <hex/ui/view.hpp>
|
||||||
#include <hex/api/task_manager.hpp>
|
|
||||||
#include <hex/helpers/auto_reset.hpp>
|
#include <hex/helpers/auto_reset.hpp>
|
||||||
|
|
||||||
#include <hex/api/imhex_api/provider.hpp>
|
#include <hex/api/imhex_api/provider.hpp>
|
||||||
|
#include <hex/api/task_manager.hpp>
|
||||||
|
#include <hex/api/tutorial_manager.hpp>
|
||||||
|
|
||||||
#include <hex/providers/provider.hpp>
|
#include <hex/providers/provider.hpp>
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
@ -116,4 +118,63 @@ namespace hex {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void View::Window::draw(ImGuiWindowFlags extraFlags) {
|
||||||
|
if (this->shouldDraw()) {
|
||||||
|
if (!allowScroll())
|
||||||
|
extraFlags |= ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
|
||||||
|
|
||||||
|
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
||||||
|
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
|
||||||
|
if (ImGui::Begin(title.c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse | extraFlags | this->getWindowFlags())) {
|
||||||
|
TutorialManager::setLastItemInteractiveHelpPopup([this]{ this->drawHelpText(); });
|
||||||
|
this->drawContent();
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::Special::draw(ImGuiWindowFlags extraFlags) {
|
||||||
|
std::ignore = extraFlags;
|
||||||
|
|
||||||
|
if (this->shouldDraw()) {
|
||||||
|
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
||||||
|
this->drawContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::Floating::draw(ImGuiWindowFlags extraFlags) {
|
||||||
|
Window::draw(extraFlags | ImGuiWindowFlags_NoDocking);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::Scrolling::draw(ImGuiWindowFlags extraFlags) {
|
||||||
|
Window::draw(extraFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::Modal::draw(ImGuiWindowFlags extraFlags) {
|
||||||
|
if (this->shouldDraw()) {
|
||||||
|
if (this->getWindowOpenState())
|
||||||
|
ImGui::OpenPopup(View::toWindowName(this->getUnlocalizedName()).c_str());
|
||||||
|
|
||||||
|
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
|
||||||
|
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
||||||
|
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
|
||||||
|
if (ImGui::BeginPopupModal(title.c_str(), this->hasCloseButton() ? &this->getWindowOpenState() : nullptr, ImGuiWindowFlags_NoCollapse | extraFlags | this->getWindowFlags())) {
|
||||||
|
this->drawContent();
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::IsKeyPressed(ImGuiKey_Escape))
|
||||||
|
this->getWindowOpenState() = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::FullScreen::draw(ImGuiWindowFlags extraFlags) {
|
||||||
|
std::ignore = extraFlags;
|
||||||
|
|
||||||
|
this->drawContent();
|
||||||
|
this->drawAlwaysVisibleContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -25,10 +25,17 @@
|
||||||
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
|
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
|
||||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||||
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||||
namespace hex::log::impl {
|
namespace hex::dbg {
|
||||||
void assertionHandler(const char* expr_str, const char* file, int line);
|
[[noreturn]] void assertionHandler(const char* file, int line, const char *function, const char* exprString);
|
||||||
}
|
}
|
||||||
#define IM_ASSERT(_EXPR) do { if (!(_EXPR)) [[unlikely]] { hex::log::impl::assertionHandler(#_EXPR, __FILE__, __LINE__); } } while(0)
|
|
||||||
|
#if defined(__PRETTY_FUNCTION__)
|
||||||
|
#define IM_ASSERT(_EXPR) do { if (!(_EXPR)) [[unlikely]] { hex::dbg::assertionHandler(__FILE__, __LINE__, __PRETTY_FUNCTION__, #_EXPR); } } while(0)
|
||||||
|
#elif defined(__FUNCSIG__)
|
||||||
|
#define IM_ASSERT(_EXPR) do { if (!(_EXPR)) [[unlikely]] { hex::dbg::assertionHandler(__FILE__, __LINE__, __FUNCSIG__, #_EXPR); } } while(0)
|
||||||
|
#else
|
||||||
|
#define IM_ASSERT(_EXPR) do { if (!(_EXPR)) [[unlikely]] { hex::dbg::assertionHandler(__FILE__, __LINE__, __FUNCTION__, #_EXPR); } } while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
||||||
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,9 @@ if (IMHEX_TRACE_EXCEPTIONS)
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||||
target_link_options(tracing ${LIBIMHEX_LIBRARY_TYPE_PUBLIC} "-Wl,--wrap=__cxa_throw")
|
target_link_options(tracing ${LIBIMHEX_LIBRARY_TYPE_PUBLIC} "-Wl,--wrap=__cxa_throw")
|
||||||
target_compile_definitions(tracing ${LIBIMHEX_LIBRARY_TYPE_PRIVATE} HEX_WRAP_CXA_THROW)
|
target_compile_definitions(tracing ${LIBIMHEX_LIBRARY_TYPE_PRIVATE} HEX_WRAP_CXA_THROW)
|
||||||
|
|
||||||
|
target_link_options(tracing ${LIBIMHEX_LIBRARY_TYPE_PUBLIC} "-Wl,--wrap=_ZSt21__glibcxx_assert_failPKciS0_S0_")
|
||||||
|
target_compile_definitions(tracing ${LIBIMHEX_LIBRARY_TYPE_PRIVATE} HEX_WRAP_GLIBCXX_ASSERT_FAIL)
|
||||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
# Not supported currently
|
# Not supported currently
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,12 @@
|
||||||
|
|
||||||
namespace hex::trace {
|
namespace hex::trace {
|
||||||
|
|
||||||
|
using AssertionHandler = void(*)(const char* file, int line, const char *function, const char* exprString);
|
||||||
|
|
||||||
std::optional<StackTraceResult> getLastExceptionStackTrace();
|
std::optional<StackTraceResult> getLastExceptionStackTrace();
|
||||||
|
void setAssertionHandler(AssertionHandler handler);
|
||||||
|
|
||||||
void enableExceptionCaptureForCurrentThread();
|
void enableExceptionCaptureForCurrentThread();
|
||||||
|
void disableExceptionCaptureForCurrentThread();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
namespace hex::trace {
|
namespace hex::trace {
|
||||||
|
|
||||||
static std::optional<StackTraceResult> s_lastExceptionStackTrace;
|
static thread_local std::optional<StackTraceResult> s_lastExceptionStackTrace;
|
||||||
static thread_local bool s_threadExceptionCaptureEnabled = false;
|
static thread_local bool s_threadExceptionCaptureEnabled = false;
|
||||||
|
static AssertionHandler s_assertionHandler = nullptr;
|
||||||
|
|
||||||
std::optional<StackTraceResult> getLastExceptionStackTrace() {
|
std::optional<StackTraceResult> getLastExceptionStackTrace() {
|
||||||
if (!s_lastExceptionStackTrace.has_value())
|
if (!s_lastExceptionStackTrace.has_value())
|
||||||
|
|
@ -15,18 +16,26 @@ namespace hex::trace {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setAssertionHandler(AssertionHandler handler) {
|
||||||
|
s_assertionHandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
void enableExceptionCaptureForCurrentThread() {
|
void enableExceptionCaptureForCurrentThread() {
|
||||||
s_threadExceptionCaptureEnabled = true;
|
s_threadExceptionCaptureEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void disableExceptionCaptureForCurrentThread() {
|
||||||
|
s_threadExceptionCaptureEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HEX_WRAP_CXA_THROW)
|
#if defined(HEX_WRAP_CXA_THROW)
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
[[noreturn]] void __real___cxa_throw(void* thrownException, void* type, void (*destructor)(void*));
|
[[noreturn]] void __real___cxa_throw(void* thrownException, std::type_info* type, void (*destructor)(void*));
|
||||||
[[noreturn]] void __wrap___cxa_throw(void* thrownException, void* type, void (*destructor)(void*)) {
|
[[noreturn]] void __wrap___cxa_throw(void* thrownException, std::type_info* type, void (*destructor)(void*)) {
|
||||||
if (hex::trace::s_threadExceptionCaptureEnabled)
|
if (hex::trace::s_threadExceptionCaptureEnabled)
|
||||||
hex::trace::s_lastExceptionStackTrace = hex::trace::getStackTrace();
|
hex::trace::s_lastExceptionStackTrace = hex::trace::getStackTrace();
|
||||||
|
|
||||||
|
|
@ -36,3 +45,22 @@ namespace hex::trace {
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HEX_WRAP_GLIBCXX_ASSERT_FAIL)
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
[[noreturn]] void __real__ZSt21__glibcxx_assert_failPKciS0_S0_(const char* file, int line, const char* function, const char* condition);
|
||||||
|
[[noreturn]] void __wrap__ZSt21__glibcxx_assert_failPKciS0_S0_(const char* file, int line, const char* function, const char* condition) {
|
||||||
|
if (hex::trace::s_assertionHandler != nullptr) {
|
||||||
|
hex::trace::s_assertionHandler(file, line, function, condition);
|
||||||
|
} else {
|
||||||
|
__real__ZSt21__glibcxx_assert_failPKciS0_S0_(file, line, function, condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
#include <hex/helpers/debugging.hpp>
|
||||||
#include <hex/helpers/utils.hpp>
|
#include <hex/helpers/utils.hpp>
|
||||||
|
|
||||||
#if defined(IMGUI_TEST_ENGINE)
|
#if defined(IMGUI_TEST_ENGINE)
|
||||||
|
|
@ -71,23 +72,12 @@ namespace hex::crash {
|
||||||
log::warn("Could not write crash.json file!");
|
log::warn("Could not write crash.json file!");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void printStackTrace() {
|
|
||||||
auto stackTraceResult = trace::getStackTrace();
|
|
||||||
log::fatal("Printing stacktrace using implementation '{}'", stackTraceResult.implementationName);
|
|
||||||
for (const auto &stackFrame : stackTraceResult.stackFrames) {
|
|
||||||
if (stackFrame.line == 0)
|
|
||||||
log::fatal(" ({}) | {}", stackFrame.file, stackFrame.function);
|
|
||||||
else
|
|
||||||
log::fatal(" ({}:{}) | {}", stackFrame.file, stackFrame.line, stackFrame.function);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void callCrashHandlers(const std::string &msg) {
|
static void callCrashHandlers(const std::string &msg) {
|
||||||
// Call the crash callback
|
// Call the crash callback
|
||||||
crashCallback(msg);
|
crashCallback(msg);
|
||||||
|
|
||||||
// Print the stacktrace to the console or log file
|
// Print the stacktrace to the console or log file
|
||||||
printStackTrace();
|
dbg::printStackTrace(trace::getStackTrace());
|
||||||
|
|
||||||
// Flush all streams
|
// Flush all streams
|
||||||
std::fflush(stdout);
|
std::fflush(stdout);
|
||||||
|
|
@ -188,6 +178,7 @@ namespace hex::crash {
|
||||||
// Setup functions to handle signals, uncaught exception, or similar stuff that will crash ImHex
|
// Setup functions to handle signals, uncaught exception, or similar stuff that will crash ImHex
|
||||||
void setupCrashHandlers() {
|
void setupCrashHandlers() {
|
||||||
trace::initialize();
|
trace::initialize();
|
||||||
|
trace::setAssertionHandler(dbg::assertionHandler);
|
||||||
|
|
||||||
// Register signal handlers
|
// Register signal handlers
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ add_imhex_plugin(
|
||||||
source/content/providers/base64_provider.cpp
|
source/content/providers/base64_provider.cpp
|
||||||
source/content/providers/view_provider.cpp
|
source/content/providers/view_provider.cpp
|
||||||
source/content/providers/udp_provider.cpp
|
source/content/providers/udp_provider.cpp
|
||||||
|
source/content/providers/command_provider.cpp
|
||||||
|
|
||||||
source/content/tools/ascii_table.cpp
|
source/content/tools/ascii_table.cpp
|
||||||
source/content/tools/base_converter.cpp
|
source/content/tools/base_converter.cpp
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ namespace hex::plugin::builtin {
|
||||||
void handleValidatePluginCommand(const std::vector<std::string> &args);
|
void handleValidatePluginCommand(const std::vector<std::string> &args);
|
||||||
void handleSaveEditorCommand(const std::vector<std::string> &args);
|
void handleSaveEditorCommand(const std::vector<std::string> &args);
|
||||||
void handleFileInfoCommand(const std::vector<std::string> &args);
|
void handleFileInfoCommand(const std::vector<std::string> &args);
|
||||||
|
void handleMCPCommand(const std::vector<std::string> &args);
|
||||||
|
|
||||||
void registerCommandForwarders();
|
void registerCommandForwarders();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include <content/views/view_hex_editor.hpp>
|
#include <content/views/view_hex_editor.hpp>
|
||||||
#include <hex/api/localization_manager.hpp>
|
#include <hex/api/localization_manager.hpp>
|
||||||
#include <ui/text_editor.hpp>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
@ -21,6 +20,5 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_decodedString;
|
std::string m_decodedString;
|
||||||
ui::TextEditor m_editor;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <hex/providers/provider.hpp>
|
||||||
|
|
||||||
|
#include <wolv/net/socket_client.hpp>
|
||||||
|
|
||||||
|
#include <fonts/vscode_icons.hpp>
|
||||||
|
#include <hex/providers/cached_provider.hpp>
|
||||||
|
|
||||||
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
|
class CommandProvider : public prv::CachedProvider,
|
||||||
|
public prv::IProviderLoadInterface {
|
||||||
|
public:
|
||||||
|
CommandProvider();
|
||||||
|
~CommandProvider() override = default;
|
||||||
|
|
||||||
|
[[nodiscard]] bool isAvailable() const override;
|
||||||
|
[[nodiscard]] bool isReadable() const override;
|
||||||
|
[[nodiscard]] bool isWritable() const override;
|
||||||
|
[[nodiscard]] bool isResizable() const override;
|
||||||
|
[[nodiscard]] bool isSavable() const override;
|
||||||
|
|
||||||
|
void readFromSource(u64 offset, void *buffer, size_t size) override;
|
||||||
|
void writeToSource(u64 offset, const void *buffer, size_t size) override;
|
||||||
|
[[nodiscard]] u64 getSourceSize() const override;
|
||||||
|
|
||||||
|
void save() override;
|
||||||
|
|
||||||
|
[[nodiscard]] std::string getName() const override;
|
||||||
|
|
||||||
|
[[nodiscard]] OpenResult open() override;
|
||||||
|
void close() override;
|
||||||
|
|
||||||
|
bool drawLoadInterface() override;
|
||||||
|
|
||||||
|
void loadSettings(const nlohmann::json &settings) override;
|
||||||
|
[[nodiscard]] nlohmann::json storeSettings(nlohmann::json settings) const override;
|
||||||
|
|
||||||
|
[[nodiscard]] UnlocalizedString getTypeName() const override {
|
||||||
|
return "hex.builtin.provider.command";
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const char* getIcon() const override {
|
||||||
|
return ICON_VS_TERMINAL_CMD;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string m_name;
|
||||||
|
std::string m_readCommand, m_writeCommand, m_sizeCommand, m_resizeCommand, m_saveCommand;
|
||||||
|
bool m_open = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -30,7 +30,7 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
void setPath(const std::fs::path &path);
|
void setPath(const std::fs::path &path);
|
||||||
|
|
||||||
[[nodiscard]] bool open() override;
|
[[nodiscard]] OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
[[nodiscard]] std::string getName() const override;
|
[[nodiscard]] std::string getName() const override;
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,10 @@ namespace hex::plugin::builtin {
|
||||||
class FileProvider : public prv::Provider,
|
class FileProvider : public prv::Provider,
|
||||||
public prv::IProviderDataDescription,
|
public prv::IProviderDataDescription,
|
||||||
public prv::IProviderFilePicker,
|
public prv::IProviderFilePicker,
|
||||||
public prv::IProviderMenuItems {
|
public prv::IProviderMenuItems,
|
||||||
|
public prv::IProviderDataBackupable {
|
||||||
public:
|
public:
|
||||||
FileProvider() = default;
|
FileProvider() : IProviderDataBackupable(this) {}
|
||||||
~FileProvider() override = default;
|
~FileProvider() override = default;
|
||||||
|
|
||||||
[[nodiscard]] bool isAvailable() const override;
|
[[nodiscard]] bool isAvailable() const override;
|
||||||
|
|
@ -43,7 +44,7 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
void setPath(const std::fs::path &path);
|
void setPath(const std::fs::path &path);
|
||||||
|
|
||||||
[[nodiscard]] bool open() override;
|
[[nodiscard]] OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
void loadSettings(const nlohmann::json &settings) override;
|
void loadSettings(const nlohmann::json &settings) override;
|
||||||
|
|
@ -65,7 +66,7 @@ namespace hex::plugin::builtin {
|
||||||
private:
|
private:
|
||||||
void handleFileChange();
|
void handleFileChange();
|
||||||
|
|
||||||
bool open(bool memoryMapped);
|
OpenResult open(bool memoryMapped);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::fs::path m_path;
|
std::fs::path m_path;
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ namespace hex::plugin::builtin {
|
||||||
[[nodiscard]] std::string getName() const override;
|
[[nodiscard]] std::string getName() const override;
|
||||||
[[nodiscard]] std::vector<Description> getDataDescription() const override;
|
[[nodiscard]] std::vector<Description> getDataDescription() const override;
|
||||||
|
|
||||||
[[nodiscard]] bool open() override;
|
[[nodiscard]] OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
[[nodiscard]] bool isConnected() const;
|
[[nodiscard]] bool isConnected() const;
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ namespace hex::plugin::builtin {
|
||||||
[[nodiscard]] u64 getActualSize() const override;
|
[[nodiscard]] u64 getActualSize() const override;
|
||||||
void processMemoryRegions(wolv::util::Expected<std::map<u64, std::vector<u8>>, std::string> data);
|
void processMemoryRegions(wolv::util::Expected<std::map<u64, std::vector<u8>>, std::string> data);
|
||||||
static bool memoryRegionFilter(const std::string &search, const MemoryRegion &memoryRegion);
|
static bool memoryRegionFilter(const std::string &search, const MemoryRegion &memoryRegion);
|
||||||
bool open() override;
|
OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
[[nodiscard]] std::string getName() const override;
|
[[nodiscard]] std::string getName() const override;
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace hex::plugin::builtin {
|
||||||
[[nodiscard]] bool isSavable() const override { return m_name.empty(); }
|
[[nodiscard]] bool isSavable() const override { return m_name.empty(); }
|
||||||
[[nodiscard]] bool isSavableAsRecent() const override { return false; }
|
[[nodiscard]] bool isSavableAsRecent() const override { return false; }
|
||||||
|
|
||||||
[[nodiscard]] bool open() override;
|
[[nodiscard]] OpenResult open() override;
|
||||||
void close() override { }
|
void close() override { }
|
||||||
|
|
||||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ namespace hex::plugin::builtin {
|
||||||
MotorolaSRECProvider() = default;
|
MotorolaSRECProvider() = default;
|
||||||
~MotorolaSRECProvider() override = default;
|
~MotorolaSRECProvider() override = default;
|
||||||
|
|
||||||
bool open() override;
|
OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
[[nodiscard]] std::string getName() const override;
|
[[nodiscard]] std::string getName() const override;
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ namespace hex::plugin::builtin {
|
||||||
[[nodiscard]] bool isResizable() const override { return false; }
|
[[nodiscard]] bool isResizable() const override { return false; }
|
||||||
[[nodiscard]] bool isSavable() const override { return false; }
|
[[nodiscard]] bool isSavable() const override { return false; }
|
||||||
|
|
||||||
[[nodiscard]] bool open() override { return true; }
|
[[nodiscard]] OpenResult open() override { return {}; }
|
||||||
void close() override { }
|
void close() override { }
|
||||||
|
|
||||||
void readRaw(u64 offset, void *buffer, size_t size) override {
|
void readRaw(u64 offset, void *buffer, size_t size) override {
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ namespace hex::plugin::builtin {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool open() override;
|
[[nodiscard]] OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
bool drawLoadInterface() override;
|
bool drawLoadInterface() override;
|
||||||
|
|
@ -86,6 +86,7 @@ namespace hex::plugin::builtin {
|
||||||
struct Process {
|
struct Process {
|
||||||
u32 id;
|
u32 id;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
std::string commandLine;
|
||||||
ImGuiExt::Texture icon;
|
ImGuiExt::Texture icon;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ namespace hex::plugin::builtin {
|
||||||
[[nodiscard]] bool drawLoadInterface() override;
|
[[nodiscard]] bool drawLoadInterface() override;
|
||||||
void drawSidebarInterface() override;
|
void drawSidebarInterface() override;
|
||||||
|
|
||||||
[[nodiscard]] bool open() override;
|
[[nodiscard]] OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
void loadSettings(const nlohmann::json &) override;
|
void loadSettings(const nlohmann::json &) override;
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace hex::plugin::builtin {
|
||||||
[[nodiscard]] bool isSavableAsRecent() const override;
|
[[nodiscard]] bool isSavableAsRecent() const override;
|
||||||
|
|
||||||
void save() override;
|
void save() override;
|
||||||
[[nodiscard]] bool open() override;
|
[[nodiscard]] OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
void resizeRaw(u64 newSize) override;
|
void resizeRaw(u64 newSize) override;
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@
|
||||||
#include <hex/ui/view.hpp>
|
#include <hex/ui/view.hpp>
|
||||||
#include <hex/api/imhex_api/bookmarks.hpp>
|
#include <hex/api/imhex_api/bookmarks.hpp>
|
||||||
|
|
||||||
#include <ui/text_editor.hpp>
|
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <ui/markdown.hpp>
|
#include <ui/markdown.hpp>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,10 +57,6 @@ namespace hex::plugin::builtin {
|
||||||
void reloadCustomNodes();
|
void reloadCustomNodes();
|
||||||
void updateNodePositions();
|
void updateNodePositions();
|
||||||
|
|
||||||
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override {
|
|
||||||
return ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Workspace*> &getWorkspaceStack() { return *m_workspaceStack; }
|
std::vector<Workspace*> &getWorkspaceStack() { return *m_workspaceStack; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
void drawContent() override;
|
void drawContent() override;
|
||||||
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override {
|
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override {
|
||||||
return ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
|
return ImGuiWindowFlags_NoNavInputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldDefaultFocus() const override { return true; }
|
bool shouldDefaultFocus() const override { return true; }
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace hex::plugin::builtin {
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGuiWindowFlags getWindowFlags() const override {
|
ImGuiWindowFlags getWindowFlags() const override {
|
||||||
return View::Floating::getWindowFlags() | ImGuiWindowFlags_NoResize;
|
return ImGuiWindowFlags_NoResize;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
class ViewInformation : public View::Window {
|
class ViewInformation : public View::Scrolling {
|
||||||
public:
|
public:
|
||||||
explicit ViewInformation();
|
explicit ViewInformation();
|
||||||
~ViewInformation() override = default;
|
~ViewInformation() override = default;
|
||||||
|
|
|
||||||
|
|
@ -66,9 +66,6 @@ namespace hex::plugin::builtin {
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawContent() override;
|
void drawContent() override;
|
||||||
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override {
|
|
||||||
return ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPopupWindowHeight(u32 height) { m_popupWindowHeight = height; }
|
void setPopupWindowHeight(u32 height) { m_popupWindowHeight = height; }
|
||||||
u32 getPopupWindowHeight() const { return m_popupWindowHeight; }
|
u32 getPopupWindowHeight() const { return m_popupWindowHeight; }
|
||||||
|
|
@ -140,7 +137,8 @@ namespace hex::plugin::builtin {
|
||||||
std::atomic<bool> m_dangerousFunctionCalled = false;
|
std::atomic<bool> m_dangerousFunctionCalled = false;
|
||||||
std::atomic<DangerousFunctionPerms> m_dangerousFunctionsAllowed = DangerousFunctionPerms::Ask;
|
std::atomic<DangerousFunctionPerms> m_dangerousFunctionsAllowed = DangerousFunctionPerms::Ask;
|
||||||
|
|
||||||
bool m_autoLoadPatterns = true;
|
bool m_suggestSupportedPatterns = true;
|
||||||
|
bool m_autoApplyPatterns = false;
|
||||||
|
|
||||||
PerProvider<ui::VisualizerDrawer> m_visualizerDrawer;
|
PerProvider<ui::VisualizerDrawer> m_visualizerDrawer;
|
||||||
bool m_tooltipJustOpened = false;
|
bool m_tooltipJustOpened = false;
|
||||||
|
|
@ -152,12 +150,12 @@ namespace hex::plugin::builtin {
|
||||||
std::mutex m_logMutex;
|
std::mutex m_logMutex;
|
||||||
|
|
||||||
PerProvider<ui::TextEditor::Coordinates> m_cursorPosition;
|
PerProvider<ui::TextEditor::Coordinates> m_cursorPosition;
|
||||||
|
PerProvider<ImVec2> m_scroll;
|
||||||
|
PerProvider<ImVec2> m_consoleScroll;
|
||||||
|
|
||||||
PerProvider<ui::TextEditor::Coordinates> m_consoleCursorPosition;
|
PerProvider<ui::TextEditor::Coordinates> m_consoleCursorPosition;
|
||||||
PerProvider<bool> m_cursorNeedsUpdate;
|
PerProvider<ui::TextEditor::Range> m_selection;
|
||||||
PerProvider<bool> m_consoleCursorNeedsUpdate;
|
PerProvider<ui::TextEditor::Range> m_consoleSelection;
|
||||||
PerProvider<ui::TextEditor::Selection> m_selection;
|
|
||||||
PerProvider<ui::TextEditor::Selection> m_consoleSelection;
|
|
||||||
PerProvider<size_t> m_consoleLongestLineLength;
|
PerProvider<size_t> m_consoleLongestLineLength;
|
||||||
PerProvider<ui::TextEditor::Breakpoints> m_breakpoints;
|
PerProvider<ui::TextEditor::Breakpoints> m_breakpoints;
|
||||||
PerProvider<std::optional<pl::core::err::PatternLanguageError>> m_lastEvaluationError;
|
PerProvider<std::optional<pl::core::err::PatternLanguageError>> m_lastEvaluationError;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
class ViewTools : public View::Window {
|
class ViewTools : public View::Scrolling {
|
||||||
public:
|
public:
|
||||||
ViewTools();
|
ViewTools();
|
||||||
~ViewTools() override = default;
|
~ViewTools() override = default;
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ namespace hex::plugin::builtin {
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGuiWindowFlags getWindowFlags() const override {
|
ImGuiWindowFlags getWindowFlags() const override {
|
||||||
return Floating::getWindowFlags() | ImGuiWindowFlags_NoResize;
|
return ImGuiWindowFlags_NoResize;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -444,10 +444,10 @@
|
||||||
"hex.builtin.setting.folders.description": "Gib zusätzliche Orderpfade an, in welchen Pattern, Scripts, Yara Rules und anderes gesucht wird",
|
"hex.builtin.setting.folders.description": "Gib zusätzliche Orderpfade an, in welchen Pattern, Scripts, Yara Rules und anderes gesucht wird",
|
||||||
"hex.builtin.setting.folders.remove_folder": "Ausgewählter Ordner von Liste entfernen",
|
"hex.builtin.setting.folders.remove_folder": "Ausgewählter Ordner von Liste entfernen",
|
||||||
"hex.builtin.setting.general": "Allgemein",
|
"hex.builtin.setting.general": "Allgemein",
|
||||||
"hex.builtin.setting.general.auto_backup_time": "Periodisches Projekt Backup",
|
"hex.builtin.setting.general.backups.auto_backup_time": "Periodisches Projekt Backup",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.extended": "Alle {0}min {1}s",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.extended": "Alle {0}min {1}s",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.simple": "Alle {0}s",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.simple": "Alle {0}s",
|
||||||
"hex.builtin.setting.general.auto_load_patterns": "Automatisches Laden unterstützter Pattern",
|
"hex.builtin.setting.general.auto_apply_patterns": "Automatisches Laden unterstützter Pattern",
|
||||||
"hex.builtin.setting.general.network": "Netzwerk",
|
"hex.builtin.setting.general.network": "Netzwerk",
|
||||||
"hex.builtin.setting.general.network_interface": "Netzwerk Interface Aktivieren",
|
"hex.builtin.setting.general.network_interface": "Netzwerk Interface Aktivieren",
|
||||||
"hex.builtin.setting.general.patterns": "Patterns",
|
"hex.builtin.setting.general.patterns": "Patterns",
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@
|
||||||
"hex.builtin.achievement.misc.download_from_store.name": "There's an app for that",
|
"hex.builtin.achievement.misc.download_from_store.name": "There's an app for that",
|
||||||
"hex.builtin.achievement.misc.download_from_store.desc": "Download any item from the Content Store",
|
"hex.builtin.achievement.misc.download_from_store.desc": "Download any item from the Content Store",
|
||||||
"hex.builtin.background_service.network_interface": "Network Interface",
|
"hex.builtin.background_service.network_interface": "Network Interface",
|
||||||
|
"hex.builtin.setting.general.mcp_server": "MCP Server support",
|
||||||
"hex.builtin.background_service.auto_backup": "Auto Backup",
|
"hex.builtin.background_service.auto_backup": "Auto Backup",
|
||||||
"hex.builtin.command.calc.desc": "Calculator",
|
"hex.builtin.command.calc.desc": "Calculator",
|
||||||
"hex.builtin.command.convert.desc": "Unit conversion",
|
"hex.builtin.command.convert.desc": "Unit conversion",
|
||||||
|
|
@ -123,6 +124,7 @@
|
||||||
"hex.builtin.layouts.none.restore_default": "Restore default layout",
|
"hex.builtin.layouts.none.restore_default": "Restore default layout",
|
||||||
"hex.builtin.menu.edit": "Edit",
|
"hex.builtin.menu.edit": "Edit",
|
||||||
"hex.builtin.menu.edit.bookmark.create": "Create Bookmark",
|
"hex.builtin.menu.edit.bookmark.create": "Create Bookmark",
|
||||||
|
"hex.builtin.menu.edit.find.find_selection": "Find occurrences",
|
||||||
"hex.builtin.view.hex_editor.menu.edit.redo": "Redo",
|
"hex.builtin.view.hex_editor.menu.edit.redo": "Redo",
|
||||||
"hex.builtin.view.hex_editor.menu.edit.undo": "Undo",
|
"hex.builtin.view.hex_editor.menu.edit.undo": "Undo",
|
||||||
"hex.builtin.menu.extras": "Extras",
|
"hex.builtin.menu.extras": "Extras",
|
||||||
|
|
@ -406,7 +408,7 @@
|
||||||
"hex.builtin.popup.exit_application.title": "Exit Application?",
|
"hex.builtin.popup.exit_application.title": "Exit Application?",
|
||||||
"hex.builtin.popup.waiting_for_tasks.title": "Waiting for Tasks",
|
"hex.builtin.popup.waiting_for_tasks.title": "Waiting for Tasks",
|
||||||
"hex.builtin.popup.crash_recover.title": "Crash recovery",
|
"hex.builtin.popup.crash_recover.title": "Crash recovery",
|
||||||
"hex.builtin.popup.crash_recover.message": "An exception was thrown, but ImHex was able to catch it and advert a crash",
|
"hex.builtin.popup.crash_recover.message": "An exception was thrown, but ImHex was able to catch it and avert a crash",
|
||||||
"hex.builtin.popup.foreground_task.title": "Please Wait...",
|
"hex.builtin.popup.foreground_task.title": "Please Wait...",
|
||||||
"hex.builtin.popup.blocking_task.title": "Running Task",
|
"hex.builtin.popup.blocking_task.title": "Running Task",
|
||||||
"hex.builtin.popup.blocking_task.desc": "A task is currently executing.",
|
"hex.builtin.popup.blocking_task.desc": "A task is currently executing.",
|
||||||
|
|
@ -418,8 +420,18 @@
|
||||||
"hex.builtin.provider.rename": "Rename",
|
"hex.builtin.provider.rename": "Rename",
|
||||||
"hex.builtin.provider.rename.desc": "Enter a name for this data source.",
|
"hex.builtin.provider.rename.desc": "Enter a name for this data source.",
|
||||||
"hex.builtin.provider.tooltip.show_more": "Hold SHIFT for more information",
|
"hex.builtin.provider.tooltip.show_more": "Hold SHIFT for more information",
|
||||||
"hex.builtin.provider.error.open": "Failed to open data provider: {}",
|
"hex.builtin.provider.error.open": "Failed to open data source: {}",
|
||||||
"hex.builtin.provider.base64": "Base64 File",
|
"hex.builtin.provider.base64": "Base64 File",
|
||||||
|
"hex.builtin.provider.command": "Terminal Command",
|
||||||
|
"hex.builtin.provider.command.name": "Command {0}",
|
||||||
|
"hex.builtin.provider.command.load.name": "Name",
|
||||||
|
"hex.builtin.provider.command.load.hint": "Enter commands to be executed for specific functions.\n\nThe {address} and {size} placeholders will be replaced with the respective value",
|
||||||
|
"hex.builtin.provider.command.load.read_command": "Read Data Command",
|
||||||
|
"hex.builtin.provider.command.load.write_command": "Write Data Command",
|
||||||
|
"hex.builtin.provider.command.load.size_command": "Get Data Size Command",
|
||||||
|
"hex.builtin.provider.command.load.resize_command": "Resize Data Command",
|
||||||
|
"hex.builtin.provider.command.load.save_command": "Save Data Command",
|
||||||
|
"hex.builtin.provider.command.optional": "Optional",
|
||||||
"hex.builtin.provider.disk": "Raw Disk",
|
"hex.builtin.provider.disk": "Raw Disk",
|
||||||
"hex.builtin.provider.disk.disk_size": "Disk Size",
|
"hex.builtin.provider.disk.disk_size": "Disk Size",
|
||||||
"hex.builtin.provider.disk.elevation": "Accessing raw disks most likely requires elevated privileges",
|
"hex.builtin.provider.disk.elevation": "Accessing raw disks most likely requires elevated privileges",
|
||||||
|
|
@ -430,6 +442,7 @@
|
||||||
"hex.builtin.provider.disk.error.read_rw": "Failed to open disk {} in read/write mode: {}",
|
"hex.builtin.provider.disk.error.read_rw": "Failed to open disk {} in read/write mode: {}",
|
||||||
"hex.builtin.provider.file": "Regular File",
|
"hex.builtin.provider.file": "Regular File",
|
||||||
"hex.builtin.provider.file.error.open": "Failed to open file {}: {}",
|
"hex.builtin.provider.file.error.open": "Failed to open file {}: {}",
|
||||||
|
"hex.builtin.provider.file.error.already_open": "Same file is already open",
|
||||||
"hex.builtin.provider.file.access": "Last access time",
|
"hex.builtin.provider.file.access": "Last access time",
|
||||||
"hex.builtin.provider.file.creation": "Creation time",
|
"hex.builtin.provider.file.creation": "Creation time",
|
||||||
"hex.builtin.provider.file.menu.direct_access": "Direct access file",
|
"hex.builtin.provider.file.menu.direct_access": "Direct access file",
|
||||||
|
|
@ -448,6 +461,7 @@
|
||||||
"hex.builtin.provider.gdb.name": "GDB Server <{0}:{1}>",
|
"hex.builtin.provider.gdb.name": "GDB Server <{0}:{1}>",
|
||||||
"hex.builtin.provider.gdb.port": "Port",
|
"hex.builtin.provider.gdb.port": "Port",
|
||||||
"hex.builtin.provider.gdb.server": "Server",
|
"hex.builtin.provider.gdb.server": "Server",
|
||||||
|
"hex.builtin.provider.gdb.server.error.not_connected": "Failed to open connection to GDB Server",
|
||||||
"hex.builtin.provider.intel_hex": "Intel Hex File",
|
"hex.builtin.provider.intel_hex": "Intel Hex File",
|
||||||
"hex.builtin.provider.intel_hex.name": "Intel Hex {0}",
|
"hex.builtin.provider.intel_hex.name": "Intel Hex {0}",
|
||||||
"hex.builtin.provider.mem_file": "In-Memory File",
|
"hex.builtin.provider.mem_file": "In-Memory File",
|
||||||
|
|
@ -458,6 +472,8 @@
|
||||||
"hex.builtin.provider.opening": "Opening Data Source...",
|
"hex.builtin.provider.opening": "Opening Data Source...",
|
||||||
"hex.builtin.provider.process_memory": "Process Memory",
|
"hex.builtin.provider.process_memory": "Process Memory",
|
||||||
"hex.builtin.provider.process_memory.enumeration_failed": "Failed to enumerate processes",
|
"hex.builtin.provider.process_memory.enumeration_failed": "Failed to enumerate processes",
|
||||||
|
"hex.builtin.provider.process_memory.error.no_process_selected": "No process selected",
|
||||||
|
"hex.builtin.provider.process_memory.error.open_process": "Failed to attach to process",
|
||||||
"hex.builtin.provider.process_memory.macos_limitations": "macOS doesn't properly allow reading memory from other processes, even when running as root. If System Integrity Protection (SIP) is enabled, it only works for applications that are unsigned or have the 'Get Task Allow' entitlement which generally only applies to applications compiled by yourself.",
|
"hex.builtin.provider.process_memory.macos_limitations": "macOS doesn't properly allow reading memory from other processes, even when running as root. If System Integrity Protection (SIP) is enabled, it only works for applications that are unsigned or have the 'Get Task Allow' entitlement which generally only applies to applications compiled by yourself.",
|
||||||
"hex.builtin.provider.process_memory.memory_regions": "Memory Regions",
|
"hex.builtin.provider.process_memory.memory_regions": "Memory Regions",
|
||||||
"hex.builtin.provider.process_memory.name": "'{0}' Process Memory",
|
"hex.builtin.provider.process_memory.name": "'{0}' Process Memory",
|
||||||
|
|
@ -476,6 +492,7 @@
|
||||||
"hex.builtin.provider.udp.port": "Server Port",
|
"hex.builtin.provider.udp.port": "Server Port",
|
||||||
"hex.builtin.provider.udp.timestamp": "Timestamp",
|
"hex.builtin.provider.udp.timestamp": "Timestamp",
|
||||||
"hex.builtin.provider.view": "View",
|
"hex.builtin.provider.view": "View",
|
||||||
|
"hex.builtin.provider.view.error.no_provider": "No data source has been attached to this view",
|
||||||
"hex.builtin.setting.experiments": "Experiments",
|
"hex.builtin.setting.experiments": "Experiments",
|
||||||
"hex.builtin.setting.experiments.description": "Experiments are features that are still in development and may not work correctly yet.\n\nFeel free to try them out and report any issues you encounter!",
|
"hex.builtin.setting.experiments.description": "Experiments are features that are still in development and may not work correctly yet.\n\nFeel free to try them out and report any issues you encounter!",
|
||||||
"hex.builtin.setting.folders": "Folders",
|
"hex.builtin.setting.folders": "Folders",
|
||||||
|
|
@ -483,12 +500,17 @@
|
||||||
"hex.builtin.setting.folders.description": "Specify additional search paths for patterns, scripts, Yara rules and more",
|
"hex.builtin.setting.folders.description": "Specify additional search paths for patterns, scripts, Yara rules and more",
|
||||||
"hex.builtin.setting.folders.remove_folder": "Remove currently selected folder from list",
|
"hex.builtin.setting.folders.remove_folder": "Remove currently selected folder from list",
|
||||||
"hex.builtin.setting.general": "General",
|
"hex.builtin.setting.general": "General",
|
||||||
|
"hex.builtin.setting.general.backups": "Backups",
|
||||||
|
"hex.builtin.setting.general.backups.auto_backup_time": "Periodically backup project",
|
||||||
|
"hex.builtin.setting.general.backups.auto_backup_time.format.simple": "Every {0}s",
|
||||||
|
"hex.builtin.setting.general.backups.auto_backup_time.format.extended": "Every {0}m {1}s",
|
||||||
|
"hex.builtin.setting.general.backups.file_backup.enable": "Backup data sources before modification if possible",
|
||||||
|
"hex.builtin.setting.general.backups.file_backup.max_size": "Max file size for file backups",
|
||||||
|
"hex.builtin.setting.general.backups.file_backup.extension": "Backup file extension",
|
||||||
"hex.builtin.setting.general.patterns": "Patterns",
|
"hex.builtin.setting.general.patterns": "Patterns",
|
||||||
"hex.builtin.setting.general.network": "Network",
|
"hex.builtin.setting.general.network": "Network",
|
||||||
"hex.builtin.setting.general.auto_backup_time": "Periodically backup project",
|
"hex.builtin.setting.general.auto_apply_patterns": "Auto-load supported pattern",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.simple": "Every {0}s",
|
"hex.builtin.setting.general.suggest_patterns": "Suggest patterns based on loaded data",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.extended": "Every {0}m {1}s",
|
|
||||||
"hex.builtin.setting.general.auto_load_patterns": "Auto-load supported pattern",
|
|
||||||
"hex.builtin.setting.general.server_contact": "Enable update checks and usage statistics",
|
"hex.builtin.setting.general.server_contact": "Enable update checks and usage statistics",
|
||||||
"hex.builtin.setting.general.max_mem_file_size": "Max file size to load into RAM",
|
"hex.builtin.setting.general.max_mem_file_size": "Max file size to load into RAM",
|
||||||
"hex.builtin.setting.general.max_mem_file_size.desc": "Small files are loaded into memory to prevent them from being modified directly on disk.\n\nIncreasing this size allows larger files to be loaded into memory before ImHex resorts to streaming in data from disk.",
|
"hex.builtin.setting.general.max_mem_file_size.desc": "Small files are loaded into memory to prevent them from being modified directly on disk.\n\nIncreasing this size allows larger files to be loaded into memory before ImHex resorts to streaming in data from disk.",
|
||||||
|
|
@ -750,6 +772,7 @@
|
||||||
"hex.builtin.view.data_inspector.table.value": "Value",
|
"hex.builtin.view.data_inspector.table.value": "Value",
|
||||||
"hex.builtin.view.data_inspector.custom_row.title": "Adding custom rows",
|
"hex.builtin.view.data_inspector.custom_row.title": "Adding custom rows",
|
||||||
"hex.builtin.view.data_inspector.custom_row.hint": "It's possible to define custom data inspector rows by placing pattern language scripts in the <ImHex>/scripts/inspectors folder.\n\nCheck the documentation for more information.",
|
"hex.builtin.view.data_inspector.custom_row.hint": "It's possible to define custom data inspector rows by placing pattern language scripts in the <ImHex>/scripts/inspectors folder.\n\nCheck the documentation for more information.",
|
||||||
|
"hex.builtin.view.data_inspector.toggle_endianness": "Toggle Endianness",
|
||||||
"hex.builtin.view.data_processor.continuous_evaluation": "Continuous Evaluation",
|
"hex.builtin.view.data_processor.continuous_evaluation": "Continuous Evaluation",
|
||||||
"hex.builtin.view.data_processor.help_text": "Right click to add a new node",
|
"hex.builtin.view.data_processor.help_text": "Right click to add a new node",
|
||||||
"hex.builtin.view.data_processor.menu.file.load_processor": "Load data processor...",
|
"hex.builtin.view.data_processor.menu.file.load_processor": "Load data processor...",
|
||||||
|
|
@ -1031,6 +1054,9 @@
|
||||||
"hex.builtin.view.pattern_data.virtual_files.no_virtual_files": "Visualize regions of data as a virtual folder structure by adding them using the hex::core::add_virtual_file function.",
|
"hex.builtin.view.pattern_data.virtual_files.no_virtual_files": "Visualize regions of data as a virtual folder structure by adding them using the hex::core::add_virtual_file function.",
|
||||||
"hex.builtin.view.pattern_editor.no_env_vars": "The content of Environment Variables created here can be accessed from Pattern scripts using the std::env function.",
|
"hex.builtin.view.pattern_editor.no_env_vars": "The content of Environment Variables created here can be accessed from Pattern scripts using the std::env function.",
|
||||||
"hex.builtin.view.pattern_editor.no_results": "no results",
|
"hex.builtin.view.pattern_editor.no_results": "no results",
|
||||||
|
"hex.builtin.view.pattern_editor.match_case_tooltip": "Match Case Alt-C",
|
||||||
|
"hex.builtin.view.pattern_editor.whole_word_tooltip": "Whole Word Alt-W",
|
||||||
|
"hex.builtin.view.pattern_editor.regex_tooltip": "Regex Alt-R",
|
||||||
"hex.builtin.view.pattern_editor.of": "of",
|
"hex.builtin.view.pattern_editor.of": "of",
|
||||||
"hex.builtin.view.pattern_editor.open_pattern": "Open pattern",
|
"hex.builtin.view.pattern_editor.open_pattern": "Open pattern",
|
||||||
"hex.builtin.view.pattern_editor.replace_hint": "Replace",
|
"hex.builtin.view.pattern_editor.replace_hint": "Replace",
|
||||||
|
|
|
||||||
|
|
@ -443,10 +443,10 @@
|
||||||
"hex.builtin.setting.folders.description": "Especifica rutas de búsqueda adicionales para patterns, scripts, Yara Rules y más",
|
"hex.builtin.setting.folders.description": "Especifica rutas de búsqueda adicionales para patterns, scripts, Yara Rules y más",
|
||||||
"hex.builtin.setting.folders.remove_folder": "Eliminar la carpeta seleccionada de la lista",
|
"hex.builtin.setting.folders.remove_folder": "Eliminar la carpeta seleccionada de la lista",
|
||||||
"hex.builtin.setting.general": "General",
|
"hex.builtin.setting.general": "General",
|
||||||
"hex.builtin.setting.general.auto_backup_time": "",
|
"hex.builtin.setting.general.backups.auto_backup_time": "",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.extended": "",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.extended": "",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.simple": "",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.simple": "",
|
||||||
"hex.builtin.setting.general.auto_load_patterns": "Cargar automáticamente patterns soportados",
|
"hex.builtin.setting.general.auto_apply_patterns": "Cargar automáticamente patterns soportados",
|
||||||
"hex.builtin.setting.general.network": "",
|
"hex.builtin.setting.general.network": "",
|
||||||
"hex.builtin.setting.general.network_interface": "",
|
"hex.builtin.setting.general.network_interface": "",
|
||||||
"hex.builtin.setting.general.patterns": "",
|
"hex.builtin.setting.general.patterns": "",
|
||||||
|
|
|
||||||
|
|
@ -464,10 +464,10 @@
|
||||||
"hex.builtin.setting.general": "Général",
|
"hex.builtin.setting.general": "Général",
|
||||||
"hex.builtin.setting.general.patterns": "Modèles",
|
"hex.builtin.setting.general.patterns": "Modèles",
|
||||||
"hex.builtin.setting.general.network": "Réseau",
|
"hex.builtin.setting.general.network": "Réseau",
|
||||||
"hex.builtin.setting.general.auto_backup_time": "Sauvegarder périodiquement le projet",
|
"hex.builtin.setting.general.backups.auto_backup_time": "Sauvegarder périodiquement le projet",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.simple": "Toutes les {0}s",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.simple": "Toutes les {0}s",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.extended": "Toutes les {0}m {1}s",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.extended": "Toutes les {0}m {1}s",
|
||||||
"hex.builtin.setting.general.auto_load_patterns": "Charger automatiquement les modèles pris en charge",
|
"hex.builtin.setting.general.auto_apply_patterns": "Charger automatiquement les modèles pris en charge",
|
||||||
"hex.builtin.setting.general.server_contact": "Activer les vérifications de mise à jour et les statistiques d'utilisation",
|
"hex.builtin.setting.general.server_contact": "Activer les vérifications de mise à jour et les statistiques d'utilisation",
|
||||||
"hex.builtin.setting.general.max_mem_file_size": "Taille maximale du fichier à charger en mémoire",
|
"hex.builtin.setting.general.max_mem_file_size": "Taille maximale du fichier à charger en mémoire",
|
||||||
"hex.builtin.setting.general.max_mem_file_size.desc": "Les petits fichiers sont chargés en mémoire pour éviter qu'ils ne soient modifiés directement sur le disque.\n\nL'augmentation de cette taille permet de charger des fichiers plus volumineux en mémoire avqu'ImHex ne se mette à diffuser les données depuis le disque.",
|
"hex.builtin.setting.general.max_mem_file_size.desc": "Les petits fichiers sont chargés en mémoire pour éviter qu'ils ne soient modifiés directement sur le disque.\n\nL'augmentation de cette taille permet de charger des fichiers plus volumineux en mémoire avqu'ImHex ne se mette à diffuser les données depuis le disque.",
|
||||||
|
|
|
||||||
|
|
@ -438,10 +438,10 @@
|
||||||
"hex.builtin.setting.general": "Általános",
|
"hex.builtin.setting.general": "Általános",
|
||||||
"hex.builtin.setting.general.patterns": "Sablonok",
|
"hex.builtin.setting.general.patterns": "Sablonok",
|
||||||
"hex.builtin.setting.general.network": "Hálózat",
|
"hex.builtin.setting.general.network": "Hálózat",
|
||||||
"hex.builtin.setting.general.auto_backup_time": "A projekt automatikus mentése időközönként",
|
"hex.builtin.setting.general.backups.auto_backup_time": "A projekt automatikus mentése időközönként",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.simple": "Minden {0}mp",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.simple": "Minden {0}mp",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.extended": "Minden {0}p {1}mp",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.extended": "Minden {0}p {1}mp",
|
||||||
"hex.builtin.setting.general.auto_load_patterns": "Támogatott sablonok automatikus betöltése",
|
"hex.builtin.setting.general.auto_apply_patterns": "Támogatott sablonok automatikus betöltése",
|
||||||
"hex.builtin.setting.general.server_contact": "Frissítések ellenőrzésének és használati statisztikák gyűjtésének engedélyezése",
|
"hex.builtin.setting.general.server_contact": "Frissítések ellenőrzésének és használati statisztikák gyűjtésének engedélyezése",
|
||||||
"hex.builtin.setting.general.network_interface": "Hálózati interfész engedélyezése",
|
"hex.builtin.setting.general.network_interface": "Hálózati interfész engedélyezése",
|
||||||
"hex.builtin.setting.general.save_recent_providers": "Nemrég használt források mentése",
|
"hex.builtin.setting.general.save_recent_providers": "Nemrég használt források mentése",
|
||||||
|
|
|
||||||
|
|
@ -443,10 +443,10 @@
|
||||||
"hex.builtin.setting.folders.description": "",
|
"hex.builtin.setting.folders.description": "",
|
||||||
"hex.builtin.setting.folders.remove_folder": "",
|
"hex.builtin.setting.folders.remove_folder": "",
|
||||||
"hex.builtin.setting.general": "Generali",
|
"hex.builtin.setting.general": "Generali",
|
||||||
"hex.builtin.setting.general.auto_backup_time": "",
|
"hex.builtin.setting.general.backups.auto_backup_time": "",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.extended": "",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.extended": "",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.simple": "",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.simple": "",
|
||||||
"hex.builtin.setting.general.auto_load_patterns": "Auto-caricamento del pattern supportato",
|
"hex.builtin.setting.general.auto_apply_patterns": "Auto-caricamento del pattern supportato",
|
||||||
"hex.builtin.setting.general.network": "",
|
"hex.builtin.setting.general.network": "",
|
||||||
"hex.builtin.setting.general.network_interface": "",
|
"hex.builtin.setting.general.network_interface": "",
|
||||||
"hex.builtin.setting.general.patterns": "",
|
"hex.builtin.setting.general.patterns": "",
|
||||||
|
|
|
||||||
|
|
@ -443,10 +443,10 @@
|
||||||
"hex.builtin.setting.folders.description": "パターン、スクリプト、ルールなどのための検索パスを指定して追加できます。",
|
"hex.builtin.setting.folders.description": "パターン、スクリプト、ルールなどのための検索パスを指定して追加できます。",
|
||||||
"hex.builtin.setting.folders.remove_folder": "選択中のフォルダをリストから消去",
|
"hex.builtin.setting.folders.remove_folder": "選択中のフォルダをリストから消去",
|
||||||
"hex.builtin.setting.general": "基本",
|
"hex.builtin.setting.general": "基本",
|
||||||
"hex.builtin.setting.general.auto_backup_time": "",
|
"hex.builtin.setting.general.backups.auto_backup_time": "",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.extended": "",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.extended": "",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.simple": "",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.simple": "",
|
||||||
"hex.builtin.setting.general.auto_load_patterns": "対応するパターンを自動で読み込む",
|
"hex.builtin.setting.general.auto_apply_patterns": "対応するパターンを自動で読み込む",
|
||||||
"hex.builtin.setting.general.network": "",
|
"hex.builtin.setting.general.network": "",
|
||||||
"hex.builtin.setting.general.network_interface": "",
|
"hex.builtin.setting.general.network_interface": "",
|
||||||
"hex.builtin.setting.general.patterns": "",
|
"hex.builtin.setting.general.patterns": "",
|
||||||
|
|
|
||||||
|
|
@ -443,10 +443,10 @@
|
||||||
"hex.builtin.setting.folders.description": "패턴, 스크립트, YARA 규칙 등에 대한 추가 검색 경로를 지정합니다",
|
"hex.builtin.setting.folders.description": "패턴, 스크립트, YARA 규칙 등에 대한 추가 검색 경로를 지정합니다",
|
||||||
"hex.builtin.setting.folders.remove_folder": "목록에서 현재 선택된 폴더 제거",
|
"hex.builtin.setting.folders.remove_folder": "목록에서 현재 선택된 폴더 제거",
|
||||||
"hex.builtin.setting.general": "일반",
|
"hex.builtin.setting.general": "일반",
|
||||||
"hex.builtin.setting.general.auto_backup_time": "",
|
"hex.builtin.setting.general.backups.auto_backup_time": "",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.extended": "",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.extended": "",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.simple": "",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.simple": "",
|
||||||
"hex.builtin.setting.general.auto_load_patterns": "지원하는 패턴 자동으로 불러오기",
|
"hex.builtin.setting.general.auto_apply_patterns": "지원하는 패턴 자동으로 불러오기",
|
||||||
"hex.builtin.setting.general.network": "네트워크",
|
"hex.builtin.setting.general.network": "네트워크",
|
||||||
"hex.builtin.setting.general.network_interface": "네트워크 인터페이스 사용",
|
"hex.builtin.setting.general.network_interface": "네트워크 인터페이스 사용",
|
||||||
"hex.builtin.setting.general.patterns": "패턴",
|
"hex.builtin.setting.general.patterns": "패턴",
|
||||||
|
|
|
||||||
|
|
@ -465,10 +465,10 @@
|
||||||
"hex.builtin.setting.general": "Ogólne",
|
"hex.builtin.setting.general": "Ogólne",
|
||||||
"hex.builtin.setting.general.patterns": "Pattern",
|
"hex.builtin.setting.general.patterns": "Pattern",
|
||||||
"hex.builtin.setting.general.network": "Sieć",
|
"hex.builtin.setting.general.network": "Sieć",
|
||||||
"hex.builtin.setting.general.auto_backup_time": "Okresowe tworzenie kopii zapasowej projektu",
|
"hex.builtin.setting.general.backups.auto_backup_time": "Okresowe tworzenie kopii zapasowej projektu",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.simple": "Co {0}s",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.simple": "Co {0}s",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.extended": "Co {0}m {1}s",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.extended": "Co {0}m {1}s",
|
||||||
"hex.builtin.setting.general.auto_load_patterns": "Automatycznie wczytaj obsługiwany pattern",
|
"hex.builtin.setting.general.auto_apply_patterns": "Automatycznie wczytaj obsługiwany pattern",
|
||||||
"hex.builtin.setting.general.server_contact": "Włącz sprawdzanie aktualizacji i statystyki użytkowania",
|
"hex.builtin.setting.general.server_contact": "Włącz sprawdzanie aktualizacji i statystyki użytkowania",
|
||||||
"hex.builtin.setting.general.max_mem_file_size": "Maksymalny rozmiar pliku do wczytania do RAM",
|
"hex.builtin.setting.general.max_mem_file_size": "Maksymalny rozmiar pliku do wczytania do RAM",
|
||||||
"hex.builtin.setting.general.max_mem_file_size.desc": "Małe pliki są wczytywane do pamięci aby zapobiec ich bezpośredniej modyfikacji na dysku.\n\nZwiększenie tego rozmiaru pozwala większym plikom być wczytanym do pamięci zanim ImHex ucieknie się do strumieniowania danych z dysku.",
|
"hex.builtin.setting.general.max_mem_file_size.desc": "Małe pliki są wczytywane do pamięci aby zapobiec ich bezpośredniej modyfikacji na dysku.\n\nZwiększenie tego rozmiaru pozwala większym plikom być wczytanym do pamięci zanim ImHex ucieknie się do strumieniowania danych z dysku.",
|
||||||
|
|
|
||||||
|
|
@ -443,10 +443,10 @@
|
||||||
"hex.builtin.setting.folders.description": "Especifique caminhos de pesquisa adicionais para padrões, scripts, regras Yara e muito mais",
|
"hex.builtin.setting.folders.description": "Especifique caminhos de pesquisa adicionais para padrões, scripts, regras Yara e muito mais",
|
||||||
"hex.builtin.setting.folders.remove_folder": "Remover a pasta atualmente selecionada da lista",
|
"hex.builtin.setting.folders.remove_folder": "Remover a pasta atualmente selecionada da lista",
|
||||||
"hex.builtin.setting.general": "General",
|
"hex.builtin.setting.general": "General",
|
||||||
"hex.builtin.setting.general.auto_backup_time": "",
|
"hex.builtin.setting.general.backups.auto_backup_time": "",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.extended": "",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.extended": "",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.simple": "",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.simple": "",
|
||||||
"hex.builtin.setting.general.auto_load_patterns": "Padrão compatível com carregamento automático",
|
"hex.builtin.setting.general.auto_apply_patterns": "Padrão compatível com carregamento automático",
|
||||||
"hex.builtin.setting.general.network": "",
|
"hex.builtin.setting.general.network": "",
|
||||||
"hex.builtin.setting.general.network_interface": "",
|
"hex.builtin.setting.general.network_interface": "",
|
||||||
"hex.builtin.setting.general.patterns": "",
|
"hex.builtin.setting.general.patterns": "",
|
||||||
|
|
|
||||||
|
|
@ -453,10 +453,10 @@
|
||||||
"hex.builtin.setting.general": "Основное",
|
"hex.builtin.setting.general": "Основное",
|
||||||
"hex.builtin.setting.general.patterns": "Шаблоны",
|
"hex.builtin.setting.general.patterns": "Шаблоны",
|
||||||
"hex.builtin.setting.general.network": "Сеть",
|
"hex.builtin.setting.general.network": "Сеть",
|
||||||
"hex.builtin.setting.general.auto_backup_time": "Делать резервные копии каждые",
|
"hex.builtin.setting.general.backups.auto_backup_time": "Делать резервные копии каждые",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.simple": "{0} секунд",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.simple": "{0} секунд",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.extended": "{0} минут {1} секунд",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.extended": "{0} минут {1} секунд",
|
||||||
"hex.builtin.setting.general.auto_load_patterns": "Автоматически подгружать распознанные шаблоны",
|
"hex.builtin.setting.general.auto_apply_patterns": "Автоматически подгружать распознанные шаблоны",
|
||||||
"hex.builtin.setting.general.server_contact": "Включить проверку обновлений и статистики использования",
|
"hex.builtin.setting.general.server_contact": "Включить проверку обновлений и статистики использования",
|
||||||
"hex.builtin.setting.general.max_mem_file_size": "Макс. размер файла для сохранения в RAM",
|
"hex.builtin.setting.general.max_mem_file_size": "Макс. размер файла для сохранения в RAM",
|
||||||
"hex.builtin.setting.general.max_mem_file_size.desc": "Маленькие файлы загружаются в оперативную память, чтобы не сохранять изменения сразу на диск.\n\nУвеличение этого параметра позволит ImHex загружать более объёмные файлы в память.",
|
"hex.builtin.setting.general.max_mem_file_size.desc": "Маленькие файлы загружаются в оперативную память, чтобы не сохранять изменения сразу на диск.\n\nУвеличение этого параметра позволит ImHex загружать более объёмные файлы в память.",
|
||||||
|
|
|
||||||
|
|
@ -423,9 +423,9 @@
|
||||||
"hex.builtin.setting.folders.remove_folder": "Видалити поточну вибрану папку зі списку",
|
"hex.builtin.setting.folders.remove_folder": "Видалити поточну вибрану папку зі списку",
|
||||||
"hex.builtin.setting.general": "Основне",
|
"hex.builtin.setting.general": "Основне",
|
||||||
"hex.builtin.setting.general.patterns": "Шаблони",
|
"hex.builtin.setting.general.patterns": "Шаблони",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.simple": "кожні {0} секунд",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.simple": "кожні {0} секунд",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.extended": "Кожні {0} хвилин {1} секунд",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.extended": "Кожні {0} хвилин {1} секунд",
|
||||||
"hex.builtin.setting.general.auto_load_patterns": "Автоматично завантажувати розпізнані шаблони",
|
"hex.builtin.setting.general.auto_apply_patterns": "Автоматично завантажувати розпізнані шаблони",
|
||||||
"hex.builtin.setting.general.server_contact": "Увімкнути перевірку оновлень та статистику використання",
|
"hex.builtin.setting.general.server_contact": "Увімкнути перевірку оновлень та статистику використання",
|
||||||
"hex.builtin.setting.general.network_interface": "Увімкнути мережевий інтерфейс",
|
"hex.builtin.setting.general.network_interface": "Увімкнути мережевий інтерфейс",
|
||||||
"hex.builtin.setting.general.pattern_data_max_filter_items": "Максимальна кількість відфільтрованих елементів шаблону",
|
"hex.builtin.setting.general.pattern_data_max_filter_items": "Максимальна кількість відфільтрованих елементів шаблону",
|
||||||
|
|
@ -585,7 +585,7 @@
|
||||||
"hex.builtin.provider.process_memory.macos_limitations": "macOS не дозволяє належним чином зчитувати пам'ять з інших процесів, навіть під час роботи як root. Якщо ввімкнено захист цілісності системи (SIP), він працює лише для програм, які не підписані або мають право \"Отримати дозвіл на завдання\", яке зазвичай застосовується лише до програм, скомпільованих вами самостійно.",
|
"hex.builtin.provider.process_memory.macos_limitations": "macOS не дозволяє належним чином зчитувати пам'ять з інших процесів, навіть під час роботи як root. Якщо ввімкнено захист цілісності системи (SIP), він працює лише для програм, які не підписані або мають право \"Отримати дозвіл на завдання\", яке зазвичай застосовується лише до програм, скомпільованих вами самостійно.",
|
||||||
"hex.builtin.setting.experiments.description": "Експерименти — це функції, які ще знаходяться в стадії розробки і можуть працювати некоректно.\n\nНе соромтеся їх випробовувати та повідомляти про будь-які проблеми, з якими ви стикаєтеся!",
|
"hex.builtin.setting.experiments.description": "Експерименти — це функції, які ще знаходяться в стадії розробки і можуть працювати некоректно.\n\nНе соромтеся їх випробовувати та повідомляти про будь-які проблеми, з якими ви стикаєтеся!",
|
||||||
"hex.builtin.setting.general.network": "Мережа",
|
"hex.builtin.setting.general.network": "Мережа",
|
||||||
"hex.builtin.setting.general.auto_backup_time": "Робити резервні копії проекту",
|
"hex.builtin.setting.general.backups.auto_backup_time": "Робити резервні копії проекту",
|
||||||
"hex.builtin.setting.general.max_mem_file_size": "Максимальний розмір файлу для завантаження в RAM",
|
"hex.builtin.setting.general.max_mem_file_size": "Максимальний розмір файлу для завантаження в RAM",
|
||||||
"hex.builtin.setting.general.max_mem_file_size.desc": "Невеликі файли завантажуються в пам'ять, щоб запобігти їх безпосередній модифікації на диску.\n\nЗбільшення цього розміру дозволяє завантажувати в пам'ять більші файли, перш ніж ImHex вдається до потокової передачі даних із диску.",
|
"hex.builtin.setting.general.max_mem_file_size.desc": "Невеликі файли завантажуються в пам'ять, щоб запобігти їх безпосередній модифікації на диску.\n\nЗбільшення цього розміру дозволяє завантажувати в пам'ять більші файли, перш ніж ImHex вдається до потокової передачі даних із диску.",
|
||||||
"hex.builtin.setting.general.sync_pattern_source": "Синхронізація вихідного коду шаблону між відкритими джерелами даних",
|
"hex.builtin.setting.general.sync_pattern_source": "Синхронізація вихідного коду шаблону між відкритими джерелами даних",
|
||||||
|
|
|
||||||
|
|
@ -467,10 +467,10 @@
|
||||||
"hex.builtin.setting.general": "通用",
|
"hex.builtin.setting.general": "通用",
|
||||||
"hex.builtin.setting.general.patterns": "模式",
|
"hex.builtin.setting.general.patterns": "模式",
|
||||||
"hex.builtin.setting.general.network": "网络",
|
"hex.builtin.setting.general.network": "网络",
|
||||||
"hex.builtin.setting.general.auto_backup_time": "定期备份项目",
|
"hex.builtin.setting.general.backups.auto_backup_time": "定期备份项目",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.simple": "每 {0}秒",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.simple": "每 {0}秒",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.extended": "每 {0}分 {1}秒",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.extended": "每 {0}分 {1}秒",
|
||||||
"hex.builtin.setting.general.auto_load_patterns": "自动加载支持的模式",
|
"hex.builtin.setting.general.auto_apply_patterns": "自动加载支持的模式",
|
||||||
"hex.builtin.setting.general.server_contact": "启用更新检查和使用统计",
|
"hex.builtin.setting.general.server_contact": "启用更新检查和使用统计",
|
||||||
"hex.builtin.setting.general.max_mem_file_size": "要加载到内存中的文件的最大大小",
|
"hex.builtin.setting.general.max_mem_file_size": "要加载到内存中的文件的最大大小",
|
||||||
"hex.builtin.setting.general.max_mem_file_size.desc": "小文件会被加载到内存中,以防止直接在磁盘上修改它们。\n\n增大这个大小可以让更大的文件在ImHex从磁盘读取数据之前被加载到内存中。",
|
"hex.builtin.setting.general.max_mem_file_size.desc": "小文件会被加载到内存中,以防止直接在磁盘上修改它们。\n\n增大这个大小可以让更大的文件在ImHex从磁盘读取数据之前被加载到内存中。",
|
||||||
|
|
|
||||||
|
|
@ -443,10 +443,10 @@
|
||||||
"hex.builtin.setting.folders.description": "Specify additional search paths for patterns, scripts, Yara rules and more",
|
"hex.builtin.setting.folders.description": "Specify additional search paths for patterns, scripts, Yara rules and more",
|
||||||
"hex.builtin.setting.folders.remove_folder": "從列表中移除目前選擇的資料夾",
|
"hex.builtin.setting.folders.remove_folder": "從列表中移除目前選擇的資料夾",
|
||||||
"hex.builtin.setting.general": "一般",
|
"hex.builtin.setting.general": "一般",
|
||||||
"hex.builtin.setting.general.auto_backup_time": "",
|
"hex.builtin.setting.general.backups.auto_backup_time": "",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.extended": "",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.extended": "",
|
||||||
"hex.builtin.setting.general.auto_backup_time.format.simple": "",
|
"hex.builtin.setting.general.backups.auto_backup_time.format.simple": "",
|
||||||
"hex.builtin.setting.general.auto_load_patterns": "自動載入支援的模式",
|
"hex.builtin.setting.general.auto_apply_patterns": "自動載入支援的模式",
|
||||||
"hex.builtin.setting.general.network": "",
|
"hex.builtin.setting.general.network": "",
|
||||||
"hex.builtin.setting.general.network_interface": "啟用網路介面",
|
"hex.builtin.setting.general.network_interface": "啟用網路介面",
|
||||||
"hex.builtin.setting.general.patterns": "",
|
"hex.builtin.setting.general.patterns": "",
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#include <fmt/chrono.h>
|
#include <fmt/chrono.h>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <romfs/romfs.hpp>
|
||||||
|
#include <toasts/toast_notification.hpp>
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
|
|
@ -103,6 +105,16 @@ namespace hex::plugin::builtin {
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleMCPServer() {
|
||||||
|
if (!ContentRegistry::MCP::isEnabled()) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
ContentRegistry::MCP::impl::getMcpServerInstance().disconnect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentRegistry::MCP::impl::getMcpServerInstance().listen();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerBackgroundServices() {
|
void registerBackgroundServices() {
|
||||||
|
|
@ -110,12 +122,17 @@ namespace hex::plugin::builtin {
|
||||||
s_networkInterfaceServiceEnabled = value.get<bool>(false);
|
s_networkInterfaceServiceEnabled = value.get<bool>(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
ContentRegistry::Settings::onChange("hex.builtin.setting.general", "hex.builtin.setting.general.auto_backup_time", [](const ContentRegistry::Settings::SettingsValue &value) {
|
ContentRegistry::Settings::onChange("hex.builtin.setting.general", "hex.builtin.setting.general.mcp_server", [](const ContentRegistry::Settings::SettingsValue &value) {
|
||||||
|
ContentRegistry::MCP::impl::setEnabled(value.get<bool>(false));
|
||||||
|
});
|
||||||
|
|
||||||
|
ContentRegistry::Settings::onChange("hex.builtin.setting.general", "hex.builtin.setting.general.backups.auto_backup_time", [](const ContentRegistry::Settings::SettingsValue &value) {
|
||||||
s_autoBackupTime = value.get<int>(0) * 30;
|
s_autoBackupTime = value.get<int>(0) * 30;
|
||||||
});
|
});
|
||||||
|
|
||||||
ContentRegistry::BackgroundServices::registerService("hex.builtin.background_service.network_interface", handleNetworkInterfaceService);
|
ContentRegistry::BackgroundServices::registerService("hex.builtin.background_service.network_interface", handleNetworkInterfaceService);
|
||||||
ContentRegistry::BackgroundServices::registerService("hex.builtin.background_service.auto_backup", handleAutoBackup);
|
ContentRegistry::BackgroundServices::registerService("hex.builtin.background_service.auto_backup", handleAutoBackup);
|
||||||
|
ContentRegistry::BackgroundServices::registerService("hex.builtin.background_service.mcp", handleMCPServer);
|
||||||
|
|
||||||
EventProviderDirtied::subscribe([](prv::Provider *) {
|
EventProviderDirtied::subscribe([](prv::Provider *) {
|
||||||
s_dataDirty = true;
|
s_dataDirty = true;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
|
#include <iostream>
|
||||||
#include <content/command_line_interface.hpp>
|
#include <content/command_line_interface.hpp>
|
||||||
|
#include <hex/mcp/client.hpp>
|
||||||
|
|
||||||
#include <hex/api/imhex_api/system.hpp>
|
#include <hex/api/imhex_api/system.hpp>
|
||||||
#include <hex/api/imhex_api/hex_editor.hpp>
|
#include <hex/api/imhex_api/hex_editor.hpp>
|
||||||
|
|
@ -358,10 +360,10 @@ namespace hex::plugin::builtin {
|
||||||
std::fs::path filePath = reinterpret_cast<const char8_t*>(args[0].data());
|
std::fs::path filePath = reinterpret_cast<const char8_t*>(args[0].data());
|
||||||
|
|
||||||
FileProvider provider;
|
FileProvider provider;
|
||||||
|
|
||||||
provider.setPath(filePath);
|
provider.setPath(filePath);
|
||||||
if (!provider.open()) {
|
auto result = provider.open();
|
||||||
log::println("Failed to open file '{}'", args[0]);
|
if (result.isFailure()) {
|
||||||
|
log::println("Failed to open file '{}': {}", args[0], result.getErrorMessage());
|
||||||
std::exit(EXIT_FAILURE);
|
std::exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -530,6 +532,14 @@ namespace hex::plugin::builtin {
|
||||||
ContentRegistry::Views::setFullScreenView<ViewFullScreenFileInfo>(path);
|
ContentRegistry::Views::setFullScreenView<ViewFullScreenFileInfo>(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleMCPCommand(const std::vector<std::string> &) {
|
||||||
|
mcp::Client client;
|
||||||
|
|
||||||
|
auto result = client.run(std::cin, std::cout);
|
||||||
|
std::fprintf(stderr, "MCP Client disconnected!\n");
|
||||||
|
std::exit(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void registerCommandForwarders() {
|
void registerCommandForwarders() {
|
||||||
hex::subcommands::registerSubCommand("open", [](const std::vector<std::string> &args){
|
hex::subcommands::registerSubCommand("open", [](const std::vector<std::string> &args){
|
||||||
|
|
|
||||||
|
|
@ -287,23 +287,23 @@ namespace hex::plugin::builtin {
|
||||||
"@",
|
"@",
|
||||||
"hex.builtin.command.goto.desc",
|
"hex.builtin.command.goto.desc",
|
||||||
[](auto input) {
|
[](auto input) {
|
||||||
wolv::math_eval::MathEvaluator<long double> evaluator;
|
wolv::math_eval::MathEvaluator<i64> evaluator;
|
||||||
evaluator.registerStandardVariables();
|
evaluator.registerStandardVariables();
|
||||||
evaluator.registerStandardFunctions();
|
evaluator.registerStandardFunctions();
|
||||||
|
|
||||||
std::optional<long double> result = evaluator.evaluate(input);
|
const auto result = evaluator.evaluate(input);
|
||||||
if (result.has_value())
|
if (result.has_value())
|
||||||
return fmt::format("hex.builtin.command.goto.result"_lang, result.value());
|
return fmt::format("hex.builtin.command.goto.result"_lang, static_cast<u64>(result.value()));
|
||||||
else if (evaluator.hasError())
|
else if (evaluator.hasError())
|
||||||
return fmt::format("Error: {}", *evaluator.getLastError());
|
return fmt::format("Error: {}", *evaluator.getLastError());
|
||||||
else
|
else
|
||||||
return std::string("???");
|
return std::string("???");
|
||||||
}, [](auto input) -> std::optional<std::string> {
|
}, [](auto input) -> std::optional<std::string> {
|
||||||
wolv::math_eval::MathEvaluator<long double> evaluator;
|
wolv::math_eval::MathEvaluator<i64> evaluator;
|
||||||
evaluator.registerStandardVariables();
|
evaluator.registerStandardVariables();
|
||||||
evaluator.registerStandardFunctions();
|
evaluator.registerStandardFunctions();
|
||||||
|
|
||||||
std::optional<long double> result = evaluator.evaluate(input);
|
const auto result = evaluator.evaluate(input);
|
||||||
if (result.has_value()) {
|
if (result.has_value()) {
|
||||||
ImHexApi::HexEditor::setSelection(result.value(), 1);
|
ImHexApi::HexEditor::setSelection(result.value(), 1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,8 @@ namespace hex::plugin::builtin {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<std::unsigned_integral T, size_t Size = sizeof(T)>
|
template<std::unsigned_integral T, size_t Size = sizeof(T)>
|
||||||
static std::vector<u8> stringToUnsigned(const std::string &value, std::endian endian) requires(sizeof(T) <= sizeof(u64)) {
|
static ContentRegistry::DataInspector::impl::EditingFunction stringToUnsigned() requires(sizeof(T) <= sizeof(u64)) {
|
||||||
|
return ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
const auto result = wolv::util::from_chars<u64>(value).value_or(0);
|
const auto result = wolv::util::from_chars<u64>(value).value_or(0);
|
||||||
if (result > std::numeric_limits<T>::max()) return {};
|
if (result > std::numeric_limits<T>::max()) return {};
|
||||||
|
|
||||||
|
|
@ -44,10 +45,12 @@ namespace hex::plugin::builtin {
|
||||||
std::reverse(bytes.begin(), bytes.end());
|
std::reverse(bytes.begin(), bytes.end());
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::signed_integral T, size_t Size = sizeof(T)>
|
template<std::signed_integral T, size_t Size = sizeof(T)>
|
||||||
static std::vector<u8> stringToSigned(const std::string &value, std::endian endian) requires(sizeof(T) <= sizeof(u64)) {
|
static ContentRegistry::DataInspector::impl::EditingFunction stringToSigned() requires(sizeof(T) <= sizeof(u64)) {
|
||||||
|
return ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
const auto result = wolv::util::from_chars<i64>(value).value_or(0);
|
const auto result = wolv::util::from_chars<i64>(value).value_or(0);
|
||||||
if (result > std::numeric_limits<T>::max() || result < std::numeric_limits<T>::min()) return {};
|
if (result > std::numeric_limits<T>::max() || result < std::numeric_limits<T>::min()) return {};
|
||||||
|
|
||||||
|
|
@ -58,10 +61,12 @@ namespace hex::plugin::builtin {
|
||||||
std::reverse(bytes.begin(), bytes.end());
|
std::reverse(bytes.begin(), bytes.end());
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::floating_point T>
|
template<std::floating_point T>
|
||||||
static std::vector<u8> stringToFloat(const std::string &value, std::endian endian) requires(sizeof(T) <= sizeof(long double)) {
|
static ContentRegistry::DataInspector::impl::EditingFunction stringToFloat() requires(sizeof(T) <= sizeof(long double)) {
|
||||||
|
return ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
const T result = wolv::util::from_chars<double>(value).value_or(0);
|
const T result = wolv::util::from_chars<double>(value).value_or(0);
|
||||||
|
|
||||||
std::vector<u8> bytes(sizeof(T), 0x00);
|
std::vector<u8> bytes(sizeof(T), 0x00);
|
||||||
|
|
@ -71,16 +76,17 @@ namespace hex::plugin::builtin {
|
||||||
std::reverse(bytes.begin(), bytes.end());
|
std::reverse(bytes.begin(), bytes.end());
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::integral T, size_t Size = sizeof(T)>
|
template<std::integral T, size_t Size = sizeof(T)>
|
||||||
static std::vector<u8> stringToInteger(const std::string &value, std::endian endian) requires(sizeof(T) <= sizeof(u64)) {
|
static ContentRegistry::DataInspector::impl::EditingFunction stringToInteger() requires(sizeof(T) <= sizeof(u64)) {
|
||||||
if constexpr (std::unsigned_integral<T>)
|
if constexpr (std::unsigned_integral<T>)
|
||||||
return stringToUnsigned<T, Size>(value, endian);
|
return stringToUnsigned<T, Size>();
|
||||||
else if constexpr (std::signed_integral<T>)
|
else if constexpr (std::signed_integral<T>)
|
||||||
return stringToSigned<T, Size>(value, endian);
|
return stringToSigned<T, Size>();
|
||||||
else
|
else
|
||||||
return {};
|
static_assert("Unsupported type for stringToInteger");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::unsigned_integral T, size_t Size = sizeof(T)>
|
template<std::unsigned_integral T, size_t Size = sizeof(T)>
|
||||||
|
|
@ -154,7 +160,8 @@ namespace hex::plugin::builtin {
|
||||||
ImGui::TextUnformatted(binary.c_str());
|
ImGui::TextUnformatted(binary.c_str());
|
||||||
return binary;
|
return binary;
|
||||||
};
|
};
|
||||||
}, [](const std::string &value, std::endian endian) -> std::vector<u8> {
|
},
|
||||||
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::ignore = endian;
|
std::ignore = endian;
|
||||||
|
|
||||||
std::string binary = value;
|
std::string binary = value;
|
||||||
|
|
@ -167,69 +174,69 @@ namespace hex::plugin::builtin {
|
||||||
return { result.value() };
|
return { result.value() };
|
||||||
else
|
else
|
||||||
return { };
|
return { };
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u8", sizeof(u8),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.u8", sizeof(u8),
|
||||||
drawString<u8>(integerToString<u8>),
|
drawString<u8>(integerToString<u8>),
|
||||||
stringToInteger<u8>
|
stringToInteger<u8>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i8", sizeof(i8),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.i8", sizeof(i8),
|
||||||
drawString<i8>(integerToString<i8>),
|
drawString<i8>(integerToString<i8>),
|
||||||
stringToInteger<i8>
|
stringToInteger<i8>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u16", sizeof(u16),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.u16", sizeof(u16),
|
||||||
drawString<u16>(integerToString<u16>),
|
drawString<u16>(integerToString<u16>),
|
||||||
stringToInteger<u16>
|
stringToInteger<u16>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i16", sizeof(i16),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.i16", sizeof(i16),
|
||||||
drawString<i16>(integerToString<i16>),
|
drawString<i16>(integerToString<i16>),
|
||||||
stringToInteger<i16>
|
stringToInteger<i16>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u24", 3,
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.u24", 3,
|
||||||
drawString<u32, 3>(integerToString<u32, 3>),
|
drawString<u32, 3>(integerToString<u32, 3>),
|
||||||
stringToInteger<u32, 3>
|
stringToInteger<u32, 3>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i24", 3,
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.i24", 3,
|
||||||
drawString<i32, 3>(integerToString<i32, 3>),
|
drawString<i32, 3>(integerToString<i32, 3>),
|
||||||
stringToInteger<i32, 3>
|
stringToInteger<i32, 3>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u32", sizeof(u32),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.u32", sizeof(u32),
|
||||||
drawString<u32>(integerToString<u32>),
|
drawString<u32>(integerToString<u32>),
|
||||||
stringToInteger<u32>
|
stringToInteger<u32>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i32", sizeof(i32),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.i32", sizeof(i32),
|
||||||
drawString<i32>(integerToString<i32>),
|
drawString<i32>(integerToString<i32>),
|
||||||
stringToInteger<i32>
|
stringToInteger<i32>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u48", 6,
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.u48", 6,
|
||||||
drawString<u64, 6>(integerToString<u64, 6>),
|
drawString<u64, 6>(integerToString<u64, 6>),
|
||||||
stringToInteger<u64, 6>
|
stringToInteger<u64, 6>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i48", 6,
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.i48", 6,
|
||||||
drawString<i64, 6>(integerToString<i64, 6>),
|
drawString<i64, 6>(integerToString<i64, 6>),
|
||||||
stringToInteger<i64, 6>
|
stringToInteger<i64, 6>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u64", sizeof(u64),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.u64", sizeof(u64),
|
||||||
drawString<u64>(integerToString<u64>),
|
drawString<u64>(integerToString<u64>),
|
||||||
stringToInteger<u64>
|
stringToInteger<u64>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i64", sizeof(i64),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.i64", sizeof(i64),
|
||||||
drawString<i64>(integerToString<i64>),
|
drawString<i64>(integerToString<i64>),
|
||||||
stringToInteger<i64>
|
stringToInteger<i64>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.float16", sizeof(u16),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.float16", sizeof(u16),
|
||||||
|
|
@ -255,7 +262,7 @@ namespace hex::plugin::builtin {
|
||||||
auto value = fmt::format(fmt::runtime(formatString), hex::changeEndianness(result, endian));
|
auto value = fmt::format(fmt::runtime(formatString), hex::changeEndianness(result, endian));
|
||||||
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
stringToFloat<float>
|
stringToFloat<float>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.double", sizeof(double),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.double", sizeof(double),
|
||||||
|
|
@ -268,7 +275,7 @@ namespace hex::plugin::builtin {
|
||||||
auto value = fmt::format(fmt::runtime(formatString), hex::changeEndianness(result, endian));
|
auto value = fmt::format(fmt::runtime(formatString), hex::changeEndianness(result, endian));
|
||||||
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
stringToFloat<double>
|
stringToFloat<double>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.long_double", sizeof(long double),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.long_double", sizeof(long double),
|
||||||
|
|
@ -281,7 +288,7 @@ namespace hex::plugin::builtin {
|
||||||
auto value = fmt::format(fmt::runtime(formatString), hex::changeEndianness(result, endian));
|
auto value = fmt::format(fmt::runtime(formatString), hex::changeEndianness(result, endian));
|
||||||
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
stringToFloat<long double>
|
stringToFloat<long double>()
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.bfloat16", sizeof(u16),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.bfloat16", sizeof(u16),
|
||||||
|
|
@ -359,11 +366,11 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::ignore = endian;
|
std::ignore = endian;
|
||||||
|
|
||||||
return hex::crypt::encodeSleb128(wolv::util::from_chars<i64>(value).value_or(0));
|
return hex::crypt::encodeSleb128(wolv::util::from_chars<i64>(value).value_or(0));
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.uleb128", 1, (sizeof(u128) * 8 / 7) + 1,
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.uleb128", 1, (sizeof(u128) * 8 / 7) + 1,
|
||||||
|
|
@ -376,11 +383,11 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::ignore = endian;
|
std::ignore = endian;
|
||||||
|
|
||||||
return hex::crypt::encodeUleb128(wolv::util::from_chars<u64>(value).value_or(0));
|
return hex::crypt::encodeUleb128(wolv::util::from_chars<u64>(value).value_or(0));
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.bool", sizeof(bool),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.bool", sizeof(bool),
|
||||||
|
|
@ -411,13 +418,13 @@ namespace hex::plugin::builtin {
|
||||||
auto value = makePrintable(*reinterpret_cast<char8_t *>(buffer.data()));
|
auto value = makePrintable(*reinterpret_cast<char8_t *>(buffer.data()));
|
||||||
return [value] { ImGuiExt::TextFormatted("'{0}'", value.c_str()); return value; };
|
return [value] { ImGuiExt::TextFormatted("'{0}'", value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::ignore = endian;
|
std::ignore = endian;
|
||||||
|
|
||||||
if (value.length() > 1) return { };
|
if (value.length() > 1) return { };
|
||||||
|
|
||||||
return { u8(value[0]) };
|
return { u8(value[0]) };
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.wide", sizeof(wchar_t),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.wide", sizeof(wchar_t),
|
||||||
|
|
@ -432,7 +439,7 @@ namespace hex::plugin::builtin {
|
||||||
auto value = fmt::format("{0}", c <= 255 ? makePrintable(c) : wolv::util::wstringToUtf8(std::wstring(&c, 1)).value_or("???"));
|
auto value = fmt::format("{0}", c <= 255 ? makePrintable(c) : wolv::util::wstringToUtf8(std::wstring(&c, 1)).value_or("???"));
|
||||||
return [value] { ImGuiExt::TextFormatted("L'{0}'", value.c_str()); return value; };
|
return [value] { ImGuiExt::TextFormatted("L'{0}'", value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::vector<u8> bytes;
|
std::vector<u8> bytes;
|
||||||
auto wideString = wolv::util::utf8ToWstring(value);
|
auto wideString = wolv::util::utf8ToWstring(value);
|
||||||
if (!wideString.has_value())
|
if (!wideString.has_value())
|
||||||
|
|
@ -445,7 +452,7 @@ namespace hex::plugin::builtin {
|
||||||
std::reverse(bytes.begin(), bytes.end());
|
std::reverse(bytes.begin(), bytes.end());
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.char16", sizeof(char16_t),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.char16", sizeof(char16_t),
|
||||||
|
|
@ -460,7 +467,7 @@ namespace hex::plugin::builtin {
|
||||||
auto value = fmt::format("{0}", c <= 255 ? makePrintable(c) : wolv::util::utf16ToUtf8(std::u16string(&c, 1)).value_or("???"));
|
auto value = fmt::format("{0}", c <= 255 ? makePrintable(c) : wolv::util::utf16ToUtf8(std::u16string(&c, 1)).value_or("???"));
|
||||||
return [value] { ImGuiExt::TextFormatted("u'{0}'", value.c_str()); return value; };
|
return [value] { ImGuiExt::TextFormatted("u'{0}'", value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::vector<u8> bytes;
|
std::vector<u8> bytes;
|
||||||
auto wideString = wolv::util::utf8ToUtf16(value);
|
auto wideString = wolv::util::utf8ToUtf16(value);
|
||||||
if (!wideString.has_value())
|
if (!wideString.has_value())
|
||||||
|
|
@ -473,7 +480,7 @@ namespace hex::plugin::builtin {
|
||||||
std::reverse(bytes.begin(), bytes.end());
|
std::reverse(bytes.begin(), bytes.end());
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.char32", sizeof(char32_t),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.char32", sizeof(char32_t),
|
||||||
|
|
@ -488,7 +495,7 @@ namespace hex::plugin::builtin {
|
||||||
auto value = fmt::format("{0}", c <= 255 ? makePrintable(c) : wolv::util::utf32ToUtf8(std::u32string(&c, 1)).value_or("???"));
|
auto value = fmt::format("{0}", c <= 255 ? makePrintable(c) : wolv::util::utf32ToUtf8(std::u32string(&c, 1)).value_or("???"));
|
||||||
return [value] { ImGuiExt::TextFormatted("U'{0}'", value.c_str()); return value; };
|
return [value] { ImGuiExt::TextFormatted("U'{0}'", value.c_str()); return value; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::vector<u8> bytes;
|
std::vector<u8> bytes;
|
||||||
auto wideString = wolv::util::utf8ToUtf32(value);
|
auto wideString = wolv::util::utf8ToUtf32(value);
|
||||||
if (!wideString.has_value())
|
if (!wideString.has_value())
|
||||||
|
|
@ -501,7 +508,7 @@ namespace hex::plugin::builtin {
|
||||||
std::reverse(bytes.begin(), bytes.end());
|
std::reverse(bytes.begin(), bytes.end());
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.utf8", sizeof(char8_t) * 4,
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.utf8", sizeof(char8_t) * 4,
|
||||||
|
|
@ -551,11 +558,11 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
return [value, copyValue] { ImGuiExt::TextFormatted("\"{0}\"", value.c_str()); return copyValue; };
|
return [value, copyValue] { ImGuiExt::TextFormatted("\"{0}\"", value.c_str()); return copyValue; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::ignore = endian;
|
std::ignore = endian;
|
||||||
|
|
||||||
return hex::decodeByteString(value);
|
return hex::decodeByteString(value);
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.wstring", sizeof(wchar_t),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.wstring", sizeof(wchar_t),
|
||||||
|
|
@ -588,11 +595,20 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
return [value, copyValue] { ImGuiExt::TextFormatted("L\"{0}\"", value.c_str()); return copyValue; };
|
return [value, copyValue] { ImGuiExt::TextFormatted("L\"{0}\"", value.c_str()); return copyValue; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::ignore = endian;
|
auto utf8 = hex::decodeByteString(value);
|
||||||
|
auto wstring = wolv::util::utf8ToWstring({ utf8.begin(), utf8.end() });
|
||||||
|
if (!wstring.has_value())
|
||||||
|
return {};
|
||||||
|
|
||||||
return hex::decodeByteString(value);
|
for (auto &c : wstring.value()) {
|
||||||
|
c = hex::changeEndianness(c, endian);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<u8> bytes(wstring->size() * sizeof(wchar_t), 0x00);
|
||||||
|
std::memcpy(bytes.data(), wstring->data(), bytes.size());
|
||||||
|
return bytes;
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.string16", sizeof(char16_t),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.string16", sizeof(char16_t),
|
||||||
|
|
@ -625,11 +641,20 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
return [value, copyValue] { ImGuiExt::TextFormatted("u\"{0}\"", value.c_str()); return copyValue; };
|
return [value, copyValue] { ImGuiExt::TextFormatted("u\"{0}\"", value.c_str()); return copyValue; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::ignore = endian;
|
auto utf8 = hex::decodeByteString(value);
|
||||||
|
auto utf16 = wolv::util::utf8ToUtf16({ utf8.begin(), utf8.end() });
|
||||||
|
if (!utf16.has_value())
|
||||||
|
return {};
|
||||||
|
|
||||||
return hex::decodeByteString(value);
|
for (auto &c : utf16.value()) {
|
||||||
|
c = hex::changeEndianness(c, endian);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<u8> bytes(utf16->size() * sizeof(char16_t), 0x00);
|
||||||
|
std::memcpy(bytes.data(), utf16->data(), bytes.size());
|
||||||
|
return bytes;
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.string32", sizeof(char32_t),
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.string32", sizeof(char32_t),
|
||||||
|
|
@ -662,11 +687,20 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
return [value, copyValue] { ImGuiExt::TextFormatted("U\"{0}\"", value.c_str()); return copyValue; };
|
return [value, copyValue] { ImGuiExt::TextFormatted("U\"{0}\"", value.c_str()); return copyValue; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||||
std::ignore = endian;
|
auto utf8 = hex::decodeByteString(value);
|
||||||
|
auto utf32 = wolv::util::utf8ToUtf32({ utf8.begin(), utf8.end() });
|
||||||
|
if (!utf32.has_value())
|
||||||
|
return {};
|
||||||
|
|
||||||
return hex::decodeByteString(value);
|
for (auto &c : utf32.value()) {
|
||||||
|
c = hex::changeEndianness(c, endian);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<u8> bytes(utf32->size() * sizeof(char32_t), 0x00);
|
||||||
|
std::memcpy(bytes.data(), utf32->data(), bytes.size());
|
||||||
|
return bytes;
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.custom_encoding", 1, [encodingFile = EncodingFile()](const std::vector<u8> &, std::endian, Style) mutable {
|
ContentRegistry::DataInspector::add("hex.builtin.inspector.custom_encoding", 1, [encodingFile = EncodingFile()](const std::vector<u8> &, std::endian, Style) mutable {
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
static void openFile(const std::fs::path &path) {
|
static void openFile(const std::fs::path &path) {
|
||||||
|
TaskManager::doLater([path] {
|
||||||
if (path.extension() == ".hexproj") {
|
if (path.extension() == ".hexproj") {
|
||||||
if (!ProjectFile::load(path)) {
|
if (!ProjectFile::load(path)) {
|
||||||
ui::ToastError::open(fmt::format("hex.builtin.popup.error.project.load"_lang, wolv::util::toUTF8String(path)));
|
ui::ToastError::open(fmt::format("hex.builtin.popup.error.project.load"_lang, wolv::util::toUTF8String(path)));
|
||||||
|
|
@ -49,21 +50,17 @@ namespace hex::plugin::builtin {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto provider = ImHexApi::Provider::createProvider("hex.builtin.provider.file", true);
|
auto provider = ImHexApi::Provider::createProvider("hex.builtin.provider.file", true);
|
||||||
if (auto *fileProvider = dynamic_cast<FileProvider*>(provider); fileProvider != nullptr) {
|
if (auto *fileProvider = dynamic_cast<FileProvider*>(provider.get()); fileProvider != nullptr) {
|
||||||
fileProvider->setPath(path);
|
fileProvider->setPath(path);
|
||||||
if (!provider->open() || !provider->isAvailable()) {
|
|
||||||
ui::ToastError::open(fmt::format("hex.builtin.provider.error.open"_lang, provider->getErrorMessage()));
|
|
||||||
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventProviderOpened::post(fileProvider);
|
ImHexApi::Provider::openProvider(provider);
|
||||||
|
|
||||||
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name");
|
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name");
|
||||||
ImHexApi::Provider::setCurrentProvider(provider);
|
|
||||||
|
|
||||||
glfwRequestWindowAttention(ImHexApi::System::getMainWindowHandle());
|
glfwRequestWindowAttention(ImHexApi::System::getMainWindowHandle());
|
||||||
glfwFocusWindow(ImHexApi::System::getMainWindowHandle());
|
glfwFocusWindow(ImHexApi::System::getMainWindowHandle());
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerEventHandlers() {
|
void registerEventHandlers() {
|
||||||
|
|
@ -180,11 +177,8 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
RequestOpenWindow::subscribe([](const std::string &name) {
|
RequestOpenWindow::subscribe([](const std::string &name) {
|
||||||
if (name == "Create File") {
|
if (name == "Create File") {
|
||||||
auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true);
|
auto newProvider = ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true);
|
||||||
if (newProvider != nullptr && !newProvider->open())
|
ImHexApi::Provider::openProvider(newProvider);
|
||||||
hex::ImHexApi::Provider::remove(newProvider);
|
|
||||||
else
|
|
||||||
EventProviderOpened::post(newProvider);
|
|
||||||
} else if (name == "Open File") {
|
} else if (name == "Open File") {
|
||||||
fs::openFileBrowser(fs::DialogMode::Open, { }, [](const auto &path) {
|
fs::openFileBrowser(fs::DialogMode::Open, { }, [](const auto &path) {
|
||||||
if (path.extension() == ".hexproj") {
|
if (path.extension() == ".hexproj") {
|
||||||
|
|
@ -195,20 +189,15 @@ namespace hex::plugin::builtin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto newProvider = static_cast<FileProvider*>(
|
auto provider = ImHexApi::Provider::createProvider("hex.builtin.provider.file", true);
|
||||||
ImHexApi::Provider::createProvider("hex.builtin.provider.file", true)
|
auto newProvider = static_cast<FileProvider*>(provider.get());
|
||||||
);
|
|
||||||
|
|
||||||
if (newProvider == nullptr)
|
if (newProvider == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
newProvider->setPath(path);
|
newProvider->setPath(path);
|
||||||
if (!newProvider->open()) {
|
ImHexApi::Provider::openProvider(provider);
|
||||||
hex::ImHexApi::Provider::remove(newProvider);
|
|
||||||
} else {
|
|
||||||
EventProviderOpened::post(newProvider);
|
|
||||||
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name");
|
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name");
|
||||||
}
|
|
||||||
}, {}, true);
|
}, {}, true);
|
||||||
} else if (name == "Open Project") {
|
} else if (name == "Open Project") {
|
||||||
fs::openFileBrowser(fs::DialogMode::Open, { {"Project File", "hexproj"} },
|
fs::openFileBrowser(fs::DialogMode::Open, { {"Project File", "hexproj"} },
|
||||||
|
|
@ -225,34 +214,20 @@ namespace hex::plugin::builtin {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handles the provider initialization, and calls EventProviderOpened if successful
|
// Handles the provider initialization, and calls EventProviderOpened if successful
|
||||||
EventProviderCreated::subscribe([](hex::prv::Provider *provider) {
|
EventProviderCreated::subscribe([](std::shared_ptr<prv::Provider> provider) {
|
||||||
if (provider->shouldSkipLoadInterface())
|
if (provider->shouldSkipLoadInterface())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (auto *filePickerProvider = dynamic_cast<prv::IProviderFilePicker*>(provider); filePickerProvider != nullptr) {
|
if (auto *filePickerProvider = dynamic_cast<prv::IProviderFilePicker*>(provider.get()); filePickerProvider != nullptr) {
|
||||||
if (!filePickerProvider->handleFilePicker()) {
|
if (!filePickerProvider->handleFilePicker()) {
|
||||||
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
|
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider.get()); });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskManager::createBlockingTask("hex.builtin.provider.opening", TaskManager::NoProgress, [provider]() {
|
ImHexApi::Provider::openProvider(provider);
|
||||||
if (!provider->open()) {
|
|
||||||
ui::ToastError::open(fmt::format("hex.builtin.provider.error.open"_lang, provider->getErrorMessage()));
|
|
||||||
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
|
|
||||||
} else {
|
|
||||||
TaskManager::doLater([provider]{ EventProviderOpened::post(provider); });
|
|
||||||
}
|
}
|
||||||
});
|
else if (dynamic_cast<prv::IProviderLoadInterface*>(provider.get()) == nullptr) {
|
||||||
}
|
ImHexApi::Provider::openProvider(provider);
|
||||||
else if (dynamic_cast<prv::IProviderLoadInterface*>(provider) == nullptr) {
|
|
||||||
TaskManager::createBlockingTask("hex.builtin.provider.opening", TaskManager::NoProgress, [provider]() {
|
|
||||||
if (!provider->open() || !provider->isAvailable()) {
|
|
||||||
ui::ToastError::open(fmt::format("hex.builtin.provider.error.open"_lang, provider->getErrorMessage()));
|
|
||||||
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
|
|
||||||
} else {
|
|
||||||
TaskManager::doLater([provider]{ EventProviderOpened::post(provider); });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -418,6 +393,25 @@ namespace hex::plugin::builtin {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
RequestOpenProvider::subscribe([](std::shared_ptr<prv::Provider> provider) {
|
||||||
|
TaskManager::createBlockingTask("hex.builtin.provider.opening", TaskManager::NoProgress, [provider]() {
|
||||||
|
auto result = provider->open();
|
||||||
|
if (result.isFailure()) {
|
||||||
|
ui::ToastError::open(fmt::format("hex.builtin.provider.error.open"_lang, result.getErrorMessage()));
|
||||||
|
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider.get()); });
|
||||||
|
} else if (result.isRedirecting()) {
|
||||||
|
TaskManager::doLater([result, provider] {
|
||||||
|
ImHexApi::Provider::remove(provider.get());
|
||||||
|
ImHexApi::Provider::setCurrentProvider(result.getRedirectProvider());
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (result.isWarning())
|
||||||
|
ui::ToastWarning::open(std::string(result.getErrorMessage()));
|
||||||
|
TaskManager::doLater([provider]{ EventProviderOpened::post(provider.get()); });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
fs::setFileBrowserErrorCallback([](const std::string& errMsg){
|
fs::setFileBrowserErrorCallback([](const std::string& errMsg){
|
||||||
#if defined(NFD_PORTAL)
|
#if defined(NFD_PORTAL)
|
||||||
ui::PopupError::open(fmt::format("hex.builtin.popup.error.file_dialog.portal"_lang, errMsg));
|
ui::PopupError::open(fmt::format("hex.builtin.popup.error.file_dialog.portal"_lang, errMsg));
|
||||||
|
|
|
||||||
|
|
@ -377,10 +377,10 @@ namespace hex::plugin::builtin {
|
||||||
/* Create File */
|
/* Create File */
|
||||||
ContentRegistry::UserInterface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.create_file" }, ICON_VS_FILE, 1050, CTRLCMD + Keys::N + AllowWhileTyping + ShowOnWelcomeScreen, [] {
|
ContentRegistry::UserInterface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.create_file" }, ICON_VS_FILE, 1050, CTRLCMD + Keys::N + AllowWhileTyping + ShowOnWelcomeScreen, [] {
|
||||||
auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true);
|
auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true);
|
||||||
if (newProvider != nullptr && !newProvider->open())
|
if (newProvider != nullptr && newProvider->open().isFailure())
|
||||||
hex::ImHexApi::Provider::remove(newProvider);
|
hex::ImHexApi::Provider::remove(newProvider.get());
|
||||||
else
|
else
|
||||||
EventProviderOpened::post(newProvider);
|
EventProviderOpened::post(newProvider.get());
|
||||||
}, noRunningTasks, ContentRegistry::Views::getViewByName("hex.builtin.view.hex_editor.name"));
|
}, noRunningTasks, ContentRegistry::Views::getViewByName("hex.builtin.view.hex_editor.name"));
|
||||||
|
|
||||||
/* Open File */
|
/* Open File */
|
||||||
|
|
@ -401,7 +401,7 @@ namespace hex::plugin::builtin {
|
||||||
auto provider = ImHexApi::Provider::get();
|
auto provider = ImHexApi::Provider::get();
|
||||||
|
|
||||||
provider->close();
|
provider->close();
|
||||||
if (!provider->open())
|
if (provider->open().isFailure())
|
||||||
ImHexApi::Provider::remove(provider, true);
|
ImHexApi::Provider::remove(provider, true);
|
||||||
|
|
||||||
EventDataChanged::post(provider);
|
EventDataChanged::post(provider);
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,6 @@
|
||||||
|
|
||||||
#include <popups/popup_file_chooser.hpp>
|
#include <popups/popup_file_chooser.hpp>
|
||||||
|
|
||||||
#include <ui/text_editor.hpp>
|
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
PopupDecodedString::PopupDecodedString(std::string decodedString) : m_decodedString(std::move(decodedString)) {
|
PopupDecodedString::PopupDecodedString(std::string decodedString) : m_decodedString(std::move(decodedString)) {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@
|
||||||
|
|
||||||
#include <fonts/vscode_icons.hpp>
|
#include <fonts/vscode_icons.hpp>
|
||||||
|
|
||||||
#include <ui/text_editor.hpp>
|
|
||||||
#include <wolv/literals.hpp>
|
#include <wolv/literals.hpp>
|
||||||
|
|
||||||
using namespace wolv::literals;
|
using namespace wolv::literals;
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,6 @@
|
||||||
|
|
||||||
#include <popups/popup_file_chooser.hpp>
|
#include <popups/popup_file_chooser.hpp>
|
||||||
|
|
||||||
#include <ui/text_editor.hpp>
|
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
PerProvider<std::string> PopupFind::s_inputString;
|
PerProvider<std::string> PopupFind::s_inputString;
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue