Compare commits

...

392 Commits

Author SHA1 Message Date
WerWolv
efe0928fc6 feat: Initial work rework current project system 2025-02-10 21:44:14 +01:00
WerWolv
b3d208e6e6 impr: Allow sidebar to be only resized from the right 2025-02-10 21:42:12 +01:00
WerWolv
e8b391c0f6 feat: Added option to randomize window title 2025-02-10 14:02:32 +01:00
WerWolv
02b5df03ab impr: Drastically reduce font-related memory usage 2025-02-10 12:02:05 +01:00
WerWolv
e1580e51cf build: Make ImHex fully compile with warnings enabled in MSVC 2025-02-10 09:42:35 +01:00
WerWolv
3a7578879f fix: RGBA8 data processor node not working correctly 2025-02-09 23:38:35 +01:00
WerWolv
ea3d4b41a9 patterns: Updated pattern language 2025-02-09 10:28:46 +01:00
WerWolv
e0c2a39ce7 build: Fix ARM64 macOS build issues 2025-02-08 11:27:40 +01:00
WerWolv
1fa27b7f09 build: Fix remaining wasm build issues 2025-02-08 10:50:04 +01:00
WerWolv
f980f1dae2 build: Compress wasm build romfs 2025-02-07 23:56:50 +01:00
WerWolv
b81ad53449 build: Move vcpkg.json away 2025-02-07 23:56:50 +01:00
WerWolv
a9727171e2 build: vcpkg is already installed in the macOS docker 2025-02-07 23:37:10 +01:00
WerWolv
a1634fb337 build: Properly update vcpkg pages in web and macOS ARM docker 2025-02-07 23:34:05 +01:00
WerWolv
94a2f9460e impr: Use proper main() return values in forwarder 2025-02-07 22:19:35 +01:00
WerWolv
18cd39270a fix: Very slow processing of large pattern console outputs 2025-02-07 22:19:15 +01:00
WerWolv
72c2bca363 fix: Severe lack of easter eggs 2025-02-07 16:24:57 +01:00
WerWolv
4c153dc76d fix: Windows forwarder application not working when piping output 2025-02-07 16:23:27 +01:00
WerWolv
e63606f6bb feat: Added separate --version-short command 2025-02-07 15:46:11 +01:00
WerWolv
ed6da7fe14 fix: Writing not working correctly through a provider view 2025-02-07 15:45:38 +01:00
WerWolv
a588c96440 fix: Properly trigger global shortcuts 2025-02-06 22:34:34 +01:00
WerWolv
4c284b224e fix: Properly trigger all shortcuts 2025-02-06 22:33:14 +01:00
WerWolv
96afa650d1 fix: Properly trigger shortcuts on selected view on macOS 2025-02-06 22:13:06 +01:00
WerWolv
f17d0d3ae1 impr: Added simplified output option for --version 2025-02-06 21:46:27 +01:00
WerWolv
930d2b4280 fix: Some shortcuts not working correctly on macOS 2025-02-06 15:58:18 +01:00
WerWolv
f67b78bd91 build: Update vcpkg baseline on build 2025-02-06 15:24:57 +01:00
WerWolv
540e8ed602 build: Install vcpkg again in the ARM64 macOS docker 2025-02-06 15:21:07 +01:00
WerWolv
99cb51e813 build: Updated vcpkg baseline 2025-02-06 15:08:48 +01:00
WerWolv
db000c4b12 fix: Missing GLFW include on macOS 2025-02-06 14:12:52 +01:00
WerWolv
0cd557a686 impr: Remove frame from selectable text regions 2025-02-06 14:00:32 +01:00
WerWolv
6142bf859b fix: Missing new line 2025-02-06 13:27:48 +01:00
WerWolv
b6498b5c2d fix: Build error when including file in ObjC code 2025-02-06 13:04:36 +01:00
WerWolv
c15030e96e git: Remove libpl from PDB extraction process 2025-02-06 13:04:01 +01:00
WerWolv
cd2acd73b4 build: Fix libpl linking 2025-02-06 12:08:57 +01:00
WerWolv
cfe06ea1b6 build: Statically link libpl again everywhere 2025-02-06 12:03:20 +01:00
WerWolv
ca5c3e0e94 build: Fix linking against libpl in external plugins 2025-02-05 20:09:42 +01:00
WerWolv
6252fd399a fix: Loading/Storing of shortcut keys 2025-02-05 20:09:24 +01:00
WerWolv
de571e2c2a build: Updated libwolv 2025-02-05 20:09:12 +01:00
WerWolv
0cbd052b91 build: Updated dependencies 2025-02-05 15:09:09 +01:00
WerWolv
aa3ec3ece8 build: Updated dependencies 2025-02-05 13:49:16 +01:00
WerWolv
6b11028b72 impr: Use proper function to get environment variables 2025-02-05 13:47:38 +01:00
WerWolv
269c3e7398 fix: Wrong keys being loaded from settings for shortcuts 2025-02-05 13:47:17 +01:00
WerWolv
08335041f5 fix: Crash on Linux uf XDG_SESSION_TYPE is not set 2025-02-05 09:40:13 +01:00
WerWolv
d75b9cf942 build: Properly link plugins against libpl if it's a shared library 2025-02-04 12:16:46 +01:00
WerWolv
b55c40523f fix: Crash when closing ImHex with one or more view providers open 2025-02-04 09:35:26 +01:00
WerWolv
99a2dee7a2 build: Updated libromfs 2025-02-03 22:06:43 +01:00
WerWolv
c94265c77b build: Only add magic library dir in regular build 2025-02-03 21:48:13 +01:00
WerWolv
7ddfba1b4c build: Exclude more libraries from external plugin builds 2025-02-03 21:46:21 +01:00
WerWolv
9ecdd28eea build: Don't link against libcurl in external plugin builds 2025-02-03 21:43:57 +01:00
WerWolv
d8b36242f6 build: Don't set EXPORT_SYMBOLS when doing an external plugin build 2025-02-03 21:33:41 +01:00
WerWolv
3f470aabe9 fix: Compile errors 2025-02-03 21:11:48 +01:00
WerWolv
1e8dd54b3e build: Don't set -Wno-unused-result on MSVC 2025-02-03 20:51:47 +01:00
WerWolv
0a6681ccb7 impr: Remove dependencies on curl, mbedTLS and GLFW in the SDK 2025-02-03 20:50:11 +01:00
WerWolv
0140e24822 build: Fixed warning in miniaudio library 2025-02-03 16:05:40 +01:00
WerWolv
9fb38922ea impr: Disable main menu items for views that aren't selected right now 2025-02-02 22:32:24 +01:00
WerWolv
7752354598 impr: Make dark theme text slightly off-white 2025-02-02 21:48:12 +01:00
WerWolv
497670c4c3 fix: Don't apply backing scale factor twice to splash screen 2025-02-02 21:36:49 +01:00
WerWolv
84954cd2f1 build: Fixed more SDK errors 2025-02-02 21:22:42 +01:00
WerWolv
8b6eab401e fix: "Other Data Sources" welcome screen sub-window being too tall 2025-02-02 21:15:56 +01:00
WerWolv
71c11a5923 fix: Banner position being wrong while provider is loaded 2025-02-02 21:15:31 +01:00
WerWolv
f345edb252 fix: Banners not being part of the main viewport 2025-02-02 21:06:18 +01:00
WerWolv
be40fd9563 build: Apply flags correctly for imported libraries 2025-02-02 20:50:49 +01:00
WerWolv
5ee2ebfb4f build: Fix addXXXFlag functions for interface targets 2025-02-02 20:32:24 +01:00
WerWolv
cfa6b706a8 patterns: Updated pattern language 2025-02-02 20:32:06 +01:00
WerWolv
42f2a62d62 build: Make plugin library sdk path relative 2025-02-02 19:05:10 +01:00
WerWolv
41b6ef930a build: Fix MinGW build 2025-02-02 17:19:34 +01:00
WerWolv
948cbe0a9c build: Updated dependencies 2025-02-02 13:08:08 +01:00
WerWolv
18669f3230 build: Move back to upstream lunasvg 2025-02-02 12:14:32 +01:00
Tim Blume
4e9f944204 build: Install include folders of plugin libraries to SDK (#2074)
Partially fixes #2068 .

This assumes the headers are in "include" for all plugins - this is
necessary since the INCLUDES argument of add_imhex_plugin may contain
paths to third party libs, whose headers should not be copied.
To fix this I think it is necessary to add a second argument like
"PRIVATE_INCLUDES", which is included, but not installed.

With this it possible to append the ui plugin for example:
```
INCLUDES
        $ENV{IMHEX_SDK_PATH}/lib/plugins/ui/
```
and to link against it:
```    
LIBRARIES
        /usr/local/lib/imhex/plugins/ui.hexpluglib
```

In a follow-up in the CMake Template for plugins imho there should be
fixed, that:

 - you can include plugin includes relative to the SDK Path
- you can link plugins relative to the lib path + without the hexpluglib
or hexplug extension

---------

Co-authored-by: Tim Blume <git@3nd.io>
Co-authored-by: Nik <werwolv98@gmail.com>
2025-02-02 12:12:40 +01:00
WerWolv
fe18cbaa41 fix: Always properly jump to cursor position when scrolling with arrow keys
Fixes #1582
2025-02-02 12:06:34 +01:00
WerWolv
ed3712e1b9 fix: Shortcuts not working until a modal is opened 2025-02-02 12:00:59 +01:00
WerWolv
20dc4f31f0 impr: Show a loading spinner while providers are loading 2025-02-02 11:24:50 +01:00
WerWolv
19f9296a40 feat: Added blocking tasks that show a full-screen modal when active 2025-02-02 11:24:28 +01:00
WerWolv
06c019387c build: Fix most remaining warnings 2025-02-01 22:11:19 +01:00
WerWolv
645b43e9cc fix: Various MSVC warnings 2025-02-01 20:54:00 +01:00
WerWolv
ed37a3711f build: Fix extra comma 2025-02-01 20:23:02 +01:00
WerWolv
a3460de9dc build: Make VS CMake Preset do a 64 bit build 2025-02-01 20:20:42 +01:00
WerWolv
5084009d62 fix: Invalid iterator dereference when removing providers 2025-02-01 20:10:13 +01:00
WerWolv
e5c003d726 fix: Only use __declspec on with MSVC 2025-02-01 19:57:39 +01:00
WerWolv
327a02b87d fix: Plugins not having a proper entry point on MSVC 2025-02-01 19:14:15 +01:00
WerWolv
e9bf1a9f7a fix: Crash when no plugins were loaded 2025-02-01 18:08:47 +01:00
WerWolv
0c6fa768ea build: Fix building for 64bit with MSVC 2025-02-01 18:08:35 +01:00
WerWolv
483468a6c7 impr: Make WorkspaceManager internals static 2025-02-01 16:02:45 +01:00
WerWolv
8039ae1b90 build: Make ImHex fully compile with MSVC and Clang CL
This does NOT make ImHex work yet. However it can now be compiled
2025-02-01 15:13:13 +01:00
WerWolv
466b372d41 build: Added vcpkg manifest 2025-01-31 23:48:52 +01:00
WerWolv
3f6b5203ca fix: Further MSVC compile fixes 2025-01-31 23:48:38 +01:00
WerWolv
8d1352ddff fix: Remaining compile errors 2025-01-31 20:23:47 +01:00
WerWolv
e6ab2c3b7e impr: Various small fixes and improvements 2025-01-31 19:43:39 +01:00
WerWolv
e603c75bd3 build: Updated dependencies 2025-01-31 19:40:58 +01:00
WerWolv
4f28f97141 git: Fix workflow indentation 2025-01-30 22:34:50 +01:00
WerWolv
d0b32e5224 git: Try creating dmg a few times again in case XProtect is being a bitch 2025-01-30 22:25:00 +01:00
WerWolv
2062a23347 patterns: Updated pattern language 2025-01-30 22:12:04 +01:00
WerWolv
8c9236a066 patterns: Updated pattern language 2025-01-30 21:31:14 +01:00
paxcut
2f981ef91e fix: Banners not scaling properly with font size (#2096)
The banner windows did not scale with the fonts resulting in cropped
text when font size was made bigger than normal.
fixed by ensuring the window is big enough and then making sure text is
centered in the y-axis.
2025-01-30 20:18:44 +01:00
WerWolv
6725c170ea build: Updated dependencies 2025-01-30 20:12:19 +01:00
WerWolv
c8cf6e7c08 build: Fix compile errors on platforms where sizeof(long double) > sizeof(unsigned long long) 2025-01-29 22:16:42 +01:00
Connor Gibson
e0b4acee12 build: Updated macOS compile instructions as Brewfile has moved (#2093)
<!--
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
Brewfile has moved from `dist/Brewfile` to `dist/macOS/Brewfile`.

### Implementation description
Updated build instructions to reflect this previous change

### Screenshots
N/A

### Additional things
N/A
2025-01-29 21:38:47 +01:00
WerWolv
803ebe34ed build: Update for software defined 128 bit types 2025-01-29 21:37:41 +01:00
WerWolv
e981eff1e6 fix: Uninitialized buffers in resize operation 2025-01-29 18:39:19 +01:00
WerWolv
aee7a09b6c feat: Added new --select, --pattern and --debug-mode subcommands 2025-01-29 18:32:54 +01:00
WerWolv
e74e4e92a0 build: Updated libwolv 2025-01-29 18:32:35 +01:00
WerWolv
6dba15defd impr: Removed black border from splash screen bytes 2025-01-28 23:41:44 +01:00
WerWolv
fee7a16692 fix: Exception being thrown while loading projects
Fixes #2091
2025-01-28 23:23:31 +01:00
WerWolv
141030344b fix: Crash when certain pattern language exceptions were thrown
Fixes #2091
2025-01-28 23:23:08 +01:00
WerWolv
4fa9586206 impr: Added Russian language to WiX installer and ImHex Web 2025-01-28 20:55:10 +01:00
WerWolv
fbbc430b7c fix: Body text being displayed in response text field 2025-01-28 20:53:01 +01:00
WerWolv
bfc68c4d28 fix: Replace HTTP Requests text editors with input text boxes 2025-01-28 20:52:00 +01:00
WerWolv
53fc018ada fix: --pl subcommand not working correctly anymore 2025-01-28 19:47:20 +01:00
WerWolv
d45dd45720 fix: Windows system error messages not being encoded correctly 2025-01-28 19:33:31 +01:00
WerWolv
19a9786bbf impr: Make ImHex cli work more like other tools 2025-01-28 18:41:29 +01:00
WerWolv
b8caf41423 fix: Make sure splash screen is rendered consistently on all platforms 2025-01-28 18:38:20 +01:00
WerWolv
0b3866a56a fix: Wrong usage of windows icon texture 2025-01-27 22:35:27 +01:00
WerWolv
53a7577416 impr: Allow resizing of settings window 2025-01-27 22:20:15 +01:00
WerWolv
f5515417d6 fix: Message dispatching related build issues 2025-01-27 22:15:39 +01:00
WerWolv
24e7c2f3db fix: Make sure all textures are destroyed before glfw gets uninitialized 2025-01-27 22:10:30 +01:00
WerWolv
6e6c5bbc67 fix: Splash screen texture scaling 2025-01-27 21:20:59 +01:00
WerWolv
f4403ff480 impr: Make splash screen use SVG directly 2025-01-27 20:45:30 +01:00
WerWolv
098da20761 fix: Delete splash textures before destroying splash screen 2025-01-27 19:08:01 +01:00
WerWolv
ef2373e8c0 feat: Implement messaging support for Linux 2025-01-27 19:07:22 +01:00
WerWolv
b2c8ed17d5 feat: Added shortcut for opening settings 2025-01-26 22:41:20 +01:00
Nik
bb594a459f feat: Implemented macOS messaging support (#2088) 2025-01-26 18:50:19 +01:00
WerWolv
7340a30650 impr: Make scalable font the default 2025-01-26 14:26:57 +01:00
WerWolv
403104dda1 fix: Properly scale unifont glyphs 2025-01-26 14:21:17 +01:00
WerWolv
8334fbb236 fix: Properly apply backing scaling to pixel perfect default font 2025-01-26 14:18:20 +01:00
WerWolv
0a0323ce5d git: Run CI on feature branches 2025-01-26 13:42:19 +01:00
WerWolv
726d36ba3d git: Fix creation of ARM64 DMG trying to enter wrong path 2025-01-26 11:26:04 +01:00
WerWolv
8bb1521963 git: Fix ARM64 .app path 2025-01-26 10:54:26 +01:00
WerWolv
9457c1f2b9 git: Install ImageMagick so create-dmg can make a pretty volume icon 2025-01-26 10:45:26 +01:00
WerWolv
2b24330f9f build: Updated ImHex icons in MSI installer 2025-01-26 10:40:53 +01:00
WerWolv
9329170e59 git: Ignore missing signature when building DMG 2025-01-26 10:32:37 +01:00
WerWolv
98f3de828a git: Add create-dmg to PATH 2025-01-26 10:27:09 +01:00
WerWolv
3f38f42259 git: Produce nicer looking DMG file for macOS 2025-01-26 10:19:05 +01:00
WerWolv
058a8cdc15 fix: Missing <cstdlib> include 2025-01-26 09:22:53 +01:00
WerWolv
d0c1213ea0 fix: Crash on systems where XDG_SESSION_TYPE isn't defined 2025-01-25 23:30:00 +01:00
WerWolv
30967bac6d fix: Modifier keys not working correctly on X11 2025-01-25 23:24:56 +01:00
WerWolv
09c9bcb046 fix: Pattern data filter not working correctly without a compare value 2025-01-25 23:17:03 +01:00
WerWolv
93f1f5d076 impr: Better font scaling with larger backing scale factors 2025-01-25 22:27:59 +01:00
WerWolv
93e5d62782 fix: Web build scaling 2025-01-25 20:12:21 +01:00
Bananchiki
4d7021ece1 lang: Added Russian translation (#1964)
<!--
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 !
-->

### Description
This pull request introduces a complete Russian translation for ImHex,
ensuring that Russian-speaking users can navigate and utilize the
software in their native language. The translation covers all user
interface elements, menus, dialogs, and messages, providing a seamless
experience for Russian users.

### Testing
The translation has been thoroughly tested to ensure accuracy and
completeness. All translated text has been reviewed for grammatical
correctness and contextual appropriateness.

### Screenshots

![image](https://github.com/user-attachments/assets/455ca03d-0b33-45d2-9ed5-ddb404bd0728)

![image](https://github.com/user-attachments/assets/a7ebdb40-806f-43d9-ab36-deea730505c1)

![image](https://github.com/user-attachments/assets/29c5d21b-7443-4751-9129-e5fa054066d3)

Co-authored-by: Lemon4ksan <senya20151718@gmail.com>
2025-01-25 20:06:18 +01:00
WerWolv
f976988c75 impr: Try to detect backing scaling factor on the web build 2025-01-25 19:08:56 +01:00
WerWolv
1eee31fdbb fix: Debug mode only being enabled after everything has been initialized already 2025-01-25 16:54:16 +01:00
paxcut
048c483903 fix: Pattern Editor shortcuts not working correctly on different languages (#2085)
Fixes #2084 

Error in text editor prevented using shortcuts when language other than
English was chosen.

The code was mistakenly using localized name to test which window had
focus a execute the shortcut.

Fixed it by switching the name of the child window to the constant value
used to check the windows focused identity.
2025-01-25 16:34:27 +01:00
Wolf
b646ece14b impr: Refactor and restructure Event Manager (#2082)
### Problem description
This PR addresses issue #2013 that described a cluttered Event Manager.

This is a DX issue and should not impact the users whatsoever.

### Implementation description
The changes revolve around three main points:

1. the Event Manager (`event_manager.hpp`) was split into four
categories: GUI, Interaction, Lifecycle, and Provider, and two types:
Events, and Requests. This results in the following files:
    - `events_gui.hpp`
    - `events_interaction.hpp`
    - `events_lifecycle.hpp`
    - `events_provider.hpp`
    - `requests_gui.hpp`
    - `requests_interaction.hpp`
    - `requests_lifecycle.hpp`
    - `requests_provider.hpp`

2. Every event and request now has its own piece of documentation, with
a `@brief`, accompanied by a longer comment if needed, and gets its
`@param`s described.

3. The old `event_manager.hpp` import was removed and replaced by the
correct imports wherever needed, as to reduce spread of those files only
to where they are truly useful.

### Additional things
The commits have been split into (chrono-)logical steps:
- `feat`: split the Event Manager, and replace the imports
- `refactor`, `chore`: make various small changes to match the required
structure
- `docs`: add documentation for events and requests

Hopefully, this will help to review the PR.
*Note: Beware of very long rebuild times in between the commits, use
them sparingly! The Actions will ensure this PR builds anyways*

Closes #2013

---------

Signed-off-by: BioTheWolff <47079795+BioTheWolff@users.noreply.github.com>
Co-authored-by: Nik <werwolv98@gmail.com>
2025-01-25 15:32:07 +00:00
WerWolv
35e8acd69d impr: Only enable font config Apply button when setting has changed 2025-01-25 15:50:52 +01:00
WerWolv
de4135d1ad fix: ID collision with multiple items of the same name in the Accept Pattern popup 2025-01-25 15:47:09 +01:00
WerWolv
a44959ce1b feat: Added option to enable debug features in release builds 2025-01-25 15:38:57 +01:00
WerWolv
f4bad0053a fix: Linking errors in the web build 2025-01-25 15:24:44 +01:00
WerWolv
26af5987a5 fix: Properly check if distro info exists before printing it 2025-01-25 15:24:25 +01:00
WerWolv
9cf3250751 impr: Replace GitBook AI garbage with simple search API 2025-01-24 22:31:49 +01:00
WerWolv
acc77205bb fix: Image visualizer data processor nodes not working
Fixes #2081
2025-01-24 21:36:29 +01:00
WerWolv
a6b4f62d75 fix: Opening files in existing instance not working 2025-01-23 19:22:40 +01:00
WerWolv
69c5d553b5 fix: Disable postprocessing shaders in Web version 2025-01-22 19:55:17 +01:00
WerWolv
637cdd7084 git: Only generate attestation on main repo 2025-01-22 19:19:19 +01:00
WerWolv
8978e193db impr: Better OS-specific handling of system exceptions 2025-01-21 23:28:22 +01:00
WerWolv
242b100aa3 fix: Properly detect Windows 10 2025-01-20 21:45:53 +01:00
WerWolv
3a888d48df fix: ID collision with color inline visualizer 2025-01-20 21:25:00 +01:00
WerWolv
721de39dbb impr: Make icon context menu use MenuItemEx for its icons 2025-01-20 21:24:49 +01:00
WerWolv
07e29f2030 feat: Added support for OpenGL post processing shaders 2025-01-20 21:24:25 +01:00
WerWolv
c117d9b3e5 fix: Crash when changing DPI 2025-01-19 23:07:53 +01:00
WerWolv
16eae89151 fix: Save/Save As toolbar items being missing by default 2025-01-19 21:49:34 +01:00
WerWolv
95cb6d8ee6 patterns: Updated pattern language 2025-01-19 19:23:48 +01:00
WerWolv
af27c09204 fix: I guess we can still not use std::views::enumerate 2025-01-19 17:54:18 +01:00
WerWolv
5e3532267c fix: Missing glfw include 2025-01-19 17:52:32 +01:00
WerWolv
7c0331df65 impr: Hide window on macOS when close button is pressed 2025-01-19 17:04:31 +01:00
WerWolv
04ab87cd8e patterns: Updated pattern language 2025-01-19 14:42:02 +01:00
WerWolv
91f5e84250 impr: Don't insert a new line at the end of settings pages 2025-01-19 10:56:00 +01:00
WerWolv
b1edd95ebc impr: Shortcut code cleanup 2025-01-19 10:55:27 +01:00
WerWolv
758738da5c fix: Default font not being the default font 2025-01-19 10:34:54 +01:00
WerWolv
41c8be275b fix: Assert when selecting selectable text 2025-01-19 00:26:26 +01:00
WerWolv
117eb1e2a7 feat: Added more granular font settings
Fixes #1260
2025-01-18 23:34:43 +01:00
WerWolv
3129d6e8fd impr: Simplified custom font selection 2025-01-18 19:03:55 +01:00
WerWolv
2ba7db184b build: Fix favicon transparency for ImHex Web 2025-01-18 17:47:36 +01:00
WerWolv
2cb0df4080 build: Properly optimize web build 2025-01-18 16:53:11 +01:00
WerWolv
3adc2c44e6 fix: Font customization not unlocking correctly 2025-01-18 16:05:11 +01:00
WerWolv
6d3ff64894 fix: ImHex using a lot of CPU 2025-01-18 14:57:06 +01:00
WerWolv
cf84ad6196 fix: Added back old constructor for Widgets::DropDown 2025-01-18 14:56:53 +01:00
WerWolv
6259190ad9 impr: Make localization fall back to english if it doesn't exist 2025-01-18 14:40:10 +01:00
WerWolv
181be1a58e fix: Missing paste behaviour option translations 2025-01-18 14:36:31 +01:00
WerWolv
771e191f28 fix: Windows icon not being transparent anymore 2025-01-18 14:11:49 +01:00
WerWolv
d4d6893eb3 git: Make sure PORTABLE flag is created correctly 2025-01-18 13:58:20 +01:00
WerWolv
9e75562662 build: Fix RPM icon path 2025-01-18 13:45:57 +01:00
WerWolv
2b3168163b git: Extract PDBs for for portable version properly 2025-01-18 13:45:32 +01:00
WerWolv
252c06eb12 build: Extract PDBs from build files 2025-01-18 13:26:12 +01:00
WerWolv
2a51d8169a build: Move icon to correct location 2025-01-18 13:18:33 +01:00
WerWolv
7405c4b411 build: Updated disassembler library 2025-01-18 13:06:31 +01:00
WerWolv
309ae7b619 build: Fixed disassembler library git messup 2025-01-18 12:38:20 +01:00
WerWolv
64ef56a0df git: Fixed Windows PDB extraction process 2025-01-18 12:04:46 +01:00
WerWolv
fbfe7b0d25 impr: Unlock frame rate for the first few seconds after startup 2025-01-18 11:58:49 +01:00
WerWolv
8c7e1a3b2d impr: Replace icon with Papyrus icon.
Special thanks to @varlesh and @morganist
See https://github.com/PapirusDevelopmentTeam/papirus-icon-theme/issues/3909
2025-01-18 11:55:17 +01:00
WerWolv
bf249cdafe build: Updated disassembler library 2025-01-18 11:07:28 +01:00
WerWolv
59ba6f50cc build: Disable install targets of libfmt to fix Windows WIX installer 2025-01-18 11:03:51 +01:00
WerWolv
8d6e7c7d44 fix: Decompressor compile errors 2025-01-18 10:28:20 +01:00
WerWolv
52934ae166 feat: Make decompress functions return number of read bytes 2025-01-18 10:14:47 +01:00
WerWolv
56c4f2aa47 fix: ID collision with multiple banners on screen 2025-01-17 23:12:09 +01:00
WerWolv
a1d8cbd7ba fix: Properly update window position during resize 2025-01-17 23:11:53 +01:00
Nik
63a219a32b build: Added ARM64 AppImage build (#2073) 2025-01-17 22:55:41 +01:00
WerWolv
14fb256a6a build: Updated dependencies 2025-01-17 21:09:56 +01:00
WerWolv
95df7a23c3 build: Add new SDK files to Fedora package 2025-01-17 20:41:49 +01:00
WerWolv
bb17690cf5 build: Fix cv2pdb extraction errors 2025-01-17 19:56:25 +01:00
WerWolv
a943b02e43 build: Make sure unzip is installed on the CI 2025-01-17 19:50:41 +01:00
WerWolv
199f78347f build: Move PDB extraction to CI 2025-01-17 19:44:33 +01:00
WerWolv
d3d9a42d57 build: Added library plugin files to SDK 2025-01-17 19:32:52 +01:00
WerWolv
1fa45a8c84 fix: Replace bookmark comment Text Editor with multi-line text input
Closes #2056, Closes #2055
2025-01-17 17:28:13 +01:00
WerWolv
0b6316ea23 fix: Added back deleted variable to make web build work again 2025-01-17 17:26:46 +01:00
WerWolv
466a843263 build: Fix backwards compat with older cmake versions 2025-01-17 13:01:40 +01:00
WerWolv
b6ade8b101 fix: Shortcuts not working in detached windows 2025-01-17 12:39:55 +01:00
WerWolv
ff66b97e90 build: Get rid of some cmake warnings 2025-01-17 12:39:39 +01:00
WerWolv
c604ec8fb9 patterns: Updated pattern language 2025-01-16 21:23:22 +01:00
WerWolv
7564651dd5 patterns: Updated pattern language 2025-01-16 19:52:45 +01:00
WerWolv
cad17ddefd fix: Banners being misplaced on macOS 2025-01-16 19:27:22 +01:00
WerWolv
25d2f209e5 patterns: Updated pattern language 2025-01-16 19:15:39 +01:00
WerWolv
8d660c3ffe fix: Missing <numbers> include 2025-01-16 17:37:51 +01:00
WerWolv
209055d0b0 impr: Show a banner about degraded performance in debug mode 2025-01-16 17:09:17 +01:00
WerWolv
599b55965a impr: Improve the shadow of banners 2025-01-16 17:09:04 +01:00
WerWolv
69a9af5322 patterns: Added error pattern to pattern drawer 2025-01-16 17:08:49 +01:00
WerWolv
0303cd0ad0 patterns: Updated pattern language 2025-01-16 17:08:23 +01:00
WerWolv
8eb7e9fb05 fix: ID collision in provider data information section 2025-01-15 20:34:25 +01:00
WerWolv
6a1de5fc4e build: Updated ImGui to v1.91.7 2025-01-15 19:52:24 +01:00
WerWolv
a4af55cb66 build: Rename imgui_custom to imgui_backend 2025-01-15 19:52:19 +01:00
paxcut
1e17422f5e fix: Pattern Editor Find and Replace history (#2064)
The previous implementation seems to have been broken by Imgui updates. 

There is also some improvement in focus handling and also a bug in
replace where the last match was not being replaced has been fixed.

Fixed also slowdown in large files when only one char was typed by not
searching until enter has been pressed.

Added key repetitions for enter and arrows to be able to handle large
number of matches and fixed some formatting problems.
2025-01-15 19:40:12 +01:00
paxcut
8abaafab79 fix: Crash in 3D Visualizer, improved error messages (#2062)
The recently added data checks allowed invalid sized vertex arrays to be
used as if they were valid making ImHex crash.

Moved all the error messages into localization strings for translation.
2025-01-15 19:38:38 +01:00
WerWolv
71e1465524 fix: Image visualizer node trying to create texture in non-main thread 2025-01-15 19:34:58 +01:00
WerWolv
3d2ea3753b fix: Missing <clocale> include 2025-01-15 19:31:33 +01:00
Nik
88530eff8b git: Updated screenshots in readme 2025-01-15 18:31:41 +01:00
WerWolv
df3decf71b build: Updated libwolv 2025-01-15 18:08:45 +01:00
WerWolv
565ee4cb2d fix: Banner positions with multi-viewports enabled 2025-01-15 18:08:05 +01:00
WerWolv
40fc325ba9 fix: Disable bogus Keypad to function key conversions on macOS 2025-01-15 17:59:57 +01:00
WerWolv
6aca16102d impr: Move up the right column on the welcome screen to avoid a scrollbar at default size 2025-01-15 17:54:35 +01:00
WerWolv
cb11b57ab1 feat: Added banners, replace some modals with them 2025-01-15 17:54:07 +01:00
WerWolv
d504937d50 fix: Empty regions in Intel Hex and Motorola SREC files not being displayed correctly 2025-01-14 23:54:07 +01:00
WerWolv
6bfdb7ca4e fix: Make sure provider switch buttons and close button don't overlap 2025-01-14 22:10:58 +01:00
WerWolv
e1637824c6 impr: Make strings in the data information view selectable and copyable 2025-01-14 22:05:29 +01:00
WerWolv
e36f2f2bcb fix: Replace "data processor" text with "data inspector" for the custom data inspector row hint 2025-01-14 17:51:26 +01:00
WerWolv
1a54e08f11 fix: Remove constexpr from functions that really aren't constexpr 2025-01-14 17:50:48 +01:00
WerWolv
ecc86ee429 fix: ImNodes not being deinitialized correctly 2025-01-14 17:50:29 +01:00
WerWolv
185a593bc2 fix: AllowWhileTyping shortcuts only working while typing 2025-01-14 17:50:06 +01:00
WerWolv
4a916ebb89 feat: Added New File option to the GNOME launcher and a --new cli option 2025-01-14 17:49:48 +01:00
WerWolv
1c305ca762 fix: Icons still following custom font size when using default font 2025-01-13 22:34:30 +01:00
WerWolv
17fff56fa0 impr: Make sure Windows title icon is scaled correctly 2025-01-13 22:31:24 +01:00
WerWolv
ec1b1c2b7d impr: More constexpr 2025-01-13 22:31:06 +01:00
WerWolv
7bae22f56f fix: Font selector still saying "Custom Font Path" 2025-01-13 22:20:53 +01:00
WerWolv
21e5eeef16 impr: Reduce default font size slightly, adjust element sizes on welcome screen 2025-01-13 22:17:14 +01:00
WerWolv
bf5eea80f6 impr: Make font size setting use points instead of pixels 2025-01-13 22:04:55 +01:00
WerWolv
9f9a6d9827 impr: Move Jetbrains mono into regular font selector, allow it to be scaled 2025-01-13 22:04:44 +01:00
WerWolv
ae622e6d75 git: Merge WebAssembly build into main build artifacts script, add to releases 2025-01-12 23:08:09 +01:00
WerWolv
68fbff631f git: Fix github pages artifact name 2025-01-12 22:50:39 +01:00
WerWolv
6cdce75095 git: Upload artifact for ImHex Web build 2025-01-12 22:03:50 +01:00
WerWolv
f699e76c56 build: Fix comment causing issues with docker 2025-01-11 21:41:14 +01:00
WerWolv
a729329cd4 impr: Added missing [[nodiscard]]s 2025-01-11 21:40:42 +01:00
WerWolv
d5020ce9bb impr: Rename Jump To option to Follow Selection to avoid confusion with Go To 2025-01-11 21:40:26 +01:00
WerWolv
126868c251 fix: Hang when filtering for a large number of items in the pattern data view 2025-01-11 17:22:53 +01:00
WerWolv
b206e9fc95 fix: Copy-paste error with "Extend selection left" shortcut name 2025-01-11 16:42:00 +01:00
WerWolv
4b6ff68464 git: Fixed CI permissions 2025-01-11 16:28:29 +01:00
WerWolv
b23a0febb5 git: Added build provenance attestation for most artifacts 2025-01-11 16:17:27 +01:00
WerWolv
05ad547341 git: Use zstd to compress .deb builds 2025-01-11 15:57:42 +01:00
paxcut
f10af882a7 fix: Text Editor find option jumping to the wrong location (#2060)
After successfully finding matches and setting the cursor to them, the
screen would jump to the original window location upon closing the
window.

The error was caused by the wrong assumption that the scroll location
should be restored when window is closed. Instead, the right amount of
scrolling needs to be calculated to account for the window no longer
covering part of the text editor. Unused variable was discarded.

Another unrelated error is that the history of search names cannot be
accessed which will be addressed at a later PR.
2025-01-09 18:39:00 +01:00
WerWolv
98f32ebcad impr: Made interactive help api easier to use 2025-01-09 18:34:39 +01:00
WerWolv
e2c302836f feat: Added support for scanning binaries for UTF-8 strings 2025-01-09 18:33:45 +01:00
WerWolv
f1d9642cf6 impr: Better color picker widgets in the settings 2025-01-07 21:46:26 +01:00
WerWolv
5c58e5b545 fix: Selection highlight color setting not working
Fixes #2059
2025-01-07 18:09:56 +01:00
WerWolv
803cb335e1 feat: Added interface accent colors 2025-01-07 00:06:52 +01:00
WerWolv
ae4dde8255 impr: Unlock frame rate in more cases to make the UI feel more responsive 2025-01-06 20:34:00 +01:00
WerWolv
cb34f68b1b patterns: Updated pattern language 2025-01-06 20:15:21 +01:00
WerWolv
96ef983cfb fix: ASCII column not getting highlighted anymore 2025-01-06 20:14:27 +01:00
WerWolv
d8c3d67dfe build: Disable romfs compression in web build 2025-01-05 21:25:28 +01:00
WerWolv
5de5153663 impr: Simplify hex editor class API 2025-01-05 21:24:13 +01:00
WerWolv
1e747b6831 patterns: Updated pattern language 2025-01-05 19:18:46 +01:00
WerWolv
fbe9d16073 build: Updated libromfs 2025-01-05 17:52:04 +01:00
WerWolv
d02c0073a0 build: Ignore pdb copy file errors 2025-01-05 15:27:54 +01:00
WerWolv
1090b9879c build: Make pdb copy operation happen at install time 2025-01-05 15:20:03 +01:00
WerWolv
5a6af976cd build: Rename output pdb file if necessary 2025-01-05 15:14:25 +01:00
WerWolv
55e39a5d30 build: Fix dwarf stripping logic 2025-01-05 15:00:45 +01:00
WerWolv
c9b1ddfb59 build: Updated libromfs 2025-01-05 14:56:16 +01:00
WerWolv
f7dd696ffc build: Silence stupid brew errors 2025-01-05 14:51:03 +01:00
WerWolv
70f210ac5d build: Updated libromfs 2025-01-05 14:37:39 +01:00
WerWolv
cad1c11f8b build: Updated dependencies 2025-01-05 14:17:54 +01:00
WerWolv
f7fa305e82 build: Generate pdb file for libpl, significantly reduce binary size 2025-01-05 12:06:32 +01:00
WerWolv
f96c51e854 impr: Added shortcut for Copy as -> Custom Encoding 2025-01-05 11:12:56 +01:00
WerWolv
c19705d3e5 git: Try to silence brew error messages again 2025-01-05 10:42:29 +01:00
WerWolv
1190511994 impr: Cleanup frame rate unlocking code 2025-01-04 23:43:10 +01:00
WerWolv
69ee7ef63c build: Updated libwolv 2025-01-04 23:42:56 +01:00
WerWolv
fc95e5a9a8 impr: Unlock frame rate when scrolling or focusing 2025-01-04 22:00:26 +01:00
WerWolv
6ecc495d43 feat: Added visibility toggle to hide bookmark highlighting 2025-01-04 21:40:18 +01:00
WerWolv
6e861001cf impr: Allow all highlights to overlap each other 2025-01-04 21:40:03 +01:00
WerWolv
c56af08c7e impr: Allow highlights of multiple overlapping bookmarks to render 2025-01-04 20:46:56 +01:00
WerWolv
e68abefe48 impr: Use info icon for more help hovers 2025-01-04 19:21:22 +01:00
WerWolv
fd0635cb82 fix: Hex editor right click menu not working on macOS 2025-01-04 19:08:37 +01:00
WerWolv
baa3cfb354 fix: User folders being added twice 2025-01-04 18:30:57 +01:00
iTrooz
aea9bab853 build: Make MacOS arm64 build use clang 19 (#2050) 2025-01-04 18:10:48 +01:00
WerWolv
48de609f53 impr: Added telemetry about whether ImHex runs on a corporate machine 2025-01-04 16:11:35 +01:00
WerWolv
71f4f87288 impr: Make sure init tasks always get executed 2025-01-04 16:11:05 +01:00
WerWolv
48b202c56b patterns: Updated pattern language 2025-01-04 15:38:20 +01:00
Nik
d975019a7b impr: Revamp frame rate limiting system to make ImHex feel less laggy in certain cases (#2049) 2025-01-04 15:35:19 +01:00
Nik
6009b5013b feat: Let ImHex use the native menu bar on macOS (#2048) 2025-01-04 15:35:06 +01:00
WerWolv
24979d7fbd impr: Other Providers -> Other Data Sources 2025-01-04 14:06:03 +01:00
WerWolv
b4bf42e377 fix: Unit test build error due to changed Provider::getTypeName() signature 2025-01-04 13:57:48 +01:00
WerWolv
f94819351a impr: Make maximum in-memory file size setting easier to use. Bump value to 512MiB 2025-01-04 13:56:20 +01:00
WerWolv
8da69c11d9 impr: Remove the word "Provider" from places where it doesn't fit 2025-01-04 13:28:35 +01:00
WerWolv
635a825095 fix: Signed/Unsigned comparison error 2025-01-04 13:03:38 +01:00
WerWolv
bbffdbf56f feat: Allow #pragma magic to index from the end of the data with negative addresses
Closes #2047
2025-01-04 12:49:14 +01:00
WerWolv
1c30533d19 fix: Off-by-one when calculating hashes of selected regions
Fixes #2046
2025-01-04 00:15:35 +01:00
WerWolv
dcd80fe6ad impr: Properly scale window on wayland 2025-01-03 15:09:06 +01:00
WerWolv
525ab8d945 fix: Settings not being saved correctly anymore 2025-01-03 14:07:09 +01:00
WerWolv
d8fb3f526a fix: Shortcut migration not working correctly in some cases
Fixes #2045
2025-01-03 10:16:22 +01:00
WerWolv
a55df1d111 fix: Exception being thrown when custom disassembler folders didn't exist 2025-01-03 00:15:52 +01:00
WerWolv
2cf32ba38d fix: Default smooth font not being scaled correctly 2025-01-03 00:15:28 +01:00
AlexGuo1998
c82907153e fix: Set LZMA decompressor memory limit to 1GiB (#2044)
<!--
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 -->

See #2033 (`hex::dec::lzma_decompress` reports an error when
decompressing a small buffer).

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

Set the LZMA decompressor memory limit to 1GiB fixed. Print a warning
when exceeded, and abort with returning `false`.

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

Normal result when decompressing a small buffer


![image](https://github.com/user-attachments/assets/5b9e6b07-464e-41f6-bdc7-f5b1cd351069)

Warning message when `memlimit` is exceeded: (Set to 64B here for a
demo)
> W: lzma_decompress memory usage 1114168 bytes would exceed the limit
(64 bytes), aborting


![image](https://github.com/user-attachments/assets/04abf3ef-1d29-4846-bb41-214695c7d09c)

### Additional things
<!-- Anything else you would like to say -->

Is the warning wording OK? I'm not a native English speaker so please
change it if you want to.
2025-01-02 08:42:28 +00:00
WerWolv
165403da67 fix: ImHex freezing on AMD GPUs when resizing
Fixes #1842
2025-01-01 20:39:12 +01:00
WerWolv
0e4d94946e fix: Disable recent files on web build since they can't work there 2025-01-01 17:08:31 +01:00
WerWolv
9f9c5abf35 impr: Prevent window from being moved while hovering over items on macOS 2025-01-01 16:45:11 +01:00
WerWolv
6a3b10111f feat: Highlight main menu item when using a shortcut 2025-01-01 16:19:38 +01:00
WerWolv
0a55f4bf83 patterns: Updated pattern language
Fixes #2042
2025-01-01 11:36:04 +01:00
WerWolv
493d66d991 fix: Crash when using hex editor when provider == nullptr 2024-12-31 21:30:05 +01:00
WerWolv
268b495a29 fix: Make capstone use little endian by default 2024-12-31 21:17:19 +01:00
WerWolv
180f4926f8 impr: Make disassembly view contain data per-provider 2024-12-31 21:16:27 +01:00
WerWolv
c853349b78 impr: Force reset window decoration to expected value after exiting full screen mode 2024-12-31 21:04:09 +01:00
WerWolv
ee555e0da9 fix: Make sure WM_NCCALCSIZE never tries to sleep a negative amount of time
#1842
2024-12-31 18:06:31 +01:00
WerWolv
3dec4cc698 fix: Signed/Unsigned integer compare 2024-12-31 17:21:37 +01:00
WerWolv
d7b2b94cec impr: Reduce jittering when changing the number of hex columns 2024-12-31 17:04:32 +01:00
WerWolv
c9e88586aa feat: Added option to fit hex columns to screen width 2024-12-31 11:35:09 +01:00
WerWolv
1d641504b1 fix: Format string issues 2024-12-31 10:01:01 +01:00
WerWolv
655e068b9b impr: Added changed data information to diff view table 2024-12-31 00:47:32 +01:00
WerWolv
67a9f314cc impr: Added icons to more context menus 2024-12-31 00:45:47 +01:00
WerWolv
ff2b58e8a3 fix: Copy paste errors 2024-12-30 23:58:34 +01:00
WerWolv
a1482cb40e fix: Tooltips not being hidden when disabling hex editor highlights 2024-12-30 23:45:48 +01:00
WerWolv
89111059f9 feat: Added setting to disable hex editor highlights entirely 2024-12-30 23:24:59 +01:00
WerWolv
0ae823716a feat: Added a preview to the Edit -> Copy as options
Closes #2026
2024-12-30 23:16:11 +01:00
WerWolv
dab3f722e8 feat: Added "Jump to address" option to data inspector row context menu 2024-12-30 22:32:06 +01:00
WerWolv
0dc1af0747 feat: Added option to change radix of numbers in hex editor view 2024-12-30 21:00:43 +01:00
WerWolv
021206e052 impr: Added icons to pattern editor context menu 2024-12-30 12:18:55 +01:00
WerWolv
cb09cf3734 feat: Added context menu and next/previous buttons to the data inspector 2024-12-30 12:07:21 +01:00
WerWolv
f0525d6463 fix: Building issues with the web build 2024-12-30 10:10:38 +01:00
WerWolv
e22424ffa4 fix: Settings not being saved correctly on the web version 2024-12-29 23:53:23 +01:00
WerWolv
6e666c64e8 patterns: Updated pattern language 2024-12-29 22:42:32 +01:00
WerWolv
5f5f6ac539 feat: Added option to move selection back to hex editor footer
Closes #2024
2024-12-29 21:08:08 +01:00
WerWolv
3024c79f4f impr: Allow the favorite column in the pattern data view to be hidden 2024-12-29 20:38:51 +01:00
WerWolv
ba96d86dc2 impr: Properly align favorite icons inside of the buttons in the pattern drawer 2024-12-29 20:38:25 +01:00
WerWolv
40ec7195d1 patterns: Updated pattern language 2024-12-29 15:20:57 +01:00
WerWolv
f10dfa0c20 patterns: Updated pattern language 2024-12-29 14:40:51 +01:00
WerWolv
6a5473f6fe impr: Moved Windows DPI awareness to manifest file, added detached console allocation
Closes #1543
2024-12-28 23:47:42 +01:00
WerWolv
f79de6fbe8 fix: Web build not starting fully anymore 2024-12-28 22:48:06 +01:00
Nik
ec4ee3132b git: Added note about launching assertion failures when launching the AppImage (#2038) 2024-12-28 22:31:34 +01:00
WerWolv
1298f2b688 impr: Refactor previous commits to work with other environments too 2024-12-28 21:37:45 +01:00
WerWolv
534a2f1d28 impr: Apply framebuffer scaling to SVGs as well 2024-12-28 20:52:49 +01:00
WerWolv
c8e95cf3c3 impr: Keep default font at whole-integer sizes 2024-12-28 20:46:26 +01:00
WerWolv
c4918a963c fix: Default font not being scaled on macOS 2024-12-28 20:45:12 +01:00
WerWolv
bf6f738d2e impr: Make text look super pretty on macOS finally 2024-12-28 20:42:05 +01:00
Nik
1605904eb1 git: Updated more runners to Ubuntu 24.04 2024-12-28 16:49:33 +01:00
Nik
138517f116 git: Updated system requirements and compile info in the readme 2024-12-28 16:48:32 +01:00
WerWolv
d4a4cb2e80 fix: Crash when providing invalid version string to semantic version class
Fixes #2036
2024-12-28 15:59:13 +01:00
WerWolv
9a9dc328e3 build: Switch to custom lunasvg repo to allow offline builds 2024-12-28 13:39:07 +01:00
WerWolv
50eea0a4f1 impr: Replace Firacode with JetbrainsMono font 2024-12-28 12:43:34 +01:00
WerWolv
528a8b5b46 fix: Exception being thrown when getting version parts from invalid version 2024-12-28 11:45:05 +01:00
WerWolv
0db0bc53fa revert: Make pattern editor scroll bar look more like all other scrollbars 2024-12-28 00:39:10 +01:00
WerWolv
0297c267e9 impr: Display "ImHex" in title bar when null provider is open 2024-12-27 23:56:14 +01:00
WerWolv
5af85f24f6 impr: Allow command palette to be closed by clicking on the menu bar 2024-12-27 23:53:55 +01:00
WerWolv
5110a7578e fix: Rendering issues with text editor in bookmark view 2024-12-27 23:36:21 +01:00
WerWolv
5af28670f0 fix: Ctrl sometimes getting stuck when pressing ALT GR and other keys at the same time
#2019
2024-12-27 23:15:20 +01:00
WerWolv
efa2b781dd impr: Better create hash popup size 2024-12-27 23:14:39 +01:00
WerWolv
979f151181 fix: Don't show library plugins in --plugins subcommand 2024-12-27 20:06:17 +01:00
WerWolv
6f125f18c3 impr: Make pattern editor scroll bar look more like all other scrollbars 2024-12-27 20:01:00 +01:00
WerWolv
edba7051f0 impr: Make interactive tutorials select windows when they're highlighted 2024-12-27 19:41:45 +01:00
WerWolv
fa1ae8d746 fix: Tutorial highlights not working anymore correctly 2024-12-27 18:28:22 +01:00
WerWolv
a476617432 build: Fix remaining build issues 2024-12-27 00:02:37 +01:00
WerWolv
ffac13bfef disasm: Updated disassembler library 2024-12-26 23:28:38 +01:00
WerWolv
f877bf21ba fix: Warning on macOS about wrong format argument 2024-12-26 23:01:19 +01:00
WerWolv
4bc4882b1f disasm: Updated disassembler library 2024-12-26 23:00:59 +01:00
WerWolv
084c17dc26 fix: Missing endian setting in ARM64 disassembler 2024-12-26 22:39:57 +01:00
WerWolv
26c39d6822 fix: ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback -> ImGui_ImplGlfw_InstallEmscriptenCallbacks 2024-12-26 20:19:55 +01:00
WerWolv
aefc173227 fix: Wrong --reset-settings subcommand description 2024-12-26 20:05:07 +01:00
WerWolv
bf44a1cce6 feat: Added initial support for custom disassemblers 2024-12-26 20:04:45 +01:00
WerWolv
a76c6c653d impr: Refactor disassembler system to make it more modular 2024-12-26 18:41:34 +01:00
WerWolv
f11205bba7 build: Updated more dependencies 2024-12-26 14:41:43 +01:00
WerWolv
72d9c5019c build: Updated dependencies 2024-12-26 14:30:52 +01:00
WerWolv
58d66e3e97 fix: Added migration routine to fix shortcuts 2024-12-26 14:01:54 +01:00
WerWolv
43c88a2fab feat: Added system to handle version migrations 2024-12-26 14:01:46 +01:00
paxcut
9ce64ec6e1 fix: Pattern Editor console scroll jumping. (#2029)
Some issues related to the padding added to scroll past the end for
console that has padding added.
Added a shortcut to scroll editors one pixel at a time.
Fixed whole lines always drawn at the top even if scroll value is chosen
so that only a portion of the top line is visible. This caused errors in
horizontal scrolling.
Fixed Ctrl-F Ctrl-G and Ctrl-H messing the editor display. 
Fixed the end of the line could not be clicked with mouse 
Fixed line numbers and their lines could be displayed at different
heights.
Made numbers that represented lines floats instead of integers to allow
partial line display.
2024-12-25 18:51:58 +01:00
WerWolv
c749d6a7dc fix: Disable ImGui assert that causes random crashes on resize 2024-12-25 18:49:50 +01:00
WerWolv
f3e6d35c98 build: Updated ImGui glfw backend 2024-12-25 18:44:43 +01:00
WerWolv
0be539b8a5 feat: Added option to copy data as escaped string
#2026
2024-12-25 16:45:34 +01:00
WerWolv
0454a369e5 fix: Crashes when disassembling data
Fixes #2025
2024-12-25 16:36:53 +01:00
WerWolv
010025cbfa fix: Wrong localStorage key for achievements 2024-12-25 16:21:38 +01:00
WerWolv
61cae0a9f8 fix: Missing emscripten include 2024-12-25 16:19:50 +01:00
WerWolv
9e83d9e68c fix: Disable browser ctrl + S in web build 2024-12-25 16:17:51 +01:00
WerWolv
248acd5e26 fix: Properly save achievements in web version 2024-12-25 16:17:33 +01:00
WerWolv
42c1f5601a fix: Saving files in web version not working correctly 2024-12-25 15:57:54 +01:00
WerWolv
9c1a673047 impr: Force update all installed content store items after an update 2024-12-25 14:29:41 +01:00
WerWolv
99b90f90ac fix: Unused variable in wasm build 2024-12-25 13:03:55 +01:00
WerWolv
6ead8d8b49 fix: Certain shortcuts not being captured by ImHex Web 2024-12-25 12:36:06 +01:00
WerWolv
9b12232e9f revert: Broken fix for cursor not being set at end of line 2024-12-25 01:41:50 +01:00
WerWolv
c1ed1baaad fix: Shortcuts not working correctly in Web build 2024-12-25 01:34:11 +01:00
WerWolv
ab34312089 fix: Clicking past end of line in text editor putting cursor before last character 2024-12-25 01:33:41 +01:00
WerWolv
a25d92fbb7 build: Bumped version to 1.37.0.WIP 2024-12-25 01:33:36 +01:00
383 changed files with 16116 additions and 5882 deletions

View File

@@ -6,6 +6,7 @@ on:
- 'master'
- 'releases/**'
- 'tests/**'
- 'feature/**'
pull_request:
workflow_dispatch:
@@ -18,11 +19,18 @@ jobs:
win:
runs-on: windows-2022
name: 🪟 Windows MINGW64
defaults:
run:
shell: msys2 {0}
env:
CCACHE_DIR: "${{ github.workspace }}/.ccache"
permissions:
id-token: write
attestations: write
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
@@ -81,11 +89,62 @@ jobs:
run: |
cd build
ninja install
- name: 🪲 Create PDBs for MSI
run: |
cd build
mkdir cv2pdb
cd cv2pdb
wget https://github.com/rainers/cv2pdb/releases/download/v0.52/cv2pdb-0.52.zip
unzip cv2pdb-0.52.zip
cd ..
cv2pdb/cv2pdb.exe imhex.exe
cv2pdb/cv2pdb.exe imhex-gui.exe
cv2pdb/cv2pdb.exe libimhex.dll
for plugin in plugins/*.hexplug; do
cv2pdb/cv2pdb.exe $plugin
done
rm -rf cv2pdb
- name: 📦 Bundle MSI
run: |
cd build
cpack
mv ImHex-*.msi ../imhex-${{ env.IMHEX_VERSION }}-Windows-x86_64.msi
echo "ImHex checks for the existence of this file to determine if it is running in portable mode. You should not delete this file" > $PWD/install/PORTABLE
- name: 🪲 Create PDBs for ZIP
run: |
cd build/install
mkdir cv2pdb
cd cv2pdb
wget https://github.com/rainers/cv2pdb/releases/download/v0.52/cv2pdb-0.52.zip
unzip cv2pdb-0.52.zip
cd ..
cv2pdb/cv2pdb.exe imhex.exe
cv2pdb/cv2pdb.exe imhex-gui.exe
cv2pdb/cv2pdb.exe libimhex.dll
for plugin in plugins/*.hexplug; do
cv2pdb/cv2pdb.exe $plugin
done
rm -rf cv2pdb
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
if: github.event.pull_request.head.repo.full_name == github.repository
with:
subject-path: |
imhex-*.msi
- name: ⬆️ Upload Windows Installer
uses: actions/upload-artifact@v4
with:
@@ -122,12 +181,16 @@ jobs:
win-plugin-template-test:
runs-on: windows-2022
name: 🧪 Plugin Template Test
defaults:
run:
shell: msys2 {0}
needs: win
env:
IMHEX_SDK_PATH: "${{ github.workspace }}/out/sdk"
steps:
- name: 🧰 Checkout ImHex
uses: actions/checkout@v4
@@ -173,9 +236,13 @@ jobs:
ninja
# MacOS build
macos:
macos-x86:
runs-on: macos-13
permissions:
id-token: write
attestations: write
strategy:
fail-fast: false
matrix:
@@ -205,10 +272,13 @@ jobs:
max-size: 1G
- name: ⬇️ Install dependencies
env:
# Make brew not display useless errors
HOMEBREW_TESTS: 1
run: |
brew reinstall python --quiet || true
brew link --overwrite --quiet python || true
brew bundle --no-lock --quiet --file dist/Brewfile || true
brew link --overwrite --quiet python 2>/dev/null || true
brew bundle --no-lock --quiet --file dist/macOS/Brewfile || true
rm -rf /usr/local/Cellar/capstone
- name: ⬇️ Install classic glfw
@@ -299,19 +369,25 @@ jobs:
- name: 📦 Create DMG
run: |
set -x
mkdir bundle
mv build/install/ImHex.app bundle
cd bundle
ln -s /Applications Applications
cd ..
brew install imagemagick
git clone https://github.com/sindresorhus/create-dmg
cd create-dmg
npm i && npm -g i
cd ../build/install
for i in $(seq 1 10); do
if hdiutil create -volname "ImHex" -srcfolder bundle -ov -format UDZO imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.suffix }}-x86_64.dmg; then
echo "Created dmg after ${i} attempts"
break
fi
sleep 10
create-dmg ImHex.app || true
if ls -d *.dmg 1>/dev/null 2>/dev/null; then
break;
fi
done
mv *.dmg ../../imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.suffix }}-x86_64.dmg
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
if: github.event.pull_request.head.repo.full_name == github.repository
with:
subject-path: |
./*.dmg
- name: ⬆️ Upload DMG
uses: actions/upload-artifact@v4
@@ -320,11 +396,13 @@ jobs:
name: macOS DMG${{ matrix.suffix }} x86_64
path: ./*.dmg
macos-arm64-build:
macos-arm64:
runs-on: ubuntu-24.04
name: 🍎 macOS 13 arm64
outputs:
IMHEX_VERSION: ${{ steps.build.outputs.IMHEX_VERSION }}
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
@@ -367,9 +445,15 @@ jobs:
macos-arm64-package:
runs-on: macos-13
name: 🍎 macOS 13 arm64 Packaging
needs: macos-arm64-build
needs: macos-arm64
env:
IMHEX_VERSION: ${{ needs.macos-arm64-build.outputs.IMHEX_VERSION }}
permissions:
id-token: write
attestations: write
steps:
- name: ⬇️ Download artifact
uses: actions/download-artifact@v4
@@ -404,19 +488,25 @@ jobs:
- name: 📦 Create DMG
run: |
set -x
mkdir bundle
mv out/ImHex.app bundle
cd bundle
ln -s /Applications Applications
cd ..
brew install imagemagick
git clone https://github.com/sindresorhus/create-dmg
cd create-dmg
npm i && npm -g i
cd ../out
for i in $(seq 1 10); do
if hdiutil create -volname "ImHex" -srcfolder bundle -ov -format UDZO imhex-${{ env.IMHEX_VERSION }}-macOS-arm64.dmg; then
echo "Created dmg after ${i} attempts"
break
fi
sleep 10
create-dmg ImHex.app || true
if ls -d *.dmg 1>/dev/null 2>/dev/null; then
break;
fi
done
mv *.dmg ../imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.suffix }}-arm64.dmg
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
if: github.event.pull_request.head.repo.full_name == github.repository
with:
subject-path: |
./*.dmg
- name: ⬆️ Upload DMG
uses: actions/upload-artifact@v4
@@ -441,6 +531,10 @@ jobs:
image: "ubuntu:${{ matrix.release_num }}"
options: --privileged
permissions:
id-token: write
attestations: write
steps:
- name: ⬇️ Install setup dependencies
run: apt update && apt install -y git curl
@@ -498,9 +592,16 @@ jobs:
- name: 📦 Bundle DEB
run: |
cp -r build/DEBIAN build/DebDir
dpkg-deb -Zgzip --build build/DebDir
dpkg-deb -Zzstd --build build/DebDir
mv build/DebDir.deb imhex-${{ env.IMHEX_VERSION }}-Ubuntu-${{ matrix.release_num }}-x86_64.deb
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
if: github.event.pull_request.head.repo.full_name == github.repository
with:
subject-path: |
./*.deb
- name: ⬆️ Upload DEB
uses: actions/upload-artifact@v4
with:
@@ -510,8 +611,26 @@ jobs:
# AppImage build
appimage:
runs-on: ubuntu-24.04
name: ⬇️ AppImage
strategy:
fail-fast: false
matrix:
include:
- architecture: "x86_64"
architecture_package: "amd64"
architecture_appimage_builder: "x86_64"
image: ubuntu-24.04
- architecture: "arm64"
architecture_package: "arm64"
architecture_appimage_builder: "aarch64"
image: ubuntu-24.04-arm
runs-on: ${{ matrix.image }}
name: ⬇️ AppImage ${{ matrix.architecture }}
permissions:
id-token: write
attestations: write
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
@@ -533,22 +652,31 @@ jobs:
- name: 🛠️ Build using docker
run: |
docker buildx build . -f dist/appimage/Dockerfile --progress=plain --build-arg "BUILD_TYPE=$BUILD_TYPE" \
--build-arg "GIT_COMMIT_HASH=$GITHUB_SHA" --build-arg "GIT_BRANCH=${GITHUB_REF##*/}" --output out
docker buildx build . -f dist/AppImage/Dockerfile --progress=plain --build-arg "BUILD_TYPE=$BUILD_TYPE" \
--build-arg "GIT_COMMIT_HASH=$GITHUB_SHA" --build-arg "GIT_BRANCH=${GITHUB_REF##*/}" \
--build-arg "ARCHITECTURE_PACKAGE=${{ matrix.architecture_package }}" --build-arg "ARCHITECTURE_FILE_NAME=${{ matrix.architecture }}" --build-arg "ARCHITECTURE_APPIMAGE_BUILDER=${{ matrix.architecture_appimage_builder }}" \
--output out
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
if: github.event.pull_request.head.repo.full_name == github.repository
with:
subject-path: |
out/*.AppImage
out/*.AppImage.zsync
- name: ⬆️ Upload AppImage
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: Linux AppImage x86_64
name: Linux AppImage ${{ matrix.architecture }}
path: 'out/*.AppImage'
- name: ⬆️ Upload AppImage zsync
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: Linux AppImage zsync x86_64
name: Linux AppImage zsync ${{ matrix.architecture }}
path: 'out/*.AppImage.zsync'
# ArchLinux build
@@ -559,6 +687,10 @@ jobs:
container:
image: archlinux:base-devel
permissions:
id-token: write
attestations: write
steps:
- name: ⬇️ Update all packages
run: |
@@ -642,6 +774,13 @@ jobs:
rm *imhex-bin-debug* # rm debug package which is created for some reason
mv *.pkg.tar.zst imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
if: github.event.pull_request.head.repo.full_name == github.repository
with:
subject-path: |
build/imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst
- name: ⬆️ Upload imhex-archlinux.pkg.tar.zst
uses: actions/upload-artifact@v4
with:
@@ -680,6 +819,10 @@ jobs:
image: "almalinux:9"
options: --privileged --pid=host --security-opt apparmor=unconfined
permissions:
id-token: write
attestations: write
steps:
# This, together with the `--pid=host --security-opt apparmor=unconfined` docker options is required to allow
# fedpkg to work inside a Docker container running on Ubuntu again.
@@ -775,6 +918,13 @@ jobs:
mv $GITHUB_WORKSPACE/results_imhex/${{ env.IMHEX_VERSION }}/*/imhex-${{ env.IMHEX_VERSION }}-0.*.x86_64.rpm \
$GITHUB_WORKSPACE/imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.rpm
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
if: github.event.pull_request.head.repo.full_name == github.repository
with:
subject-path: |
imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.rpm
- name: ⬆️ Upload RPM
uses: actions/upload-artifact@v4
with:
@@ -782,3 +932,85 @@ jobs:
name: ${{ matrix.name }} ${{ matrix.release_num }} RPM x86_64
path: |
imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.rpm
webassembly-build:
runs-on: ubuntu-24.04
name: 🌍 Web
permissions:
pages: write
id-token: write
actions: write
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: 📁 Restore docker /cache
uses: actions/cache@v4
with:
path: cache
key: web-cache-${{ hashFiles('**/CMakeLists.txt') }}
- name: 🐳 Inject /cache into docker
uses: reproducible-containers/buildkit-cache-dance@v2
with:
cache-source: cache
cache-target: /cache
- name: 🛠️ Build using docker
run: |
docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out --target raw
- name: 🔨 Fix permissions
run: |
chmod -c -R +rX "out/"
- name: ⬆️ Upload artifacts
uses: actions/upload-pages-artifact@v3
with:
path: out/
- name: 🔨 Copy necessary files
run: |
cp dist/web/serve.py out/start_imhex_web.py
- name: ⬆️ Upload package
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: ImHex Web
path: out/*
# See https://github.com/actions/cache/issues/342#issuecomment-1711054115
- name: 🗑️ Delete old cache
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
gh extension install actions/gh-actions-cache || true
gh actions-cache delete "build-web-cache" --confirm || true
webassembly-deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
permissions:
pages: write
id-token: write
actions: write
name: 📃 Deploy to GitHub Pages
runs-on: ubuntu-24.04
if: ${{ github.ref == 'refs/heads/master' && github.event.repository.fork == false }}
needs: webassembly-build
steps:
- name: 🌍 Deploy WebAssembly Build to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
- name: 🗑️ Delete artifact
uses: geekyeggo/delete-artifact@v5
with:
name: github-pages

View File

@@ -1,79 +0,0 @@
name: Build for the web
on:
push:
branches:
- 'master'
- 'releases/**'
- 'tests/**'
pull_request:
workflow_dispatch:
env:
BUILD_TYPE: Release
permissions:
pages: write
id-token: write
actions: write
jobs:
build:
runs-on: ubuntu-24.04
name: 🌍 WebAssembly
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: 📁 Restore docker /cache
uses: actions/cache@v4
with:
path: cache
key: web-cache-${{ hashFiles('**/CMakeLists.txt') }}
- name: 🐳 Inject /cache into docker
uses: reproducible-containers/buildkit-cache-dance@v2
with:
cache-source: cache
cache-target: /cache
- name: 🛠️ Build using docker
run: |
docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out --target raw
- name: 🔨 Fix permissions
run: |
chmod -c -R +rX "out/"
- name: ⬆️ Upload artifacts
uses: actions/upload-pages-artifact@v3
with:
path: out/
# See https://github.com/actions/cache/issues/342#issuecomment-1711054115
- name: 🗑️ Delete old cache
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
gh extension install actions/gh-actions-cache || true
gh actions-cache delete "build-web-cache" --confirm || true
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
name: 📃 Deploy to GitHub Pages
runs-on: ubuntu-24.04
if: ${{ github.ref == 'refs/heads/master' && github.event.repository.fork == false }}
needs: build
steps:
- name: 🌍 Deploy
id: deployment
uses: actions/deploy-pages@v4

View File

@@ -63,7 +63,7 @@ jobs:
token: ${{ secrets.RELEASE_TOKEN }}
release-upload-artifacts:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
name: Release Upload Artifacts
steps:
@@ -117,6 +117,7 @@ jobs:
run: |
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.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
- name: ⬆️ Upload everything to release
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981

View File

@@ -6,7 +6,7 @@ on:
jobs:
close-issues:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
permissions:
issues: write
pull-requests: write

View File

@@ -6,6 +6,7 @@ on:
- 'master'
- 'releases/**'
- 'tests/**'
- 'feature/**'
pull_request:
branches:
- 'master'

2
.gitignore vendored
View File

@@ -14,3 +14,5 @@ imgui.ini
.DS_Store
CMakeUserPresets.json
Brewfile.lock.json
.vs/

5
.gitmodules vendored
View File

@@ -43,4 +43,7 @@
[submodule "lib/third_party/HashLibPlus"]
path = lib/third_party/HashLibPlus
url = https://github.com/WerWolv/HashLibPlus
url = https://github.com/WerWolv/HashLibPlus
[submodule "lib/external/disassembler"]
path = lib/external/disassembler
url = https://github.com/WerWolv/Disassembler

View File

@@ -81,7 +81,6 @@ if (IMHEX_ENABLE_UNIT_TESTS)
endif ()
# Configure more resources that will be added to the install package
generatePDBs()
generateSDKDirectory()
# Handle package generation

View File

@@ -45,6 +45,19 @@
"IMHEX_IDE_HELPERS_OVERRIDE_XCODE_COMPILER": "ON"
}
},
{
"name": "vs2022",
"displayName": "Visual Studio 2022",
"generator": "Visual Studio 17 2022",
"binaryDir": "${sourceDir}/build/${presetName}",
"architecture": {
"strategy": "set",
"value": "x64"
},
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
}
}
],
"buildPresets": [

View File

@@ -27,6 +27,11 @@ chmod +x imhex-*.AppImage
./imhex-*.AppImage
```
If you're experiencing glib / libgtk assertion failures, you might need to setup your `XDG_DATA_DIRS` env var correctly. In this case, run the following command before executing the AppImage. (See issue [ImHex/#2038](https://github.com/WerWolv/ImHex/issues/2038))
```bash
export XDG_DATA_DIRS="/usr/local/share:/usr/share"
```
#### Flatpak
To install the Flatpak, make sure you have the Flathub repository added to your system. Then simply run the following command:

View File

@@ -38,8 +38,8 @@ If you like my work, please consider supporting me on GitHub Sponsors, Patreon o
</p>
## Screenshots
![Hex editor, patterns and data information](https://github.com/WerWolv/ImHex/assets/10835354/4f358238-2d27-41aa-9015-a2c6cc3708cf)
![Bookmarks, disassembler and data processor](https://github.com/WerWolv/ImHex/assets/10835354/183bc2cc-2439-4ded-b4c5-b140e19fc92f)
![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)
<details>
<summary><strong>More Screenshots</strong></summary>
@@ -328,12 +328,12 @@ To use ImHex, the following minimal system requirements need to be met.
- RHEL/AlmaLinux
- Arch Linux
- Basically any other distro will work as well when compiling ImHex from sources.
- **CPU**: x86_64 (64 Bit)
- **CPU**: Officially supported are x86_64 and ARM64, though any Little Endian 64 bit CPU should work.
- **GPU**: OpenGL 3.0 or higher
- Integrated Intel HD iGPUs are supported, however certain drivers are known to cause various graphical artifacts, especially on Windows. Use at your own risk.
- In case you don't have a GPU available, there are software rendered releases available for Windows and macOS
- **RAM**: 256MB, more may be required for more complicated analysis
- **Storage**: 150MB
- **RAM**: ~150MiB, more is required for more complex analysis
- **Storage**: 150MiB
## Installing
@@ -342,8 +342,10 @@ Information on how to install ImHex can be found in the [Install](/INSTALL.md) g
## Compiling
To compile ImHex on any platform, GCC (or Clang) is required with a version that supports C++23 or higher.
On macOS, Clang is also required to compile some ObjC code.
All releases are being built using latest available GCC.
Windows and Linux releases are being built using latest available GCC.
MacOS releases are being built using latest available LLVM Clang.
Important to note is, the MSVC and AppleClang compilers are both **NOT** supported since they're both generally severely outdated and lack features GCC and LLVM Clang have.
> [!NOTE]
> Many dependencies are bundled into the repository using submodules so make sure to clone it using the `--recurse-submodules` option.

View File

@@ -1 +1 @@
1.36.0
1.37.0.WIP

View File

@@ -1,3 +1,73 @@
# Some libraries we use set the BUILD_SHARED_LIBS variable to ON, which causes CMake to
# display a warning about options being set using set() instead of option().
# Explicitly set the policy to NEW to suppress the warning.
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW)
if (POLICY CMP0177)
set(CMAKE_POLICY_DEFAULT_CMP0177 OLD)
cmake_policy(SET CMP0177 OLD)
endif()
function(getTarget target type)
get_target_property(IMPORTED_TARGET ${target} IMPORTED)
if (IMPORTED_TARGET)
set(${type} INTERFACE PARENT_SCOPE)
else()
set(${type} PRIVATE PARENT_SCOPE)
endif()
endfunction()
function(addCFlag)
if (ARGC EQUAL 1)
add_compile_options($<$<COMPILE_LANGUAGE:C>:${ARGV0}>)
elseif (ARGC EQUAL 2)
getTarget(${ARGV1} TYPE)
target_compile_options(${ARGV1} ${TYPE} $<$<COMPILE_LANGUAGE:C>:${ARGV0}>)
endif()
endfunction()
function(addCXXFlag)
if (ARGC EQUAL 1)
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:${ARGV0}>)
elseif (ARGC EQUAL 2)
getTarget(${ARGV1} TYPE)
target_compile_options(${ARGV1} ${TYPE} $<$<COMPILE_LANGUAGE:CXX>:${ARGV0}>)
endif()
endfunction()
function(addObjCFlag)
if (ARGC EQUAL 1)
add_compile_options($<$<COMPILE_LANGUAGE:OBJC>:${ARGV0}>)
elseif (ARGC EQUAL 2)
getTarget(${ARGV1} TYPE)
target_compile_options(${ARGV1} ${TYPE} $<$<COMPILE_LANGUAGE:OBJC>:${ARGV0}>)
endif()
endfunction()
function(addLinkerFlag)
if (ARGC EQUAL 1)
add_link_options(${ARGV0})
elseif (ARGC EQUAL 2)
getTarget(${ARGV1} TYPE)
target_link_options(${ARGV1} ${TYPE} ${ARGV0})
endif()
endfunction()
function(addCCXXFlag)
addCFlag(${ARGV0} ${ARGV1})
addCXXFlag(${ARGV0} ${ARGV1})
endfunction()
function(addCommonFlag)
addCFlag(${ARGV0} ${ARGV1})
addCXXFlag(${ARGV0} ${ARGV1})
addObjCFlag(${ARGV0} ${ARGV1})
endfunction()
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Disable deprecated warnings" FORCE)
include(FetchContent)
if(IMHEX_STRIP_RELEASE)
@@ -59,7 +129,9 @@ macro(detectOS)
set(CMAKE_INSTALL_LIBDIR ".")
set(PLUGINS_INSTALL_LOCATION "plugins")
add_compile_definitions(WIN32_LEAN_AND_MEAN)
add_compile_definitions(NOMINMAX)
add_compile_definitions(UNICODE)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
elseif (APPLE)
add_compile_definitions(OS_MACOS)
set(CMAKE_INSTALL_BINDIR ".")
@@ -110,7 +182,7 @@ macro(configurePackingResources)
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")
set(CPACK_WIX_CULTURES "en-US;de-DE;ja-JP;it-IT;pt-BR;zh-CN;zh-TW;ru-RU")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "ImHex")
set_property(INSTALL "$<TARGET_FILE_NAME:main>"
PROPERTY CPACK_START_MENU_SHORTCUTS "ImHex"
@@ -226,7 +298,7 @@ macro(createPackage)
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.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.png)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.svg DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.svg)
downloadImHexPatternsFiles("./share/imhex")
# install AppStream file
@@ -343,9 +415,9 @@ macro(configureCMake)
if (LD_LLD_PATH)
set(CMAKE_LINKER ${LD_LLD_PATH})
if (NOT XCODE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=lld")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=lld")
if (NOT XCODE AND NOT MSVC)
set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} -fuse-ld=lld)
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -fuse-ld=lld)
endif()
else ()
message(WARNING "lld not found, using default linker!")
@@ -370,15 +442,6 @@ macro(configureCMake)
message(WARNING "LTO is not supported: ${output_error}")
endif ()
endif ()
# Some libraries we use set the BUILD_SHARED_LIBS variable to ON, which causes CMake to
# display a warning about options being set using set() instead of option().
# Explicitly set the policy to NEW to suppress the warning.
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW)
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Disable deprecated warnings" FORCE)
endmacro()
function(configureProject)
@@ -434,6 +497,8 @@ function(verifyCompiler)
message(FATAL_ERROR "ImHex requires GCC 12.0.0 or newer. Please use the latest GCC version.")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "17.0.0")
message(FATAL_ERROR "ImHex requires Clang 17.0.0 or newer. Please use the latest Clang version.")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
elseif (NOT (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
message(FATAL_ERROR "ImHex can only be compiled with GCC or Clang. ${CMAKE_CXX_COMPILER_ID} is not supported.")
endif()
@@ -501,16 +566,16 @@ function(downloadImHexPatternsFiles dest)
# Maybe patterns are cloned to a subdirectory
if (NOT EXISTS ${imhex_patterns_SOURCE_DIR})
set(imhex_patterns_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ImHex-Patterns")
set(imhex_patterns_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ImHex-Patterns")
endif()
# Or a sibling directory
if (NOT EXISTS ${imhex_patterns_SOURCE_DIR})
set(imhex_patterns_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../ImHex-Patterns")
set(imhex_patterns_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../ImHex-Patterns")
endif()
endif ()
if (NOT EXISTS ${imhex_patterns_SOURCE_DIR})
if (NOT EXISTS ${imhex_patterns_SOURCE_DIR})
message(WARNING "Failed to locate ImHex-Patterns repository, some resources will be missing during install!")
elseif(XCODE)
# The Xcode build has multiple configurations, which each need a copy of these files
@@ -553,34 +618,49 @@ macro(setupDebugCompressionFlag)
elseif (COMPRESS_AVAILABLE_COMPILER AND COMPRESS_AVAILABLE_LINKER)
message("Using default compression for debug info because both compiler and linker support it")
set(DEBUG_COMPRESSION_FLAG "-gz" CACHE STRING "Cache to use for debug info compression")
else()
set(DEBUG_COMPRESSION_FLAG "" CACHE STRING "Cache to use for debug info compression")
endif()
endif()
set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} ${DEBUG_COMPRESSION_FLAG}")
addCommonFlag(${DEBUG_COMPRESSION_FLAG})
endmacro()
macro(setupCompilerFlags target)
# IMHEX_COMMON_FLAGS: flags common for C, C++, Objective C, etc.. compilers
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
if (IMHEX_STRICT_WARNINGS)
addCommonFlag("/W4" ${target})
addCommonFlag("/wd4242" ${target})
addCommonFlag("/wd4244" ${target})
addCommonFlag("/wd4267" ${target})
addCommonFlag("/wd4996" ${target})
addCommonFlag("/wd4127" ${target})
endif()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
# Define strict compilation flags
if (IMHEX_STRICT_WARNINGS)
set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} -Wall -Wextra -Wpedantic -Werror")
addCommonFlag("-Wall" ${target})
addCommonFlag("-Wextra" ${target})
addCommonFlag("-Wpedantic" ${target})
addCommonFlag("-Werror" ${target})
endif()
if (UNIX AND NOT APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} -rdynamic")
addCommonFlag("-rdynamic" ${target})
endif()
set(IMHEX_CXX_FLAGS "-fexceptions -frtti")
addCXXFlag("-fexceptions" ${target})
addCXXFlag("-frtti" ${target})
# Disable some warnings
set(IMHEX_C_CXX_FLAGS "-Wno-array-bounds -Wno-deprecated-declarations -Wno-unknown-pragmas")
addCCXXFlag("-Wno-array-bounds" ${target})
addCCXXFlag("-Wno-deprecated-declarations" ${target})
addCCXXFlag("-Wno-unknown-pragmas" ${target})
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if (IMHEX_ENABLE_UNITY_BUILD AND WIN32)
set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} -Wa,-mbig-obj")
if (WIN32)
addLinkerFlag("-Wa,mbig-obj" ${target})
endif ()
endif()
@@ -588,36 +668,45 @@ macro(setupCompilerFlags target)
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++")
set(IMHEX_C_CXX_FLAGS "-Wno-unknown-warning-option")
addCCXXFlag("-Wno-unknown-warning-option" ${target})
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
addCommonFlag("/bigobj" ${target})
addCFlag("/std:clatest" ${target})
addCXXFlag("/std:c++latest" ${target})
endif()
# Disable some warnings for gcc
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(IMHEX_C_CXX_FLAGS "${IMHEX_C_CXX_FLAGS} -Wno-restrict -Wno-stringop-overread -Wno-stringop-overflow -Wno-dangling-reference")
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
addCCXXFlag("-Wno-restrict" ${target})
addCCXXFlag("-Wno-stringop-overread" ${target})
addCCXXFlag("-Wno-stringop-overflow" ${target})
addCCXXFlag("-Wno-dangling-reference" ${target})
endif()
# Define emscripten-specific disabled warnings
if (EMSCRIPTEN)
set(IMHEX_C_CXX_FLAGS "${IMHEX_C_CXX_FLAGS} -pthread -Wno-dollar-in-identifier-extension -Wno-pthreads-mem-growth")
addCCXXFlag("-pthread" ${target})
addCCXXFlag("-Wno-dollar-in-identifier-extension" ${target})
addCCXXFlag("-Wno-pthreads-mem-growth" ${target})
endif ()
if (IMHEX_COMPRESS_DEBUG_INFO)
setupDebugCompressionFlag()
endif()
# Set actual CMake flags
set_target_properties(${target} PROPERTIES COMPILE_FLAGS "${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS} ${IMHEX_CXX_FLAGS}")
set(CMAKE_OBJC_FLAGS "${CMAKE_OBJC_FLAGS} ${IMHEX_COMMON_FLAGS}")
# Only generate minimal debug information for stacktraces in RelWithDebInfo builds
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -g1")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g1")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# Add flags for debug info in inline functions
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -gstatement-frontiers -ginline-points")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -gstatement-frontiers -ginline-points")
if (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
addCCXXFlag("-g1" ${target})
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# Add flags for debug info in inline functions
addCCXXFlag("-gstatement-frontiers" ${target})
addCCXXFlag("-ginline-points" ${target})
endif()
endif()
endmacro()
@@ -649,6 +738,7 @@ macro(addBundledLibraries)
set(FPHSA_NAME_MISMATCHED ON CACHE BOOL "")
if(NOT USE_SYSTEM_FMT)
set(FMT_INSTALL OFF CACHE BOOL "Disable install targets for libfmt" FORCE)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/fmt EXCLUDE_FROM_ALL)
set(FMT_LIBRARIES fmt::fmt-header-only)
else()
@@ -721,13 +811,10 @@ macro(addBundledLibraries)
set(LIBPL_BUILD_CLI_AS_EXECUTABLE OFF CACHE BOOL "" FORCE)
set(LIBPL_ENABLE_PRECOMPILED_HEADERS ${IMHEX_ENABLE_PRECOMPILED_HEADERS} CACHE BOOL "" FORCE)
if (WIN32)
set(LIBPL_SHARED_LIBRARY ON CACHE BOOL "" FORCE)
else()
set(LIBPL_SHARED_LIBRARY OFF CACHE BOOL "" FORCE)
endif()
set(LIBPL_SHARED_LIBRARY OFF CACHE BOOL "" FORCE)
add_subdirectory(${EXTERNAL_LIBS_FOLDER}/pattern_language EXCLUDE_FROM_ALL)
add_subdirectory(${EXTERNAL_LIBS_FOLDER}/disassembler EXCLUDE_FROM_ALL)
if (LIBPL_SHARED_LIBRARY)
install(
@@ -784,70 +871,20 @@ function(enableUnityBuild TARGET)
endif ()
endfunction()
function(generatePDBs)
if (NOT IMHEX_GENERATE_PDBS)
return()
endif ()
if (NOT WIN32 OR CMAKE_BUILD_TYPE STREQUAL "Debug")
return()
endif ()
include(FetchContent)
FetchContent_Declare(
cv2pdb
URL "https://github.com/rainers/cv2pdb/releases/download/v0.52/cv2pdb-0.52.zip"
DOWNLOAD_EXTRACT_TIMESTAMP ON
)
FetchContent_Populate(cv2pdb)
set(PDBS_TO_GENERATE main main-forwarder libimhex ${PLUGINS})
foreach (PDB ${PDBS_TO_GENERATE})
if (PDB STREQUAL "main")
set(GENERATED_PDB imhex)
elseif (PDB STREQUAL "main-forwarder")
set(GENERATED_PDB imhex-gui)
elseif (PDB STREQUAL "libimhex")
set(GENERATED_PDB libimhex)
else ()
set(GENERATED_PDB plugins/${PDB})
endif ()
if (IMHEX_REPLACE_DWARF_WITH_PDB)
set(PDB_OUTPUT_PATH ${CMAKE_BINARY_DIR}/${GENERATED_PDB})
else ()
set(PDB_OUTPUT_PATH)
endif()
add_custom_target(${PDB}_pdb DEPENDS ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb)
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMAND
(
${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb &&
${cv2pdb_SOURCE_DIR}/cv2pdb64.exe $<TARGET_FILE:${PDB}> ${PDB_OUTPUT_PATH} &&
${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/${GENERATED_PDB}
) || (exit 0)
COMMAND_EXPAND_LISTS)
install(FILES ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb DESTINATION ".")
add_dependencies(imhex_all ${PDB}_pdb)
endforeach ()
function(setSDKPaths)
if (WIN32)
set(SDK_PATH "./sdk" PARENT_SCOPE)
elseif (APPLE)
set(SDK_PATH "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Resources/sdk" PARENT_SCOPE)
else()
set(SDK_PATH "share/imhex/sdk" PARENT_SCOPE)
endif()
set(SDK_BUILD_PATH "${CMAKE_BINARY_DIR}/sdk" PARENT_SCOPE)
endfunction()
function(generateSDKDirectory)
if (WIN32)
set(SDK_PATH "./sdk")
elseif (APPLE)
set(SDK_PATH "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Resources/sdk")
else()
set(SDK_PATH "share/imhex/sdk")
endif()
set(SDK_BUILD_PATH "${CMAKE_BINARY_DIR}/sdk")
setSDKPaths()
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/libimhex DESTINATION "${SDK_PATH}/lib" PATTERN "**/source/*" EXCLUDE)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/external DESTINATION "${SDK_PATH}/lib")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/imgui DESTINATION "${SDK_PATH}/lib/third_party" PATTERN "**/source/*" EXCLUDE)
@@ -865,6 +902,12 @@ function(generateSDKDirectory)
install(FILES ${CMAKE_SOURCE_DIR}/cmake/build_helpers.cmake DESTINATION "${SDK_PATH}/cmake")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/sdk/ DESTINATION "${SDK_PATH}")
install(TARGETS libimhex ARCHIVE DESTINATION "${SDK_PATH}/lib")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/plugins/ui DESTINATION "${SDK_PATH}/lib" PATTERN "**/source/*" EXCLUDE)
install(TARGETS ui ARCHIVE DESTINATION "${SDK_PATH}/lib")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/plugins/fonts DESTINATION "${SDK_PATH}/lib" PATTERN "**/source/*" EXCLUDE)
install(TARGETS fonts ARCHIVE DESTINATION "${SDK_PATH}/lib")
endfunction()
function(addIncludesFromLibrary target library)
@@ -885,4 +928,4 @@ function(precompileHeaders target includeFolder)
PUBLIC
"$<$<COMPILE_LANGUAGE:CXX>:${INCLUDES}>"
)
endfunction()
endfunction()

View File

@@ -40,7 +40,12 @@ IF(MBEDTLS_FOUND)
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})
SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}")
if (MSVC)
SET(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY_FILE}.lib ${MBEDX509_LIBRARY_FILE}.lib ${MBEDCRYPTO_LIBRARY_FILE}.lib)
else()
SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}")
endif()
IF(NOT MBEDTLS_FIND_QUIETLY)
MESSAGE(STATUS "Found mbedTLS:")

View File

@@ -1,4 +1,5 @@
macro(add_imhex_plugin)
setSDKPaths()
# Parse arguments
set(options LIBRARY_PLUGIN)
set(oneValueArgs NAME IMHEX_VERSION)
@@ -28,6 +29,10 @@ macro(add_imhex_plugin)
endif()
endif()
if (IMHEX_PLUGIN_LIBRARY_PLUGIN)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION "${SDK_PATH}/lib/plugins/${IMHEX_PLUGIN_NAME}")
endif()
# Define new project for plugin
project(${IMHEX_PLUGIN_NAME})
@@ -62,7 +67,11 @@ macro(add_imhex_plugin)
)
# Set rpath of plugin libraries to the plugins folder
if (APPLE)
if (WIN32)
if (IMHEX_PLUGIN_LIBRARY_PLUGIN)
set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
endif()
elseif (APPLE)
set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES BUILD_RPATH "@executable_path/../Frameworks;@executable_path/plugins")
endif()
@@ -147,4 +156,4 @@ macro (enable_plugin_feature feature)
remove_definitions(-DIMHEX_PLUGIN_${IMHEX_PLUGIN_NAME}_FEATURE_${feature}=0)
add_definitions(-DIMHEX_PLUGIN_${IMHEX_PLUGIN_NAME}_FEATURE_${feature}=1)
endmacro()
endmacro()

View File

@@ -38,11 +38,6 @@ add_subdirectory(lib/external/libwolv EXCLUDE_FROM_ALL)
set(LIBPL_ENABLE_CLI OFF CACHE BOOL "" FORCE)
add_subdirectory(lib/external/pattern_language EXCLUDE_FROM_ALL)
find_package(CURL REQUIRED)
find_package(mbedTLS 3.4.0 REQUIRED)
set(CURL_LIBRARIES ${CURL_LIBRARIES} PARENT_SCOPE)
set(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARIES} PARENT_SCOPE)
add_subdirectory(lib/libimhex)
if (WIN32)

View File

@@ -11,32 +11,23 @@ AppDir:
exec_args: $@
apt:
arch:
- amd64
- "{{ARCHITECTURE_PACKAGE}}"
allow_unauthenticated: true
sources:
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular main restricted
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular-updates main restricted
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular universe
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular-updates universe
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular multiverse
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular-updates multiverse
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular-backports main restricted
universe multiverse
- sourceline: deb http://security.ubuntu.com/ubuntu oracular-security main restricted
- sourceline: deb http://security.ubuntu.com/ubuntu oracular-security universe
- sourceline: deb http://security.ubuntu.com/ubuntu oracular-security multiverse
- 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'
include:
- librsvg2-common
- libbz2-1.0:amd64
- libcap2:amd64
- libdbus-1-3:amd64
- libfontconfig1:amd64
- libgpg-error0:amd64
- liblzma5:amd64
- libnss-mdns:amd64
- libpcre3:amd64
- libselinux1:amd64
- libtinfo6:amd64
- libbz2-1.0
- libcap2
- libdbus-1-3
- libfontconfig1
- libgpg-error0
- liblzma5
- libnss-mdns
- libpcre3
- libselinux1
- libtinfo6
files:
include:
- /lib/x86_64-linux-gnu/libLLVM-13.so.1
@@ -133,6 +124,6 @@ AppDir:
- usr/share/doc/*/NEWS.*
- usr/share/doc/*/TODO.*
AppImage:
arch: x86_64
update-information: gh-releases-zsync|WerWolv|ImHex|latest|imhex-*-x86_64.AppImage.zsync
file_name: imhex-{{VERSION}}-x86_64.AppImage
arch: "{{ARCHITECTURE_APPIMAGE_BUILDER}}"
update-information: gh-releases-zsync|WerWolv|ImHex|latest|imhex-*-{{ARCHITECTURE_FILE_NAME}}.AppImage.zsync
file_name: imhex-{{VERSION}}-{{ARCHITECTURE_FILE_NAME}}.AppImage

View File

@@ -30,8 +30,14 @@ 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
WORKDIR /build
SHELL ["bash", "-c"] # Ubuntu sh doesnt support string substitution
# Ubuntu sh doesnt support string substitution
SHELL ["bash", "-c"]
RUN <<EOF
# Prepare ImHex build
set -xe
@@ -73,7 +79,10 @@ pip3 install git+https://github.com/AppImageCrafters/appimage-builder@f38699e
# Package ImHex as AppImage
export VERSION=$(cat /imhex/VERSION)
appimage-builder --recipe /imhex/dist/AppImageBuilder.yml
export ARCHITECTURE_PACKAGE=${ARCHITECTURE_PACKAGE}
export ARCHITECTURE_FILE_NAME=${ARCHITECTURE_FILE_NAME}
export ARCHITECTURE_APPIMAGE_BUILDER=${ARCHITECTURE_APPIMAGE_BUILDER}
appimage-builder --recipe /imhex/dist/AppImage/AppImageBuilder.yml
EOF
FROM scratch

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/Brewfile`
2. Install all the dependencies using `brew bundle --no-lock --file dist/macOS/Brewfile`
3. Build ImHex itself using the following commands:
```sh
cd ImHex
@@ -19,4 +19,4 @@ cmake -G "Ninja" \
-DIMHEX_GENERATE_PACKAGE=ON \
..
ninja install
```
```

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env sh
pacman -S --needed --noconfirm pactoys
pacman -S --needed --noconfirm pactoys unzip
pacboy -S --needed --noconfirm \
gcc:p \
lld:p \

6
dist/imhex.desktop vendored
View File

@@ -1,4 +1,5 @@
[Desktop Entry]
Version=1.0
Name=ImHex
Comment=ImHex Hex Editor
GenericName=Hex Editor
@@ -10,3 +11,8 @@ Categories=Development;IDE;
StartupWMClass=imhex
Keywords=static-analysis;reverse-engineering;disassembler;disassembly;hacking;forensics;hex-editor;cybersecurity;security;binary-analysis;
MimeType=application/vnd.imhex.proj;
Actions=NewFile;
[Desktop Action NewFile]
Exec=imhex --new
Name=Create New File

View File

@@ -1,10 +1,21 @@
# This base image is also known as "crosscompile". See arm64.crosscompile.Dockerfile
FROM ghcr.io/itrooz/macos-crosscompile:clang17-nosdk as build
FROM ghcr.io/itrooz/macos-crosscompile:clang19-nosdk as build
ENV MACOSX_DEPLOYMENT_TARGET 13.0
# -- DOWNLOADING STUFF
# Update vcpkg
RUN <<EOF
cp /vcpkg/triplets/community/arm-osx-mytriplet.cmake /tmp/arm-osx-mytriplet.cmake
git -C /vcpkg clean -ffdx
git -C /vcpkg checkout origin/master
git -C /vcpkg reset --hard
git -C /vcpkg pull
/vcpkg/bootstrap-vcpkg.sh
cp /tmp/arm-osx-mytriplet.cmake /vcpkg/triplets/community/arm-osx-mytriplet.cmake
EOF
## Install make
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y make
@@ -35,7 +46,7 @@ EOF
## Download libmagic
### Clone libmagic
RUN git clone --depth 1 --branch FILE5_45 https://github.com/file/file /mnt/file
RUN git clone --depth 1 --branch FILE5_46 https://github.com/file/file /mnt/file
### Download libmagic dependencies
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y libtool autoconf

View File

@@ -1,4 +1,4 @@
# This image is is provided for reference, but a (probably more up to date) image should be available at https://github.com/iTrooz/macos-crosscompile
# This image is provided for reference, but a (probably more up to date) image should be available at https://github.com/iTrooz/macos-crosscompile
FROM ubuntu:22.04
ENV PATH $PATH:/osxcross/target/bin

4
dist/rpm/imhex.spec vendored
View File

@@ -123,9 +123,11 @@ cp -a lib/third_party/xdgpp/LICENSE %{buildroot
%doc README.md
%{_bindir}/imhex
%{_bindir}/imhex-updater
%{_datadir}/pixmaps/%{name}.png
%{_datadir}/pixmaps/%{name}.svg
%{_datadir}/applications/%{name}.desktop
%{_datadir}/mime/packages/%{name}.xml
%{_libdir}/libimhex.so*
%{_libdir}/%{name}/
%{_libdir}/*.hexpluglib
/usr/lib/debug/%{_libdir}/*.debug
%{_metainfodir}/net.werwolv.%{name}.metainfo.xml

16
dist/vcpkg.json vendored Normal file
View File

@@ -0,0 +1,16 @@
{
"name": "vcpkg",
"version": "1.0.0",
"builtin-baseline": "7e21420f775f72ae938bdeb5e6068f722088f06a",
"dependencies": [
"libmagic",
"freetype",
"mbedtls",
"zlib",
"bzip2",
"liblzma",
"zstd",
"glfw3",
"curl"
]
}

12
dist/web/Dockerfile vendored
View File

@@ -1,4 +1,4 @@
FROM emscripten/emsdk:3.1.51 as build
FROM emscripten/emsdk:3.1.51 AS build
# Used to invalidate layer cache but not mount cache
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493
@@ -13,6 +13,7 @@ RUN <<EOF
set -xe
git clone https://github.com/microsoft/vcpkg /vcpkg
git -C /vcpkg pull
/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
@@ -27,7 +28,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
' >> /emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake
EOF
ENV VCPKG_DEFAULT_BINARY_CACHE /cache/vcpkg
ENV VCPKG_DEFAULT_BINARY_CACHE=/cache/vcpkg
RUN --mount=type=cache,target=/cache <<EOF
# Install dependencies with vcpkg
set -xe
@@ -45,7 +46,7 @@ EOF
# Build ImHex
ARG JOBS=4
ENV CCACHE_DIR /cache/ccache
ENV CCACHE_DIR=/cache/ccache
RUN mkdir /build
WORKDIR /build
@@ -67,6 +68,7 @@ cmake /imhex
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake \
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
-DLIBROMFS_COMPRESS_RESOURCES=OFF \
-DCMAKE_BUILD_TYPE=Release
ninja -j $JOBS
@@ -79,7 +81,7 @@ EOF
# See https://stackoverflow.com/questions/41701849/cannot-modify-accept-encoding-with-fetch https://github.com/AnthumChris/fetch-progress-indicators/issues/13
RUN du -b /build/imhex.wasm | cut -f1 > imhex.wasm.size
FROM scratch as raw
FROM scratch AS raw
COPY --from=build [ \
# ImHex \
"/build/imhex.wasm", \
@@ -93,7 +95,7 @@ COPY --from=build [ \
"/build/wasm-config.js", \
"/build/enable-threads.js", \
"/build/favicon.ico", \
"/build/icon.png", \
"/build/icon.svg", \
"/build/manifest.json", \
"/build/robots.txt", \
"/build/sitemap.xml", \

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 KiB

11
dist/web/source/icon.svg vendored Normal file
View File

@@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" version="1">
<rect style="opacity:0.2" width="55" height="10" x="5" y="-60" rx="1.41" transform="rotate(90)"/>
<rect style="fill:#2b50a1" width="55" height="10" x="4" y="-60" rx="1.41" transform="rotate(90)"/>
<rect style="fill:#2b50a1" width="55" height="10" x="4" y="-14" rx="1.41" transform="rotate(90)"/>
<rect style="fill:#2b50a1" width="55" height="10" x="4" y="-33" rx="1.41" transform="rotate(90)"/>
<path style="opacity:0.2" d="M 5.3808594,5 C 4.6158118,5 4,5.6158118 4,6.3808594 V 13.619141 C 4,14.384188 4.6158118,15 5.3808594,15 H 31.619141 C 32.384188,15 33,14.384188 33,13.619141 V 6.3808594 C 33,5.6158118 32.384188,5 31.619141,5 Z M 40.400391,5 C 39.624791,5 39,5.6247906 39,6.4003906 V 13.599609 C 39,14.375209 39.624791,15 40.400391,15 H 58.599609 C 59.375209,15 60,14.375209 60,13.599609 V 6.4003906 C 60,5.6247906 59.375209,5 58.599609,5 Z M 5.3808594,50 C 4.6158118,50 4,50.615812 4,51.380859 v 7.238282 C 4,59.384188 4.6158118,60 5.3808594,60 H 31.619141 C 32.384188,60 33,59.384188 33,58.619141 V 51.380859 C 33,50.615812 32.384188,50 31.619141,50 Z"/>
<rect style="fill:#3a6be0" width="29" height="10" x="4" y="4" rx="1.381"/>
<rect style="fill:#3a6be0" width="21" height="10" x="39" y="4" rx="1.4"/>
<rect style="fill:#3a6be0" width="29" height="10" x="4" y="49" rx="1.381"/>
<path style="fill:#ffffff;opacity:0.1" d="M 5.3808594 4 C 4.6158118 4 4 4.6158118 4 5.3808594 L 4 6.3808594 C 4 5.6158118 4.6158118 5 5.3808594 5 L 31.619141 5 C 32.384188 5 33 5.6158118 33 6.3808594 L 33 5.3808594 C 33 4.6158118 32.384188 4 31.619141 4 L 5.3808594 4 z M 40.400391 4 C 39.624791 4 39 4.6247906 39 5.4003906 L 39 6.4003906 C 39 5.6247906 39.624791 5 40.400391 5 L 58.599609 5 C 59.375209 5 60 5.6247906 60 6.4003906 L 60 5.4003906 C 60 4.6247906 59.375209 4 58.599609 4 L 40.400391 4 z M 5.3808594 49 C 4.6158118 49 4 49.615812 4 50.380859 L 4 51.380859 C 4 50.615812 4.6158118 50 5.3808594 50 L 31.619141 50 C 32.384188 50 33 50.615812 33 51.380859 L 33 50.380859 C 33 49.615812 32.384188 49 31.619141 49 L 5.3808594 49 z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -11,7 +11,7 @@
<meta name="title" content="ImHex">
<meta name="description" content="Free and extremely powerful Online Hex Editor for your Web Browser. ImHex is a free and open source Hex Editor for Reverse Engineers and Developers and Data Analysts.">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="apple-touch-icon" href="icon.png">
<link rel="apple-touch-icon" href="icon.svg">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
@@ -38,7 +38,7 @@
"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.png"
"logo": "https://imhex.werwolv.net/assets/logos/logo.svg"
}
</script>

View File

@@ -10,8 +10,8 @@
],
"icons": [
{
"src": "icon.png",
"type": "image/png",
"src": "icon.svg",
"type": "image/svg",
"sizes": "640x640"
}
],

View File

@@ -57,6 +57,11 @@
<loc>https://web.imhex.werwolv.net?lang=it-IT</loc>
<lastmod>2024-01-02T11:44:00+00:00</lastmod>
</url>
<url>
<title>Русский</title>
<loc>https://web.imhex.werwolv.net?lang=ru-RU</loc>
<lastmod>2024-01-02T11:44:00+00:00</lastmod>
</url>
</urlset>

View File

@@ -261,4 +261,11 @@ function js_resizeCanvas() {
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);
}
}
// Prevent some default browser shortcuts from preventing ImHex ones to work
document.addEventListener('keydown', e => {
if (e.ctrlKey) {
if (e.which == 83) e.preventDefault();
}
})

1
lib/external/disassembler vendored Submodule

View File

@@ -22,6 +22,9 @@ set(LIBIMHEX_SOURCES
source/data_processor/link.cpp
source/data_processor/node.cpp
source/project/project.cpp
source/project/project_manager.cpp
source/helpers/utils.cpp
source/helpers/utils_linux.cpp
source/helpers/fs.cpp
@@ -38,6 +41,8 @@ set(LIBIMHEX_SOURCES
source/helpers/debugging.cpp
source/helpers/default_paths.cpp
source/helpers/imgui_hooks.cpp
source/helpers/semantic_version.cpp
source/helpers/keys.cpp
source/test/tests.cpp
@@ -49,6 +54,7 @@ set(LIBIMHEX_SOURCES
source/ui/view.cpp
source/ui/popup.cpp
source/ui/toast.cpp
source/ui/banner.cpp
source/subcommands/subcommands.cpp
)
@@ -120,31 +126,41 @@ setupCompilerFlags(libimhex)
include(GenerateExportHeader)
generate_export_header(libimhex)
target_include_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} include ${XDGPP_INCLUDE_DIRS} ${MBEDTLS_INCLUDE_DIR} ${MAGIC_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS} ${FMT_INCLUDE_DIRS} ${LIBBACKTRACE_INCLUDE_DIRS})
target_link_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_LIBRARY_DIR} ${MAGIC_LIBRARY_DIRS})
if (NOT EMSCRIPTEN)
# curl is only used in non-emscripten builds
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} CURL::libcurl)
endif()
target_include_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} include ${XDGPP_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS} ${FMT_INCLUDE_DIRS})
if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
if (WIN32)
set_target_properties(libimhex PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
target_link_options(libimhex PRIVATE -Wl,--export-all-symbols)
if (NOT MSVC)
target_link_options(libimhex PRIVATE -Wl,--export-all-symbols)
endif()
target_link_libraries(libimhex PRIVATE Netapi32.lib)
target_compile_definitions(libimhex PRIVATE EXPORT_SYMBOLS=1)
elseif (APPLE)
find_library(FOUNDATION NAMES Foundation)
target_link_libraries(libimhex PUBLIC ${FOUNDATION})
endif ()
target_link_libraries(libimhex PRIVATE microtar libwolv ${NFD_LIBRARIES} magic dl ${JTHREAD_LIBRARIES})
target_link_libraries(libimhex PUBLIC libpl ${IMGUI_LIBRARIES})
target_link_libraries(libimhex PRIVATE libpl microtar ${NFD_LIBRARIES} magic)
target_link_libraries(libimhex PUBLIC libwolv libpl_includes libpl-gen ${IMGUI_LIBRARIES} ${JTHREAD_LIBRARIES})
if (NOT WIN32)
target_link_libraries(libimhex PRIVATE dl)
endif()
if (NOT EMSCRIPTEN)
# curl is only used in non-emscripten builds
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} CURL::libcurl)
endif()
target_include_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_INCLUDE_DIR} ${LIBBACKTRACE_INCLUDE_DIRS} ${MAGIC_INCLUDE_DIRS})
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_LIBRARIES})
target_link_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_LIBRARY_DIR} ${MAGIC_LIBRARY_DIRS})
precompileHeaders(libimhex "${CMAKE_CURRENT_SOURCE_DIR}/include")
endif()
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${NLOHMANN_JSON_LIBRARIES} imgui_all_includes ${MBEDTLS_LIBRARIES} ${FMT_LIBRARIES} ${LUNASVG_LIBRARIES} ${BOOST_LIBRARIES})
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${NLOHMANN_JSON_LIBRARIES} imgui_all_includes ${FMT_LIBRARIES} ${LUNASVG_LIBRARIES} ${BOOST_LIBRARIES})
set_property(TARGET libimhex PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE)

View File

@@ -14,6 +14,7 @@
#include <imgui.h>
#include <hex/ui/imgui_imhex_extensions.h>
#include <hex/api/localization_manager.hpp>
#include <hex/helpers/auto_reset.hpp>
namespace hex {
@@ -361,7 +362,7 @@ namespace hex {
* @brief Returns all registered achievements
* @return All achievements
*/
static const std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>>& getAchievements();
static const std::unordered_map<UnlocalizedString, std::unordered_map<UnlocalizedString, std::unique_ptr<Achievement>>>& getAchievements();
/**
* @brief Returns all achievement start nodes
@@ -369,14 +370,14 @@ namespace hex {
* @param rebuild Whether to rebuild the list of start nodes
* @return All achievement start nodes
*/
static const std::unordered_map<std::string, std::vector<AchievementNode*>>& getAchievementStartNodes(bool rebuild = true);
static const std::unordered_map<UnlocalizedString, std::vector<AchievementNode*>>& getAchievementStartNodes(bool rebuild = true);
/**
* @brief Returns all achievement nodes
* @param rebuild Whether to rebuild the list of nodes
* @return All achievement nodes
*/
static const std::unordered_map<std::string, std::list<AchievementNode>>& getAchievementNodes(bool rebuild = true);
static const std::unordered_map<UnlocalizedString, std::list<AchievementNode>>& getAchievementNodes(bool rebuild = true);
/**
* @brief Loads the progress of all achievements from the achievements save file
@@ -405,4 +406,4 @@ namespace hex {
static Achievement& addAchievementImpl(std::unique_ptr<Achievement> &&newAchievement);
};
}
}

View File

@@ -20,6 +20,7 @@ using ImGuiDataType = int;
using ImGuiInputTextFlags = int;
struct ImColor;
enum ImGuiCustomCol : int;
typedef int ImGuiColorEditFlags;
namespace hex {
@@ -43,7 +44,6 @@ namespace hex {
plugins when needed.
*/
namespace ContentRegistry {
/* Settings Registry. Allows adding of new entries into the ImHex preferences window. */
namespace Settings {
@@ -177,7 +177,7 @@ namespace hex {
class SliderDataSize : public Widget {
public:
SliderDataSize(u64 defaultValue, u64 min, u64 max) : m_value(defaultValue), m_min(min), m_max(max) { }
SliderDataSize(u64 defaultValue, u64 min, u64 max, u64 stepSize) : m_value(defaultValue), m_min(min), m_max(max), m_stepSize(stepSize) { }
bool draw(const std::string &name) override;
void load(const nlohmann::json &data) override;
@@ -188,11 +188,12 @@ namespace hex {
protected:
u64 m_value;
u64 m_min, m_max;
u64 m_stepSize;
};
class ColorPicker : public Widget {
public:
explicit ColorPicker(ImColor defaultColor);
explicit ColorPicker(ImColor defaultColor, ImGuiColorEditFlags flags = 0);
bool draw(const std::string &name) override;
@@ -202,12 +203,14 @@ namespace hex {
[[nodiscard]] ImColor getColor() const;
protected:
std::array<float, 4> m_value{};
std::array<float, 4> m_value = {}, m_defaultValue = {};
ImGuiColorEditFlags m_flags;
};
class DropDown : public Widget {
public:
explicit DropDown(const std::vector<std::string> &items, const std::vector<nlohmann::json> &settingsValues, const nlohmann::json &defaultItem) : m_items(items), m_settingsValues(settingsValues), m_defaultItem(defaultItem) { }
explicit DropDown(const std::vector<std::string> &items, const std::vector<nlohmann::json> &settingsValues, const nlohmann::json &defaultItem) : m_items(items.begin(), items.end()), m_settingsValues(settingsValues), m_defaultItem(defaultItem) { }
explicit DropDown(const std::vector<UnlocalizedString> &items, const std::vector<nlohmann::json> &settingsValues, const nlohmann::json &defaultItem) : m_items(items), m_settingsValues(settingsValues), m_defaultItem(defaultItem) { }
bool draw(const std::string &name) override;
@@ -218,7 +221,7 @@ namespace hex {
const nlohmann::json& getValue() const;
protected:
std::vector<std::string> m_items;
std::vector<UnlocalizedString> m_items;
std::vector<nlohmann::json> m_settingsValues;
nlohmann::json m_defaultItem;
@@ -325,7 +328,7 @@ namespace hex {
result = defaultValue;
return result.get<T>();
} catch (const nlohmann::json::exception &e) {
} catch (const nlohmann::json::exception &) {
return defaultValue;
}
}
@@ -573,7 +576,7 @@ namespace hex {
namespace impl {
void add(std::unique_ptr<View> &&view);
const std::map<std::string, std::unique_ptr<View>>& getEntries();
const std::map<UnlocalizedString, std::unique_ptr<View>>& getEntries();
}
@@ -594,6 +597,12 @@ namespace hex {
* @return The view if it exists, nullptr otherwise
*/
View* getViewByName(const UnlocalizedString &unlocalizedName);
/**
* @brief Gets the currently focused view
* @return The view that is focused right now. nullptr if none is focused
*/
View* getFocusedView();
}
/* Tools Registry. Allows adding new entries to the tools window */
@@ -623,8 +632,7 @@ namespace hex {
/* Data Inspector Registry. Allows adding of new types to the data inspector */
namespace DataInspector {
enum class NumberDisplayStyle
{
enum class NumberDisplayStyle : u8 {
Decimal,
Hexadecimal,
Octal
@@ -678,6 +686,13 @@ namespace hex {
std::optional<impl::EditingFunction> editingFunction = std::nullopt
);
/**
* @brief Allows adding new menu items to data inspector row context menus. Call this function inside the
* draw function of the data inspector row definition.
* @param function Callback that will draw menu items
*/
void drawMenuItems(const std::function<void()> &function);
}
/* Data Processor Node Registry. Allows adding new processor nodes to be used in the data processor */
@@ -712,7 +727,7 @@ namespace hex {
add(impl::Entry {
unlocalizedCategory,
unlocalizedName,
[=, ...args = std::forward<Args>(args)] mutable {
[=, ...args = std::forward<Args>(args)]() mutable {
auto node = std::make_unique<T>(std::forward<Args>(args)...);
node->setUnlocalizedName(unlocalizedName);
return node;
@@ -993,7 +1008,7 @@ namespace hex {
void add(bool addToList = true) {
auto typeName = T().getTypeName();
impl::add(typeName, [] -> std::unique_ptr<prv::Provider> {
impl::add(typeName, []() -> std::unique_ptr<prv::Provider> {
return std::make_unique<T>();
});
@@ -1008,7 +1023,7 @@ namespace hex {
namespace impl {
using Callback = std::function<std::string(prv::Provider *provider, u64 address, size_t size)>;
using Callback = std::function<std::string(prv::Provider *provider, u64 address, size_t size, bool preview)>;
struct ExportMenuEntry {
UnlocalizedString unlocalizedName;
Callback callback;
@@ -1016,7 +1031,7 @@ namespace hex {
struct FindOccurrence {
Region region;
enum class DecodeType { ASCII, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
enum class DecodeType { ASCII, UTF8, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
std::endian endian = std::endian::native;
bool selected;
};
@@ -1101,9 +1116,9 @@ namespace hex {
[[nodiscard]] const UnlocalizedString& getUnlocalizedName() const { return m_unlocalizedName; }
protected:
const static int TextInputFlags;
[[nodiscard]] static int DefaultTextInputFlags();
protected:
bool drawDefaultScalarEditingTextBox(u64 address, const char *format, ImGuiDataType dataType, u8 *data, ImGuiInputTextFlags flags) const;
bool drawDefaultTextEditingTextBox(u64 address, std::string &data, ImGuiInputTextFlags flags) const;
@@ -1354,6 +1369,7 @@ namespace hex {
}
/* Data Information Registry. Allows adding new analyzers to the data information view */
namespace DataInformation {
class InformationSection {
@@ -1420,6 +1436,54 @@ namespace hex {
}
/* Disassembler Registry. Allows adding new disassembler architectures */
namespace Disassembler {
struct Instruction {
u64 address;
u64 offset;
size_t size;
std::string bytes;
std::string mnemonic;
std::string operators;
};
class Architecture {
public:
explicit Architecture(std::string name) : m_name(std::move(name)) {}
virtual ~Architecture() = default;
virtual bool start() = 0;
virtual void end() = 0;
virtual std::optional<Instruction> disassemble(u64 imageBaseAddress, u64 instructionLoadAddress, u64 instructionDataAddress, std::span<const u8> code) = 0;
virtual void drawSettings() = 0;
[[nodiscard]] const std::string& getName() const { return m_name; }
private:
std::string m_name;
};
namespace impl {
using CreatorFunction = std::function<std::unique_ptr<Architecture>()>;
void addArchitectureCreator(CreatorFunction function);
const std::map<std::string, CreatorFunction>& getArchitectures();
}
template<std::derived_from<Architecture> T>
void add(auto && ...args) {
impl::addArchitectureCreator([...args = std::move(args)] {
return std::make_unique<T>(args...);
});
}
}
}
}

View File

@@ -11,7 +11,6 @@
#include <hex/api/imhex_api.hpp>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/patches.hpp>
#include <wolv/types/type_name.hpp>
@@ -32,15 +31,6 @@
#define EVENT_DEF_NO_LOG(event_name, ...) EVENT_DEF_IMPL(event_name, #event_name, false, __VA_ARGS__)
/* Forward declarations */
struct GLFWwindow;
namespace hex {
class Achievement;
class View;
}
namespace pl::ptrn { class Pattern; }
namespace hex {
namespace impl {
@@ -100,7 +90,8 @@ namespace hex {
/**
* @brief The EventManager allows subscribing to and posting events to different parts of the program.
* To create a new event, use the EVENT_DEF macro. This will create a new event type with the given name and parameters
* To create a new event, use the EVENT_DEF macro. This will create a new event type with the given name and parameters.
* Events should be created in an `events_*.hpp` category file under the `events` folder, and never directly here.
*/
class EventManager {
public:
@@ -200,122 +191,4 @@ namespace hex {
static void unsubscribe(void *token, impl::EventId id);
};
/* Default Events */
/**
* @brief Called when Imhex finished startup, and will enter the main window rendering loop
*/
EVENT_DEF(EventImHexStartupFinished);
EVENT_DEF(EventFileLoaded, std::fs::path);
EVENT_DEF(EventDataChanged, prv::Provider *);
EVENT_DEF(EventHighlightingChanged);
EVENT_DEF(EventWindowClosing, GLFWwindow *);
EVENT_DEF(EventRegionSelected, ImHexApi::HexEditor::ProviderRegion);
EVENT_DEF(EventAbnormalTermination, int);
EVENT_DEF(EventThemeChanged);
EVENT_DEF(EventOSThemeChanged);
EVENT_DEF(EventDPIChanged, float, float);
EVENT_DEF(EventWindowFocused, bool);
/**
* @brief Called when the provider is created.
* 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(EventProviderChanged, prv::Provider *, prv::Provider *);
/**
* @brief Called as a continuation of EventProviderCreated
* this event is normally called immediately after EventProviderCreated successfully initialized the provider.
* If no initialization (Provider::skipLoadInterface() has been set), this event should be called manually
* If skipLoadInterface failed, this event is not called
*
* @note this is not related to Provider::open()
*/
EVENT_DEF(EventProviderOpened, prv::Provider *);
EVENT_DEF(EventProviderClosing, prv::Provider *, bool *);
EVENT_DEF(EventProviderClosed, prv::Provider *);
EVENT_DEF(EventProviderDeleted, prv::Provider *);
EVENT_DEF(EventProviderSaved, prv::Provider *);
EVENT_DEF(EventWindowInitialized);
EVENT_DEF(EventWindowDeinitializing, GLFWwindow *);
EVENT_DEF(EventBookmarkCreated, ImHexApi::Bookmarks::Entry&);
/**
* @brief Called upon creation of an IPS patch.
* As for now, the event only serves a purpose for the achievement unlock.
*/
EVENT_DEF(EventPatchCreated, const u8*, u64, const PatchKind);
EVENT_DEF(EventPatternEvaluating);
EVENT_DEF(EventPatternExecuted, const std::string&);
EVENT_DEF(EventPatternEditorChanged, const std::string&);
EVENT_DEF(EventStoreContentDownloaded, const std::fs::path&);
EVENT_DEF(EventStoreContentRemoved, const std::fs::path&);
EVENT_DEF(EventImHexClosing);
EVENT_DEF(EventAchievementUnlocked, const Achievement&);
EVENT_DEF(EventSearchBoxClicked, u32);
EVENT_DEF(EventViewOpened, View*);
EVENT_DEF(EventFirstLaunch);
EVENT_DEF(EventFileDragged, bool);
EVENT_DEF(EventFileDropped, std::fs::path);
EVENT_DEF(EventProviderDataModified, prv::Provider *, u64, u64, const u8*);
EVENT_DEF(EventProviderDataInserted, prv::Provider *, u64, u64);
EVENT_DEF(EventProviderDataRemoved, prv::Provider *, u64, u64);
EVENT_DEF(EventProviderDirtied, prv::Provider *);
/**
* @brief Called when a project has been loaded
*/
EVENT_DEF(EventProjectOpened);
EVENT_DEF_NO_LOG(EventFrameBegin);
EVENT_DEF_NO_LOG(EventFrameEnd);
EVENT_DEF_NO_LOG(EventSetTaskBarIconState, u32, u32, u32);
EVENT_DEF_NO_LOG(EventImGuiElementRendered, ImGuiID, const std::array<float, 4>&);
EVENT_DEF(RequestAddInitTask, std::string, bool, std::function<bool()>);
EVENT_DEF(RequestAddExitTask, std::string, std::function<bool()>);
EVENT_DEF(RequestOpenWindow, std::string);
EVENT_DEF(RequestHexEditorSelectionChange, Region);
EVENT_DEF(RequestPatternEditorSelectionChange, u32, u32);
EVENT_DEF(RequestJumpToPattern, const pl::ptrn::Pattern*);
EVENT_DEF(RequestAddBookmark, Region, std::string, std::string, color_t, u64*);
EVENT_DEF(RequestRemoveBookmark, u64);
EVENT_DEF(RequestSetPatternLanguageCode, std::string);
EVENT_DEF(RequestRunPatternCode);
EVENT_DEF(RequestLoadPatternLanguageFile, std::fs::path);
EVENT_DEF(RequestSavePatternLanguageFile, std::fs::path);
EVENT_DEF(RequestUpdateWindowTitle);
EVENT_DEF(RequestCloseImHex, bool);
EVENT_DEF(RequestRestartImHex);
EVENT_DEF(RequestOpenFile, std::fs::path);
EVENT_DEF(RequestChangeTheme, std::string);
EVENT_DEF(RequestOpenPopup, std::string);
EVENT_DEF(RequestAddVirtualFile, std::fs::path, std::vector<u8>, Region);
/**
* @brief Creates a provider from it's unlocalized name, and add it to the provider list
*/
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, hex::prv::Provider **);
EVENT_DEF(RequestInitThemeHandlers);
/**
* @brief Send an event to the main Imhex instance
*/
EVENT_DEF(SendMessageToMainInstance, const std::string, const std::vector<u8>&);
/**
* Move the data from all PerProvider instances from one provider to another.
* The 'from' provider should not have any per provider data after this, and should be immediately deleted
*/
EVENT_DEF(MovePerProviderData, prv::Provider *, prv::Provider *);
/**
* Called when ImHex managed to catch an error in a general try/catch to prevent/recover from a crash
*/
EVENT_DEF(EventCrashRecovered, const std::exception &);
}

View File

@@ -0,0 +1,120 @@
#pragma once
#include <hex/api/event_manager.hpp>
/* Forward declarations */
struct GLFWwindow;
namespace hex { class View; }
/* GUI events definitions */
namespace hex {
/**
* @brief Signals a newly opened window
*
* This event is sent when the window has just been opened and docked by the Window manager.
*
* FIXME: In the event that a newly created window is already docked, this will not be sent.
*
* FIXME: This is currently only used for the introduction tutorial.
* If the event's only purpose is this, maybe rename it?
*
* @param view the new view reference
*/
EVENT_DEF(EventViewOpened, View*);
/**
* @brief Signals a change in the DPI scale.
*
* This event is called once at startup to signal native scale definition (by passing the same value twice).
* On Windows OS, this event can also be posted if the window DPI has been changed.
*
* @param oldScale the old scale
* @param newScale the current scale that's now in use
*/
EVENT_DEF(EventDPIChanged, float, float);
/**
* @brief Signals the focus of the ImHex main window.
*
* This is directly tied as a GLFW window focus callback, and will be called accordingly when GLFW detects
* a change in focus.
*
* @param isFocused true if the window is focused
*/
EVENT_DEF(EventWindowFocused, bool);
/**
* @brief Signals a window being closed.
*
* Allows reactive clean up of running tasks, and prevents ImHex from closing
* by displaying an exit confirmation popup.
*
* @param window The window reference
*/
EVENT_DEF(EventWindowClosing, GLFWwindow*);
/**
* @brief Informs that the main window is initialized
*
* On Windows OS, it is used to initialize system theme, if ImHex's theme is following it.
*
* FIXME: Change event name to reflect Theme detection, if it's only used for that purpose?
*/
EVENT_DEF(EventWindowInitialized);
/**
* @brief Informs that the main window is deinitializing
*
* Allows for lifecycle cleanup before ImHex shutdown.
*
* @param window The window reference
*/
EVENT_DEF(EventWindowDeinitializing, GLFWwindow*);
/**
* @brief Signals a theme change in the host OS
*
* Allows ImHex to react to OS theme changes dynamically during execution.
*/
EVENT_DEF(EventOSThemeChanged);
}
/* silent (no-logging) GUI events definitions */
namespace hex {
/**
* @brief Signals the start of a new ImGui frame
*/
EVENT_DEF_NO_LOG(EventFrameBegin);
/**
* @brief Signals the end of an ImGui frame
*/
EVENT_DEF_NO_LOG(EventFrameEnd);
/**
* @brief Windows OS: Sets the taskbar icon state
*
* This event is used on Windows OS to display progress through the taskbar icon (the famous "green loading bar"
* in the taskbar).
*
* @param progressState the progress state (converted from the TaskProgressState enum)
* @param progressType the type of progress (converted from the TaskProgressType enum)
* @param percentage actual progress percentage (expected from 0 to 100)
*
* @see hex::ImHexApi::System::TaskProgressState
* @see hex::ImHexApi::System::TaskProgressType
*/
EVENT_DEF_NO_LOG(EventSetTaskBarIconState, u32, u32, u32);
/**
* @brief Informs of an ImGui element being rendered
*
* @param elementId the element's ID
* @param boundingBox the bounding box (composed of 4 floats)
*/
EVENT_DEF_NO_LOG(EventImGuiElementRendered, ImGuiID, const std::array<float, 4>&);
}

View File

@@ -0,0 +1,158 @@
#pragma once
#include <hex/api/event_manager.hpp>
#include <hex/helpers/patches.hpp>
/* Forward declarations */
namespace hex { class Achievement; }
/* Interaction events definitions */
namespace hex {
/**
* @brief Signals a file was loaded
*
* FIXME: this event is unused and should be scrapped.
*
* @param path the loaded file's path
*/
EVENT_DEF(EventFileLoaded, std::fs::path);
/**
* @brief Signals a change in the current data
*
* Enables provider reaction to data change, especially the data inspector.
*
* This is caused by the following:
* - an explicit provider reload, requested by the user (Ctrl+R)
* - any user action that results in the creation of an "undo" stack action (generally a data modification)
*
* @param provider the Provider subject to the data change
*/
EVENT_DEF(EventDataChanged, prv::Provider *);
/**
* @brief Signals a change in highlighting
*
* The event's only purpose is for the Hex editor to clear highlights when receiving this event.
*/
EVENT_DEF(EventHighlightingChanged);
/**
* @brief Informs of a provider region being selected
*
* This is very generally used to signal user actions that select a specific region within the provider.
* It is also used to pass on regions when the provider changes.
*
* @param providerRegion the provider-aware region being selected
*/
EVENT_DEF(EventRegionSelected, ImHexApi::HexEditor::ProviderRegion);
/**
* @brief Signals a theme change
*
* On Windows OS, this is used to reflect the theme color onto the window frame.
*/
EVENT_DEF(EventThemeChanged);
/**
* @brief Signals that a bookmark was created
*
* For now, this event's only purpose is to unlock an achievement.
*
* @param entry the new bookmark
*/
EVENT_DEF(EventBookmarkCreated, ImHexApi::Bookmarks::Entry&);
/**
* @brief Called upon creation of an IPS patch.
* As for now, the event only serves a purpose for the achievement unlock.
*
* @param data the pointer to the patch content's start
* @param size the patch data size
* @param kind the patch's kind
*/
EVENT_DEF(EventPatchCreated, const u8*, u64, const PatchKind);
/**
* @brief Signals the beginning of evaluation of the current pattern
*
* This allows resetting the drawer view for the pattern data while we wait for the execution completion.
*/
EVENT_DEF(EventPatternEvaluating);
/**
* @brief Signals the completion of the pattern evaluation
*
* This causes another reset in the drawer view, to refresh the table displayed to the user.
*
* @param code the execution's status code
*/
EVENT_DEF(EventPatternExecuted, const std::string&);
/**
* @brief Denotes when pattern editor has changed
*
* FIXME: this event is unused and should be scrapped.
*/
EVENT_DEF(EventPatternEditorChanged, const std::string&);
/**
* @brief Signals that a Content Store item was downloaded
*
* FIXME: this event is unused and should be scrapped.
*
* @param path the item's path on the filesystem
*/
EVENT_DEF(EventStoreContentDownloaded, const std::fs::path&);
/**
* @brief Signals the removal of a Content Store item
*
* Note: at the time of the event firing, the item has already been removed from the filesystem.
*
* FIXME: this event is unused and should be scrapped.
*
* @param path the item's old file path where it used to be in the filesystem
*/
EVENT_DEF(EventStoreContentRemoved, const std::fs::path&);
/**
* @brief Signals the unlocking of an achievement
*
* This is used by the achievement manager to refresh the achievement display, as well as store progress to
* the appropriate storage file.
*
* @param achievement the achievement that was unlocked
*/
EVENT_DEF(EventAchievementUnlocked, const Achievement&);
/**
* @brief Signals a click on the search box
*
* As there are different behaviours depending on the click (left or right) done by the user,
* this allows the consequences of said click to be registered in their own components.
*
* @param button the ImGuiMouseButton's value
*/
EVENT_DEF(EventSearchBoxClicked, u32);
/**
* @brief Updates on whether a file is being dragged into ImHex
*
* Allows ImGUi to display a file dragging information on screen when a file is being dragged.
*
* @param isFileDragged true if a file is being dragged
*/
EVENT_DEF(EventFileDragged, bool);
/**
* @brief Triggers loading when a file is dropped
*
* The event fires when a file is dropped into ImHex, which passes it to file handlers to load it.
*
* @param path the dropped file's path
*/
EVENT_DEF(EventFileDropped, std::fs::path);
}

View File

@@ -0,0 +1,78 @@
#pragma once
#include <hex/api/event_manager.hpp>
/* Lifecycle events definitions */
namespace hex {
/**
* @brief Called when Imhex finished startup, and will enter the main window rendering loop
*/
EVENT_DEF(EventImHexStartupFinished);
/**
* @brief Called when ImHex is closing, to trigger the last shutdown hooks
*
* This is the last event to fire before complete graceful shutdown.
*/
EVENT_DEF(EventImHexClosing);
/**
* @brief Signals that it's ImHex first launch ever
*
* This event allows for the launch of the ImHex tutorial (also called Out of Box experience).
*/
EVENT_DEF(EventFirstLaunch);
/**
* FIXME: this event is unused and should be scrapped.
*/
EVENT_DEF(EventAnySettingChanged);
/**
* @brief Ensures correct plugin cleanup on crash
*
* This event is fired when catching an unexpected error that cannot be recovered and
* which forces Imhex to close immediately.
*
* Subscribing to this event ensures that the plugin can correctly clean up any mission-critical tasks
* before forceful shutdown.
*
* @param signal the POSIX signal code
*/
EVENT_DEF(EventAbnormalTermination, int);
/**
* @brief Informs of the ImHex versions (and difference, if any)
*
* Called on every startup to inform subscribers of the two versions picked up:
* - the version of the previous launch, gathered from the settings file
* - the current version, gathered directly from C++ code
*
* In most cases, and unless ImHex was updated, the two parameters will be the same.
*
* FIXME: Maybe rename the event to signal a startup information, instead of the misleading
* title that the event could be fired when ImHex detects that it was updated since last launch?
*
* @param previousLaunchVersion ImHex's version during the previous launch
* @param currentVersion ImHex's current version for this startup
*/
EVENT_DEF(EventImHexUpdated, SemanticVersion, SemanticVersion);
/**
* @brief Called when ImHex managed to catch an error in a general try/catch to prevent/recover from a crash
*/
EVENT_DEF(EventCrashRecovered, const std::exception &);
/**
* @brief Called when a project has been loaded
*/
EVENT_DEF(EventProjectOpened);
/**
* @brief Called when a native message was received from another ImHex instance
* @param rawData Raw bytes received from other instance
*/
EVENT_DEF(EventNativeMessageReceived, std::vector<u8>);
}

View File

@@ -0,0 +1,113 @@
#pragma once
#include <hex.hpp>
#include <hex/api/event_manager.hpp>
/* Provider events definitions */
namespace hex {
/**
* @brief Called when the provider is created.
* 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 *);
/**
* @brief Called as a continuation of EventProviderCreated
* this event is normally called immediately after EventProviderCreated successfully initialized the provider.
* If no initialization (Provider::skipLoadInterface() has been set), this event should be called manually
* If skipLoadInterface failed, this event is not called
*
* @note this is not related to Provider::open()
*/
EVENT_DEF(EventProviderOpened, prv::Provider *);
/**
* @brief Signals a change in provider (in-place)
*
* Note: if the provider was deleted, the new ("current") provider will be `nullptr`
*
* @param oldProvider the old provider
* @param currentProvider the current provider
*/
EVENT_DEF(EventProviderChanged, prv::Provider *, prv::Provider *);
/**
* @brief Signals that a provider was saved
*
* @param provider the saved provider
*/
EVENT_DEF(EventProviderSaved, prv::Provider *);
/**
* @brief Signals a provider is closing
*
* FIXME: as for now, this behaves as a request more than an event. Also, the boolean is always set to true,
* and serves no purpose. This should be moved into the Provider requests section and declared accordingly.
*
* @param provider the closing provider
* @param shouldClose whether the provider should close
*/
EVENT_DEF(EventProviderClosing, prv::Provider *, bool *);
/**
* @brief Signals that a provider was closed
*
* As this is a closure information broadcast, the provider should generally not be accessed, as it could
* result in problems.
*
* @param provider the now-closed provider
*/
EVENT_DEF(EventProviderClosed, prv::Provider *);
/**
* @brief Signals that a provider is being deleted
*
* Provider's data should not be accessed.
*
* @param provider the provider
*/
EVENT_DEF(EventProviderDeleted, prv::Provider *);
}
/* Provider data events definitions */
namespace hex {
/**
* @brief Signals the dirtying of a provider
*
* Any data modification that occurs in a provider dirties it, until its state is either saved or restored.
* This event signals that fact to subscribers so additional code can be executed for certain cases.
*/
EVENT_DEF(EventProviderDirtied, prv::Provider *);
/**
* @brief Signals an insertion of new data into a provider
*
* @param provider the provider
* @param offset the start of the insertion
* @param size the new data's size
*/
EVENT_DEF(EventProviderDataInserted, prv::Provider *, u64, u64);
/**
* @brief Signals a modification in the provider's data
*
* @param provider the provider
* @param offset the data modification's offset (start address)
* @param size the buffer's size
* @param buffer the modified data written at this address
*/
EVENT_DEF(EventProviderDataModified, prv::Provider *, u64, u64, const u8*);
/**
* @brief Signals a removal of some of the provider's data
*
* @param provider the provider
* @param offset the deletion offset (start address)
* @param size the deleted data's size
*/
EVENT_DEF(EventProviderDataRemoved, prv::Provider *, u64, u64);
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include <hex/api/event_manager.hpp>
/* GUI requests definitions */
namespace hex {
/**
* @brief Requests the opening of a new window.
*
* @param name the window's name
*/
EVENT_DEF(RequestOpenWindow, std::string);
/**
* @brief Centralized request to update ImHex's main window title
*
* This request can be called to make ImHex refresh its main window title, taking into account a new project
* or file opened/closed.
*/
EVENT_DEF(RequestUpdateWindowTitle);
/**
* @brief Requests a theme type (light or dark) change
*
* @param themeType either `Light` or `Dark`
*/
EVENT_DEF(RequestChangeTheme, std::string);
/**
* @brief Requests the opening of a popup
*
* @param name the popup's name
*/
EVENT_DEF(RequestOpenPopup, std::string);
}

View File

@@ -0,0 +1,116 @@
#pragma once
#include <hex.hpp>
#include <hex/api/event_manager.hpp>
/* Forward declarations */
namespace pl::ptrn { class Pattern; }
/* Interaction requests definitions */
namespace hex {
/**
* @brief Requests a selection change in the Hex editor
*
* This request is handled by the Hex editor, which proceeds to check if the selection is valid.
* If it is invalid, the Hex editor fires the `EventRegionSelected` event with nullptr region info.
*
* @param region the region that should be selected
*/
EVENT_DEF(RequestHexEditorSelectionChange, ImHexApi::HexEditor::ProviderRegion);
/**
* @brief Requests the Pattern editor to move selection
*
* Requests the Pattern editor to move the cursor's position to reflect the user's click or movement.
*
* @param line the target line
* @param column the target column
*/
EVENT_DEF(RequestPatternEditorSelectionChange, u32, u32);
/**
* @brief Requests a jump to a given pattern
*
* This request is fired by the Hex editor when the user asks to jump to the pattern.
* It is then caught and reflected by the Pattern data component.
*
* @param pattern the pattern to jump to
*/
EVENT_DEF(RequestJumpToPattern, const pl::ptrn::Pattern*);
/**
* @brief Requests to add a bookmark
*
* @param region the region to be bookmarked
* @param name the bookmark's name
* @param comment a comment
* @param color the color
* @param id the bookmark's unique ID
*/
EVENT_DEF(RequestAddBookmark, Region, std::string, std::string, color_t, u64*);
/**
* @brief Requests a bookmark removal
*
* @param id the bookmark's unique ID
*/
EVENT_DEF(RequestRemoveBookmark, u64);
/**
* @brief Request the Pattern editor to set its code
*
* This request allows the rest of ImHex to interface with the Pattern editor component, by setting its code.
* This allows for `.hexpat` file loading, and more.
*
* @param code the code's string
*/
EVENT_DEF(RequestSetPatternLanguageCode, std::string);
/**
* @brief Requests the Pattern editor to run the current code
*
* This is only ever used in the introduction tutorial.
*
* FIXME: the name is misleading, as for now this activates the pattern's auto-evaluation rather than a
* one-off execution
*/
EVENT_DEF(RequestRunPatternCode);
/**
* @brief Request to load a pattern language file
*
* FIXME: this request is unused, as now another component is responsible for pattern file loading.
* This request should be scrapped.
*
* @param path the pattern file's path
*/
EVENT_DEF(RequestLoadPatternLanguageFile, std::fs::path);
/**
* @brief Request to save a pattern language file
*
* FIXME: this request is unused, as now another component is responsible for pattern file saving.
* This request should be scrapped.
*
* @param path the pattern file's path
*/
EVENT_DEF(RequestSavePatternLanguageFile, std::fs::path);
/**
* @brief Requests ImHex to open and process a file
*
* @param path the file's path
*/
EVENT_DEF(RequestOpenFile, std::fs::path);
/**
* @brief Adds a virtual file in the Pattern editor
*
* @param path the file's path
* @param data the file's data
* @param region the impacted region
*/
EVENT_DEF(RequestAddVirtualFile, std::fs::path, std::vector<u8>, Region);
}

View File

@@ -0,0 +1,84 @@
#pragma once
#include <hex.hpp>
#include <hex/api/event_manager.hpp>
/* Lifecycle requests definitions */
namespace hex {
/**
* @brief Emit a request to add an initialization task to the list
*
* These tasks will be executed at startup.
*
* @param name Name of the init task
* @param isAsync Whether the task is asynchronous (true if yes)
* @param callbackFunction The function to call to execute the task
*/
EVENT_DEF(RequestAddInitTask, std::string, bool, std::function<bool()>);
/**
* @brief Emit a request to add an exit task to the list
*
* These tasks will be executed during the exit phase.
*
* FIXME: request is unused and should be scrapped.
*
* @param name Name of the exit task
* @param callbackFunction The function to call to execute the task
*/
EVENT_DEF(RequestAddExitTask, std::string, std::function<bool()>);
/**
* @brief Requests ImHex's graceful shutdown
*
* If there are no questions (bool set to true), ImHex closes immediately.
* If set to false, there is a procedure run to prompt a confirmation to the user.
*
* @param noQuestions true if no questions
*/
EVENT_DEF(RequestCloseImHex, bool);
/**
* @brief Requests ImHex's restart
*
* This event is necessary for ImHex to restart in the main loop for native and web platforms,
* as ImHex cannot simply close and re-open.
*
* This event serves no purpose on Linux, Windows and macOS platforms.
*/
EVENT_DEF(RequestRestartImHex);
/**
* @brief Requests the initialization of theme handlers
*
* This is called during ImGui bootstrapping, and should not be called at any other time.
*/
EVENT_DEF(RequestInitThemeHandlers);
/**
* @brief Requests version and first-startup checks
*
* This request is called during ImHex's startup, and allows ImHex to check if it was updated since last launch.
* It also ensures newcomers (that open ImHex for the first time) are greeted with the tutorial.
*
* FIXME: the name is misleading, as this request does not effectively start any migration. It only executes
* checks about ImHex's version. The name should be changed to reflect this behaviour.
*/
EVENT_DEF(RequestStartMigration);
/**
* @brief Send a subcommand to the main Imhex instance
*
* This request is called to send a subcommand to the main ImHex instance.
* This subcommand will then be executed by a handler when ImHex finishing initializing
* (`EventImHexStartupFinished`).
*
* FIXME: change the name so that it is prefixed with "Request" like every other request.
*
* @param name the subcommand's name
* @param data the subcommand's data
*/
EVENT_DEF(SendMessageToMainInstance, const std::string, const std::vector<u8>&);
}

View File

@@ -0,0 +1,22 @@
#pragma once
#include <hex/api/event_manager.hpp>
/* Provider requests definitions */
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 **);
/**
* @brief Move the data from all PerProvider instances from one provider to another
*
* The 'from' provider should not have any per provider data after this, and should be immediately deleted
*
* FIXME: rename with the "Request" prefix to apply standard naming convention.
*/
EVENT_DEF(MovePerProviderData, prv::Provider *, prv::Provider *);
}

View File

@@ -2,6 +2,8 @@
#include <hex.hpp>
#include <hex/api/localization_manager.hpp>
#include <hex/helpers/semantic_version.hpp>
#include <hex/helpers/fs.hpp>
#include <functional>
#include <optional>
@@ -10,8 +12,7 @@
#include <vector>
#include <map>
#include <set>
#include <wolv/io/fs.hpp>
#include <memory>
using ImGuiID = unsigned int;
struct ImVec2;
@@ -443,6 +444,8 @@ namespace hex {
bool isWindowResizable();
void addAutoResetObject(hex::impl::AutoResetBase *object);
void removeAutoResetObject(hex::impl::AutoResetBase *object);
void cleanup();
}
@@ -492,6 +495,7 @@ namespace hex {
*/
float getNativeScale();
float getBackingScaleFactor();
/**
* @brief Gets the current main window position
@@ -580,6 +584,14 @@ namespace hex {
*/
const std::string& getGLRenderer();
/**
* @brief Checks if ImHex is being run in a "Corporate Environment"
* This function simply checks for common telltale signs such as if the machine is joined a
* domain. It's not super accurate, but it's still useful for statistics
* @return True if it is
*/
bool isCorporateEnvironment();
/**
* @brief Checks if ImHex is running in portable mode
* @return Whether ImHex is running in portable mode
@@ -618,7 +630,7 @@ namespace hex {
* @brief Gets the current ImHex version
* @return ImHex version
*/
std::string getImHexVersion(bool withBuildType = true);
SemanticVersion getImHexVersion();
/**
* @brief Gets the current git commit hash
@@ -695,6 +707,13 @@ namespace hex {
*/
void* getLibImHexModuleHandle();
/**
* Adds a new migration routine that will be executed when upgrading from a lower version than specified in migrationVersion
* @param migrationVersion Upgrade point version
* @param function Function to run
*/
void addMigrationRoutine(SemanticVersion migrationVersion, std::function<void()> function);
}
/**
@@ -736,11 +755,8 @@ namespace hex {
const std::vector<Font>& getFonts();
void setCustomFontPath(const std::fs::path &path);
void setFontSize(float size);
void setFontAtlas(ImFontAtlas *fontAtlas);
std::map<UnlocalizedString, ImFont*>& getFontDefinitions();
void setFonts(ImFont *bold, ImFont *italic);
}
GlyphRange glyph(const char *glyph);
@@ -753,26 +769,8 @@ namespace hex {
constexpr static float DefaultFontSize = 13.0;
ImFont* Bold();
ImFont* Italic();
/**
* @brief Gets the current custom font path
* @return The current custom font path
*/
const std::filesystem::path& getCustomFontPath();
/**
* @brief Gets the current font size
* @return The current font size
*/
float getFontSize();
/**
* @brief Gets the current font atlas
* @return Current font atlas
*/
ImFontAtlas* getFontAtlas();
void registerFont(const UnlocalizedString &fontName);
ImFont* getFont(const UnlocalizedString &fontName);
}

View File

@@ -31,7 +31,7 @@ namespace hex {
}
void loadLanguage(const std::string &language);
void loadLanguage(std::string language);
std::string getLocalizedString(const std::string &unlocalizedString, const std::string &language = "");
[[nodiscard]] const std::map<std::string, std::string> &getSupportedLanguages();
@@ -101,10 +101,9 @@ namespace hex {
public:
UnlocalizedString() = default;
template<typename T>
UnlocalizedString(T &&arg) : m_unlocalizedString(std::forward<T>(arg)) {
static_assert(!std::same_as<std::remove_cvref_t<T>, Lang>, "Expected a unlocalized name, got a localized one!");
}
UnlocalizedString(const std::string &string) : m_unlocalizedString(string) { }
UnlocalizedString(const char *string) : m_unlocalizedString(string) { }
UnlocalizedString(const Lang& arg) = delete;
[[nodiscard]] operator std::string() const {
return m_unlocalizedString;
@@ -149,3 +148,10 @@ namespace hex {
}
}
template<>
struct std::hash<hex::UnlocalizedString> {
std::size_t operator()(const hex::UnlocalizedString &string) const noexcept {
return std::hash<std::string>{}(string.get());
}
};

View File

@@ -15,11 +15,17 @@ struct ImGuiContext;
namespace hex {
struct SubCommand {
enum class Type : u8 {
Option,
SubCommand
};
std::string commandLong;
std::string commandShort;
std::string commandDescription;
std::function<void(const std::vector<std::string>&)> callback;
Type type = Type::Option;
};
struct Feature {

View File

@@ -2,137 +2,25 @@
#include <hex.hpp>
#include <hex/api/localization_manager.hpp>
#include <hex/helpers/keys.hpp>
#include <functional>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <GLFW/glfw3.h>
struct ImGuiWindow;
struct KeyEquivalent {
bool valid;
bool ctrl, opt, cmd, shift;
int key;
};
namespace hex {
class View;
enum class Keys : u32 {
Space = GLFW_KEY_SPACE,
Apostrophe = GLFW_KEY_APOSTROPHE,
Comma = GLFW_KEY_COMMA,
Minus = GLFW_KEY_MINUS,
Period = GLFW_KEY_PERIOD,
Slash = GLFW_KEY_SLASH,
Num0 = GLFW_KEY_0,
Num1 = GLFW_KEY_1,
Num2 = GLFW_KEY_2,
Num3 = GLFW_KEY_3,
Num4 = GLFW_KEY_4,
Num5 = GLFW_KEY_5,
Num6 = GLFW_KEY_6,
Num7 = GLFW_KEY_7,
Num8 = GLFW_KEY_8,
Num9 = GLFW_KEY_9,
Semicolon = GLFW_KEY_SEMICOLON,
Equals = GLFW_KEY_EQUAL,
A = GLFW_KEY_A,
B = GLFW_KEY_B,
C = GLFW_KEY_C,
D = GLFW_KEY_D,
E = GLFW_KEY_E,
F = GLFW_KEY_F,
G = GLFW_KEY_G,
H = GLFW_KEY_H,
I = GLFW_KEY_I,
J = GLFW_KEY_J,
K = GLFW_KEY_K,
L = GLFW_KEY_L,
M = GLFW_KEY_M,
N = GLFW_KEY_N,
O = GLFW_KEY_O,
P = GLFW_KEY_P,
Q = GLFW_KEY_Q,
R = GLFW_KEY_R,
S = GLFW_KEY_S,
T = GLFW_KEY_T,
U = GLFW_KEY_U,
V = GLFW_KEY_V,
W = GLFW_KEY_W,
X = GLFW_KEY_X,
Y = GLFW_KEY_Y,
Z = GLFW_KEY_Z,
LeftBracket = GLFW_KEY_LEFT_BRACKET,
Backslash = GLFW_KEY_BACKSLASH,
RightBracket = GLFW_KEY_RIGHT_BRACKET,
GraveAccent = GLFW_KEY_GRAVE_ACCENT,
World1 = GLFW_KEY_WORLD_1,
World2 = GLFW_KEY_WORLD_2,
Escape = GLFW_KEY_ESCAPE,
Enter = GLFW_KEY_ENTER,
Tab = GLFW_KEY_TAB,
Backspace = GLFW_KEY_BACKSPACE,
Insert = GLFW_KEY_INSERT,
Delete = GLFW_KEY_DELETE,
Right = GLFW_KEY_RIGHT,
Left = GLFW_KEY_LEFT,
Down = GLFW_KEY_DOWN,
Up = GLFW_KEY_UP,
PageUp = GLFW_KEY_PAGE_UP,
PageDown = GLFW_KEY_PAGE_DOWN,
Home = GLFW_KEY_HOME,
End = GLFW_KEY_END,
CapsLock = GLFW_KEY_CAPS_LOCK,
ScrollLock = GLFW_KEY_SCROLL_LOCK,
NumLock = GLFW_KEY_NUM_LOCK,
PrintScreen = GLFW_KEY_PRINT_SCREEN,
Pause = GLFW_KEY_PAUSE,
F1 = GLFW_KEY_F1,
F2 = GLFW_KEY_F2,
F3 = GLFW_KEY_F3,
F4 = GLFW_KEY_F4,
F5 = GLFW_KEY_F5,
F6 = GLFW_KEY_F6,
F7 = GLFW_KEY_F7,
F8 = GLFW_KEY_F8,
F9 = GLFW_KEY_F9,
F10 = GLFW_KEY_F10,
F11 = GLFW_KEY_F11,
F12 = GLFW_KEY_F12,
F13 = GLFW_KEY_F13,
F14 = GLFW_KEY_F14,
F15 = GLFW_KEY_F15,
F16 = GLFW_KEY_F16,
F17 = GLFW_KEY_F17,
F18 = GLFW_KEY_F18,
F19 = GLFW_KEY_F19,
F20 = GLFW_KEY_F20,
F21 = GLFW_KEY_F21,
F22 = GLFW_KEY_F22,
F23 = GLFW_KEY_F23,
F24 = GLFW_KEY_F24,
F25 = GLFW_KEY_F25,
KeyPad0 = GLFW_KEY_KP_0,
KeyPad1 = GLFW_KEY_KP_1,
KeyPad2 = GLFW_KEY_KP_2,
KeyPad3 = GLFW_KEY_KP_3,
KeyPad4 = GLFW_KEY_KP_4,
KeyPad5 = GLFW_KEY_KP_5,
KeyPad6 = GLFW_KEY_KP_6,
KeyPad7 = GLFW_KEY_KP_7,
KeyPad8 = GLFW_KEY_KP_8,
KeyPad9 = GLFW_KEY_KP_9,
KeyPadDecimal = GLFW_KEY_KP_DECIMAL,
KeyPadDivide = GLFW_KEY_KP_DIVIDE,
KeyPadMultiply = GLFW_KEY_KP_MULTIPLY,
KeyPadSubtract = GLFW_KEY_KP_SUBTRACT,
KeyPadAdd = GLFW_KEY_KP_ADD,
KeyPadEnter = GLFW_KEY_KP_ENTER,
KeyPadEqual = GLFW_KEY_KP_EQUAL,
Menu = GLFW_KEY_MENU,
};
class Key {
public:
constexpr Key() = default;
@@ -153,12 +41,7 @@ namespace hex {
constexpr static auto SUPER = Key(static_cast<Keys>(0x0800'0000));
constexpr static auto CurrentView = Key(static_cast<Keys>(0x1000'0000));
constexpr static auto AllowWhileTyping = Key(static_cast<Keys>(0x2000'0000));
#if defined (OS_MACOS)
constexpr static auto CTRLCMD = SUPER;
#else
constexpr static auto CTRLCMD = CTRL;
#endif
constexpr static auto CTRLCMD = Key(static_cast<Keys>(0x4000'0000));
class Shortcut {
public:
@@ -180,6 +63,7 @@ namespace hex {
bool isLocal() const;
std::string toString() const;
KeyEquivalent toKeyEquivalent() const;
const std::set<Key>& getKeys() const;
bool has(Key key) const;
bool matches(const Shortcut &other) const;
@@ -199,10 +83,12 @@ namespace hex {
class ShortcutManager {
public:
using Callback = std::function<void()>;
using EnabledCallback = std::function<bool()>;
struct ShortcutEntry {
Shortcut shortcut;
std::vector<UnlocalizedString> unlocalizedName;
Callback callback;
EnabledCallback enabledCallback;
};
/**
@@ -210,9 +96,10 @@ namespace hex {
* @param shortcut The shortcut to add.
* @param unlocalizedName The unlocalized name of the shortcut
* @param callback The callback to call when the shortcut is triggered.
* @param enabledCallback Callback that's called to check if this shortcut is enabled
*/
static void addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback);
static void addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback);
static void addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
static void addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
/**
* @brief Add a view-specific shortcut. View-specific shortcuts can only be triggered when the specified view is focused.
@@ -220,9 +107,10 @@ namespace hex {
* @param shortcut The shortcut to add.
* @param unlocalizedName The unlocalized name of the shortcut
* @param callback The callback to call when the shortcut is triggered.
* @param enabledCallback Callback that's called to check if this shortcut is enabled
*/
static void addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback);
static void addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback);
static void addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
static void addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
/**
@@ -247,6 +135,14 @@ namespace hex {
*/
static void processGlobals(bool ctrl, bool alt, bool shift, bool super, u32 keyCode);
/**
* @brief Runs the callback of a shortcut as if it was pressed on the keyboard
* @param shortcut Shortcut to run
* @param view View the shortcut belongs to or nullptr to run a global shortcut
* @return True if a callback was executed, false if not
*/
static bool runShortcut(const Shortcut &shortcut, const View *view = nullptr);
/**
* @brief Clear all shortcuts
*/
@@ -255,6 +151,11 @@ namespace hex {
static void resumeShortcuts();
static void pauseShortcuts();
static void enableMacOSMode();
[[nodiscard]] static std::optional<UnlocalizedString> getLastActivatedMenu();
static void resetLastActivatedMenu();
[[nodiscard]] static std::optional<Shortcut> getPreviousShortcut();
[[nodiscard]] static std::vector<ShortcutEntry> getGlobalShortcuts();

View File

@@ -22,7 +22,7 @@ namespace hex {
class Task {
public:
Task() = default;
Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function);
Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function);
Task(const Task&) = delete;
Task(Task &&other) noexcept;
@@ -57,6 +57,7 @@ namespace hex {
void setInterruptCallback(std::function<void()> callback);
[[nodiscard]] bool isBackgroundTask() const;
[[nodiscard]] bool isBlocking() const;
[[nodiscard]] bool isFinished() const;
[[nodiscard]] bool hadException() const;
[[nodiscard]] bool wasInterrupted() const;
@@ -84,6 +85,7 @@ namespace hex {
std::atomic<bool> m_shouldInterrupt = false;
std::atomic<bool> m_background = true;
std::atomic<bool> m_blocking = false;
std::atomic<bool> m_interrupted = false;
std::atomic<bool> m_finished = false;
@@ -162,6 +164,24 @@ namespace hex {
*/
static TaskHolder createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void()> function);
/**
* @brief Creates a new asynchronous task that shows a blocking modal window
* @param unlocalizedName Name of the task
* @param maxValue Maximum value of the task
* @param function Function to be executed
* @return A TaskHolder holding a weak reference to the task
*/
static TaskHolder createBlockingTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function);
/**
* @brief Creates a new asynchronous task that shows a blocking modal window
* @param unlocalizedName Name of the task
* @param maxValue Maximum value of the task
* @param function Function to be executed
* @return A TaskHolder holding a weak reference to the task
*/
static TaskHolder createBlockingTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function);
/**
* @brief Creates a new synchronous task that will execute the given function at the start of the next frame
* @param function Function to be executed
@@ -202,12 +222,13 @@ namespace hex {
static size_t getRunningTaskCount();
static size_t getRunningBackgroundTaskCount();
static size_t getRunningBlockingTaskCount();
static const std::list<std::shared_ptr<Task>>& getRunningTasks();
static void runDeferredCalls();
private:
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function);
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function);
};
}

View File

@@ -67,6 +67,7 @@ namespace hex {
static void reset();
static void setAccentColor(const ImColor &color);
public:
struct ThemeHandler {
@@ -82,6 +83,7 @@ namespace hex {
static const std::map<std::string, ThemeHandler>& getThemeHandlers();
static const std::map<std::string, StyleHandler>& getStyleHandlers();
private:
ThemeManager() = default;
};

View File

@@ -151,6 +151,9 @@ namespace hex {
static void addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString);
static void addInteractiveHelpLink(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, std::string link);
static void setLastItemInteractiveHelpPopup(std::function<void()> callback);
static void setLastItemInteractiveHelpLink(std::string link);
/**
* @brief Draws the tutorial

View File

@@ -24,8 +24,8 @@ namespace hex {
static void removeWorkspace(const std::string &name);
static const auto& getWorkspaces() { return *s_workspaces; }
static const auto& getCurrentWorkspace() { return s_currentWorkspace; }
static const std::map<std::string, Workspace>& getWorkspaces();
static const std::map<std::string, Workspace>::iterator& getCurrentWorkspace();
static void reset();
static void reload();
@@ -34,9 +34,6 @@ namespace hex {
private:
WorkspaceManager() = default;
static AutoReset<std::map<std::string, Workspace>> s_workspaces;
static decltype(s_workspaces)::Type::iterator s_currentWorkspace, s_previousWorkspace, s_workspaceToRemove;
};
}

View File

@@ -1,6 +1,5 @@
#pragma once
#include <hex/api/event_manager.hpp>
#include <hex/api/imhex_api.hpp>
namespace hex {
@@ -24,6 +23,20 @@ namespace hex {
ImHexApi::System::impl::addAutoResetObject(this);
}
AutoReset(const T &value) : AutoReset() {
m_value = value;
m_valid = true;
}
AutoReset(T &&value) noexcept : AutoReset() {
m_value = std::move(value);
m_valid = true;
}
~AutoReset() {
ImHexApi::System::impl::removeAutoResetObject(this);
}
T* operator->() {
return &m_value;
}

View File

@@ -44,4 +44,7 @@ namespace hex::dbg {
}
}
bool debugModeEnabled();
void setDebugModeEnabled(bool enabled);
}

View File

@@ -2,6 +2,7 @@
#include <hex/helpers/fs.hpp>
#include <array>
#include <vector>
namespace hex::paths {
@@ -82,8 +83,9 @@ namespace hex::paths {
const static inline impl::DataPath Nodes("scripts/nodes");
const static inline impl::DataPath Layouts("layouts");
const static inline impl::DataPath Workspaces("workspaces");
const static inline impl::DataPath Disassemblers("disassemblers");
constexpr static inline std::array<const impl::DefaultPath*, 20> All = {
constexpr static inline std::array<const impl::DefaultPath*, 21> All = {
&Config,
&Recent,
@@ -106,6 +108,7 @@ namespace hex::paths {
&Nodes,
&Layouts,
&Workspaces,
&Disassemblers
};
}

View File

@@ -3,6 +3,7 @@
#include <string_view>
#include <fmt/core.h>
#include <fmt/ranges.h>
#include <fmt/ostream.h>
namespace hex {

View File

@@ -12,10 +12,6 @@
#if defined(OS_WEB)
#include <emscripten/fetch.h>
using curl_off_t = long;
#else
#include <curl/curl.h>
#endif
typedef void CURL;
@@ -121,18 +117,18 @@ namespace hex {
static std::string urlDecode(const std::string &input);
protected:
void setDefaultConfig();
void setProgress(float progress) { m_progress = progress; }
bool isCanceled() const { return m_canceled; }
static size_t writeToVector(void *contents, size_t size, size_t nmemb, void *userdata);
static size_t writeToFile(void *contents, size_t size, size_t nmemb, void *userdata);
template<typename T>
Result<T> executeImpl(std::vector<u8> &data);
static size_t writeToVector(void *contents, size_t size, size_t nmemb, void *userdata);
static size_t writeToFile(void *contents, size_t size, size_t nmemb, void *userdata);
static int progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow);
private:
static void checkProxyErrors();
void setDefaultConfig();
private:
#if defined(OS_WEB)

View File

@@ -5,8 +5,6 @@
#include <string>
#include <future>
#include <curl/curl.h>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/fmt.hpp>
@@ -14,14 +12,26 @@
namespace hex {
namespace impl {
void setWriteFunctions(CURL *curl, wolv::io::File &file);
void setWriteFunctions(CURL *curl, std::vector<u8> &data);
void setupFileUpload(CURL *curl, wolv::io::File &file, const std::string &fileName, const std::string &mimeName);
void setupFileUpload(CURL *curl, const std::vector<u8> &data, const std::fs::path &fileName, const std::string &mimeName);
int executeCurl(CURL *curl, const std::string &url, const std::string &method, const std::string &body, std::map<std::string, std::string> &headers);
long getStatusCode(CURL *curl);
std::string getStatusText(int result);
}
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::downloadFile(const std::fs::path &path) {
return std::async(std::launch::async, [this, path] {
std::vector<u8> response;
wolv::io::File file(path, wolv::io::File::Mode::Create);
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToFile);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &file);
impl::setWriteFunctions(m_curl, file);
return this->executeImpl<T>(response);
});
@@ -31,40 +41,12 @@
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(const std::fs::path &path, const std::string &mimeName) {
return std::async(std::launch::async, [this, path, mimeName]{
auto fileName = wolv::util::toUTF8String(path.filename());
curl_mime *mime = curl_mime_init(m_curl);
curl_mimepart *part = curl_mime_addpart(mime);
wolv::io::File file(path, wolv::io::File::Mode::Read);
curl_mime_data_cb(part, file.getSize(),
[](char *buffer, size_t size, size_t nitems, void *arg) -> size_t {
auto handle = static_cast<FILE*>(arg);
return fread(buffer, size, nitems, handle);
},
[](void *arg, curl_off_t offset, int origin) -> int {
auto handle = static_cast<FILE*>(arg);
if (fseek(handle, offset, origin) != 0)
return CURL_SEEKFUNC_CANTSEEK;
else
return CURL_SEEKFUNC_OK;
},
[](void *arg) {
auto handle = static_cast<FILE*>(arg);
fclose(handle);
},
file.getHandle());
curl_mime_filename(part, fileName.c_str());
curl_mime_name(part, mimeName.c_str());
curl_easy_setopt(m_curl, CURLOPT_MIMEPOST, mime);
impl::setupFileUpload(m_curl, file, fileName, mimeName);
std::vector<u8> responseData;
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &responseData);
impl::setWriteFunctions(m_curl, responseData);
return this->executeImpl<T>(responseData);
});
@@ -73,19 +55,10 @@
template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(std::vector<u8> data, const std::string &mimeName, const std::fs::path &fileName) {
return std::async(std::launch::async, [this, data = std::move(data), mimeName, fileName]{
curl_mime *mime = curl_mime_init(m_curl);
curl_mimepart *part = curl_mime_addpart(mime);
curl_mime_data(part, reinterpret_cast<const char *>(data.data()), data.size());
auto fileNameStr = wolv::util::toUTF8String(fileName.filename());
curl_mime_filename(part, fileNameStr.c_str());
curl_mime_name(part, mimeName.c_str());
curl_easy_setopt(m_curl, CURLOPT_MIMEPOST, mime);
impl::setupFileUpload(m_curl, data, fileName, mimeName);
std::vector<u8> responseData;
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &responseData);
impl::setWriteFunctions(m_curl, responseData);
return this->executeImpl<T>(responseData);
});
@@ -96,8 +69,7 @@
return std::async(std::launch::async, [this] {
std::vector<u8> responseData;
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &responseData);
impl::setWriteFunctions(m_curl, responseData);
return this->executeImpl<T>(responseData);
});
@@ -105,43 +77,16 @@
template<typename T>
HttpRequest::Result<T> HttpRequest::executeImpl(std::vector<u8> &data) {
curl_easy_setopt(m_curl, CURLOPT_URL, m_url.c_str());
curl_easy_setopt(m_curl, CURLOPT_CUSTOMREQUEST, m_method.c_str());
setDefaultConfig();
if (!m_body.empty()) {
curl_easy_setopt(m_curl, CURLOPT_POSTFIELDS, m_body.c_str());
std::scoped_lock lock(m_transmissionMutex);
if (auto result = impl::executeCurl(m_curl, m_url, m_method, m_body, m_headers); result != 0) {
log::error("Http request '{0} {1}' failed with error {2}: '{3}'", m_method, m_url, u32(result), impl::getStatusText(result));
checkProxyErrors();
}
curl_slist *headers = nullptr;
headers = curl_slist_append(headers, "Cache-Control: no-cache");
ON_SCOPE_EXIT { curl_slist_free_all(headers); };
for (auto &[key, value] : m_headers) {
std::string header = hex::format("{}: {}", key, value);
headers = curl_slist_append(headers, header.c_str());
}
curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, headers);
{
std::scoped_lock lock(m_transmissionMutex);
auto result = curl_easy_perform(m_curl);
if (result != CURLE_OK){
char *url = nullptr;
curl_easy_getinfo(m_curl, CURLINFO_EFFECTIVE_URL, &url);
log::error("Http request '{0} {1}' failed with error {2}: '{3}'", m_method, url, u32(result), curl_easy_strerror(result));
checkProxyErrors();
return { };
}
}
long statusCode = 0;
curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &statusCode);
return Result<T>(statusCode, { data.begin(), data.end() });
return Result<T>(impl::getStatusCode(m_curl), { data.begin(), data.end() });
}
}

View File

@@ -0,0 +1,124 @@
#pragma once
#if defined(__cplusplus)
enum class Keys {
#else
enum Keys {
#endif
Invalid,
Space,
Apostrophe,
Comma,
Minus,
Period,
Slash,
Num0,
Num1,
Num2,
Num3,
Num4,
Num5,
Num6,
Num7,
Num8,
Num9,
Semicolon,
Equals,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
LeftBracket,
Backslash,
RightBracket,
GraveAccent,
World1,
World2,
Escape,
Enter,
Tab,
Backspace,
Insert,
Delete,
Right,
Left,
Down,
Up,
PageUp,
PageDown,
Home,
End,
CapsLock,
ScrollLock,
NumLock,
PrintScreen,
Pause,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
F13,
F14,
F15,
F16,
F17,
F18,
F19,
F20,
F21,
F22,
F23,
F24,
F25,
KeyPad0,
KeyPad1,
KeyPad2,
KeyPad3,
KeyPad4,
KeyPad5,
KeyPad6,
KeyPad7,
KeyPad8,
KeyPad9,
KeyPadDecimal,
KeyPadDivide,
KeyPadMultiply,
KeyPadSubtract,
KeyPadAdd,
KeyPadEnter,
KeyPadEqual,
Menu
};
enum Keys scanCodeToKey(int scanCode);
int keyToScanCode(enum Keys key);

View File

@@ -9,9 +9,9 @@
#include <map>
#include <span>
#include <string>
#include <numbers>
#include <opengl_support.h>
#include <GLFW/glfw3.h>
#include "imgui.h"
namespace hex::gl {
@@ -188,43 +188,43 @@ namespace hex::gl {
T &getElement(int row,int col) {
return this->mat[row*Columns+col];
return this->mat[row * Columns+col];
}
Vector<T,Rows> getColumn(int col) {
Vector<T,Rows> result;
for (size_t i = 0; i < Rows; i++)
result[i] = this->mat[i*Columns+col];
result[i] = this->mat[i * Columns + col];
return result;
}
Vector<T,Columns> getRow(int row) {
Vector<T,Columns> result;
for (size_t i = 0; i < Columns; i++)
result[i] = this->mat[row*Columns+i];
result[i] = this->mat[row * Columns+i];
return result;
}
void updateRow(int row, Vector<T,Columns> values) {
for (size_t i = 0; i < Columns; i++)
this->mat[row*Columns+i] = values[i];
this->mat[row * Columns + i] = values[i];
}
void updateColumn(int col, Vector<T,Rows> values) {
for (size_t i = 0; i < Rows; i++)
this->mat[i*Columns+col] = values[i];
this->mat[i * Columns + col] = values[i];
}
void updateElement( int row,int col, T value) {
this->mat[row*Columns + col] = value;
void updateElement(int row, int col, T value) {
this->mat[row * Columns + col] = value;
}
T &operator()( const int &row,const int &col) {
return this->mat[row*Columns + col];
T &operator()(const unsigned &row, const unsigned &col) {
return this->mat[row * Columns + col];
}
const T &operator()(const unsigned& row,const unsigned& col ) const {
return this->mat[row*Columns + col];
const T &operator()(const unsigned &row, const unsigned &col) const {
return this->mat[row * Columns + col];
}
Matrix& operator=(const Matrix& A) {
@@ -242,7 +242,7 @@ namespace hex::gl {
for (size_t i = 0; i < Rows; i++)
for (size_t j = 0; j < Columns; j++)
result(i, j) = this->mat[i*Columns+j] + A(i, j);
result(i, j) = this->mat[i * Columns + j] + A(i, j);
return result;
}
@@ -251,7 +251,7 @@ namespace hex::gl {
for (size_t i = 0; i < Rows; i++)
for (size_t j = 0; j < Columns; j++)
result(i, j) = this->mat[i*Columns+j] - A(i, j);
result(i, j) = this->mat[i * Columns + j] - A(i, j);
return result;
}
@@ -268,7 +268,7 @@ namespace hex::gl {
Matrix t(0);
for (size_t i = 0; i < Columns; i++)
for (size_t j = 0; j < Rows; j++)
t.updateElement(i, j, this->mat[j*Rows+i]);
t.updateElement(i, j, this->mat[j * Rows + i]);
return t;
}
@@ -400,8 +400,8 @@ namespace hex::gl {
T Sx, Cx, Sy, Cy, Sz, Cz;
Vector<T,3> angles = ypr;
if(!radians)
angles *= M_PI/180;
if (!radians)
angles *= std::numbers::pi_v<T> / 180;
Sx = -sin(angles[0]); Cx = cos(angles[0]);
Sy = -sin(angles[1]); Cy = cos(angles[1]);
@@ -524,7 +524,7 @@ namespace hex::gl {
Vector<T,3> rotationVector3 = {{rotationVector[0], rotationVector[1], rotationVector[2]}};
T theta = rotationVector3.magnitude();
if (!radians)
theta *= M_PI / 180;
theta *= std::numbers::pi / 180;
Vector<T,3> axis = rotationVector3;
if (theta != 0)
axis = axis.normalize();
@@ -807,16 +807,18 @@ namespace hex::gl {
void bind() const;
void unbind() const;
bool isValid() const { return m_program != 0; }
void setUniform(std::string_view name, const int &value);
void setUniform(std::string_view name, const float &value);
template<size_t N>
void setUniform(std::string_view name, const Vector<float, N> &value) {
if (N == 2)
if constexpr (N == 2)
glUniform2f(getUniformLocation(name), value[0], value[1]);
else if (N == 3)
else if constexpr (N == 3)
glUniform3f(getUniformLocation(name), value[0], value[1], value[2]);
else if (N == 4)
else if constexpr (N == 4)
glUniform4f(getUniformLocation(name), value[0], value[1], value[2],value[3]);
}

View File

@@ -0,0 +1,36 @@
#pragma once
#include <hex.hpp>
#include <compare>
#include <string>
#include <vector>
namespace hex {
class SemanticVersion {
public:
SemanticVersion() = default;
SemanticVersion(std::string version);
SemanticVersion(std::string_view version);
SemanticVersion(const char *version);
std::strong_ordering operator<=>(const SemanticVersion &) const;
bool operator==(const SemanticVersion &other) const;
u32 major() const;
u32 minor() const;
u32 patch() const;
bool nightly() const;
const std::string& buildType() const;
bool isValid() const;
std::string get(bool withBuildType = true) const;
private:
std::vector<std::string> m_parts;
std::string m_buildType;
};
}

View File

@@ -6,17 +6,10 @@
#include <concepts>
#include <type_traits>
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using u128 = __uint128_t;
#include <wolv/types.hpp>
using i8 = std::int8_t;
using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128_t;
using namespace wolv::unsigned_integers;
using namespace wolv::signed_integers;
using color_t = u32;

View File

@@ -26,7 +26,7 @@
#include <hex/helpers/utils_linux.hpp>
#endif
struct ImVec2;
#include <imgui.h>
namespace hex {
@@ -37,7 +37,7 @@ namespace hex {
template<typename T>
[[nodiscard]] std::vector<std::vector<T>> sampleChannels(const std::vector<T> &data, size_t count, size_t channels) {
if (channels == 0) return {};
size_t signalLength = std::max(1.0, double(data.size()) / channels);
size_t signalLength = std::max<double>(1.0, double(data.size()) / channels);
size_t stride = std::max(1.0, double(signalLength) / count);
@@ -109,13 +109,13 @@ namespace hex {
[[nodiscard]] std::wstring utf8ToUtf16(const std::string& utf8);
[[nodiscard]] std::string utf16ToUtf8(const std::wstring& utf16);
[[nodiscard]] constexpr u64 extract(u8 from, u8 to, const std::unsigned_integral auto &value) {
[[nodiscard]] constexpr u64 extract(u8 from, u8 to, const auto &value) {
if (from < to) std::swap(from, to);
using ValueType = std::remove_cvref_t<decltype(value)>;
ValueType mask = (std::numeric_limits<ValueType>::max() >> (((sizeof(value) * 8) - 1) - (from - to))) << to;
return (value & mask) >> to;
return u64((value & mask) >> to);
}
[[nodiscard]] inline u64 extract(u32 from, u32 to, const std::vector<u8> &bytes) {
@@ -278,7 +278,7 @@ namespace hex {
std::string result;
for (i16 bit = hex::bit_width(number) - 1; bit >= 0; bit -= 1)
result += (number & (0b1 << bit)) == 0 ? '0' : '1';
result += (number & (0b1LLU << bit)) == 0 ? '0' : '1';
return result;
}
@@ -340,4 +340,6 @@ namespace hex {
*/
[[nodiscard]] void* getContainingModule(void* symbol);
[[nodiscard]] std::optional<ImColor> blendColors(const std::optional<ImColor> &a, const std::optional<ImColor> &b);
}

View File

@@ -1,5 +1,7 @@
#pragma once
#include <hex/helpers/keys.hpp>
#if defined(OS_MACOS)
struct GLFWwindow;
@@ -17,8 +19,15 @@
void enumerateFontsMacos();
void macosHandleTitlebarDoubleClickGesture(GLFWwindow *window);
void macosSetWindowMovable(GLFWwindow *window, bool movable);
bool macosIsWindowBeingResizedByUser(GLFWwindow *window);
void macosMarkContentEdited(GLFWwindow *window, bool edited = true);
void macosGetKey(Keys key, int *output);
bool macosIsMainInstance();
void macosSendMessageToMainInstance(const unsigned char *data, size_t size);
void macosInstallEventListener();
}
#endif

View File

@@ -13,6 +13,13 @@
#include <wolv/utils/preproc.hpp>
#include <wolv/utils/guards.hpp>
#if defined(_MSC_VER)
#include <windows.h>
#define PLUGIN_ENTRY_POINT extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return TRUE; }
#else
#define PLUGIN_ENTRY_POINT
#endif
namespace {
struct PluginFunctionHelperInstantiation {};
}
@@ -45,7 +52,11 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
#if defined (IMHEX_STATIC_LINK_PLUGINS)
#define IMHEX_PLUGIN_VISIBILITY_PREFIX static
#else
#define IMHEX_PLUGIN_VISIBILITY_PREFIX extern "C" [[gnu::visibility("default")]]
#if defined(_MSC_VER)
#define IMHEX_PLUGIN_VISIBILITY_PREFIX extern "C" __declspec(dllexport)
#else
#define IMHEX_PLUGIN_VISIBILITY_PREFIX extern "C" [[gnu::visibility("default")]]
#endif
#endif
#define IMHEX_FEATURE_ENABLED(feature) WOLV_TOKEN_CONCAT(WOLV_TOKEN_CONCAT(WOLV_TOKEN_CONCAT(IMHEX_PLUGIN_, IMHEX_PLUGIN_NAME), _FEATURE_), feature)
@@ -77,7 +88,7 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
ImGui::SetCurrentContext(ctx); \
GImGui = ctx; \
} \
extern "C" [[gnu::visibility("default")]] void WOLV_TOKEN_CONCAT(forceLinkPlugin_, IMHEX_PLUGIN_NAME)() { \
extern "C" void WOLV_TOKEN_CONCAT(forceLinkPlugin_, IMHEX_PLUGIN_NAME)() { \
hex::PluginManager::addPlugin(name, hex::PluginFunctions { \
nullptr, \
WOLV_TOKEN_CONCAT(initializeLibrary_, IMHEX_PLUGIN_NAME), \
@@ -92,6 +103,7 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
nullptr \
}); \
} \
PLUGIN_ENTRY_POINT \
IMHEX_PLUGIN_VISIBILITY_PREFIX void WOLV_TOKEN_CONCAT(initializeLibrary_, IMHEX_PLUGIN_NAME)()
#define IMHEX_PLUGIN_SETUP_IMPL(name, author, description) \
@@ -112,7 +124,7 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
return PluginSubCommandsFunctionHelper<PluginFunctionHelperInstantiation>::getSubCommands(); \
} \
IMHEX_PLUGIN_VISIBILITY_PREFIX void initializePlugin(); \
extern "C" [[gnu::visibility("default")]] void WOLV_TOKEN_CONCAT(forceLinkPlugin_, IMHEX_PLUGIN_NAME)() { \
extern "C" void WOLV_TOKEN_CONCAT(forceLinkPlugin_, IMHEX_PLUGIN_NAME)() { \
hex::PluginManager::addPlugin(name, hex::PluginFunctions { \
initializePlugin, \
nullptr, \
@@ -127,6 +139,7 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
getFeatures \
}); \
} \
PLUGIN_ENTRY_POINT \
IMHEX_PLUGIN_VISIBILITY_PREFIX void initializePlugin()
/**

View File

@@ -0,0 +1,57 @@
#pragma once
#include <hex.hpp>
#include <hex/api/localization_manager.hpp>
#include <memory>
#include <list>
#include <string>
namespace hex::proj {
class Content {
public:
explicit Content(UnlocalizedString type, std::string name)
: m_type(std::move(type)), m_name(std::move(name)) { }
void setData(std::string data) { m_data = std::move(data); }
const std::string& getData() const { return m_data; }
const std::string& getName() const { return m_name; }
void setName(std::string name) { m_name = std::move(name); }
const UnlocalizedString& getType() const { return m_type; }
bool isOpen() const { return m_open; }
void setOpen(bool open) { m_open = open; }
bool isEmpty() const { return m_data.empty(); }
private:
UnlocalizedString m_type;
std::string m_name;
std::string m_data;
bool m_open = false;
};
class Project {
public:
explicit Project(std::string name) : m_name(std::move(name)) {}
Project(const Project &) = delete;
Project(Project &&) = delete;
~Project();
Project &operator=(const Project &) = delete;
Project &operator=(Project &&) = delete;
const std::string &getName() const { return m_name; }
void addContent(UnlocalizedString type);
const std::list<std::unique_ptr<Content>>& getContents() const { return m_contents; }
private:
std::string m_name;
std::list<std::unique_ptr<Content>> m_contents;
};
}

View File

@@ -0,0 +1,43 @@
#pragma once
#include <hex.hpp>
#include <hex/project/project.hpp>
#include <list>
#include <string>
#include <filesystem>
#include <functional>
namespace hex::proj {
class ProjectManager {
ProjectManager() = default;
public:
static void createProject(std::string name);
static void loadProject(const std::filesystem::path &path);
static void removeProject(const Project &project);
using LoadFunction = std::function<void(const Content&)>;
using StoreFunction = std::function<void(Content&)>;
struct ContentHandler {
UnlocalizedString type;
bool allowMultiple = false;
LoadFunction load;
StoreFunction store;
};
static void registerContentHandler(ContentHandler handler);
static const std::list<ContentHandler>& getContentHandlers();
static const ContentHandler* getContentHandler(const UnlocalizedString &typeName);
static const std::list<std::unique_ptr<Project>> &getProjects();
static void storeContent(Content &content);
static void loadContent(Content &content);
static Content* getLoadedContent(const UnlocalizedString &type);
};
}

View File

@@ -38,7 +38,7 @@ namespace hex::prv {
[[nodiscard]] std::string getName() const override { return m_name; }
[[nodiscard]] std::string getTypeName() const override { return "MemoryProvider"; }
[[nodiscard]] UnlocalizedString getTypeName() const override { return "MemoryProvider"; }
private:
void renameFile();

View File

@@ -30,6 +30,7 @@ namespace hex::prv {
struct MenuEntry {
std::string name;
const char *icon;
std::function<void()> callback;
};
@@ -113,7 +114,7 @@ namespace hex::prv {
* @param size number of bytes to read
* @param overlays apply overlays and patches is true. Same as readRaw() if false
*/
void read(u64 offset, void *buffer, size_t size, bool overlays = true);
virtual void read(u64 offset, void *buffer, size_t size, bool overlays = true);
/**
* @brief Write data to the patches of this provider. Will not directly modify provider.
@@ -121,7 +122,7 @@ namespace hex::prv {
* @param buffer buffer to take data to write from
* @param size number of bytes to write
*/
void write(u64 offset, const void *buffer, size_t size);
virtual void write(u64 offset, const void *buffer, size_t size);
/**
* @brief Read data from this provider, without applying overlays and patches
@@ -151,7 +152,7 @@ namespace hex::prv {
* like "hex.builtin.provider.mem_file" or "hex.builtin.provider.file"
* @return The provider's type name
*/
[[nodiscard]] virtual std::string getTypeName() const = 0;
[[nodiscard]] virtual UnlocalizedString getTypeName() const = 0;
/**
* @brief Gets a human readable representation of the current provider
@@ -193,11 +194,11 @@ namespace hex::prv {
[[nodiscard]] virtual std::vector<Description> getDataDescription() const;
[[nodiscard]] virtual std::variant<std::string, i128> queryInformation(const std::string &category, const std::string &argument);
void undo();
void redo();
virtual void undo();
virtual void redo();
[[nodiscard]] bool canUndo() const;
[[nodiscard]] bool canRedo() const;
[[nodiscard]] virtual bool canUndo() const;
[[nodiscard]] virtual bool canRedo() const;
[[nodiscard]] virtual bool hasFilePicker() const;
virtual bool handleFilePicker();
@@ -231,7 +232,7 @@ namespace hex::prv {
return m_undoRedoStack.add<T>(std::forward<decltype(args)...>(args)...);
}
[[nodiscard]] undo::Stack& getUndoStack() { return m_undoRedoStack; }
[[nodiscard]] virtual undo::Stack& getUndoStack() { return m_undoRedoStack; }
protected:
u32 m_currPage = 0;

View File

@@ -1,7 +1,10 @@
#pragma once
#include <hex/api/imhex_api.hpp>
#include <hex/api/event_manager.hpp>
#include <hex/api/events/events_provider.hpp>
#include <hex/api/events/events_lifecycle.hpp>
#include <hex/api/events/requests_provider.hpp>
#include <map>
#include <ranges>

View File

@@ -2,7 +2,7 @@
#include <hex.hpp>
#include <hex/api/localization_manager.hpp>
#include <hex/api/event_manager.hpp>
#include <hex/api/events/events_interaction.hpp>
#include <hex/providers/undo_redo/operations/operation.hpp>

View File

@@ -47,7 +47,7 @@ namespace hex::test {
return m_data->size();
}
[[nodiscard]] std::string getTypeName() const override { return "hex.test.provider.test"; }
[[nodiscard]] UnlocalizedString getTypeName() const override { return "hex.test.provider.test"; }
bool open() override { return true; }
void close() override { }

View File

@@ -0,0 +1,57 @@
#pragma once
#include <hex.hpp>
#include <imgui.h>
#include <imgui_internal.h>
#include <hex/helpers/utils.hpp>
#include <list>
#include <memory>
#include <mutex>
#include "hex/api/localization_manager.hpp"
namespace hex {
namespace impl {
class BannerBase {
public:
BannerBase(ImColor color) : m_color(color) {}
virtual ~BannerBase() = default;
virtual void draw() { drawContent(); }
virtual void drawContent() = 0;
[[nodiscard]] static std::list<std::unique_ptr<BannerBase>> &getOpenBanners();
[[nodiscard]] const ImColor& getColor() const {
return m_color;
}
void close() { m_shouldClose = true; }
[[nodiscard]] bool shouldClose() const { return m_shouldClose; }
protected:
static std::mutex& getMutex();
bool m_shouldClose = false;
ImColor m_color;
};
}
template<typename T>
class Banner : public impl::BannerBase {
public:
using impl::BannerBase::BannerBase;
template<typename ...Args>
static void open(Args && ... args) {
std::lock_guard lock(getMutex());
auto toast = std::make_unique<T>(std::forward<Args>(args)...);
getOpenBanners().emplace_back(std::move(toast));
}
};
}

View File

@@ -79,17 +79,16 @@ namespace ImGuiExt {
Texture(const Texture&) = delete;
Texture(Texture&& other) noexcept;
static Texture fromImage(const ImU8 *buffer, int size, Filter filter = Filter::Nearest);
static Texture fromImage(std::span<const std::byte> buffer, Filter filter = Filter::Nearest);
static Texture fromImage(const char *path, Filter filter = Filter::Nearest);
static Texture fromImage(const std::fs::path &path, Filter filter = Filter::Nearest);
static Texture fromGLTexture(unsigned int texture, int width, int height);
static Texture fromBitmap(const ImU8 *buffer, int size, int width, int height, Filter filter = Filter::Nearest);
static Texture fromBitmap(std::span<const std::byte> buffer, int width, int height, Filter filter = Filter::Nearest);
static Texture fromSVG(const char *path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
static Texture fromSVG(const std::fs::path &path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
static Texture fromSVG(std::span<const std::byte> buffer, int width = 0, int height = 0, Filter filter = Filter::Nearest);
[[nodiscard]] static Texture fromImage(const ImU8 *buffer, int size, Filter filter = Filter::Nearest);
[[nodiscard]] static Texture fromImage(std::span<const std::byte> buffer, Filter filter = Filter::Nearest);
[[nodiscard]] static Texture fromImage(const char *path, Filter filter = Filter::Nearest);
[[nodiscard]] static Texture fromImage(const std::fs::path &path, Filter filter = Filter::Nearest);
[[nodiscard]] static Texture fromGLTexture(unsigned int texture, int width, int height);
[[nodiscard]] static Texture fromBitmap(const ImU8 *buffer, int size, int width, int height, Filter filter = Filter::Nearest);
[[nodiscard]] static Texture fromBitmap(std::span<const std::byte> buffer, int width, int height, Filter filter = Filter::Nearest);
[[nodiscard]] static Texture fromSVG(const char *path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
[[nodiscard]] static Texture fromSVG(const std::fs::path &path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
[[nodiscard]] static Texture fromSVG(std::span<const std::byte> buffer, int width = 0, int height = 0, Filter filter = Filter::Nearest);
~Texture();
@@ -114,6 +113,8 @@ namespace ImGuiExt {
return float(m_width) / float(m_height);
}
void reset();
private:
ImTextureID m_textureId = 0;
int m_width = 0, m_height = 0;
@@ -144,13 +145,13 @@ namespace ImGuiExt {
bool TitleBarButton(const char *label, ImVec2 size_arg);
bool ToolBarButton(const char *symbol, ImVec4 color);
bool IconButton(const char *symbol, ImVec4 color, ImVec2 size_arg = ImVec2(0, 0));
bool IconButton(const char *symbol, ImVec4 color, ImVec2 size_arg = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
bool InputIntegerPrefix(const char* label, const char *prefix, void *value, ImGuiDataType type, const char *format, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
bool InputHexadecimal(const char* label, u32 *value, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
bool InputHexadecimal(const char* label, u64 *value, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
bool SliderBytes(const char *label, u64 *value, u64 min, u64 max, ImGuiSliderFlags flags = ImGuiSliderFlags_None);
bool SliderBytes(const char *label, u64 *value, u64 min, u64 max, u64 stepSize = 1, ImGuiSliderFlags flags = ImGuiSliderFlags_None);
inline bool HasSecondPassed() {
return static_cast<ImU32>(ImGui::GetTime() * 100) % 100 <= static_cast<ImU32>(ImGui::GetIO().DeltaTime * 100);
@@ -158,6 +159,8 @@ namespace ImGuiExt {
void OpenPopupInWindow(const char *window_name, const char *popup_name);
void DisableWindowResize(ImGuiDir dir);
struct ImHexCustomData {
ImVec4 Colors[ImGuiCustomCol_COUNT];
@@ -183,7 +186,7 @@ namespace ImGuiExt {
void StyleCustomColorsLight();
void StyleCustomColorsClassic();
void SmallProgressBar(float fraction, float yOffset = 0.0F);
void ProgressBar(float fraction, ImVec2 size_value = ImVec2(0, 0), float yOffset = 0.0F);
inline void TextFormatted(std::string_view fmt, auto &&...args) {
if constexpr (sizeof...(args) == 0) {
@@ -200,14 +203,15 @@ namespace ImGuiExt {
ImGui::PushID(text.c_str());
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2());
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::InputText("##", const_cast<char *>(text.c_str()), text.size(), ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoHorizontalScroll);
ImGui::InputText("##", const_cast<char *>(text.c_str()), text.size() + 1, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoHorizontalScroll);
ImGui::PopItemWidth();
ImGui::PopStyleColor();
ImGui::PopStyleVar();
ImGui::PopStyleVar(2);
ImGui::PopID();
}
@@ -235,29 +239,32 @@ namespace ImGuiExt {
inline void TextFormattedWrappedSelectable(std::string_view fmt, auto &&...args) {
// 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::wrapMonospacedString(
auto text = wolv::util::trim(wolv::util::wrapMonospacedString(
hex::format(fmt, std::forward<decltype(args)>(args)...),
ImGui::CalcTextSize("M").x,
ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize - ImGui::GetStyle().FrameBorderSize
);
));
auto textSize = ImGui::CalcTextSize(text.c_str());
ImGui::PushID(text.c_str());
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2());
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::InputTextMultiline(
"##",
const_cast<char *>(text.c_str()),
text.size(),
ImVec2(0, -FLT_MIN),
text.size() + 1,
ImVec2(0, textSize.y),
ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoHorizontalScroll
);
ImGui::PopItemWidth();
ImGui::PopStyleColor();
ImGui::PopStyleVar();
ImGui::PopStyleVar(2);
ImGui::PopID();
}
@@ -291,8 +298,8 @@ namespace ImGuiExt {
bool BitCheckbox(const char* label, bool* v);
bool DimmedButton(const char* label, ImVec2 size = ImVec2(0, 0));
bool DimmedIconButton(const char *symbol, ImVec4 color, ImVec2 size = ImVec2(0, 0));
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size);
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);

View File

@@ -8,7 +8,6 @@
#include <hex/api/imhex_api.hpp>
#include <hex/api/shortcut_manager.hpp>
#include <hex/api/event_manager.hpp>
#include <hex/api/localization_manager.hpp>
#include <hex/providers/provider.hpp>
@@ -99,6 +98,14 @@ namespace hex {
[[nodiscard]] static std::string toWindowName(const UnlocalizedString &unlocalizedName);
[[nodiscard]] bool isFocused() const { return m_focused; }
/**
* @brief Used for focus handling. Don't use this directly
* @param focused Whether this view is focused
*/
void setFocused(bool focused) { m_focused = focused; }
public:
class Window;
class Special;
@@ -111,6 +118,7 @@ namespace hex {
std::map<Shortcut, ShortcutManager::ShortcutEntry> m_shortcuts;
bool m_windowJustOpened = false;
const char *m_icon;
bool m_focused = false;
friend class ShortcutManager;
};
@@ -175,7 +183,7 @@ namespace hex {
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
if (ImGui::BeginPopupModal(View::toWindowName(this->getUnlocalizedName()).c_str(), this->hasCloseButton() ? &this->getWindowOpenState() : nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize | this->getWindowFlags())) {
if (ImGui::BeginPopupModal(View::toWindowName(this->getUnlocalizedName()).c_str(), this->hasCloseButton() ? &this->getWindowOpenState() : nullptr, ImGuiWindowFlags_NoCollapse | this->getWindowFlags())) {
this->drawContent();
ImGui::EndPopup();

View File

@@ -1,20 +1,24 @@
#include <hex/api/achievement_manager.hpp>
#include <hex/api/event_manager.hpp>
#include <hex/api/events/events_interaction.hpp>
#include <hex/helpers/auto_reset.hpp>
#include <hex/helpers/default_paths.hpp>
#include <nlohmann/json.hpp>
#if defined(OS_WEB)
#include <emscripten.h>
#endif
namespace hex {
static AutoReset<std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>>> s_achievements;
const std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>> &AchievementManager::getAchievements() {
static AutoReset<std::unordered_map<UnlocalizedString, std::unordered_map<UnlocalizedString, std::unique_ptr<Achievement>>>> s_achievements;
const std::unordered_map<UnlocalizedString, std::unordered_map<UnlocalizedString, std::unique_ptr<Achievement>>> &AchievementManager::getAchievements() {
return *s_achievements;
}
static AutoReset<std::unordered_map<std::string, std::list<AchievementManager::AchievementNode>>> s_nodeCategoryStorage;
std::unordered_map<std::string, std::list<AchievementManager::AchievementNode>>& getAchievementNodesMutable(bool rebuild) {
static AutoReset<std::unordered_map<UnlocalizedString, std::list<AchievementManager::AchievementNode>>> s_nodeCategoryStorage;
std::unordered_map<UnlocalizedString, std::list<AchievementManager::AchievementNode>>& getAchievementNodesMutable(bool rebuild) {
if (!s_nodeCategoryStorage->empty() || !rebuild)
return s_nodeCategoryStorage;
@@ -32,12 +36,12 @@ namespace hex {
return s_nodeCategoryStorage;
}
const std::unordered_map<std::string, std::list<AchievementManager::AchievementNode>>& AchievementManager::getAchievementNodes(bool rebuild) {
const std::unordered_map<UnlocalizedString, std::list<AchievementManager::AchievementNode>>& AchievementManager::getAchievementNodes(bool rebuild) {
return getAchievementNodesMutable(rebuild);
}
static AutoReset<std::unordered_map<std::string, std::vector<AchievementManager::AchievementNode*>>> s_startNodes;
const std::unordered_map<std::string, std::vector<AchievementManager::AchievementNode*>>& AchievementManager::getAchievementStartNodes(bool rebuild) {
static AutoReset<std::unordered_map<UnlocalizedString, std::vector<AchievementManager::AchievementNode*>>> s_startNodes;
const std::unordered_map<UnlocalizedString, std::vector<AchievementManager::AchievementNode*>>& AchievementManager::getAchievementStartNodes(bool rebuild) {
if (!s_startNodes->empty() || !rebuild)
return s_startNodes;
@@ -183,10 +187,10 @@ namespace hex {
const auto &category = newAchievement->getUnlocalizedCategory();
const auto &name = newAchievement->getUnlocalizedName();
auto [categoryIter, categoryInserted] = s_achievements->insert({ category, std::unordered_map<std::string, std::unique_ptr<Achievement>>{} });
auto [categoryIter, categoryInserted] = s_achievements->insert({ category, std::unordered_map<UnlocalizedString, std::unique_ptr<Achievement>>{} });
auto &[categoryKey, achievements] = *categoryIter;
auto [achievementIter, achievementInserted] = achievements.insert({ name, std::move(newAchievement) });
auto [achievementIter, achievementInserted] = achievements.emplace(name, std::move(newAchievement));
auto &[achievementKey, achievement] = *achievementIter;
achievementAdded();
@@ -215,7 +219,16 @@ namespace hex {
}
try {
auto json = nlohmann::json::parse(file.readString());
#if defined(OS_WEB)
auto data = (char *) MAIN_THREAD_EM_ASM_INT({
let data = localStorage.getItem("achievements");
return data ? stringToNewUTF8(data) : null;
});
#else
auto data = file.readString();
#endif
auto json = nlohmann::json::parse(data);
for (const auto &[categoryName, achievements] : getAchievements()) {
for (const auto &[achievementName, achievement] : achievements) {
@@ -226,7 +239,7 @@ namespace hex {
achievement->setProgress(progress);
} catch (const std::exception &e) {
log::warn("Failed to load achievement progress for '{}::{}': {}", categoryName, achievementName, e.what());
log::warn("Failed to load achievement progress for '{}::{}': {}", categoryName.get(), achievementName.get(), e.what());
}
}
}
@@ -254,16 +267,23 @@ namespace hex {
if (json.empty())
return;
for (const auto &directory : paths::Config.write()) {
auto path = directory / AchievementsFile;
#if defined(OS_WEB)
auto data = json.dump();
MAIN_THREAD_EM_ASM({
localStorage.setItem("achievements", UTF8ToString($0));
}, data.c_str());
#else
for (const auto &directory : paths::Config.write()) {
auto path = directory / AchievementsFile;
wolv::io::File file(path, wolv::io::File::Mode::Create);
if (!file.isValid())
continue;
wolv::io::File file(path, wolv::io::File::Mode::Create);
if (!file.isValid())
continue;
file.writeString(json.dump(4));
break;
}
file.writeString(json.dump(4));
break;
}
#endif
}
}

View File

@@ -1,5 +1,6 @@
#include <hex/api/content_registry.hpp>
#include <hex/api/shortcut_manager.hpp>
#include <hex/api/events/requests_provider.hpp>
#include <hex/helpers/fs.hpp>
#include <hex/helpers/logger.hpp>
@@ -32,12 +33,40 @@ namespace hex {
namespace impl {
struct OnChange {
u32 id;
u64 id;
OnChangeCallback callback;
};
static AutoReset<std::map<std::string, std::map<std::string, std::vector<OnChange>>>> s_onChangeCallbacks;
static void runAllOnChangeCallbacks() {
for (const auto &[category, rest] : *impl::s_onChangeCallbacks) {
for (const auto &[name, callbacks] : rest) {
for (const auto &[id, callback] : callbacks) {
try {
callback(getSetting(category, name, {}));
} catch (const std::exception &e) {
log::error("Failed to load setting [{}/{}]: {}", category, name, e.what());
}
}
}
}
}
void runOnChangeHandlers(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const nlohmann::json &value) {
if (auto categoryIt = s_onChangeCallbacks->find(unlocalizedCategory); categoryIt != s_onChangeCallbacks->end()) {
if (auto nameIt = categoryIt->second.find(unlocalizedName); nameIt != categoryIt->second.end()) {
for (const auto &[id, callback] : nameIt->second) {
try {
callback(value);
} catch (const nlohmann::json::exception &e) {
log::error("Failed to run onChange handler for setting {}/{}: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
}
}
}
}
}
static AutoReset<nlohmann::json> s_settings;
const nlohmann::json& getSettingsData() {
return s_settings;
@@ -72,24 +101,28 @@ namespace hex {
s_settings = nlohmann::json::parse(data);
}
for (const auto &[category, rest] : *impl::s_onChangeCallbacks) {
for (const auto &[name, callbacks] : rest) {
for (const auto &[id, callback] : callbacks) {
try {
callback(getSetting(category, name, {}));
} catch (const std::exception &e) {
log::error("Failed to load setting [{}/{}]: {}", category, name, e.what());
}
}
}
}
runAllOnChangeCallbacks();
}
void store() {
auto data = s_settings->dump();
if (!s_settings.isValid())
return;
const auto &settingsData = *s_settings;
// During a crash settings can be empty, causing them to be overwritten.
if (settingsData.empty()) {
return;
}
const auto result = settingsData.dump(4);
if (result.empty()) {
return;
}
MAIN_THREAD_EM_ASM({
localStorage.setItem("config", UTF8ToString($0));
}, data.c_str());
}, result.c_str());
}
void clear() {
@@ -115,17 +148,7 @@ namespace hex {
if (!loaded)
store();
for (const auto &[category, rest] : *impl::s_onChangeCallbacks) {
for (const auto &[name, callbacks] : rest) {
for (const auto &[id, callback] : callbacks) {
try {
callback(getSetting(category, name, {}));
} catch (const std::exception &e) {
log::error("Failed to load setting [{}/{}]: {}", category, name, e.what());
}
}
}
}
runAllOnChangeCallbacks();
}
void store() {
@@ -135,7 +158,7 @@ namespace hex {
const auto &settingsData = *s_settings;
// During a crash settings can be empty, causing them to be overwritten.
if (settingsData.empty()) {
if (s_settings->empty()) {
return;
}
@@ -201,6 +224,8 @@ namespace hex {
log::error("Failed to load setting [{} / {}]: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
}
});
runOnChangeHandlers(unlocalizedCategory, unlocalizedName, getSetting(unlocalizedCategory, unlocalizedName, entry->widget->store()));
}
return entry->widget.get();
@@ -210,20 +235,6 @@ namespace hex {
hex::log::error("Failed to read setting {}/{}: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
}
void runOnChangeHandlers(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const nlohmann::json &value) {
if (auto categoryIt = s_onChangeCallbacks->find(unlocalizedCategory); categoryIt != s_onChangeCallbacks->end()) {
if (auto nameIt = categoryIt->second.find(unlocalizedName); nameIt != categoryIt->second.end()) {
for (const auto &[id, callback] : nameIt->second) {
try {
callback(value);
} catch (const nlohmann::json::exception &e) {
log::error("Failed to run onChange handler for setting {}/{}: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
}
}
}
}
}
}
void setCategoryDescription(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedDescription) {
@@ -325,7 +336,7 @@ namespace hex {
bool SliderDataSize::draw(const std::string &name) {
return ImGuiExt::SliderBytes(name.c_str(), &m_value, m_min, m_max);
return ImGuiExt::SliderBytes(name.c_str(), &m_value, m_min, m_max, m_stepSize);
}
void SliderDataSize::load(const nlohmann::json &data) {
@@ -341,17 +352,34 @@ namespace hex {
}
ColorPicker::ColorPicker(ImColor defaultColor) {
m_value = {
defaultColor.Value.x,
defaultColor.Value.y,
defaultColor.Value.z,
defaultColor.Value.w
ColorPicker::ColorPicker(ImColor defaultColor, ImGuiColorEditFlags flags) {
m_defaultValue = m_value = {
defaultColor.Value.x,
defaultColor.Value.y,
defaultColor.Value.z,
defaultColor.Value.w
};
m_flags = flags;
}
bool ColorPicker::draw(const std::string &name) {
return ImGui::ColorEdit4(name.c_str(), m_value.data(), ImGuiColorEditFlags_NoInputs);
ImGui::PushID(name.c_str());
auto result = ImGui::ColorEdit4("##color_picker", m_value.data(), ImGuiColorEditFlags_NoInputs | m_flags);
ImGui::SameLine();
if (ImGui::Button("X", ImGui::GetStyle().FramePadding * 2 + ImVec2(ImGui::GetTextLineHeight(), ImGui::GetTextLineHeight()))) {
m_value = m_defaultValue;
result = true;
}
ImGui::SameLine();
ImGui::TextUnformatted(name.c_str());
ImGui::PopID();
return result;
}
void ColorPicker::load(const nlohmann::json &data) {
@@ -377,7 +405,7 @@ namespace hex {
bool DropDown::draw(const std::string &name) {
auto preview = "";
if (static_cast<size_t>(m_value) < m_items.size())
preview = m_items[m_value].c_str();
preview = m_items[m_value].get().c_str();
bool changed = false;
if (ImGui::BeginCombo(name.c_str(), Lang(preview))) {
@@ -630,7 +658,7 @@ namespace hex {
}
runtime.addDefine("__IMHEX__");
runtime.addDefine("__IMHEX_VERSION__", ImHexApi::System::getImHexVersion());
runtime.addDefine("__IMHEX_VERSION__", ImHexApi::System::getImHexVersion().get());
}
void addPragma(const std::string &name, const pl::api::PragmaHandler &handler) {
@@ -686,15 +714,15 @@ namespace hex {
namespace impl {
static AutoReset<std::map<std::string, std::unique_ptr<View>>> s_views;
const std::map<std::string, std::unique_ptr<View>>& getEntries() {
static AutoReset<std::map<UnlocalizedString, std::unique_ptr<View>>> s_views;
const std::map<UnlocalizedString, std::unique_ptr<View>>& getEntries() {
return *s_views;
}
void add(std::unique_ptr<View> &&view) {
log::debug("Registered new view: {}", view->getUnlocalizedName().get());
s_views->insert({ view->getUnlocalizedName(), std::move(view) });
s_views->emplace(view->getUnlocalizedName(), std::move(view));
}
}
@@ -708,6 +736,15 @@ namespace hex {
return nullptr;
}
View* getFocusedView() {
for (const auto &[unlocalizedName, view] : *impl::s_views) {
if (view->isFocused())
return view.get();
}
return nullptr;
}
}
namespace ContentRegistry::Tools {
@@ -752,6 +789,14 @@ namespace hex {
impl::s_entries->push_back({ unlocalizedName, requiredSize, maxSize, std::move(displayGeneratorFunction), std::move(editingFunction) });
}
void drawMenuItems(const std::function<void()> &function) {
if (ImGui::BeginPopup("##DataInspectorRowContextMenu")) {
function();
ImGui::Separator();
ImGui::EndPopup();
}
}
}
namespace ContentRegistry::DataProcessorNode {
@@ -917,17 +962,10 @@ namespace hex {
});
if (shortcut != Shortcut::None) {
auto callbackIfEnabled = [enabledCallback, function]{ if (enabledCallback()) { function(); } };
const auto unlocalizedShortcutName =
unlocalizedMainMenuNames.size() == 1 ?
std::vector { unlocalizedMainMenuNames.back() } :
std::vector(unlocalizedMainMenuNames.begin() + 1, unlocalizedMainMenuNames.end());
if (shortcut.isLocal() && view != nullptr)
ShortcutManager::addShortcut(view, shortcut, unlocalizedShortcutName, callbackIfEnabled);
ShortcutManager::addShortcut(view, shortcut, unlocalizedMainMenuNames, function, enabledCallback);
else
ShortcutManager::addGlobalShortcut(shortcut, unlocalizedShortcutName, callbackIfEnabled);
ShortcutManager::addGlobalShortcut(shortcut, unlocalizedMainMenuNames, function, enabledCallback);
}
}
@@ -1097,7 +1135,9 @@ namespace hex {
namespace ContentRegistry::HexEditor {
const int DataVisualizer::TextInputFlags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoHorizontalScroll | ImGuiInputTextFlags_AlwaysOverwrite;
int DataVisualizer::DefaultTextInputFlags() {
return ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoHorizontalScroll | ImGuiInputTextFlags_AlwaysOverwrite;
}
bool DataVisualizer::drawDefaultScalarEditingTextBox(u64 address, const char *format, ImGuiDataType dataType, u8 *data, ImGuiInputTextFlags flags) const {
struct UserData {
@@ -1115,7 +1155,7 @@ namespace hex {
};
ImGui::PushID(reinterpret_cast<void*>(address));
ImGuiExt::InputScalarCallback("##editing_input", dataType, data, format, flags | TextInputFlags | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int {
ImGuiExt::InputScalarCallback("##editing_input", dataType, data, format, flags | DefaultTextInputFlags() | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int {
auto &userData = *static_cast<UserData*>(data->UserData);
if (data->CursorPos >= userData.maxChars)
@@ -1146,7 +1186,7 @@ namespace hex {
};
ImGui::PushID(reinterpret_cast<void*>(address));
ImGui::InputText("##editing_input", data.data(), data.size() + 1, flags | TextInputFlags | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int {
ImGui::InputText("##editing_input", data.data(), data.size() + 1, flags | DefaultTextInputFlags() | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int {
auto &userData = *static_cast<UserData*>(data->UserData);
userData.data->resize(data->BufSize);
@@ -1391,4 +1431,23 @@ namespace hex {
}
namespace ContentRegistry::Disassembler {
namespace impl {
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;
}
}
}
}

View File

@@ -1,6 +1,13 @@
#include <hex/api/imhex_api.hpp>
#include <hex/api/event_manager.hpp>
#include <hex/api/events/events_provider.hpp>
#include <hex/api/events/events_lifecycle.hpp>
#include <hex/api/events/events_gui.hpp>
#include <hex/api/events/requests_interaction.hpp>
#include <hex/api/events/requests_lifecycle.hpp>
#include <hex/api/events/requests_provider.hpp>
#include <hex/api/events/requests_gui.hpp>
#include <hex/api/task_manager.hpp>
#include <hex/helpers/fmt.hpp>
#include <hex/helpers/utils.hpp>
@@ -11,6 +18,7 @@
#include <wolv/utils/string.hpp>
#include <utility>
#include <numeric>
#include <imgui.h>
#include <imgui_internal.h>
@@ -18,13 +26,20 @@
#include <algorithm>
#include <GLFW/glfw3.h>
#include <hex/helpers/utils_macos.hpp>
#if defined(OS_WINDOWS)
#include <windows.h>
#include <DSRole.h>
#else
#include <sys/utsname.h>
#include <unistd.h>
#endif
#if defined(OS_WEB)
#include <emscripten.h>
#endif
namespace hex {
@@ -447,7 +462,7 @@ namespace hex {
if (s_providers->empty())
EventProviderChanged::post(provider, nullptr);
EventProviderClosed::post(it->get());
EventProviderClosed::post(providerToRemove);
RequestUpdateWindowTitle::post();
// Do the destruction of the provider in the background once all tasks have finished
@@ -559,13 +574,22 @@ namespace hex {
return s_windowResizable;
}
static std::vector<hex::impl::AutoResetBase*> s_autoResetObjects;
static auto& getAutoResetObjects() {
static std::set<hex::impl::AutoResetBase*> autoResetObjects;
return autoResetObjects;
}
void addAutoResetObject(hex::impl::AutoResetBase *object) {
s_autoResetObjects.emplace_back(object);
getAutoResetObjects().insert(object);
}
void removeAutoResetObject(hex::impl::AutoResetBase *object) {
getAutoResetObjects().erase(object);
}
void cleanup() {
for (const auto &object : s_autoResetObjects)
for (const auto &object : getAutoResetObjects())
object->reset();
}
@@ -608,6 +632,28 @@ namespace hex {
return impl::s_nativeScale;
}
float getBackingScaleFactor() {
#if defined(OS_WINDOWS)
return 1.0F;
#elif defined(OS_MACOS)
return ::getBackingScaleFactor();
#elif defined(OS_LINUX)
const auto sessionType = hex::getEnvironmentVariable("XDG_SESSION_TYPE");
if (!sessionType.has_value() || sessionType == "x11")
return 1.0F;
else {
float xScale = 0, yScale = 0;
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &xScale, &yScale);
return std::midpoint(xScale, yScale);
}
#elif defined(OS_WEB)
return 1.0F;
#else
return 1.0F;
#endif
}
ImVec2 getMainWindowPosition() {
if ((ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) != ImGuiConfigFlags_None)
@@ -645,6 +691,14 @@ namespace hex {
return hex::getContainingModule(reinterpret_cast<void*>(&getLibImHexModuleHandle));
}
void addMigrationRoutine(SemanticVersion migrationVersion, std::function<void()> function) {
EventImHexUpdated::subscribe([migrationVersion, function](const SemanticVersion &oldVersion, const SemanticVersion &newVersion) {
if (oldVersion < migrationVersion && newVersion >= migrationVersion) {
function();
}
});
}
const std::map<std::string, std::string>& getInitArguments() {
return *impl::s_initArguments;
@@ -689,6 +743,27 @@ namespace hex {
return impl::s_glRenderer;
}
bool isCorporateEnvironment() {
#if defined(OS_WINDOWS)
{
DSROLE_PRIMARY_DOMAIN_INFO_BASIC * info;
if ((DsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic, (PBYTE *)&info) == ERROR_SUCCESS) && (info != nullptr))
{
bool result = std::wstring(info->DomainNameFlat).empty();
DsRoleFreeMemory(info);
return result;
} else {
DWORD size = 1024;
::GetComputerNameExA(ComputerNameDnsDomain, nullptr, &size);
return size > 0;
}
}
#else
return false;
#endif
}
bool isPortableVersion() {
static std::optional<bool> portable;
if (portable.has_value())
@@ -794,16 +869,11 @@ namespace hex {
return { { name, version } };
}
std::string getImHexVersion(bool withBuildType) {
SemanticVersion getImHexVersion() {
#if defined IMHEX_VERSION
if (withBuildType) {
return IMHEX_VERSION;
} else {
auto version = std::string(IMHEX_VERSION);
return version.substr(0, version.find('-'));
}
return SemanticVersion(IMHEX_VERSION);
#else
return "Unknown";
return {};
#endif
}
@@ -837,7 +907,7 @@ namespace hex {
}
bool isNightlyBuild() {
return getImHexVersion(false).ends_with("WIP");
return getImHexVersion().nightly();
}
bool updateImHex(UpdateType updateType) {
@@ -935,11 +1005,6 @@ namespace hex {
return *s_fonts;
}
static AutoReset<std::fs::path> s_customFontPath;
void setCustomFontPath(const std::fs::path &path) {
s_customFontPath = path;
}
static float s_fontSize = DefaultFontSize;
void setFontSize(float size) {
s_fontSize = size;
@@ -957,6 +1022,10 @@ namespace hex {
s_italicFont = italic;
}
static AutoReset<std::map<UnlocalizedString, ImFont*>> s_fontDefinitions;
std::map<UnlocalizedString, ImFont*>& getFontDefinitions() {
return *s_fontDefinitions;
}
}
@@ -1021,10 +1090,6 @@ namespace hex {
});
}
const std::fs::path& getCustomFontPath() {
return impl::s_customFontPath;
}
float getFontSize() {
return impl::s_fontSize;
}
@@ -1033,6 +1098,14 @@ namespace hex {
return impl::s_fontAtlas;
}
void registerFont(const UnlocalizedString &fontName) {
(*impl::s_fontDefinitions)[fontName] = nullptr;
}
ImFont* getFont(const UnlocalizedString &fontName) {
return (*impl::s_fontDefinitions)[fontName];
}
ImFont* Bold() {
return impl::s_boldFont;
}

View File

@@ -56,18 +56,19 @@ namespace hex {
}
}
void loadLanguage(const std::string &language) {
void loadLanguage(std::string language) {
auto &definitions = ContentRegistry::Language::impl::getLanguageDefinitions();
const auto& fallbackLanguage = getFallbackLanguage();
if (!definitions.contains(language))
return;
language = fallbackLanguage;
s_currStrings->clear();
loadLanguageDefinitions(definitions.at(language));
const auto& fallbackLanguage = getFallbackLanguage();
loadLanguageDefinitions(definitions.at(fallbackLanguage));
if (language != fallbackLanguage)
loadLanguageDefinitions(definitions.at(fallbackLanguage));
s_selectedLanguage = language;
}

View File

@@ -129,7 +129,7 @@ namespace hex {
const auto requestedVersion = getCompatibleVersion();
const auto imhexVersion = ImHexApi::System::getImHexVersion();
const auto imhexVersion = ImHexApi::System::getImHexVersion().get();
if (!imhexVersion.starts_with(requestedVersion)) {
if (requestedVersion.empty()) {
log::warn("Plugin '{}' did not specify a compatible version, assuming it is compatible with the current version of ImHex.", wolv::util::toUTF8String(m_path.filename()));

View File

@@ -1,6 +1,7 @@
#include <hex/api/shortcut_manager.hpp>
#include <imgui.h>
#include <hex/api/content_registry.hpp>
#include <hex/api/task_manager.hpp>
#include <hex/helpers/auto_reset.hpp>
#include <hex/ui/view.hpp>
@@ -12,6 +13,8 @@ namespace hex {
AutoReset<std::map<Shortcut, ShortcutManager::ShortcutEntry>> s_globalShortcuts;
std::atomic<bool> s_paused;
std::optional<Shortcut> s_prevShortcut;
bool s_macOSMode = false;
AutoReset<std::optional<UnlocalizedString>> s_lastShortcutMainMenu;
}
@@ -78,22 +81,14 @@ namespace hex {
std::string Shortcut::toString() const {
std::string result;
#if defined(OS_MACOS)
constexpr static auto CTRL_NAME = "";
constexpr static auto ALT_NAME = "";
constexpr static auto SHIFT_NAME = "";
constexpr static auto SUPER_NAME = "";
constexpr static auto Concatination = " ";
#else
constexpr static auto CTRL_NAME = "CTRL";
constexpr static auto ALT_NAME = "ALT";
constexpr static auto SHIFT_NAME = "SHIFT";
constexpr static auto SUPER_NAME = "SUPER";
constexpr static auto Concatination = " + ";
#endif
const auto CTRL_NAME = s_macOSMode ? "" : "CTRL";
const auto ALT_NAME = s_macOSMode ? "" : "ALT";
const auto SHIFT_NAME = s_macOSMode ? "" : "SHIFT";
const auto SUPER_NAME = s_macOSMode ? "" : "SUPER";
const auto Concatination = s_macOSMode ? " " : " + ";
auto keys = m_keys;
if (keys.erase(CTRL) > 0) {
if (keys.erase(CTRL) > 0 || (!s_macOSMode && keys.erase(CTRLCMD) > 0)) {
result += CTRL_NAME;
result += Concatination;
}
@@ -105,7 +100,7 @@ namespace hex {
result += SHIFT_NAME;
result += Concatination;
}
if (keys.erase(SUPER) > 0) {
if (keys.erase(SUPER) > 0 || (s_macOSMode && keys.erase(CTRLCMD) > 0)) {
result += SUPER_NAME;
result += Concatination;
}
@@ -238,28 +233,66 @@ namespace hex {
return result;
}
KeyEquivalent Shortcut::toKeyEquivalent() const {
#if defined(OS_MACOS)
if (*this == None)
return { };
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback) {
KeyEquivalent result = {};
result.valid = true;
for (const auto &key : m_keys) {
switch (key.getKeyCode()) {
case CTRL.getKeyCode():
result.ctrl = true;
break;
case SHIFT.getKeyCode():
result.shift = true;
break;
case ALT.getKeyCode():
result.opt = true;
break;
case SUPER.getKeyCode():
case CTRLCMD.getKeyCode():
result.cmd = true;
break;
case CurrentView.getKeyCode(): break;
case AllowWhileTyping.getKeyCode(): break;
default:
macosGetKey(Keys(key.getKeyCode()), &result.key);
break;
}
}
return result;
#else
return { };
#endif
}
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 } });
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, unlocalizedName, callback, enabledCallback } });
if (!inserted) log::error("Failed to add shortcut!");
}
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback) {
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 } });
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, { unlocalizedName }, callback, 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) {
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 } });
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback, 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) {
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 } });
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, { unlocalizedName }, callback, enabledCallback } });
if (!inserted) log::error("Failed to add shortcut!");
}
@@ -267,33 +300,58 @@ namespace hex {
Shortcut pressedShortcut;
if (ctrl)
pressedShortcut += CTRL;
pressedShortcut += s_macOSMode ? CTRL : CTRLCMD;
if (alt)
pressedShortcut += ALT;
if (shift)
pressedShortcut += SHIFT;
if (super)
pressedShortcut += SUPER;
pressedShortcut += s_macOSMode ? CTRLCMD : SUPER;
if (focused)
pressedShortcut += CurrentView;
if (ImGui::GetIO().WantTextInput)
pressedShortcut += AllowWhileTyping;
pressedShortcut += static_cast<Keys>(keyCode);
pressedShortcut += scanCodeToKey(keyCode);
return pressedShortcut;
}
static void processShortcut(const Shortcut &shortcut, const std::map<Shortcut, ShortcutManager::ShortcutEntry> &shortcuts) {
if (s_paused) return;
static bool processShortcut(Shortcut shortcut, const std::map<Shortcut, ShortcutManager::ShortcutEntry> &shortcuts) {
if (s_paused)
return true;
if (ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId))
return;
return true;
if (auto it = shortcuts.find(shortcut); it != shortcuts.end()) {
const auto &[foundShortcut, entry] = *it;
entry.callback();
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);
}
if (it != shortcuts.end()) {
const auto &[foundShortcut, entry] = *it;
if (entry.enabledCallback()) {
entry.callback();
if (!entry.unlocalizedName.empty()) {
s_lastShortcutMainMenu = entry.unlocalizedName.front();
}
return true;
}
}
return false;
}
bool ShortcutManager::runShortcut(const Shortcut &shortcut, const View *view) {
if (view == nullptr)
return processShortcut(shortcut, s_globalShortcuts);
else
return processShortcut(shortcut, view->m_shortcuts);
}
void ShortcutManager::process(const View *currentView, bool ctrl, bool alt, bool shift, bool super, bool focused, u32 keyCode) {
@@ -301,7 +359,7 @@ namespace hex {
if (keyCode != 0)
s_prevShortcut = Shortcut(pressedShortcut.getKeys());
processShortcut(pressedShortcut, currentView->m_shortcuts);
runShortcut(pressedShortcut, currentView);
}
void ShortcutManager::processGlobals(bool ctrl, bool alt, bool shift, bool super, u32 keyCode) {
@@ -309,9 +367,18 @@ namespace hex {
if (keyCode != 0)
s_prevShortcut = Shortcut(pressedShortcut.getKeys());
processShortcut(pressedShortcut, s_globalShortcuts);
runShortcut(pressedShortcut);
}
std::optional<UnlocalizedString> ShortcutManager::getLastActivatedMenu() {
return *s_lastShortcutMainMenu;
}
void ShortcutManager::resetLastActivatedMenu() {
s_lastShortcutMainMenu->reset();
}
void ShortcutManager::clearShortcuts() {
s_globalShortcuts->clear();
}
@@ -387,4 +454,9 @@ namespace hex {
return result;
}
void ShortcutManager::enableMacOSMode() {
s_macOSMode = true;
}
}

View File

@@ -63,8 +63,11 @@ namespace hex {
}
Task::Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function)
: m_unlocalizedName(std::move(unlocalizedName)), m_maxValue(maxValue), m_function(std::move(function)), m_background(background) { }
Task::Task(const 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)),
m_background(background), m_blocking(blocking) { }
Task::Task(hex::Task &&other) noexcept {
{
@@ -133,6 +136,11 @@ namespace hex {
return m_background;
}
bool Task::isBlocking() const {
return m_blocking;
}
bool Task::isFinished() const {
return m_finished;
}
@@ -327,11 +335,11 @@ namespace hex {
s_tasksFinishedCallbacks.clear();
}
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, std::function<void(Task&)> function) {
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, std::move(function));
auto task = std::make_shared<Task>(std::move(unlocalizedName), maxValue, background, blocking, std::move(function));
s_tasks.emplace_back(task);
@@ -346,12 +354,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, std::move(function));
return createTask(std::move(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,
return createTask(std::move(unlocalizedName), maxValue, false, false,
[function = std::move(function)](Task&) {
function();
}
@@ -360,12 +368,26 @@ 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, std::move(function));
return createTask(std::move(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,
return createTask(std::move(unlocalizedName), 0, true, false,
[function = std::move(function)](Task&) {
function();
}
);
}
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));
}
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,
[function = std::move(function)](Task&) {
function();
}
@@ -414,6 +436,14 @@ namespace hex {
});
}
size_t TaskManager::getRunningBlockingTaskCount() {
std::scoped_lock lock(s_queueMutex);
return std::ranges::count_if(s_tasks, [](const auto &task){
return task->isBlocking();
});
}
void TaskManager::doLater(const std::function<void()> &function) {
std::scoped_lock lock(s_deferredCallsMutex);

View File

@@ -1,5 +1,5 @@
#include <hex/api/theme_manager.hpp>
#include <hex/api/event_manager.hpp>
#include <hex/api/events/events_interaction.hpp>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/utils.hpp>
@@ -16,6 +16,7 @@ namespace hex {
AutoReset<std::map<std::string, ThemeManager::StyleHandler>> s_styleHandlers;
AutoReset<std::string> s_imageTheme;
AutoReset<std::string> s_currTheme;
AutoReset<std::optional<float>> s_accentColor;
std::recursive_mutex s_themeMutex;
}
@@ -155,12 +156,28 @@ namespace hex {
continue;
}
auto color = parseColorString(value.get<std::string>());
auto colorString = value.get<std::string>();
bool accentableColor = false;
if (colorString.starts_with("*")) {
colorString = colorString.substr(1);
accentableColor = true;
}
auto color = parseColorString(colorString);
if (!color.has_value()) {
log::warn("Invalid color '{}' for '{}.{}'", value.get<std::string>(), type, key);
log::warn("Invalid color '{}' for '{}.{}'", colorString, type, key);
continue;
}
if (accentableColor && s_accentColor->has_value()) {
float h, s, v;
ImGui::ColorConvertRGBtoHSV(color->Value.x, color->Value.y, color->Value.z, h, s, v);
h = s_accentColor->value();
ImGui::ColorConvertHSVtoRGB(h, s, v, color->Value.x, color->Value.y, color->Value.z);
}
(*s_themeHandlers)[type].setFunction((*s_themeHandlers)[type].colorMap.at(key), color.value());
}
}
@@ -236,6 +253,14 @@ namespace hex {
s_currTheme->clear();
}
void ThemeManager::setAccentColor(const ImColor &color) {
float h, s, v;
ImGui::ColorConvertRGBtoHSV(color.Value.x, color.Value.y, color.Value.z, h, s, v);
s_accentColor = h;
reapplyCurrentTheme();
}
const std::map<std::string, ThemeManager::ThemeHandler> &ThemeManager::getThemeHandlers() {
return s_themeHandlers;

View File

@@ -2,6 +2,7 @@
#include <hex/api/imhex_api.hpp>
#include <hex/api/localization_manager.hpp>
#include <hex/api/task_manager.hpp>
#include <hex/api/events/events_gui.hpp>
#include <hex/helpers/auto_reset.hpp>
@@ -11,6 +12,8 @@
#include <map>
#include <imgui.h>
namespace hex {
namespace {
@@ -20,10 +23,12 @@ namespace hex {
AutoReset<std::map<ImGuiID, std::string>> s_highlights;
AutoReset<std::vector<std::pair<ImRect, std::string>>> s_highlightDisplays;
AutoReset<std::map<ImGuiID, ImRect>> s_interactiveHelpDisplays;
AutoReset<std::map<ImGuiID, std::function<void()>>> s_interactiveHelpItems;
ImRect s_hoveredRect;
ImGuiID s_hoveredId;
ImGuiID s_activeHelpId;
bool s_helpHoverActive = false;
@@ -33,6 +38,13 @@ namespace hex {
idStack.push_back(0);
}
void add(const char *string) {
const ImGuiID seed = idStack.back();
const ImGuiID id = ImHashStr(string, 0, seed);
idStack.push_back(id);
}
void add(const std::string &string) {
const ImGuiID seed = idStack.back();
const ImGuiID id = ImHashStr(string.c_str(), string.length(), seed);
@@ -84,9 +96,23 @@ namespace hex {
EventImGuiElementRendered::subscribe([](ImGuiID id, const std::array<float, 4> bb){
const auto boundingBox = ImRect(bb[0], bb[1], bb[2], bb[3]);
const auto element = hex::s_highlights->find(id);
if (element != hex::s_highlights->end()) {
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
{
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;
}
}
if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
@@ -117,10 +143,10 @@ namespace hex {
});
}
void TutorialManager::addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString text) {
void TutorialManager::addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString) {
auto id = calculateId(ids);
s_interactiveHelpItems->emplace(id, [text = std::move(text)]{
s_interactiveHelpItems->emplace(id, [text = std::move(unlocalizedString)]{
log::info("{}", Lang(text).get());
});
}
@@ -133,6 +159,39 @@ namespace hex {
});
}
void TutorialManager::setLastItemInteractiveHelpPopup(std::function<void()> callback) {
auto id = ImGui::GetItemID();
if (!s_interactiveHelpItems->contains(id)) {
s_interactiveHelpItems->emplace(id, [id]{
s_activeHelpId = id;
});
}
if (id == s_activeHelpId) {
ImGui::SetNextWindowSize(scaled({ 400, 0 }));
if (ImGui::BeginTooltip()) {
callback();
ImGui::EndTooltip();
}
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) || ImGui::IsKeyPressed(ImGuiKey_Escape))
s_activeHelpId = 0;
}
}
void TutorialManager::setLastItemInteractiveHelpLink(std::string link) {
auto id = ImGui::GetItemID();
if (s_interactiveHelpItems->contains(id))
return;
s_interactiveHelpItems->emplace(id, [link = std::move(link)]{
hex::openWebpage(link);
});
}
void TutorialManager::startTutorial(const UnlocalizedString &unlocalizedName) {
s_currentTutorial = s_tutorials->find(unlocalizedName);
if (s_currentTutorial == s_tutorials->end())
@@ -146,6 +205,19 @@ namespace hex {
const auto &drawList = ImGui::GetForegroundDrawList();
drawList->AddText(ImGui::GetMousePos() + scaled({ 10, -5, }), ImGui::GetColorU32(ImGuiCol_Text), "?");
for (const auto &[id, boundingBox] : *s_interactiveHelpDisplays) {
drawList->AddRect(
boundingBox.Min - ImVec2(5, 5),
boundingBox.Max + ImVec2(5, 5),
ImGui::GetColorU32(ImGuiCol_PlotHistogram),
5.0F,
ImDrawFlags_None,
2.0F
);
}
s_interactiveHelpDisplays->clear();
const bool mouseClicked = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
if (s_hoveredId != 0) {
drawList->AddRectFilled(s_hoveredRect.Min, s_hoveredRect.Max, 0x30FFFFFF);
@@ -164,6 +236,11 @@ namespace hex {
if (mouseClicked || ImGui::IsKeyPressed(ImGuiKey_Escape)) {
s_helpHoverActive = false;
}
// Discard mouse click so it doesn't activate clicked item
ImGui::GetIO().MouseDown[ImGuiMouseButton_Left] = false;
ImGui::GetIO().MouseReleased[ImGuiMouseButton_Left] = false;
ImGui::GetIO().MouseClicked[ImGuiMouseButton_Left] = false;
}
for (const auto &[rect, unlocalizedText] : *s_highlightDisplays) {

View File

@@ -14,10 +14,10 @@
namespace hex {
AutoReset<std::map<std::string, WorkspaceManager::Workspace>> WorkspaceManager::s_workspaces;
decltype(WorkspaceManager::s_workspaces)::Type::iterator WorkspaceManager::s_currentWorkspace = s_workspaces->end();
decltype(WorkspaceManager::s_workspaces)::Type::iterator WorkspaceManager::s_previousWorkspace = s_workspaces->end();
decltype(WorkspaceManager::s_workspaces)::Type::iterator WorkspaceManager::s_workspaceToRemove = s_workspaces->end();
static AutoReset<std::map<std::string, WorkspaceManager::Workspace>> s_workspaces;
static decltype(s_workspaces)::Type::iterator s_currentWorkspace = s_workspaces->end();
static decltype(s_workspaces)::Type::iterator s_previousWorkspace = s_workspaces->end();
static decltype(s_workspaces)::Type::iterator s_workspaceToRemove = s_workspaces->end();
void WorkspaceManager::createWorkspace(const std::string& name, const std::string &layout) {
s_currentWorkspace = s_workspaces->insert_or_assign(name, Workspace {
@@ -174,7 +174,13 @@ namespace hex {
}
}
const std::map<std::string, WorkspaceManager::Workspace>& WorkspaceManager::getWorkspaces() {
return *s_workspaces;
}
const std::map<std::string, WorkspaceManager::Workspace>::iterator& WorkspaceManager::getCurrentWorkspace() {
return s_currentWorkspace;
}
}

View File

@@ -41,7 +41,7 @@ namespace hex::dp {
const i128& Node::getIntegerOnInput(u32 index) {
auto attribute = this->getConnectedInputAttribute(index);
auto &outputData = [&] -> std::vector<u8>& {
auto &outputData = [&]() -> std::vector<u8>&{
if (attribute != nullptr) {
if (attribute->getType() != Attribute::Type::Integer)
throwNodeError("Tried to read integer from non-integer attribute");
@@ -68,7 +68,7 @@ namespace hex::dp {
const double& Node::getFloatOnInput(u32 index) {
auto attribute = this->getConnectedInputAttribute(index);
auto &outputData = [&] -> std::vector<u8>& {
auto &outputData = [&]() -> std::vector<u8>&{
if (attribute != nullptr) {
if (attribute->getType() != Attribute::Type::Float)
throwNodeError("Tried to read integer from non-float attribute");

View File

@@ -470,7 +470,7 @@ namespace hex::crypt {
std::vector<u8> bytes;
u8 byte;
while (true) {
byte = value & 0x7F;
byte = u8(value & 0x7F);
value >>= 7;
if constexpr(std::signed_integral<T>) {
if (value == 0 && (byte & 0x40) == 0) {

View File

@@ -12,4 +12,13 @@ namespace hex::dbg {
}
static bool s_debugMode = false;
bool debugModeEnabled() {
return s_debugMode;
}
void setDebugModeEnabled(bool enabled) {
s_debugMode = enabled;
}
}

View File

@@ -123,7 +123,13 @@ namespace hex::fs {
// Call callback that will write the file
Module._fileBrowserCallback(stringToNewUTF8("/savedFiles/" + filename));
let data = FS.readFile("/savedFiles/" + filename);
let data;
try {
data = FS.readFile("/savedFiles/" + filename);
} catch (e) {
console.log(e);
return;
}
const reader = Object.assign(new FileReader(), {
onload: () => {
@@ -191,6 +197,7 @@ namespace hex::fs {
else if (!validExtensions.empty())
path = "file." + validExtensions[0].spec;
std::fs::create_directory("/savedFiles");
callJs_saveFile(path.filename().string().c_str());
break;
}

View File

@@ -49,15 +49,6 @@ namespace hex {
}
void HttpRequest::checkProxyErrors() { }
int HttpRequest::progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow) {
std::ignore = contents;
std::ignore = dlTotal;
std::ignore = dlNow;
std::ignore = ulTotal;
std::ignore = ulNow;
return -1;
}
}
#endif

View File

@@ -1,6 +1,7 @@
#if !defined(OS_WEB)
#include <hex/helpers/http_requests.hpp>
#include <curl/curl.h>
namespace hex {
@@ -11,6 +12,19 @@ namespace hex {
}
int progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow) {
auto &request = *static_cast<HttpRequest *>(contents);
if (dlTotal > 0)
request.setProgress(float(dlNow) / dlTotal);
else if (ulTotal > 0)
request.setProgress(float(ulNow) / ulTotal);
else
request.setProgress(0.0F);
return request.isCanceled() ? CURLE_ABORTED_BY_CALLBACK : CURLE_OK;
}
HttpRequest::HttpRequest(std::string method, std::string url) : m_method(std::move(method)), m_url(std::move(url)) {
AT_FIRST_TIME {
curl_global_init(CURL_GLOBAL_ALL);
@@ -95,19 +109,101 @@ namespace hex {
}
}
int HttpRequest::progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow) {
auto &request = *static_cast<HttpRequest *>(contents);
namespace impl {
if (dlTotal > 0)
request.m_progress = float(dlNow) / dlTotal;
else if (ulTotal > 0)
request.m_progress = float(ulNow) / ulTotal;
else
request.m_progress = 0.0F;
void setWriteFunctions(CURL *curl, wolv::io::File &file) {
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HttpRequest::writeToFile);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file);
}
void setWriteFunctions(CURL *curl, std::vector<u8> &data) {
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HttpRequest::writeToVector);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
}
void setupFileUpload(CURL *curl, wolv::io::File &file, const std::string &fileName, const std::string &mimeName) {
curl_mime *mime = curl_mime_init(curl);
curl_mimepart *part = curl_mime_addpart(mime);
curl_mime_data_cb(part, file.getSize(),
[](char *buffer, size_t size, size_t nitems, void *arg) -> size_t {
auto handle = static_cast<FILE*>(arg);
return fread(buffer, size, nitems, handle);
},
[](void *arg, curl_off_t offset, int origin) -> int {
auto handle = static_cast<FILE*>(arg);
if (fseek(handle, offset, origin) != 0)
return CURL_SEEKFUNC_CANTSEEK;
else
return CURL_SEEKFUNC_OK;
},
[](void *arg) {
auto handle = static_cast<FILE*>(arg);
fclose(handle);
},
file.getHandle());
curl_mime_filename(part, fileName.c_str());
curl_mime_name(part, mimeName.c_str());
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
}
void setupFileUpload(CURL *curl, const std::vector<u8> &data, const std::fs::path &fileName, const std::string &mimeName) {
curl_mime *mime = curl_mime_init(curl);
curl_mimepart *part = curl_mime_addpart(mime);
curl_mime_data(part, reinterpret_cast<const char *>(data.data()), data.size());
auto fileNameStr = wolv::util::toUTF8String(fileName.filename());
curl_mime_filename(part, fileNameStr.c_str());
curl_mime_name(part, mimeName.c_str());
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
}
int executeCurl(CURL *curl, const std::string &url, const std::string &method, const std::string &body, std::map<std::string, std::string> &headers) {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method.c_str());
if (!body.empty()) {
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
}
curl_slist *headersList = nullptr;
headersList = curl_slist_append(headersList, "Cache-Control: no-cache");
ON_SCOPE_EXIT { curl_slist_free_all(headersList); };
for (auto &[key, value] : headers) {
std::string header = hex::format("{}: {}", key, value);
headersList = curl_slist_append(headersList, header.c_str());
}
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headersList);
auto result = curl_easy_perform(curl);
if (result != CURLE_OK){
return result;
}
return 0;
}
long getStatusCode(CURL *curl) {
long statusCode = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &statusCode);
return statusCode;
}
std::string getStatusText(int result) {
return curl_easy_strerror(CURLcode(result));
}
return request.m_canceled ? CURLE_ABORTED_BY_CALLBACK : CURLE_OK;
}
}

View File

@@ -1,4 +1,4 @@
#include <hex/api/event_manager.hpp>
#include <hex/api/events/events_gui.hpp>
#include <imgui.h>
#include <imgui_internal.h>

View File

@@ -0,0 +1,239 @@
#include <hex/helpers/keys.hpp>
#include <GLFW/glfw3.h>
enum Keys scanCodeToKey(int scanCode) {
switch (scanCode) {
case GLFW_KEY_SPACE: return Keys::Space;
case GLFW_KEY_APOSTROPHE: return Keys::Apostrophe;
case GLFW_KEY_COMMA: return Keys::Comma;
case GLFW_KEY_MINUS: return Keys::Minus;
case GLFW_KEY_PERIOD: return Keys::Period;
case GLFW_KEY_SLASH: return Keys::Slash;
case GLFW_KEY_0: return Keys::Num0;
case GLFW_KEY_1: return Keys::Num1;
case GLFW_KEY_2: return Keys::Num2;
case GLFW_KEY_3: return Keys::Num3;
case GLFW_KEY_4: return Keys::Num4;
case GLFW_KEY_5: return Keys::Num5;
case GLFW_KEY_6: return Keys::Num6;
case GLFW_KEY_7: return Keys::Num7;
case GLFW_KEY_8: return Keys::Num8;
case GLFW_KEY_9: return Keys::Num9;
case GLFW_KEY_SEMICOLON: return Keys::Semicolon;
case GLFW_KEY_EQUAL: return Keys::Equals;
case GLFW_KEY_A: return Keys::A;
case GLFW_KEY_B: return Keys::B;
case GLFW_KEY_C: return Keys::C;
case GLFW_KEY_D: return Keys::D;
case GLFW_KEY_E: return Keys::E;
case GLFW_KEY_F: return Keys::F;
case GLFW_KEY_G: return Keys::G;
case GLFW_KEY_H: return Keys::H;
case GLFW_KEY_I: return Keys::I;
case GLFW_KEY_J: return Keys::J;
case GLFW_KEY_K: return Keys::K;
case GLFW_KEY_L: return Keys::L;
case GLFW_KEY_M: return Keys::M;
case GLFW_KEY_N: return Keys::N;
case GLFW_KEY_O: return Keys::O;
case GLFW_KEY_P: return Keys::P;
case GLFW_KEY_Q: return Keys::Q;
case GLFW_KEY_R: return Keys::R;
case GLFW_KEY_S: return Keys::S;
case GLFW_KEY_T: return Keys::T;
case GLFW_KEY_U: return Keys::U;
case GLFW_KEY_V: return Keys::V;
case GLFW_KEY_W: return Keys::W;
case GLFW_KEY_X: return Keys::X;
case GLFW_KEY_Y: return Keys::Y;
case GLFW_KEY_Z: return Keys::Z;
case GLFW_KEY_LEFT_BRACKET: return Keys::LeftBracket;
case GLFW_KEY_BACKSLASH: return Keys::Backslash;
case GLFW_KEY_RIGHT_BRACKET: return Keys::RightBracket;
case GLFW_KEY_GRAVE_ACCENT: return Keys::GraveAccent;
case GLFW_KEY_WORLD_1: return Keys::World1;
case GLFW_KEY_WORLD_2: return Keys::World2;
case GLFW_KEY_ESCAPE: return Keys::Escape;
case GLFW_KEY_ENTER: return Keys::Enter;
case GLFW_KEY_TAB: return Keys::Tab;
case GLFW_KEY_BACKSPACE: return Keys::Backspace;
case GLFW_KEY_INSERT: return Keys::Insert;
case GLFW_KEY_DELETE: return Keys::Delete;
case GLFW_KEY_RIGHT: return Keys::Right;
case GLFW_KEY_LEFT: return Keys::Left;
case GLFW_KEY_DOWN: return Keys::Down;
case GLFW_KEY_UP: return Keys::Up;
case GLFW_KEY_PAGE_UP: return Keys::PageUp;
case GLFW_KEY_PAGE_DOWN: return Keys::PageDown;
case GLFW_KEY_HOME: return Keys::Home;
case GLFW_KEY_END: return Keys::End;
case GLFW_KEY_CAPS_LOCK: return Keys::CapsLock;
case GLFW_KEY_SCROLL_LOCK: return Keys::ScrollLock;
case GLFW_KEY_NUM_LOCK: return Keys::NumLock;
case GLFW_KEY_PRINT_SCREEN: return Keys::PrintScreen;
case GLFW_KEY_PAUSE: return Keys::Pause;
case GLFW_KEY_F1: return Keys::F1;
case GLFW_KEY_F2: return Keys::F2;
case GLFW_KEY_F3: return Keys::F3;
case GLFW_KEY_F4: return Keys::F4;
case GLFW_KEY_F5: return Keys::F5;
case GLFW_KEY_F6: return Keys::F6;
case GLFW_KEY_F7: return Keys::F7;
case GLFW_KEY_F8: return Keys::F8;
case GLFW_KEY_F9: return Keys::F9;
case GLFW_KEY_F10: return Keys::F10;
case GLFW_KEY_F11: return Keys::F11;
case GLFW_KEY_F12: return Keys::F12;
case GLFW_KEY_F13: return Keys::F13;
case GLFW_KEY_F14: return Keys::F14;
case GLFW_KEY_F15: return Keys::F15;
case GLFW_KEY_F16: return Keys::F16;
case GLFW_KEY_F17: return Keys::F17;
case GLFW_KEY_F18: return Keys::F18;
case GLFW_KEY_F19: return Keys::F19;
case GLFW_KEY_F20: return Keys::F20;
case GLFW_KEY_F21: return Keys::F21;
case GLFW_KEY_F22: return Keys::F22;
case GLFW_KEY_F23: return Keys::F23;
case GLFW_KEY_F24: return Keys::F24;
case GLFW_KEY_F25: return Keys::F25;
case GLFW_KEY_KP_0: return Keys::KeyPad0;
case GLFW_KEY_KP_1: return Keys::KeyPad1;
case GLFW_KEY_KP_2: return Keys::KeyPad2;
case GLFW_KEY_KP_3: return Keys::KeyPad3;
case GLFW_KEY_KP_4: return Keys::KeyPad4;
case GLFW_KEY_KP_5: return Keys::KeyPad5;
case GLFW_KEY_KP_6: return Keys::KeyPad6;
case GLFW_KEY_KP_7: return Keys::KeyPad7;
case GLFW_KEY_KP_8: return Keys::KeyPad8;
case GLFW_KEY_KP_9: return Keys::KeyPad9;
case GLFW_KEY_KP_DECIMAL: return Keys::KeyPadDecimal;
case GLFW_KEY_KP_DIVIDE: return Keys::KeyPadDivide;
case GLFW_KEY_KP_MULTIPLY: return Keys::KeyPadMultiply;
case GLFW_KEY_KP_SUBTRACT: return Keys::KeyPadSubtract;
case GLFW_KEY_KP_ADD: return Keys::KeyPadAdd;
case GLFW_KEY_KP_ENTER: return Keys::KeyPadEnter;
case GLFW_KEY_KP_EQUAL: return Keys::KeyPadEqual;
case GLFW_KEY_MENU: return Keys::Menu;
default: return Keys(scanCode);
}
}
int keyToScanCode(enum Keys key) {
switch (key) {
case Keys::Space: return GLFW_KEY_SPACE;
case Keys::Apostrophe: return GLFW_KEY_APOSTROPHE;
case Keys::Comma: return GLFW_KEY_COMMA;
case Keys::Minus: return GLFW_KEY_MINUS;
case Keys::Period: return GLFW_KEY_PERIOD;
case Keys::Slash: return GLFW_KEY_SLASH;
case Keys::Num0: return GLFW_KEY_0;
case Keys::Num1: return GLFW_KEY_1;
case Keys::Num2: return GLFW_KEY_2;
case Keys::Num3: return GLFW_KEY_3;
case Keys::Num4: return GLFW_KEY_4;
case Keys::Num5: return GLFW_KEY_5;
case Keys::Num6: return GLFW_KEY_6;
case Keys::Num7: return GLFW_KEY_7;
case Keys::Num8: return GLFW_KEY_8;
case Keys::Num9: return GLFW_KEY_9;
case Keys::Semicolon: return GLFW_KEY_SEMICOLON;
case Keys::Equals: return GLFW_KEY_EQUAL;
case Keys::A: return GLFW_KEY_A;
case Keys::B: return GLFW_KEY_B;
case Keys::C: return GLFW_KEY_C;
case Keys::D: return GLFW_KEY_D;
case Keys::E: return GLFW_KEY_E;
case Keys::F: return GLFW_KEY_F;
case Keys::G: return GLFW_KEY_G;
case Keys::H: return GLFW_KEY_H;
case Keys::I: return GLFW_KEY_I;
case Keys::J: return GLFW_KEY_J;
case Keys::K: return GLFW_KEY_K;
case Keys::L: return GLFW_KEY_L;
case Keys::M: return GLFW_KEY_M;
case Keys::N: return GLFW_KEY_N;
case Keys::O: return GLFW_KEY_O;
case Keys::P: return GLFW_KEY_P;
case Keys::Q: return GLFW_KEY_Q;
case Keys::R: return GLFW_KEY_R;
case Keys::S: return GLFW_KEY_S;
case Keys::T: return GLFW_KEY_T;
case Keys::U: return GLFW_KEY_U;
case Keys::V: return GLFW_KEY_V;
case Keys::W: return GLFW_KEY_W;
case Keys::X: return GLFW_KEY_X;
case Keys::Y: return GLFW_KEY_Y;
case Keys::Z: return GLFW_KEY_Z;
case Keys::LeftBracket: return GLFW_KEY_LEFT_BRACKET;
case Keys::Backslash: return GLFW_KEY_BACKSLASH;
case Keys::RightBracket: return GLFW_KEY_RIGHT_BRACKET;
case Keys::GraveAccent: return GLFW_KEY_GRAVE_ACCENT;
case Keys::World1: return GLFW_KEY_WORLD_1;
case Keys::World2: return GLFW_KEY_WORLD_2;
case Keys::Escape: return GLFW_KEY_ESCAPE;
case Keys::Enter: return GLFW_KEY_ENTER;
case Keys::Tab: return GLFW_KEY_TAB;
case Keys::Backspace: return GLFW_KEY_BACKSPACE;
case Keys::Insert: return GLFW_KEY_INSERT;
case Keys::Delete: return GLFW_KEY_DELETE;
case Keys::Right: return GLFW_KEY_RIGHT;
case Keys::Left: return GLFW_KEY_LEFT;
case Keys::Down: return GLFW_KEY_DOWN;
case Keys::Up: return GLFW_KEY_UP;
case Keys::PageUp: return GLFW_KEY_PAGE_UP;
case Keys::PageDown: return GLFW_KEY_PAGE_DOWN;
case Keys::Home: return GLFW_KEY_HOME;
case Keys::End: return GLFW_KEY_END;
case Keys::CapsLock: return GLFW_KEY_CAPS_LOCK;
case Keys::ScrollLock: return GLFW_KEY_SCROLL_LOCK;
case Keys::NumLock: return GLFW_KEY_NUM_LOCK;
case Keys::PrintScreen: return GLFW_KEY_PRINT_SCREEN;
case Keys::Pause: return GLFW_KEY_PAUSE;
case Keys::F1: return GLFW_KEY_F1;
case Keys::F2: return GLFW_KEY_F2;
case Keys::F3: return GLFW_KEY_F3;
case Keys::F4: return GLFW_KEY_F4;
case Keys::F5: return GLFW_KEY_F5;
case Keys::F6: return GLFW_KEY_F6;
case Keys::F7: return GLFW_KEY_F7;
case Keys::F8: return GLFW_KEY_F8;
case Keys::F9: return GLFW_KEY_F9;
case Keys::F10: return GLFW_KEY_F10;
case Keys::F11: return GLFW_KEY_F11;
case Keys::F12: return GLFW_KEY_F12;
case Keys::F13: return GLFW_KEY_F13;
case Keys::F14: return GLFW_KEY_F14;
case Keys::F15: return GLFW_KEY_F15;
case Keys::F16: return GLFW_KEY_F16;
case Keys::F17: return GLFW_KEY_F17;
case Keys::F18: return GLFW_KEY_F18;
case Keys::F19: return GLFW_KEY_F19;
case Keys::F20: return GLFW_KEY_F20;
case Keys::F21: return GLFW_KEY_F21;
case Keys::F22: return GLFW_KEY_F22;
case Keys::F23: return GLFW_KEY_F23;
case Keys::F24: return GLFW_KEY_F24;
case Keys::F25: return GLFW_KEY_F25;
case Keys::KeyPad0: return GLFW_KEY_KP_0;
case Keys::KeyPad1: return GLFW_KEY_KP_1;
case Keys::KeyPad2: return GLFW_KEY_KP_2;
case Keys::KeyPad3: return GLFW_KEY_KP_3;
case Keys::KeyPad4: return GLFW_KEY_KP_4;
case Keys::KeyPad5: return GLFW_KEY_KP_5;
case Keys::KeyPad6: return GLFW_KEY_KP_6;
case Keys::KeyPad7: return GLFW_KEY_KP_7;
case Keys::KeyPad8: return GLFW_KEY_KP_8;
case Keys::KeyPad9: return GLFW_KEY_KP_9;
case Keys::KeyPadDecimal: return GLFW_KEY_KP_DECIMAL;
case Keys::KeyPadDivide: return GLFW_KEY_KP_DIVIDE;
case Keys::KeyPadMultiply: return GLFW_KEY_KP_MULTIPLY;
case Keys::KeyPadSubtract: return GLFW_KEY_KP_SUBTRACT;
case Keys::KeyPadAdd: return GLFW_KEY_KP_ADD;
case Keys::KeyPadEnter: return GLFW_KEY_KP_ENTER;
case Keys::KeyPadEqual: return GLFW_KEY_KP_EQUAL;
case Keys::Menu: return GLFW_KEY_MENU;
default: return int(key);
}
}

View File

@@ -1,7 +1,6 @@
#include <hex/helpers/logger.hpp>
#include <hex/api/task_manager.hpp>
#include <hex/api/event_manager.hpp>
#include <hex/helpers/fs.hpp>
#include <hex/helpers/fmt.hpp>

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