mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-28 07:47:03 -05:00
Compare commits
76 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76cf877115 | ||
|
|
8e4ccef52f | ||
|
|
b78a1024c1 | ||
|
|
fbae871d65 | ||
|
|
1a9fa0875b | ||
|
|
96232c2d80 | ||
|
|
6405c75242 | ||
|
|
5a853569e6 | ||
|
|
ea9d965ffe | ||
|
|
8b84c47b73 | ||
|
|
a3cd6e6a40 | ||
|
|
2f707afa67 | ||
|
|
765c8f4fe2 | ||
|
|
4120e10a95 | ||
|
|
67ec26b22a | ||
|
|
937ca4a327 | ||
|
|
96587415f6 | ||
|
|
b2f062cf10 | ||
|
|
91ef40ec99 | ||
|
|
684a9b3009 | ||
|
|
51d773cf14 | ||
|
|
cae063985a | ||
|
|
798bd25202 | ||
|
|
11df253fd3 | ||
|
|
a44278b1fe | ||
|
|
cd7705664d | ||
|
|
23e484c468 | ||
|
|
c4c8c46c11 | ||
|
|
f633c3f33a | ||
|
|
b8bcb815c8 | ||
|
|
81826df897 | ||
|
|
f6b2251205 | ||
|
|
1a7fefbc22 | ||
|
|
fdc1434cc6 | ||
|
|
230568f681 | ||
|
|
48c869fc89 | ||
|
|
4222904be9 | ||
|
|
20b4630faa | ||
|
|
6ddf2bb9fd | ||
|
|
77f049f0aa | ||
|
|
588412543c | ||
|
|
9939007fcf | ||
|
|
119f6f78b9 | ||
|
|
e2e397f188 | ||
|
|
60e2c32ae0 | ||
|
|
febd46ec58 | ||
|
|
bb9a0517fe | ||
|
|
e03d3d9f36 | ||
|
|
08daaec380 | ||
|
|
5a9f44e696 | ||
|
|
c95cbc5933 | ||
|
|
516a2f119e | ||
|
|
99e81b53af | ||
|
|
8bce2b072c | ||
|
|
539a00ae5d | ||
|
|
38075a1438 | ||
|
|
2c82d561c0 | ||
|
|
48e72a88c2 | ||
|
|
95c9168e25 | ||
|
|
64cbc16f78 | ||
|
|
b5f63e899c | ||
|
|
0a994d61b3 | ||
|
|
a8237326ad | ||
|
|
1253d68256 | ||
|
|
c944750f4d | ||
|
|
fb21f11554 | ||
|
|
d8e54e535b | ||
|
|
59afa06bf4 | ||
|
|
358f961f50 | ||
|
|
fc1b30eef2 | ||
|
|
596564ec48 | ||
|
|
a652b95816 | ||
|
|
0e3ce90db7 | ||
|
|
a3f31da365 | ||
|
|
27518cc584 | ||
|
|
3bcce0a243 |
137
.clang-tidy
137
.clang-tidy
@@ -1,69 +1,68 @@
|
||||
# Generated from CLion Inspection settings
|
||||
---
|
||||
Checks: '-*,
|
||||
mpi-*,
|
||||
bugprone-*,
|
||||
-bugprone-signal-handler,
|
||||
-bugprone-narrowing-conversions,
|
||||
-bugprone-redundant-branch-condition,
|
||||
-bugprone-exception-escape,
|
||||
-bugprone-shared-ptr-array-mismatch,
|
||||
-bugprone-implicit-widening-of-multiplication-result,
|
||||
-bugprone-signed-char-misuse,
|
||||
-bugprone-unhandled-exception-at-new,
|
||||
-bugprone-infinite-loop,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
cert-err52-cpp,
|
||||
cert-err60-cpp,
|
||||
cert-err34-c,
|
||||
cert-str34-c,
|
||||
cert-dcl21-cpp,
|
||||
cert-msc50-cpp,
|
||||
cert-msc51-cpp,
|
||||
cert-dcl58-cpp,
|
||||
cert-flp30-c,
|
||||
cppcoreguidelines-avoid-const-or-ref-data-members,
|
||||
cppcoreguidelines-pro-type-member-init,
|
||||
cppcoreguidelines-slicing,
|
||||
cppcoreguidelines-interfaces-global-init,
|
||||
cppcoreguidelines-pro-type-static-cast-downcast,
|
||||
cppcoreguidelines-narrowing-conversions,
|
||||
google-default-arguments,
|
||||
google-runtime-operator,
|
||||
google-explicit-constructor,
|
||||
hicpp-multiway-paths-covered,
|
||||
hicpp-exception-baseclass,
|
||||
misc-*,
|
||||
-misc-definitions-in-headers,
|
||||
-misc-unused-parameters,
|
||||
-misc-unused-alias-decls,
|
||||
-misc-use-anonymous-namespace,
|
||||
-misc-misleading-identifier,
|
||||
-misc-confusable-identifiers,
|
||||
-misc-misleading-bidirectional,
|
||||
-misc-static-assert,
|
||||
-misc-no-recursion,
|
||||
-misc-const-correctness,
|
||||
modernize-*,
|
||||
-modernize-use-trailing-return-type,
|
||||
openmp-use-default-none,
|
||||
performance-*,
|
||||
-performance-no-int-to-ptr,
|
||||
portability-*,
|
||||
-portability-restrict-system-includes,
|
||||
readability-*,
|
||||
-readability-redundant-preprocessor,
|
||||
-readability-named-parameter,
|
||||
-readability-function-size,
|
||||
-readability-use-anyofallof,
|
||||
-readability-identifier-length,
|
||||
-readability-magic-numbers,
|
||||
-readability-braces-around-statements,
|
||||
-readability-suspicious-call-argument,
|
||||
-readability-isolate-declaration,
|
||||
-readability-else-after-return,
|
||||
-readability-redundant-access-specifiers,
|
||||
-readability-function-cognitive-complexity,
|
||||
-readability-identifier-naming,
|
||||
*-include-cleaner,
|
||||
-readability-qualified-auto'
|
||||
Checks:
|
||||
- -*
|
||||
- mpi-*
|
||||
- bugprone-*
|
||||
- -bugprone-signal-handler
|
||||
- -bugprone-narrowing-conversions
|
||||
- -bugprone-redundant-branch-condition
|
||||
- -bugprone-exception-escape
|
||||
- -bugprone-shared-ptr-array-mismatch
|
||||
- -bugprone-implicit-widening-of-multiplication-result
|
||||
- -bugprone-signed-char-misuse
|
||||
- -bugprone-unhandled-exception-at-new
|
||||
- -bugprone-infinite-loop
|
||||
- -bugprone-easily-swappable-parameters
|
||||
- cert-err52-cpp
|
||||
- cert-err60-cpp
|
||||
- cert-err34-c
|
||||
- cert-str34-c
|
||||
- cert-dcl21-cpp
|
||||
- cert-msc50-cpp
|
||||
- cert-msc51-cpp
|
||||
- cert-dcl58-cpp
|
||||
- cert-flp30-c
|
||||
- cppcoreguidelines-avoid-const-or-ref-data-members
|
||||
- cppcoreguidelines-pro-type-member-init
|
||||
- cppcoreguidelines-slicing
|
||||
- cppcoreguidelines-interfaces-global-init
|
||||
- cppcoreguidelines-pro-type-static-cast-downcast
|
||||
- cppcoreguidelines-narrowing-conversions
|
||||
- google-default-arguments
|
||||
- google-runtime-operator
|
||||
- google-explicit-constructor
|
||||
- hicpp-multiway-paths-covered
|
||||
- hicpp-exception-baseclass
|
||||
- misc-*
|
||||
- -misc-definitions-in-headers
|
||||
- -misc-unused-parameters
|
||||
- -misc-unused-alias-decls
|
||||
- -misc-use-anonymous-namespace
|
||||
- -misc-misleading-identifier
|
||||
- -misc-confusable-identifiers
|
||||
- -misc-misleading-bidirectional
|
||||
- -misc-static-assert
|
||||
- -misc-no-recursion
|
||||
- -misc-const-correctness
|
||||
- modernize-*
|
||||
- -modernize-use-trailing-return-type
|
||||
- openmp-use-default-none
|
||||
- performance-*
|
||||
- -performance-no-int-to-ptr
|
||||
- portability-*
|
||||
- -portability-restrict-system-includes
|
||||
- readability-*
|
||||
- -readability-redundant-preprocessor
|
||||
- -readability-named-parameter
|
||||
- -readability-function-size
|
||||
- -readability-use-anyofallof
|
||||
- -readability-identifier-length
|
||||
- -readability-magic-numbers
|
||||
- -readability-braces-around-statements
|
||||
- -readability-suspicious-call-argument
|
||||
- -readability-isolate-declaration
|
||||
- -readability-else-after-return
|
||||
- -readability-redundant-access-specifiers
|
||||
- -readability-function-cognitive-complexity
|
||||
- -readability-identifier-naming
|
||||
- '*-include-cleaner'
|
||||
- -readability-qualified-auto
|
||||
|
||||
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@@ -1,5 +1,9 @@
|
||||
name: Build
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
@@ -95,7 +99,6 @@ jobs:
|
||||
-DIMHEX_GENERATE_PDBS=ON \
|
||||
-DIMHEX_REPLACE_DWARF_WITH_PDB=ON \
|
||||
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" \
|
||||
-DCPACK_WIX_VERSION="4" \
|
||||
-DCPACK_WIX_ROOT="$(echo "$USERPROFILE" | tr '\\' '/')/.dotnet/tools" \
|
||||
..
|
||||
|
||||
@@ -166,6 +169,7 @@ jobs:
|
||||
|
||||
- name: ⬆️ Upload Windows Installer
|
||||
uses: actions/upload-artifact@v4
|
||||
id: upload-installer
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: Windows Installer ${{ matrix.architecture_name }}
|
||||
@@ -247,6 +251,7 @@ jobs:
|
||||
- name: ⬇️ Install dependencies
|
||||
run: |
|
||||
cp dist/vcpkg.json vcpkg.json
|
||||
vcpkg install
|
||||
|
||||
- name: ⬇️ Install CMake and Ninja
|
||||
uses: lukka/get-cmake@latest
|
||||
@@ -279,7 +284,6 @@ jobs:
|
||||
-DIMHEX_COMMIT_HASH_LONG="$env:GITHUB_SHA" `
|
||||
-DIMHEX_COMMIT_BRANCH="$($env:GITHUB_REF -replace '.*/', '')" `
|
||||
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" `
|
||||
-DCPACK_WIX_VERSION="4" `
|
||||
-DCPACK_WIX_ROOT="$($env:USERPROFILE -replace '\\','/')/.dotnet/tools" `
|
||||
.
|
||||
|
||||
|
||||
37
.github/workflows/nightly_release.yml
vendored
37
.github/workflows/nightly_release.yml
vendored
@@ -82,6 +82,43 @@ jobs:
|
||||
git fetch --tags --recurse-submodules=no
|
||||
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
|
||||
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
|
||||
run: |
|
||||
|
||||
95
.github/workflows/release.yml
vendored
95
.github/workflows/release.yml
vendored
@@ -7,6 +7,12 @@ on:
|
||||
release:
|
||||
types: [published]
|
||||
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:
|
||||
release-update-repos:
|
||||
@@ -25,7 +31,7 @@ jobs:
|
||||
project_version=`cat ImHex/VERSION`
|
||||
tag_version="${{github.event.release.tag_name}}"
|
||||
tag_version="${tag_version:1}"
|
||||
if [ "$project_version" != "$tag_version" ]; then
|
||||
if [ "$project_version" != "$tag_version" ] && [ ! -z "$tag_version" ]; then
|
||||
echo "::warning::$project_version and $tag_version are not the same ! Refusing to populate release"
|
||||
exit 1
|
||||
fi
|
||||
@@ -41,6 +47,7 @@ jobs:
|
||||
tag: ImHex-v${{ env.IMHEX_VERSION }}
|
||||
repo: PatternLanguage
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
skipIfReleaseExists: true
|
||||
|
||||
- name: 🎫 Create ImHex-Patterns release
|
||||
uses: ncipollo/release-action@v1
|
||||
@@ -51,6 +58,7 @@ jobs:
|
||||
tag: ImHex-v${{ env.IMHEX_VERSION }}
|
||||
repo: ImHex-Patterns
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
skipIfReleaseExists: true
|
||||
|
||||
- name: 🎫 Create imhex-download-sdk release
|
||||
uses: ncipollo/release-action@v1
|
||||
@@ -61,11 +69,13 @@ jobs:
|
||||
tag: v${{ env.IMHEX_VERSION }}
|
||||
repo: imhex-download-sdk
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
skipIfReleaseExists: true
|
||||
|
||||
release-upload-artifacts:
|
||||
runs-on: ubuntu-24.04
|
||||
name: Release Upload Artifacts
|
||||
|
||||
outputs:
|
||||
IMHEX_VERSION: ${{ steps.verify_version.outputs.IMHEX_VERSION }}
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -74,17 +84,19 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: 📜 Verify version and set version variable
|
||||
id: verify_version
|
||||
run: |
|
||||
set -x
|
||||
project_version=`cat ImHex/VERSION`
|
||||
tag_version="${{github.event.release.tag_name}}"
|
||||
tag_version="${tag_version:1}"
|
||||
if [ "$project_version" != "$tag_version" ]; then
|
||||
if [ "$project_version" != "$tag_version" ] && [ ! -z "$tag_version" ]; then
|
||||
echo "::warning::$project_version and $tag_version are not the same ! Refusing to populate release"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "IMHEX_VERSION=$project_version" >> $GITHUB_ENV
|
||||
echo "IMHEX_VERSION=$project_version" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: 🗜️ Create tarball from sources with dependencies
|
||||
run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex
|
||||
@@ -97,6 +109,7 @@ jobs:
|
||||
branch: ${{ github.event.release.target_commitish }}
|
||||
workflow_conclusion: success
|
||||
skip_unpack: true
|
||||
commit: ${{ github.event.inputs.commit_hash }}
|
||||
|
||||
- name: 🗜️ Unzip files when needed
|
||||
run: |
|
||||
@@ -115,25 +128,82 @@ jobs:
|
||||
|
||||
- name: 🟩 Rename artifacts when needed
|
||||
run: |
|
||||
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip
|
||||
mv "Windows Portable arm64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-arm64.zip
|
||||
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip
|
||||
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-Web.zip
|
||||
mv "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 || true
|
||||
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 || true
|
||||
rm artifact.tar || true
|
||||
|
||||
- name: ⬆️ Upload Unsigned x86_64 Windows Installer
|
||||
uses: actions/upload-artifact@v4
|
||||
id: upload-installer-x86_64
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: Windows Installer x86_64
|
||||
path: |
|
||||
imhex-*-x86_64.msi
|
||||
|
||||
- name: ⬆️ Upload Unsigned ARM64 Windows Installer
|
||||
if: false
|
||||
uses: actions/upload-artifact@v4
|
||||
id: upload-installer-arm64
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: Windows Installer ARM64
|
||||
path: |
|
||||
imhex-*-arm64.msi
|
||||
|
||||
- name: 🗑️ Delete unsigned installers
|
||||
run: |
|
||||
rm imhex-*-x86_64.msi
|
||||
|
||||
- name: 🗝️ Sign x86_64 Installer
|
||||
uses: signpath/github-action-submit-signing-request@v1
|
||||
with:
|
||||
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
|
||||
organization-id: 'f605a0e8-86cd-411c-bb6f-e05025afcc33'
|
||||
project-slug: 'ImHex'
|
||||
signing-policy-slug: 'release-signing'
|
||||
github-artifact-id: '${{ steps.upload-installer-x86_64.outputs.artifact-id }}'
|
||||
wait-for-completion: true
|
||||
output-artifact-directory: '.'
|
||||
|
||||
- name: 🗝️ Sign ARM64 Installer
|
||||
if: false
|
||||
uses: signpath/github-action-submit-signing-request@v1
|
||||
with:
|
||||
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
|
||||
organization-id: 'f605a0e8-86cd-411c-bb6f-e05025afcc33'
|
||||
project-slug: 'ImHex'
|
||||
signing-policy-slug: 'release-signing'
|
||||
github-artifact-id: '${{ steps.upload-installer-arm64.outputs.artifact-id }}'
|
||||
wait-for-completion: true
|
||||
output-artifact-directory: '.'
|
||||
|
||||
- name: ⬆️ Upload everything to release
|
||||
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
|
||||
with:
|
||||
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
|
||||
run: |
|
||||
set -x
|
||||
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
|
||||
|
||||
- name: ⬆️ Publish AUR package
|
||||
@@ -149,7 +219,7 @@ jobs:
|
||||
commit_username: iTrooz
|
||||
commit_email: itrooz@protonmail.com
|
||||
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
|
||||
|
||||
release-update-winget:
|
||||
@@ -161,6 +231,7 @@ jobs:
|
||||
shell: pwsh
|
||||
run: |
|
||||
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
|
||||
|
||||
- name: ⬆️ Update winget manifest
|
||||
shell: pwsh
|
||||
env:
|
||||
@@ -193,7 +264,7 @@ jobs:
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
||||
with:
|
||||
snap: imhex-${{ env.IMHEX_VERSION }}-x86_64.snap
|
||||
snap: imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-x86_64.snap
|
||||
release: stable
|
||||
|
||||
- name: ⬆️ Publish arm64 Snap package
|
||||
@@ -202,5 +273,5 @@ jobs:
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
||||
with:
|
||||
snap: imhex-${{ env.IMHEX_VERSION }}-arm64.snap
|
||||
snap: imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-arm64.snap
|
||||
release: stable
|
||||
@@ -1,33 +1,38 @@
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
|
||||
# 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_OFFLINE_BUILD "Enable offline build" 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_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_DISABLE_STACKTRACE "Disables support for printing stack traces" OFF)
|
||||
option(IMHEX_BUNDLE_DOTNET "Bundle .NET runtime" ON )
|
||||
option(IMHEX_ENABLE_LTO "Enables Link Time Optimizations if possible" 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_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_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_COMPRESS_DEBUG_INFO "Compress debug information" ON )
|
||||
option(IMHEX_ENABLE_CXX_MODULES "Enable C++20 Module compilation. Testing only!" OFF)
|
||||
option(IMHEX_ENABLE_CPPCHECK "Enable cppcheck static analysis" OFF)
|
||||
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(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules")
|
||||
|
||||
@@ -175,15 +175,11 @@ macro(detectOS)
|
||||
endif()
|
||||
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
|
||||
# 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")
|
||||
endif()
|
||||
# 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
|
||||
add_compile_definitions(SYSTEM_PLUGINS_LOCATION="${CMAKE_INSTALL_FULL_LIBDIR}/imhex")
|
||||
|
||||
else ()
|
||||
message(FATAL_ERROR "Unknown / unsupported system!")
|
||||
@@ -205,11 +201,14 @@ macro(configurePackingResources)
|
||||
set(CPACK_GENERATOR "WIX")
|
||||
set(CPACK_PACKAGE_NAME "ImHex")
|
||||
set(CPACK_PACKAGE_VENDOR "WerWolv")
|
||||
set(CPACK_WIX_VERSION 4)
|
||||
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_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_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_property(INSTALL "$<TARGET_FILE_NAME:main>"
|
||||
PROPERTY CPACK_START_MENU_SHORTCUTS "ImHex"
|
||||
@@ -312,7 +311,7 @@ macro(createPackage)
|
||||
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}\"!")
|
||||
endif()
|
||||
|
||||
@@ -560,6 +559,9 @@ function(detectBadClone)
|
||||
|
||||
file (GLOB EXTERNAL_DIRS "lib/external/*" "lib/third_party/*")
|
||||
foreach (EXTERNAL_DIR ${EXTERNAL_DIRS})
|
||||
if(NOT IS_DIRECTORY "${EXTERNAL_DIR}")
|
||||
continue()
|
||||
endif()
|
||||
file(GLOB_RECURSE RESULT "${EXTERNAL_DIR}/*")
|
||||
list(LENGTH RESULT ENTRY_COUNT)
|
||||
if(ENTRY_COUNT LESS_EQUAL 1)
|
||||
@@ -587,7 +589,9 @@ endfunction()
|
||||
macro(detectBundledPlugins)
|
||||
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})
|
||||
if (EXISTS "${PLUGIN_DIR}/CMakeLists.txt")
|
||||
get_filename_component(PLUGIN_NAME ${PLUGIN_DIR} NAME)
|
||||
@@ -596,8 +600,6 @@ macro(detectBundledPlugins)
|
||||
endif ()
|
||||
endif()
|
||||
endforeach()
|
||||
else()
|
||||
set(PLUGINS ${IMHEX_INCLUDE_PLUGINS})
|
||||
endif()
|
||||
|
||||
foreach(PLUGIN_NAME ${PLUGINS})
|
||||
@@ -608,9 +610,13 @@ macro(detectBundledPlugins)
|
||||
message(FATAL_ERROR "No bundled plugins enabled")
|
||||
endif()
|
||||
|
||||
if (NOT ("builtin" IN_LIST PLUGINS))
|
||||
message(FATAL_ERROR "The 'builtin' plugin is required for ImHex to work!")
|
||||
endif ()
|
||||
set(REQUIRED_PLUGINS builtin fonts ui)
|
||||
foreach(PLUGIN ${REQUIRED_PLUGINS})
|
||||
list(FIND PLUGINS ${PLUGIN} PLUGIN_INDEX)
|
||||
if (PLUGIN_INDEX EQUAL -1)
|
||||
message(FATAL_ERROR "Required plugin '${PLUGIN}' is not enabled!")
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
macro(setVariableInParent variable value)
|
||||
|
||||
4
dist/AppImage/AppImageBuilder.yml
vendored
4
dist/AppImage/AppImageBuilder.yml
vendored
@@ -15,8 +15,8 @@ AppDir:
|
||||
- "{{ARCHITECTURE_PACKAGE}}"
|
||||
allow_unauthenticated: true
|
||||
sources:
|
||||
- sourceline: 'deb [arch=amd64] http://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=amd64] https://us.archive.ubuntu.com/ubuntu/ noble main restricted universe multiverse'
|
||||
- sourceline: 'deb [arch=arm64] https://ports.ubuntu.com/ubuntu-ports/ noble main restricted universe multiverse'
|
||||
include:
|
||||
- libgdk-pixbuf2.0-0
|
||||
- libgdk-pixbuf2.0-common
|
||||
|
||||
28
dist/AppImage/Dockerfile
vendored
28
dist/AppImage/Dockerfile
vendored
@@ -30,9 +30,9 @@ ARG LTO=ON
|
||||
ARG BUILD_TYPE=RelWithDebInfo
|
||||
ARG GIT_COMMIT_HASH
|
||||
ARG GIT_BRANCH
|
||||
ARG ARCHITECTURE_PACKAGE
|
||||
ARG ARCHITECTURE_FILE_NAME
|
||||
ARG ARCHITECTURE_APPIMAGE_BUILDER
|
||||
ARG ARCHITECTURE_PACKAGE=x86_64
|
||||
ARG ARCHITECTURE_FILE_NAME=amd64
|
||||
ARG ARCHITECTURE_APPIMAGE_BUILDER=x86_64
|
||||
WORKDIR /build
|
||||
|
||||
# Ubuntu sh doesnt support string substitution
|
||||
@@ -42,16 +42,18 @@ RUN <<EOF
|
||||
# Prepare ImHex build
|
||||
set -xe
|
||||
|
||||
CC=gcc-14 CXX=g++-14 cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
||||
-DIMHEX_COMMIT_HASH_LONG="${GIT_COMMIT_HASH}" \
|
||||
-DIMHEX_COMMIT_BRANCH="${GIT_BRANCH}" \
|
||||
-DIMHEX_ENABLE_LTO=${LTO} \
|
||||
-DIMHEX_PLUGINS_IN_SHARE=ON \
|
||||
CC=gcc-14 CXX=g++-14 cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
||||
-DIMHEX_COMMIT_HASH_LONG="${GIT_COMMIT_HASH}" \
|
||||
-DIMHEX_COMMIT_BRANCH="${GIT_BRANCH}" \
|
||||
-DIMHEX_ENABLE_LTO=${LTO} \
|
||||
-DIMHEX_BUNDLE_PLUGIN_SDK=OFF \
|
||||
`# To prevent using a libdir with an architecture-specific name` \
|
||||
-DCMAKE_INSTALL_LIBDIR="lib" \
|
||||
/imhex
|
||||
EOF
|
||||
|
||||
|
||||
2
dist/DEBIAN/control.in
vendored
2
dist/DEBIAN/control.in
vendored
@@ -4,7 +4,7 @@ Section: editors
|
||||
Priority: optional
|
||||
Architecture: amd64
|
||||
License: GNU GPL-2
|
||||
Depends: libfontconfig1, libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal, 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>
|
||||
Description: ImHex Hex Editor
|
||||
A Hex Editor for Reverse Engineers, Programmers and
|
||||
|
||||
1
dist/flatpak/net.werwolv.ImHex.yaml
vendored
1
dist/flatpak/net.werwolv.ImHex.yaml
vendored
@@ -120,6 +120,7 @@ modules:
|
||||
- -DUSE_SYSTEM_FMT=ON
|
||||
- -DUSE_SYSTEM_YARA=ON
|
||||
- -DIMHEX_OFFLINE_BUILD=ON
|
||||
- -DIMHEX_BUNDLE_PLUGIN_SDK=OFF
|
||||
- -DCMAKE_INSTALL_LIBDIR=lib
|
||||
- -DCMAKE_INSTALL_RPATH='$ORIGIN/../lib:$ORIGIN/../lib64'
|
||||
sources:
|
||||
|
||||
4
dist/macOS/arm64.Dockerfile
vendored
4
dist/macOS/arm64.Dockerfile
vendored
@@ -150,9 +150,7 @@ EOF
|
||||
# Build ImHex
|
||||
## Copy ImHex
|
||||
COPY --from=imhex / /mnt/ImHex
|
||||
## Patch ImHex with hacks
|
||||
# COPY toolchain.cmake.2 /osxcross/target/toolchain.cmake
|
||||
# Configure ImHex build
|
||||
## Configure ImHex build
|
||||
RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/_deps \
|
||||
cd /mnt/ImHex && \
|
||||
# compilers
|
||||
|
||||
1
dist/snap/snapcraft.yaml
vendored
1
dist/snap/snapcraft.yaml
vendored
@@ -41,6 +41,7 @@ parts:
|
||||
- -DCMAKE_C_COMPILER_LAUNCHER=${CCACHE}
|
||||
- -DCMAKE_CXX_COMPILER_LAUNCHER=${CCACHE}
|
||||
- -DIMHEX_PATTERNS_PULL_MASTER=ON
|
||||
- -DIMHEX_BUNDLE_PLUGIN_SDK=OFF
|
||||
cmake-generator: Ninja
|
||||
build-packages:
|
||||
- cmake
|
||||
|
||||
12
dist/web/Dockerfile
vendored
12
dist/web/Dockerfile
vendored
@@ -2,7 +2,7 @@ FROM emscripten/emsdk:4.0.21 AS build
|
||||
|
||||
# Used to invalidate layer cache but not mount cache
|
||||
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493
|
||||
ARG UNIQUEKEY 1
|
||||
ARG UNIQUEKEY=1
|
||||
|
||||
RUN apt update
|
||||
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
|
||||
set -xe
|
||||
|
||||
git clone https://github.com/microsoft/vcpkg /vcpkg
|
||||
git -C /vcpkg pull
|
||||
git clone --depth 1 https://github.com/microsoft/vcpkg /vcpkg
|
||||
/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
|
||||
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
|
||||
set -xe
|
||||
|
||||
@@ -50,6 +50,7 @@ ENV CCACHE_DIR=/cache/ccache
|
||||
|
||||
RUN mkdir /build
|
||||
WORKDIR /build
|
||||
ARG BUILD_TYPE=Release
|
||||
RUN --mount=type=cache,target=/cache \
|
||||
--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 \
|
||||
-DLIBROMFS_COMPRESS_RESOURCES=OFF \
|
||||
-DIMHEX_ENABLE_PLUGIN_TESTS=OFF \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
||||
|
||||
ninja -j $JOBS
|
||||
|
||||
@@ -106,3 +107,4 @@ COPY --from=build [ \
|
||||
|
||||
FROM nginx
|
||||
COPY --from=raw . /usr/share/nginx/html
|
||||
RUN chmod -R 755 /usr/share/nginx/html
|
||||
|
||||
1
dist/web/compose.yml
vendored
1
dist/web/compose.yml
vendored
@@ -1,5 +1,4 @@
|
||||
# docker compose -f dist/web/compose.yml up --build
|
||||
version: '3'
|
||||
services:
|
||||
imhex_web:
|
||||
image: imhex_web:latest
|
||||
|
||||
2
lib/external/libwolv
vendored
2
lib/external/libwolv
vendored
Submodule lib/external/libwolv updated: 5be84628dc...c9108712ba
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
Submodule lib/external/pattern_language updated: 33057885fd...fb6ea061f7
@@ -19,7 +19,7 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
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);
|
||||
|
||||
struct Entry {
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace hex {
|
||||
* This event is responsible for (optionally) initializing the provider and calling EventProviderOpened
|
||||
* (although the event can also be called manually without problem)
|
||||
*/
|
||||
EVENT_DEF(EventProviderCreated, prv::Provider *);
|
||||
EVENT_DEF(EventProviderCreated, std::shared_ptr<prv::Provider>);
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
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
|
||||
|
||||
@@ -86,7 +86,7 @@ EXPORT_MODULE namespace hex {
|
||||
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
|
||||
* @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
|
||||
@@ -111,12 +111,18 @@ EXPORT_MODULE namespace hex {
|
||||
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
|
||||
* @param select Whether to select the provider after adding it
|
||||
*/
|
||||
prv::Provider* createProvider(
|
||||
std::shared_ptr<prv::Provider> createProvider(
|
||||
const UnlocalizedString &unlocalizedName,
|
||||
bool skipLoadInterface = false,
|
||||
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 <source_location>
|
||||
#include <thread>
|
||||
#include <hex/trace/exceptions.hpp>
|
||||
|
||||
EXPORT_MODULE namespace hex {
|
||||
|
||||
@@ -94,7 +95,12 @@ EXPORT_MODULE namespace hex {
|
||||
std::atomic_flag m_hadException;
|
||||
std::string m_exceptionMessage;
|
||||
|
||||
struct TaskInterruptor { virtual ~TaskInterruptor() = default; };
|
||||
struct TaskInterruptor {
|
||||
TaskInterruptor() {
|
||||
trace::disableExceptionCaptureForCurrentThread();
|
||||
}
|
||||
virtual ~TaskInterruptor() = default;
|
||||
};
|
||||
|
||||
friend class TaskHolder;
|
||||
friend class TaskManager;
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
static_assert(false, "Debug variables are only intended for use during development.");
|
||||
#endif
|
||||
|
||||
namespace hex::trace {
|
||||
struct StackTraceResult;
|
||||
}
|
||||
|
||||
namespace hex::dbg {
|
||||
|
||||
namespace impl {
|
||||
@@ -47,4 +51,6 @@ namespace hex::dbg {
|
||||
bool debugModeEnabled();
|
||||
void setDebugModeEnabled(bool enabled);
|
||||
|
||||
void printStackTrace(const trace::StackTraceResult &stackTrace);
|
||||
|
||||
}
|
||||
@@ -98,6 +98,7 @@ namespace hex {
|
||||
|
||||
void startProgram(const std::vector<std::string> &command);
|
||||
int executeCommand(const std::string &command);
|
||||
std::optional<std::string> executeCommandWithOutput(const std::string &command);
|
||||
void openWebpage(std::string url);
|
||||
|
||||
extern "C" void registerFont(const char *fontName, const char *fontPath);
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace hex::prv {
|
||||
CachedProvider(size_t cacheBlockSize = 4096, size_t maxBlocks = 1024);
|
||||
~CachedProvider() override;
|
||||
|
||||
bool open() override;
|
||||
OpenResult open() override;
|
||||
void close() 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 isSavableAsRecent() const override { return false; }
|
||||
|
||||
[[nodiscard]] bool open() override;
|
||||
[[nodiscard]] OpenResult open() override;
|
||||
void close() override { }
|
||||
|
||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||
|
||||
@@ -79,6 +79,65 @@ namespace hex::prv {
|
||||
public:
|
||||
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();
|
||||
virtual ~Provider();
|
||||
Provider(const Provider&) = delete;
|
||||
@@ -94,7 +153,7 @@ namespace hex::prv {
|
||||
* @note This is not related to the EventProviderOpened event
|
||||
* @return true if the provider was opened successfully, else false
|
||||
*/
|
||||
[[nodiscard]] virtual bool open() = 0;
|
||||
[[nodiscard]] virtual OpenResult open() = 0;
|
||||
|
||||
/**
|
||||
* @brief Closes this provider
|
||||
@@ -262,9 +321,6 @@ namespace hex::prv {
|
||||
void skipLoadInterface() { m_skipLoadInterface = true; }
|
||||
[[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>
|
||||
bool addUndoableOperation(auto && ... args) {
|
||||
return m_undoRedoStack.add<T>(std::forward<decltype(args)...>(args)...);
|
||||
@@ -296,8 +352,6 @@ namespace hex::prv {
|
||||
*/
|
||||
bool m_skipLoadInterface = false;
|
||||
|
||||
std::string m_errorMessage = "Unspecified error";
|
||||
|
||||
u64 m_pageSize = MaxPageSize;
|
||||
};
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace hex::test {
|
||||
|
||||
[[nodiscard]] UnlocalizedString getTypeName() const override { return "hex.test.provider.test"; }
|
||||
|
||||
bool open() override { return true; }
|
||||
OpenResult open() override { return {}; }
|
||||
void close() override { }
|
||||
|
||||
nlohmann::json storeSettings(nlohmann::json) const override { return {}; }
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <hex/api/tutorial_manager.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -27,7 +26,7 @@ namespace hex {
|
||||
* @brief Draws the view
|
||||
* @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
|
||||
@@ -126,6 +125,7 @@ namespace hex {
|
||||
class Window;
|
||||
class Special;
|
||||
class Floating;
|
||||
class Scrolling;
|
||||
class Modal;
|
||||
class FullScreen;
|
||||
|
||||
@@ -153,16 +153,10 @@ namespace hex {
|
||||
*/
|
||||
virtual void drawHelpText() = 0;
|
||||
|
||||
void draw() final {
|
||||
if (this->shouldDraw()) {
|
||||
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 | this->getWindowFlags())) {
|
||||
TutorialManager::setLastItemInteractiveHelpPopup([this]{ this->drawHelpText(); });
|
||||
this->drawContent();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) override;
|
||||
|
||||
virtual bool allowScroll() const {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -174,12 +168,7 @@ namespace hex {
|
||||
public:
|
||||
explicit Special(UnlocalizedString unlocalizedName) : View(std::move(unlocalizedName), "") {}
|
||||
|
||||
void draw() final {
|
||||
if (this->shouldDraw()) {
|
||||
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
||||
this->drawContent();
|
||||
}
|
||||
}
|
||||
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -189,7 +178,24 @@ namespace hex {
|
||||
public:
|
||||
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; }
|
||||
};
|
||||
|
||||
@@ -200,24 +206,7 @@ namespace hex {
|
||||
public:
|
||||
explicit Modal(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon) {}
|
||||
|
||||
void draw() final {
|
||||
if (this->shouldDraw()) {
|
||||
if (this->getWindowOpenState())
|
||||
ImGui::OpenPopup(View::toWindowName(this->getUnlocalizedName()).c_str());
|
||||
|
||||
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
|
||||
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
||||
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
|
||||
if (ImGui::BeginPopupModal(title.c_str(), this->hasCloseButton() ? &this->getWindowOpenState() : nullptr, ImGuiWindowFlags_NoCollapse | this->getWindowFlags())) {
|
||||
this->drawContent();
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Escape))
|
||||
this->getWindowOpenState() = false;
|
||||
}
|
||||
}
|
||||
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||
|
||||
[[nodiscard]] virtual bool hasCloseButton() const { return true; }
|
||||
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
|
||||
@@ -227,10 +216,7 @@ namespace hex {
|
||||
public:
|
||||
explicit FullScreen() : View("FullScreen", "") {}
|
||||
|
||||
void draw() final {
|
||||
this->drawContent();
|
||||
this->drawAlwaysVisibleContent();
|
||||
}
|
||||
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1101,13 +1101,13 @@ namespace hex {
|
||||
namespace impl {
|
||||
|
||||
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;
|
||||
|
||||
auto newProvider = creationFunction();
|
||||
|
||||
if (provider != nullptr) {
|
||||
*provider = newProvider.get();
|
||||
*provider = newProvider;
|
||||
ImHexApi::Provider::add(std::move(newProvider), skipLoadInterface, selectProvider);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -294,8 +294,8 @@ namespace hex {
|
||||
namespace ImHexApi::Provider {
|
||||
|
||||
static i64 s_currentProvider = -1;
|
||||
static AutoReset<std::vector<std::unique_ptr<prv::Provider>>> s_providers;
|
||||
static AutoReset<std::map<prv::Provider*, std::unique_ptr<prv::Provider>>> s_providersToRemove;
|
||||
static AutoReset<std::vector<std::shared_ptr<prv::Provider>>> s_providers;
|
||||
static AutoReset<std::map<prv::Provider*, std::shared_ptr<prv::Provider>>> s_providersToRemove;
|
||||
|
||||
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);
|
||||
|
||||
if (TaskManager::getRunningTaskCount() > 0)
|
||||
@@ -391,7 +391,7 @@ namespace hex {
|
||||
if (skipLoadInterface)
|
||||
provider->skipLoadInterface();
|
||||
|
||||
EventProviderCreated::post(provider.get());
|
||||
EventProviderCreated::post(provider);
|
||||
s_providers->emplace_back(std::move(provider));
|
||||
|
||||
if (select || s_providers->size() == 1)
|
||||
@@ -491,13 +491,17 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
prv::Provider* createProvider(const UnlocalizedString &unlocalizedName, bool skipLoadInterface, bool select) {
|
||||
prv::Provider* result = nullptr;
|
||||
std::shared_ptr<prv::Provider> createProvider(const UnlocalizedString &unlocalizedName, bool skipLoadInterface, bool select) {
|
||||
std::shared_ptr<prv::Provider> result = nullptr;
|
||||
RequestCreateProvider::post(unlocalizedName, skipLoadInterface, select, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void openProvider(std::shared_ptr<prv::Provider> provider) {
|
||||
RequestOpenProvider::post(provider);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ImHexApi::System {
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <ranges>
|
||||
|
||||
#include <jthread.hpp>
|
||||
#include <hex/helpers/debugging.hpp>
|
||||
#include <hex/trace/exceptions.hpp>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#include <windows.h>
|
||||
@@ -310,6 +312,8 @@ namespace hex {
|
||||
}
|
||||
|
||||
try {
|
||||
trace::enableExceptionCaptureForCurrentThread();
|
||||
|
||||
// Set the thread name to the name of the task
|
||||
TaskManager::setCurrentThreadName(Lang(task->m_unlocalizedName));
|
||||
|
||||
@@ -323,15 +327,21 @@ namespace hex {
|
||||
} catch (const std::exception &e) {
|
||||
log::error("Exception in task '{}': {}", task->m_unlocalizedName.get(), e.what());
|
||||
|
||||
dbg::printStackTrace(trace::getStackTrace());
|
||||
|
||||
// Handle the task throwing an uncaught exception
|
||||
task->exception(e.what());
|
||||
} catch (...) {
|
||||
log::error("Exception in task '{}'", task->m_unlocalizedName.get());
|
||||
|
||||
dbg::printStackTrace(trace::getStackTrace());
|
||||
|
||||
// Handle the task throwing an uncaught exception of unknown type
|
||||
task->exception("Unknown Exception");
|
||||
}
|
||||
|
||||
trace::disableExceptionCaptureForCurrentThread();
|
||||
|
||||
s_currentTask = nullptr;
|
||||
task->finish();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include <hex/helpers/debugging.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/trace/stacktrace.hpp>
|
||||
|
||||
namespace hex::dbg {
|
||||
|
||||
@@ -21,4 +23,23 @@ namespace hex::dbg {
|
||||
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() {
|
||||
// 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);
|
||||
|
||||
// Add the system plugin directory to the path if one was provided at compile time
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <mutex>
|
||||
#include <chrono>
|
||||
#include <fmt/chrono.h>
|
||||
#include <hex/helpers/debugging.hpp>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#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 {
|
||||
|
||||
fmt::color debug() { return fmt::color::medium_sea_green; }
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace hex {
|
||||
[[nodiscard]] bool isSavable() 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 readRaw(u64 offset, void *buffer, size_t size) override {
|
||||
|
||||
@@ -309,6 +309,50 @@ namespace hex {
|
||||
return ::system(command.c_str());
|
||||
}
|
||||
|
||||
std::optional<std::string> executeCommandWithOutput(const std::string &command) {
|
||||
std::array<char, 256> buffer = {};
|
||||
std::string result;
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
FILE* pipe = _popen(command.c_str(), "r");
|
||||
#else
|
||||
FILE* pipe = popen(command.c_str(), "r");
|
||||
#endif
|
||||
|
||||
if (!pipe) {
|
||||
hex::log::error("Failed to open pipe for command: {}", command);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
try {
|
||||
while (fgets(buffer.data(), buffer.size(), pipe) != nullptr) {
|
||||
result += buffer.data();
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
hex::log::error("Exception while reading command output: {}", e.what());
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
_pclose(pipe);
|
||||
#else
|
||||
pclose(pipe);
|
||||
#endif
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
int exitCode = _pclose(pipe);
|
||||
#else
|
||||
int exitCode = pclose(pipe);
|
||||
#endif
|
||||
|
||||
if (exitCode != 0) {
|
||||
hex::log::debug("Command exited with code {}: {}", exitCode, command);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void openWebpage(std::string url) {
|
||||
if (!url.contains("://"))
|
||||
url = "https://" + url;
|
||||
|
||||
@@ -11,9 +11,9 @@ namespace hex::prv {
|
||||
clearCache();
|
||||
}
|
||||
|
||||
bool CachedProvider::open() {
|
||||
Provider::OpenResult CachedProvider::open() {
|
||||
clearCache();
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
void CachedProvider::close() {
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
|
||||
namespace hex::prv {
|
||||
|
||||
bool MemoryProvider::open() {
|
||||
Provider::OpenResult MemoryProvider::open() {
|
||||
if (m_data.empty()) {
|
||||
m_data.resize(1);
|
||||
}
|
||||
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
void MemoryProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#include <hex/ui/view.hpp>
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/helpers/auto_reset.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 <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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
2
lib/third_party/.clang-tidy
vendored
Normal file
2
lib/third_party/.clang-tidy
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Disable all checks
|
||||
Checks: '-*'
|
||||
13
lib/third_party/imgui/imgui/include/imconfig.h
vendored
13
lib/third_party/imgui/imgui/include/imconfig.h
vendored
@@ -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.
|
||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||
namespace hex::log::impl {
|
||||
void assertionHandler(const char* expr_str, const char* file, int line);
|
||||
namespace hex::dbg {
|
||||
[[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
|
||||
// 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")
|
||||
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_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")
|
||||
# Not supported currently
|
||||
endif()
|
||||
|
||||
@@ -6,7 +6,12 @@
|
||||
|
||||
namespace hex::trace {
|
||||
|
||||
using AssertionHandler = void(*)(const char* file, int line, const char *function, const char* exprString);
|
||||
|
||||
std::optional<StackTraceResult> getLastExceptionStackTrace();
|
||||
void setAssertionHandler(AssertionHandler handler);
|
||||
|
||||
void enableExceptionCaptureForCurrentThread();
|
||||
void disableExceptionCaptureForCurrentThread();
|
||||
|
||||
}
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
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 AssertionHandler s_assertionHandler = nullptr;
|
||||
|
||||
std::optional<StackTraceResult> getLastExceptionStackTrace() {
|
||||
if (!s_lastExceptionStackTrace.has_value())
|
||||
@@ -15,18 +16,26 @@ namespace hex::trace {
|
||||
return result;
|
||||
}
|
||||
|
||||
void setAssertionHandler(AssertionHandler handler) {
|
||||
s_assertionHandler = handler;
|
||||
}
|
||||
|
||||
void enableExceptionCaptureForCurrentThread() {
|
||||
s_threadExceptionCaptureEnabled = true;
|
||||
}
|
||||
|
||||
void disableExceptionCaptureForCurrentThread() {
|
||||
s_threadExceptionCaptureEnabled = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if defined(HEX_WRAP_CXA_THROW)
|
||||
|
||||
extern "C" {
|
||||
|
||||
[[noreturn]] void __real___cxa_throw(void* thrownException, void* type, void (*destructor)(void*));
|
||||
[[noreturn]] void __wrap___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, std::type_info* type, void (*destructor)(void*)) {
|
||||
if (hex::trace::s_threadExceptionCaptureEnabled)
|
||||
hex::trace::s_lastExceptionStackTrace = hex::trace::getStackTrace();
|
||||
|
||||
@@ -35,4 +44,23 @@ namespace hex::trace {
|
||||
|
||||
}
|
||||
|
||||
#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 <exception>
|
||||
#include <typeinfo>
|
||||
#include <hex/helpers/debugging.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
#if defined(IMGUI_TEST_ENGINE)
|
||||
@@ -71,23 +72,12 @@ namespace hex::crash {
|
||||
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) {
|
||||
// Call the crash callback
|
||||
crashCallback(msg);
|
||||
|
||||
// Print the stacktrace to the console or log file
|
||||
printStackTrace();
|
||||
dbg::printStackTrace(trace::getStackTrace());
|
||||
|
||||
// Flush all streams
|
||||
std::fflush(stdout);
|
||||
@@ -188,6 +178,7 @@ namespace hex::crash {
|
||||
// Setup functions to handle signals, uncaught exception, or similar stuff that will crash ImHex
|
||||
void setupCrashHandlers() {
|
||||
trace::initialize();
|
||||
trace::setAssertionHandler(dbg::assertionHandler);
|
||||
|
||||
// Register signal handlers
|
||||
{
|
||||
|
||||
@@ -102,12 +102,12 @@ std::optional<std::fs::path> downloadUpdate(const std::string &url) {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#if defined(__x86_64__) || defined(_X86_) || defined(_AMD64_) || defined(_M_X64)
|
||||
#define ARCH_DEPENDENT(x86_64, arm64) x86_64
|
||||
#elif defined(__arm64__)
|
||||
#elif defined(__arm64__) || defined(_ARM64_) || defined(__aarch64__) || defined(_M_ARM64)
|
||||
#define ARCH_DEPENDENT(x86_64, arm64) arm64
|
||||
#else
|
||||
#define ARCH_DEPENDENT(x86_64, arm64) ""
|
||||
#error "Unsupported architecture for updater"
|
||||
#endif
|
||||
|
||||
std::string_view getUpdateArtifactEnding() {
|
||||
@@ -134,6 +134,8 @@ std::string_view getUpdateArtifactEnding() {
|
||||
return ARCH_DEPENDENT("Fedora-41-x86_64.rpm", "");
|
||||
else if (hex::executeCommand("grep -q 'VERSION_ID=\"42\"' /etc/os-release") == 0)
|
||||
return ARCH_DEPENDENT("Fedora-42-x86_64.rpm", "");
|
||||
else if (hex::executeCommand("grep -q 'VERSION_ID=\"43\"' /etc/os-release") == 0)
|
||||
return ARCH_DEPENDENT("Fedora-43-x86_64.rpm", "");
|
||||
else if (hex::executeCommand("grep -q 'VERSION_ID=\"rawhide\"' /etc/os-release") == 0)
|
||||
return ARCH_DEPENDENT("Fedora-rawhide-x86_64.rpm", "");
|
||||
} else if (hex::executeCommand("grep -q '^NAME=\"Arch Linux\"' /etc/os-release") == 0) {
|
||||
@@ -144,33 +146,103 @@ std::string_view getUpdateArtifactEnding() {
|
||||
return "";
|
||||
}
|
||||
|
||||
auto updateCommand(std::string command) {
|
||||
return [command](const std::fs::path &updatePath) -> bool {
|
||||
const auto formattedCommand = fmt::format(fmt::runtime(command), updatePath.string());
|
||||
|
||||
hex::log::info("Starting update process with command: '{}'", formattedCommand);
|
||||
return hex::executeCommand(formattedCommand) == 0;
|
||||
};
|
||||
}
|
||||
|
||||
auto updateMacOSBundle(const std::fs::path &updatePath) {
|
||||
// Mount the DMG
|
||||
auto mountCmd = fmt::format("hdiutil attach \"{}\" -nobrowse", updatePath.string());
|
||||
auto mountOutput = hex::executeCommandWithOutput(mountCmd);
|
||||
if (!mountOutput.has_value()) {
|
||||
hex::log::error("Failed to mount DMG");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extract mount point from output
|
||||
std::string mountPoint;
|
||||
for (const auto &line : wolv::util::splitString(*mountOutput, "\n")) {
|
||||
if (line.contains("/Volumes/")) {
|
||||
auto parts = wolv::util::splitString(line, "\t");
|
||||
mountPoint = parts.back();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mountPoint.empty()) {
|
||||
hex::log::error("Failed to find mount point");
|
||||
return false;
|
||||
}
|
||||
|
||||
ON_SCOPE_EXIT {
|
||||
hex::executeCommand(fmt::format("hdiutil detach \"{}\"", mountPoint));
|
||||
};
|
||||
|
||||
// Find the .app bundle in the mounted DMG
|
||||
auto findCmd = fmt::format("find \"{}\" -name '*.app' -maxdepth 1", mountPoint);
|
||||
auto appPath = hex::executeCommandWithOutput(findCmd);
|
||||
if (!appPath.has_value()) {
|
||||
hex::log::error("Failed to find .app in DMG");
|
||||
hex::executeCommand(fmt::format("hdiutil detach \"{}\"", mountPoint));
|
||||
return false;
|
||||
}
|
||||
|
||||
appPath = wolv::util::trim(*appPath);
|
||||
|
||||
if (appPath->empty()) {
|
||||
hex::log::error("Failed to find .app in DMG");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the app name
|
||||
auto appName = std::fs::path(*appPath).filename().string();
|
||||
auto installPath = fmt::format("/Applications/{}", appName);
|
||||
|
||||
// Use AppleScript to copy with elevated privileges
|
||||
auto installScript = fmt::format(
|
||||
R"(osascript -e 'do shell script "rm -rf \"{}\" && cp -R \"{}\" /Applications/" with administrator privileges')",
|
||||
installPath, *appPath
|
||||
);
|
||||
|
||||
if (hex::executeCommand(installScript) != 0) {
|
||||
hex::log::error("Failed to install update");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Launch the new version
|
||||
hex::executeCommand(fmt::format("open \"{}\"", installPath));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool installUpdate(const std::fs::path &updatePath) {
|
||||
using UpdaterFunction = std::function<bool(const std::fs::path &updatePath)>;
|
||||
struct UpdateHandler {
|
||||
std::string ending;
|
||||
std::string command;
|
||||
UpdaterFunction func;
|
||||
};
|
||||
|
||||
const static auto UpdateHandlers = {
|
||||
UpdateHandler { ".msi", "msiexec /i \"{}\" /qb" },
|
||||
UpdateHandler { ".dmg", "hdiutil attach -autoopen \"{}\"" },
|
||||
UpdateHandler { ".deb", "zenity --password | sudo -S apt install -y --fix-broken \"{}\"" },
|
||||
UpdateHandler { ".rpm", "zenity --password | sudo -S rpm -i \"{}\"" },
|
||||
UpdateHandler { ".pkg.tar.zst", "zenity --password | sudo -S pacman -Syy && sudo pacman -U --noconfirm \"{}\"" },
|
||||
UpdateHandler { ".AppImage", fmt::format("zenity --password | sudo -S cp \"{{}}\" \"{}\"", hex::getEnvironmentVariable("APPIMAGE").value_or("")) },
|
||||
UpdateHandler { ".flatpak", "zenity --password | sudo -S flatpak install -y --reinstall \"{}\"" },
|
||||
UpdateHandler { ".snap", "zenity --password | sudo -S snap install --dangerous \"{}\"" },
|
||||
UpdateHandler { .ending=".msi", .func=updateCommand("msiexec /i \"{}\" /qb") },
|
||||
UpdateHandler { .ending=".dmg", .func=updateMacOSBundle },
|
||||
UpdateHandler { .ending=".deb", .func=updateCommand("zenity --password | sudo -S apt install -y --fix-broken \"{}\"") },
|
||||
UpdateHandler { .ending=".rpm", .func=updateCommand("zenity --password | sudo -S rpm -i \"{}\"") },
|
||||
UpdateHandler { .ending=".pkg.tar.zst", .func=updateCommand("zenity --password | sudo -S pacman -Syy && sudo pacman -U --noconfirm \"{}\"") },
|
||||
UpdateHandler { .ending=".AppImage", .func=updateCommand(fmt::format(R"(zenity --password | sudo -S cp "{{}}" "{}")", hex::getEnvironmentVariable("APPIMAGE").value_or(""))) },
|
||||
UpdateHandler { .ending=".flatpak", .func=updateCommand("zenity --password | sudo -S flatpak install -y --reinstall \"{}\"") },
|
||||
UpdateHandler { .ending=".snap", .func=updateCommand("zenity --password | sudo -S snap install --dangerous \"{}\"") },
|
||||
};
|
||||
|
||||
const auto updateFileName = wolv::util::toUTF8String(updatePath.filename());
|
||||
for (const auto &handler : UpdateHandlers) {
|
||||
if (updateFileName.ends_with(handler.ending)) {
|
||||
// Install the update using the correct command
|
||||
const auto command = fmt::format(fmt::runtime(handler.command), updatePath.string());
|
||||
|
||||
hex::log::info("Starting update process with command: '{}'", command);
|
||||
hex::executeCommand(command);
|
||||
|
||||
return true;
|
||||
return handler.func(updatePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,9 +270,11 @@ int main(int argc, char **argv) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
hex::log::info("Updating ImHex...");
|
||||
|
||||
// Read the version type from the arguments
|
||||
const std::string_view versionTypeString = argv[1];
|
||||
hex::log::info("Updater started with version type: {}", versionTypeString);
|
||||
hex::log::info("Installing '{}' version of ImHex", versionTypeString);
|
||||
|
||||
// Convert the version type string to the enum value
|
||||
hex::ImHexApi::System::UpdateType updateType;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include <content/views/view_hex_editor.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <ui/text_editor.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
@@ -21,6 +20,5 @@ namespace hex::plugin::builtin {
|
||||
|
||||
private:
|
||||
std::string m_decodedString;
|
||||
ui::TextEditor m_editor;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void setPath(const std::fs::path &path);
|
||||
|
||||
[[nodiscard]] bool open() override;
|
||||
[[nodiscard]] OpenResult open() override;
|
||||
void close() override;
|
||||
|
||||
[[nodiscard]] std::string getName() const override;
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void setPath(const std::fs::path &path);
|
||||
|
||||
[[nodiscard]] bool open() override;
|
||||
[[nodiscard]] OpenResult open() override;
|
||||
void close() override;
|
||||
|
||||
void loadSettings(const nlohmann::json &settings) override;
|
||||
@@ -65,7 +65,7 @@ namespace hex::plugin::builtin {
|
||||
private:
|
||||
void handleFileChange();
|
||||
|
||||
bool open(bool memoryMapped);
|
||||
OpenResult open(bool memoryMapped);
|
||||
|
||||
protected:
|
||||
std::fs::path m_path;
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace hex::plugin::builtin {
|
||||
[[nodiscard]] std::string getName() const override;
|
||||
[[nodiscard]] std::vector<Description> getDataDescription() const override;
|
||||
|
||||
[[nodiscard]] bool open() override;
|
||||
[[nodiscard]] OpenResult open() override;
|
||||
void close() override;
|
||||
|
||||
[[nodiscard]] bool isConnected() const;
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace hex::plugin::builtin {
|
||||
[[nodiscard]] u64 getActualSize() const override;
|
||||
void processMemoryRegions(wolv::util::Expected<std::map<u64, std::vector<u8>>, std::string> data);
|
||||
static bool memoryRegionFilter(const std::string &search, const MemoryRegion &memoryRegion);
|
||||
bool open() override;
|
||||
OpenResult open() override;
|
||||
void close() 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 isSavableAsRecent() const override { return false; }
|
||||
|
||||
[[nodiscard]] bool open() override;
|
||||
[[nodiscard]] OpenResult open() override;
|
||||
void close() override { }
|
||||
|
||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace hex::plugin::builtin {
|
||||
MotorolaSRECProvider() = default;
|
||||
~MotorolaSRECProvider() override = default;
|
||||
|
||||
bool open() override;
|
||||
OpenResult open() override;
|
||||
void close() override;
|
||||
|
||||
[[nodiscard]] std::string getName() const override;
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace hex::plugin::builtin {
|
||||
[[nodiscard]] bool isResizable() 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 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;
|
||||
|
||||
bool drawLoadInterface() override;
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace hex::plugin::builtin {
|
||||
[[nodiscard]] bool drawLoadInterface() override;
|
||||
void drawSidebarInterface() override;
|
||||
|
||||
[[nodiscard]] bool open() override;
|
||||
[[nodiscard]] OpenResult open() override;
|
||||
void close() override;
|
||||
|
||||
void loadSettings(const nlohmann::json &) override;
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace hex::plugin::builtin {
|
||||
[[nodiscard]] bool isSavableAsRecent() const override;
|
||||
|
||||
void save() override;
|
||||
[[nodiscard]] bool open() override;
|
||||
[[nodiscard]] OpenResult open() override;
|
||||
void close() override;
|
||||
|
||||
void resizeRaw(u64 newSize) override;
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
#include <hex/ui/view.hpp>
|
||||
#include <hex/api/imhex_api/bookmarks.hpp>
|
||||
|
||||
#include <ui/text_editor.hpp>
|
||||
|
||||
#include <list>
|
||||
#include <ui/markdown.hpp>
|
||||
|
||||
|
||||
@@ -57,10 +57,6 @@ namespace hex::plugin::builtin {
|
||||
void reloadCustomNodes();
|
||||
void updateNodePositions();
|
||||
|
||||
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override {
|
||||
return ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
|
||||
}
|
||||
|
||||
std::vector<Workspace*> &getWorkspaceStack() { return *m_workspaceStack; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void drawContent() override;
|
||||
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override {
|
||||
return ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
|
||||
return ImGuiWindowFlags_NoNavInputs;
|
||||
}
|
||||
|
||||
bool shouldDefaultFocus() const override { return true; }
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
ImGuiWindowFlags getWindowFlags() const override {
|
||||
return View::Floating::getWindowFlags() | ImGuiWindowFlags_NoResize;
|
||||
return ImGuiWindowFlags_NoResize;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class ViewInformation : public View::Window {
|
||||
class ViewInformation : public View::Scrolling {
|
||||
public:
|
||||
explicit ViewInformation();
|
||||
~ViewInformation() override = default;
|
||||
|
||||
@@ -66,9 +66,6 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void drawContent() override;
|
||||
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override {
|
||||
return ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
|
||||
}
|
||||
|
||||
void setPopupWindowHeight(u32 height) { m_popupWindowHeight = height; }
|
||||
u32 getPopupWindowHeight() const { return m_popupWindowHeight; }
|
||||
@@ -152,12 +149,12 @@ namespace hex::plugin::builtin {
|
||||
std::mutex m_logMutex;
|
||||
|
||||
PerProvider<ui::TextEditor::Coordinates> m_cursorPosition;
|
||||
PerProvider<ImVec2> m_scroll;
|
||||
PerProvider<ImVec2> m_consoleScroll;
|
||||
|
||||
PerProvider<ui::TextEditor::Coordinates> m_consoleCursorPosition;
|
||||
PerProvider<bool> m_cursorNeedsUpdate;
|
||||
PerProvider<bool> m_consoleCursorNeedsUpdate;
|
||||
PerProvider<ui::TextEditor::Selection> m_selection;
|
||||
PerProvider<ui::TextEditor::Selection> m_consoleSelection;
|
||||
PerProvider<ui::TextEditor::Range> m_selection;
|
||||
PerProvider<ui::TextEditor::Range> m_consoleSelection;
|
||||
PerProvider<size_t> m_consoleLongestLineLength;
|
||||
PerProvider<ui::TextEditor::Breakpoints> m_breakpoints;
|
||||
PerProvider<std::optional<pl::core::err::PatternLanguageError>> m_lastEvaluationError;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class ViewTools : public View::Window {
|
||||
class ViewTools : public View::Scrolling {
|
||||
public:
|
||||
ViewTools();
|
||||
~ViewTools() override = default;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
ImGuiWindowFlags getWindowFlags() const override {
|
||||
return Floating::getWindowFlags() | ImGuiWindowFlags_NoResize;
|
||||
return ImGuiWindowFlags_NoResize;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -406,7 +406,7 @@
|
||||
"hex.builtin.popup.exit_application.title": "Exit Application?",
|
||||
"hex.builtin.popup.waiting_for_tasks.title": "Waiting for Tasks",
|
||||
"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.blocking_task.title": "Running Task",
|
||||
"hex.builtin.popup.blocking_task.desc": "A task is currently executing.",
|
||||
@@ -418,7 +418,7 @@
|
||||
"hex.builtin.provider.rename": "Rename",
|
||||
"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.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.disk": "Raw Disk",
|
||||
"hex.builtin.provider.disk.disk_size": "Disk Size",
|
||||
@@ -430,6 +430,7 @@
|
||||
"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.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.creation": "Creation time",
|
||||
"hex.builtin.provider.file.menu.direct_access": "Direct access file",
|
||||
@@ -448,6 +449,7 @@
|
||||
"hex.builtin.provider.gdb.name": "GDB Server <{0}:{1}>",
|
||||
"hex.builtin.provider.gdb.port": "Port",
|
||||
"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.name": "Intel Hex {0}",
|
||||
"hex.builtin.provider.mem_file": "In-Memory File",
|
||||
@@ -458,6 +460,8 @@
|
||||
"hex.builtin.provider.opening": "Opening Data Source...",
|
||||
"hex.builtin.provider.process_memory": "Process Memory",
|
||||
"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.memory_regions": "Memory Regions",
|
||||
"hex.builtin.provider.process_memory.name": "'{0}' Process Memory",
|
||||
@@ -476,6 +480,7 @@
|
||||
"hex.builtin.provider.udp.port": "Server Port",
|
||||
"hex.builtin.provider.udp.timestamp": "Timestamp",
|
||||
"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.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",
|
||||
@@ -1031,6 +1036,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_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.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.open_pattern": "Open pattern",
|
||||
"hex.builtin.view.pattern_editor.replace_hint": "Replace",
|
||||
|
||||
@@ -358,10 +358,10 @@ namespace hex::plugin::builtin {
|
||||
std::fs::path filePath = reinterpret_cast<const char8_t*>(args[0].data());
|
||||
|
||||
FileProvider provider;
|
||||
|
||||
provider.setPath(filePath);
|
||||
if (!provider.open()) {
|
||||
log::println("Failed to open file '{}'", args[0]);
|
||||
auto result = provider.open();
|
||||
if (result.isFailure()) {
|
||||
log::println("Failed to open file '{}': {}", args[0], result.getErrorMessage());
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
@@ -287,23 +287,23 @@ namespace hex::plugin::builtin {
|
||||
"@",
|
||||
"hex.builtin.command.goto.desc",
|
||||
[](auto input) {
|
||||
wolv::math_eval::MathEvaluator<long double> evaluator;
|
||||
wolv::math_eval::MathEvaluator<i64> evaluator;
|
||||
evaluator.registerStandardVariables();
|
||||
evaluator.registerStandardFunctions();
|
||||
|
||||
std::optional<long double> result = evaluator.evaluate(input);
|
||||
const auto result = evaluator.evaluate(input);
|
||||
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())
|
||||
return fmt::format("Error: {}", *evaluator.getLastError());
|
||||
else
|
||||
return std::string("???");
|
||||
}, [](auto input) -> std::optional<std::string> {
|
||||
wolv::math_eval::MathEvaluator<long double> evaluator;
|
||||
wolv::math_eval::MathEvaluator<i64> evaluator;
|
||||
evaluator.registerStandardVariables();
|
||||
evaluator.registerStandardFunctions();
|
||||
|
||||
std::optional<long double> result = evaluator.evaluate(input);
|
||||
const auto result = evaluator.evaluate(input);
|
||||
if (result.has_value()) {
|
||||
ImHexApi::HexEditor::setSelection(result.value(), 1);
|
||||
}
|
||||
|
||||
@@ -589,9 +589,18 @@ namespace hex::plugin::builtin {
|
||||
return [value, copyValue] { ImGuiExt::TextFormatted("L\"{0}\"", value.c_str()); return copyValue; };
|
||||
},
|
||||
[](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;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -626,9 +635,18 @@ namespace hex::plugin::builtin {
|
||||
return [value, copyValue] { ImGuiExt::TextFormatted("u\"{0}\"", value.c_str()); return copyValue; };
|
||||
},
|
||||
[](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;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -663,9 +681,18 @@ namespace hex::plugin::builtin {
|
||||
return [value, copyValue] { ImGuiExt::TextFormatted("U\"{0}\"", value.c_str()); return copyValue; };
|
||||
},
|
||||
[](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;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -40,30 +40,27 @@
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
static void openFile(const std::fs::path &path) {
|
||||
if (path.extension() == ".hexproj") {
|
||||
if (!ProjectFile::load(path)) {
|
||||
ui::ToastError::open(fmt::format("hex.builtin.popup.error.project.load"_lang, wolv::util::toUTF8String(path)));
|
||||
}
|
||||
TaskManager::doLater([path] {
|
||||
if (path.extension() == ".hexproj") {
|
||||
if (!ProjectFile::load(path)) {
|
||||
ui::ToastError::open(fmt::format("hex.builtin.popup.error.project.load"_lang, wolv::util::toUTF8String(path)));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto provider = ImHexApi::Provider::createProvider("hex.builtin.provider.file", true);
|
||||
if (auto *fileProvider = dynamic_cast<FileProvider*>(provider); fileProvider != nullptr) {
|
||||
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);
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name");
|
||||
ImHexApi::Provider::setCurrentProvider(provider);
|
||||
auto provider = ImHexApi::Provider::createProvider("hex.builtin.provider.file", true);
|
||||
if (auto *fileProvider = dynamic_cast<FileProvider*>(provider.get()); fileProvider != nullptr) {
|
||||
fileProvider->setPath(path);
|
||||
|
||||
glfwRequestWindowAttention(ImHexApi::System::getMainWindowHandle());
|
||||
glfwFocusWindow(ImHexApi::System::getMainWindowHandle());
|
||||
}
|
||||
ImHexApi::Provider::openProvider(provider);
|
||||
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name");
|
||||
|
||||
glfwRequestWindowAttention(ImHexApi::System::getMainWindowHandle());
|
||||
glfwFocusWindow(ImHexApi::System::getMainWindowHandle());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void registerEventHandlers() {
|
||||
@@ -180,11 +177,8 @@ namespace hex::plugin::builtin {
|
||||
|
||||
RequestOpenWindow::subscribe([](const std::string &name) {
|
||||
if (name == "Create File") {
|
||||
auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true);
|
||||
if (newProvider != nullptr && !newProvider->open())
|
||||
hex::ImHexApi::Provider::remove(newProvider);
|
||||
else
|
||||
EventProviderOpened::post(newProvider);
|
||||
auto newProvider = ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true);
|
||||
ImHexApi::Provider::openProvider(newProvider);
|
||||
} else if (name == "Open File") {
|
||||
fs::openFileBrowser(fs::DialogMode::Open, { }, [](const auto &path) {
|
||||
if (path.extension() == ".hexproj") {
|
||||
@@ -195,20 +189,15 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}
|
||||
|
||||
auto newProvider = static_cast<FileProvider*>(
|
||||
ImHexApi::Provider::createProvider("hex.builtin.provider.file", true)
|
||||
);
|
||||
auto provider = ImHexApi::Provider::createProvider("hex.builtin.provider.file", true);
|
||||
auto newProvider = static_cast<FileProvider*>(provider.get());
|
||||
|
||||
if (newProvider == nullptr)
|
||||
return;
|
||||
|
||||
newProvider->setPath(path);
|
||||
if (!newProvider->open()) {
|
||||
hex::ImHexApi::Provider::remove(newProvider);
|
||||
} else {
|
||||
EventProviderOpened::post(newProvider);
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name");
|
||||
}
|
||||
ImHexApi::Provider::openProvider(provider);
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name");
|
||||
}, {}, true);
|
||||
} else if (name == "Open Project") {
|
||||
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
|
||||
EventProviderCreated::subscribe([](hex::prv::Provider *provider) {
|
||||
EventProviderCreated::subscribe([](std::shared_ptr<prv::Provider> provider) {
|
||||
if (provider->shouldSkipLoadInterface())
|
||||
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()) {
|
||||
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
|
||||
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider.get()); });
|
||||
return;
|
||||
}
|
||||
|
||||
TaskManager::createBlockingTask("hex.builtin.provider.opening", TaskManager::NoProgress, [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); });
|
||||
}
|
||||
});
|
||||
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); });
|
||||
}
|
||||
});
|
||||
else if (dynamic_cast<prv::IProviderLoadInterface*>(provider.get()) == nullptr) {
|
||||
ImHexApi::Provider::openProvider(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){
|
||||
#if defined(NFD_PORTAL)
|
||||
ui::PopupError::open(fmt::format("hex.builtin.popup.error.file_dialog.portal"_lang, errMsg));
|
||||
|
||||
@@ -377,10 +377,10 @@ namespace hex::plugin::builtin {
|
||||
/* Create File */
|
||||
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);
|
||||
if (newProvider != nullptr && !newProvider->open())
|
||||
hex::ImHexApi::Provider::remove(newProvider);
|
||||
if (newProvider != nullptr && newProvider->open().isFailure())
|
||||
hex::ImHexApi::Provider::remove(newProvider.get());
|
||||
else
|
||||
EventProviderOpened::post(newProvider);
|
||||
EventProviderOpened::post(newProvider.get());
|
||||
}, noRunningTasks, ContentRegistry::Views::getViewByName("hex.builtin.view.hex_editor.name"));
|
||||
|
||||
/* Open File */
|
||||
@@ -401,7 +401,7 @@ namespace hex::plugin::builtin {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
provider->close();
|
||||
if (!provider->open())
|
||||
if (provider->open().isFailure())
|
||||
ImHexApi::Provider::remove(provider, true);
|
||||
|
||||
EventDataChanged::post(provider);
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
|
||||
#include <popups/popup_file_chooser.hpp>
|
||||
|
||||
#include <ui/text_editor.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
PopupDecodedString::PopupDecodedString(std::string decodedString) : m_decodedString(std::move(decodedString)) {
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#include <fonts/vscode_icons.hpp>
|
||||
|
||||
#include <ui/text_editor.hpp>
|
||||
#include <wolv/literals.hpp>
|
||||
|
||||
using namespace wolv::literals;
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
|
||||
#include <popups/popup_file_chooser.hpp>
|
||||
|
||||
#include <ui/text_editor.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
PerProvider<std::string> PopupFind::s_inputString;
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
#include <hex/api/content_registry/settings.hpp>
|
||||
|
||||
#include <ui/text_editor.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
PopupPasteBehaviour::PopupPasteBehaviour(const Region &selection, const std::function<void(const Region &selection, bool selectionCheck)> &pasteCallback)
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
|
||||
#include <content/differing_byte_searcher.hpp>
|
||||
|
||||
#include <ui/text_editor.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
PopupRemove::PopupRemove(u64 address, size_t size) : m_address(address), m_size(size) {}
|
||||
|
||||
@@ -87,13 +87,14 @@ namespace hex::plugin::builtin {
|
||||
newProvider->loadSettings(providerSettings.at("settings"));
|
||||
loaded = true;
|
||||
} catch (const std::exception &e){
|
||||
providerWarnings[newProvider] = e.what();
|
||||
providerWarnings[newProvider.get()] = e.what();
|
||||
}
|
||||
if (loaded) {
|
||||
if (!newProvider->open() || !newProvider->isAvailable() || !newProvider->isReadable()) {
|
||||
providerWarnings[newProvider] = newProvider->getErrorMessage();
|
||||
auto result = newProvider->open();
|
||||
if (result.isFailure() || !newProvider->isAvailable() || !newProvider->isReadable()) {
|
||||
providerWarnings[newProvider.get()] = result.getErrorMessage();
|
||||
} else {
|
||||
EventProviderOpened::post(newProvider);
|
||||
EventProviderOpened::post(newProvider.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,8 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
#endif
|
||||
|
||||
bool DiskProvider::open() {
|
||||
prv::Provider::OpenResult DiskProvider::open() {
|
||||
OpenResult result;
|
||||
m_readable = true;
|
||||
m_writable = true;
|
||||
|
||||
@@ -171,8 +172,7 @@ namespace hex::plugin::builtin {
|
||||
m_writable = false;
|
||||
|
||||
if (m_diskHandle == INVALID_HANDLE_VALUE) {
|
||||
this->setErrorMessage(hex::formatSystemError(::GetLastError()));
|
||||
return false;
|
||||
return OpenResult::failure(hex::formatSystemError(::GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,12 +194,12 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
if (m_diskHandle == nullptr || m_diskHandle == INVALID_HANDLE_VALUE) {
|
||||
this->setErrorMessage(hex::formatSystemError(::GetLastError()));
|
||||
auto error = ::GetLastError();
|
||||
m_readable = false;
|
||||
m_diskHandle = nullptr;
|
||||
CloseHandle(m_diskHandle);
|
||||
|
||||
return false;
|
||||
return OpenResult::failure(hex::formatSystemError(error));
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -208,17 +208,14 @@ namespace hex::plugin::builtin {
|
||||
|
||||
m_diskHandle = ::open(path.c_str(), O_RDWR);
|
||||
if (m_diskHandle == -1) {
|
||||
this->setErrorMessage(fmt::format("hex.builtin.provider.disk.error.read_rw"_lang, path, formatSystemError(errno)));
|
||||
log::warn("{}", this->getErrorMessage());
|
||||
result = OpenResult::warning(fmt::format("hex.builtin.provider.disk.error.read_rw"_lang, path, formatSystemError(errno)));
|
||||
m_diskHandle = ::open(path.c_str(), O_RDONLY);
|
||||
m_writable = false;
|
||||
}
|
||||
|
||||
if (m_diskHandle == -1) {
|
||||
this->setErrorMessage(fmt::format("hex.builtin.provider.disk.error.read_ro"_lang, path, formatSystemError(errno)));
|
||||
log::warn("{}", this->getErrorMessage());
|
||||
m_readable = false;
|
||||
return false;
|
||||
return OpenResult::failure(fmt::format("hex.builtin.provider.disk.error.read_ro"_lang, path, formatSystemError(errno)));
|
||||
}
|
||||
|
||||
u64 diskSize = 0;
|
||||
@@ -228,7 +225,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
#endif
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
void DiskProvider::close() {
|
||||
|
||||
@@ -198,24 +198,23 @@ namespace hex::plugin::builtin {
|
||||
m_path.make_preferred();
|
||||
}
|
||||
|
||||
bool FileProvider::open() {
|
||||
prv::Provider::OpenResult FileProvider::open() {
|
||||
const size_t maxMemoryFileSize = ContentRegistry::Settings::read<u64>("hex.builtin.setting.general", "hex.builtin.setting.general.max_mem_file_size", 128_MiB);
|
||||
|
||||
size_t fileSize = 0x00;
|
||||
{
|
||||
wolv::io::File file(m_path, wolv::io::File::Mode::Read);
|
||||
if (!file.isValid()) {
|
||||
this->setErrorMessage(fmt::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), formatSystemError(file.getOpenError().value_or(0))));
|
||||
return false;
|
||||
return OpenResult::failure(fmt::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), formatSystemError(file.getOpenError().value_or(0))));
|
||||
}
|
||||
|
||||
fileSize = file.getSize();
|
||||
}
|
||||
|
||||
const bool directAccess = fileSize >= maxMemoryFileSize;
|
||||
const bool result = open(directAccess);
|
||||
const auto result = open(directAccess);
|
||||
|
||||
if (result && directAccess) {
|
||||
if (result.isSuccess() && directAccess) {
|
||||
m_writable = false;
|
||||
|
||||
ui::BannerButton::open(ICON_VS_WARNING, "hex.builtin.provider.file.too_large", ImColor(135, 116, 66), "hex.builtin.provider.file.too_large.allow_write", [this]{
|
||||
@@ -227,7 +226,7 @@ namespace hex::plugin::builtin {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool FileProvider::open(bool directAccess) {
|
||||
prv::Provider::OpenResult FileProvider::open(bool directAccess) {
|
||||
m_readable = true;
|
||||
m_writable = true;
|
||||
|
||||
@@ -238,8 +237,7 @@ namespace hex::plugin::builtin {
|
||||
file = wolv::io::File(m_path, wolv::io::File::Mode::Read);
|
||||
if (!file.isValid()) {
|
||||
m_readable = false;
|
||||
this->setErrorMessage(fmt::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), formatSystemError(file.getOpenError().value_or(0))));
|
||||
return false;
|
||||
return OpenResult::failure(fmt::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), formatSystemError(file.getOpenError().value_or(0))));
|
||||
}
|
||||
|
||||
ui::ToastInfo::open("hex.builtin.popup.error.read_only"_lang);
|
||||
@@ -258,8 +256,7 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
|
||||
if (alreadyOpenedFileProvider != s_openedFiles.end()) {
|
||||
ImHexApi::Provider::setCurrentProvider(*alreadyOpenedFileProvider);
|
||||
return false;
|
||||
return OpenResult::redirect(*alreadyOpenedFileProvider);
|
||||
} else {
|
||||
s_openedFiles.insert(this);
|
||||
}
|
||||
@@ -281,7 +278,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
m_changeEventAcknowledgementPending = false;
|
||||
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -313,10 +310,6 @@ namespace hex::plugin::builtin {
|
||||
if (!wolv::io::fs::exists(fullPath))
|
||||
fullPath = path;
|
||||
|
||||
if (!wolv::io::fs::exists(fullPath)) {
|
||||
this->setErrorMessage(fmt::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), formatSystemError(ENOENT)));
|
||||
}
|
||||
|
||||
path = std::move(fullPath);
|
||||
}
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@ namespace hex::plugin::builtin {
|
||||
};
|
||||
}
|
||||
|
||||
bool GDBProvider::open() {
|
||||
prv::Provider::OpenResult GDBProvider::open() {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
|
||||
CachedProvider::open();
|
||||
@@ -264,11 +264,11 @@ namespace hex::plugin::builtin {
|
||||
gdb::sendReceivePackage(m_socket, gdb::createPacket("!"));
|
||||
gdb::sendReceivePackage(m_socket, gdb::createPacket("Hg0"));
|
||||
|
||||
if (m_socket.isConnected()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
if (!m_socket.isConnected()) {
|
||||
return OpenResult::failure("hex.builtin.provider.gdb.server.error.not_connected"_lang);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void GDBProvider::close() {
|
||||
|
||||
@@ -245,21 +245,19 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
}
|
||||
|
||||
bool IntelHexProvider::open() {
|
||||
prv::Provider::OpenResult IntelHexProvider::open() {
|
||||
auto file = wolv::io::File(m_sourceFilePath, wolv::io::File::Mode::Read);
|
||||
if (!file.isValid()) {
|
||||
this->setErrorMessage(fmt::format("hex.builtin.provider.file.error.open"_lang, m_sourceFilePath.string(), formatSystemError(errno)));
|
||||
return false;
|
||||
return OpenResult::failure(fmt::format("hex.builtin.provider.file.error.open"_lang, m_sourceFilePath.string(), formatSystemError(errno)));
|
||||
}
|
||||
|
||||
auto data = intel_hex::parseIntelHex(file.readString());
|
||||
if (!data.has_value()) {
|
||||
this->setErrorMessage(data.error());
|
||||
return false;
|
||||
return OpenResult::failure(data.error());
|
||||
}
|
||||
processMemoryRegions(data);
|
||||
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
void IntelHexProvider::close() {
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
bool MemoryFileProvider::open() {
|
||||
prv::Provider::OpenResult MemoryFileProvider::open() {
|
||||
if (m_data.empty()) {
|
||||
m_data.resize(1);
|
||||
}
|
||||
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
void MemoryFileProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
||||
@@ -51,16 +51,16 @@ namespace hex::plugin::builtin {
|
||||
|
||||
auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.file", true);
|
||||
|
||||
if (auto fileProvider = dynamic_cast<FileProvider*>(newProvider); fileProvider != nullptr) {
|
||||
if (auto fileProvider = dynamic_cast<FileProvider*>(newProvider.get()); fileProvider != nullptr) {
|
||||
fileProvider->setPath(path);
|
||||
|
||||
if (!fileProvider->open()) {
|
||||
ImHexApi::Provider::remove(newProvider);
|
||||
if (fileProvider->open().isFailure()) {
|
||||
ImHexApi::Provider::remove(newProvider.get());
|
||||
} else {
|
||||
MovePerProviderData::post(this, fileProvider);
|
||||
|
||||
fileProvider->markDirty(false);
|
||||
EventProviderOpened::post(newProvider);
|
||||
EventProviderOpened::post(newProvider.get());
|
||||
ImHexApi::Provider::remove(this, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,21 +170,19 @@ namespace hex::plugin::builtin {
|
||||
|
||||
}
|
||||
|
||||
bool MotorolaSRECProvider::open() {
|
||||
prv::Provider::OpenResult MotorolaSRECProvider::open() {
|
||||
auto file = wolv::io::File(m_sourceFilePath, wolv::io::File::Mode::Read);
|
||||
if (!file.isValid()) {
|
||||
this->setErrorMessage(fmt::format("hex.builtin.provider.file.error.open"_lang, m_sourceFilePath.string(), formatSystemError(errno)));
|
||||
return false;
|
||||
return OpenResult::failure(fmt::format("hex.builtin.provider.file.error.open"_lang, m_sourceFilePath.string(), formatSystemError(errno)));
|
||||
}
|
||||
|
||||
auto data = motorola_srec::parseMotorolaSREC(file.readString());
|
||||
if (!data.has_value()) {
|
||||
this->setErrorMessage(data.error());
|
||||
return false;
|
||||
return OpenResult::failure(data.error());
|
||||
}
|
||||
processMemoryRegions(data);
|
||||
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
void MotorolaSRECProvider::close() {
|
||||
|
||||
@@ -33,21 +33,21 @@
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
bool ProcessMemoryProvider::open() {
|
||||
prv::Provider::OpenResult ProcessMemoryProvider::open() {
|
||||
if (m_selectedProcess == nullptr)
|
||||
return false;
|
||||
return OpenResult::failure("hex.builtin.provider.process_memory.error.no_process_selected"_lang);
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
m_processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_selectedProcess->id);
|
||||
if (m_processHandle == nullptr)
|
||||
return false;
|
||||
return OpenResult::failure("hex.builtin.provider.process_memory.error.open_process"_lang);
|
||||
#else
|
||||
m_processId = pid_t(m_selectedProcess->id);
|
||||
#endif
|
||||
|
||||
this->reloadProcessModules();
|
||||
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
void ProcessMemoryProvider::close() {
|
||||
@@ -125,7 +125,7 @@ namespace hex::plugin::builtin {
|
||||
for (const auto &memoryRegion : m_memoryRegions) {
|
||||
|
||||
if (address < memoryRegion.region.getStartAddress())
|
||||
return { Region { lastRegion.getEndAddress() + 1LLU, memoryRegion.region.getStartAddress() - lastRegion.getEndAddress() }, false };
|
||||
return { Region { lastRegion.getEndAddress(), memoryRegion.region.getStartAddress() - lastRegion.getEndAddress() }, false };
|
||||
|
||||
lastRegion = memoryRegion.region;
|
||||
}
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
bool UDPProvider::open() {
|
||||
prv::Provider::OpenResult UDPProvider::open() {
|
||||
m_udpServer = UDPServer(m_port, [this](std::span<const u8> data) {
|
||||
this->receive(data);
|
||||
});
|
||||
m_udpServer.start();
|
||||
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
void UDPProvider::close() {
|
||||
|
||||
@@ -48,9 +48,9 @@ namespace hex::plugin::builtin {
|
||||
m_provider->save();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool ViewProvider::open() {
|
||||
[[nodiscard]] prv::Provider::OpenResult ViewProvider::open() {
|
||||
if (m_provider == this)
|
||||
return false;
|
||||
return OpenResult::failure("hex.builtin.provider.view.error.no_provider"_lang);
|
||||
|
||||
EventProviderClosing::subscribe(this, [this](const prv::Provider *provider, bool*) {
|
||||
if (m_provider == provider) {
|
||||
@@ -59,7 +59,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
void ViewProvider::close() {
|
||||
EventProviderClosing::unsubscribe(this);
|
||||
|
||||
@@ -279,18 +279,11 @@ namespace hex::plugin::builtin::recent {
|
||||
return;
|
||||
}
|
||||
|
||||
auto *provider = ImHexApi::Provider::createProvider(recentEntry.type, true);
|
||||
auto provider = ImHexApi::Provider::createProvider(recentEntry.type, true);
|
||||
if (provider != nullptr) {
|
||||
provider->loadSettings(recentEntry.data);
|
||||
|
||||
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); });
|
||||
}
|
||||
});
|
||||
ImHexApi::Provider::openProvider(provider);
|
||||
|
||||
updateRecentEntries();
|
||||
}
|
||||
|
||||
@@ -1247,7 +1247,7 @@ namespace hex::plugin::builtin {
|
||||
if (isLocationValid(error.getLocation())) {
|
||||
auto key = ui::TextEditor::Coordinates(error.getLocation().line, error.getLocation().column);
|
||||
|
||||
if (!errorMarkers.contains(key) || errorMarkers[key].first < error.getLocation().length)
|
||||
if (!errorMarkers.contains(key) || errorMarkers[key].first < (i32) error.getLocation().length)
|
||||
errorMarkers[key] = std::make_pair(error.getLocation().length, processMessage(error.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <hex/api/imhex_api/system.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/api/tutorial_manager.hpp>
|
||||
|
||||
#include <hex/api/events/events_provider.hpp>
|
||||
#include <hex/api/events/events_gui.hpp>
|
||||
@@ -523,7 +524,6 @@ namespace hex::plugin::builtin {
|
||||
flags |= ImGuiTabItemFlags_UnsavedDocument;
|
||||
if (i64(i) == selectedProviderIndex && providerJustChanged) {
|
||||
flags |= ImGuiTabItemFlags_SetSelected;
|
||||
providerJustChanged = false;
|
||||
}
|
||||
|
||||
static size_t lastSelectedProvider = 0;
|
||||
@@ -534,7 +534,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (isSelected && lastSelectedProvider != i) {
|
||||
if (isSelected && lastSelectedProvider != i && !providerJustChanged) {
|
||||
ImHexApi::Provider::setCurrentProvider(i);
|
||||
lastSelectedProvider = i;
|
||||
}
|
||||
@@ -554,6 +554,8 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
|
||||
providerJustChanged = false;
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
@@ -15,8 +15,9 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ViewFullScreenFileInfo::ViewFullScreenFileInfo(std::fs::path filePath) : m_filePath(std::move(filePath)) {
|
||||
this->m_provider.setPath(m_filePath);
|
||||
if (!this->m_provider.open()) {
|
||||
if (this->m_provider.open().isFailure()) {
|
||||
ui::ToastError::open("hex.builtin.view.fullscreen.file_info.error.file_not_readable"_lang);
|
||||
return;
|
||||
}
|
||||
|
||||
m_analysisTask = TaskManager::createBlockingTask("hex.builtin.view.fullscreen.file_info.analyzing", TaskManager::NoProgress, [this](Task &task) {
|
||||
|
||||
@@ -67,8 +67,9 @@ namespace hex::plugin::builtin {
|
||||
if (ImGuiExt::DimmedButton(fmt::format("{} {}", ICON_VS_OPEN_PREVIEW, "hex.builtin.view.fullscreen.save_editor.select_file"_lang).c_str(), ImVec2(-1, 0))) {
|
||||
fs::openFileBrowser(fs::DialogMode::Open, {}, [this](const std::fs::path &path) {
|
||||
this->m_provider.setPath(path);
|
||||
if (!this->m_provider.open()) {
|
||||
if (this->m_provider.open().isFailure()) {
|
||||
ui::ToastError::open("hex.builtin.view.fullscreen.save_editor.error.not_readable"_lang);
|
||||
return;
|
||||
}
|
||||
|
||||
ContentRegistry::PatternLanguage::configureRuntime(m_runtime, &m_provider);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <wolv/io/file.hpp>
|
||||
#include <wolv/utils/guards.hpp>
|
||||
#include "imgui_internal.h"
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
@@ -389,14 +390,13 @@ namespace hex::plugin::builtin {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
TaskManager::doLater([region, provider, name]{
|
||||
auto newProvider = ImHexApi::Provider::createProvider("hex.builtin.provider.view", true);
|
||||
if (auto *viewProvider = dynamic_cast<ViewProvider*>(newProvider); viewProvider != nullptr) {
|
||||
if (auto *viewProvider = dynamic_cast<ViewProvider*>(newProvider.get()); viewProvider != nullptr) {
|
||||
viewProvider->setProvider(region.getStartAddress(), region.getSize(), provider);
|
||||
viewProvider->setName(fmt::format("'{}' View", name));
|
||||
|
||||
if (viewProvider->open()) {
|
||||
EventProviderOpened::post(viewProvider);
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.hex_editor", "hex.builtin.achievement.hex_editor.open_new_view.name");
|
||||
}
|
||||
ImHexApi::Provider::openProvider(newProvider);
|
||||
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.hex_editor", "hex.builtin.achievement.hex_editor.open_new_view.name");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -441,6 +441,10 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||
m_selectedEntryName.reset();
|
||||
}
|
||||
|
||||
// Enter editing mode when double-clicking the row
|
||||
const bool editable = entry.editingFunction.has_value() && m_selectedProvider->isWritable();
|
||||
if (ImGui::IsItemHovered()) {
|
||||
@@ -469,6 +473,10 @@ namespace hex::plugin::builtin {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||
entry.editing = false;
|
||||
}
|
||||
|
||||
// Handle editing mode
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::SetNextItemWidth(-1);
|
||||
|
||||
@@ -1187,7 +1187,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableSetupScrollFreeze(0, 1);
|
||||
ImGui::TableSetupColumn("hex.ui.common.offset"_lang, 0, -1, ImGui::GetID("offset"));
|
||||
ImGui::TableSetupColumn("hex.ui.common.size"_lang, 0, -1, ImGui::GetID("size"));
|
||||
ImGui::TableSetupColumn("hex.ui.common.value"_lang, 0, -1, ImGui::GetID("value"));
|
||||
ImGui::TableSetupColumn("hex.ui.common.value"_lang, ImGuiTableColumnFlags_WidthStretch, -1, ImGui::GetID("value"));
|
||||
|
||||
auto sortSpecs = ImGui::TableGetSortSpecs();
|
||||
|
||||
@@ -1197,22 +1197,22 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
if (sortSpecs->SpecsDirty) {
|
||||
std::sort(currOccurrences.begin(), currOccurrences.end(), [this, &sortSpecs, provider](const Occurrence &left, const Occurrence &right) -> bool {
|
||||
std::ranges::stable_sort(currOccurrences, [this, &sortSpecs, provider](const Occurrence &left, const Occurrence &right) -> bool {
|
||||
if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("offset")) {
|
||||
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
||||
return left.region.getStartAddress() > right.region.getStartAddress();
|
||||
else
|
||||
return left.region.getStartAddress() < right.region.getStartAddress();
|
||||
else
|
||||
return left.region.getStartAddress() > right.region.getStartAddress();
|
||||
} else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("size")) {
|
||||
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
||||
return left.region.getSize() > right.region.getSize();
|
||||
else
|
||||
return left.region.getSize() < right.region.getSize();
|
||||
else
|
||||
return left.region.getSize() > right.region.getSize();
|
||||
} else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("value")) {
|
||||
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
||||
return this->decodeValue(provider, left) > this->decodeValue(provider, right);
|
||||
else
|
||||
return this->decodeValue(provider, left) < this->decodeValue(provider, right);
|
||||
else
|
||||
return this->decodeValue(provider, left) > this->decodeValue(provider, right);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
#include <content/popups/hex_editor/popup_hex_editor_find.hpp>
|
||||
#include <pl/patterns/pattern.hpp>
|
||||
#include <hex/helpers/menu_items.hpp>
|
||||
#include <ui/text_editor.hpp>
|
||||
#include <wolv/literals.hpp>
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
@@ -60,8 +59,10 @@ namespace hex::plugin::builtin {
|
||||
|
||||
std::optional<color_t> result;
|
||||
for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getForegroundHighlightingFunctions()) {
|
||||
if (auto color = callback(address, data, size, result.has_value()); color.has_value())
|
||||
if (auto color = callback(address, data, size, result.has_value()); color.has_value()) {
|
||||
result = color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!result.has_value()) {
|
||||
@@ -95,7 +96,7 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
|
||||
ContentRegistry::Settings::onChange("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.show_extended_ascii", [this](const ContentRegistry::Settings::SettingsValue &value) {
|
||||
m_hexEditor.enableShowExtendedAscii(value.get<bool>(true));
|
||||
m_hexEditor.enableShowExtendedAscii(value.get<bool>(false));
|
||||
});
|
||||
|
||||
ContentRegistry::Settings::onChange("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.minimap", [this](const ContentRegistry::Settings::SettingsValue &value) {
|
||||
@@ -1167,10 +1168,9 @@ namespace hex::plugin::builtin {
|
||||
auto selection = ImHexApi::HexEditor::getSelection();
|
||||
|
||||
auto newProvider = ImHexApi::Provider::createProvider("hex.builtin.provider.view", true);
|
||||
if (auto *viewProvider = dynamic_cast<ViewProvider*>(newProvider); viewProvider != nullptr) {
|
||||
if (auto *viewProvider = dynamic_cast<ViewProvider*>(newProvider.get()); viewProvider != nullptr) {
|
||||
viewProvider->setProvider(selection->getStartAddress(), selection->getSize(), selection->getProvider());
|
||||
if (viewProvider->open())
|
||||
EventProviderOpened::post(viewProvider);
|
||||
ImHexApi::Provider::openProvider(newProvider);
|
||||
}
|
||||
},
|
||||
[] { return ImHexApi::HexEditor::isSelectionValid() && ImHexApi::Provider::isValid(); },
|
||||
|
||||
@@ -181,7 +181,7 @@ namespace hex::plugin::builtin {
|
||||
// Draw a table containing all the existing highlighting rules
|
||||
if (ImGui::BeginTable("RulesList", 2, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_ScrollY, ImGui::GetContentRegionAvail() - ImVec2(0, ImGui::GetTextLineHeightWithSpacing() + ImGui::GetStyle().WindowPadding.y))) {
|
||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch, 1);
|
||||
ImGui::TableSetupColumn("Enabled", ImGuiTableColumnFlags_WidthFixed, 10_scaled);
|
||||
ImGui::TableSetupColumn("Enabled", ImGuiTableColumnFlags_WidthFixed, 15_scaled);
|
||||
|
||||
for (auto it = m_rules->begin(); it != m_rules->end(); ++it) {
|
||||
auto &rule = *it;
|
||||
@@ -197,6 +197,9 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (m_selectedRule == it && !rule.enabled)
|
||||
m_selectedRule = m_rules->end();
|
||||
|
||||
// Draw enabled checkbox
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2());
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
using namespace hex::literals;
|
||||
|
||||
ViewInformation::ViewInformation() : View::Window("hex.builtin.view.information.name", ICON_VS_GRAPH_LINE) {
|
||||
ViewInformation::ViewInformation() : View::Scrolling("hex.builtin.view.information.name", ICON_VS_GRAPH_LINE) {
|
||||
m_analysisData.setOnCreateCallback([](const prv::Provider *provider, AnalysisData &data) {
|
||||
data.analyzedProvider = provider;
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ namespace hex::plugin::builtin {
|
||||
bool patternsValid = false;
|
||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||
if (TRY_LOCK(ContentRegistry::PatternLanguage::getRuntimeLock())) {
|
||||
patternsValid = runtime.arePatternsValid();
|
||||
patternsValid = runtime.getCreatedPatternCount() > 0 && runtime.arePatternsValid();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabBar("##SectionSelector")) {
|
||||
|
||||
@@ -477,11 +477,6 @@ namespace hex::plugin::builtin {
|
||||
m_textEditor.get(provider).selectWordUnderCursor();
|
||||
}
|
||||
|
||||
if (m_cursorNeedsUpdate.get(provider)) {
|
||||
m_textEditor.get(provider).setFocusAtCoords(m_cursorPosition.get(provider));
|
||||
m_cursorNeedsUpdate.get(provider) = false;
|
||||
}
|
||||
|
||||
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr) {
|
||||
setupFindReplace(editor);
|
||||
setupGotoLine(editor);
|
||||
@@ -716,7 +711,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
static int findFlags = ImGuiInputTextFlags_EnterReturnsTrue;
|
||||
static int findFlags = ImGuiInputTextFlags_None;
|
||||
|
||||
std::string hint = "hex.builtin.view.pattern_editor.find_hint"_lang.operator std::string();
|
||||
if (m_findHistorySize > 0) {
|
||||
@@ -724,6 +719,8 @@ namespace hex::plugin::builtin {
|
||||
hint += ICON_BI_DATA_TRANSFER_BOTH;
|
||||
hint += "hex.builtin.view.pattern_editor.find_hint_history"_lang.operator std::string();
|
||||
}
|
||||
|
||||
static bool enterPressedReplace = false;
|
||||
static bool enterPressedFind = false;
|
||||
ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
|
||||
if (ImGui::InputTextWithHint("###findInputTextWidget", hint.c_str(), findWord, findFlags) || enter ) {
|
||||
@@ -775,6 +772,12 @@ namespace hex::plugin::builtin {
|
||||
updateCount = true;
|
||||
requestFocusFind = true;
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
if (ImGui::BeginTooltip()) {
|
||||
ImGui::TextUnformatted("hex.builtin.view.pattern_editor.match_case_tooltip"_lang);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -791,7 +794,12 @@ namespace hex::plugin::builtin {
|
||||
updateCount = true;
|
||||
requestFocusFind = true;
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
if (ImGui::BeginTooltip()) {
|
||||
ImGui::TextUnformatted("hex.builtin.view.pattern_editor.whole_word_tooltip"_lang);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
bool useRegex = findReplaceHandler->getFindRegEx();
|
||||
@@ -807,6 +815,13 @@ namespace hex::plugin::builtin {
|
||||
updateCount = true;
|
||||
requestFocusFind = true;
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
if (ImGui::BeginTooltip()) {
|
||||
ImGui::TextUnformatted("hex.builtin.view.pattern_editor.regex_tooltip"_lang);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static std::string counterString;
|
||||
|
||||
@@ -852,12 +867,15 @@ namespace hex::plugin::builtin {
|
||||
if (ImGuiExt::IconButton(ICON_VS_ARROW_UP, ImVec4(1, 1, 1, 1)))
|
||||
upArrowFind = true;
|
||||
|
||||
static bool downArrowReplace = false;
|
||||
static bool upArrowReplace = false;
|
||||
static std::string replaceWord;
|
||||
if (m_replaceMode) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
static int replaceFlags = ImGuiInputTextFlags_EnterReturnsTrue;
|
||||
static int replaceFlags = ImGuiInputTextFlags_None;
|
||||
|
||||
hint = "hex.builtin.view.pattern_editor.replace_hint"_lang.operator std::string();
|
||||
if (m_replaceHistorySize > 0) {
|
||||
@@ -867,31 +885,13 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
|
||||
static std::string replaceWord;
|
||||
static bool downArrowReplace = false;
|
||||
static bool upArrowReplace = false;
|
||||
if (ImGui::InputTextWithHint("###replaceInputTextWidget", hint.c_str(), replaceWord, replaceFlags) || downArrowReplace || upArrowReplace) {
|
||||
findReplaceHandler->setReplaceWord(replaceWord);
|
||||
historyInsert(m_replaceHistory, m_replaceHistorySize, m_replaceHistoryIndex, replaceWord);
|
||||
if (ImGui::InputTextWithHint("###replaceInputTextWidget", hint.c_str(), replaceWord, replaceFlags) || enter) {
|
||||
if (enter)
|
||||
enterPressedReplace = true;
|
||||
|
||||
bool textReplaced = findReplaceHandler->replace(textEditor, !shift && !upArrowReplace);
|
||||
if (textReplaced) {
|
||||
if (count > 0) {
|
||||
if (position == count)
|
||||
position -= 1;
|
||||
count -= 1;
|
||||
}
|
||||
updateCount = true;
|
||||
}
|
||||
|
||||
downArrowReplace = false;
|
||||
upArrowReplace = false;
|
||||
|
||||
if (enterPressedFind) {
|
||||
enterPressedFind = false;
|
||||
requestFocusFind = false;
|
||||
}
|
||||
updateCount = true;
|
||||
requestFocusReplace = true;
|
||||
findReplaceHandler->setReplaceWord(replaceWord);
|
||||
}
|
||||
|
||||
if (requestFocus || requestFocusReplace) {
|
||||
@@ -947,6 +947,31 @@ namespace hex::plugin::builtin {
|
||||
requestFocusFind = true;
|
||||
enterPressedFind = false;
|
||||
}
|
||||
|
||||
if (downArrowReplace || upArrowReplace || enterPressedReplace) {
|
||||
historyInsert(m_replaceHistory, m_replaceHistorySize, m_replaceHistoryIndex, replaceWord);
|
||||
findReplaceHandler->m_undoBuffer.clear();
|
||||
bool textReplaced = findReplaceHandler->replace(textEditor, !shift && !upArrowReplace);
|
||||
textEditor->addUndo(findReplaceHandler->m_undoBuffer);
|
||||
if (textReplaced) {
|
||||
if (count > 0) {
|
||||
if (position == count)
|
||||
position -= 1;
|
||||
count -= 1;
|
||||
}
|
||||
updateCount = true;
|
||||
}
|
||||
|
||||
downArrowReplace = false;
|
||||
upArrowReplace = false;
|
||||
|
||||
if (enterPressedFind) {
|
||||
enterPressedFind = false;
|
||||
requestFocusFind = false;
|
||||
}
|
||||
requestFocusReplace = true;
|
||||
enterPressedReplace = false;
|
||||
}
|
||||
}
|
||||
// Escape key to close the popup
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Escape, false)) {
|
||||
@@ -1045,10 +1070,6 @@ namespace hex::plugin::builtin {
|
||||
m_consoleEditor.get(provider).clearRaiseContextMenu();
|
||||
}
|
||||
|
||||
if (m_consoleCursorNeedsUpdate.get(provider)) {
|
||||
m_consoleEditor.get(provider).setFocusAtCoords(m_consoleCursorPosition.get(provider));
|
||||
m_consoleCursorNeedsUpdate.get(provider) = false;
|
||||
}
|
||||
|
||||
if (m_consoleNeedsUpdate) {
|
||||
std::scoped_lock lock(m_logMutex);
|
||||
@@ -1352,7 +1373,7 @@ namespace hex::plugin::builtin {
|
||||
auto source = error.getLocation().source;
|
||||
if (source != nullptr && source->mainSource) {
|
||||
auto key = ui::TextEditor::Coordinates(error.getLocation().line, error.getLocation().column);
|
||||
if (!errorMarkers.contains(key) ||errorMarkers[key].first < error.getLocation().length)
|
||||
if (!errorMarkers.contains(key) || (u32) errorMarkers[key].first < error.getLocation().length)
|
||||
errorMarkers[key] = std::make_pair(u32(error.getLocation().length), processMessage(error.getMessage()));
|
||||
}
|
||||
}
|
||||
@@ -1679,6 +1700,9 @@ namespace hex::plugin::builtin {
|
||||
EventHighlightingChanged::post();
|
||||
|
||||
TaskManager::createTask("hex.builtin.view.pattern_editor.evaluating", TaskManager::NoProgress, [this, code, provider](auto &task) {
|
||||
// Disable exception tracing to speed up evaluation
|
||||
trace::disableExceptionCaptureForCurrentThread();
|
||||
|
||||
auto runtimeLock = std::scoped_lock(ContentRegistry::PatternLanguage::getRuntimeLock());
|
||||
|
||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||
@@ -1836,31 +1860,30 @@ namespace hex::plugin::builtin {
|
||||
EventProviderChanged::subscribe(this, [this](prv::Provider *oldProvider, prv::Provider *newProvider) {
|
||||
if (oldProvider != nullptr) {
|
||||
m_sourceCode.get(oldProvider) = m_textEditor.get(oldProvider).getText();
|
||||
m_scroll.get(oldProvider) = m_textEditor.get(oldProvider).getScroll();
|
||||
m_cursorPosition.get(oldProvider) = m_textEditor.get(oldProvider).getCursorPosition();
|
||||
m_selection.get(oldProvider) = m_textEditor.get(oldProvider).getSelection();
|
||||
m_breakpoints.get(oldProvider) = m_textEditor.get(oldProvider).getBreakpoints();
|
||||
m_consoleCursorPosition.get(oldProvider) = m_consoleEditor.get(oldProvider).getCursorPosition();
|
||||
m_consoleSelection.get(oldProvider) = m_consoleEditor.get(oldProvider).getSelection();
|
||||
m_consoleLongestLineLength.get(oldProvider) = m_consoleEditor.get(oldProvider).getLongestLineLength();
|
||||
m_breakpoints.get(oldProvider) = m_textEditor.get(oldProvider).getBreakpoints();
|
||||
m_cursorNeedsUpdate.get(oldProvider) = false;
|
||||
m_consoleCursorNeedsUpdate.get(oldProvider) = false;
|
||||
m_consoleScroll.get(oldProvider) = m_consoleEditor.get(oldProvider).getScroll();
|
||||
}
|
||||
|
||||
if (newProvider != nullptr) {
|
||||
m_textEditor.get(newProvider).setText(wolv::util::preprocessText(m_sourceCode.get(newProvider)));
|
||||
m_textEditor.get(newProvider).setCursorPosition(m_cursorPosition.get(newProvider));
|
||||
ui::TextEditor::Selection selection = m_selection.get(newProvider);
|
||||
m_textEditor.get(newProvider).setSelection(selection);
|
||||
m_textEditor.get(newProvider).setCursorPosition(m_cursorPosition.get(newProvider),false);
|
||||
m_textEditor.get(newProvider).setScroll(m_scroll.get(newProvider));
|
||||
m_textEditor.get(newProvider).setSelection(m_selection.get(newProvider));
|
||||
m_textEditor.get(newProvider).setBreakpoints(m_breakpoints.get(newProvider));
|
||||
m_textEditor.get(newProvider).setTextChanged(false);
|
||||
m_hasUnevaluatedChanges.get(newProvider) = true;
|
||||
m_consoleEditor.get(newProvider).setText(wolv::util::combineStrings(m_console.get(newProvider), "\n"));
|
||||
m_consoleEditor.get(newProvider).setCursorPosition(m_consoleCursorPosition.get(newProvider));
|
||||
m_consoleEditor.get(newProvider).setLongestLineLength(m_consoleLongestLineLength.get(newProvider));
|
||||
selection = m_consoleSelection.get(newProvider);
|
||||
m_consoleEditor.get(newProvider).setSelection(selection);
|
||||
m_cursorNeedsUpdate.get(newProvider) = true;
|
||||
m_consoleCursorNeedsUpdate.get(newProvider) = true;
|
||||
m_textEditor.get(newProvider).setTextChanged(false);
|
||||
m_hasUnevaluatedChanges.get(newProvider) = true;
|
||||
m_consoleEditor.get(newProvider).setSelection(m_consoleSelection.get(newProvider));
|
||||
m_consoleEditor.get(newProvider).setScroll(m_consoleScroll.get(newProvider));
|
||||
|
||||
}
|
||||
m_textHighlighter.m_needsToUpdateColors = false;
|
||||
|
||||
@@ -1959,7 +1982,7 @@ namespace hex::plugin::builtin {
|
||||
ui::TextEditor::FindReplaceHandler *findReplaceHandler = editor->getFindReplaceHandler();
|
||||
findReplaceHandler->findMatch(editor, 1);
|
||||
} else {
|
||||
m_textEditor->getFindReplaceHandler()->findMatch(&*m_textEditor, 1);
|
||||
m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->findMatch(&m_textEditor.get(ImHexApi::Provider::get()), 1);
|
||||
}
|
||||
}, [this] {
|
||||
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr) {
|
||||
@@ -1977,11 +2000,11 @@ namespace hex::plugin::builtin {
|
||||
ui::TextEditor::FindReplaceHandler *findReplaceHandler = editor->getFindReplaceHandler();
|
||||
findReplaceHandler->findMatch(editor, -1);
|
||||
} else {
|
||||
m_textEditor->getFindReplaceHandler()->findMatch(&*m_textEditor, -1);
|
||||
m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->findMatch(&m_textEditor.get(ImHexApi::Provider::get()), -1);
|
||||
}
|
||||
}, [this] {
|
||||
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr) {
|
||||
return ImHexApi::Provider::isValid() && !m_textEditor->getFindReplaceHandler()->getFindWord().empty();
|
||||
return ImHexApi::Provider::isValid() && !m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->getFindWord().empty();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -1998,22 +2021,22 @@ namespace hex::plugin::builtin {
|
||||
|
||||
/* Replace Next */
|
||||
ContentRegistry::UserInterface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.view.pattern_editor.menu.replace_next" }, 1550, Shortcut::None, [this] {
|
||||
m_textEditor->getFindReplaceHandler()->replace(&*m_textEditor, true);
|
||||
}, [this] { return ImHexApi::Provider::isValid() && !m_textEditor->getFindReplaceHandler()->getReplaceWord().empty() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||
m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->replace(&m_textEditor.get(ImHexApi::Provider::get()), true);
|
||||
}, [this] { return ImHexApi::Provider::isValid() && !m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->getReplaceWord().empty() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||
[]{ return false; },
|
||||
this);
|
||||
|
||||
/* Replace Previous */
|
||||
ContentRegistry::UserInterface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.view.pattern_editor.menu.replace_previous" }, 1560, Shortcut::None, [this] {
|
||||
m_textEditor->getFindReplaceHandler()->replace(&*m_textEditor, false);
|
||||
}, [this] { return ImHexApi::Provider::isValid() && !m_textEditor->getFindReplaceHandler()->getReplaceWord().empty() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||
m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->replace(&m_textEditor.get(ImHexApi::Provider::get()), false);
|
||||
}, [this] { return ImHexApi::Provider::isValid() && !m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->getReplaceWord().empty() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||
[]{ return false; },
|
||||
this);
|
||||
|
||||
/* Replace All */
|
||||
ContentRegistry::UserInterface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.view.pattern_editor.menu.replace_all" }, ICON_VS_REPLACE_ALL, 1570, Shortcut::None, [this] {
|
||||
m_textEditor->getFindReplaceHandler()->replaceAll(&*m_textEditor);
|
||||
}, [this] { return ImHexApi::Provider::isValid() && !m_textEditor->getFindReplaceHandler()->getReplaceWord().empty() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||
m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->replaceAll(&m_textEditor.get(ImHexApi::Provider::get()));
|
||||
}, [this] { return ImHexApi::Provider::isValid() && !m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->getReplaceWord().empty() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||
this);
|
||||
|
||||
|
||||
@@ -2032,19 +2055,19 @@ namespace hex::plugin::builtin {
|
||||
ContentRegistry::UserInterface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.export", "hex.builtin.menu.file.export.pattern" }, ICON_VS_FILE_CODE, 7050, Shortcut::None, [this] {
|
||||
savePatternAsNewFile(false);
|
||||
}, [this] {
|
||||
return ImHexApi::Provider::isValid() && !wolv::util::trim(m_textEditor->getText()).empty();
|
||||
return ImHexApi::Provider::isValid() && !wolv::util::trim(m_textEditor.get(ImHexApi::Provider::get()).getText()).empty();
|
||||
});
|
||||
|
||||
/* Undo */
|
||||
ContentRegistry::UserInterface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.pattern_editor.menu.edit.undo" }, ICON_VS_DISCARD, 1250, AllowWhileTyping + CTRLCMD + Keys::Z, [this] {
|
||||
m_textEditor->undo();
|
||||
}, [this] { return ImHexApi::Provider::isValid() && m_textEditor->canUndo() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||
m_textEditor.get(ImHexApi::Provider::get()).undo();
|
||||
}, [this] { return ImHexApi::Provider::isValid() && m_textEditor.get(ImHexApi::Provider::get()).canUndo() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||
this);
|
||||
|
||||
/* Redo */
|
||||
ContentRegistry::UserInterface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.pattern_editor.menu.edit.redo" }, ICON_VS_REDO, 1275, AllowWhileTyping + CTRLCMD + Keys::Y, [this] {
|
||||
m_textEditor->redo();
|
||||
}, [this] { return ImHexApi::Provider::isValid() && m_textEditor->canRedo() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||
m_textEditor.get(ImHexApi::Provider::get()).redo();
|
||||
}, [this] { return ImHexApi::Provider::isValid() && m_textEditor.get(ImHexApi::Provider::get()).canRedo() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||
this);
|
||||
|
||||
ContentRegistry::UserInterface::addMenuItemSeparator({ "hex.builtin.menu.edit" }, 1280, this);
|
||||
@@ -2052,8 +2075,8 @@ namespace hex::plugin::builtin {
|
||||
|
||||
/* Cut */
|
||||
ContentRegistry::UserInterface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.pattern_editor.menu.edit.cut" }, ICON_VS_COMBINE, 1300, AllowWhileTyping + CTRLCMD + Keys::X, [this] {
|
||||
m_textEditor->cut();
|
||||
}, [this] { return ImHexApi::Provider::isValid() && m_textEditor->hasSelection() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||
m_textEditor.get(ImHexApi::Provider::get()).cut();
|
||||
}, [this] { return ImHexApi::Provider::isValid() && m_textEditor.get(ImHexApi::Provider::get()).hasSelection() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||
this);
|
||||
|
||||
/* Copy */
|
||||
@@ -2061,7 +2084,7 @@ namespace hex::plugin::builtin {
|
||||
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr) {
|
||||
editor->copy();
|
||||
} else {
|
||||
m_textEditor->copy();
|
||||
m_textEditor.get(ImHexApi::Provider::get()).copy();
|
||||
}
|
||||
}, [this] {
|
||||
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
|
||||
@@ -2073,7 +2096,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
/* Paste */
|
||||
ContentRegistry::UserInterface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.pattern_editor.menu.edit.paste" }, ICON_VS_OUTPUT, 1500, AllowWhileTyping + CTRLCMD + Keys::V, [this] {
|
||||
m_textEditor->paste();
|
||||
m_textEditor.get(ImHexApi::Provider::get()).paste();
|
||||
}, [this] { return m_focusedSubWindowName.contains(TextEditorView); },
|
||||
this);
|
||||
|
||||
@@ -2089,7 +2112,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
/* Add Breakpoint */
|
||||
ContentRegistry::UserInterface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.pattern_editor.menu.edit.add_breakpoint"}, ICON_VS_DEBUG_BREAKPOINT_DATA, 1750, Keys::F8 + AllowWhileTyping, [this] {
|
||||
const auto line = m_textEditor.get(ImHexApi::Provider::get()).getCursorPosition().m_line + 1;
|
||||
const auto line = m_textEditor.get(ImHexApi::Provider::get()).getCursorPosition().getLine() + 1;
|
||||
const auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||
|
||||
auto &evaluator = runtime.getInternals().evaluator;
|
||||
@@ -2618,7 +2641,7 @@ namespace hex::plugin::builtin {
|
||||
if (provider == nullptr)
|
||||
return;
|
||||
auto path = m_changeTracker.get(provider).getPath();
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Write);
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||
if (file.isValid() && trackFile) {
|
||||
if (isPatternDirty(provider)) {
|
||||
file.writeString(wolv::util::trim(m_textEditor.get(provider).getText()));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user