mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-29 00:10:02 -05:00
Compare commits
76 Commits
feature/co
...
v1.38.1
| 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:
|
||||||
---
|
- -*
|
||||||
Checks: '-*,
|
- mpi-*
|
||||||
mpi-*,
|
- bugprone-*
|
||||||
bugprone-*,
|
- -bugprone-signal-handler
|
||||||
-bugprone-signal-handler,
|
- -bugprone-narrowing-conversions
|
||||||
-bugprone-narrowing-conversions,
|
- -bugprone-redundant-branch-condition
|
||||||
-bugprone-redundant-branch-condition,
|
- -bugprone-exception-escape
|
||||||
-bugprone-exception-escape,
|
- -bugprone-shared-ptr-array-mismatch
|
||||||
-bugprone-shared-ptr-array-mismatch,
|
- -bugprone-implicit-widening-of-multiplication-result
|
||||||
-bugprone-implicit-widening-of-multiplication-result,
|
- -bugprone-signed-char-misuse
|
||||||
-bugprone-signed-char-misuse,
|
- -bugprone-unhandled-exception-at-new
|
||||||
-bugprone-unhandled-exception-at-new,
|
- -bugprone-infinite-loop
|
||||||
-bugprone-infinite-loop,
|
- -bugprone-easily-swappable-parameters
|
||||||
-bugprone-easily-swappable-parameters,
|
- cert-err52-cpp
|
||||||
cert-err52-cpp,
|
- cert-err60-cpp
|
||||||
cert-err60-cpp,
|
- cert-err34-c
|
||||||
cert-err34-c,
|
- cert-str34-c
|
||||||
cert-str34-c,
|
- cert-dcl21-cpp
|
||||||
cert-dcl21-cpp,
|
- cert-msc50-cpp
|
||||||
cert-msc50-cpp,
|
- cert-msc51-cpp
|
||||||
cert-msc51-cpp,
|
- cert-dcl58-cpp
|
||||||
cert-dcl58-cpp,
|
- cert-flp30-c
|
||||||
cert-flp30-c,
|
- cppcoreguidelines-avoid-const-or-ref-data-members
|
||||||
cppcoreguidelines-avoid-const-or-ref-data-members,
|
- cppcoreguidelines-pro-type-member-init
|
||||||
cppcoreguidelines-pro-type-member-init,
|
- cppcoreguidelines-slicing
|
||||||
cppcoreguidelines-slicing,
|
- cppcoreguidelines-interfaces-global-init
|
||||||
cppcoreguidelines-interfaces-global-init,
|
- cppcoreguidelines-pro-type-static-cast-downcast
|
||||||
cppcoreguidelines-pro-type-static-cast-downcast,
|
- cppcoreguidelines-narrowing-conversions
|
||||||
cppcoreguidelines-narrowing-conversions,
|
- google-default-arguments
|
||||||
google-default-arguments,
|
- google-runtime-operator
|
||||||
google-runtime-operator,
|
- google-explicit-constructor
|
||||||
google-explicit-constructor,
|
- hicpp-multiway-paths-covered
|
||||||
hicpp-multiway-paths-covered,
|
- hicpp-exception-baseclass
|
||||||
hicpp-exception-baseclass,
|
- misc-*
|
||||||
misc-*,
|
- -misc-definitions-in-headers
|
||||||
-misc-definitions-in-headers,
|
- -misc-unused-parameters
|
||||||
-misc-unused-parameters,
|
- -misc-unused-alias-decls
|
||||||
-misc-unused-alias-decls,
|
- -misc-use-anonymous-namespace
|
||||||
-misc-use-anonymous-namespace,
|
- -misc-misleading-identifier
|
||||||
-misc-misleading-identifier,
|
- -misc-confusable-identifiers
|
||||||
-misc-confusable-identifiers,
|
- -misc-misleading-bidirectional
|
||||||
-misc-misleading-bidirectional,
|
- -misc-static-assert
|
||||||
-misc-static-assert,
|
- -misc-no-recursion
|
||||||
-misc-no-recursion,
|
- -misc-const-correctness
|
||||||
-misc-const-correctness,
|
- modernize-*
|
||||||
modernize-*,
|
- -modernize-use-trailing-return-type
|
||||||
-modernize-use-trailing-return-type,
|
- openmp-use-default-none
|
||||||
openmp-use-default-none,
|
- performance-*
|
||||||
performance-*,
|
- -performance-no-int-to-ptr
|
||||||
-performance-no-int-to-ptr,
|
- portability-*
|
||||||
portability-*,
|
- -portability-restrict-system-includes
|
||||||
-portability-restrict-system-includes,
|
- readability-*
|
||||||
readability-*,
|
- -readability-redundant-preprocessor
|
||||||
-readability-redundant-preprocessor,
|
- -readability-named-parameter
|
||||||
-readability-named-parameter,
|
- -readability-function-size
|
||||||
-readability-function-size,
|
- -readability-use-anyofallof
|
||||||
-readability-use-anyofallof,
|
- -readability-identifier-length
|
||||||
-readability-identifier-length,
|
- -readability-magic-numbers
|
||||||
-readability-magic-numbers,
|
- -readability-braces-around-statements
|
||||||
-readability-braces-around-statements,
|
- -readability-suspicious-call-argument
|
||||||
-readability-suspicious-call-argument,
|
- -readability-isolate-declaration
|
||||||
-readability-isolate-declaration,
|
- -readability-else-after-return
|
||||||
-readability-else-after-return,
|
- -readability-redundant-access-specifiers
|
||||||
-readability-redundant-access-specifiers,
|
- -readability-function-cognitive-complexity
|
||||||
-readability-function-cognitive-complexity,
|
- -readability-identifier-naming
|
||||||
-readability-identifier-naming,
|
- '*-include-cleaner'
|
||||||
*-include-cleaner,
|
- -readability-qualified-auto
|
||||||
-readability-qualified-auto'
|
|
||||||
|
|||||||
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@@ -1,5 +1,9 @@
|
|||||||
name: Build
|
name: Build
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
@@ -95,7 +99,6 @@ jobs:
|
|||||||
-DIMHEX_GENERATE_PDBS=ON \
|
-DIMHEX_GENERATE_PDBS=ON \
|
||||||
-DIMHEX_REPLACE_DWARF_WITH_PDB=ON \
|
-DIMHEX_REPLACE_DWARF_WITH_PDB=ON \
|
||||||
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" \
|
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" \
|
||||||
-DCPACK_WIX_VERSION="4" \
|
|
||||||
-DCPACK_WIX_ROOT="$(echo "$USERPROFILE" | tr '\\' '/')/.dotnet/tools" \
|
-DCPACK_WIX_ROOT="$(echo "$USERPROFILE" | tr '\\' '/')/.dotnet/tools" \
|
||||||
..
|
..
|
||||||
|
|
||||||
@@ -166,6 +169,7 @@ jobs:
|
|||||||
|
|
||||||
- name: ⬆️ Upload Windows Installer
|
- name: ⬆️ Upload Windows Installer
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
id: upload-installer
|
||||||
with:
|
with:
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
name: Windows Installer ${{ matrix.architecture_name }}
|
name: Windows Installer ${{ matrix.architecture_name }}
|
||||||
@@ -247,6 +251,7 @@ jobs:
|
|||||||
- name: ⬇️ Install dependencies
|
- name: ⬇️ Install dependencies
|
||||||
run: |
|
run: |
|
||||||
cp dist/vcpkg.json vcpkg.json
|
cp dist/vcpkg.json vcpkg.json
|
||||||
|
vcpkg install
|
||||||
|
|
||||||
- name: ⬇️ Install CMake and Ninja
|
- name: ⬇️ Install CMake and Ninja
|
||||||
uses: lukka/get-cmake@latest
|
uses: lukka/get-cmake@latest
|
||||||
@@ -279,7 +284,6 @@ jobs:
|
|||||||
-DIMHEX_COMMIT_HASH_LONG="$env:GITHUB_SHA" `
|
-DIMHEX_COMMIT_HASH_LONG="$env:GITHUB_SHA" `
|
||||||
-DIMHEX_COMMIT_BRANCH="$($env:GITHUB_REF -replace '.*/', '')" `
|
-DIMHEX_COMMIT_BRANCH="$($env:GITHUB_REF -replace '.*/', '')" `
|
||||||
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" `
|
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" `
|
||||||
-DCPACK_WIX_VERSION="4" `
|
|
||||||
-DCPACK_WIX_ROOT="$($env:USERPROFILE -replace '\\','/')/.dotnet/tools" `
|
-DCPACK_WIX_ROOT="$($env:USERPROFILE -replace '\\','/')/.dotnet/tools" `
|
||||||
.
|
.
|
||||||
|
|
||||||
|
|||||||
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 fetch --tags --recurse-submodules=no
|
||||||
git log nightly..origin/master --oneline --no-merges --pretty=format:'* %s' >> changelog.md
|
git log nightly..origin/master --oneline --no-merges --pretty=format:'* %s' >> changelog.md
|
||||||
|
|
||||||
|
- name: ⬆️ Upload Unsigned x86_64 Windows Installer
|
||||||
|
if: false
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
id: upload-installer-x86_64
|
||||||
|
with:
|
||||||
|
if-no-files-found: error
|
||||||
|
name: Windows Installer ${{ matrix.architecture_name }}
|
||||||
|
path: |
|
||||||
|
imhex-*-x86_64.msi
|
||||||
|
|
||||||
|
- name: ⬆️ Upload Unsigned ARM64 Windows Installer
|
||||||
|
if: false
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
id: upload-installer-arm64
|
||||||
|
with:
|
||||||
|
if-no-files-found: error
|
||||||
|
name: Windows Installer ${{ matrix.architecture_name }}
|
||||||
|
path: |
|
||||||
|
imhex-*-arm64.msi
|
||||||
|
|
||||||
|
- name: 🗑️ Delete unsigned installers
|
||||||
|
if: false
|
||||||
|
run: |
|
||||||
|
rm imhex-*.msi
|
||||||
|
|
||||||
|
- name: 🗝️ Sign Installer
|
||||||
|
if: false
|
||||||
|
uses: signpath/github-action-submit-signing-request@v1
|
||||||
|
with:
|
||||||
|
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
|
||||||
|
organization-id: 'f605a0e8-86cd-411c-bb6f-e05025afcc33'
|
||||||
|
project-slug: 'ImHex'
|
||||||
|
signing-policy-slug: 'release-signing'
|
||||||
|
github-artifact-id: '${{ steps.upload-installer.outputs.artifact-id }}'
|
||||||
|
wait-for-completion: true
|
||||||
|
output-artifact-directory: '.'
|
||||||
|
|
||||||
- name: 📦 Update Pre-Release
|
- name: 📦 Update Pre-Release
|
||||||
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
|
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
95
.github/workflows/release.yml
vendored
95
.github/workflows/release.yml
vendored
@@ -7,6 +7,12 @@ on:
|
|||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
commit_hash:
|
||||||
|
type: string
|
||||||
|
description: 'The commit hash to build (defaults to the latest commit on the default branch)'
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release-update-repos:
|
release-update-repos:
|
||||||
@@ -25,7 +31,7 @@ jobs:
|
|||||||
project_version=`cat ImHex/VERSION`
|
project_version=`cat ImHex/VERSION`
|
||||||
tag_version="${{github.event.release.tag_name}}"
|
tag_version="${{github.event.release.tag_name}}"
|
||||||
tag_version="${tag_version:1}"
|
tag_version="${tag_version:1}"
|
||||||
if [ "$project_version" != "$tag_version" ]; 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"
|
echo "::warning::$project_version and $tag_version are not the same ! Refusing to populate release"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -41,6 +47,7 @@ jobs:
|
|||||||
tag: ImHex-v${{ env.IMHEX_VERSION }}
|
tag: ImHex-v${{ env.IMHEX_VERSION }}
|
||||||
repo: PatternLanguage
|
repo: PatternLanguage
|
||||||
token: ${{ secrets.RELEASE_TOKEN }}
|
token: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
skipIfReleaseExists: true
|
||||||
|
|
||||||
- name: 🎫 Create ImHex-Patterns release
|
- name: 🎫 Create ImHex-Patterns release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
@@ -51,6 +58,7 @@ jobs:
|
|||||||
tag: ImHex-v${{ env.IMHEX_VERSION }}
|
tag: ImHex-v${{ env.IMHEX_VERSION }}
|
||||||
repo: ImHex-Patterns
|
repo: ImHex-Patterns
|
||||||
token: ${{ secrets.RELEASE_TOKEN }}
|
token: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
skipIfReleaseExists: true
|
||||||
|
|
||||||
- name: 🎫 Create imhex-download-sdk release
|
- name: 🎫 Create imhex-download-sdk release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
@@ -61,11 +69,13 @@ jobs:
|
|||||||
tag: v${{ env.IMHEX_VERSION }}
|
tag: v${{ env.IMHEX_VERSION }}
|
||||||
repo: imhex-download-sdk
|
repo: imhex-download-sdk
|
||||||
token: ${{ secrets.RELEASE_TOKEN }}
|
token: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
skipIfReleaseExists: true
|
||||||
|
|
||||||
release-upload-artifacts:
|
release-upload-artifacts:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
name: Release Upload Artifacts
|
name: Release Upload Artifacts
|
||||||
|
outputs:
|
||||||
|
IMHEX_VERSION: ${{ steps.verify_version.outputs.IMHEX_VERSION }}
|
||||||
steps:
|
steps:
|
||||||
- name: 🧰 Checkout
|
- name: 🧰 Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -74,17 +84,19 @@ jobs:
|
|||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: 📜 Verify version and set version variable
|
- name: 📜 Verify version and set version variable
|
||||||
|
id: verify_version
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
project_version=`cat ImHex/VERSION`
|
project_version=`cat ImHex/VERSION`
|
||||||
tag_version="${{github.event.release.tag_name}}"
|
tag_version="${{github.event.release.tag_name}}"
|
||||||
tag_version="${tag_version:1}"
|
tag_version="${tag_version:1}"
|
||||||
if [ "$project_version" != "$tag_version" ]; 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"
|
echo "::warning::$project_version and $tag_version are not the same ! Refusing to populate release"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "IMHEX_VERSION=$project_version" >> $GITHUB_ENV
|
echo "IMHEX_VERSION=$project_version" >> $GITHUB_ENV
|
||||||
|
echo "IMHEX_VERSION=$project_version" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: 🗜️ Create tarball from sources with dependencies
|
- name: 🗜️ Create tarball from sources with dependencies
|
||||||
run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex
|
run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex
|
||||||
@@ -97,6 +109,7 @@ jobs:
|
|||||||
branch: ${{ github.event.release.target_commitish }}
|
branch: ${{ github.event.release.target_commitish }}
|
||||||
workflow_conclusion: success
|
workflow_conclusion: success
|
||||||
skip_unpack: true
|
skip_unpack: true
|
||||||
|
commit: ${{ github.event.inputs.commit_hash }}
|
||||||
|
|
||||||
- name: 🗜️ Unzip files when needed
|
- name: 🗜️ Unzip files when needed
|
||||||
run: |
|
run: |
|
||||||
@@ -115,25 +128,82 @@ jobs:
|
|||||||
|
|
||||||
- name: 🟩 Rename artifacts when needed
|
- name: 🟩 Rename artifacts when needed
|
||||||
run: |
|
run: |
|
||||||
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip
|
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip || true
|
||||||
mv "Windows Portable arm64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-arm64.zip
|
mv "Windows Portable arm64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-arm64.zip || true
|
||||||
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip
|
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip || true
|
||||||
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-Web.zip
|
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-Web.zip || true
|
||||||
rm artifact.tar || true
|
rm artifact.tar || true
|
||||||
|
|
||||||
|
- name: ⬆️ Upload Unsigned x86_64 Windows Installer
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
id: upload-installer-x86_64
|
||||||
|
with:
|
||||||
|
if-no-files-found: error
|
||||||
|
name: Windows Installer x86_64
|
||||||
|
path: |
|
||||||
|
imhex-*-x86_64.msi
|
||||||
|
|
||||||
|
- name: ⬆️ Upload Unsigned ARM64 Windows Installer
|
||||||
|
if: false
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
id: upload-installer-arm64
|
||||||
|
with:
|
||||||
|
if-no-files-found: error
|
||||||
|
name: Windows Installer ARM64
|
||||||
|
path: |
|
||||||
|
imhex-*-arm64.msi
|
||||||
|
|
||||||
|
- name: 🗑️ Delete unsigned installers
|
||||||
|
run: |
|
||||||
|
rm imhex-*-x86_64.msi
|
||||||
|
|
||||||
|
- name: 🗝️ Sign x86_64 Installer
|
||||||
|
uses: signpath/github-action-submit-signing-request@v1
|
||||||
|
with:
|
||||||
|
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
|
||||||
|
organization-id: 'f605a0e8-86cd-411c-bb6f-e05025afcc33'
|
||||||
|
project-slug: 'ImHex'
|
||||||
|
signing-policy-slug: 'release-signing'
|
||||||
|
github-artifact-id: '${{ steps.upload-installer-x86_64.outputs.artifact-id }}'
|
||||||
|
wait-for-completion: true
|
||||||
|
output-artifact-directory: '.'
|
||||||
|
|
||||||
|
- name: 🗝️ Sign ARM64 Installer
|
||||||
|
if: false
|
||||||
|
uses: signpath/github-action-submit-signing-request@v1
|
||||||
|
with:
|
||||||
|
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
|
||||||
|
organization-id: 'f605a0e8-86cd-411c-bb6f-e05025afcc33'
|
||||||
|
project-slug: 'ImHex'
|
||||||
|
signing-policy-slug: 'release-signing'
|
||||||
|
github-artifact-id: '${{ steps.upload-installer-arm64.outputs.artifact-id }}'
|
||||||
|
wait-for-completion: true
|
||||||
|
output-artifact-directory: '.'
|
||||||
|
|
||||||
- name: ⬆️ Upload everything to release
|
- name: ⬆️ Upload everything to release
|
||||||
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
|
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
|
||||||
with:
|
with:
|
||||||
files: '*'
|
files: '*'
|
||||||
|
|
||||||
|
release-update-aur:
|
||||||
|
name: Release update AUR package
|
||||||
|
needs: release-upload-artifacts
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: ⬇️ Download artifacts
|
||||||
|
run: |
|
||||||
|
tagname=${GITHUB_REF#refs/tags/}
|
||||||
|
version=${tagname#v}
|
||||||
|
wget https://github.com/WerWolv/ImHex/releases/download/${tagname}/imhex-${version}-ArchLinux-x86_64.pkg.tar.zst
|
||||||
|
|
||||||
- name: ✒️ Prepare PKGBUILD
|
- name: ✒️ Prepare PKGBUILD
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
cp ImHex/dist/Arch/PKGBUILD .
|
cp ImHex/dist/Arch/PKGBUILD .
|
||||||
|
|
||||||
hash=`md5sum imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst | cut -d ' ' -f 1`
|
hash=`md5sum imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst | cut -d ' ' -f 1`
|
||||||
|
|
||||||
sed -i 's/%version%/${{ env.IMHEX_VERSION }}/g' PKGBUILD
|
sed -i 's/%version%/${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}/g' PKGBUILD
|
||||||
sed -i "s/(SKIP)/($hash)/g" PKGBUILD
|
sed -i "s/(SKIP)/($hash)/g" PKGBUILD
|
||||||
|
|
||||||
- name: ⬆️ Publish AUR package
|
- name: ⬆️ Publish AUR package
|
||||||
@@ -149,7 +219,7 @@ jobs:
|
|||||||
commit_username: iTrooz
|
commit_username: iTrooz
|
||||||
commit_email: itrooz@protonmail.com
|
commit_email: itrooz@protonmail.com
|
||||||
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
||||||
commit_message: Bump to version ${{ env.IMHEX_VERSION }}
|
commit_message: Bump to version ${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}
|
||||||
ssh_keyscan_types: rsa,ecdsa,ed25519
|
ssh_keyscan_types: rsa,ecdsa,ed25519
|
||||||
|
|
||||||
release-update-winget:
|
release-update-winget:
|
||||||
@@ -161,6 +231,7 @@ jobs:
|
|||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
|
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
|
||||||
|
|
||||||
- name: ⬆️ Update winget manifest
|
- name: ⬆️ Update winget manifest
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
env:
|
env:
|
||||||
@@ -193,7 +264,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
||||||
with:
|
with:
|
||||||
snap: imhex-${{ env.IMHEX_VERSION }}-x86_64.snap
|
snap: imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-x86_64.snap
|
||||||
release: stable
|
release: stable
|
||||||
|
|
||||||
- name: ⬆️ Publish arm64 Snap package
|
- name: ⬆️ Publish arm64 Snap package
|
||||||
@@ -202,5 +273,5 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
||||||
with:
|
with:
|
||||||
snap: imhex-${{ env.IMHEX_VERSION }}-arm64.snap
|
snap: imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-arm64.snap
|
||||||
release: stable
|
release: stable
|
||||||
@@ -1,33 +1,38 @@
|
|||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
option(IMHEX_PLUGINS_IN_SHARE "Put the plugins in share/imhex/plugins instead of lib[..]/imhex/plugins (Linux only)" OFF)
|
## General
|
||||||
option(IMHEX_STRIP_RELEASE "Strip the release builds" ON )
|
option(IMHEX_STRIP_RELEASE "Strip the release builds" ON )
|
||||||
option(IMHEX_OFFLINE_BUILD "Enable offline build" OFF)
|
option(IMHEX_OFFLINE_BUILD "Enable offline build" OFF)
|
||||||
option(IMHEX_IGNORE_BAD_CLONE "Disable the bad clone prevention checks" OFF)
|
option(IMHEX_IGNORE_BAD_CLONE "Disable the bad clone prevention checks" OFF)
|
||||||
option(IMHEX_PATTERNS_PULL_MASTER "Download latest files from master branch of the ImHex-Patterns repo" OFF)
|
option(IMHEX_PATTERNS_PULL_MASTER "Download latest files from master branch of the ImHex-Patterns repo" OFF)
|
||||||
option(IMHEX_IGNORE_BAD_COMPILER "Allow compiling with an unsupported compiler" OFF)
|
option(IMHEX_IGNORE_BAD_COMPILER "Allow compiling with an unsupported compiler" OFF)
|
||||||
option(IMHEX_USE_GTK_FILE_PICKER "Use GTK file picker instead of xdg-desktop-portals (Linux only)" OFF)
|
option(IMHEX_USE_GTK_FILE_PICKER "Use GTK file picker instead of xdg-desktop-portals (Linux only)" OFF)
|
||||||
option(IMHEX_DISABLE_STACKTRACE "Disables support for printing stack traces" OFF)
|
|
||||||
option(IMHEX_BUNDLE_DOTNET "Bundle .NET runtime" ON )
|
option(IMHEX_BUNDLE_DOTNET "Bundle .NET runtime" ON )
|
||||||
option(IMHEX_ENABLE_LTO "Enables Link Time Optimizations if possible" OFF)
|
option(IMHEX_ENABLE_LTO "Enables Link Time Optimizations if possible" OFF)
|
||||||
option(IMHEX_USE_DEFAULT_BUILD_SETTINGS "Use default build settings" OFF)
|
option(IMHEX_USE_DEFAULT_BUILD_SETTINGS "Use default build settings" OFF)
|
||||||
option(IMHEX_STRICT_WARNINGS "Enable most available warnings and treat them as errors" ON )
|
|
||||||
option(IMHEX_BUILD_HARDENING "Enable hardening flags for build" ON )
|
option(IMHEX_BUILD_HARDENING "Enable hardening flags for build" ON )
|
||||||
option(IMHEX_STATIC_LINK_PLUGINS "Statically link all plugins into the main executable" OFF)
|
|
||||||
option(IMHEX_GENERATE_PACKAGE "Specify if a native package should be built. (Windows and MacOS only)" OFF)
|
option(IMHEX_GENERATE_PACKAGE "Specify if a native package should be built. (Windows and MacOS only)" OFF)
|
||||||
option(IMHEX_ENABLE_UNITY_BUILD "Enables building ImHex as a unity build." OFF)
|
option(IMHEX_ENABLE_UNITY_BUILD "Enables building ImHex as a unity build." OFF)
|
||||||
option(IMHEX_GENERATE_PDBS "Enable generating PDB files in non-debug builds (Windows only)" OFF)
|
|
||||||
option(IMHEX_REPLACE_DWARF_WITH_PDB "Remove DWARF information from binaries when generating PDBS (Windows only)" OFF)
|
|
||||||
option(IMHEX_ENABLE_STD_ASSERTS "Enable debug asserts in the C++ std library. (Breaks Plugin ABI!)" OFF)
|
|
||||||
option(IMHEX_ENABLE_UNIT_TESTS "Enable building unit tests" ON )
|
|
||||||
option(IMHEX_ENABLE_PLUGIN_TESTS "Enable building plugin tests" ON )
|
|
||||||
option(IMHEX_ENABLE_IMGUI_TEST_ENGINE "Enable the ImGui Test Engine" OFF)
|
|
||||||
option(IMHEX_ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF)
|
option(IMHEX_ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF)
|
||||||
option(IMHEX_COMPRESS_DEBUG_INFO "Compress debug information" ON )
|
|
||||||
option(IMHEX_ENABLE_CXX_MODULES "Enable C++20 Module compilation. Testing only!" OFF)
|
option(IMHEX_ENABLE_CXX_MODULES "Enable C++20 Module compilation. Testing only!" OFF)
|
||||||
option(IMHEX_ENABLE_CPPCHECK "Enable cppcheck static analysis" OFF)
|
option(IMHEX_ENABLE_CPPCHECK "Enable cppcheck static analysis" OFF)
|
||||||
option(IMHEX_BUNDLE_PLUGIN_SDK "Enable bundling of Plugin SDK into install package" ON )
|
option(IMHEX_BUNDLE_PLUGIN_SDK "Enable bundling of Plugin SDK into install package" ON )
|
||||||
|
## Testing
|
||||||
|
option(IMHEX_ENABLE_UNIT_TESTS "Enable building unit tests" ON )
|
||||||
|
option(IMHEX_ENABLE_IMGUI_TEST_ENGINE "Enable the ImGui Test Engine" OFF)
|
||||||
|
option(IMHEX_ENABLE_STD_ASSERTS "Enable debug asserts in the C++ std library. (Breaks Plugin ABI!)" OFF)
|
||||||
|
## Debug info
|
||||||
|
option(IMHEX_COMPRESS_DEBUG_INFO "Compress debug information" ON )
|
||||||
|
option(IMHEX_GENERATE_PDBS "Enable generating PDB files in non-debug builds (Windows only)" OFF)
|
||||||
|
option(IMHEX_REPLACE_DWARF_WITH_PDB "Remove DWARF information from binaries when generating PDBS (Windows only)" OFF)
|
||||||
|
option(IMHEX_STRICT_WARNINGS "Enable most available warnings and treat them as errors" ON )
|
||||||
|
option(IMHEX_DISABLE_STACKTRACE "Disables support for printing stack traces" OFF)
|
||||||
|
## Plugins
|
||||||
|
option(IMHEX_STATIC_LINK_PLUGINS "Statically link all plugins into the main executable" OFF)
|
||||||
|
option(IMHEX_ENABLE_PLUGIN_TESTS "Enable building plugin tests" ON )
|
||||||
|
option(IMHEX_INCLUDE_PLUGINS "Semicolon-separated list of plugins to include in the build (empty = build all)" "" )
|
||||||
|
option(IMHEX_EXCLUDE_PLUGINS "Semicolon-separated list of plugins to exclude from the build" "" )
|
||||||
|
|
||||||
set(IMHEX_BASE_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}")
|
set(IMHEX_BASE_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
set(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules")
|
set(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules")
|
||||||
|
|||||||
@@ -175,15 +175,11 @@ macro(detectOS)
|
|||||||
endif()
|
endif()
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
if(IMHEX_PLUGINS_IN_SHARE)
|
set(PLUGINS_INSTALL_LOCATION "${CMAKE_INSTALL_LIBDIR}/imhex/plugins")
|
||||||
set(PLUGINS_INSTALL_LOCATION "share/imhex/plugins")
|
|
||||||
else()
|
|
||||||
set(PLUGINS_INSTALL_LOCATION "${CMAKE_INSTALL_LIBDIR}/imhex/plugins")
|
|
||||||
|
|
||||||
# Add System plugin location for plugins to be loaded from
|
# Add System plugin location for plugins to be loaded from
|
||||||
# IMPORTANT: This does not work for Sandboxed or portable builds such as the Flatpak or AppImage release
|
# IMPORTANT: This does not work for Sandboxed or portable builds such as the Flatpak or AppImage release
|
||||||
add_compile_definitions(SYSTEM_PLUGINS_LOCATION="${CMAKE_INSTALL_FULL_LIBDIR}/imhex")
|
add_compile_definitions(SYSTEM_PLUGINS_LOCATION="${CMAKE_INSTALL_FULL_LIBDIR}/imhex")
|
||||||
endif()
|
|
||||||
|
|
||||||
else ()
|
else ()
|
||||||
message(FATAL_ERROR "Unknown / unsupported system!")
|
message(FATAL_ERROR "Unknown / unsupported system!")
|
||||||
@@ -205,11 +201,14 @@ macro(configurePackingResources)
|
|||||||
set(CPACK_GENERATOR "WIX")
|
set(CPACK_GENERATOR "WIX")
|
||||||
set(CPACK_PACKAGE_NAME "ImHex")
|
set(CPACK_PACKAGE_NAME "ImHex")
|
||||||
set(CPACK_PACKAGE_VENDOR "WerWolv")
|
set(CPACK_PACKAGE_VENDOR "WerWolv")
|
||||||
|
set(CPACK_WIX_VERSION 4)
|
||||||
set(CPACK_WIX_UPGRADE_GUID "05000E99-9659-42FD-A1CF-05C554B39285")
|
set(CPACK_WIX_UPGRADE_GUID "05000E99-9659-42FD-A1CF-05C554B39285")
|
||||||
set(CPACK_WIX_PRODUCT_ICON "${PROJECT_SOURCE_DIR}/resources/dist/windows/icon.ico")
|
set(CPACK_WIX_PRODUCT_ICON "${PROJECT_SOURCE_DIR}/resources/dist/windows/icon.ico")
|
||||||
set(CPACK_WIX_UI_BANNER "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_banner.png")
|
set(CPACK_WIX_UI_BANNER "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_banner.png")
|
||||||
set(CPACK_WIX_UI_DIALOG "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_dialog.png")
|
set(CPACK_WIX_UI_DIALOG "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_dialog.png")
|
||||||
set(CPACK_WIX_CULTURES "en-US;de-DE;ja-JP;it-IT;pt-BR;zh-CN;zh-TW;ru-RU")
|
set(CPACK_WIX_CULTURES "en-US;de-DE;ja-JP;it-IT;pt-BR;zh-CN;zh-TW;ru-RU")
|
||||||
|
set(CPACK_WIX_PATCH_FILE "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_patch.xml")
|
||||||
|
|
||||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "ImHex")
|
set(CPACK_PACKAGE_INSTALL_DIRECTORY "ImHex")
|
||||||
set_property(INSTALL "$<TARGET_FILE_NAME:main>"
|
set_property(INSTALL "$<TARGET_FILE_NAME:main>"
|
||||||
PROPERTY CPACK_START_MENU_SHORTCUTS "ImHex"
|
PROPERTY CPACK_START_MENU_SHORTCUTS "ImHex"
|
||||||
@@ -312,7 +311,7 @@ macro(createPackage)
|
|||||||
POST_EXCLUDE_REGEXES ".*system32/.*\\.dll"
|
POST_EXCLUDE_REGEXES ".*system32/.*\\.dll"
|
||||||
)
|
)
|
||||||
|
|
||||||
if(_c_deps_FILENAMES AND NOT _c_deps STREQUAL "")
|
if(_c_deps_FILENAMES AND _c_deps AND NOT (_c_deps STREQUAL ""))
|
||||||
message(WARNING "Conflicting dependencies for library: \"${_c_deps}\"!")
|
message(WARNING "Conflicting dependencies for library: \"${_c_deps}\"!")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -560,6 +559,9 @@ function(detectBadClone)
|
|||||||
|
|
||||||
file (GLOB EXTERNAL_DIRS "lib/external/*" "lib/third_party/*")
|
file (GLOB EXTERNAL_DIRS "lib/external/*" "lib/third_party/*")
|
||||||
foreach (EXTERNAL_DIR ${EXTERNAL_DIRS})
|
foreach (EXTERNAL_DIR ${EXTERNAL_DIRS})
|
||||||
|
if(NOT IS_DIRECTORY "${EXTERNAL_DIR}")
|
||||||
|
continue()
|
||||||
|
endif()
|
||||||
file(GLOB_RECURSE RESULT "${EXTERNAL_DIR}/*")
|
file(GLOB_RECURSE RESULT "${EXTERNAL_DIR}/*")
|
||||||
list(LENGTH RESULT ENTRY_COUNT)
|
list(LENGTH RESULT ENTRY_COUNT)
|
||||||
if(ENTRY_COUNT LESS_EQUAL 1)
|
if(ENTRY_COUNT LESS_EQUAL 1)
|
||||||
@@ -587,7 +589,9 @@ endfunction()
|
|||||||
macro(detectBundledPlugins)
|
macro(detectBundledPlugins)
|
||||||
file(GLOB PLUGINS_DIRS "plugins/*")
|
file(GLOB PLUGINS_DIRS "plugins/*")
|
||||||
|
|
||||||
if (NOT DEFINED IMHEX_INCLUDE_PLUGINS)
|
if (IMHEX_INCLUDE_PLUGINS)
|
||||||
|
set(PLUGINS ${IMHEX_INCLUDE_PLUGINS})
|
||||||
|
else()
|
||||||
foreach(PLUGIN_DIR ${PLUGINS_DIRS})
|
foreach(PLUGIN_DIR ${PLUGINS_DIRS})
|
||||||
if (EXISTS "${PLUGIN_DIR}/CMakeLists.txt")
|
if (EXISTS "${PLUGIN_DIR}/CMakeLists.txt")
|
||||||
get_filename_component(PLUGIN_NAME ${PLUGIN_DIR} NAME)
|
get_filename_component(PLUGIN_NAME ${PLUGIN_DIR} NAME)
|
||||||
@@ -596,8 +600,6 @@ macro(detectBundledPlugins)
|
|||||||
endif ()
|
endif ()
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
else()
|
|
||||||
set(PLUGINS ${IMHEX_INCLUDE_PLUGINS})
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
foreach(PLUGIN_NAME ${PLUGINS})
|
foreach(PLUGIN_NAME ${PLUGINS})
|
||||||
@@ -608,9 +610,13 @@ macro(detectBundledPlugins)
|
|||||||
message(FATAL_ERROR "No bundled plugins enabled")
|
message(FATAL_ERROR "No bundled plugins enabled")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT ("builtin" IN_LIST PLUGINS))
|
set(REQUIRED_PLUGINS builtin fonts ui)
|
||||||
message(FATAL_ERROR "The 'builtin' plugin is required for ImHex to work!")
|
foreach(PLUGIN ${REQUIRED_PLUGINS})
|
||||||
endif ()
|
list(FIND PLUGINS ${PLUGIN} PLUGIN_INDEX)
|
||||||
|
if (PLUGIN_INDEX EQUAL -1)
|
||||||
|
message(FATAL_ERROR "Required plugin '${PLUGIN}' is not enabled!")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
macro(setVariableInParent variable value)
|
macro(setVariableInParent variable value)
|
||||||
|
|||||||
4
dist/AppImage/AppImageBuilder.yml
vendored
4
dist/AppImage/AppImageBuilder.yml
vendored
@@ -15,8 +15,8 @@ AppDir:
|
|||||||
- "{{ARCHITECTURE_PACKAGE}}"
|
- "{{ARCHITECTURE_PACKAGE}}"
|
||||||
allow_unauthenticated: true
|
allow_unauthenticated: true
|
||||||
sources:
|
sources:
|
||||||
- sourceline: 'deb [arch=amd64] http://us.archive.ubuntu.com/ubuntu/ noble main restricted universe multiverse'
|
- sourceline: 'deb [arch=amd64] https://us.archive.ubuntu.com/ubuntu/ noble main restricted universe multiverse'
|
||||||
- sourceline: 'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ noble main restricted universe multiverse'
|
- sourceline: 'deb [arch=arm64] https://ports.ubuntu.com/ubuntu-ports/ noble main restricted universe multiverse'
|
||||||
include:
|
include:
|
||||||
- libgdk-pixbuf2.0-0
|
- libgdk-pixbuf2.0-0
|
||||||
- libgdk-pixbuf2.0-common
|
- libgdk-pixbuf2.0-common
|
||||||
|
|||||||
28
dist/AppImage/Dockerfile
vendored
28
dist/AppImage/Dockerfile
vendored
@@ -30,9 +30,9 @@ ARG LTO=ON
|
|||||||
ARG BUILD_TYPE=RelWithDebInfo
|
ARG BUILD_TYPE=RelWithDebInfo
|
||||||
ARG GIT_COMMIT_HASH
|
ARG GIT_COMMIT_HASH
|
||||||
ARG GIT_BRANCH
|
ARG GIT_BRANCH
|
||||||
ARG ARCHITECTURE_PACKAGE
|
ARG ARCHITECTURE_PACKAGE=x86_64
|
||||||
ARG ARCHITECTURE_FILE_NAME
|
ARG ARCHITECTURE_FILE_NAME=amd64
|
||||||
ARG ARCHITECTURE_APPIMAGE_BUILDER
|
ARG ARCHITECTURE_APPIMAGE_BUILDER=x86_64
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
|
|
||||||
# Ubuntu sh doesnt support string substitution
|
# Ubuntu sh doesnt support string substitution
|
||||||
@@ -42,16 +42,18 @@ RUN <<EOF
|
|||||||
# Prepare ImHex build
|
# Prepare ImHex build
|
||||||
set -xe
|
set -xe
|
||||||
|
|
||||||
CC=gcc-14 CXX=g++-14 cmake -G "Ninja" \
|
CC=gcc-14 CXX=g++-14 cmake -G "Ninja" \
|
||||||
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||||
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
||||||
-DIMHEX_COMMIT_HASH_LONG="${GIT_COMMIT_HASH}" \
|
-DIMHEX_COMMIT_HASH_LONG="${GIT_COMMIT_HASH}" \
|
||||||
-DIMHEX_COMMIT_BRANCH="${GIT_BRANCH}" \
|
-DIMHEX_COMMIT_BRANCH="${GIT_BRANCH}" \
|
||||||
-DIMHEX_ENABLE_LTO=${LTO} \
|
-DIMHEX_ENABLE_LTO=${LTO} \
|
||||||
-DIMHEX_PLUGINS_IN_SHARE=ON \
|
-DIMHEX_BUNDLE_PLUGIN_SDK=OFF \
|
||||||
|
`# To prevent using a libdir with an architecture-specific name` \
|
||||||
|
-DCMAKE_INSTALL_LIBDIR="lib" \
|
||||||
/imhex
|
/imhex
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|||||||
2
dist/DEBIAN/control.in
vendored
2
dist/DEBIAN/control.in
vendored
@@ -4,7 +4,7 @@ Section: editors
|
|||||||
Priority: optional
|
Priority: optional
|
||||||
Architecture: amd64
|
Architecture: amd64
|
||||||
License: GNU GPL-2
|
License: GNU GPL-2
|
||||||
Depends: libfontconfig1, libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal, libssh2-1, md4c
|
Depends: libfontconfig1, libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal, libssh2-1, libmd4c0
|
||||||
Maintainer: WerWolv <hey@werwolv.net>
|
Maintainer: WerWolv <hey@werwolv.net>
|
||||||
Description: ImHex Hex Editor
|
Description: ImHex Hex Editor
|
||||||
A Hex Editor for Reverse Engineers, Programmers and
|
A Hex Editor for Reverse Engineers, Programmers and
|
||||||
|
|||||||
1
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_FMT=ON
|
||||||
- -DUSE_SYSTEM_YARA=ON
|
- -DUSE_SYSTEM_YARA=ON
|
||||||
- -DIMHEX_OFFLINE_BUILD=ON
|
- -DIMHEX_OFFLINE_BUILD=ON
|
||||||
|
- -DIMHEX_BUNDLE_PLUGIN_SDK=OFF
|
||||||
- -DCMAKE_INSTALL_LIBDIR=lib
|
- -DCMAKE_INSTALL_LIBDIR=lib
|
||||||
- -DCMAKE_INSTALL_RPATH='$ORIGIN/../lib:$ORIGIN/../lib64'
|
- -DCMAKE_INSTALL_RPATH='$ORIGIN/../lib:$ORIGIN/../lib64'
|
||||||
sources:
|
sources:
|
||||||
|
|||||||
4
dist/macOS/arm64.Dockerfile
vendored
4
dist/macOS/arm64.Dockerfile
vendored
@@ -150,9 +150,7 @@ EOF
|
|||||||
# Build ImHex
|
# Build ImHex
|
||||||
## Copy ImHex
|
## Copy ImHex
|
||||||
COPY --from=imhex / /mnt/ImHex
|
COPY --from=imhex / /mnt/ImHex
|
||||||
## Patch ImHex with hacks
|
## Configure ImHex build
|
||||||
# COPY toolchain.cmake.2 /osxcross/target/toolchain.cmake
|
|
||||||
# Configure ImHex build
|
|
||||||
RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/_deps \
|
RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/_deps \
|
||||||
cd /mnt/ImHex && \
|
cd /mnt/ImHex && \
|
||||||
# compilers
|
# compilers
|
||||||
|
|||||||
1
dist/snap/snapcraft.yaml
vendored
1
dist/snap/snapcraft.yaml
vendored
@@ -41,6 +41,7 @@ parts:
|
|||||||
- -DCMAKE_C_COMPILER_LAUNCHER=${CCACHE}
|
- -DCMAKE_C_COMPILER_LAUNCHER=${CCACHE}
|
||||||
- -DCMAKE_CXX_COMPILER_LAUNCHER=${CCACHE}
|
- -DCMAKE_CXX_COMPILER_LAUNCHER=${CCACHE}
|
||||||
- -DIMHEX_PATTERNS_PULL_MASTER=ON
|
- -DIMHEX_PATTERNS_PULL_MASTER=ON
|
||||||
|
- -DIMHEX_BUNDLE_PLUGIN_SDK=OFF
|
||||||
cmake-generator: Ninja
|
cmake-generator: Ninja
|
||||||
build-packages:
|
build-packages:
|
||||||
- cmake
|
- cmake
|
||||||
|
|||||||
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
|
# Used to invalidate layer cache but not mount cache
|
||||||
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493
|
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493
|
||||||
ARG UNIQUEKEY 1
|
ARG UNIQUEKEY=1
|
||||||
|
|
||||||
RUN apt update
|
RUN apt update
|
||||||
RUN apt install -y git ccache autoconf automake libtool pkg-config ninja-build
|
RUN apt install -y git ccache autoconf automake libtool pkg-config ninja-build
|
||||||
@@ -12,13 +12,13 @@ RUN <<EOF
|
|||||||
# Note: we are a patch on the libmagic port
|
# Note: we are a patch on the libmagic port
|
||||||
set -xe
|
set -xe
|
||||||
|
|
||||||
git clone https://github.com/microsoft/vcpkg /vcpkg
|
git clone --depth 1 https://github.com/microsoft/vcpkg /vcpkg
|
||||||
git -C /vcpkg pull
|
|
||||||
/vcpkg/bootstrap-vcpkg.sh
|
/vcpkg/bootstrap-vcpkg.sh
|
||||||
sed -i 's/vcpkg_install_make(${EXTRA_ARGS})/vcpkg_install_make(${EXTRA_ARGS} SUBPATH src)/g' /vcpkg/ports/libmagic/portfile.cmake
|
sed -i 's/vcpkg_install_make(${EXTRA_ARGS})/vcpkg_install_make(${EXTRA_ARGS} SUBPATH src)/g' /vcpkg/ports/libmagic/portfile.cmake
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Patch vcpkg build instructions to add -pthread
|
# Patch vcpkg build instructions to add -pthread flag
|
||||||
|
# Even dependencies must be built with -pthread to be able to use USE_PTHREADS=1
|
||||||
RUN <<EOF
|
RUN <<EOF
|
||||||
set -xe
|
set -xe
|
||||||
|
|
||||||
@@ -50,6 +50,7 @@ ENV CCACHE_DIR=/cache/ccache
|
|||||||
|
|
||||||
RUN mkdir /build
|
RUN mkdir /build
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
|
ARG BUILD_TYPE=Release
|
||||||
RUN --mount=type=cache,target=/cache \
|
RUN --mount=type=cache,target=/cache \
|
||||||
--mount=type=bind,source=.,target=/imhex <<EOF
|
--mount=type=bind,source=.,target=/imhex <<EOF
|
||||||
|
|
||||||
@@ -70,7 +71,7 @@ ccache -zs
|
|||||||
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
|
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
|
||||||
-DLIBROMFS_COMPRESS_RESOURCES=OFF \
|
-DLIBROMFS_COMPRESS_RESOURCES=OFF \
|
||||||
-DIMHEX_ENABLE_PLUGIN_TESTS=OFF \
|
-DIMHEX_ENABLE_PLUGIN_TESTS=OFF \
|
||||||
-DCMAKE_BUILD_TYPE=Release
|
-DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
||||||
|
|
||||||
ninja -j $JOBS
|
ninja -j $JOBS
|
||||||
|
|
||||||
@@ -106,3 +107,4 @@ COPY --from=build [ \
|
|||||||
|
|
||||||
FROM nginx
|
FROM nginx
|
||||||
COPY --from=raw . /usr/share/nginx/html
|
COPY --from=raw . /usr/share/nginx/html
|
||||||
|
RUN chmod -R 755 /usr/share/nginx/html
|
||||||
|
|||||||
1
dist/web/compose.yml
vendored
1
dist/web/compose.yml
vendored
@@ -1,5 +1,4 @@
|
|||||||
# docker compose -f dist/web/compose.yml up --build
|
# docker compose -f dist/web/compose.yml up --build
|
||||||
version: '3'
|
|
||||||
services:
|
services:
|
||||||
imhex_web:
|
imhex_web:
|
||||||
image: imhex_web:latest
|
image: imhex_web:latest
|
||||||
|
|||||||
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);
|
void addProviderName(const UnlocalizedString &unlocalizedName, const char *icon);
|
||||||
|
|
||||||
using ProviderCreationFunction = std::function<std::unique_ptr<prv::Provider>()>;
|
using ProviderCreationFunction = std::function<std::shared_ptr<prv::Provider>()>;
|
||||||
void add(const std::string &typeName, ProviderCreationFunction creationFunction);
|
void add(const std::string &typeName, ProviderCreationFunction creationFunction);
|
||||||
|
|
||||||
struct Entry {
|
struct Entry {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace hex {
|
|||||||
* This event is responsible for (optionally) initializing the provider and calling EventProviderOpened
|
* This event is responsible for (optionally) initializing the provider and calling EventProviderOpened
|
||||||
* (although the event can also be called manually without problem)
|
* (although the event can also be called manually without problem)
|
||||||
*/
|
*/
|
||||||
EVENT_DEF(EventProviderCreated, prv::Provider *);
|
EVENT_DEF(EventProviderCreated, std::shared_ptr<prv::Provider>);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called as a continuation of EventProviderCreated
|
* @brief Called as a continuation of EventProviderCreated
|
||||||
|
|||||||
@@ -8,7 +8,12 @@ namespace hex {
|
|||||||
/**
|
/**
|
||||||
* @brief Creates a provider from its unlocalized name, and add it to the provider list
|
* @brief Creates a provider from its unlocalized name, and add it to the provider list
|
||||||
*/
|
*/
|
||||||
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, hex::prv::Provider **);
|
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, std::shared_ptr<hex::prv::Provider> *);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Used internally when opening a provider through the API
|
||||||
|
*/
|
||||||
|
EVENT_DEF(RequestOpenProvider, std::shared_ptr<prv::Provider>);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Move the data from all PerProvider instances from one provider to another
|
* @brief Move the data from all PerProvider instances from one provider to another
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ EXPORT_MODULE namespace hex {
|
|||||||
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
|
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
|
||||||
* @param select Whether to select the provider after adding it
|
* @param select Whether to select the provider after adding it
|
||||||
*/
|
*/
|
||||||
void add(std::unique_ptr<prv::Provider> &&provider, bool skipLoadInterface = false, bool select = true);
|
void add(std::shared_ptr<prv::Provider> &&provider, bool skipLoadInterface = false, bool select = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new provider and adds it to the list of providers
|
* @brief Creates a new provider and adds it to the list of providers
|
||||||
@@ -111,12 +111,18 @@ EXPORT_MODULE namespace hex {
|
|||||||
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
|
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
|
||||||
* @param select Whether to select the provider after adding it
|
* @param select Whether to select the provider after adding it
|
||||||
*/
|
*/
|
||||||
prv::Provider* createProvider(
|
std::shared_ptr<prv::Provider> createProvider(
|
||||||
const UnlocalizedString &unlocalizedName,
|
const UnlocalizedString &unlocalizedName,
|
||||||
bool skipLoadInterface = false,
|
bool skipLoadInterface = false,
|
||||||
bool select = true
|
bool select = true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Opens a provider, making its data available to ImHex and handling any error that may occur
|
||||||
|
* @param provider The provider to open
|
||||||
|
*/
|
||||||
|
void openProvider(std::shared_ptr<prv::Provider> provider);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <source_location>
|
#include <source_location>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <hex/trace/exceptions.hpp>
|
||||||
|
|
||||||
EXPORT_MODULE namespace hex {
|
EXPORT_MODULE namespace hex {
|
||||||
|
|
||||||
@@ -94,7 +95,12 @@ EXPORT_MODULE namespace hex {
|
|||||||
std::atomic_flag m_hadException;
|
std::atomic_flag m_hadException;
|
||||||
std::string m_exceptionMessage;
|
std::string m_exceptionMessage;
|
||||||
|
|
||||||
struct TaskInterruptor { virtual ~TaskInterruptor() = default; };
|
struct TaskInterruptor {
|
||||||
|
TaskInterruptor() {
|
||||||
|
trace::disableExceptionCaptureForCurrentThread();
|
||||||
|
}
|
||||||
|
virtual ~TaskInterruptor() = default;
|
||||||
|
};
|
||||||
|
|
||||||
friend class TaskHolder;
|
friend class TaskHolder;
|
||||||
friend class TaskManager;
|
friend class TaskManager;
|
||||||
|
|||||||
@@ -14,6 +14,10 @@
|
|||||||
static_assert(false, "Debug variables are only intended for use during development.");
|
static_assert(false, "Debug variables are only intended for use during development.");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace hex::trace {
|
||||||
|
struct StackTraceResult;
|
||||||
|
}
|
||||||
|
|
||||||
namespace hex::dbg {
|
namespace hex::dbg {
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
@@ -47,4 +51,6 @@ namespace hex::dbg {
|
|||||||
bool debugModeEnabled();
|
bool debugModeEnabled();
|
||||||
void setDebugModeEnabled(bool enabled);
|
void setDebugModeEnabled(bool enabled);
|
||||||
|
|
||||||
|
void printStackTrace(const trace::StackTraceResult &stackTrace);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -98,6 +98,7 @@ namespace hex {
|
|||||||
|
|
||||||
void startProgram(const std::vector<std::string> &command);
|
void startProgram(const std::vector<std::string> &command);
|
||||||
int executeCommand(const std::string &command);
|
int executeCommand(const std::string &command);
|
||||||
|
std::optional<std::string> executeCommandWithOutput(const std::string &command);
|
||||||
void openWebpage(std::string url);
|
void openWebpage(std::string url);
|
||||||
|
|
||||||
extern "C" void registerFont(const char *fontName, const char *fontPath);
|
extern "C" void registerFont(const char *fontName, const char *fontPath);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace hex::prv {
|
|||||||
CachedProvider(size_t cacheBlockSize = 4096, size_t maxBlocks = 1024);
|
CachedProvider(size_t cacheBlockSize = 4096, size_t maxBlocks = 1024);
|
||||||
~CachedProvider() override;
|
~CachedProvider() override;
|
||||||
|
|
||||||
bool open() override;
|
OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace hex::prv {
|
|||||||
[[nodiscard]] bool isSavable() const override { return m_name.empty(); }
|
[[nodiscard]] bool isSavable() const override { return m_name.empty(); }
|
||||||
[[nodiscard]] bool isSavableAsRecent() const override { return false; }
|
[[nodiscard]] bool isSavableAsRecent() const override { return false; }
|
||||||
|
|
||||||
[[nodiscard]] bool open() override;
|
[[nodiscard]] OpenResult open() override;
|
||||||
void close() override { }
|
void close() override { }
|
||||||
|
|
||||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||||
|
|||||||
@@ -79,6 +79,65 @@ namespace hex::prv {
|
|||||||
public:
|
public:
|
||||||
constexpr static u64 MaxPageSize = 0xFFFF'FFFF'FFFF'FFFF;
|
constexpr static u64 MaxPageSize = 0xFFFF'FFFF'FFFF'FFFF;
|
||||||
|
|
||||||
|
class OpenResult {
|
||||||
|
public:
|
||||||
|
OpenResult() : m_result(std::monostate{}) {}
|
||||||
|
|
||||||
|
[[nodiscard]] static OpenResult failure(std::string errorMessage) {
|
||||||
|
OpenResult result;
|
||||||
|
result.m_result = std::move(errorMessage);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static OpenResult warning(std::string warningMessage) {
|
||||||
|
OpenResult result;
|
||||||
|
result.m_result = std::move(warningMessage);
|
||||||
|
result.m_warning = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static OpenResult redirect(Provider *provider) {
|
||||||
|
OpenResult result;
|
||||||
|
result.m_result = provider;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool isSuccess() const {
|
||||||
|
return std::holds_alternative<std::monostate>(m_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool isFailure() const {
|
||||||
|
return std::holds_alternative<std::string>(m_result) && !m_warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool isWarning() const {
|
||||||
|
return std::holds_alternative<std::string>(m_result) && m_warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool isRedirecting() const {
|
||||||
|
return std::holds_alternative<Provider*>(m_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Provider* getRedirectProvider() const {
|
||||||
|
if (std::holds_alternative<Provider*>(m_result)) {
|
||||||
|
return std::get<Provider*>(m_result);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::string_view getErrorMessage() const {
|
||||||
|
if (std::holds_alternative<std::string>(m_result)) {
|
||||||
|
return std::get<std::string>(m_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::variant<std::monostate, std::string, Provider*> m_result;
|
||||||
|
bool m_warning = false;
|
||||||
|
};
|
||||||
|
|
||||||
Provider();
|
Provider();
|
||||||
virtual ~Provider();
|
virtual ~Provider();
|
||||||
Provider(const Provider&) = delete;
|
Provider(const Provider&) = delete;
|
||||||
@@ -94,7 +153,7 @@ namespace hex::prv {
|
|||||||
* @note This is not related to the EventProviderOpened event
|
* @note This is not related to the EventProviderOpened event
|
||||||
* @return true if the provider was opened successfully, else false
|
* @return true if the provider was opened successfully, else false
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] virtual bool open() = 0;
|
[[nodiscard]] virtual OpenResult open() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Closes this provider
|
* @brief Closes this provider
|
||||||
@@ -262,9 +321,6 @@ namespace hex::prv {
|
|||||||
void skipLoadInterface() { m_skipLoadInterface = true; }
|
void skipLoadInterface() { m_skipLoadInterface = true; }
|
||||||
[[nodiscard]] bool shouldSkipLoadInterface() const { return m_skipLoadInterface; }
|
[[nodiscard]] bool shouldSkipLoadInterface() const { return m_skipLoadInterface; }
|
||||||
|
|
||||||
void setErrorMessage(const std::string &errorMessage) { m_errorMessage = errorMessage; }
|
|
||||||
[[nodiscard]] const std::string& getErrorMessage() const { return m_errorMessage; }
|
|
||||||
|
|
||||||
template<std::derived_from<undo::Operation> T>
|
template<std::derived_from<undo::Operation> T>
|
||||||
bool addUndoableOperation(auto && ... args) {
|
bool addUndoableOperation(auto && ... args) {
|
||||||
return m_undoRedoStack.add<T>(std::forward<decltype(args)...>(args)...);
|
return m_undoRedoStack.add<T>(std::forward<decltype(args)...>(args)...);
|
||||||
@@ -296,8 +352,6 @@ namespace hex::prv {
|
|||||||
*/
|
*/
|
||||||
bool m_skipLoadInterface = false;
|
bool m_skipLoadInterface = false;
|
||||||
|
|
||||||
std::string m_errorMessage = "Unspecified error";
|
|
||||||
|
|
||||||
u64 m_pageSize = MaxPageSize;
|
u64 m_pageSize = MaxPageSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ namespace hex::test {
|
|||||||
|
|
||||||
[[nodiscard]] UnlocalizedString getTypeName() const override { return "hex.test.provider.test"; }
|
[[nodiscard]] UnlocalizedString getTypeName() const override { return "hex.test.provider.test"; }
|
||||||
|
|
||||||
bool open() override { return true; }
|
OpenResult open() override { return {}; }
|
||||||
void close() override { }
|
void close() override { }
|
||||||
|
|
||||||
nlohmann::json storeSettings(nlohmann::json) const override { return {}; }
|
nlohmann::json storeSettings(nlohmann::json) const override { return {}; }
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <hex/api/tutorial_manager.hpp>
|
|
||||||
|
|
||||||
namespace hex {
|
namespace hex {
|
||||||
|
|
||||||
@@ -27,7 +26,7 @@ namespace hex {
|
|||||||
* @brief Draws the view
|
* @brief Draws the view
|
||||||
* @note Do not override this method. Override drawContent() instead
|
* @note Do not override this method. Override drawContent() instead
|
||||||
*/
|
*/
|
||||||
virtual void draw() = 0;
|
virtual void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Draws the content of the view
|
* @brief Draws the content of the view
|
||||||
@@ -126,6 +125,7 @@ namespace hex {
|
|||||||
class Window;
|
class Window;
|
||||||
class Special;
|
class Special;
|
||||||
class Floating;
|
class Floating;
|
||||||
|
class Scrolling;
|
||||||
class Modal;
|
class Modal;
|
||||||
class FullScreen;
|
class FullScreen;
|
||||||
|
|
||||||
@@ -153,16 +153,10 @@ namespace hex {
|
|||||||
*/
|
*/
|
||||||
virtual void drawHelpText() = 0;
|
virtual void drawHelpText() = 0;
|
||||||
|
|
||||||
void draw() final {
|
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) override;
|
||||||
if (this->shouldDraw()) {
|
|
||||||
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
virtual bool allowScroll() const {
|
||||||
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
|
return false;
|
||||||
if (ImGui::Begin(title.c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse | this->getWindowFlags())) {
|
|
||||||
TutorialManager::setLastItemInteractiveHelpPopup([this]{ this->drawHelpText(); });
|
|
||||||
this->drawContent();
|
|
||||||
}
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -174,12 +168,7 @@ namespace hex {
|
|||||||
public:
|
public:
|
||||||
explicit Special(UnlocalizedString unlocalizedName) : View(std::move(unlocalizedName), "") {}
|
explicit Special(UnlocalizedString unlocalizedName) : View(std::move(unlocalizedName), "") {}
|
||||||
|
|
||||||
void draw() final {
|
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||||
if (this->shouldDraw()) {
|
|
||||||
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
|
||||||
this->drawContent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -189,7 +178,24 @@ namespace hex {
|
|||||||
public:
|
public:
|
||||||
explicit Floating(UnlocalizedString unlocalizedName, const char *icon) : Window(std::move(unlocalizedName), icon) {}
|
explicit Floating(UnlocalizedString unlocalizedName, const char *icon) : Window(std::move(unlocalizedName), icon) {}
|
||||||
|
|
||||||
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override { return ImGuiWindowFlags_NoDocking; }
|
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||||
|
|
||||||
|
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A view that draws all its content at once without any scrolling being done by the window itself
|
||||||
|
*/
|
||||||
|
class View::Scrolling : public View::Window {
|
||||||
|
public:
|
||||||
|
explicit Scrolling(UnlocalizedString unlocalizedName, const char *icon) : Window(std::move(unlocalizedName), icon) {}
|
||||||
|
|
||||||
|
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||||
|
|
||||||
|
bool allowScroll() const final {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
|
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -200,24 +206,7 @@ namespace hex {
|
|||||||
public:
|
public:
|
||||||
explicit Modal(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon) {}
|
explicit Modal(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon) {}
|
||||||
|
|
||||||
void draw() final {
|
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||||
if (this->shouldDraw()) {
|
|
||||||
if (this->getWindowOpenState())
|
|
||||||
ImGui::OpenPopup(View::toWindowName(this->getUnlocalizedName()).c_str());
|
|
||||||
|
|
||||||
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
|
|
||||||
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
|
||||||
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
|
|
||||||
if (ImGui::BeginPopupModal(title.c_str(), this->hasCloseButton() ? &this->getWindowOpenState() : nullptr, ImGuiWindowFlags_NoCollapse | this->getWindowFlags())) {
|
|
||||||
this->drawContent();
|
|
||||||
|
|
||||||
ImGui::EndPopup();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::IsKeyPressed(ImGuiKey_Escape))
|
|
||||||
this->getWindowOpenState() = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] virtual bool hasCloseButton() const { return true; }
|
[[nodiscard]] virtual bool hasCloseButton() const { return true; }
|
||||||
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
|
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
|
||||||
@@ -227,10 +216,7 @@ namespace hex {
|
|||||||
public:
|
public:
|
||||||
explicit FullScreen() : View("FullScreen", "") {}
|
explicit FullScreen() : View("FullScreen", "") {}
|
||||||
|
|
||||||
void draw() final {
|
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||||
this->drawContent();
|
|
||||||
this->drawAlwaysVisibleContent();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1101,13 +1101,13 @@ namespace hex {
|
|||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
void add(const std::string &typeName, ProviderCreationFunction creationFunction) {
|
void add(const std::string &typeName, ProviderCreationFunction creationFunction) {
|
||||||
(void)RequestCreateProvider::subscribe([expectedName = typeName, creationFunction](const std::string &name, bool skipLoadInterface, bool selectProvider, prv::Provider **provider) {
|
(void)RequestCreateProvider::subscribe([expectedName = typeName, creationFunction](const std::string &name, bool skipLoadInterface, bool selectProvider, std::shared_ptr<prv::Provider> *provider) {
|
||||||
if (name != expectedName) return;
|
if (name != expectedName) return;
|
||||||
|
|
||||||
auto newProvider = creationFunction();
|
auto newProvider = creationFunction();
|
||||||
|
|
||||||
if (provider != nullptr) {
|
if (provider != nullptr) {
|
||||||
*provider = newProvider.get();
|
*provider = newProvider;
|
||||||
ImHexApi::Provider::add(std::move(newProvider), skipLoadInterface, selectProvider);
|
ImHexApi::Provider::add(std::move(newProvider), skipLoadInterface, selectProvider);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -294,8 +294,8 @@ namespace hex {
|
|||||||
namespace ImHexApi::Provider {
|
namespace ImHexApi::Provider {
|
||||||
|
|
||||||
static i64 s_currentProvider = -1;
|
static i64 s_currentProvider = -1;
|
||||||
static AutoReset<std::vector<std::unique_ptr<prv::Provider>>> s_providers;
|
static AutoReset<std::vector<std::shared_ptr<prv::Provider>>> s_providers;
|
||||||
static AutoReset<std::map<prv::Provider*, std::unique_ptr<prv::Provider>>> s_providersToRemove;
|
static AutoReset<std::map<prv::Provider*, std::shared_ptr<prv::Provider>>> s_providersToRemove;
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
@@ -382,7 +382,7 @@ namespace hex {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(std::unique_ptr<prv::Provider> &&provider, bool skipLoadInterface, bool select) {
|
void add(std::shared_ptr<prv::Provider> &&provider, bool skipLoadInterface, bool select) {
|
||||||
std::scoped_lock lock(impl::s_providerMutex);
|
std::scoped_lock lock(impl::s_providerMutex);
|
||||||
|
|
||||||
if (TaskManager::getRunningTaskCount() > 0)
|
if (TaskManager::getRunningTaskCount() > 0)
|
||||||
@@ -391,7 +391,7 @@ namespace hex {
|
|||||||
if (skipLoadInterface)
|
if (skipLoadInterface)
|
||||||
provider->skipLoadInterface();
|
provider->skipLoadInterface();
|
||||||
|
|
||||||
EventProviderCreated::post(provider.get());
|
EventProviderCreated::post(provider);
|
||||||
s_providers->emplace_back(std::move(provider));
|
s_providers->emplace_back(std::move(provider));
|
||||||
|
|
||||||
if (select || s_providers->size() == 1)
|
if (select || s_providers->size() == 1)
|
||||||
@@ -491,13 +491,17 @@ namespace hex {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
prv::Provider* createProvider(const UnlocalizedString &unlocalizedName, bool skipLoadInterface, bool select) {
|
std::shared_ptr<prv::Provider> createProvider(const UnlocalizedString &unlocalizedName, bool skipLoadInterface, bool select) {
|
||||||
prv::Provider* result = nullptr;
|
std::shared_ptr<prv::Provider> result = nullptr;
|
||||||
RequestCreateProvider::post(unlocalizedName, skipLoadInterface, select, &result);
|
RequestCreateProvider::post(unlocalizedName, skipLoadInterface, select, &result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void openProvider(std::shared_ptr<prv::Provider> provider) {
|
||||||
|
RequestOpenProvider::post(provider);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ImHexApi::System {
|
namespace ImHexApi::System {
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
#include <jthread.hpp>
|
#include <jthread.hpp>
|
||||||
|
#include <hex/helpers/debugging.hpp>
|
||||||
|
#include <hex/trace/exceptions.hpp>
|
||||||
|
|
||||||
#if defined(OS_WINDOWS)
|
#if defined(OS_WINDOWS)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@@ -310,6 +312,8 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
trace::enableExceptionCaptureForCurrentThread();
|
||||||
|
|
||||||
// Set the thread name to the name of the task
|
// Set the thread name to the name of the task
|
||||||
TaskManager::setCurrentThreadName(Lang(task->m_unlocalizedName));
|
TaskManager::setCurrentThreadName(Lang(task->m_unlocalizedName));
|
||||||
|
|
||||||
@@ -323,15 +327,21 @@ namespace hex {
|
|||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
log::error("Exception in task '{}': {}", task->m_unlocalizedName.get(), e.what());
|
log::error("Exception in task '{}': {}", task->m_unlocalizedName.get(), e.what());
|
||||||
|
|
||||||
|
dbg::printStackTrace(trace::getStackTrace());
|
||||||
|
|
||||||
// Handle the task throwing an uncaught exception
|
// Handle the task throwing an uncaught exception
|
||||||
task->exception(e.what());
|
task->exception(e.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
log::error("Exception in task '{}'", task->m_unlocalizedName.get());
|
log::error("Exception in task '{}'", task->m_unlocalizedName.get());
|
||||||
|
|
||||||
|
dbg::printStackTrace(trace::getStackTrace());
|
||||||
|
|
||||||
// Handle the task throwing an uncaught exception of unknown type
|
// Handle the task throwing an uncaught exception of unknown type
|
||||||
task->exception("Unknown Exception");
|
task->exception("Unknown Exception");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace::disableExceptionCaptureForCurrentThread();
|
||||||
|
|
||||||
s_currentTask = nullptr;
|
s_currentTask = nullptr;
|
||||||
task->finish();
|
task->finish();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
#include <hex/helpers/debugging.hpp>
|
#include <hex/helpers/debugging.hpp>
|
||||||
|
#include <hex/helpers/logger.hpp>
|
||||||
|
#include <hex/trace/stacktrace.hpp>
|
||||||
|
|
||||||
namespace hex::dbg {
|
namespace hex::dbg {
|
||||||
|
|
||||||
@@ -21,4 +23,23 @@ namespace hex::dbg {
|
|||||||
s_debugMode = enabled;
|
s_debugMode = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[noreturn]] void assertionHandler(const char* file, int line, const char *function, const char* exprString) {
|
||||||
|
log::error("Assertion failed: {} at {}:{} => {}", exprString, file, line, function);
|
||||||
|
|
||||||
|
const auto stackTrace = trace::getStackTrace();
|
||||||
|
dbg::printStackTrace(stackTrace);
|
||||||
|
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void printStackTrace(const trace::StackTraceResult &stackTrace) {
|
||||||
|
log::fatal("Printing stacktrace using implementation '{}'", stackTrace.implementationName);
|
||||||
|
for (const auto &stackFrame : stackTrace.stackFrames) {
|
||||||
|
if (stackFrame.line == 0)
|
||||||
|
log::fatal(" ({}) | {}", stackFrame.file, stackFrame.function);
|
||||||
|
else
|
||||||
|
log::fatal(" ({}:{}) | {}", stackFrame.file, stackFrame.line, stackFrame.function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -97,6 +97,13 @@ namespace hex::paths {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::fs::path> getPluginPaths() {
|
static std::vector<std::fs::path> getPluginPaths() {
|
||||||
|
// If running from an AppImage, only allow loaded plugins from inside it
|
||||||
|
#if defined(OS_LINUX)
|
||||||
|
if(const char* appdir = std::getenv("APPDIR")) { // check for AppImage environment
|
||||||
|
return {std::string(appdir) + "/usr/lib/imhex"};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
std::vector<std::fs::path> paths = getDataPaths(true);
|
std::vector<std::fs::path> paths = getDataPaths(true);
|
||||||
|
|
||||||
// Add the system plugin directory to the path if one was provided at compile time
|
// Add the system plugin directory to the path if one was provided at compile time
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <fmt/chrono.h>
|
#include <fmt/chrono.h>
|
||||||
|
#include <hex/helpers/debugging.hpp>
|
||||||
|
|
||||||
#if defined(OS_WINDOWS)
|
#if defined(OS_WINDOWS)
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
@@ -149,14 +150,6 @@ namespace hex::log {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void assertionHandler(const char* exprString, const char* file, int line) {
|
|
||||||
log::error("Assertion failed: {} at {}:{}", exprString, file, line);
|
|
||||||
|
|
||||||
#if defined (DEBUG)
|
|
||||||
std::abort();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace color {
|
namespace color {
|
||||||
|
|
||||||
fmt::color debug() { return fmt::color::medium_sea_green; }
|
fmt::color debug() { return fmt::color::medium_sea_green; }
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace hex {
|
|||||||
[[nodiscard]] bool isSavable() const override { return false; }
|
[[nodiscard]] bool isSavable() const override { return false; }
|
||||||
[[nodiscard]] bool isSavableAsRecent() const override { return false; }
|
[[nodiscard]] bool isSavableAsRecent() const override { return false; }
|
||||||
|
|
||||||
[[nodiscard]] bool open() override { return true; }
|
[[nodiscard]] OpenResult open() override { return {}; }
|
||||||
void close() override { }
|
void close() override { }
|
||||||
|
|
||||||
void readRaw(u64 offset, void *buffer, size_t size) override {
|
void readRaw(u64 offset, void *buffer, size_t size) override {
|
||||||
|
|||||||
@@ -309,6 +309,50 @@ namespace hex {
|
|||||||
return ::system(command.c_str());
|
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) {
|
void openWebpage(std::string url) {
|
||||||
if (!url.contains("://"))
|
if (!url.contains("://"))
|
||||||
url = "https://" + url;
|
url = "https://" + url;
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ namespace hex::prv {
|
|||||||
clearCache();
|
clearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CachedProvider::open() {
|
Provider::OpenResult CachedProvider::open() {
|
||||||
clearCache();
|
clearCache();
|
||||||
return true;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void CachedProvider::close() {
|
void CachedProvider::close() {
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
|
|
||||||
namespace hex::prv {
|
namespace hex::prv {
|
||||||
|
|
||||||
bool MemoryProvider::open() {
|
Provider::OpenResult MemoryProvider::open() {
|
||||||
if (m_data.empty()) {
|
if (m_data.empty()) {
|
||||||
m_data.resize(1);
|
m_data.resize(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
void MemoryProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
#include <hex/ui/view.hpp>
|
#include <hex/ui/view.hpp>
|
||||||
#include <hex/api/task_manager.hpp>
|
|
||||||
#include <hex/helpers/auto_reset.hpp>
|
#include <hex/helpers/auto_reset.hpp>
|
||||||
|
|
||||||
#include <hex/api/imhex_api/provider.hpp>
|
#include <hex/api/imhex_api/provider.hpp>
|
||||||
|
#include <hex/api/task_manager.hpp>
|
||||||
|
#include <hex/api/tutorial_manager.hpp>
|
||||||
|
|
||||||
#include <hex/providers/provider.hpp>
|
#include <hex/providers/provider.hpp>
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
@@ -116,4 +118,63 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void View::Window::draw(ImGuiWindowFlags extraFlags) {
|
||||||
|
if (this->shouldDraw()) {
|
||||||
|
if (!allowScroll())
|
||||||
|
extraFlags |= ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
|
||||||
|
|
||||||
|
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
||||||
|
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
|
||||||
|
if (ImGui::Begin(title.c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse | extraFlags | this->getWindowFlags())) {
|
||||||
|
TutorialManager::setLastItemInteractiveHelpPopup([this]{ this->drawHelpText(); });
|
||||||
|
this->drawContent();
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::Special::draw(ImGuiWindowFlags extraFlags) {
|
||||||
|
std::ignore = extraFlags;
|
||||||
|
|
||||||
|
if (this->shouldDraw()) {
|
||||||
|
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
||||||
|
this->drawContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::Floating::draw(ImGuiWindowFlags extraFlags) {
|
||||||
|
Window::draw(extraFlags | ImGuiWindowFlags_NoDocking);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::Scrolling::draw(ImGuiWindowFlags extraFlags) {
|
||||||
|
Window::draw(extraFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::Modal::draw(ImGuiWindowFlags extraFlags) {
|
||||||
|
if (this->shouldDraw()) {
|
||||||
|
if (this->getWindowOpenState())
|
||||||
|
ImGui::OpenPopup(View::toWindowName(this->getUnlocalizedName()).c_str());
|
||||||
|
|
||||||
|
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
|
||||||
|
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
||||||
|
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
|
||||||
|
if (ImGui::BeginPopupModal(title.c_str(), this->hasCloseButton() ? &this->getWindowOpenState() : nullptr, ImGuiWindowFlags_NoCollapse | extraFlags | this->getWindowFlags())) {
|
||||||
|
this->drawContent();
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::IsKeyPressed(ImGuiKey_Escape))
|
||||||
|
this->getWindowOpenState() = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::FullScreen::draw(ImGuiWindowFlags extraFlags) {
|
||||||
|
std::ignore = extraFlags;
|
||||||
|
|
||||||
|
this->drawContent();
|
||||||
|
this->drawAlwaysVisibleContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
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.
|
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
|
||||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||||
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||||
namespace hex::log::impl {
|
namespace hex::dbg {
|
||||||
void assertionHandler(const char* expr_str, const char* file, int line);
|
[[noreturn]] void assertionHandler(const char* file, int line, const char *function, const char* exprString);
|
||||||
}
|
}
|
||||||
#define IM_ASSERT(_EXPR) do { if (!(_EXPR)) [[unlikely]] { hex::log::impl::assertionHandler(#_EXPR, __FILE__, __LINE__); } } while(0)
|
|
||||||
|
#if defined(__PRETTY_FUNCTION__)
|
||||||
|
#define IM_ASSERT(_EXPR) do { if (!(_EXPR)) [[unlikely]] { hex::dbg::assertionHandler(__FILE__, __LINE__, __PRETTY_FUNCTION__, #_EXPR); } } while(0)
|
||||||
|
#elif defined(__FUNCSIG__)
|
||||||
|
#define IM_ASSERT(_EXPR) do { if (!(_EXPR)) [[unlikely]] { hex::dbg::assertionHandler(__FILE__, __LINE__, __FUNCSIG__, #_EXPR); } } while(0)
|
||||||
|
#else
|
||||||
|
#define IM_ASSERT(_EXPR) do { if (!(_EXPR)) [[unlikely]] { hex::dbg::assertionHandler(__FILE__, __LINE__, __FUNCTION__, #_EXPR); } } while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
||||||
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
||||||
|
|||||||
@@ -81,6 +81,9 @@ if (IMHEX_TRACE_EXCEPTIONS)
|
|||||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||||
target_link_options(tracing ${LIBIMHEX_LIBRARY_TYPE_PUBLIC} "-Wl,--wrap=__cxa_throw")
|
target_link_options(tracing ${LIBIMHEX_LIBRARY_TYPE_PUBLIC} "-Wl,--wrap=__cxa_throw")
|
||||||
target_compile_definitions(tracing ${LIBIMHEX_LIBRARY_TYPE_PRIVATE} HEX_WRAP_CXA_THROW)
|
target_compile_definitions(tracing ${LIBIMHEX_LIBRARY_TYPE_PRIVATE} HEX_WRAP_CXA_THROW)
|
||||||
|
|
||||||
|
target_link_options(tracing ${LIBIMHEX_LIBRARY_TYPE_PUBLIC} "-Wl,--wrap=_ZSt21__glibcxx_assert_failPKciS0_S0_")
|
||||||
|
target_compile_definitions(tracing ${LIBIMHEX_LIBRARY_TYPE_PRIVATE} HEX_WRAP_GLIBCXX_ASSERT_FAIL)
|
||||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
# Not supported currently
|
# Not supported currently
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -6,7 +6,12 @@
|
|||||||
|
|
||||||
namespace hex::trace {
|
namespace hex::trace {
|
||||||
|
|
||||||
|
using AssertionHandler = void(*)(const char* file, int line, const char *function, const char* exprString);
|
||||||
|
|
||||||
std::optional<StackTraceResult> getLastExceptionStackTrace();
|
std::optional<StackTraceResult> getLastExceptionStackTrace();
|
||||||
|
void setAssertionHandler(AssertionHandler handler);
|
||||||
|
|
||||||
void enableExceptionCaptureForCurrentThread();
|
void enableExceptionCaptureForCurrentThread();
|
||||||
|
void disableExceptionCaptureForCurrentThread();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
namespace hex::trace {
|
namespace hex::trace {
|
||||||
|
|
||||||
static std::optional<StackTraceResult> s_lastExceptionStackTrace;
|
static thread_local std::optional<StackTraceResult> s_lastExceptionStackTrace;
|
||||||
static thread_local bool s_threadExceptionCaptureEnabled = false;
|
static thread_local bool s_threadExceptionCaptureEnabled = false;
|
||||||
|
static AssertionHandler s_assertionHandler = nullptr;
|
||||||
|
|
||||||
std::optional<StackTraceResult> getLastExceptionStackTrace() {
|
std::optional<StackTraceResult> getLastExceptionStackTrace() {
|
||||||
if (!s_lastExceptionStackTrace.has_value())
|
if (!s_lastExceptionStackTrace.has_value())
|
||||||
@@ -15,18 +16,26 @@ namespace hex::trace {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setAssertionHandler(AssertionHandler handler) {
|
||||||
|
s_assertionHandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
void enableExceptionCaptureForCurrentThread() {
|
void enableExceptionCaptureForCurrentThread() {
|
||||||
s_threadExceptionCaptureEnabled = true;
|
s_threadExceptionCaptureEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void disableExceptionCaptureForCurrentThread() {
|
||||||
|
s_threadExceptionCaptureEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HEX_WRAP_CXA_THROW)
|
#if defined(HEX_WRAP_CXA_THROW)
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
[[noreturn]] void __real___cxa_throw(void* thrownException, void* type, void (*destructor)(void*));
|
[[noreturn]] void __real___cxa_throw(void* thrownException, std::type_info* type, void (*destructor)(void*));
|
||||||
[[noreturn]] void __wrap___cxa_throw(void* thrownException, void* type, void (*destructor)(void*)) {
|
[[noreturn]] void __wrap___cxa_throw(void* thrownException, std::type_info* type, void (*destructor)(void*)) {
|
||||||
if (hex::trace::s_threadExceptionCaptureEnabled)
|
if (hex::trace::s_threadExceptionCaptureEnabled)
|
||||||
hex::trace::s_lastExceptionStackTrace = hex::trace::getStackTrace();
|
hex::trace::s_lastExceptionStackTrace = hex::trace::getStackTrace();
|
||||||
|
|
||||||
@@ -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
|
#endif
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
#include <hex/helpers/debugging.hpp>
|
||||||
#include <hex/helpers/utils.hpp>
|
#include <hex/helpers/utils.hpp>
|
||||||
|
|
||||||
#if defined(IMGUI_TEST_ENGINE)
|
#if defined(IMGUI_TEST_ENGINE)
|
||||||
@@ -71,23 +72,12 @@ namespace hex::crash {
|
|||||||
log::warn("Could not write crash.json file!");
|
log::warn("Could not write crash.json file!");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void printStackTrace() {
|
|
||||||
auto stackTraceResult = trace::getStackTrace();
|
|
||||||
log::fatal("Printing stacktrace using implementation '{}'", stackTraceResult.implementationName);
|
|
||||||
for (const auto &stackFrame : stackTraceResult.stackFrames) {
|
|
||||||
if (stackFrame.line == 0)
|
|
||||||
log::fatal(" ({}) | {}", stackFrame.file, stackFrame.function);
|
|
||||||
else
|
|
||||||
log::fatal(" ({}:{}) | {}", stackFrame.file, stackFrame.line, stackFrame.function);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void callCrashHandlers(const std::string &msg) {
|
static void callCrashHandlers(const std::string &msg) {
|
||||||
// Call the crash callback
|
// Call the crash callback
|
||||||
crashCallback(msg);
|
crashCallback(msg);
|
||||||
|
|
||||||
// Print the stacktrace to the console or log file
|
// Print the stacktrace to the console or log file
|
||||||
printStackTrace();
|
dbg::printStackTrace(trace::getStackTrace());
|
||||||
|
|
||||||
// Flush all streams
|
// Flush all streams
|
||||||
std::fflush(stdout);
|
std::fflush(stdout);
|
||||||
@@ -188,6 +178,7 @@ namespace hex::crash {
|
|||||||
// Setup functions to handle signals, uncaught exception, or similar stuff that will crash ImHex
|
// Setup functions to handle signals, uncaught exception, or similar stuff that will crash ImHex
|
||||||
void setupCrashHandlers() {
|
void setupCrashHandlers() {
|
||||||
trace::initialize();
|
trace::initialize();
|
||||||
|
trace::setAssertionHandler(dbg::assertionHandler);
|
||||||
|
|
||||||
// Register signal handlers
|
// Register signal handlers
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -102,12 +102,12 @@ std::optional<std::fs::path> downloadUpdate(const std::string &url) {
|
|||||||
return filePath;
|
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
|
#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
|
#define ARCH_DEPENDENT(x86_64, arm64) arm64
|
||||||
#else
|
#else
|
||||||
#define ARCH_DEPENDENT(x86_64, arm64) ""
|
#error "Unsupported architecture for updater"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string_view getUpdateArtifactEnding() {
|
std::string_view getUpdateArtifactEnding() {
|
||||||
@@ -134,6 +134,8 @@ std::string_view getUpdateArtifactEnding() {
|
|||||||
return ARCH_DEPENDENT("Fedora-41-x86_64.rpm", "");
|
return ARCH_DEPENDENT("Fedora-41-x86_64.rpm", "");
|
||||||
else if (hex::executeCommand("grep -q 'VERSION_ID=\"42\"' /etc/os-release") == 0)
|
else if (hex::executeCommand("grep -q 'VERSION_ID=\"42\"' /etc/os-release") == 0)
|
||||||
return ARCH_DEPENDENT("Fedora-42-x86_64.rpm", "");
|
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)
|
else if (hex::executeCommand("grep -q 'VERSION_ID=\"rawhide\"' /etc/os-release") == 0)
|
||||||
return ARCH_DEPENDENT("Fedora-rawhide-x86_64.rpm", "");
|
return ARCH_DEPENDENT("Fedora-rawhide-x86_64.rpm", "");
|
||||||
} else if (hex::executeCommand("grep -q '^NAME=\"Arch Linux\"' /etc/os-release") == 0) {
|
} else if (hex::executeCommand("grep -q '^NAME=\"Arch Linux\"' /etc/os-release") == 0) {
|
||||||
@@ -144,33 +146,103 @@ std::string_view getUpdateArtifactEnding() {
|
|||||||
return "";
|
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) {
|
bool installUpdate(const std::fs::path &updatePath) {
|
||||||
|
using UpdaterFunction = std::function<bool(const std::fs::path &updatePath)>;
|
||||||
struct UpdateHandler {
|
struct UpdateHandler {
|
||||||
std::string ending;
|
std::string ending;
|
||||||
std::string command;
|
UpdaterFunction func;
|
||||||
};
|
};
|
||||||
|
|
||||||
const static auto UpdateHandlers = {
|
const static auto UpdateHandlers = {
|
||||||
UpdateHandler { ".msi", "msiexec /i \"{}\" /qb" },
|
UpdateHandler { .ending=".msi", .func=updateCommand("msiexec /i \"{}\" /qb") },
|
||||||
UpdateHandler { ".dmg", "hdiutil attach -autoopen \"{}\"" },
|
UpdateHandler { .ending=".dmg", .func=updateMacOSBundle },
|
||||||
UpdateHandler { ".deb", "zenity --password | sudo -S apt install -y --fix-broken \"{}\"" },
|
UpdateHandler { .ending=".deb", .func=updateCommand("zenity --password | sudo -S apt install -y --fix-broken \"{}\"") },
|
||||||
UpdateHandler { ".rpm", "zenity --password | sudo -S rpm -i \"{}\"" },
|
UpdateHandler { .ending=".rpm", .func=updateCommand("zenity --password | sudo -S rpm -i \"{}\"") },
|
||||||
UpdateHandler { ".pkg.tar.zst", "zenity --password | sudo -S pacman -Syy && sudo pacman -U --noconfirm \"{}\"" },
|
UpdateHandler { .ending=".pkg.tar.zst", .func=updateCommand("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 { .ending=".AppImage", .func=updateCommand(fmt::format(R"(zenity --password | sudo -S cp "{{}}" "{}")", hex::getEnvironmentVariable("APPIMAGE").value_or(""))) },
|
||||||
UpdateHandler { ".flatpak", "zenity --password | sudo -S flatpak install -y --reinstall \"{}\"" },
|
UpdateHandler { .ending=".flatpak", .func=updateCommand("zenity --password | sudo -S flatpak install -y --reinstall \"{}\"") },
|
||||||
UpdateHandler { ".snap", "zenity --password | sudo -S snap install --dangerous \"{}\"" },
|
UpdateHandler { .ending=".snap", .func=updateCommand("zenity --password | sudo -S snap install --dangerous \"{}\"") },
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto updateFileName = wolv::util::toUTF8String(updatePath.filename());
|
const auto updateFileName = wolv::util::toUTF8String(updatePath.filename());
|
||||||
for (const auto &handler : UpdateHandlers) {
|
for (const auto &handler : UpdateHandlers) {
|
||||||
if (updateFileName.ends_with(handler.ending)) {
|
if (updateFileName.ends_with(handler.ending)) {
|
||||||
// Install the update using the correct command
|
// Install the update using the correct command
|
||||||
const auto command = fmt::format(fmt::runtime(handler.command), updatePath.string());
|
return handler.func(updatePath);
|
||||||
|
|
||||||
hex::log::info("Starting update process with command: '{}'", command);
|
|
||||||
hex::executeCommand(command);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,9 +270,11 @@ int main(int argc, char **argv) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hex::log::info("Updating ImHex...");
|
||||||
|
|
||||||
// Read the version type from the arguments
|
// Read the version type from the arguments
|
||||||
const std::string_view versionTypeString = argv[1];
|
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
|
// Convert the version type string to the enum value
|
||||||
hex::ImHexApi::System::UpdateType updateType;
|
hex::ImHexApi::System::UpdateType updateType;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include <content/views/view_hex_editor.hpp>
|
#include <content/views/view_hex_editor.hpp>
|
||||||
#include <hex/api/localization_manager.hpp>
|
#include <hex/api/localization_manager.hpp>
|
||||||
#include <ui/text_editor.hpp>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
@@ -21,6 +20,5 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_decodedString;
|
std::string m_decodedString;
|
||||||
ui::TextEditor m_editor;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
void setPath(const std::fs::path &path);
|
void setPath(const std::fs::path &path);
|
||||||
|
|
||||||
[[nodiscard]] bool open() override;
|
[[nodiscard]] OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
[[nodiscard]] std::string getName() const override;
|
[[nodiscard]] std::string getName() const override;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
void setPath(const std::fs::path &path);
|
void setPath(const std::fs::path &path);
|
||||||
|
|
||||||
[[nodiscard]] bool open() override;
|
[[nodiscard]] OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
void loadSettings(const nlohmann::json &settings) override;
|
void loadSettings(const nlohmann::json &settings) override;
|
||||||
@@ -65,7 +65,7 @@ namespace hex::plugin::builtin {
|
|||||||
private:
|
private:
|
||||||
void handleFileChange();
|
void handleFileChange();
|
||||||
|
|
||||||
bool open(bool memoryMapped);
|
OpenResult open(bool memoryMapped);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::fs::path m_path;
|
std::fs::path m_path;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace hex::plugin::builtin {
|
|||||||
[[nodiscard]] std::string getName() const override;
|
[[nodiscard]] std::string getName() const override;
|
||||||
[[nodiscard]] std::vector<Description> getDataDescription() const override;
|
[[nodiscard]] std::vector<Description> getDataDescription() const override;
|
||||||
|
|
||||||
[[nodiscard]] bool open() override;
|
[[nodiscard]] OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
[[nodiscard]] bool isConnected() const;
|
[[nodiscard]] bool isConnected() const;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace hex::plugin::builtin {
|
|||||||
[[nodiscard]] u64 getActualSize() const override;
|
[[nodiscard]] u64 getActualSize() const override;
|
||||||
void processMemoryRegions(wolv::util::Expected<std::map<u64, std::vector<u8>>, std::string> data);
|
void processMemoryRegions(wolv::util::Expected<std::map<u64, std::vector<u8>>, std::string> data);
|
||||||
static bool memoryRegionFilter(const std::string &search, const MemoryRegion &memoryRegion);
|
static bool memoryRegionFilter(const std::string &search, const MemoryRegion &memoryRegion);
|
||||||
bool open() override;
|
OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
[[nodiscard]] std::string getName() const override;
|
[[nodiscard]] std::string getName() const override;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace hex::plugin::builtin {
|
|||||||
[[nodiscard]] bool isSavable() const override { return m_name.empty(); }
|
[[nodiscard]] bool isSavable() const override { return m_name.empty(); }
|
||||||
[[nodiscard]] bool isSavableAsRecent() const override { return false; }
|
[[nodiscard]] bool isSavableAsRecent() const override { return false; }
|
||||||
|
|
||||||
[[nodiscard]] bool open() override;
|
[[nodiscard]] OpenResult open() override;
|
||||||
void close() override { }
|
void close() override { }
|
||||||
|
|
||||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace hex::plugin::builtin {
|
|||||||
MotorolaSRECProvider() = default;
|
MotorolaSRECProvider() = default;
|
||||||
~MotorolaSRECProvider() override = default;
|
~MotorolaSRECProvider() override = default;
|
||||||
|
|
||||||
bool open() override;
|
OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
[[nodiscard]] std::string getName() const override;
|
[[nodiscard]] std::string getName() const override;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace hex::plugin::builtin {
|
|||||||
[[nodiscard]] bool isResizable() const override { return false; }
|
[[nodiscard]] bool isResizable() const override { return false; }
|
||||||
[[nodiscard]] bool isSavable() const override { return false; }
|
[[nodiscard]] bool isSavable() const override { return false; }
|
||||||
|
|
||||||
[[nodiscard]] bool open() override { return true; }
|
[[nodiscard]] OpenResult open() override { return {}; }
|
||||||
void close() override { }
|
void close() override { }
|
||||||
|
|
||||||
void readRaw(u64 offset, void *buffer, size_t size) override {
|
void readRaw(u64 offset, void *buffer, size_t size) override {
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ namespace hex::plugin::builtin {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool open() override;
|
[[nodiscard]] OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
bool drawLoadInterface() override;
|
bool drawLoadInterface() override;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace hex::plugin::builtin {
|
|||||||
[[nodiscard]] bool drawLoadInterface() override;
|
[[nodiscard]] bool drawLoadInterface() override;
|
||||||
void drawSidebarInterface() override;
|
void drawSidebarInterface() override;
|
||||||
|
|
||||||
[[nodiscard]] bool open() override;
|
[[nodiscard]] OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
void loadSettings(const nlohmann::json &) override;
|
void loadSettings(const nlohmann::json &) override;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace hex::plugin::builtin {
|
|||||||
[[nodiscard]] bool isSavableAsRecent() const override;
|
[[nodiscard]] bool isSavableAsRecent() const override;
|
||||||
|
|
||||||
void save() override;
|
void save() override;
|
||||||
[[nodiscard]] bool open() override;
|
[[nodiscard]] OpenResult open() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
void resizeRaw(u64 newSize) override;
|
void resizeRaw(u64 newSize) override;
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
#include <hex/ui/view.hpp>
|
#include <hex/ui/view.hpp>
|
||||||
#include <hex/api/imhex_api/bookmarks.hpp>
|
#include <hex/api/imhex_api/bookmarks.hpp>
|
||||||
|
|
||||||
#include <ui/text_editor.hpp>
|
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <ui/markdown.hpp>
|
#include <ui/markdown.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -57,10 +57,6 @@ namespace hex::plugin::builtin {
|
|||||||
void reloadCustomNodes();
|
void reloadCustomNodes();
|
||||||
void updateNodePositions();
|
void updateNodePositions();
|
||||||
|
|
||||||
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override {
|
|
||||||
return ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Workspace*> &getWorkspaceStack() { return *m_workspaceStack; }
|
std::vector<Workspace*> &getWorkspaceStack() { return *m_workspaceStack; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
void drawContent() override;
|
void drawContent() override;
|
||||||
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override {
|
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override {
|
||||||
return ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
|
return ImGuiWindowFlags_NoNavInputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldDefaultFocus() const override { return true; }
|
bool shouldDefaultFocus() const override { return true; }
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImGuiWindowFlags getWindowFlags() const override {
|
ImGuiWindowFlags getWindowFlags() const override {
|
||||||
return View::Floating::getWindowFlags() | ImGuiWindowFlags_NoResize;
|
return ImGuiWindowFlags_NoResize;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
class ViewInformation : public View::Window {
|
class ViewInformation : public View::Scrolling {
|
||||||
public:
|
public:
|
||||||
explicit ViewInformation();
|
explicit ViewInformation();
|
||||||
~ViewInformation() override = default;
|
~ViewInformation() override = default;
|
||||||
|
|||||||
@@ -66,9 +66,6 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void drawContent() override;
|
void drawContent() override;
|
||||||
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override {
|
|
||||||
return ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPopupWindowHeight(u32 height) { m_popupWindowHeight = height; }
|
void setPopupWindowHeight(u32 height) { m_popupWindowHeight = height; }
|
||||||
u32 getPopupWindowHeight() const { return m_popupWindowHeight; }
|
u32 getPopupWindowHeight() const { return m_popupWindowHeight; }
|
||||||
@@ -152,12 +149,12 @@ namespace hex::plugin::builtin {
|
|||||||
std::mutex m_logMutex;
|
std::mutex m_logMutex;
|
||||||
|
|
||||||
PerProvider<ui::TextEditor::Coordinates> m_cursorPosition;
|
PerProvider<ui::TextEditor::Coordinates> m_cursorPosition;
|
||||||
|
PerProvider<ImVec2> m_scroll;
|
||||||
|
PerProvider<ImVec2> m_consoleScroll;
|
||||||
|
|
||||||
PerProvider<ui::TextEditor::Coordinates> m_consoleCursorPosition;
|
PerProvider<ui::TextEditor::Coordinates> m_consoleCursorPosition;
|
||||||
PerProvider<bool> m_cursorNeedsUpdate;
|
PerProvider<ui::TextEditor::Range> m_selection;
|
||||||
PerProvider<bool> m_consoleCursorNeedsUpdate;
|
PerProvider<ui::TextEditor::Range> m_consoleSelection;
|
||||||
PerProvider<ui::TextEditor::Selection> m_selection;
|
|
||||||
PerProvider<ui::TextEditor::Selection> m_consoleSelection;
|
|
||||||
PerProvider<size_t> m_consoleLongestLineLength;
|
PerProvider<size_t> m_consoleLongestLineLength;
|
||||||
PerProvider<ui::TextEditor::Breakpoints> m_breakpoints;
|
PerProvider<ui::TextEditor::Breakpoints> m_breakpoints;
|
||||||
PerProvider<std::optional<pl::core::err::PatternLanguageError>> m_lastEvaluationError;
|
PerProvider<std::optional<pl::core::err::PatternLanguageError>> m_lastEvaluationError;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
class ViewTools : public View::Window {
|
class ViewTools : public View::Scrolling {
|
||||||
public:
|
public:
|
||||||
ViewTools();
|
ViewTools();
|
||||||
~ViewTools() override = default;
|
~ViewTools() override = default;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImGuiWindowFlags getWindowFlags() const override {
|
ImGuiWindowFlags getWindowFlags() const override {
|
||||||
return Floating::getWindowFlags() | ImGuiWindowFlags_NoResize;
|
return ImGuiWindowFlags_NoResize;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -406,7 +406,7 @@
|
|||||||
"hex.builtin.popup.exit_application.title": "Exit Application?",
|
"hex.builtin.popup.exit_application.title": "Exit Application?",
|
||||||
"hex.builtin.popup.waiting_for_tasks.title": "Waiting for Tasks",
|
"hex.builtin.popup.waiting_for_tasks.title": "Waiting for Tasks",
|
||||||
"hex.builtin.popup.crash_recover.title": "Crash recovery",
|
"hex.builtin.popup.crash_recover.title": "Crash recovery",
|
||||||
"hex.builtin.popup.crash_recover.message": "An exception was thrown, but ImHex was able to catch it and advert a crash",
|
"hex.builtin.popup.crash_recover.message": "An exception was thrown, but ImHex was able to catch it and avert a crash",
|
||||||
"hex.builtin.popup.foreground_task.title": "Please Wait...",
|
"hex.builtin.popup.foreground_task.title": "Please Wait...",
|
||||||
"hex.builtin.popup.blocking_task.title": "Running Task",
|
"hex.builtin.popup.blocking_task.title": "Running Task",
|
||||||
"hex.builtin.popup.blocking_task.desc": "A task is currently executing.",
|
"hex.builtin.popup.blocking_task.desc": "A task is currently executing.",
|
||||||
@@ -418,7 +418,7 @@
|
|||||||
"hex.builtin.provider.rename": "Rename",
|
"hex.builtin.provider.rename": "Rename",
|
||||||
"hex.builtin.provider.rename.desc": "Enter a name for this data source.",
|
"hex.builtin.provider.rename.desc": "Enter a name for this data source.",
|
||||||
"hex.builtin.provider.tooltip.show_more": "Hold SHIFT for more information",
|
"hex.builtin.provider.tooltip.show_more": "Hold SHIFT for more information",
|
||||||
"hex.builtin.provider.error.open": "Failed to open data provider: {}",
|
"hex.builtin.provider.error.open": "Failed to open data source: {}",
|
||||||
"hex.builtin.provider.base64": "Base64 File",
|
"hex.builtin.provider.base64": "Base64 File",
|
||||||
"hex.builtin.provider.disk": "Raw Disk",
|
"hex.builtin.provider.disk": "Raw Disk",
|
||||||
"hex.builtin.provider.disk.disk_size": "Disk Size",
|
"hex.builtin.provider.disk.disk_size": "Disk Size",
|
||||||
@@ -430,6 +430,7 @@
|
|||||||
"hex.builtin.provider.disk.error.read_rw": "Failed to open disk {} in read/write mode: {}",
|
"hex.builtin.provider.disk.error.read_rw": "Failed to open disk {} in read/write mode: {}",
|
||||||
"hex.builtin.provider.file": "Regular File",
|
"hex.builtin.provider.file": "Regular File",
|
||||||
"hex.builtin.provider.file.error.open": "Failed to open file {}: {}",
|
"hex.builtin.provider.file.error.open": "Failed to open file {}: {}",
|
||||||
|
"hex.builtin.provider.file.error.already_open": "Same file is already open",
|
||||||
"hex.builtin.provider.file.access": "Last access time",
|
"hex.builtin.provider.file.access": "Last access time",
|
||||||
"hex.builtin.provider.file.creation": "Creation time",
|
"hex.builtin.provider.file.creation": "Creation time",
|
||||||
"hex.builtin.provider.file.menu.direct_access": "Direct access file",
|
"hex.builtin.provider.file.menu.direct_access": "Direct access file",
|
||||||
@@ -448,6 +449,7 @@
|
|||||||
"hex.builtin.provider.gdb.name": "GDB Server <{0}:{1}>",
|
"hex.builtin.provider.gdb.name": "GDB Server <{0}:{1}>",
|
||||||
"hex.builtin.provider.gdb.port": "Port",
|
"hex.builtin.provider.gdb.port": "Port",
|
||||||
"hex.builtin.provider.gdb.server": "Server",
|
"hex.builtin.provider.gdb.server": "Server",
|
||||||
|
"hex.builtin.provider.gdb.server.error.not_connected": "Failed to open connection to GDB Server",
|
||||||
"hex.builtin.provider.intel_hex": "Intel Hex File",
|
"hex.builtin.provider.intel_hex": "Intel Hex File",
|
||||||
"hex.builtin.provider.intel_hex.name": "Intel Hex {0}",
|
"hex.builtin.provider.intel_hex.name": "Intel Hex {0}",
|
||||||
"hex.builtin.provider.mem_file": "In-Memory File",
|
"hex.builtin.provider.mem_file": "In-Memory File",
|
||||||
@@ -458,6 +460,8 @@
|
|||||||
"hex.builtin.provider.opening": "Opening Data Source...",
|
"hex.builtin.provider.opening": "Opening Data Source...",
|
||||||
"hex.builtin.provider.process_memory": "Process Memory",
|
"hex.builtin.provider.process_memory": "Process Memory",
|
||||||
"hex.builtin.provider.process_memory.enumeration_failed": "Failed to enumerate processes",
|
"hex.builtin.provider.process_memory.enumeration_failed": "Failed to enumerate processes",
|
||||||
|
"hex.builtin.provider.process_memory.error.no_process_selected": "No process selected",
|
||||||
|
"hex.builtin.provider.process_memory.error.open_process": "Failed to attach to process",
|
||||||
"hex.builtin.provider.process_memory.macos_limitations": "macOS doesn't properly allow reading memory from other processes, even when running as root. If System Integrity Protection (SIP) is enabled, it only works for applications that are unsigned or have the 'Get Task Allow' entitlement which generally only applies to applications compiled by yourself.",
|
"hex.builtin.provider.process_memory.macos_limitations": "macOS doesn't properly allow reading memory from other processes, even when running as root. If System Integrity Protection (SIP) is enabled, it only works for applications that are unsigned or have the 'Get Task Allow' entitlement which generally only applies to applications compiled by yourself.",
|
||||||
"hex.builtin.provider.process_memory.memory_regions": "Memory Regions",
|
"hex.builtin.provider.process_memory.memory_regions": "Memory Regions",
|
||||||
"hex.builtin.provider.process_memory.name": "'{0}' Process Memory",
|
"hex.builtin.provider.process_memory.name": "'{0}' Process Memory",
|
||||||
@@ -476,6 +480,7 @@
|
|||||||
"hex.builtin.provider.udp.port": "Server Port",
|
"hex.builtin.provider.udp.port": "Server Port",
|
||||||
"hex.builtin.provider.udp.timestamp": "Timestamp",
|
"hex.builtin.provider.udp.timestamp": "Timestamp",
|
||||||
"hex.builtin.provider.view": "View",
|
"hex.builtin.provider.view": "View",
|
||||||
|
"hex.builtin.provider.view.error.no_provider": "No data source has been attached to this view",
|
||||||
"hex.builtin.setting.experiments": "Experiments",
|
"hex.builtin.setting.experiments": "Experiments",
|
||||||
"hex.builtin.setting.experiments.description": "Experiments are features that are still in development and may not work correctly yet.\n\nFeel free to try them out and report any issues you encounter!",
|
"hex.builtin.setting.experiments.description": "Experiments are features that are still in development and may not work correctly yet.\n\nFeel free to try them out and report any issues you encounter!",
|
||||||
"hex.builtin.setting.folders": "Folders",
|
"hex.builtin.setting.folders": "Folders",
|
||||||
@@ -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_data.virtual_files.no_virtual_files": "Visualize regions of data as a virtual folder structure by adding them using the hex::core::add_virtual_file function.",
|
||||||
"hex.builtin.view.pattern_editor.no_env_vars": "The content of Environment Variables created here can be accessed from Pattern scripts using the std::env function.",
|
"hex.builtin.view.pattern_editor.no_env_vars": "The content of Environment Variables created here can be accessed from Pattern scripts using the std::env function.",
|
||||||
"hex.builtin.view.pattern_editor.no_results": "no results",
|
"hex.builtin.view.pattern_editor.no_results": "no results",
|
||||||
|
"hex.builtin.view.pattern_editor.match_case_tooltip": "Match Case Alt-C",
|
||||||
|
"hex.builtin.view.pattern_editor.whole_word_tooltip": "Whole Word Alt-W",
|
||||||
|
"hex.builtin.view.pattern_editor.regex_tooltip": "Regex Alt-R",
|
||||||
"hex.builtin.view.pattern_editor.of": "of",
|
"hex.builtin.view.pattern_editor.of": "of",
|
||||||
"hex.builtin.view.pattern_editor.open_pattern": "Open pattern",
|
"hex.builtin.view.pattern_editor.open_pattern": "Open pattern",
|
||||||
"hex.builtin.view.pattern_editor.replace_hint": "Replace",
|
"hex.builtin.view.pattern_editor.replace_hint": "Replace",
|
||||||
|
|||||||
@@ -358,10 +358,10 @@ namespace hex::plugin::builtin {
|
|||||||
std::fs::path filePath = reinterpret_cast<const char8_t*>(args[0].data());
|
std::fs::path filePath = reinterpret_cast<const char8_t*>(args[0].data());
|
||||||
|
|
||||||
FileProvider provider;
|
FileProvider provider;
|
||||||
|
|
||||||
provider.setPath(filePath);
|
provider.setPath(filePath);
|
||||||
if (!provider.open()) {
|
auto result = provider.open();
|
||||||
log::println("Failed to open file '{}'", args[0]);
|
if (result.isFailure()) {
|
||||||
|
log::println("Failed to open file '{}': {}", args[0], result.getErrorMessage());
|
||||||
std::exit(EXIT_FAILURE);
|
std::exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -287,23 +287,23 @@ namespace hex::plugin::builtin {
|
|||||||
"@",
|
"@",
|
||||||
"hex.builtin.command.goto.desc",
|
"hex.builtin.command.goto.desc",
|
||||||
[](auto input) {
|
[](auto input) {
|
||||||
wolv::math_eval::MathEvaluator<long double> evaluator;
|
wolv::math_eval::MathEvaluator<i64> evaluator;
|
||||||
evaluator.registerStandardVariables();
|
evaluator.registerStandardVariables();
|
||||||
evaluator.registerStandardFunctions();
|
evaluator.registerStandardFunctions();
|
||||||
|
|
||||||
std::optional<long double> result = evaluator.evaluate(input);
|
const auto result = evaluator.evaluate(input);
|
||||||
if (result.has_value())
|
if (result.has_value())
|
||||||
return fmt::format("hex.builtin.command.goto.result"_lang, result.value());
|
return fmt::format("hex.builtin.command.goto.result"_lang, static_cast<u64>(result.value()));
|
||||||
else if (evaluator.hasError())
|
else if (evaluator.hasError())
|
||||||
return fmt::format("Error: {}", *evaluator.getLastError());
|
return fmt::format("Error: {}", *evaluator.getLastError());
|
||||||
else
|
else
|
||||||
return std::string("???");
|
return std::string("???");
|
||||||
}, [](auto input) -> std::optional<std::string> {
|
}, [](auto input) -> std::optional<std::string> {
|
||||||
wolv::math_eval::MathEvaluator<long double> evaluator;
|
wolv::math_eval::MathEvaluator<i64> evaluator;
|
||||||
evaluator.registerStandardVariables();
|
evaluator.registerStandardVariables();
|
||||||
evaluator.registerStandardFunctions();
|
evaluator.registerStandardFunctions();
|
||||||
|
|
||||||
std::optional<long double> result = evaluator.evaluate(input);
|
const auto result = evaluator.evaluate(input);
|
||||||
if (result.has_value()) {
|
if (result.has_value()) {
|
||||||
ImHexApi::HexEditor::setSelection(result.value(), 1);
|
ImHexApi::HexEditor::setSelection(result.value(), 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -589,9 +589,18 @@ namespace hex::plugin::builtin {
|
|||||||
return [value, copyValue] { ImGuiExt::TextFormatted("L\"{0}\"", value.c_str()); return copyValue; };
|
return [value, copyValue] { ImGuiExt::TextFormatted("L\"{0}\"", value.c_str()); return copyValue; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
[](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; };
|
return [value, copyValue] { ImGuiExt::TextFormatted("u\"{0}\"", value.c_str()); return copyValue; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
[](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; };
|
return [value, copyValue] { ImGuiExt::TextFormatted("U\"{0}\"", value.c_str()); return copyValue; };
|
||||||
},
|
},
|
||||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
[](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 {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
static void openFile(const std::fs::path &path) {
|
static void openFile(const std::fs::path &path) {
|
||||||
if (path.extension() == ".hexproj") {
|
TaskManager::doLater([path] {
|
||||||
if (!ProjectFile::load(path)) {
|
if (path.extension() == ".hexproj") {
|
||||||
ui::ToastError::open(fmt::format("hex.builtin.popup.error.project.load"_lang, wolv::util::toUTF8String(path)));
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
EventProviderOpened::post(fileProvider);
|
auto provider = ImHexApi::Provider::createProvider("hex.builtin.provider.file", true);
|
||||||
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name");
|
if (auto *fileProvider = dynamic_cast<FileProvider*>(provider.get()); fileProvider != nullptr) {
|
||||||
ImHexApi::Provider::setCurrentProvider(provider);
|
fileProvider->setPath(path);
|
||||||
|
|
||||||
glfwRequestWindowAttention(ImHexApi::System::getMainWindowHandle());
|
ImHexApi::Provider::openProvider(provider);
|
||||||
glfwFocusWindow(ImHexApi::System::getMainWindowHandle());
|
|
||||||
}
|
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() {
|
void registerEventHandlers() {
|
||||||
@@ -180,11 +177,8 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
RequestOpenWindow::subscribe([](const std::string &name) {
|
RequestOpenWindow::subscribe([](const std::string &name) {
|
||||||
if (name == "Create File") {
|
if (name == "Create File") {
|
||||||
auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true);
|
auto newProvider = ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true);
|
||||||
if (newProvider != nullptr && !newProvider->open())
|
ImHexApi::Provider::openProvider(newProvider);
|
||||||
hex::ImHexApi::Provider::remove(newProvider);
|
|
||||||
else
|
|
||||||
EventProviderOpened::post(newProvider);
|
|
||||||
} else if (name == "Open File") {
|
} else if (name == "Open File") {
|
||||||
fs::openFileBrowser(fs::DialogMode::Open, { }, [](const auto &path) {
|
fs::openFileBrowser(fs::DialogMode::Open, { }, [](const auto &path) {
|
||||||
if (path.extension() == ".hexproj") {
|
if (path.extension() == ".hexproj") {
|
||||||
@@ -195,20 +189,15 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto newProvider = static_cast<FileProvider*>(
|
auto provider = ImHexApi::Provider::createProvider("hex.builtin.provider.file", true);
|
||||||
ImHexApi::Provider::createProvider("hex.builtin.provider.file", true)
|
auto newProvider = static_cast<FileProvider*>(provider.get());
|
||||||
);
|
|
||||||
|
|
||||||
if (newProvider == nullptr)
|
if (newProvider == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
newProvider->setPath(path);
|
newProvider->setPath(path);
|
||||||
if (!newProvider->open()) {
|
ImHexApi::Provider::openProvider(provider);
|
||||||
hex::ImHexApi::Provider::remove(newProvider);
|
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name");
|
||||||
} else {
|
|
||||||
EventProviderOpened::post(newProvider);
|
|
||||||
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name");
|
|
||||||
}
|
|
||||||
}, {}, true);
|
}, {}, true);
|
||||||
} else if (name == "Open Project") {
|
} else if (name == "Open Project") {
|
||||||
fs::openFileBrowser(fs::DialogMode::Open, { {"Project File", "hexproj"} },
|
fs::openFileBrowser(fs::DialogMode::Open, { {"Project File", "hexproj"} },
|
||||||
@@ -225,34 +214,20 @@ namespace hex::plugin::builtin {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Handles the provider initialization, and calls EventProviderOpened if successful
|
// Handles the provider initialization, and calls EventProviderOpened if successful
|
||||||
EventProviderCreated::subscribe([](hex::prv::Provider *provider) {
|
EventProviderCreated::subscribe([](std::shared_ptr<prv::Provider> provider) {
|
||||||
if (provider->shouldSkipLoadInterface())
|
if (provider->shouldSkipLoadInterface())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (auto *filePickerProvider = dynamic_cast<prv::IProviderFilePicker*>(provider); filePickerProvider != nullptr) {
|
if (auto *filePickerProvider = dynamic_cast<prv::IProviderFilePicker*>(provider.get()); filePickerProvider != nullptr) {
|
||||||
if (!filePickerProvider->handleFilePicker()) {
|
if (!filePickerProvider->handleFilePicker()) {
|
||||||
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
|
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider.get()); });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskManager::createBlockingTask("hex.builtin.provider.opening", TaskManager::NoProgress, [provider]() {
|
ImHexApi::Provider::openProvider(provider);
|
||||||
if (!provider->open()) {
|
|
||||||
ui::ToastError::open(fmt::format("hex.builtin.provider.error.open"_lang, provider->getErrorMessage()));
|
|
||||||
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
|
|
||||||
} else {
|
|
||||||
TaskManager::doLater([provider]{ EventProviderOpened::post(provider); });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else if (dynamic_cast<prv::IProviderLoadInterface*>(provider) == nullptr) {
|
else if (dynamic_cast<prv::IProviderLoadInterface*>(provider.get()) == nullptr) {
|
||||||
TaskManager::createBlockingTask("hex.builtin.provider.opening", TaskManager::NoProgress, [provider]() {
|
ImHexApi::Provider::openProvider(provider);
|
||||||
if (!provider->open() || !provider->isAvailable()) {
|
|
||||||
ui::ToastError::open(fmt::format("hex.builtin.provider.error.open"_lang, provider->getErrorMessage()));
|
|
||||||
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
|
|
||||||
} else {
|
|
||||||
TaskManager::doLater([provider]{ EventProviderOpened::post(provider); });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -418,6 +393,25 @@ namespace hex::plugin::builtin {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
RequestOpenProvider::subscribe([](std::shared_ptr<prv::Provider> provider) {
|
||||||
|
TaskManager::createBlockingTask("hex.builtin.provider.opening", TaskManager::NoProgress, [provider]() {
|
||||||
|
auto result = provider->open();
|
||||||
|
if (result.isFailure()) {
|
||||||
|
ui::ToastError::open(fmt::format("hex.builtin.provider.error.open"_lang, result.getErrorMessage()));
|
||||||
|
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider.get()); });
|
||||||
|
} else if (result.isRedirecting()) {
|
||||||
|
TaskManager::doLater([result, provider] {
|
||||||
|
ImHexApi::Provider::remove(provider.get());
|
||||||
|
ImHexApi::Provider::setCurrentProvider(result.getRedirectProvider());
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (result.isWarning())
|
||||||
|
ui::ToastWarning::open(std::string(result.getErrorMessage()));
|
||||||
|
TaskManager::doLater([provider]{ EventProviderOpened::post(provider.get()); });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
fs::setFileBrowserErrorCallback([](const std::string& errMsg){
|
fs::setFileBrowserErrorCallback([](const std::string& errMsg){
|
||||||
#if defined(NFD_PORTAL)
|
#if defined(NFD_PORTAL)
|
||||||
ui::PopupError::open(fmt::format("hex.builtin.popup.error.file_dialog.portal"_lang, errMsg));
|
ui::PopupError::open(fmt::format("hex.builtin.popup.error.file_dialog.portal"_lang, errMsg));
|
||||||
|
|||||||
@@ -377,10 +377,10 @@ namespace hex::plugin::builtin {
|
|||||||
/* Create File */
|
/* Create File */
|
||||||
ContentRegistry::UserInterface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.create_file" }, ICON_VS_FILE, 1050, CTRLCMD + Keys::N + AllowWhileTyping + ShowOnWelcomeScreen, [] {
|
ContentRegistry::UserInterface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.create_file" }, ICON_VS_FILE, 1050, CTRLCMD + Keys::N + AllowWhileTyping + ShowOnWelcomeScreen, [] {
|
||||||
auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true);
|
auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true);
|
||||||
if (newProvider != nullptr && !newProvider->open())
|
if (newProvider != nullptr && newProvider->open().isFailure())
|
||||||
hex::ImHexApi::Provider::remove(newProvider);
|
hex::ImHexApi::Provider::remove(newProvider.get());
|
||||||
else
|
else
|
||||||
EventProviderOpened::post(newProvider);
|
EventProviderOpened::post(newProvider.get());
|
||||||
}, noRunningTasks, ContentRegistry::Views::getViewByName("hex.builtin.view.hex_editor.name"));
|
}, noRunningTasks, ContentRegistry::Views::getViewByName("hex.builtin.view.hex_editor.name"));
|
||||||
|
|
||||||
/* Open File */
|
/* Open File */
|
||||||
@@ -401,7 +401,7 @@ namespace hex::plugin::builtin {
|
|||||||
auto provider = ImHexApi::Provider::get();
|
auto provider = ImHexApi::Provider::get();
|
||||||
|
|
||||||
provider->close();
|
provider->close();
|
||||||
if (!provider->open())
|
if (provider->open().isFailure())
|
||||||
ImHexApi::Provider::remove(provider, true);
|
ImHexApi::Provider::remove(provider, true);
|
||||||
|
|
||||||
EventDataChanged::post(provider);
|
EventDataChanged::post(provider);
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
|
|
||||||
#include <popups/popup_file_chooser.hpp>
|
#include <popups/popup_file_chooser.hpp>
|
||||||
|
|
||||||
#include <ui/text_editor.hpp>
|
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
PopupDecodedString::PopupDecodedString(std::string decodedString) : m_decodedString(std::move(decodedString)) {
|
PopupDecodedString::PopupDecodedString(std::string decodedString) : m_decodedString(std::move(decodedString)) {
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
#include <fonts/vscode_icons.hpp>
|
#include <fonts/vscode_icons.hpp>
|
||||||
|
|
||||||
#include <ui/text_editor.hpp>
|
|
||||||
#include <wolv/literals.hpp>
|
#include <wolv/literals.hpp>
|
||||||
|
|
||||||
using namespace wolv::literals;
|
using namespace wolv::literals;
|
||||||
|
|||||||
@@ -18,8 +18,6 @@
|
|||||||
|
|
||||||
#include <popups/popup_file_chooser.hpp>
|
#include <popups/popup_file_chooser.hpp>
|
||||||
|
|
||||||
#include <ui/text_editor.hpp>
|
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
PerProvider<std::string> PopupFind::s_inputString;
|
PerProvider<std::string> PopupFind::s_inputString;
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
#include <hex/api/content_registry/settings.hpp>
|
#include <hex/api/content_registry/settings.hpp>
|
||||||
|
|
||||||
#include <ui/text_editor.hpp>
|
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
PopupPasteBehaviour::PopupPasteBehaviour(const Region &selection, const std::function<void(const Region &selection, bool selectionCheck)> &pasteCallback)
|
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 <content/differing_byte_searcher.hpp>
|
||||||
|
|
||||||
#include <ui/text_editor.hpp>
|
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
PopupRemove::PopupRemove(u64 address, size_t size) : m_address(address), m_size(size) {}
|
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"));
|
newProvider->loadSettings(providerSettings.at("settings"));
|
||||||
loaded = true;
|
loaded = true;
|
||||||
} catch (const std::exception &e){
|
} catch (const std::exception &e){
|
||||||
providerWarnings[newProvider] = e.what();
|
providerWarnings[newProvider.get()] = e.what();
|
||||||
}
|
}
|
||||||
if (loaded) {
|
if (loaded) {
|
||||||
if (!newProvider->open() || !newProvider->isAvailable() || !newProvider->isReadable()) {
|
auto result = newProvider->open();
|
||||||
providerWarnings[newProvider] = newProvider->getErrorMessage();
|
if (result.isFailure() || !newProvider->isAvailable() || !newProvider->isReadable()) {
|
||||||
|
providerWarnings[newProvider.get()] = result.getErrorMessage();
|
||||||
} else {
|
} else {
|
||||||
EventProviderOpened::post(newProvider);
|
EventProviderOpened::post(newProvider.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,7 +157,8 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool DiskProvider::open() {
|
prv::Provider::OpenResult DiskProvider::open() {
|
||||||
|
OpenResult result;
|
||||||
m_readable = true;
|
m_readable = true;
|
||||||
m_writable = true;
|
m_writable = true;
|
||||||
|
|
||||||
@@ -171,8 +172,7 @@ namespace hex::plugin::builtin {
|
|||||||
m_writable = false;
|
m_writable = false;
|
||||||
|
|
||||||
if (m_diskHandle == INVALID_HANDLE_VALUE) {
|
if (m_diskHandle == INVALID_HANDLE_VALUE) {
|
||||||
this->setErrorMessage(hex::formatSystemError(::GetLastError()));
|
return OpenResult::failure(hex::formatSystemError(::GetLastError()));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,12 +194,12 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_diskHandle == nullptr || m_diskHandle == INVALID_HANDLE_VALUE) {
|
if (m_diskHandle == nullptr || m_diskHandle == INVALID_HANDLE_VALUE) {
|
||||||
this->setErrorMessage(hex::formatSystemError(::GetLastError()));
|
auto error = ::GetLastError();
|
||||||
m_readable = false;
|
m_readable = false;
|
||||||
m_diskHandle = nullptr;
|
m_diskHandle = nullptr;
|
||||||
CloseHandle(m_diskHandle);
|
CloseHandle(m_diskHandle);
|
||||||
|
|
||||||
return false;
|
return OpenResult::failure(hex::formatSystemError(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@@ -208,17 +208,14 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
m_diskHandle = ::open(path.c_str(), O_RDWR);
|
m_diskHandle = ::open(path.c_str(), O_RDWR);
|
||||||
if (m_diskHandle == -1) {
|
if (m_diskHandle == -1) {
|
||||||
this->setErrorMessage(fmt::format("hex.builtin.provider.disk.error.read_rw"_lang, path, formatSystemError(errno)));
|
result = OpenResult::warning(fmt::format("hex.builtin.provider.disk.error.read_rw"_lang, path, formatSystemError(errno)));
|
||||||
log::warn("{}", this->getErrorMessage());
|
|
||||||
m_diskHandle = ::open(path.c_str(), O_RDONLY);
|
m_diskHandle = ::open(path.c_str(), O_RDONLY);
|
||||||
m_writable = false;
|
m_writable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_diskHandle == -1) {
|
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;
|
m_readable = false;
|
||||||
return false;
|
return OpenResult::failure(fmt::format("hex.builtin.provider.disk.error.read_ro"_lang, path, formatSystemError(errno)));
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 diskSize = 0;
|
u64 diskSize = 0;
|
||||||
@@ -228,7 +225,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return true;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiskProvider::close() {
|
void DiskProvider::close() {
|
||||||
|
|||||||
@@ -198,24 +198,23 @@ namespace hex::plugin::builtin {
|
|||||||
m_path.make_preferred();
|
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);
|
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;
|
size_t fileSize = 0x00;
|
||||||
{
|
{
|
||||||
wolv::io::File file(m_path, wolv::io::File::Mode::Read);
|
wolv::io::File file(m_path, wolv::io::File::Mode::Read);
|
||||||
if (!file.isValid()) {
|
if (!file.isValid()) {
|
||||||
this->setErrorMessage(fmt::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), formatSystemError(file.getOpenError().value_or(0))));
|
return OpenResult::failure(fmt::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), formatSystemError(file.getOpenError().value_or(0))));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fileSize = file.getSize();
|
fileSize = file.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool directAccess = fileSize >= maxMemoryFileSize;
|
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;
|
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]{
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileProvider::open(bool directAccess) {
|
prv::Provider::OpenResult FileProvider::open(bool directAccess) {
|
||||||
m_readable = true;
|
m_readable = true;
|
||||||
m_writable = true;
|
m_writable = true;
|
||||||
|
|
||||||
@@ -238,8 +237,7 @@ namespace hex::plugin::builtin {
|
|||||||
file = wolv::io::File(m_path, wolv::io::File::Mode::Read);
|
file = wolv::io::File(m_path, wolv::io::File::Mode::Read);
|
||||||
if (!file.isValid()) {
|
if (!file.isValid()) {
|
||||||
m_readable = false;
|
m_readable = false;
|
||||||
this->setErrorMessage(fmt::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), formatSystemError(file.getOpenError().value_or(0))));
|
return OpenResult::failure(fmt::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), formatSystemError(file.getOpenError().value_or(0))));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ui::ToastInfo::open("hex.builtin.popup.error.read_only"_lang);
|
ui::ToastInfo::open("hex.builtin.popup.error.read_only"_lang);
|
||||||
@@ -258,8 +256,7 @@ namespace hex::plugin::builtin {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (alreadyOpenedFileProvider != s_openedFiles.end()) {
|
if (alreadyOpenedFileProvider != s_openedFiles.end()) {
|
||||||
ImHexApi::Provider::setCurrentProvider(*alreadyOpenedFileProvider);
|
return OpenResult::redirect(*alreadyOpenedFileProvider);
|
||||||
return false;
|
|
||||||
} else {
|
} else {
|
||||||
s_openedFiles.insert(this);
|
s_openedFiles.insert(this);
|
||||||
}
|
}
|
||||||
@@ -281,7 +278,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
m_changeEventAcknowledgementPending = false;
|
m_changeEventAcknowledgementPending = false;
|
||||||
|
|
||||||
return true;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -313,10 +310,6 @@ namespace hex::plugin::builtin {
|
|||||||
if (!wolv::io::fs::exists(fullPath))
|
if (!wolv::io::fs::exists(fullPath))
|
||||||
fullPath = path;
|
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);
|
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);
|
std::scoped_lock lock(m_mutex);
|
||||||
|
|
||||||
CachedProvider::open();
|
CachedProvider::open();
|
||||||
@@ -264,11 +264,11 @@ namespace hex::plugin::builtin {
|
|||||||
gdb::sendReceivePackage(m_socket, gdb::createPacket("!"));
|
gdb::sendReceivePackage(m_socket, gdb::createPacket("!"));
|
||||||
gdb::sendReceivePackage(m_socket, gdb::createPacket("Hg0"));
|
gdb::sendReceivePackage(m_socket, gdb::createPacket("Hg0"));
|
||||||
|
|
||||||
if (m_socket.isConnected()) {
|
if (!m_socket.isConnected()) {
|
||||||
return true;
|
return OpenResult::failure("hex.builtin.provider.gdb.server.error.not_connected"_lang);
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDBProvider::close() {
|
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);
|
auto file = wolv::io::File(m_sourceFilePath, wolv::io::File::Mode::Read);
|
||||||
if (!file.isValid()) {
|
if (!file.isValid()) {
|
||||||
this->setErrorMessage(fmt::format("hex.builtin.provider.file.error.open"_lang, m_sourceFilePath.string(), formatSystemError(errno)));
|
return OpenResult::failure(fmt::format("hex.builtin.provider.file.error.open"_lang, m_sourceFilePath.string(), formatSystemError(errno)));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = intel_hex::parseIntelHex(file.readString());
|
auto data = intel_hex::parseIntelHex(file.readString());
|
||||||
if (!data.has_value()) {
|
if (!data.has_value()) {
|
||||||
this->setErrorMessage(data.error());
|
return OpenResult::failure(data.error());
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
processMemoryRegions(data);
|
processMemoryRegions(data);
|
||||||
|
|
||||||
return true;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntelHexProvider::close() {
|
void IntelHexProvider::close() {
|
||||||
|
|||||||
@@ -16,12 +16,12 @@
|
|||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
bool MemoryFileProvider::open() {
|
prv::Provider::OpenResult MemoryFileProvider::open() {
|
||||||
if (m_data.empty()) {
|
if (m_data.empty()) {
|
||||||
m_data.resize(1);
|
m_data.resize(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryFileProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
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);
|
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);
|
fileProvider->setPath(path);
|
||||||
|
|
||||||
if (!fileProvider->open()) {
|
if (fileProvider->open().isFailure()) {
|
||||||
ImHexApi::Provider::remove(newProvider);
|
ImHexApi::Provider::remove(newProvider.get());
|
||||||
} else {
|
} else {
|
||||||
MovePerProviderData::post(this, fileProvider);
|
MovePerProviderData::post(this, fileProvider);
|
||||||
|
|
||||||
fileProvider->markDirty(false);
|
fileProvider->markDirty(false);
|
||||||
EventProviderOpened::post(newProvider);
|
EventProviderOpened::post(newProvider.get());
|
||||||
ImHexApi::Provider::remove(this, true);
|
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);
|
auto file = wolv::io::File(m_sourceFilePath, wolv::io::File::Mode::Read);
|
||||||
if (!file.isValid()) {
|
if (!file.isValid()) {
|
||||||
this->setErrorMessage(fmt::format("hex.builtin.provider.file.error.open"_lang, m_sourceFilePath.string(), formatSystemError(errno)));
|
return OpenResult::failure(fmt::format("hex.builtin.provider.file.error.open"_lang, m_sourceFilePath.string(), formatSystemError(errno)));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = motorola_srec::parseMotorolaSREC(file.readString());
|
auto data = motorola_srec::parseMotorolaSREC(file.readString());
|
||||||
if (!data.has_value()) {
|
if (!data.has_value()) {
|
||||||
this->setErrorMessage(data.error());
|
return OpenResult::failure(data.error());
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
processMemoryRegions(data);
|
processMemoryRegions(data);
|
||||||
|
|
||||||
return true;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotorolaSRECProvider::close() {
|
void MotorolaSRECProvider::close() {
|
||||||
|
|||||||
@@ -33,21 +33,21 @@
|
|||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
bool ProcessMemoryProvider::open() {
|
prv::Provider::OpenResult ProcessMemoryProvider::open() {
|
||||||
if (m_selectedProcess == nullptr)
|
if (m_selectedProcess == nullptr)
|
||||||
return false;
|
return OpenResult::failure("hex.builtin.provider.process_memory.error.no_process_selected"_lang);
|
||||||
|
|
||||||
#if defined(OS_WINDOWS)
|
#if defined(OS_WINDOWS)
|
||||||
m_processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_selectedProcess->id);
|
m_processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_selectedProcess->id);
|
||||||
if (m_processHandle == nullptr)
|
if (m_processHandle == nullptr)
|
||||||
return false;
|
return OpenResult::failure("hex.builtin.provider.process_memory.error.open_process"_lang);
|
||||||
#else
|
#else
|
||||||
m_processId = pid_t(m_selectedProcess->id);
|
m_processId = pid_t(m_selectedProcess->id);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
this->reloadProcessModules();
|
this->reloadProcessModules();
|
||||||
|
|
||||||
return true;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessMemoryProvider::close() {
|
void ProcessMemoryProvider::close() {
|
||||||
@@ -125,7 +125,7 @@ namespace hex::plugin::builtin {
|
|||||||
for (const auto &memoryRegion : m_memoryRegions) {
|
for (const auto &memoryRegion : m_memoryRegions) {
|
||||||
|
|
||||||
if (address < memoryRegion.region.getStartAddress())
|
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;
|
lastRegion = memoryRegion.region;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
bool UDPProvider::open() {
|
prv::Provider::OpenResult UDPProvider::open() {
|
||||||
m_udpServer = UDPServer(m_port, [this](std::span<const u8> data) {
|
m_udpServer = UDPServer(m_port, [this](std::span<const u8> data) {
|
||||||
this->receive(data);
|
this->receive(data);
|
||||||
});
|
});
|
||||||
m_udpServer.start();
|
m_udpServer.start();
|
||||||
|
|
||||||
return true;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDPProvider::close() {
|
void UDPProvider::close() {
|
||||||
|
|||||||
@@ -48,9 +48,9 @@ namespace hex::plugin::builtin {
|
|||||||
m_provider->save();
|
m_provider->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool ViewProvider::open() {
|
[[nodiscard]] prv::Provider::OpenResult ViewProvider::open() {
|
||||||
if (m_provider == this)
|
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*) {
|
EventProviderClosing::subscribe(this, [this](const prv::Provider *provider, bool*) {
|
||||||
if (m_provider == provider) {
|
if (m_provider == provider) {
|
||||||
@@ -59,7 +59,7 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return {};
|
||||||
}
|
}
|
||||||
void ViewProvider::close() {
|
void ViewProvider::close() {
|
||||||
EventProviderClosing::unsubscribe(this);
|
EventProviderClosing::unsubscribe(this);
|
||||||
|
|||||||
@@ -279,18 +279,11 @@ namespace hex::plugin::builtin::recent {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *provider = ImHexApi::Provider::createProvider(recentEntry.type, true);
|
auto provider = ImHexApi::Provider::createProvider(recentEntry.type, true);
|
||||||
if (provider != nullptr) {
|
if (provider != nullptr) {
|
||||||
provider->loadSettings(recentEntry.data);
|
provider->loadSettings(recentEntry.data);
|
||||||
|
|
||||||
TaskManager::createBlockingTask("hex.builtin.provider.opening", TaskManager::NoProgress, [provider]() {
|
ImHexApi::Provider::openProvider(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); });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
updateRecentEntries();
|
updateRecentEntries();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1247,7 +1247,7 @@ namespace hex::plugin::builtin {
|
|||||||
if (isLocationValid(error.getLocation())) {
|
if (isLocationValid(error.getLocation())) {
|
||||||
auto key = ui::TextEditor::Coordinates(error.getLocation().line, error.getLocation().column);
|
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()));
|
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/imhex_api/system.hpp>
|
||||||
#include <hex/api/localization_manager.hpp>
|
#include <hex/api/localization_manager.hpp>
|
||||||
#include <hex/api/task_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_provider.hpp>
|
||||||
#include <hex/api/events/events_gui.hpp>
|
#include <hex/api/events/events_gui.hpp>
|
||||||
@@ -523,7 +524,6 @@ namespace hex::plugin::builtin {
|
|||||||
flags |= ImGuiTabItemFlags_UnsavedDocument;
|
flags |= ImGuiTabItemFlags_UnsavedDocument;
|
||||||
if (i64(i) == selectedProviderIndex && providerJustChanged) {
|
if (i64(i) == selectedProviderIndex && providerJustChanged) {
|
||||||
flags |= ImGuiTabItemFlags_SetSelected;
|
flags |= ImGuiTabItemFlags_SetSelected;
|
||||||
providerJustChanged = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t lastSelectedProvider = 0;
|
static size_t lastSelectedProvider = 0;
|
||||||
@@ -534,7 +534,7 @@ namespace hex::plugin::builtin {
|
|||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSelected && lastSelectedProvider != i) {
|
if (isSelected && lastSelectedProvider != i && !providerJustChanged) {
|
||||||
ImHexApi::Provider::setCurrentProvider(i);
|
ImHexApi::Provider::setCurrentProvider(i);
|
||||||
lastSelectedProvider = i;
|
lastSelectedProvider = i;
|
||||||
}
|
}
|
||||||
@@ -554,6 +554,8 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndTabBar();
|
ImGui::EndTabBar();
|
||||||
|
|
||||||
|
providerJustChanged = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
ViewFullScreenFileInfo::ViewFullScreenFileInfo(std::fs::path filePath) : m_filePath(std::move(filePath)) {
|
ViewFullScreenFileInfo::ViewFullScreenFileInfo(std::fs::path filePath) : m_filePath(std::move(filePath)) {
|
||||||
this->m_provider.setPath(m_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);
|
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) {
|
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))) {
|
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) {
|
fs::openFileBrowser(fs::DialogMode::Open, {}, [this](const std::fs::path &path) {
|
||||||
this->m_provider.setPath(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);
|
ui::ToastError::open("hex.builtin.view.fullscreen.save_editor.error.not_readable"_lang);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentRegistry::PatternLanguage::configureRuntime(m_runtime, &m_provider);
|
ContentRegistry::PatternLanguage::configureRuntime(m_runtime, &m_provider);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <wolv/io/file.hpp>
|
#include <wolv/io/file.hpp>
|
||||||
#include <wolv/utils/guards.hpp>
|
#include <wolv/utils/guards.hpp>
|
||||||
|
#include "imgui_internal.h"
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
@@ -389,14 +390,13 @@ namespace hex::plugin::builtin {
|
|||||||
auto provider = ImHexApi::Provider::get();
|
auto provider = ImHexApi::Provider::get();
|
||||||
TaskManager::doLater([region, provider, name]{
|
TaskManager::doLater([region, provider, name]{
|
||||||
auto newProvider = ImHexApi::Provider::createProvider("hex.builtin.provider.view", true);
|
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->setProvider(region.getStartAddress(), region.getSize(), provider);
|
||||||
viewProvider->setName(fmt::format("'{}' View", name));
|
viewProvider->setName(fmt::format("'{}' View", name));
|
||||||
|
|
||||||
if (viewProvider->open()) {
|
ImHexApi::Provider::openProvider(newProvider);
|
||||||
EventProviderOpened::post(viewProvider);
|
|
||||||
AchievementManager::unlockAchievement("hex.builtin.achievement.hex_editor", "hex.builtin.achievement.hex_editor.open_new_view.name");
|
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
|
// Enter editing mode when double-clicking the row
|
||||||
const bool editable = entry.editingFunction.has_value() && m_selectedProvider->isWritable();
|
const bool editable = entry.editingFunction.has_value() && m_selectedProvider->isWritable();
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
@@ -469,6 +473,10 @@ namespace hex::plugin::builtin {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||||
|
entry.editing = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle editing mode
|
// Handle editing mode
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||||
ImGui::SetNextItemWidth(-1);
|
ImGui::SetNextItemWidth(-1);
|
||||||
|
|||||||
@@ -1187,7 +1187,7 @@ namespace hex::plugin::builtin {
|
|||||||
ImGui::TableSetupScrollFreeze(0, 1);
|
ImGui::TableSetupScrollFreeze(0, 1);
|
||||||
ImGui::TableSetupColumn("hex.ui.common.offset"_lang, 0, -1, ImGui::GetID("offset"));
|
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.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();
|
auto sortSpecs = ImGui::TableGetSortSpecs();
|
||||||
|
|
||||||
@@ -1197,22 +1197,22 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sortSpecs->SpecsDirty) {
|
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->ColumnUserID == ImGui::GetID("offset")) {
|
||||||
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
||||||
return left.region.getStartAddress() > right.region.getStartAddress();
|
|
||||||
else
|
|
||||||
return left.region.getStartAddress() < right.region.getStartAddress();
|
return left.region.getStartAddress() < right.region.getStartAddress();
|
||||||
|
else
|
||||||
|
return left.region.getStartAddress() > right.region.getStartAddress();
|
||||||
} else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("size")) {
|
} else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("size")) {
|
||||||
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
||||||
return left.region.getSize() > right.region.getSize();
|
|
||||||
else
|
|
||||||
return left.region.getSize() < right.region.getSize();
|
return left.region.getSize() < right.region.getSize();
|
||||||
|
else
|
||||||
|
return left.region.getSize() > right.region.getSize();
|
||||||
} else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("value")) {
|
} else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("value")) {
|
||||||
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
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);
|
return this->decodeValue(provider, left) < this->decodeValue(provider, right);
|
||||||
|
else
|
||||||
|
return this->decodeValue(provider, left) > this->decodeValue(provider, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -43,7 +43,6 @@
|
|||||||
#include <content/popups/hex_editor/popup_hex_editor_find.hpp>
|
#include <content/popups/hex_editor/popup_hex_editor_find.hpp>
|
||||||
#include <pl/patterns/pattern.hpp>
|
#include <pl/patterns/pattern.hpp>
|
||||||
#include <hex/helpers/menu_items.hpp>
|
#include <hex/helpers/menu_items.hpp>
|
||||||
#include <ui/text_editor.hpp>
|
|
||||||
#include <wolv/literals.hpp>
|
#include <wolv/literals.hpp>
|
||||||
|
|
||||||
using namespace std::literals::string_literals;
|
using namespace std::literals::string_literals;
|
||||||
@@ -60,8 +59,10 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
std::optional<color_t> result;
|
std::optional<color_t> result;
|
||||||
for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getForegroundHighlightingFunctions()) {
|
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;
|
result = color;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.has_value()) {
|
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) {
|
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) {
|
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 selection = ImHexApi::HexEditor::getSelection();
|
||||||
|
|
||||||
auto newProvider = ImHexApi::Provider::createProvider("hex.builtin.provider.view", true);
|
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());
|
viewProvider->setProvider(selection->getStartAddress(), selection->getSize(), selection->getProvider());
|
||||||
if (viewProvider->open())
|
ImHexApi::Provider::openProvider(newProvider);
|
||||||
EventProviderOpened::post(viewProvider);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[] { return ImHexApi::HexEditor::isSelectionValid() && ImHexApi::Provider::isValid(); },
|
[] { return ImHexApi::HexEditor::isSelectionValid() && ImHexApi::Provider::isValid(); },
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ namespace hex::plugin::builtin {
|
|||||||
// Draw a table containing all the existing highlighting rules
|
// 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))) {
|
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("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) {
|
for (auto it = m_rules->begin(); it != m_rules->end(); ++it) {
|
||||||
auto &rule = *it;
|
auto &rule = *it;
|
||||||
@@ -197,6 +197,9 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
|
if (m_selectedRule == it && !rule.enabled)
|
||||||
|
m_selectedRule = m_rules->end();
|
||||||
|
|
||||||
// Draw enabled checkbox
|
// Draw enabled checkbox
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2());
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2());
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
using namespace hex::literals;
|
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) {
|
m_analysisData.setOnCreateCallback([](const prv::Provider *provider, AnalysisData &data) {
|
||||||
data.analyzedProvider = provider;
|
data.analyzedProvider = provider;
|
||||||
|
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ namespace hex::plugin::builtin {
|
|||||||
bool patternsValid = false;
|
bool patternsValid = false;
|
||||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||||
if (TRY_LOCK(ContentRegistry::PatternLanguage::getRuntimeLock())) {
|
if (TRY_LOCK(ContentRegistry::PatternLanguage::getRuntimeLock())) {
|
||||||
patternsValid = runtime.arePatternsValid();
|
patternsValid = runtime.getCreatedPatternCount() > 0 && runtime.arePatternsValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::BeginTabBar("##SectionSelector")) {
|
if (ImGui::BeginTabBar("##SectionSelector")) {
|
||||||
|
|||||||
@@ -477,11 +477,6 @@ namespace hex::plugin::builtin {
|
|||||||
m_textEditor.get(provider).selectWordUnderCursor();
|
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) {
|
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr) {
|
||||||
setupFindReplace(editor);
|
setupFindReplace(editor);
|
||||||
setupGotoLine(editor);
|
setupGotoLine(editor);
|
||||||
@@ -716,7 +711,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
ImGui::TableNextColumn();
|
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();
|
std::string hint = "hex.builtin.view.pattern_editor.find_hint"_lang.operator std::string();
|
||||||
if (m_findHistorySize > 0) {
|
if (m_findHistorySize > 0) {
|
||||||
@@ -724,6 +719,8 @@ namespace hex::plugin::builtin {
|
|||||||
hint += ICON_BI_DATA_TRANSFER_BOTH;
|
hint += ICON_BI_DATA_TRANSFER_BOTH;
|
||||||
hint += "hex.builtin.view.pattern_editor.find_hint_history"_lang.operator std::string();
|
hint += "hex.builtin.view.pattern_editor.find_hint_history"_lang.operator std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool enterPressedReplace = false;
|
||||||
static bool enterPressedFind = false;
|
static bool enterPressedFind = false;
|
||||||
ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
|
ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
|
||||||
if (ImGui::InputTextWithHint("###findInputTextWidget", hint.c_str(), findWord, findFlags) || enter ) {
|
if (ImGui::InputTextWithHint("###findInputTextWidget", hint.c_str(), findWord, findFlags) || enter ) {
|
||||||
@@ -775,6 +772,12 @@ namespace hex::plugin::builtin {
|
|||||||
updateCount = true;
|
updateCount = true;
|
||||||
requestFocusFind = true;
|
requestFocusFind = true;
|
||||||
}
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
if (ImGui::BeginTooltip()) {
|
||||||
|
ImGui::TextUnformatted("hex.builtin.view.pattern_editor.match_case_tooltip"_lang);
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
@@ -791,7 +794,12 @@ namespace hex::plugin::builtin {
|
|||||||
updateCount = true;
|
updateCount = true;
|
||||||
requestFocusFind = true;
|
requestFocusFind = true;
|
||||||
}
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
if (ImGui::BeginTooltip()) {
|
||||||
|
ImGui::TextUnformatted("hex.builtin.view.pattern_editor.whole_word_tooltip"_lang);
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
bool useRegex = findReplaceHandler->getFindRegEx();
|
bool useRegex = findReplaceHandler->getFindRegEx();
|
||||||
@@ -807,6 +815,13 @@ namespace hex::plugin::builtin {
|
|||||||
updateCount = true;
|
updateCount = true;
|
||||||
requestFocusFind = 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;
|
static std::string counterString;
|
||||||
|
|
||||||
@@ -852,12 +867,15 @@ namespace hex::plugin::builtin {
|
|||||||
if (ImGuiExt::IconButton(ICON_VS_ARROW_UP, ImVec4(1, 1, 1, 1)))
|
if (ImGuiExt::IconButton(ICON_VS_ARROW_UP, ImVec4(1, 1, 1, 1)))
|
||||||
upArrowFind = true;
|
upArrowFind = true;
|
||||||
|
|
||||||
|
static bool downArrowReplace = false;
|
||||||
|
static bool upArrowReplace = false;
|
||||||
|
static std::string replaceWord;
|
||||||
if (m_replaceMode) {
|
if (m_replaceMode) {
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
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();
|
hint = "hex.builtin.view.pattern_editor.replace_hint"_lang.operator std::string();
|
||||||
if (m_replaceHistorySize > 0) {
|
if (m_replaceHistorySize > 0) {
|
||||||
@@ -867,31 +885,13 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
|
ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
|
||||||
static std::string replaceWord;
|
if (ImGui::InputTextWithHint("###replaceInputTextWidget", hint.c_str(), replaceWord, replaceFlags) || enter) {
|
||||||
static bool downArrowReplace = false;
|
if (enter)
|
||||||
static bool upArrowReplace = false;
|
enterPressedReplace = true;
|
||||||
if (ImGui::InputTextWithHint("###replaceInputTextWidget", hint.c_str(), replaceWord, replaceFlags) || downArrowReplace || upArrowReplace) {
|
|
||||||
findReplaceHandler->setReplaceWord(replaceWord);
|
|
||||||
historyInsert(m_replaceHistory, m_replaceHistorySize, m_replaceHistoryIndex, replaceWord);
|
|
||||||
|
|
||||||
bool textReplaced = findReplaceHandler->replace(textEditor, !shift && !upArrowReplace);
|
updateCount = true;
|
||||||
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;
|
requestFocusReplace = true;
|
||||||
|
findReplaceHandler->setReplaceWord(replaceWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestFocus || requestFocusReplace) {
|
if (requestFocus || requestFocusReplace) {
|
||||||
@@ -947,6 +947,31 @@ namespace hex::plugin::builtin {
|
|||||||
requestFocusFind = true;
|
requestFocusFind = true;
|
||||||
enterPressedFind = false;
|
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
|
// Escape key to close the popup
|
||||||
if (ImGui::IsKeyPressed(ImGuiKey_Escape, false)) {
|
if (ImGui::IsKeyPressed(ImGuiKey_Escape, false)) {
|
||||||
@@ -1045,10 +1070,6 @@ namespace hex::plugin::builtin {
|
|||||||
m_consoleEditor.get(provider).clearRaiseContextMenu();
|
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) {
|
if (m_consoleNeedsUpdate) {
|
||||||
std::scoped_lock lock(m_logMutex);
|
std::scoped_lock lock(m_logMutex);
|
||||||
@@ -1352,7 +1373,7 @@ namespace hex::plugin::builtin {
|
|||||||
auto source = error.getLocation().source;
|
auto source = error.getLocation().source;
|
||||||
if (source != nullptr && source->mainSource) {
|
if (source != nullptr && source->mainSource) {
|
||||||
auto key = ui::TextEditor::Coordinates(error.getLocation().line, error.getLocation().column);
|
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()));
|
errorMarkers[key] = std::make_pair(u32(error.getLocation().length), processMessage(error.getMessage()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1679,6 +1700,9 @@ namespace hex::plugin::builtin {
|
|||||||
EventHighlightingChanged::post();
|
EventHighlightingChanged::post();
|
||||||
|
|
||||||
TaskManager::createTask("hex.builtin.view.pattern_editor.evaluating", TaskManager::NoProgress, [this, code, provider](auto &task) {
|
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 runtimeLock = std::scoped_lock(ContentRegistry::PatternLanguage::getRuntimeLock());
|
||||||
|
|
||||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||||
@@ -1836,31 +1860,30 @@ namespace hex::plugin::builtin {
|
|||||||
EventProviderChanged::subscribe(this, [this](prv::Provider *oldProvider, prv::Provider *newProvider) {
|
EventProviderChanged::subscribe(this, [this](prv::Provider *oldProvider, prv::Provider *newProvider) {
|
||||||
if (oldProvider != nullptr) {
|
if (oldProvider != nullptr) {
|
||||||
m_sourceCode.get(oldProvider) = m_textEditor.get(oldProvider).getText();
|
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_cursorPosition.get(oldProvider) = m_textEditor.get(oldProvider).getCursorPosition();
|
||||||
m_selection.get(oldProvider) = m_textEditor.get(oldProvider).getSelection();
|
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_consoleCursorPosition.get(oldProvider) = m_consoleEditor.get(oldProvider).getCursorPosition();
|
||||||
m_consoleSelection.get(oldProvider) = m_consoleEditor.get(oldProvider).getSelection();
|
m_consoleSelection.get(oldProvider) = m_consoleEditor.get(oldProvider).getSelection();
|
||||||
m_consoleLongestLineLength.get(oldProvider) = m_consoleEditor.get(oldProvider).getLongestLineLength();
|
m_consoleLongestLineLength.get(oldProvider) = m_consoleEditor.get(oldProvider).getLongestLineLength();
|
||||||
m_breakpoints.get(oldProvider) = m_textEditor.get(oldProvider).getBreakpoints();
|
m_consoleScroll.get(oldProvider) = m_consoleEditor.get(oldProvider).getScroll();
|
||||||
m_cursorNeedsUpdate.get(oldProvider) = false;
|
|
||||||
m_consoleCursorNeedsUpdate.get(oldProvider) = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newProvider != nullptr) {
|
if (newProvider != nullptr) {
|
||||||
m_textEditor.get(newProvider).setText(wolv::util::preprocessText(m_sourceCode.get(newProvider)));
|
m_textEditor.get(newProvider).setText(wolv::util::preprocessText(m_sourceCode.get(newProvider)));
|
||||||
m_textEditor.get(newProvider).setCursorPosition(m_cursorPosition.get(newProvider));
|
m_textEditor.get(newProvider).setCursorPosition(m_cursorPosition.get(newProvider),false);
|
||||||
ui::TextEditor::Selection selection = m_selection.get(newProvider);
|
m_textEditor.get(newProvider).setScroll(m_scroll.get(newProvider));
|
||||||
m_textEditor.get(newProvider).setSelection(selection);
|
m_textEditor.get(newProvider).setSelection(m_selection.get(newProvider));
|
||||||
m_textEditor.get(newProvider).setBreakpoints(m_breakpoints.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).setText(wolv::util::combineStrings(m_console.get(newProvider), "\n"));
|
||||||
m_consoleEditor.get(newProvider).setCursorPosition(m_consoleCursorPosition.get(newProvider));
|
m_consoleEditor.get(newProvider).setCursorPosition(m_consoleCursorPosition.get(newProvider));
|
||||||
m_consoleEditor.get(newProvider).setLongestLineLength(m_consoleLongestLineLength.get(newProvider));
|
m_consoleEditor.get(newProvider).setLongestLineLength(m_consoleLongestLineLength.get(newProvider));
|
||||||
selection = m_consoleSelection.get(newProvider);
|
m_consoleEditor.get(newProvider).setSelection(m_consoleSelection.get(newProvider));
|
||||||
m_consoleEditor.get(newProvider).setSelection(selection);
|
m_consoleEditor.get(newProvider).setScroll(m_consoleScroll.get(newProvider));
|
||||||
m_cursorNeedsUpdate.get(newProvider) = true;
|
|
||||||
m_consoleCursorNeedsUpdate.get(newProvider) = true;
|
|
||||||
m_textEditor.get(newProvider).setTextChanged(false);
|
|
||||||
m_hasUnevaluatedChanges.get(newProvider) = true;
|
|
||||||
}
|
}
|
||||||
m_textHighlighter.m_needsToUpdateColors = false;
|
m_textHighlighter.m_needsToUpdateColors = false;
|
||||||
|
|
||||||
@@ -1959,7 +1982,7 @@ namespace hex::plugin::builtin {
|
|||||||
ui::TextEditor::FindReplaceHandler *findReplaceHandler = editor->getFindReplaceHandler();
|
ui::TextEditor::FindReplaceHandler *findReplaceHandler = editor->getFindReplaceHandler();
|
||||||
findReplaceHandler->findMatch(editor, 1);
|
findReplaceHandler->findMatch(editor, 1);
|
||||||
} else {
|
} else {
|
||||||
m_textEditor->getFindReplaceHandler()->findMatch(&*m_textEditor, 1);
|
m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->findMatch(&m_textEditor.get(ImHexApi::Provider::get()), 1);
|
||||||
}
|
}
|
||||||
}, [this] {
|
}, [this] {
|
||||||
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr) {
|
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr) {
|
||||||
@@ -1977,11 +2000,11 @@ namespace hex::plugin::builtin {
|
|||||||
ui::TextEditor::FindReplaceHandler *findReplaceHandler = editor->getFindReplaceHandler();
|
ui::TextEditor::FindReplaceHandler *findReplaceHandler = editor->getFindReplaceHandler();
|
||||||
findReplaceHandler->findMatch(editor, -1);
|
findReplaceHandler->findMatch(editor, -1);
|
||||||
} else {
|
} else {
|
||||||
m_textEditor->getFindReplaceHandler()->findMatch(&*m_textEditor, -1);
|
m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->findMatch(&m_textEditor.get(ImHexApi::Provider::get()), -1);
|
||||||
}
|
}
|
||||||
}, [this] {
|
}, [this] {
|
||||||
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr) {
|
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 {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1998,22 +2021,22 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
/* Replace Next */
|
/* Replace Next */
|
||||||
ContentRegistry::UserInterface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.view.pattern_editor.menu.replace_next" }, 1550, Shortcut::None, [this] {
|
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);
|
m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->replace(&m_textEditor.get(ImHexApi::Provider::get()), true);
|
||||||
}, [this] { return ImHexApi::Provider::isValid() && !m_textEditor->getFindReplaceHandler()->getReplaceWord().empty() && m_focusedSubWindowName.contains(TextEditorView); },
|
}, [this] { return ImHexApi::Provider::isValid() && !m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->getReplaceWord().empty() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||||
[]{ return false; },
|
[]{ return false; },
|
||||||
this);
|
this);
|
||||||
|
|
||||||
/* Replace Previous */
|
/* Replace Previous */
|
||||||
ContentRegistry::UserInterface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.view.pattern_editor.menu.replace_previous" }, 1560, Shortcut::None, [this] {
|
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);
|
m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->replace(&m_textEditor.get(ImHexApi::Provider::get()), false);
|
||||||
}, [this] { return ImHexApi::Provider::isValid() && !m_textEditor->getFindReplaceHandler()->getReplaceWord().empty() && m_focusedSubWindowName.contains(TextEditorView); },
|
}, [this] { return ImHexApi::Provider::isValid() && !m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->getReplaceWord().empty() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||||
[]{ return false; },
|
[]{ return false; },
|
||||||
this);
|
this);
|
||||||
|
|
||||||
/* Replace All */
|
/* 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] {
|
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);
|
m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->replaceAll(&m_textEditor.get(ImHexApi::Provider::get()));
|
||||||
}, [this] { return ImHexApi::Provider::isValid() && !m_textEditor->getFindReplaceHandler()->getReplaceWord().empty() && m_focusedSubWindowName.contains(TextEditorView); },
|
}, [this] { return ImHexApi::Provider::isValid() && !m_textEditor.get(ImHexApi::Provider::get()).getFindReplaceHandler()->getReplaceWord().empty() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||||
this);
|
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] {
|
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);
|
savePatternAsNewFile(false);
|
||||||
}, [this] {
|
}, [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 */
|
/* 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] {
|
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();
|
m_textEditor.get(ImHexApi::Provider::get()).undo();
|
||||||
}, [this] { return ImHexApi::Provider::isValid() && m_textEditor->canUndo() && m_focusedSubWindowName.contains(TextEditorView); },
|
}, [this] { return ImHexApi::Provider::isValid() && m_textEditor.get(ImHexApi::Provider::get()).canUndo() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||||
this);
|
this);
|
||||||
|
|
||||||
/* Redo */
|
/* 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] {
|
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();
|
m_textEditor.get(ImHexApi::Provider::get()).redo();
|
||||||
}, [this] { return ImHexApi::Provider::isValid() && m_textEditor->canRedo() && m_focusedSubWindowName.contains(TextEditorView); },
|
}, [this] { return ImHexApi::Provider::isValid() && m_textEditor.get(ImHexApi::Provider::get()).canRedo() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||||
this);
|
this);
|
||||||
|
|
||||||
ContentRegistry::UserInterface::addMenuItemSeparator({ "hex.builtin.menu.edit" }, 1280, this);
|
ContentRegistry::UserInterface::addMenuItemSeparator({ "hex.builtin.menu.edit" }, 1280, this);
|
||||||
@@ -2052,8 +2075,8 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
/* Cut */
|
/* 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] {
|
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();
|
m_textEditor.get(ImHexApi::Provider::get()).cut();
|
||||||
}, [this] { return ImHexApi::Provider::isValid() && m_textEditor->hasSelection() && m_focusedSubWindowName.contains(TextEditorView); },
|
}, [this] { return ImHexApi::Provider::isValid() && m_textEditor.get(ImHexApi::Provider::get()).hasSelection() && m_focusedSubWindowName.contains(TextEditorView); },
|
||||||
this);
|
this);
|
||||||
|
|
||||||
/* Copy */
|
/* Copy */
|
||||||
@@ -2061,7 +2084,7 @@ namespace hex::plugin::builtin {
|
|||||||
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr) {
|
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr) {
|
||||||
editor->copy();
|
editor->copy();
|
||||||
} else {
|
} else {
|
||||||
m_textEditor->copy();
|
m_textEditor.get(ImHexApi::Provider::get()).copy();
|
||||||
}
|
}
|
||||||
}, [this] {
|
}, [this] {
|
||||||
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
|
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
|
||||||
@@ -2073,7 +2096,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
/* Paste */
|
/* 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] {
|
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] { return m_focusedSubWindowName.contains(TextEditorView); },
|
||||||
this);
|
this);
|
||||||
|
|
||||||
@@ -2089,7 +2112,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
/* Add Breakpoint */
|
/* 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] {
|
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();
|
const auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||||
|
|
||||||
auto &evaluator = runtime.getInternals().evaluator;
|
auto &evaluator = runtime.getInternals().evaluator;
|
||||||
@@ -2618,7 +2641,7 @@ namespace hex::plugin::builtin {
|
|||||||
if (provider == nullptr)
|
if (provider == nullptr)
|
||||||
return;
|
return;
|
||||||
auto path = m_changeTracker.get(provider).getPath();
|
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 (file.isValid() && trackFile) {
|
||||||
if (isPatternDirty(provider)) {
|
if (isPatternDirty(provider)) {
|
||||||
file.writeString(wolv::util::trim(m_textEditor.get(provider).getText()));
|
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