Compare commits

..

485 Commits

Author SHA1 Message Date
WerWolv
810955b1be fix: Start fixing shortcuts on welcome screen. Breaks certain shortcuts still 2026-01-23 00:07:34 +01:00
WerWolv
96a5a5d34c build: Output error message if capstone version is too low 2026-01-22 21:22:42 +01:00
WerWolv
928e0f227a fix: Banner tooltip text not being visible properly 2026-01-19 22:25:51 +01:00
WerWolv
93fc6f2de1 patterns: Update pattern language 2026-01-19 22:25:51 +01:00
iTrooz
cdc260b45c doc: add instructions to use ImHex on macOS without a GPU 2026-01-19 18:00:34 +01:00
WerWolv
0e41813cfc fix: [[format_write]] attribute not working as expected on integer and floating point types 2026-01-18 21:56:09 +01:00
WerWolv
a7e94e31c9 build: Update libwolv 2026-01-18 14:31:21 +01:00
WerWolv
2903a97941 build: Make people Acknowledge the GPLv2 in the Windows installer instead of accepting it 2026-01-18 11:32:35 +01:00
WerWolv
753e1ceff6 build: Allow MSI installer to downgrade installations 2026-01-17 21:47:11 +01:00
WerWolvTranslationBot
06f4d12f10 lang: Translations update from Weblate (#2621)
Translations update from [Weblate](https://weblate.werwolv.net) for
[ImHex/Builtin](https://weblate.werwolv.net/projects/imhex/builtin/).


It also includes following components:

* [ImHex/Diffing](https://weblate.werwolv.net/projects/imhex/diffing/)

* [ImHex/UI](https://weblate.werwolv.net/projects/imhex/ui/)

* [ImHex/Fonts](https://weblate.werwolv.net/projects/imhex/fonts/)

*
[ImHex/Disassembler](https://weblate.werwolv.net/projects/imhex/disassembler/)

* [ImHex/Hashes](https://weblate.werwolv.net/projects/imhex/hashes/)

* [ImHex/Remote](https://weblate.werwolv.net/projects/imhex/remote/)

* [ImHex/Script
Loader](https://weblate.werwolv.net/projects/imhex/script-loader/)

*
[ImHex/Visualizers](https://weblate.werwolv.net/projects/imhex/visualizers/)

* [ImHex/Yara
Rules](https://weblate.werwolv.net/projects/imhex/yara-rules/)

* [ImHex/Windows](https://weblate.werwolv.net/projects/imhex/windows/)



Current translation status:

![Weblate translation
status](https://weblate.werwolv.net/widgets/imhex/-/builtin/horizontal-auto.svg)

Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Rutar Andriy <RutarAndriy@gmail.com>
Co-authored-by: Yaroslav <mrikso821@gmail.com>
2026-01-17 21:45:41 +01:00
WerWolv
684c2e66fb fix: Ranges are still not available everywhere 2026-01-17 21:13:04 +01:00
WerWolv
4a311ed69f fix: Multiple issues with undo/redo stack handling 2026-01-17 21:03:36 +01:00
WerWolv
220b5f9772 patterns: Update pattern language 2026-01-15 20:47:29 +01:00
WerWolv
42fd5b0fef patterns: Update pattern language 2026-01-15 20:39:04 +01:00
WerWolv
c28492e51d fix: GLFW version check 2026-01-13 18:22:06 +01:00
WerWolv
d8ff84672c fix: Gate Wayland check to good distros that update their dependencies 2026-01-13 18:09:21 +01:00
WerWolv
2af967d788 fix: Window auto-maximizing on Wayland 2026-01-13 18:02:48 +01:00
WerWolv
8cb23e8200 build: Don't build test engine if it's disabled 2026-01-13 18:02:27 +01:00
WerWolvTranslationBot
9a058efc79 lang: Translations update from Weblate (#2553)
Translations update from [Weblate](https://weblate.werwolv.net) for
[ImHex/Builtin](https://weblate.werwolv.net/projects/imhex/builtin/).


It also includes following components:

* [ImHex/Diffing](https://weblate.werwolv.net/projects/imhex/diffing/)

* [ImHex/UI](https://weblate.werwolv.net/projects/imhex/ui/)

*
[ImHex/Disassembler](https://weblate.werwolv.net/projects/imhex/disassembler/)

* [ImHex/Yara
Rules](https://weblate.werwolv.net/projects/imhex/yara-rules/)

* [ImHex/Fonts](https://weblate.werwolv.net/projects/imhex/fonts/)

* [ImHex/Hashes](https://weblate.werwolv.net/projects/imhex/hashes/)

* [ImHex/Remote](https://weblate.werwolv.net/projects/imhex/remote/)

* [ImHex/Script
Loader](https://weblate.werwolv.net/projects/imhex/script-loader/)

*
[ImHex/Visualizers](https://weblate.werwolv.net/projects/imhex/visualizers/)

* [ImHex/Windows](https://weblate.werwolv.net/projects/imhex/windows/)



Current translation status:

![Weblate translation
status](https://weblate.werwolv.net/widgets/imhex/-/builtin/horizontal-auto.svg)

Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: MrClock <mrclock8163@gmail.com>
2026-01-12 23:26:15 +01:00
WerWolv
06c8cb51e3 web: Handle partial page resizes better 2026-01-12 22:59:18 +01:00
WerWolv
01e8ae1b5c ci: Don't upload docker build record as artifact 2026-01-12 22:59:18 +01:00
WerWolv
b052cb001c web: Make sure canvas gets resized after the first frame 2026-01-12 22:59:18 +01:00
WerWolv
d004eb3048 fix: Occasional crash on Linux when closing task manager 2026-01-12 20:43:01 +01:00
WerWolv
dccd74667e fix: Texture ids not getting reset correctly in destructor 2026-01-12 20:42:23 +01:00
WerWolv
6b6470850f ci: Make sure folder exists before copying files 2026-01-11 10:12:28 +01:00
WerWolv
f09b1aae23 ci: Fix artifact names 2026-01-11 09:52:34 +01:00
WerWolv
68487bc903 web: Fix meta tags and social preview image 2026-01-10 21:43:45 +01:00
WerWolv
ebd78e1526 ci: Update github pages deployment name 2026-01-10 14:28:07 +01:00
WerWolv
6d0dfcfe2e fix: Does WebGL use GLES2 after all? 2026-01-10 14:15:56 +01:00
WerWolv
5b01d23ed7 ci: Make docker image deploy only run after build 2026-01-10 14:12:02 +01:00
WerWolv
d9eb01b526 build: Deploy ImHex-Web as a docker image 2026-01-10 14:09:58 +01:00
WerWolv
9e165ac4a1 impr: Add more broader support for GLES3
Closes #2608
2026-01-10 11:49:58 +01:00
Nik
25ab371a81 git: Fix macOS packaging job name 2026-01-09 21:04:27 +01:00
Nik
d62abaed8d build: Add support for x86 macOS 10.15 and ARM64 macOS 11.0 (#2607)
This PR drops the use of brew for dependency management in favor of
macports so we can support lower macOS versions instead of just the
lowest one supported by Apple

Closes #2586
2026-01-09 17:42:51 +01:00
iTrooz
1fb7a318ed chore: remove jthread added inadvertently 2026-01-09 16:49:43 +01:00
iTrooz
e29ae631fc ci: always take artifacts from master branch in nightly release 2026-01-09 16:43:18 +01:00
WerWolv
3cc0b9294e web: Fix flickering on resize 2026-01-08 21:45:36 +01:00
WerWolv
e80f7fa14f git: Properly define env var for dispatch key 2026-01-08 20:37:35 +01:00
WerWolv
9261fd7190 git: Fix dispatch never running 2026-01-08 20:29:20 +01:00
WerWolv
58c714b350 git: Switch to repository dispatch for updating website 2026-01-08 20:05:41 +01:00
WerWolv
5cd3f5c255 git: Fix permissions again 2026-01-08 19:42:47 +01:00
WerWolv
0d443d7d00 git: Fix permissions on nightly CI 2026-01-08 19:20:13 +01:00
WerWolv
38fecca489 git: Fix nightly CI 2026-01-08 17:53:44 +01:00
WerWolv
f655ea59a8 git: Update new ImHex website during nightly 2026-01-07 23:18:06 +01:00
WerWolv
aa7daa5c54 web: Disable splash screen 2026-01-07 23:09:07 +01:00
WerWolv
f4b2be9334 chore: Cleanup logs slightly 2026-01-07 21:27:41 +01:00
WerWolv
edbd8a811e fix: Just detach stdin/stdout redirect threads as the program will exit immediately afterwards
(cherry picked from commit aeb58b5e9c3eef9f26fde104a2adc2684423b8ac)
2026-01-07 18:32:16 +01:00
Alex
ea9b197d36 build: improve FindMagic.cmake module (#2610)
Now it properly fails if libmagic is not installed in the system.

The error message would look like:

```
CMake Error at cmake/modules/FindPackageHandleStandardArgs.cmake:230 (message):
  Could NOT find Magic (missing: LIBMAGIC_LIBRARY LIBMAGIC_INCLUDE_DIR)
  (Required is at least version "5.39")
Call Stack (most recent call first):
  cmake/modules/FindPackageHandleStandardArgs.cmake:600 (_FPHSA_FAILURE_MESSAGE)
  cmake/modules/FindMagic.cmake:5 (find_package_handle_standard_args)
  cmake/build_helpers.cmake:971 (find_package)
  CMakeLists.txt:81 (addBundledLibraries)
```

### Problem description

The current `FindMagic.cmake` module doesn't properly report failure
about absent libmagic libs and #includes. This behavior leads to the
compile errors on the build stage (possibly after some time, which will
be simply wasted). This Find module should set the `Magic_FOUND`
variable and handle all required variables( LIBMAGIC_INCLUDE_DIR and
LIBMAGIC_LIBRARY) to present.
But the current module sets the `libmagic_FOUND` variable, so the CMake
assumes that it is found something. This behaviour should also be
handled by `find_package_handle_standard_args()` ("FPHSA"), and it is
actually handled, but as we requested the `Magic` package to be
required, the former function ("FPHSA") didn't stop the configure
process.

### Implementation description
 - Clean up the unused ifs, as "FPHSA" already done it better.
- Use the proper name for "FPHSA" so it could set the proper
`Magic_FOUND` and could make sure that the requested package is
`REQUIRED`.

### Screenshots
Before:
```
-- Could NOT find libmagic (missing: LIBMAGIC_LIBRARY LIBMAGIC_INCLUDE_DIR)
```

<img width="1005" height="24" alt="изображение"
src="https://github.com/user-attachments/assets/082e2842-ff94-4418-8f86-86021c7dd23d"
/>

After:

```
CMake Error at cmake/modules/FindPackageHandleStandardArgs.cmake:230 (message):
  Could NOT find Magic (missing: LIBMAGIC_LIBRARY LIBMAGIC_INCLUDE_DIR)
  (Required is at least version "5.39")
Call Stack (most recent call first):
  cmake/modules/FindPackageHandleStandardArgs.cmake:600 (_FPHSA_FAILURE_MESSAGE)
  cmake/modules/FindMagic.cmake:5 (find_package_handle_standard_args)
  cmake/build_helpers.cmake:971 (find_package)
  CMakeLists.txt:81 (addBundledLibraries)
```

### Additional things

Closes #2244 .
2026-01-07 17:13:41 +01:00
WerWolv
a0a049a920 fix: ImHex not always exiting when forwarder is killed 2026-01-07 17:12:58 +01:00
WerWolv
550fe8e4aa impr: Add MCP Client information to footer icon tooltip 2026-01-07 17:12:40 +01:00
WerWolv
2064aea3b6 fix: ImHex processes getting stuck in the background
Fixes #2611
2026-01-07 17:12:17 +01:00
WerWolv
3411bc4577 fix: Unused variable 2026-01-07 11:13:52 +01:00
WerWolv
6eedb469e9 fix: Notifications on Web build causing exceptions 2026-01-07 09:45:30 +01:00
WerWolv
684373b88b fix: Properly forward stdin to main process from forwarder
(cherry picked from commit 1fc857cf7d2a9a525dec5fcda0727a39046b6c86)
2026-01-07 09:45:30 +01:00
iTrooz
08aa03bab6 chore: remove unused steps from nightly release CI 2026-01-06 21:05:52 +01:00
iTrooz
62bc953d53 ci: remove unused permissions to webassembly-build job 2026-01-06 09:28:20 +01:00
iTrooz
5263f81487 ci: do not give pages write permission to webassembly-build job 2026-01-06 09:23:30 +01:00
iTrooz
8272ebf68f ci: use gh CLI to download artifact instead of third party action 2026-01-06 09:13:47 +01:00
paxcut
90d8e03f2c Fixes by @AkiSakurai for bug thats caused crashing ImHex when creating recursive inheritances. (#2612)
The previous code I approved was wrong and caused ImHex to grow until
computer froze. This PR is a copy of the original fix in PR #2546 by
@AkiSakurai
2026-01-05 16:57:04 -07:00
iTrooz
0d34edc7f6 ci: replace artifact deletion action with custom script 2026-01-05 16:36:30 +01:00
Aki Sakurai
63fd61e245 Fix crash in Pattern Language syntax highlighting for self-inheriting structs (#2546)
``` rust
struct Rec : Rec {
};
```

Prevent infinite recursion in appendInheritances by erasing processed
inheritance entries during traversal, and safely iterate over
m_inheritances in appendInheritances to avoid
modification-during-iteration issues.

Co-authored-by: paxcut <53811119+paxcut@users.noreply.github.com>
2026-01-05 03:11:21 -07:00
iTrooz
58fe8a22a9 ci: use hendrikmuhs/ccache-action@v1, not @main 2026-01-05 08:21:21 +01:00
WerWolv
03dd20c263 web: Fix canvas size issues when zooming page 2026-01-04 11:07:17 +01:00
WerWolv
712a125be7 fix: listxattrs signature being different between Linux and macOS 2026-01-03 23:52:42 +01:00
WerWolv
49e14e6e7c build: Update dependencies 2026-01-03 22:44:46 +01:00
WerWolv
e8a6e102c3 feat: Add xatts to file info display 2026-01-03 22:43:34 +01:00
WerWolv
b2cc09852d fix: Weirdly worded pattern editor help message 2026-01-03 22:40:45 +01:00
WerWolv
60627b8325 impr: Only add pattern editor help text to first opened data source 2026-01-03 22:38:36 +01:00
WerWolv
8fc2d6b225 impr: Disable exception wrapping as it causes a lot of slowdowns 2026-01-03 20:41:17 +01:00
WerWolv
051cdfa305 fix: Error message rendering of visualizers 2026-01-03 13:27:52 +01:00
WerWolv
bfa807ca8b feat: Add data inspector option to reverse bit order 2026-01-03 12:04:51 +01:00
WerWolv
598914a67a fix: Windows notifications filling up tray area 2026-01-03 11:04:33 +01:00
WerWolv
3274649b77 fix: Task finished notification showing up regardless of focus state on Windows 2026-01-03 10:48:46 +01:00
paxcut
5756105347 fix: Text highlighter crash (#2595)
The assumption that the number of lines of colors will be equal to the
number of lines in the input signal is incorrect. As issue #2594 shows,
erroneous input can cause the lexer to end processing the input file
prematurely thus being unable to create tokens past the line where the
error occurred which in turn implies that no colors can be found beyond
those lines.

To fix the crash (the underlying problem is user caused and can't be
fixed) is to use the size of the vectors containing the first token
index of each line since that size must be equal to the number of lines
stored in token sequence.

Fixes #2594
2026-01-02 16:04:35 +01:00
paxcut
ed583d8bd1 fix: Division by zero in sound visualizer. (#2593)
Can happen if input is less than 2400*channels number of points. The fix
is detecting it and throwing an error.
2026-01-02 16:03:52 +01:00
WerWolv
731cf10207 fix: Goto setting hex editor scroll position to imprecise value for large addresses
#2599
2026-01-02 15:36:32 +01:00
iTrooz
cb898ce8cf ci: remove Fedora 41, 42 builds and AlmaLinux 9 2026-01-01 18:27:34 +01:00
iTrooz
892334e31a ci: update workflow to manually download cache key 2026-01-01 16:34:52 +01:00
iTrooz
a16e16853f ci: add workflow to manually download cache key 2026-01-01 02:08:52 +01:00
WerWolv
5cec83b3ef web: Render at higher resolution 2025-12-30 19:38:38 +01:00
WerWolv
a628784c6d fix: Empty entry showing up in main menu bar 2025-12-30 19:12:17 +01:00
WerWolv
fd8b70fb12 fix: Settings not always applying correctly 2025-12-30 19:12:00 +01:00
WerWolv
3dad5a43a1 web: Resize canvas right away 2025-12-30 19:11:33 +01:00
WerWolv
89dea86b3b web: Fix canvas being too big 2025-12-30 18:28:26 +01:00
WerWolv
42da24e31d patterns: Update pattern language
Fixes #2589
2025-12-30 14:51:10 +01:00
WerWolv
5b9b5d4f1f fix: Another use of ssize_t 2025-12-30 14:35:56 +01:00
paxcut
5332a26294 fixing isEmpty again. (#2591)
hopefully the last time.
2025-12-30 06:08:18 -07:00
WerWolv
54d9f8ec5c fix: Build on MSVC, properly handle empty files 2025-12-30 10:30:14 +01:00
WerWolv
73a17308cc feat: Allow opening special files with no specific size 2025-12-30 09:34:45 +01:00
paxcut
b835c48a0c fix: Unable to delete empty lines in text editor (#2588)
fixes for issue #2587
2025-12-29 20:01:26 +01:00
WerWolv
40b604c6e4 fix: ImGui-internal shortcuts not working correctly with native macOS menu bar enabled
(cherry picked from commit f0f6a22391)
2025-12-29 19:32:25 +01:00
WerWolv
1fd3580f97 web: Let ImHex Web run more standalone
(cherry picked from commit f76ea2a677)
2025-12-29 19:32:25 +01:00
WerWolv
e28f3b75a4 fix: Make sure updater properly exists after launching update process 2025-12-29 13:35:44 +01:00
WerWolv
53153ca3e0 fix: Merge messup 2025-12-29 13:27:25 +01:00
WerWolv
a496b14a0f impr: Add setting for task-finish notifications 2025-12-28 18:17:38 +01:00
WerWolv
da6e7240d6 fix: Race condition causing old patterns to stick around in the pattern drawer 2025-12-28 17:46:22 +01:00
WerWolv
89981c6994 git: Add x86_64 to the remaining builds that don't have that specification 2025-12-28 12:52:09 +01:00
WerWolv
fe22a43e09 git: Remove Ubuntu 25.04, add Ubuntu 25.10 and Debian 13 2025-12-28 12:33:53 +01:00
WerWolv
3e1a797ea7 impr: Replace Patreon links with Ko-Fi 2025-12-27 17:36:26 +01:00
WerWolv
b23ce7ba18 impr: Replace achievement icons with font icons 2025-12-27 12:00:58 +01:00
WerWolv
6165f891ca fix: Get rid of std::common_type in settings API 2025-12-27 10:31:28 +01:00
WerWolv
7df4b1157c impr: Make sure all data is received by MCP bridge 2025-12-27 10:21:38 +01:00
paxcut
64cbd5fc8d Make the syntax highlighter more thread safety aware (#2585)
By creating copies of the required inputs on the main thread just before
the task is spawned. A;so if task is still running when new data can be
copied then the task is interrupted thus avoiding concurrency without
mutexes. Atomics are used to signal state information used to determine
what and when to spawn.

Also includes update to pattern editor library and some fixes to syntax
highlighting error when custom types defined inside namespaces were used
inside the namespaces without the full qualified name and other small
changes mostly to improve the current style.
2025-12-26 20:21:19 -07:00
WerWolv
ba7e789a80 feat: Add support for executing patterns using MCP 2025-12-26 22:33:05 +01:00
WerWolv
d6d70ca076 impr: Don't show crash popup when sending ^C to command line 2025-12-26 22:33:05 +01:00
WerWolv
88c37bb7d9 impr: Handle MCP error when no instance of ImHex is running better 2025-12-26 22:33:05 +01:00
WerWolv
59b4f4efce impr: Add abstraction for common variable-saved-as-setting code pattern 2025-12-26 22:33:05 +01:00
Jacques Pienaar
ed1f120b0b build: Remove --no-lock flag from macOS build instructions (#2584)
### Problem description
-no-lock CLI options has been removed
https://github.com/Homebrew/homebrew-bundle/pull/1509.

### Implementation description
Remove flag from invocation.
2025-12-25 21:24:49 +01:00
WerWolv
bf461abfec fix: Invalid toolbar items appearing in the toolbar 2025-12-25 20:12:31 +01:00
WerWolv
d42665db88 fix: Crash on exit 2025-12-25 20:00:17 +01:00
WerWolv
33c4dc3347 impr: Use settings icon as everywhere else for hex editor settings 2025-12-25 20:00:17 +01:00
WerWolv
6d976fb785 fix: Pattern Editor content getting reset to default comment when opening new data source 2025-12-25 20:00:17 +01:00
iTrooz
39b43cec2d fix: correctly compute nameSpace in TextHighlighter::getVariableTypeName() 2025-12-25 18:48:00 +01:00
WerWolv
691b56b4ac impr: Show OS toast popup when a task finishes while ImHex is not focused 2025-12-25 15:34:56 +01:00
WerWolv
bf1f613052 patterns: Update pattern language 2025-12-24 20:20:30 +01:00
WerWolv
721ed9f2a2 patterns: Update pattern language 2025-12-24 17:00:37 +01:00
WerWolv
f760b1ba83 impr: Add help text to MCP server setting 2025-12-24 14:00:26 +01:00
WerWolv
1dba144fca fix: Various warnings related to AutoReset variables 2025-12-23 23:29:59 +01:00
WerWolv
ebc1b531ff fix: Pattern children not getting sorted properly 2025-12-23 23:29:35 +01:00
WerWolv
5ecf122686 fix: Hidden patterns getting used for pattern parent highlighting 2025-12-23 22:38:00 +01:00
WerWolv
56ed18882c patterns: Update pattern language 2025-12-23 22:36:44 +01:00
WerWolv
86c555d053 fix: Theme view not being scrollable anymore 2025-12-23 15:56:54 +01:00
WerWolv
49ec30899e feat: Give macOS window a Liquid Glass look when the background is set to transparent 2025-12-23 15:56:45 +01:00
WerWolv
d4a2b617bd fix: Another MSVC build error 2025-12-23 11:12:20 +01:00
WerWolv
8e7bd4b98a fix: File provider not erroring out correctly when selecting a folder to open 2025-12-23 10:51:52 +01:00
WerWolv
ea359285e0 build: Fix run configuration 2025-12-22 23:08:36 +01:00
WerWolv
d4bfa5d284 build: Generate a macOS bundle by default 2025-12-22 22:57:33 +01:00
WerWolv
4433006842 fix: MSVC build 2025-12-22 18:09:06 +01:00
WerWolv
646ebcdd00 feat: Add create and open options to macOS dock icon context menu 2025-12-22 16:20:23 +01:00
WerWolv
8b53b36b20 fix: Exit code getting in forwarder not working 2025-12-22 12:53:39 +01:00
WerWolv
64db392699 patterns: Update pattern language 2025-12-22 11:12:22 +01:00
WerWolv
bff78704cc fix: Use of non-atomic variables 2025-12-22 11:12:22 +01:00
iTrooz
40651e8dfd chore: update my email 2025-12-21 20:55:57 +01:00
iTrooz
e5d9d9ec9e chore: apply more complicated lints (#2576)
<!--
Please provide as much information as possible about what your PR aims
to do.
PRs with no description will most likely be closed until more
information is provided.
If you're planing on changing fundamental behaviour or add big new
features, please open a GitHub Issue first before starting to work on
it.
If it's not something big and you still want to contact us about it,
feel free to do so !
-->

### Problem description
<!-- Describe the bug that you fixed/feature request that you
implemented, or link to an existing issue describing it -->

### Implementation description
<!-- Explain what you did to correct the problem -->

### Screenshots
<!-- If your change is visual, take a screenshot showing it. Ideally,
make before/after sceenshots -->

### Additional things
<!-- Anything else you would like to say -->
2025-12-21 20:55:50 +01:00
WerWolv
4e628826c3 fix: Forwarder not correctly returning return code on Windows 2025-12-21 20:53:07 +01:00
WerWolv
018bedb2bd patterns: Update pattern language 2025-12-21 20:52:46 +01:00
WerWolv
33e315709a git: Fix AUR release CI not having repo available anymore
(cherry picked from commit 34bc55a648)
2025-12-21 20:10:03 +01:00
WerWolv
8b14a4775b build: Disable ARM msi signing because it doesn't work
(cherry picked from commit 76cf877115)
2025-12-21 20:10:03 +01:00
WerWolv
fa8fdb0170 build: Don't fail release CI if tag is empty
(cherry picked from commit 8e4ccef52f)
2025-12-21 20:10:03 +01:00
WerWolv
f856e16917 fix: Duplicate artifact name in release CI
(cherry picked from commit b78a1024c1)
2025-12-21 20:10:03 +01:00
WerWolv
3b5271ab77 patterns: Update pattern language 2025-12-21 13:02:42 +01:00
WerWolv
428fbddbbb impr: Better updater experience on macOS 2025-12-21 11:47:21 +01:00
WerWolv
5774837a6e fix: Updater architecture check on MSVC 2025-12-21 10:54:14 +01:00
iTrooz
17c2dfcbd0 chore: apply more light lints (#2575)
<!--
Please provide as much information as possible about what your PR aims
to do.
PRs with no description will most likely be closed until more
information is provided.
If you're planing on changing fundamental behaviour or add big new
features, please open a GitHub Issue first before starting to work on
it.
If it's not something big and you still want to contact us about it,
feel free to do so !
-->

### Problem description
<!-- Describe the bug that you fixed/feature request that you
implemented, or link to an existing issue describing it -->

### Implementation description
<!-- Explain what you did to correct the problem -->

### Screenshots
<!-- If your change is visual, take a screenshot showing it. Ideally,
make before/after sceenshots -->

### Additional things
<!-- Anything else you would like to say -->
2025-12-20 15:59:48 +01:00
WerWolv
a1711ccfa6 impr: Added icons to all menu items on macOS 2025-12-20 14:07:31 +01:00
iTrooz
261610dcf1 chore: apply light lints (#2570) 2025-12-19 23:49:37 +01:00
WerWolv
92cfdf1145 fix: Fedora 43 not being updatable
(cherry picked from commit 5a853569e6)
2025-12-19 19:17:13 +01:00
WerWolv
155465b8c6 fix: Linux aarch64 detection in the updater 2025-12-19 18:43:02 +01:00
WerWolv
6f49bbdd41 fix: Updater not detecting architecture on Windows correctly 2025-12-19 18:13:39 +01:00
iTrooz
3badaa5cba ci: cancel old workflows when pushing a new commit 2025-12-19 13:38:17 +01:00
iTrooz
a66747a0d0 ci: build dependencies in different step than configuring cmake (#2574)
<!--
Please provide as much information as possible about what your PR aims
to do.
PRs with no description will most likely be closed until more
information is provided.
If you're planing on changing fundamental behaviour or add big new
features, please open a GitHub Issue first before starting to work on
it.
If it's not something big and you still want to contact us about it,
feel free to do so !
-->

### Problem description
<!-- Describe the bug that you fixed/feature request that you
implemented, or link to an existing issue describing it -->

### Implementation description
<!-- Explain what you did to correct the problem -->

### Screenshots
<!-- If your change is visual, take a screenshot showing it. Ideally,
make before/after sceenshots -->

### Additional things
<!-- Anything else you would like to say -->
2025-12-19 12:26:07 +00:00
iTrooz
c376759be0 chore: update invalid comments in arm64 Dockerfile 2025-12-19 12:19:03 +01:00
iTrooz
1c17f3ee43 fix: DiskProvider::open() default result on Windows (#2573)
<!--
Please provide as much information as possible about what your PR aims
to do.
PRs with no description will most likely be closed until more
information is provided.
If you're planing on changing fundamental behaviour or add big new
features, please open a GitHub Issue first before starting to work on
it.
If it's not something big and you still want to contact us about it,
feel free to do so !
-->

### Problem description
<!-- Describe the bug that you fixed/feature request that you
implemented, or link to an existing issue describing it -->

### Implementation description
<!-- Explain what you did to correct the problem -->

### Screenshots
<!-- If your change is visual, take a screenshot showing it. Ideally,
make before/after sceenshots -->

### Additional things
<!-- Anything else you would like to say -->
2025-12-19 11:12:08 +00:00
paxcut
5f549cc8aa patterns: update pattern language (#2572)
for the ghost break point bug
2025-12-19 03:29:52 -07:00
WerWolv
f97be02087 impr: Added proper cancel buttons to tutorial popups and tutorial selector
Closes #2571
2025-12-19 10:13:48 +01:00
WerWolv
2d82776e62 fix: Disk provider still using old open() api on windows 2025-12-17 23:42:13 +01:00
WerWolv
fdee0ac3e3 fix: Test Provider still using old open function signature 2025-12-17 16:56:55 +01:00
WerWolv
d775b80a44 feat: Add initial MCP commands to query, open select and read data 2025-12-17 16:04:07 +01:00
iTrooz
2047a41498 chore: use cleaner yaml format for clang-tidy 2025-12-17 16:02:06 +01:00
iTrooz
f88890a052 chore: disable all clang-tidy checks in third_party libraries 2025-12-17 16:02:06 +01:00
WerWolv
5500faa57e fix: Inverted logic when opening files from the command line 2025-12-17 13:50:57 +01:00
WerWolv
89004574d3 impr: Handle provider opening more centrally, switch to existing provider if same file is being opened again 2025-12-17 12:55:34 +01:00
iTrooz
c11c05a399 build: do not bundle SDK in snap and flatpak packages (#2567) 2025-12-17 11:31:35 +01:00
WerWolv
baa3329e7f fix: Make sure providers returned by createProvider don't get deleted unexpectedly 2025-12-16 23:36:05 +01:00
WerWolv
e696d384c2 feat: Add initial MCP Server support 2025-12-16 20:25:46 +01:00
WerWolv
932c281223 fix: Pattern files not getting truncated correctly when saving
Fixes #2566
2025-12-16 10:02:10 +01:00
WerWolv
858fe0384e impr: Make most windows non-scrolling by default 2025-12-15 21:06:44 +01:00
WerWolv
e904cd749f fix: Inverted sorting of find view table
Fixes #2564
2025-12-15 20:13:19 +01:00
WerWolv
6b16f39be4 impr: Allow tutorials to use markdown formatted text 2025-12-15 20:07:43 +01:00
WerWolv
021c7e5fdb impr: Add localization option to store long, formatted texts in external files 2025-12-15 20:07:18 +01:00
WerWolv
c161a5c71b fix: Typo in crash popup 2025-12-15 11:31:41 +01:00
WerWolv
76ccdbccea patterns: Update pattern language 2025-12-15 10:10:15 +01:00
WerWolv
553ee89787 fix: Only enable widgets in pattern data view when there's actually any patterns available 2025-12-15 10:00:29 +01:00
WerWolv
cb6247b16e fix: Crash when using @ command palette command
Fixes #2563
2025-12-15 09:52:44 +01:00
WerWolv
cfac7ff0ba impr: Unionize exception and assertion handling 2025-12-15 09:52:13 +01:00
iTrooz
49bbe7dc77 build: remove IMHEX_PLUGINS_IN_SHARE option + only allow AppImage to load plugins from inside itself
Rationale: The `IMHEX_PLUGINS_IN_SHARE` is a hack to prevent the appimage from loading plugin from system imhex installation, like /usr/lib/imhex/

In reality, I do not think people compile plugins specifically for the AppImage (plugins must be compiled for the specific imhex & compiler version the imhex binary is used), and this lets us remove the hack
2025-12-14 18:29:00 +01:00
iTrooz
07b6fa0e2e build(web): add BUILD_TYPE arg to Dockerfile 2025-12-14 15:02:46 +01:00
iTrooz
67396f2009 chore: fix web Dockerfile ARG syntax 2025-12-14 15:02:46 +01:00
iTrooz
a20ff87cc9 chore: update comment 2025-12-14 15:02:46 +01:00
iTrooz
e02e57a729 chore: remove version attribute from web compose.yaml 2025-12-14 14:19:15 +01:00
iTrooz
225dc53795 build(appimage): use https when querying repos 2025-12-14 02:02:40 +01:00
iTrooz
e7404376db build: do not bundle plugin SDK in AppImage 2025-12-14 01:55:57 +01:00
iTrooz
d6aec341fe build(web): make a shallow clone of vcpkg 2025-12-14 01:43:40 +01:00
iTrooz
3a3c2fb204 build: add defaults to AppImage build for x86 2025-12-14 00:45:56 +01:00
iTrooz
e9b5cdbccf build: fix IMHEX_INCLUDE_PLUGINS defined check 2025-12-14 00:15:08 +01:00
iTrooz
3f30e63d95 chore(web): allow nginx to access files in development docker image 2025-12-14 00:08:11 +01:00
iTrooz
f9c6866c7b build: require all plugins that builtint depends on to be present 2025-12-13 23:54:58 +01:00
iTrooz
388dccfd9f chore: organise cmake build flags 2025-12-13 23:46:13 +01:00
paxcut
1676342e28 Various fixes for pattern editor (#2561)
- Fix for vertical scroll bar being too far to the left.
- Fix constructor not initializing from const char pointer properly
- maxcolumn not being set for console text lines causing crashes on
empty pattern evaluation
- A replacement using replace all is now undone in one step.
- Find/replace no longer need to have enter or return key to accept
text. You can use arrows or shortcuts.
- More efficient search replace implementation with plans to add even
faster.
- Tooltips added to find/replace window
- Providers now save both horizontal and vertical scroll positions when
switching to another one and restore them when switching back. This is
independent to the cursor position which is also saved.
- Pattern editor no longer takes focus when changing providers via a tab
click. This has the effect that menus won't change by just clicking on a
tab.
- Small fixes and code refactoring.
2025-12-13 05:23:16 -07:00
WerWolv
62732de227 fix: Gaps in-between hex editor highlighting on specific scalings 2025-12-12 22:04:15 +01:00
WerWolv
63e777c84c impr: Intercept glibc++ assertion handler 2025-12-12 22:02:56 +01:00
WerWolv
ab95cdf3e5 fix: Minimap not allowing scrolling as far as the scroll bar 2025-12-12 17:19:57 +01:00
WerWolv
827b5b01dd patterns: Update pattern language 2025-12-12 16:57:20 +01:00
paxcut
bfa9788099 impr: Various fixes and improvements to the pattern editor (#2559)
- fixed crash when utf8 chars were present in text editor
- fixed unable to scroll when cursor at line 1
- removed dependencies on thext editor that were not being used.

I had to go back to the old code (old for me) and fit in the changes
that were applied to the new code.That was only possible by
incorporating some of the new structural differences to the text editor.
This created new bugs and crashes that I ve have fixed but there may be
ones that I couldn't find in the very small amount of time I could spend
testing so that this commit wouldn't be delayed. If more crashes are
found due to the mixing of old and new code they should be resolved when
the new code is brought in.
2025-12-12 16:27:26 +01:00
WerWolv
de25ce7fbb feat: Add support for custom inspector edit widgets 2025-12-12 13:15:16 +01:00
WerWolv
21e61bfce6 fix: Extended ASCII display being enabled by default 2025-12-12 13:14:49 +01:00
WerWolv
82e168c438 build: Update libwolv 2025-12-12 13:14:27 +01:00
WerWolv
48583a2b6e build: Go back to WiX 4 again for ARM64 support 2025-12-11 23:41:37 +01:00
WerWolv
0db0982fa7 build: Update dependencies 2025-12-11 23:15:13 +01:00
WerWolv
6a28ce9e4b fix: Wrong variable access 2025-12-11 21:32:18 +01:00
WerWolv
1db79f6117 feat: Add command line arguments to process tooltips, exclude kthreads on Linux
Fixes #2558
2025-12-11 17:09:26 +01:00
WerWolv
f234103320 fix: Off-by-one of starts of process memory regions 2025-12-11 16:27:36 +01:00
WerWolv
45c382a19a fix: Auto backup localization key names 2025-12-11 16:27:13 +01:00
WerWolv
fb7ef61d06 fix: Crash when canceling creation of SSH provider
Fixes #2557
2025-12-11 16:24:43 +01:00
WerWolv
2586645d02 build: Force-set REINSTALLMODE=amus for WiX installer 2025-12-11 12:34:29 +01:00
WerWolv
e23cb5509d build: Use WiX 3 for packaging 2025-12-11 11:13:26 +01:00
WerWolv
5cbd53ae7a build: Fix version stripping issues 2025-12-09 21:58:29 +01:00
WerWolv
a4ee590875 build: Only build the version stripper on mingw 2025-12-09 21:31:50 +01:00
WerWolv
495608ed7c build: Force-remove all version information from libwinpthread 2025-12-09 21:25:35 +01:00
WerWolv
4d10d9a195 build: Manually set FILEVERSION of libwinpthread to 0.0.0.0
#2550
2025-12-08 23:54:33 +01:00
WerWolv
4914a34dd9 build: Fix WiX patch 2025-12-08 21:26:18 +01:00
WerWolv
ab0fb3131d fix: Reset selected row after checking it 2025-12-08 21:10:49 +01:00
WerWolv
7922d3b3cb build: Try to force-overwrite libwinpthread 2025-12-08 18:17:33 +01:00
WerWolv
6427f53b5a feat: Add endian option to Sum hash 2025-12-07 22:18:34 +01:00
WerWolv
994df0a3a4 feat: Add shortcut to directly search for the selected bytes 2025-12-07 22:17:57 +01:00
WerWolv
e6eee55810 fix: Editing of WString, String16, String32 in data inspector 2025-12-07 21:44:33 +01:00
WerWolv
855e4c4913 feat: Add option to create auto backups of files before they're modified 2025-12-07 21:37:14 +01:00
WerWolv
c2e07bf7b2 feat: Added data inspector shortcut to toggle endianness 2025-12-07 20:58:30 +01:00
WerWolv
77b9e3eac8 impr: Allow Esc to clear editing and selected state in data inspector 2025-12-07 20:58:17 +01:00
WerWolv
790487eea6 impr: If there's multiple foreground highlighting providers, only evaluate until a color is found 2025-12-07 20:48:16 +01:00
WerWolv
eb83354179 feat: Add option to automatically apply found pattern when a provider is opened 2025-12-07 20:47:33 +01:00
WerWolv
9ba8754f97 build: Remove file version from main executable to make msi installer not skip it 2025-12-07 17:57:21 +01:00
WerWolv
84346119b3 fix: Missing includes 2025-12-07 17:22:26 +01:00
WerWolv
2b3abd06db build: Fix deb package referring to incorrect md4c library package
Fixes #2548
2025-12-07 16:25:15 +01:00
WerWolv
8267aad79e feat: Add new Command Line data source 2025-12-07 16:24:36 +01:00
WerWolv
3f9ce561b9 fix: Post-pone file opening till everything has been initialized 2025-12-07 14:00:10 +01:00
WerWolv
347fc3ed9f impr: Show proper error message if nethost header can't be found 2025-12-07 13:35:08 +01:00
WerWolv
0488c996e9 impr: Make icons look slightly nicer at low resolutions 2025-12-07 11:48:14 +01:00
WerWolv
37bfd97d93 git: Make release CI more reliable 2025-12-07 10:36:03 +01:00
WerWolv
c8652b0576 Merge branch 'feature/code-signing' 2025-12-07 00:01:54 +01:00
WerWolv
1208d2eb5e git: Fix issues with the release CI 2025-12-07 00:01:40 +01:00
WerWolv
ab34fed0c5 build: Bump version to 1.39.0.WIP 2025-12-07 00:01:22 +01:00
WerWolv
0906e5f9cf git: Remove test signing, get release signing ready 2025-12-06 23:59:56 +01:00
WerWolv
47b1c603b3 git: Remove signpath parameters 2025-12-06 23:59:56 +01:00
WerWolv
4bda321e7a git: Fix version string 2025-12-06 23:59:56 +01:00
WerWolv
691ff11fbc git: Added Windows code signing 2025-12-06 23:59:56 +01:00
WerWolv
83650c908d git: Fix invalid renaming logic 2025-12-06 22:24:07 +01:00
WerWolv
afa297bb53 build: Fix macOS and Snap builds not bundling latest patterns 2025-12-06 20:57:51 +01:00
WerWolv
00986d0ea8 build: Bump version to 1.38.0 2025-12-06 19:56:30 +01:00
WerWolv
633914316a build: Fix wrong name of cli launcher script 2025-12-06 19:14:53 +01:00
WerWolv
205bb81a0a patterns: Update pattern language 2025-12-06 16:50:49 +01:00
WerWolv
60a69e3a54 patterns: Update pattern language 2025-12-06 16:26:52 +01:00
WerWolv
5c629494da build: Update libwolv 2025-12-06 16:12:04 +01:00
WerWolv
95f010395c fix: Pressing enter while in insert mode not behaving correctly 2025-12-06 16:11:28 +01:00
WerWolv
d575d0f724 patterns: Update pattern language 2025-12-06 16:11:28 +01:00
WerWolv
bdbdb46005 fix: Menu items with the ShowOnWelcomeScreen shortcut modifier not producing a valid shortcut on macOS 2025-12-05 22:56:16 +01:00
WerWolv
efc28a3177 pattern: Update pattern language 2025-12-05 22:23:17 +01:00
WerWolv
5d50653495 patterns: Update pattern language 2025-12-05 21:34:13 +01:00
WerWolv
24c55beb9c build: Fix broken FindmbedTLS script 2025-12-05 20:32:47 +01:00
WerWolv
04547ad6af build: Add CMake Debug option to run configuration 2025-12-05 20:32:32 +01:00
WerWolv
d2951d06b2 build: Update capstone 2025-12-05 20:23:40 +01:00
WerWolv
926910bf6e feat: patterns: Update pattern language
Fixes #2538
2025-12-05 20:23:34 +01:00
WerWolv
6652750044 build: Add preliminary build support for mbedTLS 4 2025-12-05 20:20:11 +01:00
WerWolv
ab3853eb9d build: Properly link against the homebrew llvm libc++ library on macOS 2025-12-05 19:26:09 +01:00
WerWolv
4f4af83699 build: Fix more macOS build issues 2025-12-05 18:06:51 +01:00
iTrooz
df3200f936 refactor: move hex editor popups to their own files (#2536) 2025-12-05 12:04:49 +01:00
iTrooz
7374a06faa fix: Linux SDK looking for files in the wrong place + update doc on building SDK (#2537) 2025-12-05 12:02:39 +01:00
WerWolv
22b13f5ba6 build: Fix another llvm20 instance 2025-12-05 00:08:06 +01:00
WerWolv
031301e1bb git: Fix macOS clang paths 2025-12-04 23:54:49 +01:00
WerWolv
3ad508c6fc build: Update llvm version on macOS 2025-12-04 23:50:24 +01:00
WerWolv
c3421aef8c fix: Initializing std::atomic_flag makes no sense 2025-12-04 21:04:48 +01:00
WerWolv
f2e8d402dd impr: Calculate hashes in a background thread 2025-12-04 20:57:06 +01:00
WerWolv
ab54acb176 fix: Find results staying behind until new search has finished 2025-12-04 17:29:45 +01:00
WerWolv
7585e191d0 build: Fix Windows 32 bit build 2025-12-04 17:29:18 +01:00
WerWolv
a4f6795a44 build: Update macOS ARM docker to latest clang version and macOS 15 SDK 2025-12-04 17:28:54 +01:00
WerWolv
3529bce009 build: Update dependencies 2025-12-04 17:28:09 +01:00
WerWolv
bc3afbb271 build: Upgrade emscripten to latest release 2025-12-03 21:33:32 +01:00
WerWolv
a0d0621725 build: Start using std::from_chars 2025-12-03 20:48:22 +01:00
WerWolv
c2d70dbd50 fix: Build issues on clang 2025-12-03 19:51:35 +01:00
WerWolv
e2fdd91956 feat: Add option to access remote files using raw SSH 2025-12-03 19:23:42 +01:00
WerWolv
2a84534ced impr: Don't hide entire data inspector UI anymore if no bytes are selected 2025-12-03 19:21:47 +01:00
WerWolv
94b53592d9 impr: Only show remaining Open File / New File menu options when they make sense 2025-12-03 19:21:23 +01:00
WerWolv
09006588fc feat: Allow integer literals to be used in binary patterns 2025-12-03 19:20:45 +01:00
WerWolv
9d5cdaeb33 fix: Tutorial highlights not always being visible still 2025-12-02 23:03:02 +01:00
WerWolv
d4df465633 feat: Replace useless constants view with a constant search option in the Find view 2025-12-02 23:02:44 +01:00
WerWolv
da0c1674a6 patterns: Update pattern language 2025-12-02 20:05:52 +01:00
WerWolv
18aa11117a impr: Fix fixed point inspector row requiring the correct number of bytes to be selected 2025-12-02 20:01:46 +01:00
WerWolv
ed32439645 impr: Only add stacktrace to exceptions thrown in main thread 2025-12-02 20:00:19 +01:00
WerWolv
5c890e710e build: Improve info in metainfo file 2025-12-02 19:59:24 +01:00
Nik
d15b7862b8 fix: Build error due to size_t not being u64 on macOS 2025-12-02 08:08:19 +01:00
WerWolv
0e5136196a fix: Potential infinite loop while wrapping text 2025-12-01 22:57:49 +01:00
WerWolv
46fdbd5bc0 fix: String inspector rows not displaying the correctly decoded value 2025-12-01 22:38:56 +01:00
WerWolv
da755ec75b feat: Added pattern context menu for copy and edit 2025-12-01 21:25:57 +01:00
WerWolv
d610f787b9 Revert "build: Enable color cli output for ninja builds"
This reverts commit a2ce89af32.
2025-12-01 20:36:36 +01:00
WerWolv
1ab1f7ada0 fix: Comparison between literal and optional 2025-12-01 20:35:55 +01:00
WerWolv
56cb1f2747 fix: Pattern auto loading not working anymore
Fixes #2531
2025-12-01 19:54:55 +01:00
WerWolv
413c6b5116 fix: Some interactive help regions not being highlighted 2025-12-01 19:38:19 +01:00
WerWolv
f4753a5bd8 feat: Added hex editor minimap option to shade cells based on the byte's value 2025-12-01 19:37:36 +01:00
WerWolv
980438008c fix: Crashes and usability issues with the pattern tree filter 2025-12-01 19:35:22 +01:00
WerWolv
8f57dd86af fix: Typos 2025-12-01 19:33:21 +01:00
WerWolv
a2ce89af32 build: Enable color cli output for ninja builds 2025-12-01 19:32:49 +01:00
WerWolv
67008288e2 fix: Clear pattern editor change flag after setting help text 2025-11-30 23:57:52 +01:00
WerWolv
4caa0ce570 fix: Turn cli file path into absolute path before passing it on 2025-11-30 23:57:22 +01:00
WerWolv
4e2dcef7d7 fix: Crash when an error occurrs when opening a file through the cli 2025-11-30 23:14:02 +01:00
WerWolv
f47a248768 build: Properly link mbedtls in brewfile 2025-11-30 23:01:49 +01:00
WerWolv
862462c5bb build: Keep using mbedTLS 3 on macOS 2025-11-30 22:39:35 +01:00
WerWolv
375471160f build: Fix capstone license path on AlmaLinux 2025-11-30 21:42:23 +01:00
WerWolv
4000e7c886 build: Upgrade to macOS 15 due to GitHub Actions deprecation 2025-11-30 21:32:57 +01:00
WerWolv
48095671c3 build: Put launcher shell script into share folder 2025-11-30 21:12:36 +01:00
WerWolv
c96b47f345 feat: Added RGBA8 and RGB565 minimap visualizer 2025-11-30 21:01:20 +01:00
WerWolv
b250172bb5 fix: Wrong localization keys for some MIPS disassembler options 2025-11-30 20:41:48 +01:00
WerWolv
257b248f34 build: Add imhex launcher shell script to rpm 2025-11-30 20:40:43 +01:00
WerWolv
a8fe63ee93 impr: Better name and icons for recent files 2025-11-30 20:34:00 +01:00
WerWolv
d359a21a66 impr: Add icons to welcome screen description buttons 2025-11-30 20:33:38 +01:00
WerWolv
e5cdf22753 build: Update capstone to latest alpha tag 2025-11-30 19:50:05 +01:00
WerWolv
c33d53b728 feat: Add support for Capstone 6, drop support for Capstone 4 2025-11-30 19:49:07 +01:00
WerWolv
e5829a316b impr: Remove the constants view from the views menu as it's still pretty much useless 2025-11-30 16:43:24 +01:00
WerWolv
569bf474bd impr: Replace the data information "Analyze page" button with an "Analyze" button 2025-11-30 16:42:46 +01:00
WerWolv
06ecd5d571 feat: Add support for markdown to the comments of bookmarks 2025-11-30 16:42:20 +01:00
WerWolv
9ae233a41c feat: Integrate the interactive help option and add a help text for every view 2025-11-30 16:42:01 +01:00
WerWolv
989f7f7678 impr: Add option to ShortcutManager to get a shortcut by its name 2025-11-30 16:40:23 +01:00
WerWolv
a75947e611 fix: Show auto backup button not being translatable 2025-11-30 14:36:09 +01:00
WerWolv
1d4233514f impr: Add dropdown to disassembler architectures 2025-11-30 14:08:40 +01:00
WerWolv
fa780e9706 impr: Add some help text to the pattern editor by default 2025-11-30 14:08:21 +01:00
WerWolv
cba93e87eb fix: Issues with drawing interactive tutorial 2025-11-30 14:07:57 +01:00
WerWolv
f3a2fe5b0d build: Update ImGui 2025-11-30 14:04:38 +01:00
WerWolv
ebee8ff0a6 build: Include a launcher shell script with the executables
Closes #2528
2025-11-30 12:03:12 +01:00
WerWolv
34971162cb fix: Crash in some cases when starting ImHex with --open 2025-11-30 12:03:12 +01:00
WerWolvTranslationBot
58eec483c9 lang: Translations update from Weblate (#2480)
Translations update from [Weblate](https://weblate.werwolv.net) for
[ImHex/Builtin](https://weblate.werwolv.net/projects/imhex/builtin/).


It also includes following components:

* [ImHex/Diffing](https://weblate.werwolv.net/projects/imhex/diffing/)

* [ImHex/UI](https://weblate.werwolv.net/projects/imhex/ui/)

*
[ImHex/Disassembler](https://weblate.werwolv.net/projects/imhex/disassembler/)

* [ImHex/Yara
Rules](https://weblate.werwolv.net/projects/imhex/yara-rules/)

* [ImHex/Fonts](https://weblate.werwolv.net/projects/imhex/fonts/)

* [ImHex/Hashes](https://weblate.werwolv.net/projects/imhex/hashes/)

* [ImHex/Remote](https://weblate.werwolv.net/projects/imhex/remote/)

* [ImHex/Script
Loader](https://weblate.werwolv.net/projects/imhex/script-loader/)

*
[ImHex/Visualizers](https://weblate.werwolv.net/projects/imhex/visualizers/)

* [ImHex/Windows](https://weblate.werwolv.net/projects/imhex/windows/)



Current translation status:

![Weblate translation
status](https://weblate.werwolv.net/widgets/imhex/-/builtin/horizontal-auto.svg)

Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: liushuyu <liushuyu011@gmail.com>
2025-11-29 13:02:09 +01:00
David Given
c57f071f0c impr: Add hooks to let Views to get notified when they are opened or closed (#2493)
This is a trivial change which adds virtual methods to View, `onOpen()`
and `onClose()`, which are called when the view is opened or closed.

This information is already tracked inside the View, but not exposed via
the API. There is `didWindowJustOpen()` and `didWindowJustClose()`, but
these fetch and then reset the flag, so they can't be used more than
once in a frame (and are sometimes called by the frame, meaning the flag
has already been consumed by the time the View's draw callback gets
called).

The use case here is that I have a View which needs to do some work
every time it's shown.
2025-11-29 13:01:38 +01:00
Stefan
b30e2bcfa4 lang: Fix typo in German language file (#2525) 2025-11-29 13:00:37 +01:00
WerWolv
b56c3c5a46 git: Add retry for downloading mesa 2025-11-29 11:11:53 +01:00
WerWolv
120c4202b4 git: Fix CodeQL CI failing 2025-11-29 10:58:33 +01:00
WerWolv
1f257290ab impr: Manually parse time auto backup time strings as std::chrono::parse is not available everywhere 2025-11-29 10:57:40 +01:00
WerWolv
4d585d17de fix: Achievements re-triggering in cases where an achievement is triggered before its save is loaded 2025-11-29 09:07:37 +01:00
WerWolv
2c7da65242 impr: Add auto backups to crash restore popup 2025-11-29 09:06:49 +01:00
WerWolv
95ff52b025 build: Update dependencies 2025-11-29 09:06:25 +01:00
iTrooz
b1e2185966 fix: Always order recent providers (#2490) 2025-10-31 21:01:30 +00:00
iTrooz
5d77402211 fix: add newly created projects to "Recent" (#2492)
<!--
Please provide as much information as possible about what your PR aims
to do.
PRs with no description will most likely be closed until more
information is provided.
If you're planing on changing fundamental behaviour or add big new
features, please open a GitHub Issue first before starting to work on
it.
If it's not something big and you still want to contact us about it,
feel free to do so !
-->

### Problem description
<!-- Describe the bug that you fixed/feature request that you
implemented, or link to an existing issue describing it -->
Projects weren't being saved as recent when a new project was saved.
They were only added as recent when re-opening the project

### Implementation description
<!-- Explain what you did to correct the problem -->
I also save projects as recent when saving them (I don't make a
difference between saving existing and new projects)

### Screenshots
<!-- If your change is visual, take a screenshot showing it. Ideally,
make before/after sceenshots -->

### Additional things
<!-- Anything else you would like to say -->
2025-10-31 20:34:29 +01:00
iTrooz
f762cc2906 ci: add support for Fedora 43 (#2489) 2025-10-31 20:34:14 +01:00
paxcut
7ca2e558c9 patterns: updated pattern language (#2483) 2025-10-23 04:25:02 -07:00
WerWolv
e388d0c5e8 impr: Remove unnecessary moves in the task manager 2025-10-18 00:01:27 +02:00
WerWolv
05f8d9302d impr: Add proper move constructors to UnlocalizedString 2025-10-17 23:47:03 +02:00
WerWolvTranslationBot
8f277f00a4 lang: Translations update from Weblate (#2472)
Translations update from [Weblate](https://weblate.werwolv.net) for
[ImHex/Builtin](https://weblate.werwolv.net/projects/imhex/builtin/).


It also includes following components:

* [ImHex/Diffing](https://weblate.werwolv.net/projects/imhex/diffing/)

* [ImHex/Yara
Rules](https://weblate.werwolv.net/projects/imhex/yara-rules/)

*
[ImHex/Disassembler](https://weblate.werwolv.net/projects/imhex/disassembler/)

* [ImHex/Fonts](https://weblate.werwolv.net/projects/imhex/fonts/)

* [ImHex/Hashes](https://weblate.werwolv.net/projects/imhex/hashes/)

* [ImHex/Remote](https://weblate.werwolv.net/projects/imhex/remote/)

* [ImHex/Script
Loader](https://weblate.werwolv.net/projects/imhex/script-loader/)

* [ImHex/UI](https://weblate.werwolv.net/projects/imhex/ui/)

*
[ImHex/Visualizers](https://weblate.werwolv.net/projects/imhex/visualizers/)

* [ImHex/Windows](https://weblate.werwolv.net/projects/imhex/windows/)



Current translation status:

![Weblate translation
status](https://weblate.werwolv.net/widgets/imhex/-/builtin/horizontal-auto.svg)

Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Yaroslav <mrikso821@gmail.com>
2025-10-17 23:25:59 +02:00
WerWolv
59f9da59e2 impr: Less unnecessary copying 2025-10-17 23:23:48 +02:00
WerWolv
8d4415fe15 patterns: Updated pattern language
Fixes #2478
2025-10-17 23:23:33 +02:00
WerWolv
fd54b2b803 fix: Don't try to move a const reference 2025-10-17 19:33:27 +02:00
WerWolv
ba6953fda4 fix: Color picker slider moving around when dragging them 2025-10-17 19:33:08 +02:00
WerWolv
c0f667ce20 patterns: Updated pattern language 2025-10-17 19:32:49 +02:00
WerWolv
c93c15563a build: Bump macOS minimum version in all places 2025-10-14 22:56:34 +02:00
WerWolv
d0340c13dc build: Bump macOS minimum version to 13.3 2025-10-14 22:16:29 +02:00
WerWolv
c6caa1d067 git: Fix nightly release runner running when there's nothing to do 2025-10-14 22:11:55 +02:00
WerWolv
2f0efa1197 build: Updated libwolv 2025-10-14 21:55:13 +02:00
WerWolv
a76eae2c11 build: Updated libwolv 2025-09-25 18:01:53 +02:00
WerWolv
b82c1f051c build: Update libwolv 2025-09-24 21:20:56 +02:00
WerWolv
1b6a150624 build: Move jthread library to libwolv 2025-09-24 20:48:50 +02:00
WerWolv
265360229f fix: ImGui assert due to trying to select tab bar button 2025-09-24 20:37:15 +02:00
WerWolv
98e9729267 fix: Preview fonts not being properly reset during soft-restarts 2025-09-21 22:11:28 +02:00
WerWolv
cfe16ee2c5 build: Updated dependencies 2025-09-21 12:47:45 +02:00
WerWolv
c9f856b219 build: Updated libwolv 2025-09-21 11:31:56 +02:00
Zackary Newman
3c167c3306 feat: Add keyboard shortcuts to jump to the prev/next differences in diff view (#2445)
Adds keyboard shortcuts (currently `n` and `N`) in the diffing plugin
view to jump to the next/prev difference in the list.

IMPORTANT NOTE: Depends on changes made in a library submodule. [This
PR](https://github.com/WerWolv/libwolv/pull/34) must be accepted first.

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-09-21 10:39:37 +02:00
WerWolv
fedbce6f9e build: Fix emscripten build issues 2025-09-20 12:11:25 +02:00
WerWolv
28be4cea97 build: Move X11 library linking to backend, make X11 not required 2025-09-20 11:44:31 +02:00
WerWolv
05fb2bfd23 impr: Use better icon for the download update button 2025-09-19 18:22:35 +02:00
WerWolv
3905335c53 build: Update Tabler icons 2025-09-19 18:22:06 +02:00
WerWolv
4dc3f9e033 build: Update ImGui Test Engine 2025-09-19 18:21:57 +02:00
WerWolv
07a6a9b7d4 build: Update ImGui backend 2025-09-19 18:21:02 +02:00
WerWolv
fac7dff77f build: Updated ImGui to v1.92.3 2025-09-17 22:19:02 +02:00
WerWolv
60c7ced335 build: Change AppImage sourceline to noble 2025-09-17 21:59:05 +02:00
WerWolv
8f981e7707 fix: Prevent providers to be created via "Open Recent" menu while tasks are running 2025-09-17 20:56:28 +02:00
WerWolv
725cc10a92 lang: Un-hide Ukrainian language 2025-09-17 20:53:47 +02:00
WerWolvTranslationBot
d3896ccfda lang: Added Ukrainian language (#2444)
Translation by @RutarAndriy
Translations update from [Weblate](https://weblate.werwolv.net) for
[ImHex/Builtin](https://weblate.werwolv.net/projects/imhex/builtin/).


It also includes following components:

* [ImHex/Diffing](https://weblate.werwolv.net/projects/imhex/diffing/)

* [ImHex/Yara
Rules](https://weblate.werwolv.net/projects/imhex/yara-rules/)

*
[ImHex/Disassembler](https://weblate.werwolv.net/projects/imhex/disassembler/)

* [ImHex/Fonts](https://weblate.werwolv.net/projects/imhex/fonts/)

* [ImHex/Hashes](https://weblate.werwolv.net/projects/imhex/hashes/)

* [ImHex/Remote](https://weblate.werwolv.net/projects/imhex/remote/)

* [ImHex/Script
Loader](https://weblate.werwolv.net/projects/imhex/script-loader/)

* [ImHex/UI](https://weblate.werwolv.net/projects/imhex/ui/)

*
[ImHex/Visualizers](https://weblate.werwolv.net/projects/imhex/visualizers/)

* [ImHex/Windows](https://weblate.werwolv.net/projects/imhex/windows/)



Current translation status:

![Weblate translation
status](https://weblate.werwolv.net/widgets/imhex/-/builtin/horizontal-auto.svg)

Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Rutar Andriy <RutarAndriy@gmail.com>
2025-09-17 20:52:24 +02:00
WerWolv
de3e532a5c build: Go back to Ubuntu 24.04 for AppImages since AppImageBuilder doesn't support 25.04 2025-09-17 20:47:14 +02:00
WerWolv
98369600c3 impr: Various rendering performance improvements 2025-09-17 20:46:15 +02:00
WerWolv
d9aaef29d2 git: Make Snap upload errors not fail CI 2025-09-17 12:03:58 +02:00
WerWolv
48f4410a2a build: Remove EoL Ubuntu 24.10 builds, Update AppImage runner to use 25.04 2025-09-17 12:01:29 +02:00
WerWolv
ca0b232ada fix: Data inspector not updating when reloading file changes
Fixes #2451
2025-09-16 23:34:38 +02:00
WerWolv
75efe39298 fix: Pattern Data table not retaining column settings in all cases 2025-09-16 23:28:31 +02:00
WerWolv
84342f7a7b git: Added Jetbrains to sponsors section 2025-09-14 19:28:20 +02:00
Zackary Newman
67efea6444 Fix segfault when opening recent file with pattern sync; Don't show p… (#2448)
…attern selection popup when pattern is already open

This PR does two things. Most importantly, it fixes a segfault that can
be caused by opening a recent file with pattern sync enabled.
Secondly, it makes it so that the pattern selection popup does not
appear if you already have text in the pattern editor for a given
provider (due to CLI args, a project file, pattern sync, etc.). If you
open a file normally, that text field is empty and the popup will appear
so you can select a pre-made pattern like usual.
2025-09-13 21:10:38 -07:00
WerWolv
f08b182bf2 impr: Make sure pattern settings window doesn't go off-screen anymore
Fixes #2446
2025-09-13 11:30:13 +02:00
WerWolv
3c83a62aef git: Add note for people with push access 2025-09-13 10:22:28 +02:00
WerWolv
821db4d2a1 impr: Allow hiding unfinished languages in non-debug mode 2025-09-12 22:47:17 +02:00
WerWolv
3c661842a2 lang: Added empty files for Ukrainian 2025-09-12 22:15:10 +02:00
WerWolv
920578003e lang: Added skeleton structure for Ukrainian language
#2443
2025-09-12 21:55:53 +02:00
WerWolvTranslationBot
22aadcc1ae lang: Translations update from Weblate (#2442)
Translations update from [Weblate](https://weblate.werwolv.net) for
[ImHex/Builtin](https://weblate.werwolv.net/projects/imhex/builtin/).


It also includes following components:

* [ImHex/Diffing](https://weblate.werwolv.net/projects/imhex/diffing/)

* [ImHex/Yara
Rules](https://weblate.werwolv.net/projects/imhex/yara-rules/)

*
[ImHex/Disassembler](https://weblate.werwolv.net/projects/imhex/disassembler/)

* [ImHex/Fonts](https://weblate.werwolv.net/projects/imhex/fonts/)

* [ImHex/Hashes](https://weblate.werwolv.net/projects/imhex/hashes/)

* [ImHex/Remote](https://weblate.werwolv.net/projects/imhex/remote/)

* [ImHex/Script
Loader](https://weblate.werwolv.net/projects/imhex/script-loader/)

* [ImHex/UI](https://weblate.werwolv.net/projects/imhex/ui/)

*
[ImHex/Visualizers](https://weblate.werwolv.net/projects/imhex/visualizers/)

* [ImHex/Windows](https://weblate.werwolv.net/projects/imhex/windows/)



Current translation status:

![Weblate translation
status](https://weblate.werwolv.net/widgets/imhex/-/builtin/horizontal-auto.svg)

Co-authored-by: Weblate <noreply@weblate.org>
2025-09-12 21:11:59 +02:00
WerWolv
efc65479c6 git: Added sponsorship section and note to comply with SignPath's terms 2025-09-12 21:09:00 +02:00
Zackary Newman
dcbba9cbfc impr: Rework command line argument parsing (#2440)
The current CLI argument parsing did not work as documented and had a
number of issues related to multi-flag (subcommand) parsing. I've
reworked the logic in such a way that should maintain full compatibility
with any existing scripts/use-cases but with added functionality.

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-09-12 21:07:33 +02:00
WerWolvTranslationBot
6169078c04 lang: Translations update from Weblate (#2437)
Translations update from [Weblate](https://weblate.werwolv.net) for
[ImHex/Builtin](https://weblate.werwolv.net/projects/imhex/builtin/).


It also includes following components:

* [ImHex/Diffing](https://weblate.werwolv.net/projects/imhex/diffing/)

* [ImHex/Yara
Rules](https://weblate.werwolv.net/projects/imhex/yara-rules/)

*
[ImHex/Disassembler](https://weblate.werwolv.net/projects/imhex/disassembler/)

* [ImHex/Fonts](https://weblate.werwolv.net/projects/imhex/fonts/)

* [ImHex/Hashes](https://weblate.werwolv.net/projects/imhex/hashes/)

* [ImHex/Remote](https://weblate.werwolv.net/projects/imhex/remote/)

* [ImHex/Script
Loader](https://weblate.werwolv.net/projects/imhex/script-loader/)

* [ImHex/UI](https://weblate.werwolv.net/projects/imhex/ui/)

*
[ImHex/Visualizers](https://weblate.werwolv.net/projects/imhex/visualizers/)

* [ImHex/Windows](https://weblate.werwolv.net/projects/imhex/windows/)



Current translation status:

![Weblate translation
status](https://weblate.werwolv.net/widgets/imhex/-/builtin/horizontal-auto.svg)

Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Francisco J. Solis <siscomagma@gmail.com>
2025-09-11 20:12:02 +02:00
WerWolv
955f48f532 impr: Use better icons for data inspector buttons 2025-09-11 20:11:25 +02:00
Shadow775711
d7a830ca95 lang: Update Polish translation (#2420)
Unfortunately, I had to create a new fork and branch because GitHub kept
rejecting my push due to the workflow files (nightly_release.yml and
release.yml), even though they were not intentionally modified.

I only made changes in two language files and added a helper script
Formatter.py.

Please test if everything works correctly in the interface.

Thanks for the project, and I’m happy to help further if needed.

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-09-11 20:10:53 +02:00
sonorousfreq
96b27645d6 feat: Add region sidebar list to Intel Hex and Motorola SREC providers (#2417)
Add block list for intel hex and motorola srec

TEST: Load various hex and srec files
 - Test search capability
 - Test jump to section

### Problem description
The intel-hex/motorola formats can be loaded but not quite ideally,
including there is no list of segments/blocks that
can be extracted from file layout (metadata).

### Implementation description
I implemented similar feature as process monitor provider does, to
extract chunks while parsing the file and show
them as a sidebar list

### Screenshots
Looks like this:
<img width="1893" height="897" alt="image"
src="https://github.com/user-attachments/assets/c37d46cb-d129-4f9a-bb9a-d8969f397c6e"
/>



### Additional things
There are some improvements that could be made:
1. There is currently no API to jump to address, which would be useful
to jump to beginning of a hex/srec segment.
2. When jumping with setSelection, jumping backwards makes the first
visible line the jump address/line, however, when jumping forward, the
jump address is at the bottom (see image).
3. Unsure about convention for searches, should we search elements as
startsWith given user string, or contains or including 0x prefix or not,
whether to keep prefix zeros since the region size is 8 bytes, but
addresses should be <= 32 bits, etc.
2025-09-11 09:50:38 +00:00
WerWolv
8b6346ae41 feat: Allow jumping to Yara rule matches
Fixes #2439
2025-09-10 21:06:28 +02:00
WerWolv
c1619820c7 impr: Jump to top of selection instead of the bottom
Fixes #2354
2025-09-10 20:50:27 +02:00
WerWolv
88ccb0e075 fix: Plugin features display not working correctly 2025-09-10 19:44:46 +02:00
WerWolv
12564dd78f impr: Fix layout of pattern settings popup 2025-09-10 19:13:47 +02:00
WerWolv
b0c4db7a64 fix: Invalid localization string for pattern settings popup 2025-09-09 23:40:36 +02:00
WerWolv
310ca6c6dc fix: Custom data processor node name ID collisions 2025-09-09 23:37:22 +02:00
WerWolv
32e3a4e74f impr: Move items from pattern editor console area to more appropriate places 2025-09-09 22:30:29 +02:00
WerWolv
be66e3fe79 impr: Simplify and standardize resizable console window in pattern editor 2025-09-08 21:24:01 +02:00
WerWolv
d794734f1d git: Fix nightly tag getting put on non-master branches 2025-09-08 20:14:03 +02:00
WerWolv
8661b6551d fix: Opening pattern sections not working 2025-09-08 19:53:51 +02:00
WerWolv
a0326c4371 impr: Properly align buttons in pattern data view 2025-09-08 19:52:12 +02:00
WerWolv
b039bc14c6 fix: Only first opened popup appearing properly 2025-09-08 19:51:58 +02:00
paxcut
d08853df8c fix: No scrolling on jumping to error source. (#2438)
When I implemented the changes to allow creating breakpoints without
losing focus in the pattern editor and without forcing it to scroll to
the cursor position I broke the code that ensures the cursor is visible
after being moved to the source code that caused the error. All I needed
to do is to explicitly set the argument because the default is to not
scroll to the cursor when focus is given to the pattern editor
2025-09-07 12:31:09 -07:00
paxcut
d8dd287cdf fix: Fixed ImHex crashing when using ctrl-backspace on empty file. (#2433)
Editor was attempting to delete non-existent chars which is UB. Fixed by
checking before deleting. Also fixed was a problem created by having to
press enter to change the search string which advanced the selection to
the first match. In the next step one would expect that pressing enter
on the replace field would replace the selected item but was replacing
the item found after he first.

This was fixed by always replacing the current selection first. If the
replacement is the same as the searched term then replacing won't
advance the cursor, but if they are different then the current match
will no longer exist so it would search fora new one.
2025-09-05 02:28:11 -07:00
paxcut
d62b64c27a Fixes for next release. (#2430)
I forgot I also had comments switched to italics done easily thanks to
WerWolv's addition that lets you push and pop them.
2025-09-02 17:29:33 -07:00
paxcut
52952652de Fixes for next release. (#2429)
Attempt to fix WerWolv's strange off by one problem when using the
mouse. Added a popup question for files that contain long lines (>1024
bytes). Also improved the handling of large lines, so it won't stall the
app. May also contain other smaller issue fixes.
2025-09-02 15:30:50 -07:00
WerWolv
790c19a1cd patterns: Go back to working pattern language 2025-09-01 22:54:51 +02:00
WerWolv
9659381378 git: Fix IMHEX_VERSION env var not getting set in snap CI 2025-09-01 17:56:49 +02:00
WerWolv
4598fc098d fix: ImGui ID not getting popped correctly 2025-08-31 22:17:36 +02:00
WerWolv
2f6fde1e61 build: Rename cmake project to ImHex 2025-08-31 22:17:00 +02:00
WerWolv
16dc199431 fix: Achievement popup setting only being read once at startup 2025-08-31 17:31:16 +02:00
WerWolv
715e970d99 fix: Last column in text editor not being selectable 2025-08-31 16:59:40 +02:00
WerWolv
53535ab9be build: Updated lunasvg 2025-08-31 15:15:37 +02:00
WerWolv
24f9df90b8 impr: Added proper help text to ImHex updater 2025-08-31 15:11:35 +02:00
WerWolv
4cfdbb8095 patterns: Updated pattern language 2025-08-31 13:52:02 +02:00
WerWolv
fe4cb8575f impr: Sort View menu alphabetically 2025-08-31 11:22:40 +02:00
WerWolv
06ac7eb85f impr: Make Hex Editor view always be focused by default 2025-08-31 11:22:26 +02:00
WerWolv
0e14ff5a3d git: Fix naming and uploading of snap artifacts 2025-08-31 10:33:50 +02:00
WerWolv
c65015fcc7 fix: Make sure crash handling operations happen in the right order 2025-08-31 10:23:19 +02:00
paxcut
c8caf6124e Fix: Very long lines in text editor could make it hang. (#2426)
Fixed by only processing text that's visible.

Also fixed the cursor jumping to breakpoint line when selected by
clicking the line number and added highlighting of the current editing
line. An optimization that caches the number of utf-8 chars in each line
was included as well.
Finally, an error that caused ImHex to crash if a pattern was saved as
itself was also fixed.
2025-08-30 20:01:05 -07:00
WerWolv
76bb0e420d fix: Rename font_size setting to not cause issues during upgrade 2025-08-30 18:11:06 +02:00
WerWolv
d2c1b2a31b impr: Resume logging before printing crash logs 2025-08-30 14:35:29 +02:00
WerWolv
e30f073809 build: Properly link against libpthread on mingw 2025-08-30 14:27:40 +02:00
WerWolv
e1079d751a fix: Handle uncaught exceptions more gracefully 2025-08-30 14:24:39 +02:00
WerWolv
a9d45d837f fix: Missing pthread include 2025-08-30 11:21:09 +02:00
WerWolv
bcbe5eb105 fix: Use Win32 functions to terminate thread on Windows 2025-08-30 11:19:40 +02:00
WerWolv
6ab1f8e4e2 git: Fix snap version getting reset back 2025-08-30 10:56:59 +02:00
WerWolv
90f26d53d3 impr: Make viable pattern search properly abortable 2025-08-30 10:51:05 +02:00
WerWolv
281921d1de fix: Crashes in non-main threads causing freezes 2025-08-30 10:32:24 +02:00
WerWolv
9135153dc9 impr: Throw error if no data could be read with read node 2025-08-30 10:32:24 +02:00
WerWolv
c70b505b3a fix: Make RGBA8 visualizer node only copy the data it needs 2025-08-30 10:32:24 +02:00
WerWolv
cde9dc37e5 fix: Wrong localization for Add button in hashes view 2025-08-30 10:32:24 +02:00
WerWolv
ab1e5eb359 build: Updated libfmt to trunk for compatibility with Clang 21.1.0 2025-08-29 23:40:00 +02:00
WerWolv
aec9f7a145 impr: Use more muted colors in advanced text encoding column 2025-08-28 23:22:50 +02:00
WerWolv
bf08ed563a feat: Added Hex Editor "Decode as Encoding" option 2025-08-28 23:22:26 +02:00
WerWolv
ff70518882 fix: Hang when setting window title from non-main-thread 2025-08-28 23:22:02 +02:00
WerWolv
72364db768 fix: Build errors 2025-08-28 22:31:27 +02:00
WerWolv
92fa72eac7 fix: More hashes view layout issues 2025-08-28 22:29:30 +02:00
WerWolv
9e2c1de0f5 fix: Provider dirtying not changing window title 2025-08-28 22:20:39 +02:00
WerWolv
57ac73b9d4 impr: Properly vertically center search icon in search bar 2025-08-28 22:17:19 +02:00
WerWolv
2757c577e4 impr: Modernize yara view 2025-08-28 21:44:59 +02:00
WerWolv
704af30421 impr: Clean up hashes view 2025-08-28 21:22:47 +02:00
WerWolv
1e8a005d0e impr: Make data inspector view more compact 2025-08-28 20:13:51 +02:00
WerWolv
8a04d2f477 feat: Added fixed-point row to data inspector 2025-08-28 19:57:51 +02:00
WerWolv
a7c37bfb93 fix: Load ImHex logo at correct resolution 2025-08-28 17:28:13 +02:00
WerWolv
d1801ea438 build: Added CLion build target definition file 2025-08-28 17:25:29 +02:00
WerWolv
f6f856cd56 build: Added note for MSVC and Emscripten if vcpkg is not configured 2025-08-28 17:25:09 +02:00
WerWolv
8515cd43fa impr: Added note to Advanced Yara Information section if no matches were found 2025-08-28 17:24:51 +02:00
WerWolv
8a4cdbb371 impr: Slightly nicer layout for data information view 2025-08-28 17:24:14 +02:00
WerWolv
7fef133505 git: Add emoji to nightly release runner 2025-08-28 17:23:53 +02:00
WerWolv
5f206a33e2 build: Remove old OSX SDK setting 2025-08-28 17:23:24 +02:00
WerWolv
228385ceaa fix: Undefined behaviour when setting task bar progress 2025-08-28 00:01:49 +02:00
WerWolv
bd9e9a7dcf impr: Make crash handling from non-main threads more resilient 2025-08-27 23:53:46 +02:00
WerWolv
abffb8c138 fix: Text in toasts getting cut off very quickly 2025-08-27 23:34:16 +02:00
WerWolv
e353802e9f impr: Added more OpenGL version information to logs 2025-08-27 23:34:01 +02:00
WerWolv
130055af22 fix: Crash when force-exiting on macOS 2025-08-27 23:33:44 +02:00
WerWolv
db573840b0 fix: Incorrect word wrap calculation after ImGui update
#2325
2025-08-27 23:14:07 +02:00
WerWolv
e0fccacc32 fix: Nightlies always having an update available, even if we're already on latest 2025-08-27 23:05:00 +02:00
WerWolv
18890f47b6 build: Don't clone ImHex-Patterns during install step if it exists already 2025-08-27 22:58:14 +02:00
WerWolv
204cc1ccb3 build: Make sure updater gets properly bundled on macOS 2025-08-27 22:57:57 +02:00
WerWolv
a063eb96c6 fix: Markdown elements overflowing window width 2025-08-27 21:27:47 +02:00
WerWolv
145c8ff804 impr: Update about page 2025-08-27 21:27:06 +02:00
WerWolv
f0d2f94aef git: Only add run number on nightly builds 2025-08-27 17:35:31 +02:00
WerWolv
0c12cb683a git: Add workflow run number to snap version number 2025-08-27 17:33:33 +02:00
WerWolv
56b5d026df fix: Patterns only starting to execute when pattern editor was visible 2025-08-25 21:45:20 +02:00
WerWolv
40ccbd0d86 feat: Added pattern-provided file information to information view 2025-08-25 21:44:59 +02:00
WerWolv
c1a14cb4d4 impr: Ensure that wrapped text doesn't end up wrapping at every character 2025-08-25 21:22:43 +02:00
Nik
df2448e121 fix: Web version not starting anymore due to WebGL only supporting OpenGL 3.0 2025-08-25 07:29:36 +02:00
Nik
ca323c392b fix: Format string security issue 2025-08-25 07:27:08 +02:00
WerWolv
395dd37d33 fix: Pattern data section context menu not opening correctly 2025-08-24 22:13:01 +02:00
WerWolv
e91689a715 impr: Unlock frame rate during blocking task progress 2025-08-24 21:38:24 +02:00
WerWolv
861988f8dc fix: Compile errors 2025-08-24 21:35:50 +02:00
WerWolv
f26f1298cf impr: Added localization for save editor view 2025-08-24 21:24:39 +02:00
WerWolv
66efcf91d3 feat: Added file information command line option and fullscreen view 2025-08-24 21:21:34 +02:00
WerWolv
0178ba014a fix: Region picker widget overflowing in many views 2025-08-24 16:29:36 +02:00
WerWolv
254bd88e6b fix: macOS initialising very low OpenGL version by default 2025-08-24 16:10:13 +02:00
WerWolv
3808b78487 impr: Add styles and colors from newer ImGui versions to theme system 2025-08-24 14:11:38 +02:00
WerWolv
a80c35aa94 fix: Icon offsets being scaled incorrectly 2025-08-24 13:55:02 +02:00
WerWolv
d0f51d0462 fix: Undo invalid scaling 2025-08-24 13:31:45 +02:00
WerWolvTranslationBot
013fa85c1c lang: Updated localization (#2412)
Translations update from [Weblate](https://weblate.werwolv.net) for
[ImHex/Builtin](https://weblate.werwolv.net/projects/imhex/builtin/).


It also includes following components:

* [ImHex/Diffing](https://weblate.werwolv.net/projects/imhex/diffing/)

* [ImHex/Yara
Rules](https://weblate.werwolv.net/projects/imhex/yara-rules/)

*
[ImHex/Disassembler](https://weblate.werwolv.net/projects/imhex/disassembler/)

* [ImHex/Fonts](https://weblate.werwolv.net/projects/imhex/fonts/)

* [ImHex/Hashes](https://weblate.werwolv.net/projects/imhex/hashes/)

* [ImHex/Remote](https://weblate.werwolv.net/projects/imhex/remote/)

* [ImHex/Script
Loader](https://weblate.werwolv.net/projects/imhex/script-loader/)

* [ImHex/UI](https://weblate.werwolv.net/projects/imhex/ui/)

*
[ImHex/Visualizers](https://weblate.werwolv.net/projects/imhex/visualizers/)

* [ImHex/Windows](https://weblate.werwolv.net/projects/imhex/windows/)



Current translation status:

![Weblate translation
status](https://weblate.werwolv.net/widgets/imhex/-/builtin/horizontal-auto.svg)

Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: OctopuSSX <vladik0701@gmail.com>
2025-08-24 13:07:16 +02:00
WerWolv
fcda856198 fix: Font being scaled too large if main screen DPI is higher than secondary screen DPIs
#2419
2025-08-24 12:57:56 +02:00
WerWolv
e385487a6b build: Added simple Nix Flake 2025-08-24 12:49:05 +02:00
WerWolv
f8fa029ee3 patterns: Updated pattern language
Fixes #2280
2025-08-24 11:57:29 +02:00
WerWolv
d1a0f8ec97 impr: Use faster way of finding matching pattern files for loaded file 2025-08-24 10:54:27 +02:00
WerWolv
d02e147dc3 impr: Move most of the implementations of the pattern editor view to the cpp file 2025-08-24 10:34:07 +02:00
WerWolv
5c481d4247 impr: Add separator above connect button of tty view 2025-08-24 10:18:58 +02:00
WerWolv
f4cbdde8f6 fix: One too many menu item being shown in the overflow menu 2025-08-24 10:18:23 +02:00
WerWolv
0ac09fc57b impr: Modernize TTY console view 2025-08-23 23:44:49 +02:00
WerWolv
99c28c93b4 impr: Better diff view table headers 2025-08-23 23:44:39 +02:00
WerWolv
0e800723f5 impr: Store points instead of pixels for font size in settings 2025-08-23 20:56:34 +02:00
WerWolv
fc2ed47676 dist: Added featured snap banner 2025-08-23 11:04:41 +02:00
WerWolv
5c2309bcf7 fix: OpenGL detection not working correctly 2025-08-23 11:04:41 +02:00
WerWolv
ba71a300ec fix: Semantic version comparison only working in one direction 2025-08-23 11:04:41 +02:00
487 changed files with 19630 additions and 8938 deletions

View File

@@ -1,69 +1,97 @@
# Generated from CLion Inspection settings
---
Checks: '-*,
mpi-*,
bugprone-*,
-bugprone-signal-handler,
-bugprone-narrowing-conversions,
-bugprone-redundant-branch-condition,
-bugprone-exception-escape,
-bugprone-shared-ptr-array-mismatch,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-signed-char-misuse,
-bugprone-unhandled-exception-at-new,
-bugprone-infinite-loop,
-bugprone-easily-swappable-parameters,
cert-err52-cpp,
cert-err60-cpp,
cert-err34-c,
cert-str34-c,
cert-dcl21-cpp,
cert-msc50-cpp,
cert-msc51-cpp,
cert-dcl58-cpp,
cert-flp30-c,
cppcoreguidelines-avoid-const-or-ref-data-members,
cppcoreguidelines-pro-type-member-init,
cppcoreguidelines-slicing,
cppcoreguidelines-interfaces-global-init,
cppcoreguidelines-pro-type-static-cast-downcast,
cppcoreguidelines-narrowing-conversions,
google-default-arguments,
google-runtime-operator,
google-explicit-constructor,
hicpp-multiway-paths-covered,
hicpp-exception-baseclass,
misc-*,
-misc-definitions-in-headers,
-misc-unused-parameters,
-misc-unused-alias-decls,
-misc-use-anonymous-namespace,
-misc-misleading-identifier,
-misc-confusable-identifiers,
-misc-misleading-bidirectional,
-misc-static-assert,
-misc-no-recursion,
-misc-const-correctness,
modernize-*,
-modernize-use-trailing-return-type,
openmp-use-default-none,
performance-*,
-performance-no-int-to-ptr,
portability-*,
-portability-restrict-system-includes,
readability-*,
-readability-redundant-preprocessor,
-readability-named-parameter,
-readability-function-size,
-readability-use-anyofallof,
-readability-identifier-length,
-readability-magic-numbers,
-readability-braces-around-statements,
-readability-suspicious-call-argument,
-readability-isolate-declaration,
-readability-else-after-return,
-readability-redundant-access-specifiers,
-readability-function-cognitive-complexity,
-readability-identifier-naming,
*-include-cleaner,
-readability-qualified-auto'
# All rules should have a comment associated
# Directives that do not have any effect (e.g. disabling a rule that is not enabled) can be done to add an explanation comment.
# Or at least an empty comment # to show they were put here explicitely,
# and not as part of the historical CLion-generated rules
# Note: `- -X` means disable X
# CLI usage: go to the build directory and run: `run-clang-tidy -allow-no-checks -source-filter ".*/lib/.*" -fix -j`
Checks:
- -*
- mpi-*
- bugprone-*
- -bugprone-signal-handler
- -bugprone-narrowing-conversions
- -bugprone-redundant-branch-condition
- -bugprone-exception-escape
- -bugprone-shared-ptr-array-mismatch
- -bugprone-implicit-widening-of-multiplication-result
- -bugprone-signed-char-misuse
- -bugprone-unhandled-exception-at-new
- -bugprone-infinite-loop
- -bugprone-easily-swappable-parameters
- -bugprone-float-loop-counter #
- -bugprone-unchecked-string-to-number-conversion # Unfortunately no alternative
- -bugprone-branch-clone # Mostly warns about one-line duplicates
- cert-err52-cpp
- cert-err60-cpp
- cert-str34-c
- cert-dcl21-cpp
- cert-msc50-cpp
- cert-msc51-cpp
- cert-dcl58-cpp
- cppcoreguidelines-avoid-const-or-ref-data-members
- cppcoreguidelines-pro-type-member-init # We want to use default member initializers
- cppcoreguidelines-slicing
- cppcoreguidelines-interfaces-global-init
- -cppcoreguidelines-pro-type-static-cast-downcast # dynamic_cast has a runtime overhead
- -cppcoreguidelines-narrowing-conversions #
- google-runtime-operator
- google-explicit-constructor
- -google-default-arguments # Provider and ViewProvider read() is a good example of why this is useful
- hicpp-multiway-paths-covered
- hicpp-exception-baseclass
- misc-*
- -misc-definitions-in-headers
- -misc-unused-parameters
- -misc-unused-alias-decls
- -misc-use-anonymous-namespace
- -misc-misleading-identifier
- -misc-confusable-identifiers
- -misc-misleading-bidirectional
- -misc-static-assert
- -misc-no-recursion
- -misc-const-correctness
- -misc-use-internal-linkage # False positives if header where function is defined is not included
- -misc-include-cleaner # Allow indirect includes
- -misc-non-private-member-variables-in-classes #
- modernize-*
- -modernize-use-trailing-return-type
- -modernize-use-std-print # We want to use fmt::print instead
- -modernize-use-integer-sign-comparison # Too much occurrences to change
- openmp-use-default-none
- performance-*
- -performance-no-int-to-ptr
- portability-*
- -portability-restrict-system-includes
- readability-*
- -readability-redundant-preprocessor
- -readability-named-parameter
- -readability-function-size
- -readability-use-anyofallof
- -readability-identifier-length
- -readability-magic-numbers
- -readability-braces-around-statements
- -readability-suspicious-call-argument
- -readability-isolate-declaration
- -readability-else-after-return
- -readability-redundant-access-specifiers
- -readability-function-cognitive-complexity
- -readability-identifier-naming
- -readability-qualified-auto
- -readability-use-std-min-max # Less readable imo
- -readability-math-missing-parentheses # Basic math
- -readability-implicit-bool-conversion # Not much of a problem ?
- -readability-convert-member-functions-to-static #
- -readability-use-concise-preprocessor-directives # We do not use #ifdef
- -readability-uppercase-literal-suffix # Not important enough
- -readability-redundant-string-cstr # Sometimes used to stop at first null byte
- -readability-static-accessed-through-instance #
- -readability-ambiguous-smartptr-reset-call # Fix is hard to read
# Will fix later
- -modernize-avoid-c-arrays
- -readability-make-member-function-const # idk + lots of occurences
- -readability-misleading-indentation # We need to handle cases with #if defined()
- -bugprone-unchecked-optional-access
- -performance-unnecessary-value-param # idk
- -readability-avoid-nested-conditional-operator

4
.github/FUNDING.yml vendored
View File

@@ -1,5 +1,5 @@
# Sponsor links
patreon: werwolv
custom: https://werwolv.net/donate
github: WerWolv
ko_fi: WerWolv
custom: "https://werwolv.net/donate"

7
.github/scripts/delete-artifact.sh vendored Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/sh
set -xe
ARTIFACT_NAME="$1"
ARTIFACT_ID=$(gh api repos/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID/artifacts --jq ".artifacts[] | select(.name==\"$ARTIFACT_NAME\") | .id")
gh api -X DELETE repos/$GITHUB_REPOSITORY/actions/artifacts/$ARTIFACT_ID
echo "Deleted artifact $ARTIFACT_NAME with ID $ARTIFACT_ID"

View File

@@ -49,15 +49,16 @@ jobs:
set -x
mkdir -p build
cd build
CC=gcc-14 CXX=g++-14 cmake \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
-G Ninja \
CC=gcc-14 CXX=g++-14 cmake \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_EXCLUDE_PLUGINS="script_loader" \
-G Ninja \
..
ninja install

View File

@@ -1,5 +1,9 @@
name: Build
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
on:
push:
branches:
@@ -23,10 +27,10 @@ jobs:
include:
- architecture_name: "x86_64"
msystem: "mingw64"
runner_os: runs-on=${{ github.run_id }}/image=windows22-base-x64/family=c7a.16xlarge
runner_os: "windows-2025"
- architecture_name: "arm64"
msystem: "clangarm64"
runner_os: windows-11-arm
runner_os: "windows-11-arm"
runs-on: ${{ matrix.runner_os }}
name: 🪟 Windows MSYS2 ${{ matrix.architecture_name }}
@@ -49,7 +53,7 @@ jobs:
submodules: recursive
- name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@main
uses: hendrikmuhs/ccache-action@v1
id: cache-ccache
with:
key: ${{ runner.os }}-mingw-ccache-${{ github.run_id }}
@@ -95,7 +99,6 @@ jobs:
-DIMHEX_GENERATE_PDBS=ON \
-DIMHEX_REPLACE_DWARF_WITH_PDB=ON \
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" \
-DCPACK_WIX_VERSION="4" \
-DCPACK_WIX_ROOT="$(echo "$USERPROFILE" | tr '\\' '/')/.dotnet/tools" \
..
@@ -166,6 +169,7 @@ jobs:
- name: ⬆️ Upload Windows Installer
uses: actions/upload-artifact@v4
id: upload-installer
with:
if-no-files-found: error
name: Windows Installer ${{ matrix.architecture_name }}
@@ -186,7 +190,7 @@ jobs:
run: |
set -x
echo "NoGPU version Powered by Mesa 3D : https://fdossena.com/?p=mesa%2Findex.frag" > build/install/MESA.md
curl https://downloads.fdossena.com/geth.php?r=mesa64-latest -L -o mesa.7z
curl --connect-timeout 30 --retry 5 --retry-delay 0 --retry-max-time 30 https://downloads.fdossena.com/geth.php?r=mesa64-latest -L -o mesa.7z
7z e mesa.7z
mv opengl32.dll build/install
@@ -206,10 +210,10 @@ jobs:
include:
- architecture_name: "x86_64"
vs_arch: "amd64"
runner_os: runs-on=${{ github.run_id }}/image=windows22-base-x64/family=c7a.16xlarge
runner_os: "windows-2025"
- architecture_name: "arm64"
vs_arch: "amd64_arm64"
runner_os: windows-11-arm
runner_os: "windows-11-arm"
runs-on: ${{ matrix.runner_os }}
name: 🪟 Windows MSVC ${{ matrix.architecture_name }}
@@ -233,7 +237,7 @@ jobs:
arch: ${{ matrix.vs_arch }}
- name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@main
uses: hendrikmuhs/ccache-action@v1
id: cache-ccache
with:
key: ${{ runner.os }}-msvc-${{ matrix.vs_arch }}-ccache-${{ github.run_id }}
@@ -279,7 +283,6 @@ jobs:
-DIMHEX_COMMIT_HASH_LONG="$env:GITHUB_SHA" `
-DIMHEX_COMMIT_BRANCH="$($env:GITHUB_REF -replace '.*/', '')" `
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" `
-DCPACK_WIX_VERSION="4" `
-DCPACK_WIX_ROOT="$($env:USERPROFILE -replace '\\','/')/.dotnet/tools" `
.
@@ -316,7 +319,7 @@ jobs:
imhex-*.msi
win-plugin-template-test:
runs-on: runs-on=${{ github.run_id }}/image=windows22-base-x64/family=c7a.16xlarge
runs-on: windows-2022
name: 🧪 Plugin Template Test
defaults:
@@ -380,24 +383,13 @@ jobs:
# MacOS build
macos-x86:
runs-on: macos-13
runs-on: macos-15-intel
permissions:
id-token: write
attestations: write
strategy:
fail-fast: false
matrix:
include:
- file_suffix: "-NoGPU"
name_suffix: "NoGPU"
custom_glfw: true
- file_suffix: ""
name_suffix: ""
custom_glfw: false
name: 🍎 macOS 13 x86_64 ${{ matrix.name_suffix }}
name: 🍎 macOS 10.15 x86_64
steps:
- name: 🧰 Checkout
@@ -412,61 +404,40 @@ jobs:
- name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1
with:
key: ${{ runner.os }}${{ matrix.file_suffix }}-ccache-${{ github.run_id }}
restore-keys: ${{ runner.os }}${{ matrix.file_suffix }}-ccache
key: ${{ runner.os }}-ccache-${{ github.run_id }}
restore-keys: ${{ runner.os }}-ccache
max-size: 1G
- name: Set Xcode version
run: sudo xcode-select -s /Library/Developer/CommandLineTools
run: |
sudo xcode-select --install || true
sudo xcode-select -s /Library/Developer/CommandLineTools
- name: 📦 Install MacPorts
run: |
wget https://github.com/macports/macports-base/releases/download/v2.11.6/MacPorts-2.11.6-15-Sequoia.pkg
sudo installer -pkg MacPorts-2.11.6-15-Sequoia.pkg -target /
export PATH=/opt/local/bin:/opt/local/sbin:$PATH
echo "PATH=/opt/local/bin:/opt/local/sbin:$PATH" >> $GITHUB_ENV
echo "MACOSX_DEPLOYMENT_TARGET=10.15" >> $GITHUB_ENV
echo "universal_target 10.15" | sudo tee -a /opt/local/etc/macports/macports.conf
echo "macos_deployment_target 10.15" | sudo tee -a /opt/local/etc/macports/macports.conf
echo "macosx_sdk_version 10.15" | sudo tee -a /opt/local/etc/macports/macports.conf
sudo port selfupdate
- name: ⬇️ Install dependencies
env:
# Make brew not display useless errors
HOMEBREW_TESTS: 1
run: |
brew reinstall python --quiet || true
brew link --overwrite --quiet python 2>/dev/null || true
brew bundle --quiet --file dist/macOS/Brewfile || true
rm -rf /usr/local/Cellar/capstone
- name: ⬇️ Install classic glfw
if: ${{! matrix.custom_glfw }}
run: |
brew install --quiet glfw || true
brew install llvm automake
sudo -E port install mbedtls3 nlohmann-json ccache freetype libmagic pkgconfig curl glfw ninja zlib xz bzip2 zstd libssh2 md4c
- name: ⬇️ Install .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.100'
- name: 🧰 Checkout glfw
if: ${{ matrix.custom_glfw }}
uses: actions/checkout@v4
with:
repository: glfw/glfw
path: glfw
# GLFW custom build (to allow software rendering)
- name: ⬇️ Patch and install custom glfw
if: ${{ matrix.custom_glfw }}
run: |
set -x
cd glfw
git apply ../dist/macOS/0001-glfw-SW.patch
mkdir build
cd build
cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
-DBUILD_SHARED_LIBS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
..
ninja install
# MacOS cmake build
- name: 🛠️ Configure CMake
run: |
@@ -477,8 +448,8 @@ jobs:
CXX=$(brew --prefix llvm)/bin/clang++ \
OBJC=$(brew --prefix llvm)/bin/clang \
OBJCXX=$(brew --prefix llvm)/bin/clang++ \
PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \
cmake -G "Ninja" \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
-DIMHEX_GENERATE_PACKAGE=ON \
-DIMHEX_SYSTEM_LIBRARY_PATH="$(brew --prefix llvm)/lib;$(brew --prefix llvm)/lib/unwind;$(brew --prefix llvm)/lib/c++;$(brew --prefix)/lib" \
@@ -499,7 +470,6 @@ jobs:
run: |
set -x
cd build/install
mv imhex.app ImHex.app
codesign --remove-signature ImHex.app
codesign --force --deep --sign - ImHex.app
@@ -528,7 +498,7 @@ jobs:
break;
fi
done
mv *.dmg ../../imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.file_suffix }}-x86_64.dmg
mv *.dmg ../../imhex-${{ env.IMHEX_VERSION }}-macOS-x86_64.dmg
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
@@ -541,12 +511,12 @@ jobs:
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: macOS DMG ${{ matrix.name_suffix }} x86_64
name: macOS DMG x86_64
path: ./*.dmg
macos-arm64:
runs-on: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
name: 🍎 macOS 13 arm64
runs-on: ubuntu-24.04
name: 🍎 macOS 11 arm64
outputs:
IMHEX_VERSION: ${{ steps.build.outputs.IMHEX_VERSION }}
@@ -590,11 +560,11 @@ jobs:
GH_TOKEN: ${{ github.token }}
run: |
gh extension install actions/gh-actions-cache
gh actions-cache delete "build-macos-arm64-cache" --confirm || true
gh cache delete "macos-arm64-cache" --confirm || true
macos-arm64-package:
runs-on: macos-13
name: 🍎 macOS 13 arm64 Packaging
runs-on: macos-15-intel
name: 🍎 macOS 11 arm64 Packaging
needs: macos-arm64
env:
@@ -620,7 +590,6 @@ jobs:
run: |
set -x
cd out
mv imhex.app ImHex.app
codesign --remove-signature ImHex.app
codesign --force --deep --entitlements Entitlements.plist --sign - ImHex.app
@@ -671,15 +640,21 @@ jobs:
fail-fast: false
matrix:
include:
- release_num: "24.04"
- release_num: "24.10"
- release_num: "25.04"
- name: "Ubuntu"
release_num: "24.04"
image: "ubuntu:24.04"
- name: "Ubuntu"
release_num: "25.10"
image: "ubuntu:25.10"
- name: "Debian"
release_num: "13"
image: "debian:13"
name: 🐧 Ubuntu ${{ matrix.release_num }}
runs-on: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }} x86_64
runs-on: ubuntu-24.04
container:
image: "ubuntu:${{ matrix.release_num }}"
image: "${{ matrix.image }}"
options: --privileged
permissions:
@@ -698,8 +673,8 @@ jobs:
- name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1
with:
key: Ubuntu-${{ matrix.release_num }}-ccache-${{ github.run_id }}
restore-keys: Ubuntu-${{ matrix.release_num }}-ccache
key: ${{ matrix.image }}-ccache-${{ github.run_id }}
restore-keys: ${{ matrix.image }}-ccache
max-size: 1G
- name: ⬇️ Install dependencies
@@ -744,7 +719,7 @@ jobs:
run: |
cp -r build/DEBIAN build/DebDir
dpkg-deb -Zzstd --build build/DebDir
mv build/DebDir.deb imhex-${{ env.IMHEX_VERSION }}-Ubuntu-${{ matrix.release_num }}-x86_64.deb
mv build/DebDir.deb imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.deb
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
@@ -757,7 +732,7 @@ jobs:
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: Ubuntu ${{ matrix.release_num }} DEB x86_64
name: ${{ matrix.name }} ${{ matrix.release_num }} DEB x86_64
path: '*.deb'
# AppImage build
@@ -769,11 +744,11 @@ jobs:
- architecture: "x86_64"
architecture_package: "amd64"
architecture_appimage_builder: "x86_64"
image: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
image: ubuntu-24.04
- architecture: "arm64"
architecture_package: "arm64"
architecture_appimage_builder: "aarch64"
image: runs-on=${{ github.run_id }}/runner=16cpu-linux-arm64/image=ubuntu24-full-arm64
image: ubuntu-24.04-arm
runs-on: ${{ matrix.image }}
name: ⬇️ AppImage ${{ matrix.architecture }}
@@ -832,8 +807,8 @@ jobs:
# ArchLinux build
archlinux-build:
name: 🐧 ArchLinux
runs-on: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
name: 🐧 ArchLinux x86_64
runs-on: ubuntu-24.04
container:
image: archlinux:base-devel
@@ -948,20 +923,11 @@ jobs:
matrix:
include:
- name: Fedora
release_num: rawhide
mock_config: fedora-rawhide
- name: Fedora
release_num: 42
mock_config: fedora-42
- name: Fedora
release_num: 41
mock_config: fedora-41
- name: RHEL-AlmaLinux
release_num: 9
mock_config: "alma+epel-9"
release_num: 43
mock_config: fedora-43
name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }}
runs-on: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }} x86_64
runs-on: ubuntu-24.04
container:
image: "almalinux:10"
@@ -1086,9 +1052,9 @@ jobs:
matrix:
include:
- architecture: "x86_64"
image: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
image: ubuntu-24.04
- architecture: "arm64"
image: runs-on=${{ github.run_id }}/runner=16cpu-linux-arm64/image=ubuntu24-full-arm64
image: ubuntu-24.04-arm
name: 🐧 Snap ${{ matrix.architecture }}
runs-on: ${{ matrix.image }}
@@ -1117,12 +1083,18 @@ jobs:
run: |
export IMHEX_VERSION=$(cat VERSION)
echo "IMHEX_VERSION=$IMHEX_VERSION" >> $GITHUB_ENV
if [[ "$IMHEX_VERSION" == *.WIP ]]; then
echo "IMHEX_VERSION_STRING=$IMHEX_VERSION-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
else
echo "IMHEX_VERSION_STRING=$IMHEX_VERSION" >> $GITHUB_ENV
fi
echo "CCACHE=ccache" >> $GITHUB_ENV
- name: 📜 Move snap directory to root
run: |
mkdir -p ./snap
envsubst '${IMHEX_VERSION},${CCACHE}' < ./dist/snap/snapcraft.yaml > ./snap/snapcraft.yaml
envsubst '${IMHEX_VERSION_STRING},${CCACHE}' < ./dist/snap/snapcraft.yaml > ./snap/snapcraft.yaml
- name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1
@@ -1135,6 +1107,10 @@ jobs:
run: |
sudo snapcraft --destructive-mode
- name: 🟩 Rename Snap
run: |
mv *.snap imhex-${{ env.IMHEX_VERSION }}-${{ matrix.architecture }}.snap
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
if: ${{ github.event.repository.fork == false && github.event_name != 'pull_request' }}
@@ -1157,10 +1133,10 @@ jobs:
include:
- architecture: "x86_64"
flatpak_arch: "x86_64"
image: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
image: ubuntu-24.04
- architecture: "arm64"
flatpak_arch: "aarch64"
image: runs-on=${{ github.run_id }}/runner=16cpu-linux-arm64/image=ubuntu24-full-arm64
image: ubuntu-24.04-arm
name: 🐧 Flatpak ${{ matrix.architecture }}
runs-on: ${{ matrix.image }}
@@ -1211,12 +1187,8 @@ jobs:
imhex-${{ env.IMHEX_VERSION }}-${{ matrix.architecture }}.flatpak
webassembly-build:
runs-on: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
runs-on: ubuntu-24.04
name: 🌍 Web
permissions:
pages: write
id-token: write
actions: write
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
@@ -1236,17 +1208,20 @@ jobs:
cache-source: cache
cache-target: /cache
- name: 🛠️ Build using docker
- name: 🔨 Copy necessary files
run: |
mkdir -p out/nightly
cp dist/web/serve.py out/nightly/start_imhex_web.py
- name: 🛠️ Build using docker
run: |
docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out/nightly --target raw
- name: ⬇️ Download Release
- name: ⬇️ Download Release artifact
if: ${{ github.event.repository.fork == false }}
uses: robinraju/release-downloader@v1
with:
latest: true
fileName: 'imhex-*-Web.zip'
env:
GH_TOKEN: ${{ github.token }}
run: gh --repo $GITHUB_REPOSITORY release download --pattern "imhex-*-Web.zip"
- name: 🔨 Fix permissions
if: ${{ github.event.repository.fork == false }}
@@ -1259,10 +1234,6 @@ jobs:
with:
path: out/
- name: 🔨 Copy necessary files
run: |
cp dist/web/serve.py out/nightly/start_imhex_web.py
- name: ⬆️ Upload package
uses: actions/upload-artifact@v4
with:
@@ -1281,7 +1252,7 @@ jobs:
webassembly-deploy:
environment:
name: github-pages
name: ImHex Web
url: ${{ steps.deployment.outputs.page_url }}
permissions:
pages: write
@@ -1294,11 +1265,64 @@ jobs:
needs: webassembly-build
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
- name: 🌍 Deploy WebAssembly Build to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
- name: 🗑️ Delete artifact
uses: geekyeggo/delete-artifact@v5
env:
GH_TOKEN: ${{ github.token }}
run: |
.github/scripts/delete-artifact.sh "github-pages"
webassembly-docker-image-deploy:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
needs: webassembly-build
name: 🐋 Deploy to ghcr.io
permissions:
contents: read
packages: write
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
- name: ⬇️ Download artifact
uses: actions/download-artifact@v4
with:
name: github-pages
name: ImHex Web
path: out
- name: 📜 Login to ghcr.io
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: ⛓️ Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}/imhex-web
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: 🔨 Build and push Docker image
uses: docker/build-push-action@v6
env:
DOCKER_BUILD_RECORD_UPLOAD: false
with:
context: .
file: dist/web/Host.Dockerfile
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

47
.github/workflows/dl-cache.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
# https://gist.github.com/iTrooz/d5bacca32c0974edc6c1ac3ad3ee82f3
# See https://github.com/cli/cli/issues/9125
# Extract archive with `tar -xf cache.tzst --transform 's@\.\./@#@g' -P` to avoid ../ errors
name: Download cache key
on:
workflow_dispatch:
inputs:
cache_key:
description: 'Cache key'
required: true
type: string
jobs:
cache-download:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Query cache version
id: version
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION=$(gh api repos/$GITHUB_REPOSITORY/actions/caches \
--jq "
.actions_caches[]
| select(.ref == \"refs/heads/$GITHUB_REF_NAME\")
| select(.key == \"${{ github.event.inputs.cache_key }}\")
| .version
")
echo "version=$VERSION" | tee $GITHUB_OUTPUT
- name: Restore cache
uses: iTrooz/cache/restore@restore_with_version
with:
# Path won't be actually used, we will match by 'version'.
path: .
key: ${{ github.event.inputs.cache_key }}
version: ${{ steps.version.outputs.version }}
- name: Upload cached folder as artifact
uses: actions/upload-artifact@v4
with:
name: cache-artifact
path: |
/home/runner/work/**/*.tzst

View File

@@ -11,8 +11,7 @@ on:
jobs:
nightly-release:
runs-on: ubuntu-24.04
name: Update Nightly Release
name: 🌃 Update Nightly Release
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
@@ -22,27 +21,35 @@ jobs:
fetch-tags: true
- name: 🌃 Check for new commits
id: check_commits
run: |
cd ImHex
git config --global --add safe.directory $(pwd)
if [ -z "$(git log nightly..HEAD --oneline)" ]; then
echo "No new commits since last nightly. Exiting."
exit 0
echo "::set-output name=should_run::false"
else
echo "::set-output name=should_run::true"
fi
- name: 📜 Set version variable
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
run: |
project_version=`cat ImHex/VERSION`
echo "IMHEX_VERSION=$project_version" >> $GITHUB_ENV
# TODO: Replace by Github CLI when github.com/cli/cli/pull/12435 is closed
- name: ⬇️ Download artifacts from latest workflow
uses: dawidd6/action-download-artifact@v6
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: build.yml
branch: ${{ github.event.release.target_commitish }}
branch: master
workflow_conclusion: success
skip_unpack: true
- name: 🗜️ Unzip files when needed
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
run: |
set -x
for zipfile in ./*.zip
@@ -58,32 +65,33 @@ jobs:
done
- name: 🟩 Rename artifacts when needed
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
run: |
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip
mv "Windows Portable arm64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-arm64.zip
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-Web.zip
mv ./*_amd64.snap $(echo ./*_amd64.snap | sed 's/_amd64\.snap$/-x86_64.snap/' | sed 's/_/-/1')
mv ./*_arm64.snap $(echo ./*_arm64.snap | sed 's/_arm64\.snap$/-arm64.snap/' | sed 's/_/-/1')
rm artifact.tar || true
- name: 📖 Generate Release Notes
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
id: release_notes
continue-on-error: true
run: |
cd ImHex
echo "## Nightly ${GITHUB_SHA::7} Changelog" > changelog.md
git fetch --tags --recurse-submodules=no
git log nightly..HEAD --oneline --no-merges --pretty=format:'* %s' >> changelog.md
git log nightly..origin/master --oneline --no-merges --pretty=format:'* %s' >> changelog.md
- name: 📦 Update Pre-Release
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
run: |
set -e
cd ImHex
# Move nightly tag to latest commit
git tag -f nightly HEAD
git tag -f nightly origin/master
git push origin nightly --force
# Auth for GitHub CLI
@@ -101,6 +109,8 @@ jobs:
gh release upload nightly ../*.* --clobber
- name: ⬆️ Publish x86_64 Snap package
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
continue-on-error: true
uses: snapcore/action-publish@v1
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
@@ -109,9 +119,26 @@ jobs:
release: edge
- name: ⬆️ Publish arm64 Snap package
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
continue-on-error: true
uses: snapcore/action-publish@v1
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
with:
snap: imhex-${{ env.IMHEX_VERSION }}-arm64.snap
release: edge
release: edge
website_update:
name: 🌍 Update ImHex Landing Website
needs: nightly-release
runs-on: ubuntu-24.04
env:
WEBSITE_DISPATCH_TOKEN: ${{ secrets.WEBSITE_DISPATCH_TOKEN }}
steps:
- name: ✉️ Dispatch Landing page update
if: ${{ env.WEBSITE_DISPATCH_TOKEN != '' }}
uses: peter-evans/repository-dispatch@v4
with:
token: ${{ secrets.WEBSITE_DISPATCH_TOKEN }}
repository: WerWolv/ImHexWebsite
event-type: update_page

View File

@@ -7,6 +7,12 @@ on:
release:
types: [published]
workflow_dispatch:
inputs:
commit_hash:
type: string
description: 'The commit hash to build (defaults to the latest commit on the default branch)'
required: false
default: ''
jobs:
release-update-repos:
@@ -25,7 +31,7 @@ jobs:
project_version=`cat ImHex/VERSION`
tag_version="${{github.event.release.tag_name}}"
tag_version="${tag_version:1}"
if [ "$project_version" != "$tag_version" ]; then
if [ "$project_version" != "$tag_version" ] && [ ! -z "$tag_version" ]; then
echo "::warning::$project_version and $tag_version are not the same ! Refusing to populate release"
exit 1
fi
@@ -41,6 +47,7 @@ jobs:
tag: ImHex-v${{ env.IMHEX_VERSION }}
repo: PatternLanguage
token: ${{ secrets.RELEASE_TOKEN }}
skipIfReleaseExists: true
- name: 🎫 Create ImHex-Patterns release
uses: ncipollo/release-action@v1
@@ -51,6 +58,7 @@ jobs:
tag: ImHex-v${{ env.IMHEX_VERSION }}
repo: ImHex-Patterns
token: ${{ secrets.RELEASE_TOKEN }}
skipIfReleaseExists: true
- name: 🎫 Create imhex-download-sdk release
uses: ncipollo/release-action@v1
@@ -61,11 +69,13 @@ jobs:
tag: v${{ env.IMHEX_VERSION }}
repo: imhex-download-sdk
token: ${{ secrets.RELEASE_TOKEN }}
skipIfReleaseExists: true
release-upload-artifacts:
runs-on: ubuntu-24.04
name: Release Upload Artifacts
outputs:
IMHEX_VERSION: ${{ steps.verify_version.outputs.IMHEX_VERSION }}
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
@@ -74,17 +84,19 @@ jobs:
submodules: recursive
- name: 📜 Verify version and set version variable
id: verify_version
run: |
set -x
project_version=`cat ImHex/VERSION`
tag_version="${{github.event.release.tag_name}}"
tag_version="${tag_version:1}"
if [ "$project_version" != "$tag_version" ]; then
if [ "$project_version" != "$tag_version" ] && [ ! -z "$tag_version" ]; then
echo "::warning::$project_version and $tag_version are not the same ! Refusing to populate release"
exit 1
fi
echo "IMHEX_VERSION=$project_version" >> $GITHUB_ENV
echo "IMHEX_VERSION=$project_version" >> $GITHUB_OUTPUT
- name: 🗜️ Create tarball from sources with dependencies
run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex
@@ -97,6 +109,7 @@ jobs:
branch: ${{ github.event.release.target_commitish }}
workflow_conclusion: success
skip_unpack: true
commit: ${{ github.event.inputs.commit_hash }}
- name: 🗜️ Unzip files when needed
run: |
@@ -115,27 +128,87 @@ jobs:
- name: 🟩 Rename artifacts when needed
run: |
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip
mv "Windows Portable arm64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-arm64.zip
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip
mv ./*_amd64.snap $(echo ./*_amd64.snap | sed 's/_amd64\.snap$/-x86_64.snap/' | sed 's/_/-/1')
mv ./*_arm64.snap $(echo ./*_arm64.snap | sed 's/_arm64\.snap$/-arm64.snap/' | sed 's/_/-/1')
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-Web.zip
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip || true
mv "Windows Portable arm64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-arm64.zip || true
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip || true
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-Web.zip || true
rm artifact.tar || true
- name: ⬆️ Upload Unsigned x86_64 Windows Installer
uses: actions/upload-artifact@v4
id: upload-installer-x86_64
with:
if-no-files-found: error
name: Windows Installer x86_64
path: |
imhex-*-x86_64.msi
- name: ⬆️ Upload Unsigned ARM64 Windows Installer
if: false
uses: actions/upload-artifact@v4
id: upload-installer-arm64
with:
if-no-files-found: error
name: Windows Installer ARM64
path: |
imhex-*-arm64.msi
- name: 🗑️ Delete unsigned installers
run: |
rm imhex-*-x86_64.msi
- name: 🗝️ Sign x86_64 Installer
uses: signpath/github-action-submit-signing-request@v1
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
organization-id: 'f605a0e8-86cd-411c-bb6f-e05025afcc33'
project-slug: 'ImHex'
signing-policy-slug: 'release-signing'
github-artifact-id: '${{ steps.upload-installer-x86_64.outputs.artifact-id }}'
wait-for-completion: true
output-artifact-directory: '.'
- name: 🗝️ Sign ARM64 Installer
if: false
uses: signpath/github-action-submit-signing-request@v1
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
organization-id: 'f605a0e8-86cd-411c-bb6f-e05025afcc33'
project-slug: 'ImHex'
signing-policy-slug: 'release-signing'
github-artifact-id: '${{ steps.upload-installer-arm64.outputs.artifact-id }}'
wait-for-completion: true
output-artifact-directory: '.'
- name: ⬆️ Upload everything to release
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
with:
files: '*'
release-update-aur:
name: Release update AUR package
needs: release-upload-artifacts
runs-on: ubuntu-24.04
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
with:
path: ImHex
- name: ⬇️ Download artifacts
run: |
tagname=${GITHUB_REF#refs/tags/}
version=${tagname#v}
wget https://github.com/WerWolv/ImHex/releases/download/${tagname}/imhex-${version}-ArchLinux-x86_64.pkg.tar.zst
- name: ✒️ Prepare PKGBUILD
run: |
set -x
cp ImHex/dist/Arch/PKGBUILD .
hash=`md5sum imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst | cut -d ' ' -f 1`
hash=`md5sum imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst | cut -d ' ' -f 1`
sed -i 's/%version%/${{ env.IMHEX_VERSION }}/g' PKGBUILD
sed -i 's/%version%/${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}/g' PKGBUILD
sed -i "s/(SKIP)/($hash)/g" PKGBUILD
- name: ⬆️ Publish AUR package
@@ -149,9 +222,9 @@ jobs:
pkgname: imhex-bin
pkgbuild: ./PKGBUILD
commit_username: iTrooz
commit_email: itrooz@protonmail.com
commit_email: hey@itrooz.fr
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
commit_message: Bump to version ${{ env.IMHEX_VERSION }}
commit_message: Bump to version ${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}
ssh_keyscan_types: rsa,ecdsa,ed25519
release-update-winget:
@@ -163,6 +236,7 @@ jobs:
shell: pwsh
run: |
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
- name: ⬆️ Update winget manifest
shell: pwsh
env:
@@ -180,7 +254,7 @@ jobs:
release-update-snapstore:
name: Release update snapstore package
needs: release-upload-artifacts
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
steps:
- name: ⬇️ Download artifacts
run: |
@@ -190,17 +264,19 @@ jobs:
wget https://github.com/WerWolv/ImHex/releases/download/${tagname}/imhex-${version}-arm64.snap
- name: ⬆️ Publish x86_64 Snap package
continue-on-error: true
uses: snapcore/action-publish@v1
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
with:
snap: imhex-${{ env.IMHEX_VERSION }}-x86_64.snap
snap: imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-x86_64.snap
release: stable
- name: ⬆️ Publish arm64 Snap package
continue-on-error: true
uses: snapcore/action-publish@v1
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
with:
snap: imhex-${{ env.IMHEX_VERSION }}-arm64.snap
snap: imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-arm64.snap
release: stable

2
.gitignore vendored
View File

@@ -12,6 +12,8 @@
/install/
/out/
/dist/ImHex.run.xml
*.mgc
*.kdev4
imgui.ini

6
.gitmodules vendored
View File

@@ -18,10 +18,6 @@
path = lib/third_party/capstone
url = https://github.com/capstone-engine/capstone
ignore = dirty
[submodule "lib/third_party/jthread/jthread"]
path = lib/third_party/jthread/jthread
url = https://github.com/josuttis/jthread
ignore = dirty
[submodule "lib/third_party/edlib"]
path = lib/third_party/edlib
url = https://github.com/Martinsos/edlib
@@ -49,4 +45,4 @@
url = https://github.com/WerWolv/Disassembler
[submodule "lib/third_party/md4c"]
path = lib/third_party/md4c
url = https://github.com/mity/md4c
url = https://github.com/mity/md4c

View File

@@ -1,33 +1,39 @@
cmake_minimum_required(VERSION 3.25)
# Options
option(IMHEX_PLUGINS_IN_SHARE "Put the plugins in share/imhex/plugins instead of lib[..]/imhex/plugins (Linux only)" OFF)
## General
option(IMHEX_STRIP_RELEASE "Strip the release builds" ON )
option(IMHEX_OFFLINE_BUILD "Enable offline build" OFF)
option(IMHEX_IGNORE_BAD_CLONE "Disable the bad clone prevention checks" OFF)
option(IMHEX_PATTERNS_PULL_MASTER "Download latest files from master branch of the ImHex-Patterns repo" OFF)
option(IMHEX_IGNORE_BAD_COMPILER "Allow compiling with an unsupported compiler" OFF)
option(IMHEX_USE_GTK_FILE_PICKER "Use GTK file picker instead of xdg-desktop-portals (Linux only)" OFF)
option(IMHEX_DISABLE_STACKTRACE "Disables support for printing stack traces" OFF)
option(IMHEX_BUNDLE_DOTNET "Bundle .NET runtime" ON )
option(IMHEX_ENABLE_LTO "Enables Link Time Optimizations if possible" OFF)
option(IMHEX_USE_DEFAULT_BUILD_SETTINGS "Use default build settings" OFF)
option(IMHEX_STRICT_WARNINGS "Enable most available warnings and treat them as errors" ON )
option(IMHEX_BUILD_HARDENING "Enable hardening flags for build" ON )
option(IMHEX_STATIC_LINK_PLUGINS "Statically link all plugins into the main executable" OFF)
option(IMHEX_GENERATE_PACKAGE "Specify if a native package should be built. (Windows and MacOS only)" OFF)
option(IMHEX_GENERATE_PACKAGE "Specify if a cpack package should be built. (Windows only)" OFF)
option(IMHEX_MACOS_CREATE_BUNDLE "Creates a macOS .app bundle when building (macOS only)" ON )
option(IMHEX_ENABLE_UNITY_BUILD "Enables building ImHex as a unity build." OFF)
option(IMHEX_GENERATE_PDBS "Enable generating PDB files in non-debug builds (Windows only)" OFF)
option(IMHEX_REPLACE_DWARF_WITH_PDB "Remove DWARF information from binaries when generating PDBS (Windows only)" OFF)
option(IMHEX_ENABLE_STD_ASSERTS "Enable debug asserts in the C++ std library. (Breaks Plugin ABI!)" OFF)
option(IMHEX_ENABLE_UNIT_TESTS "Enable building unit tests" ON )
option(IMHEX_ENABLE_PLUGIN_TESTS "Enable building plugin tests" ON )
option(IMHEX_ENABLE_IMGUI_TEST_ENGINE "Enable the ImGui Test Engine" OFF)
option(IMHEX_ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF)
option(IMHEX_COMPRESS_DEBUG_INFO "Compress debug information" ON )
option(IMHEX_ENABLE_CXX_MODULES "Enable C++20 Module compilation. Testing only!" OFF)
option(IMHEX_ENABLE_CPPCHECK "Enable cppcheck static analysis" OFF)
option(IMHEX_BUNDLE_PLUGIN_SDK "Enable bundling of Plugin SDK into install package" ON )
## Testing
option(IMHEX_ENABLE_UNIT_TESTS "Enable building unit tests" ON )
option(IMHEX_ENABLE_IMGUI_TEST_ENGINE "Enable the ImGui Test Engine" OFF)
option(IMHEX_ENABLE_STD_ASSERTS "Enable debug asserts in the C++ std library. (Breaks Plugin ABI!)" OFF)
## Debug info
option(IMHEX_COMPRESS_DEBUG_INFO "Compress debug information" ON )
option(IMHEX_GENERATE_PDBS "Enable generating PDB files in non-debug builds (Windows only)" OFF)
option(IMHEX_REPLACE_DWARF_WITH_PDB "Remove DWARF information from binaries when generating PDBS (Windows only)" OFF)
option(IMHEX_STRICT_WARNINGS "Enable most available warnings and treat them as errors" ON )
option(IMHEX_DISABLE_STACKTRACE "Disables support for printing stack traces" OFF)
## Plugins
option(IMHEX_STATIC_LINK_PLUGINS "Statically link all plugins into the main executable" OFF)
option(IMHEX_ENABLE_PLUGIN_TESTS "Enable building plugin tests" ON )
option(IMHEX_INCLUDE_PLUGINS "Semicolon-separated list of plugins to include in the build (empty = build all)" "" )
option(IMHEX_EXCLUDE_PLUGINS "Semicolon-separated list of plugins to exclude from the build" "" )
set(IMHEX_BASE_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}")
set(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules")
@@ -47,7 +53,7 @@ loadVersion(IMHEX_VERSION IMHEX_VERSION_PLAIN)
setVariableInParent(IMHEX_VERSION ${IMHEX_VERSION})
configureCMake()
project(imhex
project(ImHex
LANGUAGES C CXX
VERSION ${IMHEX_VERSION_PLAIN}
DESCRIPTION "The ImHex Hex Editor"

View File

@@ -59,13 +59,14 @@
{
"name": "vs2022-x86",
"displayName": "Visual Studio 2022 x86",
"generator": "Visual Studio 17 2022",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_GENERATOR_PLATFORM": "Win32",
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"VCPKG_MANIFEST_DIR": "${sourceDir}/dist"
},
"environment": {
"VSCMD_ARG_TGT_ARCH": "x86"
}
}
],

View File

@@ -29,14 +29,23 @@
## Supporting
If you like my work, please consider supporting me on GitHub Sponsors, Patreon or PayPal. Thanks a lot!
If you like my work, please consider supporting me on GitHub Sponsors, Ko-Fi or PayPal. Thanks a lot!
<p align="center">
<a href="https://github.com/sponsors/WerWolv"><img src="https://werwolv.net/assets/github_banner.png" alt="GitHub donate button" /></a>
<a href="https://www.patreon.com/werwolv"><img src="https://c5.patreon.com/external/logo/become_a_patron_button.png" alt="Patreon donate button" /></a>
<a href="https://ko-fi.com/WerWolv"><img src="https://werwolv.net/assets/kofi_banner.png" alt="Ko-Fi donate button" /></a>
<a href="https://werwolv.net/donate"><img src="https://werwolv.net/assets/paypal_banner.png" alt="PayPal donate button" /></a>
</p>
### Notable Sponsors
| | |
|:---------------------------------------------------------------------------------------------------:|-----------------------------------------------------------------------------------|
| [![JetBrains logo](https://avatars.githubusercontent.com/u/878437?s=48)](https://www.jetbrains.com) | JetBrains, providing us with free All Products Pack licenses for development |
| [![SignPath logo](https://avatars.githubusercontent.com/u/34448643?s=48)](https://signpath.io/) | SignPath, providing us with free Code Signing Certificates for our Windows builds |
| [![AWS logo](https://avatars.githubusercontent.com/u/2232217?s=48)](https://aws.amazon.com) | Amazon, providing us with free AWS Cloud Credits for our CI |
Would you like to appear here as well? Contact us at [imhex@werwolv.net](mailto:imhex@werwolv.net)!
## Screenshots
![Hex editor, patterns and data information](https://github.com/user-attachments/assets/902a7c4c-410d-490f-999e-14c856fec027)
![Bookmarks, data information, find view and data processor](https://github.com/user-attachments/assets/58eefa1f-31c9-4bb8-a1c1-8cdd8ddbd29f)
@@ -327,8 +336,8 @@ To use ImHex, the following minimal system requirements need to be met.
- **OS**:
- **Windows**: Windows 7 or higher (Windows 10/11 recommended)
- **macOS**: macOS 13 (Ventura) or higher,
- Lower versions should still work too, but you'll need to compile ImHex yourself. The release binaries will NOT work due to GitHub not having any macOS 12 or lower CI runners available.
- **macOS**: macOS 15 (Sequoia) or higher,
- Lower versions should still work too, but you'll need to compile ImHex yourself. The release binaries will NOT work due to GitHub not having any macOS 15 or lower CI runners available.
- The macOS build is not signed and will require you to manually allow them in the Security & Privacy settings.
- **Linux**: "Modern" Linux. The following distributions have official releases available. Other distros are supported through the AppImage, Flatpak and Snap releases.
- Ubuntu and Debian
@@ -366,9 +375,20 @@ For more information, check out the [Compiling](/dist/compiling) guide.
## Contributing
See [Contributing](/CONTRIBUTING.md)
## Plugin development
## Plugin development
To develop plugins for ImHex, use the following template project to get started. You then have access to the entirety of libimhex as well as the ImHex API and the Content Registry to interact with ImHex or to add new content.
To build a plugin, you will need to use our SDK
### Getting the SDK locally
You can build the SDK by compiling ImHex like this:
- `cmake -G Ninja -DIMHEX_BUNDLE_PLUGIN_SDK=ON -B build`
- `cd build`
- `DESTDIR=install ninja install`
The SDK will then be available at `install/usr/local/share/imhex/sdk`. You will need to set the variable `IMHEX_SDK_PATH` to that (absolute) path.
### Getting the SDK in a Github Actions CI
You can use [this action](https://github.com/WerWolv/imhex-download-sdk) to automatically download the SDK to your Github Runner
- [ImHex Plugin Template](https://github.com/WerWolv/ImHex-Plugin-Template)
@@ -410,3 +430,18 @@ Notable exceptions to this are the following parts which are under the LGPLv2.1
- **/plugins/ui**: The UI plugin library that contains some common UI elements that can be used by other plugins
The reason for this is to allow for proprietary plugins to be developed for ImHex.
### Code Signing Policy
Free code signing provided by [SignPath.io](https://about.signpath.io/),
certificate by [SignPath Foundation](https://signpath.org/).
This program will not transfer any information to other networked systems
unless specifically requested by the user or the person installing or
operating it.
#### People with direct push access
- [WerWolv](https://github.com/WerWolv)
- [iTrooz](https://github.com/iTrooz)
- [jumanji144](https://github.com/jumanji144)
- [AxCut](https://github.com/paxcut)

View File

@@ -1 +1 @@
1.38.0.WIP
1.39.0.WIP

0
changelog.md Normal file
View File

View File

@@ -175,15 +175,11 @@ macro(detectOS)
endif()
include(GNUInstallDirs)
if(IMHEX_PLUGINS_IN_SHARE)
set(PLUGINS_INSTALL_LOCATION "share/imhex/plugins")
else()
set(PLUGINS_INSTALL_LOCATION "${CMAKE_INSTALL_LIBDIR}/imhex/plugins")
set(PLUGINS_INSTALL_LOCATION "${CMAKE_INSTALL_LIBDIR}/imhex/plugins")
# Add System plugin location for plugins to be loaded from
# IMPORTANT: This does not work for Sandboxed or portable builds such as the Flatpak or AppImage release
add_compile_definitions(SYSTEM_PLUGINS_LOCATION="${CMAKE_INSTALL_FULL_LIBDIR}/imhex")
endif()
# Add System plugin location for plugins to be loaded from
# IMPORTANT: This does not work for Sandboxed or portable builds such as the Flatpak or AppImage release
add_compile_definitions(SYSTEM_PLUGINS_LOCATION="${CMAKE_INSTALL_FULL_LIBDIR}/imhex")
else ()
message(FATAL_ERROR "Unknown / unsupported system!")
@@ -205,11 +201,18 @@ macro(configurePackingResources)
set(CPACK_GENERATOR "WIX")
set(CPACK_PACKAGE_NAME "ImHex")
set(CPACK_PACKAGE_VENDOR "WerWolv")
set(CPACK_WIX_VERSION 4)
set(CPACK_WIX_PRODUCT_GUID "*")
set(CPACK_WIX_UPGRADE_GUID "05000E99-9659-42FD-A1CF-05C554B39285")
set(CPACK_WIX_PRODUCT_ICON "${PROJECT_SOURCE_DIR}/resources/dist/windows/icon.ico")
set(CPACK_WIX_UI_BANNER "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_banner.png")
set(CPACK_WIX_UI_DIALOG "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_dialog.png")
set(CPACK_WIX_CULTURES "en-US;de-DE;ja-JP;it-IT;pt-BR;zh-CN;zh-TW;ru-RU")
set(CPACK_WIX_TEMPLATE "${PROJECT_SOURCE_DIR}/resources/dist/windows/WIX.template.in")
set(CPACK_WIX_EXTENSIONS "WixToolset.UI.wixext")
file(GLOB_RECURSE CPACK_WIX_EXTRA_SOURCES "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix/*.wxs")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "ImHex")
set_property(INSTALL "$<TARGET_FILE_NAME:main>"
PROPERTY CPACK_START_MENU_SHORTCUTS "ImHex"
@@ -218,9 +221,9 @@ macro(configurePackingResources)
endif()
elseif (APPLE OR ${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin")
set(IMHEX_ICON "${IMHEX_BASE_FOLDER}/resources/dist/macos/AppIcon.icns")
set(BUNDLE_NAME "imhex.app")
set(BUNDLE_NAME "ImHex.app")
if (IMHEX_GENERATE_PACKAGE)
if (IMHEX_MACOS_CREATE_BUNDLE)
set(APPLICATION_TYPE MACOSX_BUNDLE)
set_source_files_properties(${IMHEX_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
set(MACOSX_BUNDLE_ICON_FILE "AppIcon.icns")
@@ -236,9 +239,9 @@ macro(configurePackingResources)
string(TIMESTAMP CURR_YEAR "%Y")
set(MACOSX_BUNDLE_COPYRIGHT "Copyright © 2020 - ${CURR_YEAR} WerWolv. All rights reserved." )
if ("${CMAKE_GENERATOR}" STREQUAL "Xcode")
set (IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${BUNDLE_NAME}")
set(IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${BUNDLE_NAME}")
else ()
set (IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${BUNDLE_NAME}")
set(IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${BUNDLE_NAME}")
endif()
set(PLUGINS_INSTALL_LOCATION "${IMHEX_BUNDLE_PATH}/Contents/MacOS/plugins")
@@ -256,7 +259,7 @@ macro(addPluginDirectories)
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${IMHEX_MAIN_OUTPUT_DIRECTORY}/plugins")
if (APPLE)
if (IMHEX_GENERATE_PACKAGE)
if (IMHEX_MACOS_CREATE_BUNDLE)
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGINS_INSTALL_LOCATION})
endif ()
else ()
@@ -312,7 +315,7 @@ macro(createPackage)
POST_EXCLUDE_REGEXES ".*system32/.*\\.dll"
)
if(_c_deps_FILENAMES AND NOT _c_deps STREQUAL "")
if(_c_deps_FILENAMES AND _c_deps AND NOT (_c_deps STREQUAL ""))
message(WARNING "Conflicting dependencies for library: \"${_c_deps}\"!")
endif()
@@ -333,41 +336,47 @@ macro(createPackage)
downloadImHexPatternsFiles(".")
elseif(UNIX AND NOT APPLE)
set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dist/DEBIAN/control.in ${CMAKE_BINARY_DIR}/DEBIAN/control)
configure_file(${IMHEX_BASE_FOLDER}/dist/DEBIAN/control.in ${CMAKE_BINARY_DIR}/DEBIAN/control)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.mime.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages RENAME imhex.xml)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.svg DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.svg)
install(FILES ${IMHEX_BASE_FOLDER}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex)
install(FILES ${IMHEX_BASE_FOLDER}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
install(FILES ${IMHEX_BASE_FOLDER}/dist/imhex.mime.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages RENAME imhex.xml)
install(FILES ${IMHEX_BASE_FOLDER}/resources/icon.svg DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.svg)
downloadImHexPatternsFiles("./share/imhex")
# install AppStream file
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/net.werwolv.ImHex.metainfo.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo)
install(FILES ${IMHEX_BASE_FOLDER}/dist/net.werwolv.ImHex.metainfo.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo)
endif()
if (APPLE)
if (IMHEX_GENERATE_PACKAGE)
if (IMHEX_MACOS_CREATE_BUNDLE)
set(EXTRA_BUNDLE_LIBRARY_PATHS ${EXTRA_BUNDLE_LIBRARY_PATHS} "${IMHEX_SYSTEM_LIBRARY_PATH}")
include(PostprocessBundle)
set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION})
set_property(TARGET main PROPERTY MACOSX_BUNDLE_INFO_PLIST ${MACOSX_BUNDLE_INFO_PLIST})
set_property(TARGET main PROPERTY MACOSX_BUNDLE_BUNDLE_NAME "${MACOSX_BUNDLE_BUNDLE_NAME}")
# Fix rpath
install(CODE "execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath \"@executable_path/../Frameworks/\" $<TARGET_FILE:main>)")
add_custom_target(build-time-make-plugins-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${IMHEX_BUNDLE_PATH}/Contents/MacOS/plugins")
add_custom_target(build-time-make-resources-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${IMHEX_BUNDLE_PATH}/Contents/Resources")
install(CODE "execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath \"@executable_path/../Frameworks/\" $<TARGET_FILE:updater>)")
downloadImHexPatternsFiles("${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/MacOS")
install(FILES ${IMHEX_ICON} DESTINATION "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Resources")
install(TARGETS main BUNDLE DESTINATION ".")
install(TARGETS updater BUNDLE DESTINATION ".")
install(TARGETS updater DESTINATION "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/MacOS")
install(
FILES ${IMHEX_BASE_FOLDER}/dist/cli/imhex.sh
DESTINATION "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/MacOS/cli"
RENAME imhex
PERMISSIONS
OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE
)
# Update library references to make the bundle portable
postprocess_bundle(imhex_all main)
@@ -398,9 +407,31 @@ macro(createPackage)
if (TARGET main-forwarder)
install(TARGETS main-forwarder BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if (WIN32)
install(
FILES ${IMHEX_BASE_FOLDER}/dist/cli/imhex.bat
DESTINATION ${CMAKE_INSTALL_BINDIR}/cli
RENAME imhex.bat
PERMISSIONS
OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE
)
else()
install(
FILES ${IMHEX_BASE_FOLDER}/dist/cli/imhex.sh
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/imhex
RENAME imhex
PERMISSIONS
OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE
)
endif()
endif()
if (IMHEX_GENERATE_PACKAGE)
if (IMHEX_MACOS_CREATE_BUNDLE)
set(CPACK_BUNDLE_NAME "ImHex")
include(CPack)
@@ -529,6 +560,9 @@ function(detectBadClone)
file (GLOB EXTERNAL_DIRS "lib/external/*" "lib/third_party/*")
foreach (EXTERNAL_DIR ${EXTERNAL_DIRS})
if(NOT IS_DIRECTORY "${EXTERNAL_DIR}")
continue()
endif()
file(GLOB_RECURSE RESULT "${EXTERNAL_DIR}/*")
list(LENGTH RESULT ENTRY_COUNT)
if(ENTRY_COUNT LESS_EQUAL 1)
@@ -556,7 +590,9 @@ endfunction()
macro(detectBundledPlugins)
file(GLOB PLUGINS_DIRS "plugins/*")
if (NOT DEFINED IMHEX_INCLUDE_PLUGINS)
if (IMHEX_INCLUDE_PLUGINS)
set(PLUGINS ${IMHEX_INCLUDE_PLUGINS})
else()
foreach(PLUGIN_DIR ${PLUGINS_DIRS})
if (EXISTS "${PLUGIN_DIR}/CMakeLists.txt")
get_filename_component(PLUGIN_NAME ${PLUGIN_DIR} NAME)
@@ -565,8 +601,6 @@ macro(detectBundledPlugins)
endif ()
endif()
endforeach()
else()
set(PLUGINS ${IMHEX_INCLUDE_PLUGINS})
endif()
foreach(PLUGIN_NAME ${PLUGINS})
@@ -577,9 +611,13 @@ macro(detectBundledPlugins)
message(FATAL_ERROR "No bundled plugins enabled")
endif()
if (NOT ("builtin" IN_LIST PLUGINS))
message(FATAL_ERROR "The 'builtin' plugin is required for ImHex to work!")
endif ()
set(REQUIRED_PLUGINS builtin fonts ui)
foreach(PLUGIN ${REQUIRED_PLUGINS})
list(FIND PLUGINS ${PLUGIN} PLUGIN_INDEX)
if (PLUGIN_INDEX EQUAL -1)
message(FATAL_ERROR "Required plugin '${PLUGIN}' is not enabled!")
endif()
endforeach()
endmacro()
macro(setVariableInParent variable value)
@@ -605,17 +643,15 @@ function(downloadImHexPatternsFiles dest)
install(CODE "set(imhex_patterns_SOURCE_DIR \"${imhex_patterns_SOURCE_DIR}\")")
install(CODE [[
message(STATUS "Downloading ImHex patterns from branch '${PATTERNS_BRANCH}'...")
if (EXISTS "${imhex_patterns_SOURCE_DIR}")
file(REMOVE_RECURSE "${imhex_patterns_SOURCE_DIR}")
else ()
if (NOT EXISTS "${imhex_patterns_SOURCE_DIR}")
file(MAKE_DIRECTORY "${imhex_patterns_SOURCE_DIR}")
execute_process(
COMMAND
git clone --recurse-submodules --branch ${PATTERNS_BRANCH} https://github.com/WerWolv/ImHex-Patterns.git "${imhex_patterns_SOURCE_DIR}"
COMMAND_ERROR_IS_FATAL ANY
)
endif()
execute_process(
COMMAND
git clone --recurse-submodules --branch ${PATTERNS_BRANCH} https://github.com/WerWolv/ImHex-Patterns.git "${imhex_patterns_SOURCE_DIR}"
COMMAND_ERROR_IS_FATAL ANY
)
]])
else ()
set(imhex_patterns_SOURCE_DIR "")
@@ -745,15 +781,19 @@ macro(setupCompilerFlags target)
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND APPLE)
execute_process(COMMAND brew --prefix llvm OUTPUT_VARIABLE LLVM_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
addCCXXFlag("-Wno-unknown-warning-option" ${target})
# On macOS, when using clang from Homebrew, properly setup the libc++ library path so
# it's using the one from Homebrew instead of the system one.
execute_process(COMMAND brew --prefix llvm OUTPUT_VARIABLE LLVM_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
if (NOT LLVM_PREFIX STREQUAL "" AND ${CMAKE_CXX_COMPILER} STREQUAL "${LLVM_PREFIX}/bin/clang++")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
endif()
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
add_compile_definitions(_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG)
else()
add_compile_definitions(_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE)
endif()
endif()
@@ -810,6 +850,13 @@ macro(setUninstallTarget)
endmacro()
macro(addBundledLibraries)
# Make sure the build is using vcpkg on Windows and Emscripten, otherwise none of these dependencies will be found
if (MSVC OR EMSCRIPTEN)
if (NOT (CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg"))
message(AUTHOR_WARNING "Your current environment probably needs to be setup to use vcpkg, otherwise none of the dependencies will be found!")
endif()
endif()
set(EXTERNAL_LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/lib/external")
set(THIRD_PARTY_LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/lib/third_party")
set(BUILD_SHARED_LIBS OFF)
@@ -883,18 +930,6 @@ macro(addBundledLibraries)
find_package(LLVM REQUIRED Demangle)
endif()
if (NOT USE_SYSTEM_JTHREAD)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/jthread EXCLUDE_FROM_ALL)
set(JTHREAD_LIBRARIES jthread)
else()
find_path(JOSUTTIS_JTHREAD_INCLUDE_DIRS "condition_variable_any2.hpp")
include_directories(${JOSUTTIS_JTHREAD_INCLUDE_DIRS})
add_library(jthread INTERFACE)
target_include_directories(jthread INTERFACE ${JOSUTTIS_JTHREAD_INCLUDE_DIRS})
set(JTHREAD_LIBRARIES jthread)
endif()
if (USE_SYSTEM_BOOST)
find_package(Boost REQUIRED CONFIG COMPONENTS regex)
set(BOOST_LIBRARIES Boost::regex)

View File

@@ -2,11 +2,7 @@ find_path(LIBMAGIC_INCLUDE_DIR magic.h)
find_library(LIBMAGIC_LIBRARY NAMES magic)
if (LIBMAGIC_INCLUDE_DIR AND LIBMAGIC_LIBRARY)
set(LIBMAGIC_FOUND TRUE)
endif (LIBMAGIC_INCLUDE_DIR AND LIBMAGIC_LIBRARY)
find_package_handle_standard_args("libmagic" DEFAULT_MSG
find_package_handle_standard_args(Magic DEFAULT_MSG
LIBMAGIC_LIBRARY
LIBMAGIC_INCLUDE_DIR
)
@@ -14,5 +10,5 @@ find_package_handle_standard_args("libmagic" DEFAULT_MSG
mark_as_advanced(
LIBMAGIC_INCLUDE_DIR
LIBMAGIC_LIBRARY
LIBMAGIC_FOUND
)
Magic_FOUND
)

View File

@@ -26,8 +26,9 @@ SET(MBEDTLS_FIND_QUIETLY TRUE)
FIND_LIBRARY(MBEDTLS_LIBRARY NAMES mbedtls libmbedtls libmbedx509)
FIND_LIBRARY(MBEDX509_LIBRARY NAMES mbedx509 libmbedx509)
FIND_LIBRARY(MBEDCRYPTO_LIBRARY NAMES mbedcrypto libmbedcrypto)
FIND_LIBRARY(TFPSACRYPTO_LIBRARY NAMES libtfpsacrypto tfpsacrypto)
IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND MBEDCRYPTO_LIBRARY)
IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND (MBEDCRYPTO_LIBRARY OR TFPSACRYPTO_LIBRARY))
SET(MBEDTLS_FOUND TRUE)
ENDIF()
@@ -37,14 +38,24 @@ IF(MBEDTLS_FOUND)
GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY} NAME_WE)
GET_FILENAME_COMPONENT(MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY} NAME_WE)
GET_FILENAME_COMPONENT(MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY} NAME_WE)
GET_FILENAME_COMPONENT(TFPSACRYPTO_LIBRARY_FILE ${TFPSACRYPTO_LIBRARY} NAME_WE)
STRING(REGEX REPLACE "^lib" "" MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY_FILE})
STRING(REGEX REPLACE "^lib" "" MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY_FILE})
STRING(REGEX REPLACE "^lib" "" MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE})
STRING(REGEX REPLACE "^lib" "" TFPSACRYPTO_LIBRARY_FILE ${TFPSACRYPTO_LIBRARY_FILE})
if (TFPSACRYPTO_LIBRARY)
SET(MBEDTLS_CRYPTO_LIBRARY_FILE ${TFPSACRYPTO_LIBRARY_FILE})
elseif (MBEDCRYPTO_LIBRARY)
SET(MBEDTLS_CRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE})
else ()
MESSAGE(FATAL_ERROR "Could not find mbedTLS Crypto library")
endif()
if (MSVC)
SET(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY_FILE}.lib ${MBEDX509_LIBRARY_FILE}.lib ${MBEDCRYPTO_LIBRARY_FILE}.lib)
SET(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY_FILE}.lib ${MBEDX509_LIBRARY_FILE}.lib ${MBEDTLS_CRYPTO_LIBRARY_FILE}.lib)
else()
SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}")
SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDTLS_CRYPTO_LIBRARY_FILE}")
endif()
IF(NOT MBEDTLS_FIND_QUIETLY)

View File

@@ -65,9 +65,9 @@ elseif (APPLE)
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/trace/include")
else()
set_target_properties(libimhex PROPERTIES
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../libimhex.so"
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/libimhex.so"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex/include")
set_target_properties(tracing PROPERTIES
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../libtracing.a"
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libtracing.a"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/trace/include")
endif()

View File

@@ -15,8 +15,8 @@ AppDir:
- "{{ARCHITECTURE_PACKAGE}}"
allow_unauthenticated: true
sources:
- sourceline: 'deb [arch=amd64] http://us.archive.ubuntu.com/ubuntu/ oracular main restricted universe multiverse'
- sourceline: 'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ oracular main restricted universe multiverse'
- sourceline: 'deb [arch=amd64] https://us.archive.ubuntu.com/ubuntu/ noble main restricted universe multiverse'
- sourceline: 'deb [arch=arm64] https://ports.ubuntu.com/ubuntu-ports/ noble main restricted universe multiverse'
include:
- libgdk-pixbuf2.0-0
- libgdk-pixbuf2.0-common

View File

@@ -1,4 +1,4 @@
FROM ubuntu:24.10 as build
FROM ubuntu:24.04 as build
# Used to invalidate layer cache but not mount cache
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493
@@ -30,9 +30,9 @@ ARG LTO=ON
ARG BUILD_TYPE=RelWithDebInfo
ARG GIT_COMMIT_HASH
ARG GIT_BRANCH
ARG ARCHITECTURE_PACKAGE
ARG ARCHITECTURE_FILE_NAME
ARG ARCHITECTURE_APPIMAGE_BUILDER
ARG ARCHITECTURE_PACKAGE=x86_64
ARG ARCHITECTURE_FILE_NAME=amd64
ARG ARCHITECTURE_APPIMAGE_BUILDER=x86_64
WORKDIR /build
# Ubuntu sh doesnt support string substitution
@@ -42,16 +42,18 @@ RUN <<EOF
# Prepare ImHex build
set -xe
CC=gcc-14 CXX=g++-14 cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX="/usr" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_COMMIT_HASH_LONG="${GIT_COMMIT_HASH}" \
-DIMHEX_COMMIT_BRANCH="${GIT_BRANCH}" \
-DIMHEX_ENABLE_LTO=${LTO} \
-DIMHEX_PLUGINS_IN_SHARE=ON \
CC=gcc-14 CXX=g++-14 cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX="/usr" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_COMMIT_HASH_LONG="${GIT_COMMIT_HASH}" \
-DIMHEX_COMMIT_BRANCH="${GIT_BRANCH}" \
-DIMHEX_ENABLE_LTO=${LTO} \
-DIMHEX_BUNDLE_PLUGIN_SDK=OFF \
`# To prevent using a libdir with an architecture-specific name` \
-DCMAKE_INSTALL_LIBDIR="lib" \
/imhex
EOF

View File

@@ -4,7 +4,7 @@ Section: editors
Priority: optional
Architecture: amd64
License: GNU GPL-2
Depends: libfontconfig1, libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal, libssh2-1, md4c
Depends: libfontconfig1, libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal, libssh2-1, libmd4c0
Maintainer: WerWolv <hey@werwolv.net>
Description: ImHex Hex Editor
A Hex Editor for Reverse Engineers, Programmers and

13
dist/ImHex.run.xml vendored Normal file
View File

@@ -0,0 +1,13 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="ImHex" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" WORKING_DIR="file://$CMakeCurrentBuildDir$" PASS_PARENT_ENVS_2="true" PROJECT_NAME="ImHex" TARGET_NAME="imhex_all" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="ImHex" RUN_TARGET_NAME="main">
<envs>
<env name="NO_DEBUG_BANNER" value="1" />
</envs>
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<configuration default="false" name="CMake Debug" type="CMakeListConfigurationType" factoryName="CMakeListConfigurationFactory">
<method v="2" />
</configuration>
</component>

3
dist/cli/imhex.bat vendored Normal file
View File

@@ -0,0 +1,3 @@
@echo off
start "" "%~dp0..\imhex.exe" %*

5
dist/cli/imhex.sh vendored Normal file
View File

@@ -0,0 +1,5 @@
#!/bin/sh
script_path=$(readlink -f "$0")
script_dir=$(dirname "${script_path}")
"${script_dir}/../imhex" "$@" > /dev/null 2>&1 &

View File

@@ -3,7 +3,7 @@
On macOS, ImHex is built through regular GCC and LLVM clang.
1. Clone the repo using `git clone https://github.com/WerWolv/ImHex --recurse-submodules`
2. Install all the dependencies using `brew bundle --no-lock --file dist/macOS/Brewfile`
2. Install all the dependencies using `brew bundle --file dist/macOS/Brewfile`
3. Build ImHex itself using the following commands:
```sh
cd ImHex
@@ -20,3 +20,5 @@ cmake -G "Ninja" \
..
ninja install
```
If your MacOS installation doesn't have graphic acceleration, you can check the [MacOS NoGPU guide](./macos_nogpu.md)

10
dist/compiling/macos_nogpu.md vendored Normal file
View File

@@ -0,0 +1,10 @@
### Compiling and running ImHex on macOS without a GPU
In order to run ImHex on a macOS installation without a GPU, you need a custom build of GLFW. You can build it this way:
Note: only tested on macOS x86
1. `git clone --depth 1 https://github.com/glfw/glfw`
2. `git apply {IMHEX_DIR}/dist/macOS/0001-glfw-SW.patch` (file is [here](../macOS/0001-glfw-SW.patch) in the ImHex repository. [Source](https://github.com/glfw/glfw/issues/2080).)
3. `cmake -G "Ninja" -DBUILD_SHARED_LIBS=ON ..`
4. `ninja install`, or `ninja` and figure out how to make ImHex detect the shared library

54
dist/flake.nix vendored Normal file
View File

@@ -0,0 +1,54 @@
{
description = "ImHex";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs = { self, nixpkgs }:
let
supportedSystems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin" ];
forAllSystems = f: nixpkgs.lib.genAttrs supportedSystems (system: f system);
in {
devShells = forAllSystems (system:
let
pkgs = import nixpkgs { inherit system; };
in
{
default = pkgs.mkShell {
buildInputs = [
pkgs.cmake
pkgs.clang
pkgs.lld
pkgs.nghttp3
pkgs.pkg-config
pkgs.glfw
pkgs.fontconfig
pkgs.file
pkgs.mbedtls
pkgs.freetype
pkgs.dbus
pkgs.gtk3
pkgs.curl
pkgs.fmt
pkgs.yara
pkgs.nlohmann_json
pkgs.ninja
pkgs.zlib
pkgs.bzip2
pkgs.xz
pkgs.zstd
pkgs.lz4
pkgs.libssh2
pkgs.md4c
];
shellHook = ''
export CC=${pkgs.clang}/bin/clang
export CXX=${pkgs.clang}/bin/clang++
'';
};
});
};
}

View File

@@ -120,6 +120,7 @@ modules:
- -DUSE_SYSTEM_FMT=ON
- -DUSE_SYSTEM_YARA=ON
- -DIMHEX_OFFLINE_BUILD=ON
- -DIMHEX_BUNDLE_PLUGIN_SDK=OFF
- -DCMAKE_INSTALL_LIBDIR=lib
- -DCMAKE_INSTALL_RPATH='$ORIGIN/../lib:$ORIGIN/../lib64'
sources:

View File

@@ -1,5 +1,5 @@
From 9c8665af4c2e2ce66555c15c05c72027bfdf0cb6 Mon Sep 17 00:00:00 2001
From: iTrooz <itrooz@protonmail.com>
From: iTrooz <hey@itrooz.fr>
Date: Mon, 29 Aug 2022 17:29:38 +0200
Subject: [PATCH] Use software rendering on MacOS

View File

@@ -1,7 +1,7 @@
# This base image is also known as "crosscompile". See arm64.crosscompile.Dockerfile
FROM ghcr.io/werwolv/macos-crosscompile:clang20-nosdk as build
FROM ghcr.io/werwolv/macos-crosscompile:6d89b20ac5ebedb6f680f94637591c94cb36f40b as build
ENV MACOSX_DEPLOYMENT_TARGET 13.0
ENV MACOSX_DEPLOYMENT_TARGET 11.0
# -- DOWNLOADING STUFF
@@ -17,13 +17,13 @@ cp /tmp/arm-osx-mytriplet.cmake /vcpkg/triplets/community/arm-osx-mytriplet.cmak
EOF
## Install make
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y make
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y make cmake
## fix environment
### add install_name_tool for cmake command that won't have the right env set (see PostprocessBundle.cmake function postprocess_bundle())
RUN cp /osxcross/build/cctools-port/cctools/misc/install_name_tool /usr/bin/install_name_tool
### a cmake thing wants 'otool' and not '' apparently
RUN cp /osxcross/target/bin/aarch64-apple-darwin23-otool /usr/bin/otool
RUN cp /osxcross/target/bin/aarch64-apple-darwin24-otool /usr/bin/otool
## Clone glfw
RUN <<EOF
@@ -36,10 +36,10 @@ EOF
RUN --mount=type=cache,target=/cache <<EOF
## Download SDK is missing (it may have been removed from the image)
set -xe
if [ ! -d /osxcross/target/SDK/MacOSX14.0.sdk ]; then
wget https://github.com/joseluisq/macosx-sdks/releases/download/14.0/MacOSX14.0.sdk.tar.xz -O /cache/MacOSX14.0.sdk.tar.xz -nc || true
if [ ! -d /osxcross/target/SDK/MacOSX15.0.sdk ]; then
wget https://github.com/joseluisq/macosx-sdks/releases/download/15.0/MacOSX15.0.sdk.tar.xz -O /cache/MacOSX15.0.sdk.tar.xz -nc || true
mkdir -p /osxcross/target/SDK
tar -C /osxcross/target/SDK -xf /cache/MacOSX14.0.sdk.tar.xz
tar -C /osxcross/target/SDK -xf /cache/MacOSX15.0.sdk.tar.xz
fi
EOF
@@ -101,7 +101,7 @@ RUN --mount=type=cache,target=/cache <<EOF
make -j $JOBS install
# Now, we cross-compile it and install it in the libraries folder
CC=/osxcross/target/bin/aarch64-apple-darwin23-clang CXX=/osxcross/target/bin/aarch64-apple-darwin23-clang++ ./configure --prefix /vcpkg/installed/arm-osx-mytriplet --host $OSXCROSS_HOST
CC=/osxcross/target/bin/aarch64-apple-darwin24-clang CXX=/osxcross/target/bin/aarch64-apple-darwin24-clang++ ./configure --prefix /vcpkg/installed/arm-osx-mytriplet --host $OSXCROSS_HOST
make -j $JOBS
make install
@@ -132,6 +132,7 @@ if [ "$CUSTOM_GLFW" ]; then
mkdir build
cd build
CC=o64-clang CXX=o64-clang++ cmake -G "Ninja" \
-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DBUILD_SHARED_LIBS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
@@ -139,7 +140,7 @@ if [ "$CUSTOM_GLFW" ]; then
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_INSTALL_PREFIX=/vcpkg/installed/arm-osx-mytriplet \
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 \
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=13.3 \
..
ninja -j $JOBS install
@@ -150,25 +151,25 @@ EOF
# Build ImHex
## Copy ImHex
COPY --from=imhex / /mnt/ImHex
## Patch ImHex with hacks
# COPY toolchain.cmake.2 /osxcross/target/toolchain.cmake
# Configure ImHex build
## Configure ImHex build
RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/_deps \
cd /mnt/ImHex && \
# compilers
CC=o64-clang CXX=o64-clang++ OBJC=/osxcross/target/bin/aarch64-apple-darwin23-clang OBJCXX=/osxcross/target/bin/aarch64-apple-darwin23-clang++ \
CC=o64-clang CXX=o64-clang++ OBJC=/osxcross/target/bin/aarch64-apple-darwin24-clang OBJCXX=/osxcross/target/bin/aarch64-apple-darwin24-clang++ \
cmake -G "Ninja" \
`# ccache flags` \
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_OBJC_COMPILER_LAUNCHER=ccache -DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
`# MacOS cross-compiling flags` \
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 \
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=13.3 \
`# Override compilers for code generators` \
-DNATIVE_CMAKE_C_COMPILER=/usr/bin/clang -DNATIVE_CMAKE_CXX_COMPILER=/usr/bin/clang++ \
`# Normal ImHex flags` \
-DIMHEX_GENERATE_PACKAGE=ON -DCMAKE_BUILD_TYPE=$BUILD_TYPE \
`# other flags` \
-DIMHEX_STRICT_WARNINGS=OFF \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
-DCMAKE_INSTALL_PREFIX=/mnt/ImHex/build/install \
-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \
-B build
## Build ImHex
RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/_deps <<EOF
@@ -183,4 +184,4 @@ EOF
FROM scratch
COPY --from=build /mnt/ImHex/build/install/imhex.app imhex.app
COPY --from=build /mnt/ImHex/build/install/ImHex.app ImHex.app

View File

@@ -4,9 +4,9 @@ FROM ubuntu:22.04
ENV PATH $PATH:/osxcross/target/bin
ENV LD_LIBRARY_PATH /osxcross/target/lib
ENV OSXCROSS_SDK /osxcross/target/SDK/MacOSX14.0.sdk
ENV OSXCROSS_TARGET darwin23
ENV OSXCROSS_TARGET darwin24
ENV OSXCROSS_TARGET_DIR /osxcross/target
ENV OSXCROSS_HOST aarch64-apple-darwin23
ENV OSXCROSS_HOST aarch64-apple-darwin24
# -- DOWNLOADING STUFF

11
dist/macOS/osx_10_15/x64-osx.cmake vendored Normal file
View File

@@ -0,0 +1,11 @@
set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_BUILD_TYPE release)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_CMAKE_SYSTEM_NAME Darwin)
set(VCPKG_OSX_ARCHITECTURES x86_64)
set(VCPKG_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "" FORCE)
set(VCPKG_C_FLAGS "-mmacosx-version-min=10.15")
set(VCPKG_CXX_FLAGS "-mmacosx-version-min=10.15")
set(ENV{MACOSX_DEPLOYMENT_TARGET} "10.15")

View File

@@ -38,7 +38,7 @@
<url type="homepage">https://imhex.werwolv.net</url>
<url type="bugtracker">https://github.com/WerWolv/ImHex/issues</url>
<url type="help">https://docs.werwolv.net/imhex</url>
<url type="donation">https://www.patreon.com/werwolv</url>
<url type="donation">https://github.com/sponsors/WerWolv</url>
<url type="contact">https://imhex.werwolv.net/discord</url>
<url type="vcs-browser">https://github.com/WerWolv/ImHex</url>
<url type="contribute">https://github.com/WerWolv/ImHex/blob/master/CONTRIBUTING.md</url>
@@ -64,4 +64,8 @@
</release>
</releases>
<update_contact>hey@werwolv.net</update_contact>
<recommends>
<control>keyboard</control>
<control>pointing</control>
</recommends>
</component>

4
dist/rpm/imhex.spec vendored
View File

@@ -145,8 +145,7 @@ appstream-util validate-relax --nonet %{buildroot}%{_metainfodir}/net.werwolv.Im
# install licenses
%if 0%{?rhel} == 9
cp -a lib/third_party/capstone/LICENSE.TXT %{buildroot}%{_datadir}/licenses/%{name}/capstone-LICENSE
cp -a lib/third_party/capstone/suite/regress/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/capstone-regress-LICENSE
cp -a lib/third_party/capstone/LICENSES/LICENSE.TXT %{buildroot}%{_datadir}/licenses/%{name}/capstone-LICENSE
%endif
cp -a lib/third_party/microtar/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/microtar-LICENSE
cp -a lib/third_party/xdgpp/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/xdgpp-LICENSE
@@ -156,6 +155,7 @@ cp -a lib/third_party/xdgpp/LICENSE %{buildroot
%license %{_datadir}/licenses/%{name}/
%doc README.md
%{_bindir}/imhex
%{_datadir}/imhex/imhex
%{_datadir}/pixmaps/%{name}.*
%{_datadir}/applications/%{name}.desktop
%{_libdir}/libimhex.so.*

View File

@@ -1,7 +1,7 @@
name: imhex
title: ImHex
base: core24
version: ${IMHEX_VERSION}
version: ${IMHEX_VERSION_STRING}
summary: Hex editor for reverse engineering
description: ImHex is a hex editor for reverse engineering, reverse engineering, and analyzing binary files. It provides a powerful and flexible interface for working with binary data, including features like pattern matching, scripting, and a customizable user interface.
grade: stable
@@ -40,6 +40,8 @@ parts:
- -DCMAKE_BUILD_TYPE=Release
- -DCMAKE_C_COMPILER_LAUNCHER=${CCACHE}
- -DCMAKE_CXX_COMPILER_LAUNCHER=${CCACHE}
- -DIMHEX_PATTERNS_PULL_MASTER=ON
- -DIMHEX_BUNDLE_PLUGIN_SDK=OFF
cmake-generator: Ninja
build-packages:
- cmake

14
dist/web/Dockerfile vendored
View File

@@ -1,8 +1,8 @@
FROM emscripten/emsdk:4.0.8 AS build
FROM emscripten/emsdk:4.0.21 AS build
# Used to invalidate layer cache but not mount cache
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493
ARG UNIQUEKEY 1
ARG UNIQUEKEY=1
RUN apt update
RUN apt install -y git ccache autoconf automake libtool pkg-config ninja-build
@@ -12,13 +12,13 @@ RUN <<EOF
# Note: we are a patch on the libmagic port
set -xe
git clone https://github.com/microsoft/vcpkg /vcpkg
git -C /vcpkg pull
git clone --depth 1 https://github.com/microsoft/vcpkg /vcpkg
/vcpkg/bootstrap-vcpkg.sh
sed -i 's/vcpkg_install_make(${EXTRA_ARGS})/vcpkg_install_make(${EXTRA_ARGS} SUBPATH src)/g' /vcpkg/ports/libmagic/portfile.cmake
EOF
# Patch vcpkg build instructions to add -pthread
# Patch vcpkg build instructions to add -pthread flag
# Even dependencies must be built with -pthread to be able to use USE_PTHREADS=1
RUN <<EOF
set -xe
@@ -50,6 +50,7 @@ ENV CCACHE_DIR=/cache/ccache
RUN mkdir /build
WORKDIR /build
ARG BUILD_TYPE=Release
RUN --mount=type=cache,target=/cache \
--mount=type=bind,source=.,target=/imhex <<EOF
@@ -70,7 +71,7 @@ ccache -zs
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
-DLIBROMFS_COMPRESS_RESOURCES=OFF \
-DIMHEX_ENABLE_PLUGIN_TESTS=OFF \
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_BUILD_TYPE=${BUILD_TYPE}
ninja -j $JOBS
@@ -106,3 +107,4 @@ COPY --from=build [ \
FROM nginx
COPY --from=raw . /usr/share/nginx/html
RUN chmod -R 755 /usr/share/nginx/html

9
dist/web/Host.Dockerfile vendored Normal file
View File

@@ -0,0 +1,9 @@
FROM python:3.12-slim
WORKDIR /imhex
COPY ./out/ .
EXPOSE 9090
CMD [ "python", "/imhex/start_imhex_web.py" ]

View File

@@ -1,5 +1,4 @@
# docker compose -f dist/web/compose.yml up --build
version: '3'
services:
imhex_web:
image: imhex_web:latest

View File

@@ -15,17 +15,17 @@
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://imhex.werwolv.net/">
<meta property="og:url" content="https://web.imhex.werwolv.net/">
<meta property="og:title" content="ImHex Web - Online Hex Editor">
<meta property="og:image" content="https://imhex.werwolv.net/assets/splash_wasm.png">
<meta property="og:image" content="splash_wasm.png">
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:url" content="https://imhex.werwolv.net/">
<meta property="twitter:url" content="https://web.imhex.werwolv.net/">
<meta property="twitter:title" content="ImHex Web - Online Hex Editor">
<meta property="twitter:description"
content="A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.">
<meta property="twitter:image" content="https://imhex.werwolv.net/assets/splash_wasm.png">
<meta property="twitter:image" content="splash_wasm.png">
<link rel="stylesheet" type="text/css" href="style.css">
@@ -37,8 +37,8 @@
"email": "hey@werwolv.net",
"founder": "WerWolv",
"slogan": "A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.",
"url": "https://imhex.werwolv.net",
"logo": "https://imhex.werwolv.net/assets/logos/logo.svg"
"url": "https://web.imhex.werwolv.net",
"logo": "https://web.imhex.werwolv.net/icon.svg"
}
</script>

BIN
dist/web/source/splash_wasm.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 KiB

View File

@@ -59,8 +59,14 @@ monkeyPatch((file, done) => {
const mibTotal = (wasmSize / 1024**2).toFixed(1);
let root = document.querySelector(':root');
root.style.setProperty("--progress", `${percent}%`)
document.getElementById("progress-bar-content").innerHTML = `${percent}% &nbsp;[${mibNow} MiB / ${mibTotal} MiB]`;
if (root != null) {
root.style.setProperty("--progress", `${percent}%`)
let progressBar = document.getElementById("progress-bar-content");
if (progressBar != null) {
progressBar.innerHTML = `${percent}% &nbsp;[${mibNow} MiB / ${mibTotal} MiB]`;
}
}
});
function glfwSetCursorCustom(wnd, shape) {
@@ -100,7 +106,9 @@ var notWorkingTimer = setTimeout(() => {
}, 5000);
var Module = {
preRun: [],
preRun: () => {
ENV.IMHEX_SKIP_SPLASH_SCREEN = "1";
},
postRun: function() {
// Patch the emscripten GLFW module to send mouse and touch events in the right order
// For ImGui interactions to correctly work with touch input, MousePos events need
@@ -158,7 +166,7 @@ var Module = {
if (status == 1) {
GLFW.active.buttons |= (1 << eventButton);
try {
event.target.setCapture();
event.target.setPointerCapture(event.pointerId);
} catch (e) {}
} else {
GLFW.active.buttons &= ~(1 << eventButton);
@@ -174,7 +182,9 @@ var Module = {
},
onRuntimeInitialized: function() {
// Triggered when the wasm module is loaded and ready to use.
document.getElementById("loading").style.display = "none"
let loading = document.getElementById("loading");
if (loading != null)
document.getElementById("loading").style.display = "none"
document.getElementById("canvas").style.display = "initial"
clearTimeout(notWorkingTimer);
@@ -188,6 +198,8 @@ var Module = {
e.preventDefault();
}, false);
js_resizeCanvas()
// Turn long touches into right-clicks
let timer = null;
canvas.addEventListener('touchstart', event => {
@@ -257,15 +269,17 @@ if (urlParams.has("lang")) {
Module["arguments"].push(urlParams.get("save-editor"));
}
window.addEventListener('resize', js_resizeCanvas, false);
function js_resizeCanvas() {
let canvas = document.getElementById('canvas');
canvas.top = document.documentElement.clientTop;
canvas.left = document.documentElement.clientLeft;
canvas.width = Math.min(document.documentElement.clientWidth, window.innerWidth || 0);
canvas.height = Math.min(document.documentElement.clientHeight, window.innerHeight || 0);
canvas.top = canvas.parentElement.clientTop;
canvas.left = canvas.parentElement.clientLeft;
canvas.style.width = "100%";
canvas.style.height = "100%";
}
let resizeObserver = new ResizeObserver(js_resizeCanvas);
resizeObserver.observe(document.getElementById("canvas"))
// Prevent some default browser shortcuts from preventing ImHex ones to work
document.addEventListener('keydown', e => {

View File

@@ -42,6 +42,7 @@ set(LIBIMHEX_SOURCES
source/helpers/keys.cpp
source/helpers/udp_server.cpp
source/helpers/scaling.cpp
source/helpers/binary_pattern.cpp
source/test/tests.cpp
@@ -56,19 +57,13 @@ set(LIBIMHEX_SOURCES
source/ui/toast.cpp
source/ui/banner.cpp
source/mcp/client.cpp
source/mcp/server.cpp
source/subcommands/subcommands.cpp
)
if (APPLE)
set(OSX_SDK_PATH /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.sdk)
if (NOT CMAKE_OSX_SYSROOT)
if (IS_DIRECTORY ${OSX_SDK_PATH})
set(CMAKE_OSX_SYSROOT ${OSX_SDK_PATH})
else ()
message(WARNING "CMAKE_OSX_SYSROOT not set and macOS SDK not found! Using default one.")
endif ()
endif ()
set(LIBIMHEX_SOURCES ${LIBIMHEX_SOURCES}
source/helpers/utils_macos.m
source/helpers/macos_menu.m

View File

@@ -145,62 +145,17 @@ EXPORT_MODULE namespace hex {
* @brief Returns the icon of the achievement
* @return Icon of the achievement
*/
[[nodiscard]] const ImGuiExt::Texture &getIcon() const {
if (m_iconData.empty())
return m_icon;
if (m_icon.isValid())
return m_icon;
m_icon = ImGuiExt::Texture::fromImage(m_iconData.data(), m_iconData.size(), ImGuiExt::Texture::Filter::Linear);
return m_icon;
[[nodiscard]] const char* getIcon() const {
return m_icon.c_str();
}
/**
* @brief Sets the icon of the achievement
* @param data Icon data
* @param icon Icon glyph
* @return Reference to the achievement
*/
Achievement& setIcon(std::span<const std::byte> data) {
m_iconData.reserve(data.size());
for (auto &byte : data)
m_iconData.emplace_back(static_cast<u8>(byte));
return *this;
}
/**
* @brief Sets the icon of the achievement
* @param data Icon data
* @return Reference to the achievement
*/
Achievement& setIcon(std::span<const u8> data) {
m_iconData.assign(data.begin(), data.end());
return *this;
}
/**
* @brief Sets the icon of the achievement
* @param data Icon data
* @return Reference to the achievement
*/
Achievement& setIcon(std::vector<u8> data) {
m_iconData = std::move(data);
return *this;
}
/**
* @brief Sets the icon of the achievement
* @param data Icon data
* @return Reference to the achievement
*/
Achievement& setIcon(const std::vector<std::byte> &data) {
m_iconData.reserve(data.size());
for (auto &byte : data)
m_iconData.emplace_back(static_cast<u8>(byte));
Achievement& setIcon(std::string icon) {
m_icon = std::move(icon);
return *this;
}
@@ -284,8 +239,7 @@ EXPORT_MODULE namespace hex {
std::function<void(Achievement &)> m_clickCallback;
std::vector<u8> m_iconData;
mutable ImGuiExt::Texture m_icon;
std::string m_icon;
u32 m_progress = 0;
u32 m_maxProgress = 1;

View File

@@ -16,7 +16,7 @@ EXPORT_MODULE namespace hex {
void stopServices();
}
void registerService(const UnlocalizedString &unlocalizedString, const impl::Callback &callback);
void registerService(const UnlocalizedString &unlocalizedName, const impl::Callback &callback);
}
}

View File

@@ -7,6 +7,8 @@
#include <map>
#include <string>
#include <hex/mcp/server.hpp>
EXPORT_MODULE namespace hex {
/* Network Communication Interface Registry. Allows adding new communication interface endpoints */
@@ -22,4 +24,19 @@ EXPORT_MODULE namespace hex {
}
namespace ContentRegistry::MCP {
namespace impl {
std::unique_ptr<mcp::Server>& getMcpServerInstance();
void setEnabled(bool enabled);
}
bool isEnabled();
bool isConnected();
void registerTool(std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json &params)> function);
}
}

View File

@@ -27,9 +27,10 @@ EXPORT_MODULE namespace hex {
struct FindOccurrence {
Region region;
enum class DecodeType { ASCII, UTF8, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
std::endian endian = std::endian::native;
enum class DecodeType : u8 { ASCII, UTF8, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
bool selected;
std::string string;
};
using FindExporterCallback = std::function<std::vector<u8>(const std::vector<FindOccurrence>&, std::function<std::string(FindOccurrence)>)>;

View File

@@ -8,6 +8,7 @@
#include <optional>
#include <string>
#include <vector>
#include <bit>
EXPORT_MODULE namespace hex {
@@ -22,8 +23,10 @@ EXPORT_MODULE namespace hex {
namespace impl {
struct DoNotUseThisByItselfTag {};
using DisplayFunction = std::function<std::string()>;
using EditingFunction = std::function<std::vector<u8>(std::string, std::endian)>;
using EditingFunction = std::function<std::optional<std::vector<u8>>(std::string&, std::endian, DoNotUseThisByItselfTag)>;
using GeneratorFunction = std::function<DisplayFunction(const std::vector<u8> &, std::endian, NumberDisplayStyle)>;
struct Entry {
@@ -38,6 +41,35 @@ EXPORT_MODULE namespace hex {
}
namespace EditWidget {
class Widget {
public:
using Function = std::function<std::vector<u8>(const std::string&, std::endian)>;
explicit Widget(const Function &function) : m_function(function) {}
virtual ~Widget() = default;
virtual std::optional<std::vector<u8>> draw(std::string &value, std::endian endian) = 0;
std::optional<std::vector<u8>> operator()(std::string &value, std::endian endian, impl::DoNotUseThisByItselfTag) {
return draw(value, endian);
}
std::vector<u8> getBytes(const std::string &value, std::endian endian) const {
return m_function(value, endian);
}
private:
Function m_function;
};
struct TextInput : Widget {
explicit TextInput(const Function &function) : Widget(function) {}
std::optional<std::vector<u8>> draw(std::string &value, std::endian endian) override;
};
}
/**
* @brief Adds a new entry to the data inspector
* @param unlocalizedName The unlocalized name of the entry

View File

@@ -38,24 +38,14 @@ EXPORT_MODULE namespace hex {
[[nodiscard]] const Hash *getType() const { return m_type; }
[[nodiscard]] const std::string& getName() const { return m_name; }
const std::vector<u8>& get(const Region& region, prv::Provider *provider) {
if (m_cache.empty()) {
m_cache = m_callback(region, provider);
}
return m_cache;
}
void reset() {
m_cache.clear();
std::vector<u8> get(const Region& region, prv::Provider *provider) const {
return m_callback(region, provider);
}
private:
Hash *m_type;
std::string m_name;
Callback m_callback;
std::vector<u8> m_cache;
};
virtual void draw() { }

View File

@@ -19,7 +19,7 @@ EXPORT_MODULE namespace hex {
void addProviderName(const UnlocalizedString &unlocalizedName, const char *icon);
using ProviderCreationFunction = std::function<std::unique_ptr<prv::Provider>()>;
using ProviderCreationFunction = std::function<std::shared_ptr<prv::Provider>()>;
void add(const std::string &typeName, ProviderCreationFunction creationFunction);
struct Entry {

View File

@@ -52,7 +52,7 @@ EXPORT_MODULE namespace hex {
return *this;
}
Interface& setTooltip(const std::string &tooltip) {
Interface& setTooltip(const UnlocalizedString &tooltip) {
m_tooltip = tooltip;
return *this;
@@ -239,6 +239,14 @@ EXPORT_MODULE namespace hex {
nlohmann::json store() override { return {}; }
};
class Spacer : public Widget {
public:
bool draw(const std::string &name) override;
void load(const nlohmann::json &) override {}
nlohmann::json store() override { return {}; }
};
}
namespace impl {
@@ -290,8 +298,8 @@ EXPORT_MODULE namespace hex {
public:
SettingsValue(nlohmann::json value) : m_value(std::move(value)) {}
template<typename T>
T get(std::common_type_t<T> defaultValue) const {
template<typename T> requires (!(std::is_reference_v<T> || std::is_const_v<T>))
[[nodiscard]] T get(T defaultValue) const {
try {
auto result = m_value;
if (result.is_number() && std::same_as<T, bool>)
@@ -308,8 +316,8 @@ EXPORT_MODULE namespace hex {
nlohmann::json m_value;
};
template<typename T>
[[nodiscard]] T read(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const std::common_type_t<T> &defaultValue) {
template<typename T> requires (!(std::is_reference_v<T> || std::is_const_v<T>))
[[nodiscard]] T read(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, T defaultValue) {
auto setting = impl::getSetting(unlocalizedCategory, unlocalizedName, defaultValue);
try {
@@ -326,8 +334,8 @@ EXPORT_MODULE namespace hex {
}
}
template<typename T>
void write(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const std::common_type_t<T> &value) {
template<typename T> requires (!(std::is_reference_v<T> || std::is_const_v<T>))
void write(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, T value) {
impl::getSetting(unlocalizedCategory, unlocalizedName, value) = value;
impl::runOnChangeHandlers(unlocalizedCategory, unlocalizedName, value);
@@ -336,10 +344,75 @@ EXPORT_MODULE namespace hex {
using OnChangeCallback = std::function<void(const SettingsValue &)>;
u64 onChange(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const OnChangeCallback &callback);
void removeOnChangeHandler(u64 id);
using OnSaveCallback = std::function<void()>;
u64 onSave(const OnSaveCallback &callback);
template<typename T, wolv::type::StaticString UnlocalizedCategory, wolv::type::StaticString UnlocalizedName>
requires (!(std::is_reference_v<T> || std::is_const_v<T>))
class SettingsVariable {
public:
explicit(false) SettingsVariable(T defaultValue) : m_defaultValue(std::move(defaultValue)) { }
SettingsVariable(const SettingsVariable&) = delete;
SettingsVariable& operator=(const SettingsVariable&) = delete;
SettingsVariable(SettingsVariable&&) = delete;
SettingsVariable& operator=(SettingsVariable&&) = delete;
~SettingsVariable() {
if (m_onChangeId > 0)
removeOnChangeHandler(m_onChangeId);
}
[[nodiscard]] T get() const {
registerChangeHandler();
if (!m_value.has_value()) {
m_value = read<T>(
UnlocalizedCategory.value.data(),
UnlocalizedName.value.data(),
m_defaultValue
);
}
return m_value.value_or(m_defaultValue);
}
void set(T value) {
registerChangeHandler();
write<T>(
UnlocalizedCategory.value.data(),
UnlocalizedName.value.data(),
std::move(value)
);
}
explicit(false) operator T() const {
return get();
}
SettingsVariable& operator=(T value) {
set(std::move(value));
return *this;
}
private:
void registerChangeHandler() const {
if (m_onChangeId > 0)
return;
m_onChangeId = onChange(UnlocalizedCategory.value.data(), UnlocalizedName.value.data(), [this](const SettingsValue &value) {
m_value = value.get<T>(m_defaultValue);
});
}
private:
mutable std::optional<T> m_value;
T m_defaultValue;
mutable u64 m_onChangeId = 0;
};
}
}

View File

@@ -68,6 +68,7 @@ EXPORT_MODULE namespace hex {
constexpr static auto SeparatorValue = "$SEPARATOR$";
constexpr static auto SubMenuValue = "$SUBMENU$";
constexpr static auto TaskBarMenuValue = "$TASKBAR$";
const std::multimap<u32, MainMenuItem>& getMainMenuItems();
@@ -159,13 +160,15 @@ EXPORT_MODULE namespace hex {
* @param function The function to call when the entry is clicked
* @param enabledCallback The function to call to determine if the entry is enabled
* @param view The view to use for the entry. If nullptr, the item will always be visible
* @param showOnWelcomeScreen If this entry should be shown on the welcome screen
*/
void addMenuItemSubMenu(
std::vector<UnlocalizedString> unlocalizedMainMenuNames,
u32 priority,
const impl::MenuCallback &function,
const impl::EnabledCallback& enabledCallback = []{ return true; },
View *view = nullptr
View *view = nullptr,
bool showOnWelcomeScreen = false
);
/**
@@ -176,6 +179,7 @@ EXPORT_MODULE namespace hex {
* @param function The function to call when the entry is clicked
* @param enabledCallback The function to call to determine if the entry is enabled
* @param view The view to use for the entry. If nullptr, the item will always be visible
* @param showOnWelcomeScreen If this entry should be shown on the welcome screen
*/
void addMenuItemSubMenu(
std::vector<UnlocalizedString> unlocalizedMainMenuNames,
@@ -183,7 +187,8 @@ EXPORT_MODULE namespace hex {
u32 priority,
const impl::MenuCallback &function,
const impl::EnabledCallback& enabledCallback = []{ return true; },
View *view = nullptr
View *view = nullptr,
bool showOnWelcomeScreen = false
);
@@ -195,6 +200,19 @@ EXPORT_MODULE namespace hex {
*/
void addMenuItemSeparator(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, View *view = nullptr);
/**
* @brief Adds a new main menu entry
* @param unlocalizedMainMenuNames The unlocalized names of the main menu entries
* @param priority The priority of the entry. Lower values are displayed first
* @param function The function to call when the entry is clicked
* @param enabledCallback The function to call to determine if the entry is enabled
*/
void addTaskBarMenuItem(
std::vector<UnlocalizedString> unlocalizedMainMenuNames,
u32 priority,
const impl::MenuCallback &function,
const impl::EnabledCallback& enabledCallback
);
/**
* @brief Adds a new welcome screen entry
@@ -216,10 +234,10 @@ EXPORT_MODULE namespace hex {
/**
* @brief Adds a menu item to the toolbar
* @param unlocalizedName Unlocalized name of the menu item
* @param unlocalizedNames Unlocalized name of the menu item
* @param color Color of the toolbar icon
*/
void addMenuItemToToolbar(const UnlocalizedString &unlocalizedName, ImGuiCustomCol color);
void addMenuItemToToolbar(const std::vector<UnlocalizedString> &unlocalizedNames, ImGuiCustomCol color);
/**
* @brief Reconstructs the toolbar items list after they have been modified

View File

@@ -79,6 +79,11 @@ namespace hex {
*/
EVENT_DEF(EventProjectOpened);
/**
* @brief Called when a project is saved/saved as
*/
EVENT_DEF(EventProjectSaved);
/**
* @brief Called when a native message was received from another ImHex instance
* @param rawData Raw bytes received from other instance

View File

@@ -15,7 +15,7 @@ namespace hex {
* This event is responsible for (optionally) initializing the provider and calling EventProviderOpened
* (although the event can also be called manually without problem)
*/
EVENT_DEF(EventProviderCreated, prv::Provider *);
EVENT_DEF(EventProviderCreated, std::shared_ptr<prv::Provider>);
/**
* @brief Called as a continuation of EventProviderCreated

View File

@@ -8,7 +8,12 @@ namespace hex {
/**
* @brief Creates a provider from its unlocalized name, and add it to the provider list
*/
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, hex::prv::Provider **);
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, std::shared_ptr<hex::prv::Provider> *);
/**
* @brief Used internally when opening a provider through the API
*/
EVENT_DEF(RequestOpenProvider, std::shared_ptr<prv::Provider>);
/**
* @brief Move the data from all PerProvider instances from one provider to another

View File

@@ -86,7 +86,7 @@ EXPORT_MODULE namespace hex {
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
* @param select Whether to select the provider after adding it
*/
void add(std::unique_ptr<prv::Provider> &&provider, bool skipLoadInterface = false, bool select = true);
void add(std::shared_ptr<prv::Provider> &&provider, bool skipLoadInterface = false, bool select = true);
/**
* @brief Creates a new provider and adds it to the list of providers
@@ -111,12 +111,18 @@ EXPORT_MODULE namespace hex {
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
* @param select Whether to select the provider after adding it
*/
prv::Provider* createProvider(
std::shared_ptr<prv::Provider> createProvider(
const UnlocalizedString &unlocalizedName,
bool skipLoadInterface = false,
bool select = true
);
/**
* @brief Opens a provider, making its data available to ImHex and handling any error that may occur
* @param provider The provider to open
*/
void openProvider(std::shared_ptr<prv::Provider> provider);
}
}

View File

@@ -62,6 +62,7 @@ EXPORT_MODULE namespace hex {
void setMainWindowSize(u32 width, u32 height);
void setMainDockSpaceId(ImGuiID id);
void setMainWindowHandle(GLFWwindow *window);
void setMainWindowFocusState(bool focused);
void setGlobalScale(float scale);
void setNativeScale(float scale);
@@ -161,6 +162,12 @@ EXPORT_MODULE namespace hex {
*/
GLFWwindow* getMainWindowHandle();
/**
* @brief Checks if the main window is currently focused
* @return Whether the main window is focused
*/
bool isMainWindowFocused();
/**
* @brief Checks if borderless window mode is enabled currently
* @return Whether borderless window mode is enabled
@@ -171,7 +178,7 @@ EXPORT_MODULE namespace hex {
* @brief Checks if multi-window mode is enabled currently
* @return Whether multi-window mode is enabled
*/
bool isMutliWindowModeEnabled();
bool isMultiWindowModeEnabled();
/**
* @brief Gets the init arguments passed to ImHex from the splash screen
@@ -276,7 +283,7 @@ EXPORT_MODULE namespace hex {
* @brief Gets the current ImHex version
* @return ImHex version
*/
SemanticVersion getImHexVersion();
const SemanticVersion& getImHexVersion();
/**
* @brief Gets the current git commit hash

View File

@@ -27,6 +27,7 @@ EXPORT_MODULE namespace hex {
LanguageId id;
std::string name, nativeName;
LanguageId fallbackLanguageId;
bool hidden;
std::vector<PathEntry> languageFilePaths;
};
@@ -58,7 +59,6 @@ EXPORT_MODULE namespace hex {
private:
std::size_t m_entryHash;
std::string m_unlocalizedString;
};
class LangConst {
@@ -102,6 +102,14 @@ EXPORT_MODULE namespace hex {
UnlocalizedString(const std::string &string) : m_unlocalizedString(string) { }
UnlocalizedString(const char *string) : m_unlocalizedString(string) { }
UnlocalizedString(const Lang& arg) = delete;
UnlocalizedString(std::string &&string) : m_unlocalizedString(std::move(string)) { }
UnlocalizedString(UnlocalizedString &&) = default;
UnlocalizedString(const UnlocalizedString &) = default;
UnlocalizedString &operator=(const UnlocalizedString &) = default;
UnlocalizedString &operator=(UnlocalizedString &&) = default;
UnlocalizedString &operator=(const std::string &string) { m_unlocalizedString = string; return *this; }
UnlocalizedString &operator=(std::string &&string) { m_unlocalizedString = std::move(string); return *this; }
[[nodiscard]] operator std::string() const {
return m_unlocalizedString;

View File

@@ -151,6 +151,8 @@ EXPORT_MODULE namespace hex {
*/
static void clearShortcuts();
static Shortcut getShortcutByName(const std::vector<UnlocalizedString> &unlocalizedName, const View *view = nullptr);
static void resumeShortcuts();
static void pauseShortcuts();

View File

@@ -10,6 +10,7 @@
#include <condition_variable>
#include <source_location>
#include <thread>
#include <hex/trace/exceptions.hpp>
EXPORT_MODULE namespace hex {
@@ -22,7 +23,7 @@ EXPORT_MODULE namespace hex {
class Task {
public:
Task() = default;
Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function);
Task(UnlocalizedString unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function);
Task(const Task&) = delete;
Task(Task &&other) noexcept;
@@ -70,6 +71,8 @@ EXPORT_MODULE namespace hex {
[[nodiscard]] u64 getValue() const;
[[nodiscard]] u64 getMaxValue() const;
void wait() const;
private:
void finish();
void interruption();
@@ -87,12 +90,21 @@ EXPORT_MODULE namespace hex {
std::atomic<bool> m_background = true;
std::atomic<bool> m_blocking = false;
std::atomic<bool> m_interrupted = false;
std::atomic<bool> m_finished = false;
std::atomic<bool> m_hadException = false;
std::atomic_flag m_interrupted;
std::atomic_flag m_finished;
std::atomic_flag m_hadException;
std::string m_exceptionMessage;
struct TaskInterruptor { virtual ~TaskInterruptor() = default; };
struct TaskInterruptor: public std::exception {
TaskInterruptor() {
trace::disableExceptionCaptureForCurrentThread();
}
virtual ~TaskInterruptor() = default;
[[nodiscard]] const char* what() const noexcept override {
return "Task Interrupted";
}
};
friend class TaskHolder;
friend class TaskManager;
@@ -114,6 +126,7 @@ EXPORT_MODULE namespace hex {
[[nodiscard]] u32 getProgress() const;
void interrupt() const;
void wait() const;
private:
std::weak_ptr<Task> m_task;
};
@@ -239,6 +252,8 @@ EXPORT_MODULE namespace hex {
static const std::list<std::shared_ptr<Task>>& getRunningTasks();
static void runDeferredCalls();
static void addTaskCompletionCallback(const std::function<void(Task&)>& function);
private:
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function);
};

View File

@@ -10,6 +10,8 @@
#include <hex/ui/imgui_imhex_extensions.h>
struct ImRect;
EXPORT_MODULE namespace hex {
class TutorialManager {
@@ -22,6 +24,8 @@ EXPORT_MODULE namespace hex {
Right = 8
};
using DrawFunction = std::function<void()>;
struct Tutorial {
Tutorial() = delete;
Tutorial(const UnlocalizedString &unlocalizedName, const UnlocalizedString &unlocalizedDescription) :
@@ -101,6 +105,7 @@ EXPORT_MODULE namespace hex {
std::vector<Highlight> m_highlights;
std::optional<Message> m_message;
std::function<void()> m_onAppear, m_onComplete;
DrawFunction m_drawFunction;
};
Step& addStep();
@@ -146,6 +151,7 @@ EXPORT_MODULE namespace hex {
* @param unlocalizedName Name of tutorial to start
*/
static void startTutorial(const UnlocalizedString &unlocalizedName);
static void stopCurrentTutorial();
static void startHelpHover();
static void addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString);
@@ -166,6 +172,10 @@ EXPORT_MODULE namespace hex {
*/
static void reset();
static void setRenderer(std::function<DrawFunction(const std::string &)> renderer);
static void postElementRendered(ImGuiID id, const ImRect &boundingBox);
private:
TutorialManager() = delete;

View File

@@ -7,6 +7,7 @@
#include <set>
#include <span>
#include <utility>
#include <vector>
#include <nlohmann/json_fwd.hpp>
@@ -49,9 +50,15 @@ namespace hex::dp {
virtual void store(nlohmann::json &j) const { std::ignore = j; }
virtual void load(const nlohmann::json &j) { std::ignore = j; }
struct NodeError {
struct NodeError: public std::exception {
Node *node;
std::string message;
NodeError(Node *node, std::string message) : node(node), message(std::move(message)) {}
[[nodiscard]] const char* what() const noexcept override {
return this->message.c_str();
}
};
void resetOutputData() {
@@ -102,7 +109,7 @@ namespace hex::dp {
void unmarkInputProcessed(u32 index);
protected:
[[noreturn]] void throwNodeError(const std::string &message);
[[noreturn]] void throwNodeError(const std::string &msg);
void setOverlayData(u64 address, const std::vector<u8> &data);
void setAttributes(std::vector<Attribute> attributes);

View File

@@ -1,6 +1,7 @@
#pragma once
#include <hex/api/imhex_api/system.hpp>
#include <hex/helpers/logger.hpp>
namespace hex {
@@ -9,6 +10,9 @@ namespace hex {
class AutoResetBase {
public:
virtual ~AutoResetBase() = default;
private:
friend void ImHexApi::System::impl::cleanup();
virtual void reset() = 0;
};
@@ -19,16 +23,20 @@ namespace hex {
public:
using Type = T;
AutoReset() {
ImHexApi::System::impl::addAutoResetObject(this);
AutoReset() noexcept {
try {
ImHexApi::System::impl::addAutoResetObject(this);
} catch (std::exception &e) {
log::error("Failed to register AutoReset object: {}", e.what());
}
}
AutoReset(const T &value) : AutoReset() {
explicit(false) AutoReset(const T &value) : AutoReset() {
m_value = value;
m_valid = true;
}
AutoReset(T &&value) noexcept : AutoReset() {
explicit(false) AutoReset(T &&value) noexcept : AutoReset() {
m_value = std::move(value);
m_valid = true;
}
@@ -61,29 +69,27 @@ namespace hex {
return m_value;
}
T& operator=(const T &value) {
AutoReset& operator=(const T &value) {
m_value = value;
m_valid = true;
return m_value;
return *this;
}
T& operator=(T &&value) noexcept {
AutoReset& operator=(T &&value) noexcept {
m_value = std::move(value);
m_valid = true;
return m_value;
return *this;
}
bool isValid() const {
[[nodiscard]] bool isValid() const {
return m_valid;
}
private:
friend void ImHexApi::System::impl::cleanup();
void reset() override {
if constexpr (requires { m_value.reset(); }) {
if constexpr (requires(T t) { t.reset(); }) {
m_value.reset();
} else if constexpr (requires { m_value.clear(); }) {
} else if constexpr (requires(T t) { t.clear(); }) {
m_value.clear();
} else if constexpr (std::is_pointer_v<T>) {
m_value = nullptr; // cppcheck-suppress nullPointer

View File

@@ -10,92 +10,19 @@ namespace hex {
class BinaryPattern {
public:
BinaryPattern() = default;
explicit BinaryPattern(const std::string &pattern);
[[nodiscard]] bool isValid() const;
[[nodiscard]] u64 getSize() const;
[[nodiscard]] bool matches(const std::vector<u8> &bytes) const;
[[nodiscard]] bool matchesByte(u8 byte, u32 offset) const;
struct Pattern {
u8 mask, value;
};
BinaryPattern() = default;
explicit BinaryPattern(const std::string &pattern) : m_patterns(parseBinaryPatternString(pattern)) { }
[[nodiscard]] bool isValid() const { return !m_patterns.empty(); }
[[nodiscard]] bool matches(const std::vector<u8> &bytes) const {
if (bytes.size() < m_patterns.size())
return false;
for (u32 i = 0; i < m_patterns.size(); i++) {
if (!this->matchesByte(bytes[i], i))
return false;
}
return true;
}
[[nodiscard]] bool matchesByte(u8 byte, u32 offset) const {
const auto &pattern = m_patterns[offset];
return (byte & pattern.mask) == pattern.value;
}
[[nodiscard]] u64 getSize() const {
return m_patterns.size();
}
private:
static std::vector<Pattern> parseBinaryPatternString(std::string string) {
std::vector<Pattern> result;
if (string.length() < 2)
return { };
bool inString = false;
while (string.length() > 0) {
Pattern pattern = { 0, 0 };
if (string.starts_with("\"")) {
inString = !inString;
string = string.substr(1);
continue;
} else if (inString) {
pattern = { 0xFF, u8(string.front()) };
string = string.substr(1);
} else if (string.starts_with("??")) {
pattern = { 0x00, 0x00 };
string = string.substr(2);
} else if ((std::isxdigit(string.front()) || string.front() == '?') && string.length() >= 2) {
const auto hex = string.substr(0, 2);
for (const auto &c : hex) {
pattern.mask <<= 4;
pattern.value <<= 4;
if (std::isxdigit(c)) {
pattern.mask |= 0x0F;
if (auto hexValue = hex::hexCharToValue(c); hexValue.has_value())
pattern.value |= hexValue.value();
else
return { };
} else if (c != '?') {
return { };
}
}
string = string.substr(2);
} else if (std::isspace(string.front())) {
string = string.substr(1);
continue;
} else {
return { };
}
result.push_back(pattern);
}
if (inString)
return { };
return result;
}
private:
std::vector<Pattern> m_patterns;
};

View File

@@ -14,6 +14,10 @@
static_assert(false, "Debug variables are only intended for use during development.");
#endif
namespace hex::trace {
struct StackTraceResult;
}
namespace hex::dbg {
namespace impl {
@@ -47,4 +51,6 @@ namespace hex::dbg {
bool debugModeEnabled();
void setDebugModeEnabled(bool enabled);
void printStackTrace(const trace::StackTraceResult &stackTrace);
}

View File

@@ -27,10 +27,11 @@ namespace hex {
EncodingFile& operator=(const EncodingFile &other);
EncodingFile& operator=(EncodingFile &&other) noexcept;
[[nodiscard]] std::pair<std::string_view, size_t> getEncodingFor(std::span<u8> buffer) const;
[[nodiscard]] std::pair<std::string_view, size_t> getEncodingFor(std::span<const u8> buffer) const;
[[nodiscard]] u64 getEncodingLengthFor(std::span<u8> buffer) const;
[[nodiscard]] u64 getShortestSequence() const { return m_shortestSequence; }
[[nodiscard]] u64 getLongestSequence() const { return m_longestSequence; }
[[nodiscard]] std::string decodeAll(std::span<const u8> buffer) const;
[[nodiscard]] bool valid() const { return m_valid; }

View File

@@ -2,7 +2,9 @@
#include <hex.hpp>
#include <hex/api/task_manager.hpp>
#include <hex/helpers/literals.hpp>
#include <hex/helpers/fs.hpp>
#include <string>
#include <vector>
@@ -27,4 +29,14 @@ namespace hex::magic {
bool isValidMIMEType(const std::string &mimeType);
struct FoundPattern {
std::fs::path patternFilePath;
std::string author;
std::string description;
std::optional<std::string> mimeType;
std::optional<u64> magicOffset;
};
std::vector<FoundPattern> findViablePatterns(prv::Provider *provider, Task* task = nullptr);
}

View File

@@ -12,6 +12,9 @@ namespace hex::menu {
bool beginMenu(const char *label, bool enabled = true);
void endMenu();
bool beginTaskBarMenu();
void endTaskBarMenu();
bool beginMenuEx(const char* label, const char* icon, bool enabled = true);
bool menuItem(const char *label, const Shortcut &shortcut = Shortcut::None, bool selected = false, bool enabled = true);

View File

@@ -10,6 +10,7 @@
#include <span>
#include <string>
#include <numbers>
#include <array>
#include <opengl_support.h>
#include "imgui.h"
@@ -935,7 +936,7 @@ namespace hex::gl {
void attachTexture(const Texture &texture) const;
private:
GLuint m_frameBuffer, m_renderBuffer;
GLuint m_frameBuffer = 0, m_renderBuffer = 0;
};
class AxesVectors {

View File

@@ -28,6 +28,8 @@
#include <imgui.h>
#include <wolv/utils/charconv.hpp>
namespace hex {
#if !defined(HEX_MODULE_EXPORT)
@@ -96,6 +98,8 @@ namespace hex {
void startProgram(const std::vector<std::string> &command);
int executeCommand(const std::string &command);
std::optional<std::string> executeCommandWithOutput(const std::string &command);
void executeCommandDetach(const std::string &command);
void openWebpage(std::string url);
extern "C" void registerFont(const char *fontName, const char *fontPath);
@@ -261,7 +265,11 @@ namespace hex {
if (!std::isxdigit(byteString[i]) || !std::isxdigit(byteString[i + 1]))
return {};
result.push_back(std::strtoul(byteString.substr(i, 2).c_str(), nullptr, 16));
auto value = wolv::util::from_chars<u64>(byteString.substr(i, 2), 16);
if (!value.has_value())
return {};
result.push_back(*value);
}
return result;
@@ -362,7 +370,7 @@ namespace hex {
[[nodiscard]] std::optional<std::string> getEnvironmentVariable(const std::string &env);
[[nodiscard]] std::string limitStringLength(const std::string &string, size_t maxLength);
[[nodiscard]] std::string limitStringLength(const std::string &string, size_t maxLength, bool fromBothEnds = true);
[[nodiscard]] std::optional<std::fs::path> getInitialFilePath();

View File

@@ -32,6 +32,7 @@
void macosInstallEventListener();
void toastMessageMacos(const char *title, const char *message);
void macosSetupDockMenu(void);
}
#endif

View File

@@ -0,0 +1,15 @@
#pragma once
#include <iostream>
namespace hex::mcp {
class Client {
public:
Client() = default;
~Client() = default;
int run(std::istream &input, std::ostream &output);
};
}

View File

@@ -0,0 +1,123 @@
#pragma once
#include <hex.hpp>
#include <functional>
#include <nlohmann/json.hpp>
#include <wolv/net/socket_server.hpp>
namespace hex::mcp {
class JsonRpc {
public:
explicit JsonRpc(std::string request) : m_request(std::move(request)){ }
struct MethodNotFoundException : std::exception {};
struct InvalidParametersException : std::exception {};
enum class ErrorCode: i16 {
ParseError = -32700,
InvalidRequest = -32600,
MethodNotFound = -32601,
InvalidParams = -32602,
InternalError = -32603,
};
using Callback = std::function<nlohmann::json(const std::string &method, const nlohmann::json &params)>;
std::optional<std::string> execute(const Callback &callback);
void setError(ErrorCode code, std::string message);
private:
std::optional<nlohmann::json> handleMessage(const nlohmann::json &request, const Callback &callback);
std::optional<nlohmann::json> handleBatchedMessages(const nlohmann::json &request, const Callback &callback);
nlohmann::json createDefaultMessage();
nlohmann::json createErrorMessage(ErrorCode code, const std::string &message);
nlohmann::json createResponseMessage(const nlohmann::json &result);
private:
std::string m_request;
std::optional<int> m_id;
struct Error {
ErrorCode code;
std::string message;
};
std::optional<Error> m_error;
};
struct TextContent {
std::string text;
operator nlohmann::json() const {
nlohmann::json result;
result["content"] = nlohmann::json::array({
nlohmann::json::object({
{ "type", "text" },
{ "text", text }
})
});
return result;
}
};
struct StructuredContent {
std::string text;
nlohmann::json data;
operator nlohmann::json() const {
nlohmann::json result;
result["content"] = nlohmann::json::array({
nlohmann::json::object({
{ "type", "text" },
{ "text", text }
})
});
result["structuredContent"] = data;
return result;
}
};
class Server {
public:
constexpr static auto McpInternalPort = 19743;
Server();
~Server();
void listen();
void shutdown();
void disconnect();
bool isConnected();
void addPrimitive(std::string type, std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json &params)> function);
struct ClientInfo {
std::string name;
std::string version;
std::string protocolVersion;
};
const ClientInfo& getClientInfo() const {
return m_clientInfo;
}
private:
nlohmann::json handleInitialize(const nlohmann::json &params);
void handleNotifications(const std::string &method, const nlohmann::json &params);
struct Primitive {
nlohmann::json capabilities;
std::function<nlohmann::json(const nlohmann::json &params)> function;
};
std::map<std::string, std::map<std::string, Primitive>> m_primitives;
wolv::net::SocketServer m_server;
bool m_connected = false;
ClientInfo m_clientInfo;
};
}

View File

@@ -46,7 +46,7 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
[[maybe_unused]] static auto& getFeaturesImpl() {
static hex::AutoReset<std::vector<hex::Feature>> features;
return features;
return *features;
}
#if defined (IMHEX_STATIC_LINK_PLUGINS)

View File

@@ -21,7 +21,7 @@ namespace hex::prv {
CachedProvider(size_t cacheBlockSize = 4096, size_t maxBlocks = 1024);
~CachedProvider() override;
bool open() override;
OpenResult open() override;
void close() override;
void readRaw(u64 offset, void *buffer, size_t size) override;

View File

@@ -27,7 +27,7 @@ namespace hex::prv {
[[nodiscard]] bool isSavable() const override { return m_name.empty(); }
[[nodiscard]] bool isSavableAsRecent() const override { return false; }
[[nodiscard]] bool open() override;
[[nodiscard]] OpenResult open() override;
void close() override { }
void readRaw(u64 offset, void *buffer, size_t size) override;

View File

@@ -72,6 +72,21 @@ namespace hex::prv {
[[nodiscard]] virtual std::vector<Description> getDataDescription() const = 0;
};
class IProviderDataBackupable {
public:
explicit IProviderDataBackupable(Provider *provider);
virtual ~IProviderDataBackupable() = default;
void createBackupIfNeeded(const std::fs::path &inputFilePath);
private:
Provider *m_provider = nullptr;
bool m_backupCreated = false;
bool m_shouldCreateBackups = true;
u64 m_maxSize;
std::string m_backupExtension;
};
/**
* @brief Represent the data source for a tab in the UI
*/
@@ -79,6 +94,65 @@ namespace hex::prv {
public:
constexpr static u64 MaxPageSize = 0xFFFF'FFFF'FFFF'FFFF;
class OpenResult {
public:
OpenResult() : m_result(std::monostate{}) {}
[[nodiscard]] static OpenResult failure(std::string errorMessage) {
OpenResult result;
result.m_result = std::move(errorMessage);
return result;
}
[[nodiscard]] static OpenResult warning(std::string warningMessage) {
OpenResult result;
result.m_result = std::move(warningMessage);
result.m_warning = true;
return result;
}
[[nodiscard]] static OpenResult redirect(Provider *provider) {
OpenResult result;
result.m_result = provider;
return result;
}
[[nodiscard]] bool isSuccess() const {
return std::holds_alternative<std::monostate>(m_result);
}
[[nodiscard]] bool isFailure() const {
return std::holds_alternative<std::string>(m_result) && !m_warning;
}
[[nodiscard]] bool isWarning() const {
return std::holds_alternative<std::string>(m_result) && m_warning;
}
[[nodiscard]] bool isRedirecting() const {
return std::holds_alternative<Provider*>(m_result);
}
[[nodiscard]] Provider* getRedirectProvider() const {
if (std::holds_alternative<Provider*>(m_result)) {
return std::get<Provider*>(m_result);
}
return nullptr;
}
[[nodiscard]] std::string_view getErrorMessage() const {
if (std::holds_alternative<std::string>(m_result)) {
return std::get<std::string>(m_result);
}
return "";
}
private:
std::variant<std::monostate, std::string, Provider*> m_result;
bool m_warning = false;
};
Provider();
virtual ~Provider();
Provider(const Provider&) = delete;
@@ -94,7 +168,7 @@ namespace hex::prv {
* @note This is not related to the EventProviderOpened event
* @return true if the provider was opened successfully, else false
*/
[[nodiscard]] virtual bool open() = 0;
[[nodiscard]] virtual OpenResult open() = 0;
/**
* @brief Closes this provider
@@ -262,9 +336,6 @@ namespace hex::prv {
void skipLoadInterface() { m_skipLoadInterface = true; }
[[nodiscard]] bool shouldSkipLoadInterface() const { return m_skipLoadInterface; }
void setErrorMessage(const std::string &errorMessage) { m_errorMessage = errorMessage; }
[[nodiscard]] const std::string& getErrorMessage() const { return m_errorMessage; }
template<std::derived_from<undo::Operation> T>
bool addUndoableOperation(auto && ... args) {
return m_undoRedoStack.add<T>(std::forward<decltype(args)...>(args)...);
@@ -296,8 +367,6 @@ namespace hex::prv {
*/
bool m_skipLoadInterface = false;
std::string m_errorMessage = "Unspecified error";
u64 m_pageSize = MaxPageSize;
};

View File

@@ -7,6 +7,7 @@
#include <map>
#include <memory>
#include <mutex>
#include <vector>
namespace hex::prv {
@@ -40,6 +41,8 @@ namespace hex::prv::undo {
bool add(std::unique_ptr<Operation> &&operation);
static std::recursive_mutex& getMutex();
const std::vector<std::unique_ptr<Operation>> &getAppliedOperations() const {
return m_undoStack;
}

View File

@@ -49,7 +49,7 @@ namespace hex::test {
[[nodiscard]] UnlocalizedString getTypeName() const override { return "hex.test.provider.test"; }
bool open() override { return true; }
OpenResult open() override { return {}; }
void close() override { }
nlohmann::json storeSettings(nlohmann::json) const override { return {}; }

View File

@@ -11,6 +11,7 @@
#include <hex/helpers/fmt.hpp>
#include <hex/helpers/concepts.hpp>
#include <hex/helpers/fs.hpp>
#include <hex/helpers/scaling.hpp>
#include <wolv/utils/string.hpp>
@@ -133,8 +134,8 @@ namespace ImGuiExt {
bool IconHyperlink(const char *icon, const char *label, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
bool Hyperlink(const char *label, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
bool BulletHyperlink(const char *label, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
bool DescriptionButton(const char *label, const char *description, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
bool DescriptionButtonProgress(const char *label, const char *description, float fraction, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
bool DescriptionButton(const char *label, const char *description, const char *icon, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
bool DescriptionButtonProgress(const char *label, const char *description, const char *icon, float fraction, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
void HelpHover(const char *text, const char *icon = "(?)", ImU32 iconColor = ImGui::GetColorU32(ImGuiCol_ButtonActive));
@@ -253,11 +254,12 @@ namespace ImGuiExt {
}
void TextFormattedWrappedSelectable(std::string_view fmt, auto &&...args) {
using namespace hex;
// Manually wrap text, using the letter M (generally the widest character in non-monospaced fonts) to calculate the character width to use.
auto text = wolv::util::trim(wolv::util::wrapMonospacedString(
fmt::format(fmt::runtime(fmt), std::forward<decltype(args)>(args)...),
ImGui::CalcTextSize("M").x,
ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize - ImGui::GetStyle().FrameBorderSize
std::max(100_scaled, ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize - ImGui::GetStyle().FrameBorderSize)
));
auto textSize = ImGui::CalcTextSize(text.c_str());
@@ -268,7 +270,7 @@ namespace ImGuiExt {
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0F);
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4());
ImGui::PushItemWidth(ImGui::CalcTextSize(text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2);
ImGui::PushItemWidth(textSize.x + ImGui::GetStyle().FramePadding.x * 2);
ImGui::InputTextMultiline(
"##",
const_cast<char *>(text.c_str()),
@@ -312,11 +314,12 @@ namespace ImGuiExt {
bool BitCheckbox(const char* label, bool* v);
bool DimmedButton(const char* label, ImVec2 size = ImVec2(0, 0));
bool DimmedButton(const char* label, ImVec2 size = ImVec2(0, 0), ImGuiButtonFlags flags = ImGuiButtonFlags_None);
bool DimmedIconButton(const char *symbol, ImVec4 color, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
bool DimmedIconToggle(const char *icon, bool *v);
bool DimmedIconToggle(const char *iconOn, const char *iconOff, bool *v);
bool DimmedArrowButton(const char *id, ImGuiDir dir, ImVec2 size = ImVec2(ImGui::GetFrameHeight(), ImGui::GetFrameHeight()));
void TextOverlay(const char *text, ImVec2 pos, float maxWidth = -1);

View File

@@ -6,6 +6,7 @@
#include <list>
#include <memory>
#include <mutex>
#include <hex/api/task_manager.hpp>
namespace hex {
@@ -51,11 +52,11 @@ namespace hex {
template<typename ...Args>
static void open(Args && ... args) {
std::lock_guard lock(getMutex());
auto toast = std::make_unique<T>(std::forward<Args>(args)...);
getQueuedToasts().emplace_back(std::move(toast));
TaskManager::doLater([=] {
auto toast = std::make_unique<T>(args...);
getQueuedToasts().emplace_back(std::move(toast));
});
}
};
}
}

View File

@@ -26,7 +26,7 @@ namespace hex {
* @brief Draws the view
* @note Do not override this method. Override drawContent() instead
*/
virtual void draw() = 0;
virtual void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) = 0;
/**
* @brief Draws the content of the view
@@ -82,10 +82,12 @@ namespace hex {
*/
[[nodiscard]] virtual View* getMenuItemInheritView() const { return nullptr; }
[[nodiscard]] const char *getIcon() const { return m_icon; }
[[nodiscard]] const UnlocalizedString& getUnlocalizedName() const;
[[nodiscard]] std::string getName() const;
[[nodiscard]] virtual bool shouldDefaultFocus() const { return false; }
[[nodiscard]] virtual bool shouldStoreWindowState() const { return true; }
[[nodiscard]] bool &getWindowOpenState();
@@ -108,10 +110,22 @@ namespace hex {
void trackViewState();
void setFocused(bool focused);
protected:
/**
* @brief Called when this view is opened (i.e. made visible).
*/
virtual void onOpen() {}
/**
* @brief Called when this view is closed (i.e. made invisible).
*/
virtual void onClose() {}
public:
class Window;
class Special;
class Floating;
class Scrolling;
class Modal;
class FullScreen;
@@ -134,15 +148,15 @@ namespace hex {
public:
explicit Window(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon) {}
void draw() final {
if (this->shouldDraw()) {
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
if (ImGui::Begin(title.c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse | this->getWindowFlags())) {
this->drawContent();
}
ImGui::End();
}
/**
* @brief Draws help text for the view
*/
virtual void drawHelpText() = 0;
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) override;
virtual bool allowScroll() const {
return false;
}
};
@@ -154,12 +168,7 @@ namespace hex {
public:
explicit Special(UnlocalizedString unlocalizedName) : View(std::move(unlocalizedName), "") {}
void draw() final {
if (this->shouldDraw()) {
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
this->drawContent();
}
}
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
};
/**
@@ -169,7 +178,24 @@ namespace hex {
public:
explicit Floating(UnlocalizedString unlocalizedName, const char *icon) : Window(std::move(unlocalizedName), icon) {}
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override { return ImGuiWindowFlags_NoDocking; }
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
};
/**
* @brief A view that draws all its content at once without any scrolling being done by the window itself
*/
class View::Scrolling : public View::Window {
public:
explicit Scrolling(UnlocalizedString unlocalizedName, const char *icon) : Window(std::move(unlocalizedName), icon) {}
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
bool allowScroll() const final {
return true;
}
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
};
@@ -180,24 +206,7 @@ namespace hex {
public:
explicit Modal(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon) {}
void draw() final {
if (this->shouldDraw()) {
if (this->getWindowOpenState())
ImGui::OpenPopup(View::toWindowName(this->getUnlocalizedName()).c_str());
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
if (ImGui::BeginPopupModal(title.c_str(), this->hasCloseButton() ? &this->getWindowOpenState() : nullptr, ImGuiWindowFlags_NoCollapse | this->getWindowFlags())) {
this->drawContent();
ImGui::EndPopup();
}
if (ImGui::IsKeyPressed(ImGuiKey_Escape))
this->getWindowOpenState() = false;
}
}
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
[[nodiscard]] virtual bool hasCloseButton() const { return true; }
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
@@ -207,10 +216,7 @@ namespace hex {
public:
explicit FullScreen() : View("FullScreen", "") {}
void draw() final {
this->drawContent();
this->drawAlwaysVisibleContent();
}
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
};
}
}

View File

@@ -264,8 +264,7 @@ namespace hex {
}
}
if (json.empty())
return;
if (json.empty()) return;
#if defined(OS_WEB)
auto data = json.dump();

View File

@@ -594,6 +594,12 @@ namespace hex {
return false;
}
bool Spacer::draw(const std::string& name) {
std::ignore = name;
ImGui::NewLine();
return false;
}
}
@@ -624,22 +630,22 @@ namespace hex {
void add(Type type, const std::string &command, const UnlocalizedString &unlocalizedDescription, const impl::DisplayCallback &displayCallback, const impl::ExecuteCallback &executeCallback) {
log::debug("Registered new command palette command: {}", command);
impl::s_entries->push_back(impl::Entry { type, command, unlocalizedDescription, displayCallback, executeCallback });
impl::s_entries->push_back(impl::Entry { .type=type, .command=command, .unlocalizedDescription=unlocalizedDescription, .displayCallback=displayCallback, .executeCallback=executeCallback });
}
void addHandler(Type type, const std::string &command, const impl::QueryCallback &queryCallback, const impl::DisplayCallback &displayCallback) {
log::debug("Registered new command palette command handler: {}", command);
impl::s_handlers->push_back(impl::Handler { type, command, queryCallback, displayCallback });
impl::s_handlers->push_back(impl::Handler { .type=type, .command=command, .queryCallback=queryCallback, .displayCallback=displayCallback });
}
void setDisplayedContent(const impl::ContentDisplayCallback &displayCallback) {
impl::s_displayedContent = impl::ContentDisplay { true, displayCallback };
impl::s_displayedContent = impl::ContentDisplay { .showSearchBox=true, .callback=displayCallback };
}
void openWithContent(const impl::ContentDisplayCallback &displayCallback) {
RequestOpenCommandPalette::post();
impl::s_displayedContent = impl::ContentDisplay { false, displayCallback };
impl::s_displayedContent = impl::ContentDisplay { .showSearchBox=false, .callback=displayCallback };
}
}
@@ -777,12 +783,12 @@ namespace hex {
void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount) {
log::debug("Registered new pattern visualizer function: {}", name);
(*impl::s_visualizers)[name] = impl::Visualizer { parameterCount, function };
(*impl::s_visualizers)[name] = impl::Visualizer { .parameterCount=parameterCount, .callback=function };
}
void addInlineVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount) {
log::debug("Registered new inline pattern visualizer function: {}", name);
(*impl::s_inlineVisualizers)[name] = impl::Visualizer { parameterCount, function };
(*impl::s_inlineVisualizers)[name] = impl::Visualizer { .parameterCount=parameterCount, .callback=function };
}
}
@@ -848,7 +854,7 @@ namespace hex {
void add(const UnlocalizedString &unlocalizedName, const char *icon, const impl::Callback &function) {
log::debug("Registered new tool: {}", unlocalizedName.get());
impl::s_tools->emplace_back(impl::Entry { unlocalizedName, icon, function });
impl::s_tools->emplace_back(impl::Entry { .unlocalizedName=unlocalizedName, .icon=icon, .function=function });
}
}
@@ -864,6 +870,18 @@ namespace hex {
}
namespace EditWidget {
std::optional<std::vector<u8>> TextInput::draw(std::string &value, std::endian endian) {
if (ImGui::InputText("##InspectorLineEditing", value,
ImGuiInputTextFlags_EnterReturnsTrue |
ImGuiInputTextFlags_AutoSelectAll)) {
return getBytes(value, endian);
}
return std::nullopt;
}
}
void add(const UnlocalizedString &unlocalizedName, size_t requiredSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction) {
log::debug("Registered new data inspector format: {}", unlocalizedName.get());
@@ -991,7 +1009,7 @@ namespace hex {
coloredIcon.color = ImGuiCustomCol_ToolbarGray;
impl::s_menuItems->insert({
priority, impl::MenuItem { unlocalizedMainMenuNames, coloredIcon, shortcut, view, function, enabledCallback, selectedCallback, -1 }
priority, impl::MenuItem { .unlocalizedNames=unlocalizedMainMenuNames, .icon=coloredIcon, .shortcut=shortcut, .view=view, .callback=function, .enabledCallback=enabledCallback, .selectedCallback=selectedCallback, .toolbarIndex=-1 }
});
if (shortcut != Shortcut::None) {
@@ -1006,23 +1024,32 @@ namespace hex {
}
}
void addMenuItemSubMenu(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback, View *view) {
addMenuItemSubMenu(std::move(unlocalizedMainMenuNames), "", priority, function, enabledCallback, view);
void addMenuItemSubMenu(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback, View *view, bool showOnWelcomeScreen) {
addMenuItemSubMenu(std::move(unlocalizedMainMenuNames), "", priority, function, enabledCallback, view, showOnWelcomeScreen);
}
void addMenuItemSubMenu(std::vector<UnlocalizedString> unlocalizedMainMenuNames, const char *icon, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback, View *view) {
void addMenuItemSubMenu(std::vector<UnlocalizedString> unlocalizedMainMenuNames, const char *icon, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback, View *view, bool showOnWelcomeScreen) {
log::debug("Added new menu item sub menu to menu {} with priority {}", unlocalizedMainMenuNames[0].get(), priority);
unlocalizedMainMenuNames.emplace_back(impl::SubMenuValue);
impl::s_menuItems->insert({
priority, impl::MenuItem { unlocalizedMainMenuNames, icon, Shortcut::None, view, function, enabledCallback, []{ return false; }, -1 }
priority, impl::MenuItem { .unlocalizedNames=unlocalizedMainMenuNames, .icon=icon, .shortcut=showOnWelcomeScreen ? Shortcut({ ShowOnWelcomeScreen }) : Shortcut::None, .view=view, .callback=function, .enabledCallback=enabledCallback, .selectedCallback=[]{ return false; }, .toolbarIndex=-1 }
});
}
void addMenuItemSeparator(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, View *view) {
unlocalizedMainMenuNames.emplace_back(impl::SeparatorValue);
impl::s_menuItems->insert({
priority, impl::MenuItem { unlocalizedMainMenuNames, "", Shortcut::None, view, []{}, []{ return true; }, []{ return false; }, -1 }
priority, impl::MenuItem { .unlocalizedNames=unlocalizedMainMenuNames, .icon="", .shortcut=Shortcut::None, .view=view, .callback=[]{}, .enabledCallback=[]{ return true; }, .selectedCallback=[]{ return false; }, .toolbarIndex=-1 }
});
}
void addTaskBarMenuItem(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback) {
log::debug("Added new taskbar menu item to menu {} ", unlocalizedMainMenuNames[0].get());
unlocalizedMainMenuNames.insert(unlocalizedMainMenuNames.begin(), impl::TaskBarMenuValue);
impl::s_menuItems->insert({
priority, impl::MenuItem { .unlocalizedNames=unlocalizedMainMenuNames, .icon="", .shortcut=Shortcut::None, .view=nullptr, .callback=function, .enabledCallback=enabledCallback, .selectedCallback=[]{ return false; }, .toolbarIndex=-1 }
});
}
@@ -1038,13 +1065,13 @@ namespace hex {
impl::s_toolbarItems->push_back(function);
}
void addMenuItemToToolbar(const UnlocalizedString& unlocalizedName, ImGuiCustomCol color) {
void addMenuItemToToolbar(const std::vector<UnlocalizedString>& unlocalizedNames, ImGuiCustomCol color) {
const auto maxIndex = std::ranges::max_element(impl::getMenuItems(), [](const auto &a, const auto &b) {
return a.second.toolbarIndex < b.second.toolbarIndex;
})->second.toolbarIndex;
for (auto &[priority, menuItem] : *impl::s_menuItems) {
if (menuItem.unlocalizedNames.back() == unlocalizedName) {
if (menuItem.unlocalizedNames == unlocalizedNames) {
menuItem.toolbarIndex = maxIndex + 1;
menuItem.icon.color = color;
updateToolbarItems();
@@ -1096,18 +1123,18 @@ namespace hex {
}
namespace ContentRegistry::Provider {
namespace impl {
namespace ContentRegistry::Provider::impl {
void add(const std::string &typeName, ProviderCreationFunction creationFunction) {
(void)RequestCreateProvider::subscribe([expectedName = typeName, creationFunction](const std::string &name, bool skipLoadInterface, bool selectProvider, prv::Provider **provider) {
(void)RequestCreateProvider::subscribe([expectedName = typeName, creationFunction](const std::string &name, bool skipLoadInterface, bool selectProvider, std::shared_ptr<prv::Provider> *provider) {
if (name != expectedName) return;
auto newProvider = creationFunction();
if (provider != nullptr) {
*provider = newProvider.get();
*provider = newProvider;
ImHexApi::Provider::add(std::move(newProvider), skipLoadInterface, selectProvider);
}
});
@@ -1127,7 +1154,7 @@ namespace hex {
}
}
namespace ContentRegistry::DataFormatter {
@@ -1283,47 +1310,42 @@ namespace hex {
}
namespace ContentRegistry::Diffing {
namespace impl {
namespace ContentRegistry::Diffing::impl {
static AutoReset<std::vector<std::unique_ptr<Algorithm>>> s_algorithms;
const std::vector<std::unique_ptr<Algorithm>>& getAlgorithms() {
return *s_algorithms;
}
void addAlgorithm(std::unique_ptr<Algorithm> &&hash) {
s_algorithms->emplace_back(std::move(hash));
}
static AutoReset<std::vector<std::unique_ptr<Algorithm>>> s_algorithms;
const std::vector<std::unique_ptr<Algorithm>>& getAlgorithms() {
return *s_algorithms;
}
void addAlgorithm(std::unique_ptr<Algorithm> &&hash) {
s_algorithms->emplace_back(std::move(hash));
}
}
namespace ContentRegistry::Hashes {
namespace impl {
namespace ContentRegistry::Hashes::impl {
static AutoReset<std::vector<std::unique_ptr<Hash>>> s_hashes;
const std::vector<std::unique_ptr<Hash>>& getHashes() {
return *s_hashes;
}
void add(std::unique_ptr<Hash> &&hash) {
s_hashes->emplace_back(std::move(hash));
}
static AutoReset<std::vector<std::unique_ptr<Hash>>> s_hashes;
const std::vector<std::unique_ptr<Hash>>& getHashes() {
return *s_hashes;
}
void add(std::unique_ptr<Hash> &&hash) {
s_hashes->emplace_back(std::move(hash));
}
}
namespace ContentRegistry::BackgroundServices {
namespace impl {
class Service {
public:
Service(const UnlocalizedString &unlocalizedName, std::jthread thread) : m_unlocalizedName(std::move(unlocalizedName)), m_thread(std::move(thread)) { }
Service(UnlocalizedString unlocalizedName, std::jthread thread) : m_unlocalizedName(std::move(unlocalizedName)), m_thread(std::move(thread)) { }
Service(const Service&) = delete;
Service(Service &&) = default;
~Service() {
@@ -1395,6 +1417,40 @@ namespace hex {
}
namespace ContentRegistry::MCP {
namespace impl {
std::unique_ptr<mcp::Server>& getMcpServerInstance() {
static std::unique_ptr<mcp::Server> server;
if (server == nullptr)
server = std::make_unique<mcp::Server>();
return server;
}
static bool s_mcpEnabled = false;
void setEnabled(bool enabled) {
s_mcpEnabled = enabled;
}
}
bool isEnabled() {
return impl::s_mcpEnabled;
}
bool isConnected() {
return impl::getMcpServerInstance()->isConnected();
}
void registerTool(std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json &params)> function) {
impl::getMcpServerInstance()->addPrimitive("tools", capabilities, function);
}
}
namespace ContentRegistry::Experiments {
namespace impl {
@@ -1488,22 +1544,19 @@ namespace hex {
}
}
namespace ContentRegistry::Disassemblers {
namespace ContentRegistry::Disassemblers::impl {
namespace impl {
static AutoReset<std::map<std::string, impl::CreatorFunction>> s_architectures;
static AutoReset<std::map<std::string, impl::CreatorFunction>> s_architectures;
void addArchitectureCreator(impl::CreatorFunction function) {
const auto arch = function();
(*s_architectures)[arch->getName()] = std::move(function);
}
const std::map<std::string, impl::CreatorFunction>& getArchitectures() {
return *s_architectures;
}
void addArchitectureCreator(impl::CreatorFunction function) {
const auto arch = function();
(*s_architectures)[arch->getName()] = std::move(function);
}
const std::map<std::string, impl::CreatorFunction>& getArchitectures() {
return *s_architectures;
}
}

View File

@@ -1,3 +1,4 @@
#include <algorithm>
#include <hex/api/event_manager.hpp>
namespace hex {
@@ -35,7 +36,7 @@ namespace hex {
void EventManager::unsubscribe(void *token, impl::EventId id) {
auto &tokenStore = getTokenStore();
auto iter = std::find_if(tokenStore.begin(), tokenStore.end(), [&](auto &item) {
auto iter = std::ranges::find_if(tokenStore, [&](auto &item) {
return item.first == token && item.second->first == id;
});

View File

@@ -47,6 +47,10 @@
#if defined(OS_WEB)
#include <emscripten.h>
#elif defined(OS_MACOS)
extern "C" {
void macosRegisterFont(const unsigned char *data, size_t size);
}
#endif
namespace hex {
@@ -257,7 +261,7 @@ namespace hex {
}
void setSelection(u64 address, size_t size, prv::Provider *provider) {
setSelection({ { address, size }, provider == nullptr ? Provider::get() : provider });
setSelection({ { .address=address, .size=size }, provider == nullptr ? Provider::get() : provider });
}
void addVirtualFile(const std::string &path, std::vector<u8> data, Region region) {
@@ -281,7 +285,7 @@ namespace hex {
}
u64 add(u64 address, size_t size, const std::string &name, const std::string &comment, u32 color) {
return add(Region { address, size }, name, comment, color);
return add(Region { .address=address, .size=size }, name, comment, color);
}
void remove(u64 id) {
@@ -294,8 +298,8 @@ namespace hex {
namespace ImHexApi::Provider {
static i64 s_currentProvider = -1;
static AutoReset<std::vector<std::unique_ptr<prv::Provider>>> s_providers;
static AutoReset<std::map<prv::Provider*, std::unique_ptr<prv::Provider>>> s_providersToRemove;
static AutoReset<std::vector<std::shared_ptr<prv::Provider>>> s_providers;
static AutoReset<std::map<prv::Provider*, std::shared_ptr<prv::Provider>>> s_providersToRemove;
namespace impl {
@@ -382,7 +386,7 @@ namespace hex {
});
}
void add(std::unique_ptr<prv::Provider> &&provider, bool skipLoadInterface, bool select) {
void add(std::shared_ptr<prv::Provider> &&provider, bool skipLoadInterface, bool select) {
std::scoped_lock lock(impl::s_providerMutex);
if (TaskManager::getRunningTaskCount() > 0)
@@ -391,7 +395,7 @@ namespace hex {
if (skipLoadInterface)
provider->skipLoadInterface();
EventProviderCreated::post(provider.get());
EventProviderCreated::post(provider);
s_providers->emplace_back(std::move(provider));
if (select || s_providers->size() == 1)
@@ -491,13 +495,17 @@ namespace hex {
});
}
prv::Provider* createProvider(const UnlocalizedString &unlocalizedName, bool skipLoadInterface, bool select) {
prv::Provider* result = nullptr;
std::shared_ptr<prv::Provider> createProvider(const UnlocalizedString &unlocalizedName, bool skipLoadInterface, bool select) {
std::shared_ptr<prv::Provider> result = nullptr;
RequestCreateProvider::post(unlocalizedName, skipLoadInterface, select, &result);
return result;
}
void openProvider(std::shared_ptr<prv::Provider> provider) {
RequestOpenProvider::post(provider);
}
}
namespace ImHexApi::System {
@@ -530,6 +538,11 @@ namespace hex {
s_mainWindowHandle = window;
}
static bool s_mainWindowFocused = false;
void setMainWindowFocusState(bool focused) {
s_mainWindowFocused = focused;
}
static float s_globalScale = 1.0;
void setGlobalScale(float scale) {
@@ -673,7 +686,7 @@ namespace hex {
return std::midpoint(xScale, yScale);
}
#elif defined(OS_WEB)
return 1.0F;
return MAIN_THREAD_EM_ASM_INT({ return window.devicePixelRatio; });
#else
return 1.0F;
#endif
@@ -700,11 +713,15 @@ namespace hex {
return impl::s_mainWindowHandle;
}
bool isMainWindowFocused() {
return impl::s_mainWindowFocused;
}
bool isBorderlessWindowModeEnabled() {
return impl::s_borderlessWindowMode;
}
bool isMutliWindowModeEnabled() {
bool isMultiWindowModeEnabled() {
return impl::s_multiWindowMode;
}
@@ -896,15 +913,16 @@ namespace hex {
}
}
return { { name, version } };
return { { .name=name, .version=version } };
}
SemanticVersion getImHexVersion() {
const SemanticVersion& getImHexVersion() {
#if defined(IMHEX_VERSION)
static auto version = SemanticVersion(IMHEX_VERSION);
return version;
#else
return {};
static auto version = SemanticVersion();
return version;
#endif
}
@@ -946,7 +964,9 @@ namespace hex {
}
bool isNightlyBuild() {
return getImHexVersion().nightly();
const static bool isNightly = getImHexVersion().nightly();
return isNightly;
}
std::optional<std::string> checkForUpdate() {
@@ -979,7 +999,13 @@ namespace hex {
const auto nightlyUpdateTime = hex::parseTime("%Y-%m-%dT%H:%M:%SZ", firstAsset["updated_at"].get<std::string>());
const auto imhexBuildTime = ImHexApi::System::getBuildTime();
if (nightlyUpdateTime.has_value() && imhexBuildTime.has_value() && *nightlyUpdateTime > *imhexBuildTime) {
// Give a bit of time leniency for the update time check
// We're comparing here the binary build time to the release upload time. If we were to strictly compare
// upload time to be greater than current build time, the check would always be true since the CI
// takes a few minutes after the build to actually upload the artifact.
// TODO: Is there maybe a better way to handle this without downloading the artifact just to check the build time?
if (nightlyUpdateTime.has_value() && imhexBuildTime.has_value() && *nightlyUpdateTime > *imhexBuildTime + std::chrono::hours(1)) {
return "Nightly";
}
} else {
@@ -1192,6 +1218,10 @@ namespace hex {
offset,
fontSizeMultiplier
);
#if defined(OS_MACOS)
macosRegisterFont(data.data(), data.size_bytes());
#endif
}
void registerFont(const Font& font) {
@@ -1203,7 +1233,7 @@ namespace hex {
if (it == impl::s_fontDefinitions->end()) {
const auto defaultFont = ImGui::GetDefaultFont();
return { defaultFont, defaultFont, defaultFont };
return { .regular=defaultFont, .bold=defaultFont, .italic=defaultFont };
} else
return it->second;
}

View File

@@ -146,7 +146,7 @@ namespace hex {
}
void LayoutManager::lockLayout(bool locked) {
log::info("Layout {}", locked ? "locked" : "unlocked");
log::debug("Layout {}", locked ? "locked" : "unlocked");
s_layoutLocked = locked;
}

View File

@@ -7,6 +7,7 @@
#include <nlohmann/json.hpp>
#include <mutex>
#include <hex/helpers/debugging.hpp>
namespace hex {
@@ -49,9 +50,13 @@ namespace hex {
definition.fallbackLanguageId = item["fallback"].get<std::string>();
}
if (item.contains("hidden") && item["hidden"].get<bool>()) {
definition.hidden = true;
}
const auto path = item["path"].get<std::string>();
definition.languageFilePaths.emplace_back(PathEntry{ path, callback });
definition.languageFilePaths.emplace_back(PathEntry{ .path=path, .callback=callback });
}
}
@@ -99,9 +104,21 @@ namespace hex {
for (const auto &entry : json.items()) {
auto value = entry.value().get<std::string>();
// Skip empty values
if (value.empty())
continue;
// Handle references to files
if (value.starts_with("#@")) {
try {
value = path.callback(value.substr(2));
} catch (std::exception &e) {
log::error("Failed to load localization file reference '{}': {}", entry.key(), e.what());
continue;
}
}
localizations.try_emplace(LangConst::hash(entry.key()), std::move(value));
}
} catch (std::exception &e) {
@@ -138,7 +155,7 @@ namespace hex {
static AutoReset<std::unordered_map<std::size_t, std::string>> loadedLocalization;
static std::mutex mutex;
std::lock_guard lock(mutex);
std::scoped_lock lock(mutex);
if (*currentLanguageId != languageId) {
currentLanguageId = languageId;
loadedLocalization->clear();
@@ -154,16 +171,33 @@ namespace hex {
const LanguageDefinition& getLanguageDefinition(const LanguageId &languageId) {
const auto bestMatch = findBestLanguageMatch(languageId);
return (*s_languageDefinitions)[bestMatch];
const auto &result = (*s_languageDefinitions)[bestMatch];
if (!dbg::debugModeEnabled()) {
if (result.hidden)
return getLanguageDefinition(result.fallbackLanguageId);
}
return result;
}
}
Lang::Lang(const char *unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)), m_unlocalizedString(unlocalizedString) { }
Lang::Lang(const std::string &unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)), m_unlocalizedString(unlocalizedString) { }
Lang::Lang(const LangConst &localizedString) : m_entryHash(localizedString.m_entryHash), m_unlocalizedString(localizedString.m_unlocalizedString) { }
Lang::Lang(const UnlocalizedString &unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString.get())), m_unlocalizedString(unlocalizedString.get()) { }
Lang::Lang(std::string_view unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)), m_unlocalizedString(unlocalizedString) { }
static AutoReset<std::map<std::size_t, std::string>> s_unlocalizedNames;
Lang::Lang(std::string_view unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)) {
if (!s_unlocalizedNames->contains(m_entryHash)) [[unlikely]] {
s_unlocalizedNames->emplace(m_entryHash, unlocalizedString);
}
}
Lang::Lang(const char *unlocalizedString) : Lang(std::string_view(unlocalizedString)) { }
Lang::Lang(const std::string &unlocalizedString) : Lang(std::string_view(unlocalizedString)) { }
Lang::Lang(const LangConst &localizedString) : m_entryHash(localizedString.m_entryHash) {
if (!s_unlocalizedNames->contains(m_entryHash)) [[unlikely]] {
s_unlocalizedNames->emplace(m_entryHash, localizedString.m_unlocalizedString);
}
}
Lang::Lang(const UnlocalizedString &unlocalizedString) : Lang(unlocalizedString.get()) { }
Lang::operator std::string() const {
return get();
@@ -182,7 +216,11 @@ namespace hex {
const auto it = lang.find(m_entryHash);
if (it == lang.end()) {
return m_unlocalizedString.c_str();
if (auto unlocalizedIt = s_unlocalizedNames->find(m_entryHash); unlocalizedIt != s_unlocalizedNames->end()) {
return unlocalizedIt->second.c_str();
} else {
return "<unlocalized>";
}
} else {
return it->second.c_str();
}
@@ -211,4 +249,4 @@ namespace hex {
}
}
}
}

View File

@@ -85,7 +85,7 @@ namespace hex {
}
Plugin::Plugin(const std::string &name, const hex::PluginFunctions &functions) :
m_handle(0), m_path(name), m_addedManually(true), m_functions(functions) { }
m_path(name), m_addedManually(true), m_functions(functions) { }
Plugin::Plugin(Plugin &&other) noexcept {

View File

@@ -44,7 +44,7 @@ namespace hex {
}
std::fs::path ProjectFile::getPath() {
return s_currProjectPath;
return *s_currProjectPath;
}
void ProjectFile::setPath(const std::fs::path &path) {

View File

@@ -260,8 +260,11 @@ namespace hex {
case CTRLCMD.getKeyCode():
result.cmd = true;
break;
case CurrentView.getKeyCode(): break;
case AllowWhileTyping.getKeyCode(): break;
case CurrentView.getKeyCode():
case AllowWhileTyping.getKeyCode():
case ShowOnWelcomeScreen.getKeyCode():
// Ignore flags that are only used internally by the ShortcutManager
break;
default:
macosGetKey(Keys(key.getKeyCode()), &result.key);
break;
@@ -278,25 +281,25 @@ namespace hex {
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, unlocalizedName, callback, enabledCallback } });
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { .shortcut=shortcut, .unlocalizedName=unlocalizedName, .callback=callback, .enabledCallback=enabledCallback } });
if (!inserted) log::error("Failed to add shortcut!");
}
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, { unlocalizedName }, callback, enabledCallback } });
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { .shortcut=shortcut, .unlocalizedName={ unlocalizedName }, .callback=callback, .enabledCallback=enabledCallback } });
if (!inserted) log::error("Failed to add shortcut!");
}
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback, enabledCallback } });
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { .shortcut=shortcut, .unlocalizedName=unlocalizedName, .callback=callback, .enabledCallback=enabledCallback } });
if (!inserted) log::error("Failed to add shortcut!");
}
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, { unlocalizedName }, callback, enabledCallback } });
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { .shortcut=shortcut, .unlocalizedName={ unlocalizedName }, .callback=callback, .enabledCallback=enabledCallback } });
if (!inserted) log::error("Failed to add shortcut!");
}
@@ -313,27 +316,40 @@ namespace hex {
pressedShortcut += s_macOSMode ? CTRLCMD : SUPER;
if (focused)
pressedShortcut += CurrentView;
if (!ImHexApi::Provider::isValid()) {
pressedShortcut += CurrentView;
pressedShortcut += ShowOnWelcomeScreen;
}
pressedShortcut += scanCodeToKey(keyCode);
return pressedShortcut;
}
static bool processShortcut(Shortcut shortcut, const std::map<Shortcut, ShortcutManager::ShortcutEntry> &shortcuts) {
static auto findShortcut(const Shortcut &shortcut, const std::map<Shortcut, ShortcutManager::ShortcutEntry> &shortcuts, bool condition, auto ... extraOption) {
auto modifiedShortcut = shortcut;
((modifiedShortcut += extraOption), ...);
if (condition) {
return shortcuts.find(modifiedShortcut);
} else {
auto it = shortcuts.find(shortcut);
if (it == shortcuts.end())
return shortcuts.find(modifiedShortcut);
}
return shortcuts.end();
}
static bool processShortcut(const Shortcut &shortcut, const std::map<Shortcut, ShortcutManager::ShortcutEntry> &shortcuts) {
if (s_paused)
return true;
if (ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId))
return true;
const bool currentlyTyping = ImGui::GetIO().WantTextInput;
auto it = shortcuts.find(shortcut + AllowWhileTyping);
if (!currentlyTyping && it == shortcuts.end()) {
if (it == shortcuts.end())
it = shortcuts.find(shortcut);
}
auto it = findShortcut(shortcut, shortcuts, ImGui::GetIO().WantTextInput, AllowWhileTyping);
if (it == shortcuts.end())
it = findShortcut(shortcut, shortcuts, ImGui::GetIO().WantTextInput, AllowWhileTyping, ShowOnWelcomeScreen);
if (it != shortcuts.end()) {
const auto &[foundShortcut, entry] = *it;
@@ -387,6 +403,24 @@ namespace hex {
s_globalShortcuts->clear();
}
Shortcut ShortcutManager::getShortcutByName(const std::vector<UnlocalizedString> &unlocalizedName, const View *view) {
if (view != nullptr) {
for (const auto &[shortcut, entry] : view->m_shortcuts) {
if (entry.unlocalizedName == unlocalizedName) {
return entry.shortcut;
}
}
} else {
for (const auto &[shortcut, entry] : *s_globalShortcuts) {
if (entry.unlocalizedName == unlocalizedName) {
return entry.shortcut;
}
}
}
return Shortcut::None;
}
void ShortcutManager::resumeShortcuts() {
s_paused = false;
}

View File

@@ -7,6 +7,9 @@
#include <ranges>
#include <jthread.hpp>
#include <hex/helpers/debugging.hpp>
#include <hex/trace/exceptions.hpp>
#include <utility>
#if defined(OS_WINDOWS)
#include <windows.h>
@@ -52,6 +55,7 @@ namespace hex {
std::list<std::function<void()>> s_deferredCalls;
std::unordered_map<SourceLocationWrapper, std::function<void()>> s_onceDeferredCalls;
std::list<std::function<void()>> s_tasksFinishedCallbacks;
std::list<std::function<void(Task&)>> s_taskCompletionCallbacks;
std::mutex s_queueMutex;
std::condition_variable s_jobCondVar;
@@ -64,7 +68,7 @@ namespace hex {
}
Task::Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function)
Task::Task(UnlocalizedString unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function)
: m_unlocalizedName(std::move(unlocalizedName)),
m_maxValue(maxValue),
m_function(std::move(function)),
@@ -82,9 +86,17 @@ namespace hex {
m_maxValue = u64(other.m_maxValue);
m_currValue = u64(other.m_currValue);
m_finished = bool(other.m_finished);
m_hadException = bool(other.m_hadException);
m_interrupted = bool(other.m_interrupted);
if (other.m_finished.test())
m_finished.test_and_set();
if (other.m_hadException.test())
m_hadException.test_and_set();
if (other.m_interrupted.test())
m_interrupted.test_and_set();
m_finished.notify_all();
m_hadException.notify_all();
m_interrupted.notify_all();
m_shouldInterrupt = bool(other.m_shouldInterrupt);
}
@@ -143,11 +155,11 @@ namespace hex {
bool Task::isFinished() const {
return m_finished;
return m_finished.test();
}
bool Task::hadException() const {
return m_hadException;
return m_hadException.test();
}
bool Task::shouldInterrupt() const {
@@ -155,11 +167,11 @@ namespace hex {
}
bool Task::wasInterrupted() const {
return m_interrupted;
return m_interrupted.test();
}
void Task::clearException() {
m_hadException = false;
m_hadException.clear();
}
std::string Task::getExceptionMessage() const {
@@ -180,12 +192,18 @@ namespace hex {
return m_maxValue;
}
void Task::wait() const {
m_finished.wait(false);
}
void Task::finish() {
m_finished = true;
m_finished.test_and_set();
m_finished.notify_all();
}
void Task::interruption() {
m_interrupted = true;
m_interrupted.test_and_set();
m_interrupted.notify_all();
}
void Task::exception(const char *message) {
@@ -193,7 +211,8 @@ namespace hex {
// Store information about the caught exception
m_exceptionMessage = message;
m_hadException = true;
m_hadException.test_and_set();
m_hadException.notify_all();
// Call the interrupt callback on the current thread if one is set
if (m_interruptCallback)
@@ -241,6 +260,14 @@ namespace hex {
task->interrupt();
}
void TaskHolder::wait() const {
const auto &task = m_task.lock();
if (!task)
return;
task->wait();
}
u32 TaskHolder::getProgress() const {
const auto &task = m_task.lock();
if (!task)
@@ -287,6 +314,8 @@ namespace hex {
}
try {
trace::enableExceptionCaptureForCurrentThread();
// Set the thread name to the name of the task
TaskManager::setCurrentThreadName(Lang(task->m_unlocalizedName));
@@ -294,21 +323,34 @@ namespace hex {
task->m_function(*task);
log::debug("Task '{}' finished", task->m_unlocalizedName.get());
{
std::scoped_lock lock(s_tasksFinishedMutex);
for (const auto &callback : s_taskCompletionCallbacks)
callback(*task);
}
} catch (const Task::TaskInterruptor &) {
// Handle the task being interrupted by user request
task->interruption();
} catch (const std::exception &e) {
log::error("Exception in task '{}': {}", task->m_unlocalizedName.get(), e.what());
dbg::printStackTrace(trace::getStackTrace());
// Handle the task throwing an uncaught exception
task->exception(e.what());
} catch (...) {
log::error("Exception in task '{}'", task->m_unlocalizedName.get());
dbg::printStackTrace(trace::getStackTrace());
// Handle the task throwing an uncaught exception of unknown type
task->exception("Unknown Exception");
}
trace::disableExceptionCaptureForCurrentThread();
s_currentTask = nullptr;
task->finish();
}
@@ -327,7 +369,10 @@ namespace hex {
thread.request_stop();
// Wake up all the idle worker threads so they can exit
s_jobCondVar.notify_all();
{
std::unique_lock lock(s_queueMutex);
s_jobCondVar.notify_all();
}
// Wait for all worker threads to exit
s_workers.clear();
@@ -338,13 +383,14 @@ namespace hex {
s_deferredCalls.clear();
s_onceDeferredCalls.clear();
s_tasksFinishedCallbacks.clear();
s_taskCompletionCallbacks.clear();
}
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task&)> function) {
std::scoped_lock lock(s_queueMutex);
// Construct new task
auto task = std::make_shared<Task>(std::move(unlocalizedName), maxValue, background, blocking, std::move(function));
auto task = std::make_shared<Task>(unlocalizedName, maxValue, background, blocking, std::move(function));
s_tasks.emplace_back(task);
@@ -359,12 +405,12 @@ namespace hex {
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function) {
log::debug("Creating task {}", unlocalizedName.get());
return createTask(std::move(unlocalizedName), maxValue, false, false, std::move(function));
return createTask(unlocalizedName, maxValue, false, false, std::move(function));
}
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function) {
log::debug("Creating task {}", unlocalizedName.get());
return createTask(std::move(unlocalizedName), maxValue, false, false,
return createTask(unlocalizedName, maxValue, false, false,
[function = std::move(function)](Task&) {
function();
}
@@ -373,12 +419,12 @@ namespace hex {
TaskHolder TaskManager::createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void(Task &)> function) {
log::debug("Creating background task {}", unlocalizedName.get());
return createTask(std::move(unlocalizedName), 0, true, false, std::move(function));
return createTask(unlocalizedName, 0, true, false, std::move(function));
}
TaskHolder TaskManager::createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void()> function) {
log::debug("Creating background task {}", unlocalizedName.get());
return createTask(std::move(unlocalizedName), 0, true, false,
return createTask(unlocalizedName, 0, true, false,
[function = std::move(function)](Task&) {
function();
}
@@ -387,12 +433,12 @@ namespace hex {
TaskHolder TaskManager::createBlockingTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function) {
log::debug("Creating blocking task {}", unlocalizedName.get());
return createTask(std::move(unlocalizedName), maxValue, true, true, std::move(function));
return createTask(unlocalizedName, maxValue, true, true, std::move(function));
}
TaskHolder TaskManager::createBlockingTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function) {
log::debug("Creating blocking task {}", unlocalizedName.get());
return createTask(std::move(unlocalizedName), maxValue, true, true,
return createTask(unlocalizedName, maxValue, true, true,
[function = std::move(function)](Task&) {
function();
}
@@ -546,5 +592,13 @@ namespace hex {
return s_mainThreadId == std::this_thread::get_id();
}
void TaskManager::addTaskCompletionCallback(const std::function<void(Task &)> &function) {
std::scoped_lock lock(s_tasksFinishedMutex);
for (const auto &task : s_tasks) {
task->interrupt();
}
s_taskCompletionCallbacks.push_back(function);
}
}

View File

@@ -31,7 +31,7 @@ namespace hex {
void ThemeManager::addThemeHandler(const std::string &name, const ColorMap &colorMap, const std::function<ImColor(u32)> &getFunction, const std::function<void(u32, ImColor)> &setFunction) {
std::unique_lock lock(s_themeMutex);
(*s_themeHandlers)[name] = { colorMap, getFunction, setFunction };
(*s_themeHandlers)[name] = { .colorMap=colorMap, .getFunction=getFunction, .setFunction=setFunction };
}
void ThemeManager::addStyleHandler(const std::string &name, const StyleMap &styleMap) {

View File

@@ -32,6 +32,8 @@ namespace hex {
ImGuiID s_activeHelpId;
bool s_helpHoverActive = false;
AutoReset<std::function<std::function<void()>(const std::string &)>> s_renderer;
class IDStack {
public:
@@ -55,7 +57,7 @@ namespace hex {
void add(const void *pointer) {
const ImGuiID seed = idStack.back();
const ImGuiID id = ImHashData(&pointer, sizeof(pointer), seed);
const ImGuiID id = ImHashData((const void*) &pointer, sizeof(pointer), seed);
idStack.push_back(id);
}
@@ -94,35 +96,47 @@ namespace hex {
}
void TutorialManager::init() {
EventImGuiElementRendered::subscribe([](ImGuiID id, const std::array<float, 4> bb){
const auto boundingBox = ImRect(bb[0], bb[1], bb[2], bb[3]);
if (*s_renderer == nullptr) {
*s_renderer = [](const std::string &message) {
return [message] {
ImGui::PushTextWrapPos(300_scaled);
ImGui::TextUnformatted(message.c_str());
ImGui::PopTextWrapPos();
ImGui::NewLine();
};
};
}
}
{
const auto element = hex::s_highlights->find(id);
if (element != hex::s_highlights->end()) {
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
void TutorialManager::postElementRendered(ImGuiID id, const ImRect &boundingBox) {
if (!ImGui::IsRectVisible(boundingBox.Min, boundingBox.Max))
return;
const auto window = ImGui::GetCurrentWindow();
if (window != nullptr && window->DockNode != nullptr && window->DockNode->TabBar != nullptr)
window->DockNode->TabBar->NextSelectedTabId = window->TabId;
}
{
const auto element = hex::s_highlights->find(id);
if (element != hex::s_highlights->end()) {
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
const auto window = ImGui::GetCurrentWindow();
if (window != nullptr && window->DockNode != nullptr && window->DockNode->TabBar != nullptr)
window->DockNode->TabBar->NextSelectedTabId = window->TabId;
}
}
{
const auto element = s_interactiveHelpItems->find(id);
if (element != s_interactiveHelpItems->end()) {
(*s_interactiveHelpDisplays)[id] = boundingBox;
}
{
const auto element = s_interactiveHelpItems->find(id);
if (element != s_interactiveHelpItems->end()) {
(*s_interactiveHelpDisplays)[id] = boundingBox;
}
}
if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
if ((s_hoveredRect.GetArea() == 0 || boundingBox.GetArea() < s_hoveredRect.GetArea()) && s_interactiveHelpItems->contains(id)) {
s_hoveredRect = boundingBox;
s_hoveredId = id;
}
if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
if ((s_hoveredRect.GetArea() == 0 || boundingBox.GetArea() < s_hoveredRect.GetArea()) && s_interactiveHelpItems->contains(id)) {
s_hoveredRect = boundingBox;
s_hoveredId = id;
}
}
});
}
}
const std::map<std::string, TutorialManager::Tutorial>& TutorialManager::getTutorials() {
@@ -201,9 +215,13 @@ namespace hex {
s_currentTutorial->second.start();
}
void TutorialManager::stopCurrentTutorial() {
s_currentTutorial = s_tutorials->end();
}
void TutorialManager::drawHighlights() {
if (s_helpHoverActive) {
const auto &drawList = ImGui::GetForegroundDrawList();
const auto &drawList = ImGui::GetForegroundDrawList(ImGui::GetMainViewport());
drawList->AddText(ImGui::GetMousePos() + scaled({ 10, -5, }), ImGui::GetColorU32(ImGuiCol_Text), "?");
for (const auto &[id, boundingBox] : *s_interactiveHelpDisplays) {
@@ -251,6 +269,7 @@ namespace hex {
{
auto highlightColor = ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_Highlight);
highlightColor.w *= ImSin(ImGui::GetTime() * 6.0F) / 4.0F + 0.75F;
ImHexApi::System::unlockFrameRate();
drawList->AddRect(rect.Min - ImVec2(5, 5), rect.Max + ImVec2(5, 5), ImColor(highlightColor), 5.0F, ImDrawFlags_None, 2.0F);
}
@@ -299,10 +318,10 @@ namespace hex {
if (!message.has_value()) {
message = Tutorial::Step::Message {
Position::None,
"",
"",
false
.position=Position::None,
.unlocalizedTitle="",
.unlocalizedMessage="",
.allowSkip=false
};
}
@@ -329,34 +348,39 @@ namespace hex {
ImGui::SetNextWindowPos(position, ImGuiCond_Always, pivot);
ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID);
if (ImGui::Begin("##TutorialMessage", nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::SetNextWindowSize(ImVec2(300_scaled, 0));
bool open = true;
if (ImGui::Begin(message->unlocalizedTitle.empty() ? "##TutorialMessage" : Lang(message->unlocalizedTitle), &open, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindowRead());
if (!message->unlocalizedTitle.empty())
ImGuiExt::Header(Lang(message->unlocalizedTitle), true);
auto &step = s_currentTutorial->second.m_currentStep;
if (!message->unlocalizedMessage.empty()) {
ImGui::PushTextWrapPos(300_scaled);
ImGui::TextUnformatted(Lang(message->unlocalizedMessage));
ImGui::PopTextWrapPos();
step->m_drawFunction();
ImGui::NewLine();
ImGui::NewLine();
}
ImGui::BeginDisabled(s_currentTutorial->second.m_currentStep == s_currentTutorial->second.m_steps.begin());
if (ImGui::ArrowButton("Backwards", ImGuiDir_Left)) {
ImGui::BeginDisabled(step == s_currentTutorial->second.m_steps.begin());
if (ImGuiExt::DimmedArrowButton("Backwards", ImGuiDir_Left)) {
s_currentTutorial->second.m_currentStep->advance(-1);
}
ImGui::EndDisabled();
ImGui::SameLine();
ImGui::BeginDisabled(!message->allowSkip && s_currentTutorial->second.m_currentStep == s_currentTutorial->second.m_latestStep);
if (ImGui::ArrowButton("Forwards", ImGuiDir_Right)) {
s_currentTutorial->second.m_currentStep->advance(1);
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - ImGui::GetFrameHeight() - ImGui::GetStyle().WindowPadding.x);
ImGui::BeginDisabled(!message->allowSkip && step == s_currentTutorial->second.m_latestStep);
if (ImGuiExt::DimmedArrowButton("Forwards", ImGuiDir_Right)) {
step->advance(1);
}
ImGui::EndDisabled();
}
ImGui::End();
if (!open) {
stopCurrentTutorial();
}
}
void TutorialManager::drawTutorial() {
@@ -383,6 +407,10 @@ namespace hex {
s_highlightDisplays->clear();
}
void TutorialManager::setRenderer(std::function<DrawFunction(const std::string &)> renderer) {
s_renderer = std::move(renderer);
}
TutorialManager::Tutorial::Step& TutorialManager::Tutorial::addStep() {
auto &newStep = m_steps.emplace_back(this);
m_currentStep = m_steps.end();
@@ -398,6 +426,9 @@ namespace hex {
return;
m_currentStep->addHighlights();
if (m_currentStep->m_message.has_value())
m_currentStep->m_drawFunction = (*s_renderer)(Lang(m_currentStep->m_message->unlocalizedMessage));
}
void TutorialManager::Tutorial::Step::addHighlights() const {
@@ -422,8 +453,12 @@ namespace hex {
std::advance(m_parent->m_latestStep, steps);
std::advance(m_parent->m_currentStep, steps);
if (m_parent->m_currentStep != m_parent->m_steps.end())
if (m_parent->m_currentStep != m_parent->m_steps.end()) {
m_parent->m_currentStep->addHighlights();
if (m_message.has_value())
m_parent->m_currentStep->m_drawFunction = (*s_renderer)(Lang(m_parent->m_currentStep->m_message->unlocalizedMessage));
}
else
s_currentTutorial = s_tutorials->end();
}
@@ -446,10 +481,10 @@ namespace hex {
TutorialManager::Tutorial::Step& TutorialManager::Tutorial::Step::setMessage(const UnlocalizedString &unlocalizedTitle, const UnlocalizedString &unlocalizedMessage, Position position) {
m_message = Message {
position,
unlocalizedTitle,
unlocalizedMessage,
false
.position=position,
.unlocalizedTitle=unlocalizedTitle,
.unlocalizedMessage=unlocalizedMessage,
.allowSkip=false
};
return *this;
@@ -460,10 +495,10 @@ namespace hex {
m_message->allowSkip = true;
} else {
m_message = Message {
Position::Bottom | Position::Right,
"",
"",
true
.position=Position::Bottom | Position::Right,
.unlocalizedTitle="",
.unlocalizedMessage="",
.allowSkip=true
};
}

View File

@@ -135,7 +135,7 @@ namespace hex {
void WorkspaceManager::process() {
if (s_previousWorkspace != s_currentWorkspace) {
log::info("Updating workspace");
log::debug("Updating workspace");
if (s_previousWorkspace != s_workspaces->end()) {
auto newWorkspace = s_currentWorkspace;
s_currentWorkspace = s_previousWorkspace;

View File

@@ -151,8 +151,8 @@ namespace hex::dp {
m_overlay->getData() = data;
}
[[noreturn]] void Node::throwNodeError(const std::string &message) {
throw NodeError { this, message };
[[noreturn]] void Node::throwNodeError(const std::string &msg) {
throw NodeError(this, msg);
}
void Node::setAttributes(std::vector<Attribute> attributes) {

View File

@@ -0,0 +1,175 @@
#include <hex/helpers/binary_pattern.hpp>
#include <algorithm>
namespace hex {
namespace {
void skipWhitespace(std::string_view &string) {
while (!string.empty()) {
if (!std::isspace(string.front()))
break;
string = string.substr(1);
}
}
std::vector<BinaryPattern::Pattern> parseValueExpression(std::string_view &string) {
string = string.substr(1);
// Parse bit size number
u64 bitSize = 0;
std::endian endian = std::endian::little;
while (!string.empty() && std::isdigit(string.front())) {
bitSize *= 10;
bitSize += string.front() - '0';
string = string.substr(1);
skipWhitespace(string);
}
if (string.starts_with("le")) {
endian = std::endian::little;
string = string.substr(2);
} else if (string.starts_with("be")) {
endian = std::endian::big;
string = string.substr(2);
}
if (bitSize > 64 || bitSize % 8 != 0)
return { };
if (string.empty() || string.front() != '(')
return { };
string = string.substr(1);
i128 value = 0x00;
bool negative = false;
for (u32 i = 0; !string.empty(); i++) {
const char c = string.front();
if (c == ')') break;
if (i == 0 && c == '-')
negative = true;
else if (i == 0 && c == '+')
continue;
else if (std::isdigit(c))
value = value * 10 + (c - '0');
else
return {};
string = string.substr(1);
}
if (negative)
value = -value;
if (string.empty() || string.front() != ')')
return { };
string = string.substr(1);
u128 resultValue = changeEndianness(value, bitSize / 8, endian);
std::vector<BinaryPattern::Pattern> result;
for (u32 bit = 0; bit < bitSize; bit += 8) {
result.emplace_back(
0xFF,
u8((resultValue >> bit) & hex::bitmask(8))
);
}
return result;
}
std::vector<BinaryPattern::Pattern> parseBinaryPatternString(std::string_view string) {
std::vector<BinaryPattern::Pattern> result;
if (string.length() < 2)
return { };
bool inString = false;
while (!string.empty()) {
BinaryPattern::Pattern pattern = { .mask=0, .value=0 };
if (string.starts_with("\"")) {
inString = !inString;
string = string.substr(1);
continue;
} else if (inString) {
pattern = { .mask=0xFF, .value=u8(string.front()) };
string = string.substr(1);
} else if (string.starts_with("u") || string.starts_with("s")) {
auto newPatterns = parseValueExpression(string);
if (newPatterns.empty())
return {};
std::ranges::move(newPatterns, std::back_inserter(result));
continue;
} else if (string.starts_with("??")) {
pattern = { .mask=0x00, .value=0x00 };
string = string.substr(2);
} else if ((std::isxdigit(string.front()) || string.front() == '?') && string.length() >= 2) {
const auto hex = string.substr(0, 2);
for (const auto &c : hex) {
pattern.mask <<= 4;
pattern.value <<= 4;
if (std::isxdigit(c)) {
pattern.mask |= 0x0F;
if (auto hexValue = hex::hexCharToValue(c); hexValue.has_value())
pattern.value |= hexValue.value();
else
return { };
} else if (c != '?') {
return { };
}
}
string = string.substr(2);
} else if (std::isspace(string.front())) {
string = string.substr(1);
continue;
} else {
return { };
}
result.push_back(pattern);
}
if (inString)
return { };
return result;
}
}
BinaryPattern::BinaryPattern(const std::string &pattern) : m_patterns(parseBinaryPatternString(pattern)) { }
bool BinaryPattern::isValid() const { return !m_patterns.empty(); }
bool BinaryPattern::matches(const std::vector<u8> &bytes) const {
if (bytes.size() < m_patterns.size())
return false;
for (u32 i = 0; i < m_patterns.size(); i++) {
if (!this->matchesByte(bytes[i], i))
return false;
}
return true;
}
bool BinaryPattern::matchesByte(u8 byte, u32 offset) const {
const auto &pattern = m_patterns[offset];
return (byte & pattern.mask) == pattern.value;
}
u64 BinaryPattern::getSize() const {
return m_patterns.size();
}
}

Some files were not shown because too many files have changed in this diff Show More