Compare commits

..

673 Commits

Author SHA1 Message Date
WerWolv
dc8245ce4c build: Bumped version to 1.29.0 2023-05-21 10:44:41 +02:00
WerWolv
1b88b3704d feat: Allow layouts to be deleted again 2023-05-21 10:43:35 +02:00
WerWolv
6dbaac4283 impr: Make sure hex editor popups have their input focused 2023-05-21 10:35:14 +02:00
WerWolv
180a27fdc9 fix: Local keybindings not working correctly 2023-05-21 10:28:55 +02:00
WerWolv
c02465b892 fix: Byte type and Entropy graph being shifted 2023-05-21 10:23:33 +02:00
WerWolv
f503a89f98 fix: Typo in IEEE754 tool 2023-05-20 21:49:45 +02:00
WerWolv
f94e5488d4 fix: Mouse cursor not adjusting anymore properly 2023-05-20 21:36:15 +02:00
WerWolv
87621e9337 impr: Disable some Import... options when the provider isn't writable 2023-05-20 21:23:15 +02:00
WerWolv
3219ba68de impr: Better layout of ImHex subtitle on welcome screen 2023-05-20 21:20:32 +02:00
WerWolv
5d608603cb fix: Selection in diff view being retained 2023-05-20 21:13:40 +02:00
WerWolv
7336c8dddc fix: Cursor types on Windows sometimes getting stuck 2023-05-20 21:10:12 +02:00
WerWolv
c91e3875d4 build: Updated libwolv 2023-05-20 19:27:00 +02:00
WerWolv
0181325b64 build: Updated libwolv 2023-05-20 18:10:26 +02:00
WerWolv
11f55a7561 fix: File handles not being closed correctly 2023-05-20 18:07:15 +02:00
WerWolv
9bb3a92e12 build: Updated libwolv 2023-05-20 15:47:21 +02:00
KOLANICH
3e9ba8c636 build: Add EOLs to the end of all "own" CMakeLists.txt files (#1093)
Text editors on Unix-like OSes add them automatically and it is usually
considered to be a good practice.
2023-05-20 13:38:24 +02:00
KOLANICH
4faebf435c impr: Remove an unused std::mutex in TaskManager::runner (#1088) 2023-05-20 13:38:12 +02:00
KOLANICH
749823e044 build: Move -s additional compiler flags into linker flags, and enable it only when gcc/clang are used. (#1087)
Compiler when compiling doesn't use them in those cases and emit a
warning, which is turned into an error by `-Werror`. Unfortunately,
CPack doesn't expose the logic it uses for stripping binaries.
2023-05-20 13:37:57 +02:00
KOLANICH
608c9e2e7a fix: WASM disassembler not being available in Capstone < 5 (#1086)
This fixes build on Debian with Capstone from packages.
2023-05-20 13:37:45 +02:00
WerWolv
96ee544538 build: Updated libwolv 2023-05-20 13:31:41 +02:00
WerWolv
7ea7c531e2 fix: Logs not being written to disk on Windows 2023-05-20 13:10:35 +02:00
WerWolv
969a37877a fix: Crash on exit 2023-05-20 13:10:24 +02:00
WerWolv
3cb8e37182 fix: Broken file open logic
Closes #1090
2023-05-20 11:52:24 +02:00
paxcut
3e4c4430d5 feat: Greatly improved the IEEE754 tool (#1047)
I just realized one feature request existed about this tool and have
added a comment to it referring this pr. Errors and additions are
described in the fork commit already. I'm not sure if I should repeat
them here again. I have tested the changes thoroughly, but it is always
possible some fringe case was not tested and is incorrect. The tests
were done using the many similar online calculators for IEEE 754
floating point formats.
IEEE 745 floating point tool redesign modeled after 'float toy' web app
(http://evanw.github.io/float-toy/)

Streamlined output using colors and compact layout which can be further
simplified.
Chosen display mode (detailed or simplified) is automatically saved and
set on new sessions.
Edit the binary bits, the integer hexadecimal or the floating point
decimal values and the entire app will update with the change.
Supports the main IEEE745 standard formats (half, single and double
precision) together with custom formats of size <= 64 bits.
Each format choice uses and displays the number of significant decimal
digits defined by the mantissa size.
Added labels to identify the location of each bit box inside the binary
representation.
Satisfies round trip / idempotent (reproducing) conversion property
Added theme colors, radio buttons for display mode and a clear button
that resets the tool.
Removed previously and incorrectly added locale translation to various
labels and languages
Attempted to adhere to code style formatting using existing code as
example.
An effort was made to use preferred variable types and functions from
std namespace when appropriate.
Attempted to document code using comments. 

Not implemented / left to complete at an later time

Arbitrary width and precision formats. 
Extended precision formats.
Shortest string property.
hexadecimal floating point display and conversions.
2023-05-19 21:18:38 +02:00
WerWolv
4ad66365d0 fix: Crash when saving patches
Fixes #1077
2023-05-19 20:01:42 +02:00
WerWolv
39276e123e patterns: Allow bitfield values to be edited 2023-05-19 19:56:55 +02:00
WerWolv
0f9434740f fix: Crash when deleting last environment variable in pattern editor 2023-05-19 17:15:37 +02:00
WerWolv
7ed153a47b patterns: Updated pattern language 2023-05-19 16:14:54 +02:00
WerWolv
c9d673ce40 patterns: Updated pattern language 2023-05-19 15:29:18 +02:00
WerWolv
0be610f1cd patterns: Updated pattern language 2023-05-18 23:20:10 +02:00
WerWolv
f75aa1f1b0 git: Fixed color of docs shield 2023-05-18 11:46:51 +02:00
Justus Garbe
5ef58cdf76 feat: Added bit and byte reverse and bit display data processor nodes (#1082)
#1081
2023-05-18 10:25:59 +02:00
WerWolv
511375feb5 patterns: Updated pattern language 2023-05-18 09:51:24 +02:00
WerWolv
8119929ece fix: Don't wait for services on exit 2023-05-16 14:59:14 +02:00
iTrooz
e1620966e5 feat: Keep only 10 latest logs on exit (#1079)
Co-authored-by: Nik <werwolv98@gmail.com>
2023-05-16 14:45:24 +02:00
WerWolv
a5b0a8614a impr: Automatically re-evaluate pattern when changing provider and code sync is on
Closes #1078
2023-05-16 14:45:04 +02:00
WerWolv
e28f2dfea1 fix: Only 5 patterns per byte being highlighted
Fixes #1076
2023-05-16 14:41:02 +02:00
WerWolv
0dcfeaefb3 fix: Build when git commit hash or branch is not available 2023-05-16 12:02:17 +02:00
WerWolv
3bd4a3ba8b impr: Better JSON error handling in many places 2023-05-16 11:33:00 +02:00
WerWolv
7e9b23de7d impr: Improve network interface error handling 2023-05-16 11:20:46 +02:00
WerWolv
a758676b0d fix: Change network interface port to 31337 2023-05-16 11:01:59 +02:00
WerWolv
636ed0095d feat: Added new imhex/capabilities network interface 2023-05-16 11:01:40 +02:00
WerWolv
14341d611d impr: Handle macOS Open with... correctly 2023-05-15 18:07:49 +02:00
WerWolv
07565eea63 build: Updated libwolv 2023-05-15 18:07:35 +02:00
WerWolv
c006062540 feat: Added basic network interface support 2023-05-15 11:30:24 +02:00
WerWolv
e685d65be8 fix: Scrolling not working correctly on welcome screen
Fixes #1071
2023-05-15 08:33:35 +02:00
WerWolv
ab67e274b2 fix: Hex editor editing value not updating correctly 2023-05-15 08:17:16 +02:00
WerWolv
7656fd7a4e patterns: Updated pattern language 2023-05-15 08:17:02 +02:00
WerWolv
60a2b30e91 fix: Another wrong include on macOS 2023-05-14 22:53:52 +02:00
WerWolv
7ec7e562d1 fix: Wrong editing values in hex editor in some circumstances 2023-05-14 22:52:47 +02:00
WerWolv
c50d52d0a6 fix: Crash when reading from modified bytes 2023-05-14 22:46:19 +02:00
WerWolv
2b765617ce impr: Disallow saving pattern files if they're empty 2023-05-14 22:24:16 +02:00
WerWolv
79cdf51588 fix: Wrong include on macOS 2023-05-14 22:23:05 +02:00
WerWolv
7b048d9b96 fix: Compile on macOS _again_ 2023-05-14 22:03:04 +02:00
WerWolv
d96fc6d41b fix: Compilation on macOS 2023-05-14 21:50:58 +02:00
WerWolv
610f109e2a fix: Crash when too many entries are being logged at once 2023-05-14 21:39:18 +02:00
WerWolv
609afebc55 fix: Updated build script 2023-05-14 20:20:40 +02:00
WerWolv
3bd9ab6349 fix: Hopefully open files now on macOS 2023-05-14 20:20:22 +02:00
WerWolv
5027f36d95 fix: Open with crashing on macOS
#1070
2023-05-14 18:35:35 +02:00
WerWolv
a5498995ff impr: Hopefully allow macOS to open any file type
#1070
2023-05-14 09:58:15 +02:00
WerWolv
f40b5d9811 fix: Search button in numeric find option being active by default 2023-05-13 17:51:16 +02:00
WerWolv
d00fae03a9 fix: Diff table not being cleared when closing providers 2023-05-13 17:50:33 +02:00
WerWolv
3c4e1b2f27 impr: Various cleanup 2023-05-13 17:50:16 +02:00
WerWolv
6e5d6810e7 build: Disable assertions in release builds 2023-05-13 17:49:53 +02:00
WerWolv
4afd5a7905 patterns: Updated pattern language
#1069
2023-05-13 17:21:44 +02:00
WerWolv
6709baa710 patterns: Updated pattern language 2023-05-13 15:43:37 +02:00
WerWolv
aa1bf0b764 impr: Make about page resizable 2023-05-13 12:26:13 +02:00
WerWolv
a7327290ea fix: Only save custom encoding to project file when necessary 2023-05-13 11:17:27 +02:00
WerWolv
857e90a37b fix: ImHex freezing when evaluating patterns 2023-05-13 11:12:38 +02:00
WerWolv
aaeebd3fe9 fix: Various pattern execution race conditions 2023-05-12 15:46:13 +02:00
WerWolv
0a7a190b04 impr: Added tooltips to pattern data view when name or value is too long 2023-05-12 08:49:08 +02:00
WerWolv
21d922113d impr: Make sure to clear selections when all providers are deleted 2023-05-12 08:38:52 +02:00
WerWolv
b0876e1c35 impr: Move some options into a new Extras menu 2023-05-12 08:38:32 +02:00
WerWolv
18bc5de169 fix: Copy-as options not being disabled correctly 2023-05-12 08:38:07 +02:00
WerWolv
0321743f1e fix: Missing save layout localization keys 2023-05-12 08:37:43 +02:00
WerWolv
f2af90fe06 fix: Help hover icon issues 2023-05-11 23:56:51 +02:00
WerWolv
2f511ec4fa impr: Improve frame cap handling 2023-05-11 23:22:06 +02:00
WerWolv
0649e0dcd3 impr: Clean up old layout stuff 2023-05-11 23:21:52 +02:00
WerWolv
0b21e30e44 fix: White border around maximized window on WIndows 2023-05-11 20:49:07 +02:00
WerWolv
ceeaca1a4b feat: Added layout manager to save and restore custom layouts 2023-05-11 18:44:50 +02:00
WerWolv
2da89f4b9b fix: Position of restore layout button being wrong with different scalings 2023-05-11 18:44:33 +02:00
WerWolv
49371398bc fix: Resizing on windows still being janky 2023-05-11 18:43:19 +02:00
iTrooz
2e73d74cea impr: Open .hexproj files as projects when opened though the Open File option (#1061) 2023-05-11 12:38:22 +02:00
WerWolv
688471fd61 build: Updated libfmt to 10.0 2023-05-11 12:06:58 +02:00
WerWolv
ea482ff0f5 fix: Crash when closing providers too quickly 2023-05-11 12:01:06 +02:00
WerWolv
5c9d0e29c2 fix: Left/Right resizing not working correctly on Windows 2023-05-11 12:00:56 +02:00
WerWolv
8f07f0f8ae impr: Better look and feel of the welcome screen close button 2023-05-11 12:00:45 +02:00
WerWolv
4f17a96707 build: Updated libwolv 2023-05-11 10:04:09 +02:00
iTrooz
b0ab8698ec fix: Loading data processor nodes from project thowing errors (#1065)
This will correct the errors `cannot use operator[] with a string
argument with string[..]` when loading a project
2023-05-11 09:57:29 +02:00
WerWolv
ab41899cc2 build: Updated libwolv 2023-05-11 09:54:06 +02:00
WerWolv
50c3cf8272 build: Replace old interval tree in favour of custom libwolv one 2023-05-11 09:27:23 +02:00
WerWolv
1d2b8ac1f3 fix: Closing popups using Esc causing them to re-appear 2023-05-10 22:29:17 +02:00
WerWolv
0b29719fe9 patterns: Updated pattern language 2023-05-10 19:15:01 +02:00
WerWolv
5a6e5d2255 build: Switch to better interval tree implementation 2023-05-07 23:27:43 +02:00
WerWolv
82111617a4 patterns: Updated pattern language 2023-05-06 10:09:33 +02:00
WerWolv
0574387ee1 fix: Properly use absolute paths when compiling magic files 2023-05-06 10:09:23 +02:00
WerWolv
2d1381860d fix: Corrected build issues with GCC 13 2023-05-06 10:07:22 +02:00
classabbyamp
82f5900759 build: Added option to disable update checking (#1036)
This is aimed at use by linux distros, where package updates come from a
central location, and users shouldn't need to worry about updating ImHex
on their own. This disables parts of the ImHex UI that would not be
useful in that case.

Tested and confirmed that this works in both states of the of the
`-DIMHEX_DISABLE_UPDATE_CHECK` switch.
2023-05-05 22:03:45 +02:00
iTrooz
e44eb2aa8e impr: Added more documentation to libimhex (#1052)
This PR adds some documentation. It's actually pretty random, I followed
the function calls I was curious about and commented whenever I wasn't
sure/I thought it needed clarification

You might want to make sure to squash them, because the commits are kind
of a mess, I didn't went through the effort of interactive rebase
2023-05-05 22:02:18 +02:00
iTrooz
34e12e2515 feat: Added a button to restore default layout when there are no views open (#1053)
Co-authored-by: Nik <werwolv98@gmail.com>
2023-05-05 22:00:17 +02:00
iTrooz
980e4cad06 fix: Handle errors in Tar::readVector() (#1059) 2023-05-05 21:57:37 +02:00
WerWolv
5680b90549 fix: Project files failing to save when no custom encoding is loaded 2023-05-04 23:23:44 +02:00
WerWolv
bec655a8c6 impr: Added event logging in debug mode 2023-05-02 20:35:30 +02:00
WerWolv
0c8b3e31e7 fix: Dangerous function call popup not showing up 2023-05-02 20:34:37 +02:00
WerWolv
a33c7135d1 fix: Crash when closing some popups 2023-05-01 14:15:00 +02:00
iTrooz
13a3942f8f impr: Show an error message when ImHex can't open a file (#1050)
This PR does two correlated things:

- Show a generic error message (Failed to open provider) rather than a
file-specific message (Failed to open file) when a provider fails to
open
- Set the error to something more specific when opening a file fails
2023-04-30 18:37:22 +02:00
WerWolv
1bdc1d7241 build: Added CMakePresets.json file to make configuring/building easier 2023-04-30 11:53:51 +02:00
iTrooz
fe9026b68d build: Update my (iTrooz) email in PKGBUILD (#1049) 2023-04-28 18:01:30 +02:00
XorTroll
b0028b0e51 lang: Added Spanish translations (#1042)
This translates ImHex for the Spanish language

(made a new PR since I got a bit messed up on the other one, this was
faster to fix)
2023-04-21 17:44:36 +02:00
WerWolv
f54617e92f patterns: Updated pattern language 2023-04-21 11:02:12 +02:00
WerWolv
306690762c impr: Drastically improve file read speeds 2023-04-21 10:52:10 +02:00
WerWolv
58a0fe8109 patterns: Updated pattern language 2023-04-20 14:32:45 +02:00
WerWolv
1e39f4354f fix: Provider reader being broken 2023-04-20 13:46:44 +02:00
WerWolv
e1b12546da build: Updated dependencies 2023-04-20 10:48:17 +02:00
WerWolv
1b28bf1474 patterns: Updated pattern language
Fixes #1037
2023-04-20 10:41:27 +02:00
WerWolv
8245f3d4c9 build: Updated libwolv 2023-04-19 21:56:34 +02:00
Nik
5fc8e710a5 git: Added vulnearability report info file 2023-04-18 16:15:48 +02:00
Nik
b8636a8589 git: Added Code of Conduct 2023-04-18 16:11:41 +02:00
WerWolv
bb8b4afb85 patterns: Updated pattern language 2023-04-18 10:32:38 +02:00
WerWolv
d5b1ef7875 patterns: Updated pattern language 2023-04-18 10:17:37 +02:00
WerWolv
6c122e5fbe patterns: Updated to new API 2023-04-18 10:06:47 +02:00
WerWolv
7ae814f7fb fix: Various localization issues 2023-04-17 22:18:50 +02:00
WerWolv
bdc51dd8a5 patterns: Updated pattern language 2023-04-17 17:06:52 +02:00
WerWolv
04a5efc7a3 fix: Crash when evaluating patterns to quickly 2023-04-17 17:02:10 +02:00
WerWolv
99a736df27 impr: Replace horrible pattern extra data class with a more modular system 2023-04-17 16:18:48 +02:00
WerWolv
535aeb5e39 impr: Give access to a console in clion in debug mode 2023-04-17 16:06:06 +02:00
WerWolv
07bef10092 patterns: Updated pattern language 2023-04-17 09:22:21 +02:00
WerWolv
c32515bc44 impr: Clean up some more clang-tidy issues 2023-04-16 22:12:35 +02:00
WerWolv
1690cd2740 fix: Various issues with the new popup system 2023-04-16 21:34:29 +02:00
WerWolv
52925c99e8 impr: Default to monitor synchronized FPS limit 2023-04-13 17:12:40 +02:00
WerWolv
1367e9cebe build: Fixed Objective-C compiler flags 2023-04-13 17:07:34 +02:00
WerWolv
3e87022da1 fix: Provider undo stack not being handled correctly 2023-04-13 16:12:00 +02:00
WerWolv
143fe36d35 build: Fixed various build warnings 2023-04-13 16:11:39 +02:00
WerWolv
18d5fd5d3e fix: Commit link in about page not working correctly 2023-04-13 16:10:55 +02:00
WerWolv
2829bf2640 fix: New lines appearing in pattern editor when switching provider 2023-04-13 15:03:50 +02:00
WerWolv
ffafb05d3d fix: Providers with the same name not being selectable in diff view
Fixes #1034
2023-04-13 15:03:14 +02:00
WerWolv
cf72b5ec5c fix: Some shortcuts triggering twice 2023-04-12 19:50:03 +02:00
WerWolv
803b99f2a9 impr: Immensely improve provider read speeds 2023-04-12 19:21:48 +02:00
WerWolv
86b49f34d9 patterns: Updated pattern language
Fixes #1031
2023-04-12 17:18:46 +02:00
WerWolv
7e144b136b patterns: Updated pattern language
Fixes #1030
2023-04-12 16:03:58 +02:00
WerWolv
aa7c5422c0 fix: Make sure provider data is properly cleared when deleting provider 2023-04-11 15:26:18 +02:00
WerWolv
5512585cc5 fix: Make sure docs question request is always properly formatted 2023-04-10 23:05:44 +02:00
WerWolv
013eaae715 fix: Disable multi window support on Linux by default as it causes issues
Fixes #1026
2023-04-10 22:51:21 +02:00
WerWolv
349b5da810 fix: Prevent constants view from growing past the size of the screen
Fixes #1025
2023-04-10 21:30:27 +02:00
WerWolv
e7494be5e7 fix: Last line of patterns going missing in projects with multiple files
Fixes #1012
2023-04-10 16:50:23 +02:00
WerWolv
320629931c fix: Yet another popup centering issue 2023-04-10 14:10:35 +02:00
WerWolv
87d0aae608 feat: Added selection range radio button to various views
Closes #1024
2023-04-10 14:08:21 +02:00
WerWolv
391c8acfe4 impr: Added path tooltips to accept pattern popup 2023-04-10 01:46:55 +02:00
WerWolv
dc77d81e1b feat: Added documentation helper AI 2023-04-10 01:42:53 +02:00
WerWolv
00c9a92977 fix: Localization being broken in the content store 2023-04-10 01:42:28 +02:00
WerWolv
af4dd9f5b0 fix: Popup positioning being wrong 2023-04-09 23:24:48 +02:00
WerWolv
09f1b56964 fix: Popups not being centered correctly 2023-04-09 15:28:48 +02:00
WerWolv
f9a08f5c11 feat: Allow custom alignment to be used in binary sequence search 2023-04-09 15:28:31 +02:00
WerWolv
e79664256a patterns: Updated pattern language 2023-04-09 12:26:13 +02:00
WerWolv
70f3014390 fix: Some more popup rendering issues 2023-04-08 23:34:46 +02:00
WerWolv
b4d0f984a4 build: Updated libwolv 2023-04-08 21:13:19 +02:00
WerWolv
d4ad457af1 fix: Crash when closing provider that was used in view provider 2023-04-08 21:07:57 +02:00
WerWolv
cb5d197700 impr: Added tooltips to icon buttons in bookmarks view 2023-04-08 21:07:41 +02:00
WerWolv
78e66f8959 feat: Added non-ranged and aligned search to sequence and value finder 2023-04-08 20:59:33 +02:00
WerWolv
f562260e42 fix: Build error again 2023-04-08 12:30:38 +02:00
WerWolv
21f38974a8 impr: Use smart pointers to allocate Views 2023-04-08 12:08:45 +02:00
WerWolv
dfca7e923c feat: Make pins in data processor nodes more visible 2023-04-08 11:58:49 +02:00
WerWolv
6913598de4 fix: Build error 2023-04-08 11:58:12 +02:00
WerWolv
ac858b37ed fix: Main Menu items not being clickable at the outer most pixel
Closes #1020
2023-04-08 11:37:42 +02:00
WerWolv
80edaea392 impr: Update all of ImHex to the new popup system 2023-04-08 00:58:53 +02:00
WerWolv
9c9ac23818 feat: Added a much more flexible popup system 2023-04-07 10:21:27 +02:00
WerWolv
51e615095e fix: Make sure placing a type through the Edit menu re-evaluates the pattern 2023-04-06 23:01:45 +02:00
WerWolv
d92e7d19cc fix: Submenu items ignoring enabled flag 2023-04-06 22:33:02 +02:00
WerWolv
248b93f41a patterns: Updated pattern language 2023-04-06 19:23:16 +02:00
WerWolv
c73f33aac2 impr: Added various new events 2023-04-06 17:36:28 +02:00
WerWolv
7c18ad49ae impr: Allow windows that overlap the main window title bar to be movable 2023-04-06 14:58:05 +02:00
WerWolv
5f713882d4 fix: Occasional crash when loading project files 2023-04-06 12:44:25 +02:00
WerWolv
1698f1599b impr: Allow file chooser to open files using double click 2023-04-05 18:33:05 +02:00
WerWolv
24e584c77b fix: Crash when trying to place pattern language variable through the Edit menu
Fixes #1013
2023-04-05 18:29:30 +02:00
WerWolv
a5568d09d8 patterns: Updated pattern language
Fixes #1011
2023-04-05 18:03:30 +02:00
WerWolv
7a4f909c68 fix: Disassembler arch names not correctly corresponding to their ids
Fixes #1010
2023-04-05 18:02:47 +02:00
WerWolv
89aee456c6 patterns: Updated pattern language
Fixes #1011
2023-04-05 07:26:44 +02:00
WerWolv
4cf92103d8 fix: Names of disassembler architectures not corresponding to their actual type
Fixes #1010
2023-04-05 07:20:06 +02:00
WerWolv
e3b1ebb826 patterns: Updated pattern language 2023-04-04 23:42:39 +02:00
WerWolv
3658d8d96e fix: Disassembler not supporting any Capstone 5 features anymore
Fixes #1010
2023-04-04 23:08:10 +02:00
WerWolv
6c047f01f9 git: Fixed release CI not reading version correctly 2023-04-04 21:59:43 +02:00
WerWolv
fc105ecc3d build: Bumped version to 1.28.0 2023-04-04 12:04:22 +02:00
WerWolv
649f6c28bf patterns: Updated pattern language 2023-04-04 11:20:09 +02:00
WerWolv
867972b7f5 patterns: Updated pattern language 2023-04-04 10:23:01 +02:00
WerWolv
efe3227ef2 patterns: Updated pattern language 2023-04-04 09:34:50 +02:00
H1X4
aab8c88a96 feat: allow loading and saving pattern code via events (#1004)
Currently there is no way to save the pattern code progamically from a
plugin unless the builtin plugin is modified to add those events. This
pull request will be adding ability to load and save pattern code from
specified file.
2023-04-01 11:18:52 +02:00
Thomas
af18ca011b fix: Modified bytes visually reverting back after saving (#1003)
Fix #988

Co-authored-by: Nik <werwolv98@gmail.com>
2023-04-01 11:18:03 +02:00
Thomas
24106b860a impr: Added some documentation to providers (#1001) 2023-04-01 11:17:19 +02:00
WerWolv
60efb6973b fix: Filtering of long strings in find view not working correctly 2023-04-01 11:04:07 +02:00
WerWolv
cffd55bdda fix: UTF-16BE search being broken 2023-03-31 22:20:00 +02:00
WerWolv
88e767aaaf fix: Crash when loading big encoding files 2023-03-31 19:56:20 +02:00
WerWolv
d6cda43618 fix: Modified bytes visually reverting back after saving 2023-03-31 19:18:31 +02:00
WerWolv
3b229cd5cb impr: Added path tooltips to entries in the file chooser popup 2023-03-31 19:17:27 +02:00
WerWolv
72c4dbdb2f patterns: Updated pattern language 2023-03-31 13:49:59 +02:00
WerWolv
4da18d3630 fix: Custom encoding and text padding setting not applying to custom encoding column
Actually fixes #1005
2023-03-31 13:49:33 +02:00
WerWolv
2f04cfd5c6 fix: Entering decimal and float values in hex editor cells being broken 2023-03-31 11:34:08 +02:00
WerWolv
8195db6d4c fix: Prevent occasional crash when having ImHex open and connecting to the computer over RDP 2023-03-31 11:08:53 +02:00
WerWolv
722f6315c4 impr: Make sure shortcuts can't be used when popups are open 2023-03-31 11:07:53 +02:00
WerWolv
173ed5475c fix: Remove empty column when ASCII row is off and custom encoding is on
Fixes #1005
2023-03-31 11:07:32 +02:00
WerWolv
1460044e91 impr: Save custom encoding file to project
Fixes #1005
2023-03-31 11:06:51 +02:00
WerWolv
06a7b6e446 patterns: Fixed namespace of hex::prv:: functions 2023-03-28 10:27:49 +02:00
WerWolv
28b7b4b7f1 fix: File -> Open Others... menu not working correctly 2023-03-28 10:13:41 +02:00
WerWolv
8930adf532 patterns: Updated pattern language 2023-03-28 09:29:49 +02:00
WerWolv
f44b8a5618 patterns: Updated pattern language 2023-03-27 22:40:19 +02:00
WerWolv
6a9f79628e impr: Don't try to apply patches if there are none 2023-03-26 12:48:22 +02:00
Jonathan Wright
245c56ba8a build: Added Fedora 38 build (#928)
Co-authored-by: Thomas <hey@itrooz.fr>
2023-03-26 11:37:46 +02:00
WerWolv
98846421f6 build: Update dependencies 2023-03-26 11:23:32 +02:00
WerWolv
0aaeeffff7 build: Fixed capitalization of ImHex in MSI installer 2023-03-26 11:22:50 +02:00
Thomas
c2823facc2 lang: Fix weblate (#997)
This should (hopefully) fix weblate. I tried to fix merge conflicts
using instructions at
https://weblate.werwolv.net/projects/imhex/windows-plugin/#alerts

---------

Co-authored-by: xtex <xtexchooser@duck.com>
2023-03-26 11:03:30 +02:00
Thomas
fabb1596e5 impr: Handle and show NFD errors (#995)
This PR handles errors that NFD might encounter (both in Init() and the
other method to open the dialog), and log them in the logs and in the
GUI

This (among other) fix the crash I had running ImHex as root and opening
a file
2023-03-26 11:02:51 +02:00
Thomas
725e32250b fix: Move config files to XDG_CONFIG_HOME (#993)
This pull request changes Config Directories on Linux to only include
the XDG_CONFIG_HOME directory, as opposed to all directories in
XDG_DATA_DIRS before (introduced in
https://github.com/WerWolv/ImHex/pull/644/files#diff-c1a4d2b63fed168a9a3568944e9cadeae096f2ddcec3649e4a9b2d29fd104be0L162-L166).

Reasons:
- This changes the location of the config file to the standard directory
meant for configurations
- This prevents the config file from being read/written in system
locations, like /usr/share

This PR also includes a migration task that will run on Linux and move
config/GUI dimensions to the new directory

as a bonus, as discussed on discord, it writes the logs to a Data
directory instead of a Config directory
2023-03-26 11:02:23 +02:00
Zaggy1024
5fa264ea18 patterns: Update pattern_language and implement support for new bitfield features (#992)
This requires https://github.com/WerWolv/PatternLanguage/pull/34 to be
merged first, and then this can be amended to update the submodule and
merged to add support for the new features.
2023-03-26 11:01:37 +02:00
WerWolv
5e175b118d build: Updated libwolv 2023-03-25 11:24:24 +01:00
WerWolv
635173e55a impr: Make sure themes are added correctly when downloaded from the store 2023-03-23 20:35:16 +01:00
WerWolv
eb2ed6852c build: Make SSL work when using system curl on WIndows 2023-03-23 20:12:33 +01:00
WerWolv
2296766746 build: Allow building with capstone 4.X again 2023-03-23 16:45:00 +01:00
WerWolv
13be499510 build: Pull in latest version of libyara and libcurl 2023-03-23 16:30:55 +01:00
WerWolv
fec5c567e1 ui: Improve look and feel of content store 2023-03-23 13:32:47 +01:00
WerWolv
8ef863cae1 fix: Progress not working with with new http wrapper 2023-03-23 13:32:35 +01:00
WerWolv
9463105172 fix: Header memory leak in http requests class 2023-03-23 12:08:33 +01:00
WerWolv
bb4819bce4 sys: Fixed http request stack overflow 2023-03-23 11:43:07 +01:00
WerWolv
15be24db62 sys: Updated to use the new HttpRequest helper instead of Net 2023-03-23 11:23:07 +01:00
WerWolv
e7e2af9f91 patterns: Updated pattern language 2023-03-23 09:41:32 +01:00
WerWolv
8c5fd021f7 api: Hook up new http wrapper to the rest of ImHex 2023-03-22 23:05:18 +01:00
WerWolv
1a1ba19770 api: Added new, more flexible curl http wrapper 2023-03-22 21:48:14 +01:00
WerWolv
f95214d8fe patterns: Updated pattern language 2023-03-22 17:43:45 +01:00
WerWolv
631cfce2f8 impr: Added tooltip informing about font size if no custom font was selected 2023-03-22 16:30:49 +01:00
WerWolv
45649264f9 patterns: Updated pattern language 2023-03-22 13:12:57 +01:00
WerWolv
0fd3cb0c4a fix: Don't jump to previous editing position when selecting new region in hex editor
Potenially fixes issues mentioned in #924
2023-03-22 13:11:09 +01:00
Jacob Creedon
3cfec69020 feat: Added additional CRC hash types (#991)
This adds some common CRC types.

---------

Signed-off-by: Jacob Creedon <jcreedon@gmail.com>
2023-03-22 10:53:57 +01:00
WerWolv
cec62d23b0 fix: Window resizing causing freezes in some cases 2023-03-21 22:39:35 +01:00
WerWolv
f3f0dda3d4 fix: Properly clear valid region when switching to a different provider 2023-03-21 16:11:40 +01:00
WerWolv
be16b66ac0 fix: Make sure files don't get truncated when using Save As on itself
Fixes #987
2023-03-21 15:42:10 +01:00
WerWolv
b9059aaa01 fix: Make find process in the find view more easily cancelable 2023-03-21 15:37:49 +01:00
WerWolv
57a62d0544 impr: Clean up entire API and added doc comments 2023-03-21 15:33:43 +01:00
WerWolv
d82f0e952f fix: Custom data inspector rows not being writable correctly 2023-03-21 13:16:22 +01:00
Thomas
8731b7582b impr: Display a more detailed errors when opening a raw disk provider failed (#970)
PR title is self explaining

I may modify other providers implementations to display a detailed error
message later

I'm not sure how to deal with other locales because the format changed.
Before, I had to add and comment the key in all locale files, now I'm
not so sure.
2023-03-21 10:33:00 +01:00
WerWolv
e6959dc572 patterns: Updated pattern language
Fixes #954
2023-03-21 10:31:13 +01:00
WerWolv
a36b4d65e3 build: Make sure commit hash and branch end up in nightly builds 2023-03-21 10:14:09 +01:00
WerWolv
060ff56f9d impr: Improve file reading performance if opening of files is slow 2023-03-21 09:47:42 +01:00
WerWolv
0a0c0c0d07 feat: Added bytes swapper tool 2023-03-20 22:25:27 +01:00
WerWolv
17c4e405a6 impr: Update the command palette for the modern ages 2023-03-20 17:05:26 +01:00
WerWolv
53afa6ea43 fix: Crash on exit 2023-03-20 15:18:48 +01:00
WerWolv
a182e8daf2 patterns: Updated pattern language
Fixes #983
2023-03-20 15:12:27 +01:00
WerWolv
a4dfaba03f fix: All menu item shortcuts being global 2023-03-20 15:12:12 +01:00
WerWolv
6e23560e80 feat: Added all menu items to command palette 2023-03-20 14:11:43 +01:00
WerWolv
39e8d557e8 sys: Completely revamped main menu item system 2023-03-20 13:11:43 +01:00
WerWolv
677c989664 feat: Allow custom data inspector rows to be edited 2023-03-20 08:30:34 +01:00
WerWolv
c9342d90fb fix: Prevent new line from appearing on every pl code save
Fixes #982
2023-03-20 08:29:00 +01:00
WerWolv
0693bb8d51 git: Fixed documentation shield style 2023-03-18 16:10:39 +01:00
WerWolv
5cd3c305d0 git: Added documentation link to readme 2023-03-18 16:09:45 +01:00
WerWolv
e00b59c393 fix: Properly discard reopened stderr 2023-03-18 11:47:42 +01:00
WerWolv
7c1e33dde6 sys: Prevent libraries from printing garbage to the console through stderr 2023-03-18 11:35:01 +01:00
WerWolv
367bd76046 ui: Mae sure all theme scaling values are scaled correctly 2023-03-18 10:52:50 +01:00
WerWolv
1a1bf98905 impr: Look for magic files recursively 2023-03-17 21:18:28 +01:00
WerWolv
4c1a24058c ui: Fixed various scaling inconsistencies on higher scaling factors 2023-03-17 19:58:08 +01:00
WerWolv
294e95caf8 fix: Store page not clearing nodes and themes section correctly 2023-03-17 17:55:39 +01:00
WerWolv
031884c327 patterns: Updated pattern language
Fixes #979
2023-03-17 17:28:17 +01:00
WerWolv
466dacaab4 ui: Improve the look and feel of the information view 2023-03-17 17:07:39 +01:00
WerWolv
1f8645fd43 fix: Occasional crash when multiple threads are reading data from a file provider 2023-03-17 11:43:50 +01:00
WerWolv
880568cc60 impr: Better find view result filter speeds 2023-03-17 11:32:08 +01:00
WerWolv
f10fb56042 impr: Drastically improve file reading performance 2023-03-17 11:31:50 +01:00
WerWolv
64be6d89ee fix: Moving cursor around using arrow keys behaving weirdly 2023-03-17 09:17:44 +01:00
WerWolv
5442c32a3f impr: Allow non-continuous provider values to be saved 2023-03-17 08:38:38 +01:00
WerWolv
4ee53701e6 impr: Allow Regex find strategy specify string type and minimum length 2023-03-17 08:16:13 +01:00
WerWolv
5097a223e3 impr: Added default saveAs implementation for all providers 2023-03-17 08:15:43 +01:00
WerWolv
7cdba75bef fix: Crash when not making a valid selection in provider load interfaces 2023-03-16 16:48:15 +01:00
WerWolv
0312027ca8 impr: Modernize look and feel of bookmarks 2023-03-16 14:40:26 +01:00
WerWolv
c726c96286 impr: Make comment field in bookmark tooltip more readable 2023-03-16 13:35:29 +01:00
WerWolv
5a2b2e0813 feat: Make yara match list sortable 2023-03-16 13:35:09 +01:00
WerWolv
4271b2e9fd fix: Yara view filtering out all but one match 2023-03-14 17:02:59 +01:00
WerWolv
13ef4c04d1 patterns: Updated pattern language
Closes #961
2023-03-14 14:41:32 +01:00
WerWolv
96c3bb1e38 feat: Limit recent files to 5 files, add option to disable saving them
Closes #950
2023-03-14 14:07:18 +01:00
WerWolv
a0b36925ed fix: Custom styles not being scaled correctly 2023-03-14 13:19:04 +01:00
WerWolv
daadc2ea71 impr: Attempt loading of full unicode plane from font if possible 2023-03-14 12:30:28 +01:00
WerWolv
ec2934b4b8 fix: Advancing to next row when editing bytes loading wrong value
Fixes #973
2023-03-14 10:24:25 +01:00
WerWolv
3a840c4ced impr: Properly display custom encoding characters that are split between lines 2023-03-14 09:35:43 +01:00
WerWolv
bd190d2b65 patterns: Updated pattern language 2023-03-13 11:36:11 +01:00
qux-bbb
9b05a36529 fix: Find view string filters filtering for some wrong characters (#972)
`\r` and `\n` need to be filtered.
2023-03-13 11:06:30 +01:00
WerWolv
d9a498e8ec build: Make sure libwolv is compiled with -fPIC 2023-03-13 10:39:34 +01:00
WerWolv
7d86b277a7 build: Updated curl and libyara 2023-03-13 10:24:56 +01:00
WerWolv
d463b3235e tests: Fixed building of tests 2023-03-13 10:24:48 +01:00
WerWolv
5a8433ede4 build: Updated libwolv 2023-03-13 09:31:24 +01:00
WerWolv
00a5fd2d7c sys: Fixed more build issues 2023-03-13 09:25:07 +01:00
WerWolv
55f9faea10 sys: Updated more code to libwolv 2023-03-13 08:58:08 +01:00
WerWolv
fb2e668589 sys: Moved more functions to libwolv 2023-03-12 18:43:05 +01:00
WerWolv
0dafb3d230 sys: Replaced many helper functions with libwolv 2023-03-12 18:27:33 +01:00
qux-bbb
e958934a22 fix: String search not including string at end of data (#963)
Before:  

![before](https://user-images.githubusercontent.com/18598419/222937056-fec74305-21a3-4bbf-a439-e8df7031bca9.png)

After:  

![after](https://user-images.githubusercontent.com/18598419/222937069-a04cb748-4266-4fbb-8182-727bb8858329.png)
2023-03-11 14:39:50 +01:00
Fenrisfulsur
069221757f feat: Added chunk based entropy analysis to information view (#933)
Issue: https://github.com/WerWolv/ImHex/issues/522

Implementation of chunk based entropy analysis in diagram.hpp available
from the data information view and in the pattern language.

---------

Co-authored-by: WerWolv <werwolv98@gmail.com>
2023-03-10 16:06:18 +01:00
WerWolv
505c1bc274 build: Fix Fedora build errors 2023-03-10 14:46:15 +01:00
qux-bbb
cdd5d33e89 feat: Make CTRL + N automatically create a memory provider (#966)
"CTRL + N" can open a mem_file directly.
2023-03-07 16:05:03 +01:00
WerWolv
f661f4d1d6 fix: GDB provider not working nicely anymore 2023-03-07 16:04:04 +01:00
Mimi1337
f435191585 fix: Dockerfile syntax error (#945) 2023-02-21 11:29:21 +01:00
WerWolv
00c2d7ea71 patterns: Updated pattern language 2023-02-20 11:35:33 +01:00
WerWolv
cddcc1e85d patterns: Updated pattern language 2023-02-19 10:49:57 +01:00
WerWolv
91928b45d8 fix: Try to fix build again 2023-02-19 10:25:39 +01:00
WerWolv
277c83e6d8 fix: Uninitialized value build issue 2023-02-19 09:18:17 +01:00
WerWolv
0017cd2e40 feat: Added binary hex cell visualizer
Closes #939
2023-02-18 22:20:02 +01:00
WerWolv
774803492c fix: Editing binary value in data inspector not working correctly
Fixes #941
2023-02-18 21:44:43 +01:00
WerWolv
83a9655772 patterns: Updated pattern language 2023-02-17 20:30:41 +01:00
WerWolv
58324b4539 build: Fixed linking against execinfo 2023-02-17 17:56:27 +01:00
WerWolv
09b7794d71 build: Added option to disable stack traces 2023-02-17 17:52:10 +01:00
WerWolv
9e3fe9beb1 patterns: Updated pattern language 2023-02-17 17:35:41 +01:00
WerWolv
ff525fe750 impr: Properly sort choose file dialog entries
Fixes #938
2023-02-17 14:59:19 +01:00
WerWolv
94977ad216 patterns: Updated pattern language 2023-02-17 14:55:56 +01:00
WerWolv
64e34e42b8 patterns: Fixed highlighting of custom sections 2023-02-17 14:53:15 +01:00
WerWolv
21dc65f42a impr: Added comments everywhere in main application 2023-02-17 12:03:53 +01:00
WerWolv
279e085887 impr: Don't create a new font texture for no reason 2023-02-17 12:03:00 +01:00
WerWolv
d84dfa2c42 feat: Allow custom CA Certs to be loaded
Fixes #907
2023-02-17 12:01:46 +01:00
WerWolv
bf8089dc7e impr: Don't memory map files, never keep a write handle open for long
Closes #592
2023-02-17 10:26:09 +01:00
WerWolv
e48761b5c0 fix: Plot lines being invisible 2023-02-17 10:02:43 +01:00
WerWolv
35437c0300 patterns: Added rotation and scale sliders to 3D visualizer 2023-02-16 23:24:24 +01:00
WerWolv
6cecc12d04 patterns: Updated pattern language 2023-02-16 22:20:03 +01:00
WerWolv
dec4231d49 impr: Make sure fonts don't get blurry on non-integer scalings 2023-02-16 20:53:58 +01:00
WerWolv
fb1d12ebf3 sys: Remove some problematic (and rarely used) scaling settings 2023-02-16 20:19:55 +01:00
WerWolv
b19276a3e9 patterns: Added match keyword to syntax highlighting 2023-02-16 19:10:08 +01:00
WerWolv
5ccbfc1ff8 feat: Allow themes and nodes to be downloaded from the content store 2023-02-16 18:55:21 +01:00
WerWolv
d3d6a8a838 patterns: Updated pattern language 2023-02-16 18:23:49 +01:00
WerWolv
ac83bbeb0e feat: Added a theme manager view to make it easier to make new themes 2023-02-16 18:06:40 +01:00
WerWolv
8cb76a26c1 fix: Font being scaled too big 2023-02-16 16:29:41 +01:00
WerWolv
20da22d59e sys: Make sure scrolling counts as an input event 2023-02-16 08:53:23 +01:00
WerWolv
d9fa4b452c impr: Clean up diff view 2023-02-16 08:53:05 +01:00
WerWolv
6216d72aa6 fix: Format string compile issues 2023-02-15 22:22:13 +01:00
WerWolv
851f132188 impr: Make Text Editor word selector also consider underlines 2023-02-15 17:12:16 +01:00
WerWolv
3067ff08ec feat: Greatly improved diff view
Fixes #631
2023-02-15 17:01:36 +01:00
WerWolv
07fd86fc9d git: Split release workflows into multiple steps 2023-02-15 10:21:56 +01:00
WerWolv
504037c115 build: Bumped version to 1.27.1 2023-02-15 09:39:23 +01:00
WerWolv
0fad21a980 patterns: Updated pattern language 2023-02-15 09:39:16 +01:00
WerWolv
8afd698284 impr: Correct some ugly code 2023-02-14 15:43:44 +01:00
WerWolv
9ec7b90192 patterns: Updated pattern language 2023-02-14 15:10:52 +01:00
WerWolv
08f0fff34b patterns: Updated pattern language 2023-02-14 12:53:37 +01:00
WerWolv
2c1073eda9 fix: Safety backup restore popup getting hidden by tip of the day 2023-02-14 11:45:32 +01:00
WerWolv
c9348f0651 patterns: Updated pattern language 2023-02-13 23:27:12 +01:00
WerWolv
accb461c08 impr: Better word select and delete in text editor
Closes #931
2023-02-13 10:21:57 +01:00
Thomas
75adcc0a96 build: Fix Arch package name in release CI (#929)
* Fix Arch package name in release CI

* update email address
2023-02-13 09:05:52 +01:00
WerWolv
61ce88ba9b build: Fix build on systems that have no backtrace or execinfo
Fixes #932
2023-02-13 08:27:08 +01:00
WerWolv
4b451fd1d3 patterns: Fixed pattern data rows not being selectable when color column is hidden 2023-02-13 08:26:43 +01:00
WerWolv
a87190960f build: Fixed one more missing imhex target name 2023-02-12 22:08:35 +01:00
WerWolv
45558027a6 git: Fixed release workflow 2023-02-12 21:55:22 +01:00
WerWolv
e426606542 build: Fixed flatpak build issues 2023-02-12 21:55:09 +01:00
WerWolv
4d60942fea build: Bumped version to 1.27.0 2023-02-12 19:24:04 +01:00
WerWolv
3003dea409 fix: Occasional error when loading recent files 2023-02-12 17:52:09 +01:00
WerWolv
0b18930017 fix: Invalid theme load error 2023-02-12 17:39:47 +01:00
WerWolv
54ef5785cd fix: ImNodes double free 2023-02-12 17:38:13 +01:00
WerWolv
d084ec78e9 nodes: Allow immediate values on integer and float inputs
Closes #427
2023-02-12 17:33:53 +01:00
WerWolv
a59c17aa83 nodes: Fixed loading saved nodes multiple times 2023-02-10 11:22:11 +01:00
WerWolv
6281adc7c3 nodes: Added a few new nodes 2023-02-10 08:18:06 +01:00
WerWolv
5cc01ae89d nodes: Added support for nested, shareable, custom data processor nodes 2023-02-09 23:07:04 +01:00
WerWolv
303dd28c7c fix: Fix macOS build again 2023-02-08 14:11:42 +01:00
WerWolv
dd87dc7046 fix: Building on macOS 2023-02-08 13:51:56 +01:00
WerWolv
235a64deef sys: One more attempt to fix macOS scaling issues 2023-02-08 12:53:34 +01:00
WerWolv
89a96c6d25 sys: Improve pattern visualizer API 2023-02-07 14:18:59 +01:00
WerWolv
4f0e5b99a8 pattern: Make visualizer button actually accessible again 2023-02-06 17:24:06 +01:00
WerWolv
f75f3f4661 pattern: Fixed wrong number of required parameters for image visualizer 2023-02-06 17:23:50 +01:00
WerWolv
b936a28921 fix: Opening files from command line not working 2023-02-06 07:11:21 +01:00
Jonathan Wright
d02507ae4b build: Re-enable Fedora rawhide builds (#920)
* re-enable rawhide builds

* Update build.yml

* Update imhex.spec

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2023-02-02 21:42:13 +01:00
WerWolv
0b576adcf8 fix: Another P2468R2 issue 2023-02-02 21:26:46 +01:00
WerWolv
22ff033b5e fix: More P2468R2 issues 2023-02-02 21:13:56 +01:00
WerWolv
b1edede53a fix: Invalid json comparison 2023-02-02 20:54:38 +01:00
WerWolv
3877f0853d patterns: Updated pattern language 2023-02-02 20:41:51 +01:00
WerWolv
9af8a0113a patterns: Updated pattern language 2023-02-02 19:06:00 +01:00
WerWolv
0d01f0c9d7 feat: Added function to import patches from a modified file 2023-02-02 14:13:37 +01:00
WerWolv
9911166c24 git: Added translation status batch to readme 2023-02-02 13:12:48 +01:00
WerWolvTranslationBot
01736d6409 lang: Updated German translation (#916)
Currently translated at 100.0% (842 of 842 strings)

Translation: ImHex/Built-in Plugin
Translate-URL: https://weblate.werwolv.net/projects/imhex/built-in-plugin/de/

Co-authored-by: Nik <werwolv98@gmail.com>
2023-02-02 11:58:09 +01:00
WerWolv
4ea8971adf lang: Added base translation files 2023-02-02 10:08:47 +01:00
WerWolv
8da072b602 lang: Get codebase ready for the use with Weblate 2023-02-02 09:41:58 +01:00
Berylskid
f6823d5f13 lang: Updated Japanese translation (#915) 2023-02-02 09:39:40 +01:00
WerWolv
941c7ee61d fix: Still properly divide scaling by 2.0 on macOS 2023-02-01 23:47:22 +01:00
WerWolv
fd259dcde3 fix: Prevent native scaling from going below 1.0 on macOS 2023-02-01 23:45:07 +01:00
WerWolv
79ecf7fa59 build: Fix non-Windows build 2023-02-01 09:38:03 +01:00
WerWolv
4c761df181 build: Improve build script a bit 2023-02-01 09:20:46 +01:00
WerWolv
94dc688324 ui: Change feedback link 2023-02-01 09:20:32 +01:00
WerWolv
357dd883db fix: Hexadecimal string inputs in data processor nodes behaving weirdly 2023-01-31 11:39:08 +01:00
WerWolv
3bad5e1d9c fix: ImHex still opening files when multiple builtin plugins are detected 2023-01-31 11:38:26 +01:00
WerWolv
d09982d99f fix: Crash when opening selection view
Fixes #913
2023-01-30 18:15:42 +01:00
Nik
fe7eb582a4 git: Added code quality tag to readme 2023-01-30 11:36:34 +01:00
WerWolv
c76b4bc9e9 impr: Removed a bunch of trailing white spaces 2023-01-30 11:11:30 +01:00
WerWolv
55d7d7c026 impr: Improve code quality 2023-01-30 10:42:07 +01:00
WerWolv
6b645192d4 fix: Diff view highlighting issues 2023-01-30 10:26:37 +01:00
WerWolv
d6bb408078 fix: All bytes being selected when opening a new provider 2023-01-30 10:10:37 +01:00
WerWolv
434ced44f0 fix: Build failing on macOS 2023-01-28 21:30:17 +01:00
WerWolv
c6e1f45dc3 feat: Added option to copy custom encoding strings from hex view 2023-01-28 21:12:35 +01:00
WerWolv
c861bf9a5e fix: Copying strings and bad names 2023-01-28 21:12:08 +01:00
WerWolv
86be1ef1ec impr: Make find view string filter case insensitive 2023-01-28 20:55:11 +01:00
WerWolv
c4d52da924 ui: Added cancel button to task running popup 2023-01-28 14:36:39 +01:00
WerWolv
a142d4fe20 ui: Make file chooser popup bigger 2023-01-28 14:28:06 +01:00
WerWolv
197e86f327 fix: Duplicate highlightings for every yara rule 2023-01-28 14:27:51 +01:00
WerWolv
b1aa58d446 feat: Allow selected yara rules to be saved to Project file 2023-01-28 14:15:15 +01:00
WerWolv
60a178f75e fix: Last column of diff view displaying all zeros
Fixes #908
2023-01-28 12:44:40 +01:00
WerWolv
6799263317 sys: Added a info popup when closing ImHex while tasks are still running 2023-01-28 12:16:41 +01:00
WerWolv
9b80486285 fix: Process Memory provider search not being case insensitive 2023-01-28 11:41:09 +01:00
WerWolv
3254376d28 fix: Editing static array values being broken 2023-01-28 00:03:20 +01:00
WerWolv
29c1a0cb78 feat: Allow multiple yara files to be selected at once 2023-01-28 00:01:53 +01:00
WerWolv
800ffb5e56 feat: Make it easier to apply multiple yara rules at once 2023-01-27 12:17:10 +01:00
WerWolv
1cf9f7e990 patterns: Updated pattern language 2023-01-27 10:45:07 +01:00
WerWolv
d928325fdf fix: Loading of Intel Hex and Motorola SREC files with new lines inbetween
Fixes #906
2023-01-26 11:06:00 +01:00
WerWolv
b3556c7c91 lang: Updated language files 2023-01-25 10:56:13 +01:00
WerWolv
4b112321d2 feat: Added base64 exporter
Closes #900
2023-01-25 10:51:00 +01:00
WerWolv
fee1b985c0 feat: Added better error messages for generating and importing ips patches 2023-01-25 10:38:04 +01:00
WerWolv
111eabb84c feat: Added scatter plot visualizer 2023-01-25 10:16:46 +01:00
WerWolv
f9bb4d828a ui: Improve visualizer button layout and error messages 2023-01-25 10:16:31 +01:00
WerWolv
434b7649c3 fix: CRC8 hashing algorithm displaying 16 bits result 2023-01-25 00:06:48 +01:00
WerWolv
fc44dd4592 build: Fixed building of miniaudio on macOS 2023-01-24 23:57:43 +01:00
WerWolv
8ea0e9ce9c fix: Sound visualizer being really laggy 2023-01-24 23:57:29 +01:00
WerWolv
94cd83e0dc feat: Added sound visualizer 2023-01-24 23:27:35 +01:00
WerWolv
27790532f8 fix: Crash when closing provider that had pattern loaded in some cases 2023-01-24 23:27:15 +01:00
WerWolv
90d9c91717 build: Cleanup opengl and glfw linking 2023-01-24 14:59:19 +01:00
WerWolv
32ed2c30c0 fix: Flickering task bar progress bar 2023-01-24 13:42:08 +01:00
WerWolv
cf9df6e36d feat: Added ability to query provider information from pattern language 2023-01-24 09:07:11 +01:00
WerWolv
915106f360 patterns: Fixed various issues with the 3d visualizer 2023-01-23 16:25:23 +01:00
WerWolv
a51e4afb05 patterns: Updated pattern language 2023-01-23 13:53:29 +01:00
WerWolv
c30f8fa459 patterns: Updated pattern language 2023-01-23 07:25:44 +01:00
WerWolv
46221e936f feat: Allow the 3d visualizer to use index buffers 2023-01-22 16:17:10 +01:00
WerWolv
c86891e0c3 fix: Custom encodings not rendering correctly on non-zero page 2023-01-22 14:17:55 +01:00
WerWolv
acf6b839e5 patterns: Updated pattern language 2023-01-22 12:16:22 +01:00
WerWolv
1f50e834fc fix: Copying bytes from non-zero page not working 2023-01-22 11:28:17 +01:00
WerWolv
6322dbf46a fix: Revert back macOS scaling fix as it made it worse 2023-01-21 22:59:08 +01:00
WerWolv
0e1aeee3fb patterns: Display bitfield field bit addresses from the start of the bitfield 2023-01-21 22:32:16 +01:00
WerWolv
173f279ac8 fix: Find view not correctly accepting hexadecimal values 2023-01-21 18:44:12 +01:00
WerWolv
89e0df86a2 feat: Added scaling and rotation to 3D visualizer 2023-01-21 13:00:02 +01:00
WerWolv
7ba9349de2 patterns: Updated pattern language 2023-01-21 12:31:33 +01:00
WerWolv
15fb288a5b fix: Yara view only loading in .yar files and not .yara files 2023-01-21 10:10:05 +01:00
WerWolv
f17e04273d fix: IPS patch applying being broken 2023-01-21 00:29:16 +01:00
WerWolv
76d47bf856 fix: MacOS Build errors because of khronos includes 2023-01-21 00:11:33 +01:00
WerWolv
d4967018c2 feat: Added basic lighting and rotations to 3d visualizer model 2023-01-20 23:32:51 +01:00
WerWolv
8e759d9b5f feat: Added basic 3D visualizer, moved visualizers to separate file 2023-01-20 21:16:28 +01:00
WerWolv
a9cebed903 ui: Disable Jump To command when too many bytes are selected 2023-01-19 17:08:17 +01:00
WerWolv
58a70f6ad8 ui: Move around File menu items to make more logical sense 2023-01-19 17:05:54 +01:00
WerWolv
05c8158716 feat: Added a new division by invariant multiplication tool 2023-01-19 17:01:41 +01:00
WerWolv
17b0f2ae77 feat: Added a description to the IEEE754 decoder tool 2023-01-19 17:01:19 +01:00
WerWolv
b54e6ea531 ui: Always add a spacing at the end of all tools 2023-01-19 16:59:59 +01:00
WerWolv
b702ad4190 fix: Occasional crash when loading a provider 2023-01-19 16:59:34 +01:00
WerWolv
4fb544d59d fix: Views starting out super tiny 2023-01-19 16:59:09 +01:00
WerWolv
e37a73ae58 patterns: Updated pattern language 2023-01-19 12:19:09 +01:00
WerWolv
c5d2739a39 fix: File provider sometimes not saving path to project file 2023-01-19 11:09:24 +01:00
WerWolv
def40c908e patterns: Added basic disassembler visualizer 2023-01-18 17:17:34 +01:00
WerWolv
ef12798fe2 feat: Allow custom hashes to be saved to projects 2023-01-18 14:30:56 +01:00
WerWolv
c747c15567 fix: Buffer overflow caused by hex input boxes 2023-01-18 14:30:44 +01:00
Nik
48a57cd981 feat: Added stacktrace printing on crashes (#892)
* feat: Added simple stack trace output

* feat: Added backtrace wrapper

* build: Added libbacktrace include dirs to build

* build: Fixed libbacktrace variables

* build: More backtrace variable fixes

* build: Try to find backtrace include

* build: Get backtrace header from cmake script

* feat: Added backtrace support for execinfo

* feat: Added support for StackWalk on Windows
2023-01-17 21:38:56 +01:00
WerWolv
3ddef07284 fix: ImHex failing to load in Portable mode from a folder with no permissions
Fixes #881
2023-01-17 09:59:57 +01:00
Kuruyia
a65f0a5238 feat: Support macOS keyboard shortcuts (#889) 2023-01-17 08:16:02 +01:00
birdstakes
ca68150970 fix: Frame rate not unlocking correctly (#890)
m_hadEvent could be set during glfwWaitEventsTimeout and then
immediately cleared before ever being checked.
2023-01-17 08:14:40 +01:00
WerWolv
92f0aa9593 fix: Logs always being saved to user folders
Fixes #888
2023-01-16 19:39:00 +01:00
WerWolv
b368b9c6d1 git: Make install instructions reflect actual release names 2023-01-16 18:20:22 +01:00
WerWolv
7e17059154 sys: Improved exception debug output 2023-01-16 18:17:13 +01:00
WerWolv
e078d810de git: Added install instructions for all release builds
#887
2023-01-16 13:41:24 +01:00
WerWolv
62bf877046 patterns: Updated pattern language
Fixes #880, Fixes #863
2023-01-15 22:59:15 +01:00
WerWolv
1b56c7ffae ui: Show task progress in task bar 2023-01-14 14:21:16 +01:00
WerWolv
f7e22ce651 patterns: Updated pattern language 2023-01-14 14:20:48 +01:00
WerWolv
b9c2b1de5f patterns: Updated pattern language 2023-01-13 22:30:57 +01:00
WerWolv
0c302da0db build: Add option to use the GTK file picker instead of portals on Linux
Fixes #882
2023-01-13 20:11:27 +01:00
WerWolv
45492365be fix: Potentially fix scaling issues on macOS 2023-01-13 20:06:03 +01:00
WerWolv
b497e9d867 git: Switch to different repo dispatch action 2023-01-13 08:58:03 +01:00
Nik
2840935f3d build: Added glfw to Brewfile 2023-01-13 01:01:43 +01:00
Thomas
69c0e6ee6e git: Do not run make install for tests (#879)
Co-authored-by: Nik <werwolv98@gmail.com>
2023-01-13 00:32:17 +01:00
Thomas
78b07e0a46 git: Make runner cache keys unique (#878) 2023-01-13 00:10:28 +01:00
Thomas
5a865774d1 git: Cleanup build CI + separate Ubuntu and AppImage builds (#873)
* remove flatpak

rationale: if we need it again we can always get it back from old commits

* remove double spaces

* remove Fedora rawhide

* remove Windows installer signing

* separate Ubuntu and AppImage builds
2023-01-12 23:50:59 +01:00
WerWolv
8d9667c2e0 fix: Yara rules being unable to include files
Fixes #875
2023-01-12 23:29:48 +01:00
WerWolv
1f6acc101f feat: Allow OTF fonts to be selected 2023-01-12 11:37:19 +01:00
WerWolv
0d91db68db patterns: Added bitmap visualizer 2023-01-12 11:18:36 +01:00
WerWolv
825e788646 git: Added more information to the readme requirements section 2023-01-12 08:50:16 +01:00
Thomas
f3815673c0 git: Fix typo on 'Chocolatey' + add uppercase on 'Winget' (#870)
* Fix typo on 'Chocolatey'

* add uppercase on 'Winget'
2023-01-12 08:25:51 +01:00
Thomas
b070092a64 git: Add architecture to build artifacts (#869)
* rename win64 artifact to Windows

* add architecture to all artifact names
2023-01-12 08:25:28 +01:00
WerWolv
25ede7ad18 fix: List all intel hex and motorola srec file extensions manually
Fixes #871
2023-01-12 08:20:15 +01:00
WerWolv
03d216f116 feat: Allow most resources to be loaded relative to the current project 2023-01-11 23:31:25 +01:00
WerWolv
b1cab5ccd2 patterns: Updated pattern language 2023-01-11 11:22:01 +01:00
Jonathan Wright
04d0458ae7 build: Improve Fedora builds and add EL9 build. (#861) 2023-01-10 23:10:34 +01:00
WerWolv
3b5d54dd96 fix: Text Editor behaving a bit weirdly now 2023-01-10 19:27:27 +01:00
WerWolv
87571450f4 patterns: Updated pattern language 2023-01-10 16:20:54 +01:00
WerWolv
766fd626f2 fix: Hex editor editing cursor not advancing on non-zero pages 2023-01-10 13:48:50 +01:00
WerWolv
be1f711fda fix: Pattern editor not scrolling all the way to the right when typing 2023-01-10 13:27:16 +01:00
WerWolv
ef3627321c sys: Clear project after loading crash backup 2023-01-10 08:57:29 +01:00
WerWolv
dbcb13f473 patterns: Disallow application/octet-stream to be used as MIME type 2023-01-09 08:38:19 +01:00
WerWolv
c1359a71d6 feat: Added options to automatically expand or flatten the pattern tree 2023-01-08 16:06:26 +01:00
WerWolv
b1a26d02c1 patterns: Updated pattern language 2023-01-08 10:20:54 +01:00
WerWolv
ceae23eab1 fix: Crash when opening a project file when already having providers open 2023-01-07 22:43:48 +01:00
Thomas
ab29303c2e sys: Clear project context when closing all providers, Display project name in window title (#860)
* clear project context when closing all providers

* Show project name on window title

* refactor RequestChangeWindowTitle to RequestUpdateWindowTitle

* add spaces
2023-01-07 17:31:22 +01:00
Thomas
ed831c6fc9 fix: Do not check for writable provider to save project, disable shortcut when unavailable (#859)
* do not check for writable provider to save project

* disable save project shortcut when we can't save it

* log when project is saved
2023-01-07 17:16:43 +01:00
WerWolv
d86be9d9b3 sys: putenv sucks. Use setenv instead 2023-01-07 10:56:03 +01:00
WerWolv
c26bed894b sys: Add imhex/lib path to plugin libraries search paths 2023-01-07 10:32:01 +01:00
Chien Wong
27cf5953ae fix: Typo of IEEE 754 (#856) 2023-01-06 13:12:10 +01:00
WerWolv
d0b3a60a09 build: Bumped version to 1.26.2 2023-01-05 16:37:53 +01:00
WerWolv
15f2376c62 sys: Fixed some variable names 2023-01-05 16:27:52 +01:00
WerWolv
efeeea37f6 build: Updated libromfs properly 2023-01-05 16:27:16 +01:00
WerWolv
5726e52df2 ui: Make content store resizable again 2023-01-05 13:23:08 +01:00
WerWolv
a1b596adc0 build: Bumped version to 1.26.1 2023-01-05 09:53:49 +01:00
WerWolv
763196f0cc feat: Added filtering to Process Memory Provider 2023-01-05 09:30:15 +01:00
WerWolv
ff9048fcf0 fix: Crash on exit
Fixes #854
2023-01-05 09:29:33 +01:00
WerWolv
7d9c86f584 fix: Crash when loading themes on Linux and MacOS 2023-01-04 23:56:36 +01:00
WerWolv
6129360b06 patterns: Updated pattern language
Fixed #853
2023-01-04 19:39:01 +01:00
WerWolv
3c5e91b611 build: Bumped version to 1.26.0 2023-01-04 16:09:23 +01:00
WerWolv
e529a79ddb fix: Template pattern types being placeable using right click menu 2023-01-04 15:50:37 +01:00
WerWolv
45bb9e6706 build: Fix some more ObjC issues 2023-01-04 14:55:58 +01:00
WerWolv
e6d14507e2 fix: Window title not resetting when closing all providers 2023-01-04 14:24:18 +01:00
WerWolv
9a5881fc47 build: Fixed -Wpedantic issues on macOS 2023-01-04 14:24:07 +01:00
WerWolv
f7dd28002e build: Build everything using -Wpedantic 2023-01-04 14:03:09 +01:00
WerWolv
496b0ec41d build: Fixed more build errors 2023-01-04 13:29:39 +01:00
WerWolv
02df578939 build: Fix library linking on non-windows 2023-01-04 13:23:42 +01:00
WerWolv
eb4a1e2692 build: Try to clean up bundled dependencies a bit 2023-01-04 12:34:38 +01:00
WerWolv
e6bec7d2b2 patterns: Updated pattern language 2023-01-04 10:20:50 +01:00
WerWolv
80f3bbb0af feat: Added DLL injection option, fixed memory region addresses 2023-01-04 10:02:17 +01:00
WerWolv
3a117b3bed feat: Display process icons in process memory provider 2023-01-03 16:34:22 +01:00
WerWolv
ff91335011 fix: ImNodes theme colors 2023-01-03 13:14:23 +01:00
WerWolv
01917439dd fix: More invalid iterator accesses 2023-01-03 13:04:36 +01:00
WerWolv
f21c80c48a build: More libfmt fixes 2023-01-02 01:38:07 +01:00
WerWolv
3dc42b711c fix: Plot lines being invisible 2023-01-01 23:53:50 +01:00
WerWolv
4b2863ca14 patterns: Updated pattern language 2023-01-01 22:15:47 +01:00
WerWolv
fe1b4b45b5 patterns: Updated pattern language 2023-01-01 21:48:20 +01:00
WerWolv
a20d6aa2b2 fix: Project file creation issues 2023-01-01 21:46:41 +01:00
WerWolv
78e52a0fe3 patterns: Updated pattern language 2023-01-01 20:25:41 +01:00
WerWolv
b4b507ecc9 lang: Added missing localizations for new provider 2023-01-01 19:14:57 +01:00
WerWolv
d7d19d7594 feat: Further improve process memory provider 2023-01-01 12:26:27 +01:00
WerWolv
90df4413c3 feat: Added basic windows process memory provider 2023-01-01 02:29:38 +01:00
WerWolv
4cd6646cca build: Enable libstdc++ assertions in debug builds 2023-01-01 01:05:01 +01:00
WerWolv
87ed0d31d4 fix: Various invalid iterator and container accesses 2023-01-01 01:01:24 +01:00
WerWolv
921bdd9e3b patterns: Updated pattern language 2022-12-31 10:28:41 +01:00
WerWolv
1f51a603f0 patterns: Updated pattern language 2022-12-30 12:47:23 +01:00
WerWolv
5fbbdb8e3c git: Make main logo respect color theme 2022-12-30 12:07:51 +01:00
WerWolv
745da6ba45 build: Only use --export-all-symbols on Windows 2022-12-30 11:24:53 +01:00
WerWolv
ad71e612a3 build: Clean up some old compiler/linker flag settings 2022-12-30 10:35:11 +01:00
WerWolv
85823e8e5d build: Removed all usages of Python 2022-12-29 23:32:57 +01:00
WerWolv
b4fa8bebe9 build: Move main romfs to main application 2022-12-29 23:32:40 +01:00
WerWolv
7859a9bb1f feat: Added native custom theme support 2022-12-29 19:26:00 +01:00
WerWolv
696d8d1d54 feat: Allow pasting of bytes with prefixes and comma separators
Closes #581
2022-12-29 15:08:44 +01:00
123456abcdef
6e8d3e0d7f fix: Wrong i18n labels (#852) 2022-12-29 15:07:43 +01:00
123456abcdef
6a0422fb27 lang: Update german translation (#851) 2022-12-29 15:07:32 +01:00
WerWolv
26898feb62 ui: Improve colors of digram and layered distribution plot 2022-12-29 15:06:23 +01:00
WerWolv
0311feee9b feat: Further improve information view 2022-12-28 23:06:49 +01:00
WerWolv
cf601586fc fix: Deadlock when loading recent files 2022-12-28 23:06:27 +01:00
WerWolv
f7b988906e fix: Saving projects to unicode paths not working correctly 2022-12-28 10:46:02 +01:00
WerWolv
5777a6d401 patterns: Updated pattern language 2022-12-27 23:26:25 +01:00
WerWolv
4807ca0057 feat: Added Digram and Layered Distribution plots to information view 2022-12-27 22:50:37 +01:00
WerWolv
f1aeec309e fix: New lines not being drawn in pattern console 2022-12-27 22:50:16 +01:00
WerWolv
4b8e275254 fix: Crash when closing providers too quickly 2022-12-27 11:35:20 +01:00
WerWolv
4b6a75fb60 feat: Added type distribution graph to information view 2022-12-25 15:45:49 +01:00
WerWolv
d463491026 ui: Fixed bookmarks displaying too many bytes in some cases 2022-12-25 10:01:39 +01:00
WerWolv
df3d5e38ce ui: Load in all extended-Ascii and control characters from unifont 2022-12-25 10:01:21 +01:00
WerWolv
4e22d636d3 fix: Yet another hex editor scrolling issue 2022-12-24 15:29:42 +01:00
WerWolv
e71841b871 fix: Crash when printing NULL bytes to the pattern console 2022-12-24 15:29:20 +01:00
WerWolv
e272c5d000 build: Updated dependencies 2022-12-24 15:28:51 +01:00
WerWolv
0d7740773e sys: Improve speed and UX of entropy graph 2022-12-23 14:34:06 +01:00
WerWolv
e4fbb1b640 pattern: Added basic line plot and image visualizer 2022-12-23 14:33:27 +01:00
WerWolv
986252d97f pattern: Make sure pattern tree doesn't randomly collapse when evaluating 2022-12-21 11:31:33 +01:00
WerWolv
e0c1fc81e3 build: Download Mesa3D from werwolv.net instead 2022-12-21 07:13:31 +01:00
WerWolv
ee94e9d619 patterns: Updated pattern language 2022-12-21 00:14:42 +01:00
WerWolv
264da1ed78 pattern: Show array entries directly if there are less than 512 2022-12-20 20:56:01 +01:00
WerWolv
ce37c795a7 patterns: Updated pattern language 2022-12-19 15:38:51 +01:00
Nik
ed2297ab7f git: Fixed build badge 2022-12-19 09:05:22 +01:00
WerWolv
ae5d8c9aad build: Updated libromfs 2022-12-19 08:52:12 +01:00
WerWolv
603ff9256c build: Actually use correct fcntl.h 2022-12-19 07:16:38 +01:00
WerWolv
a966cab155 build: Use correct fcntl.h include on Linux 2022-12-19 07:15:18 +01:00
WerWolv
978dd65528 patterns: Make editing patterns feel better 2022-12-18 23:53:53 +01:00
WerWolv
6502920047 patterns: Move pattern editing behind a double click 2022-12-18 23:11:22 +01:00
Thomas
ed97757dde build: Fix AppImage building issues (#847)
From https://github.com/AppImageCrafters/appimage-builder/pull/281
2022-12-18 16:05:14 +01:00
WerWolv
da8ec1565e fix: Floating point finding not working with negative values 2022-12-18 14:17:57 +01:00
WerWolv
ad85a4a0e3 fix: Hopefully fix the hex editor position jumping around after search 2022-12-18 13:27:28 +01:00
WerWolv
f9a7cdf4dd patterns: Improve editing of pattern values 2022-12-17 22:22:20 +01:00
WerWolv
a5296bab95 feat: Added pattern value editing 2022-12-16 11:20:39 +01:00
WerWolv
bda7a2b351 patterns: Fixed bitfield fields not caring about endianess
Fixes #837
2022-12-15 16:16:49 +01:00
WerWolv
f23351f11c sys: Try to not load unifont if graphics drivers can't handle it 2022-12-14 09:25:37 +01:00
WerWolv
e3f2541fde sys: Make sure libromfs is never used in libimhex 2022-12-05 15:29:19 +01:00
WerWolv
94723dbba3 build: Updated libromfs 2022-12-05 10:08:25 +01:00
WerWolv
6e0b92a4de sys: Added logging for which romfs is being used 2022-12-05 09:31:16 +01:00
WerWolv
13a61f5249 build: Updated libromfs 2022-12-04 22:41:30 +01:00
WerWolv
1347f81236 sys: Added postJson Net helper function 2022-12-04 21:50:47 +01:00
xtexChooser
ab93894442 lang: Update Chinese(Simplified) translations (#840) 2022-12-04 12:28:07 +01:00
5idereal
8ed6c2094b lang: Add back missing zh_TW.json (#839) 2022-12-03 10:50:35 +01:00
WerWolv
42d7f1ca67 lang: Allow langtool to update invalid translation fields 2022-12-03 10:49:26 +01:00
Thomas R
cf51e04777 tips: Add tip about unicode symbols (#838) 2022-12-02 16:30:28 +01:00
WerWolv
8398c12f74 patterns: Updated pattern language 2022-12-02 15:25:34 +01:00
WerWolv
2a345e770e git: Added HACKING file with information about how contribute to ImHex 2022-12-02 15:16:32 +01:00
WerWolv
b3fcf71982 lib: Updated libromfs 2022-12-02 12:02:23 +01:00
WerWolv
3b94a42783 lang: Updated localization system to use a more versatile json format 2022-12-02 12:00:04 +01:00
WerWolv
453ddaf0d6 patterns: Updated pattern language 2022-11-29 17:06:34 +01:00
WerWolv
d4ff36fde0 build: Updated dependencies 2022-11-29 11:06:22 +01:00
Nik
6239858d0a build: Removed leftover .idea folder 2022-11-29 11:05:05 +01:00
WerWolv
1dd873462e build: Fixed build failure when VERSION file contains extra white space 2022-11-29 09:44:47 +01:00
WerWolv
825c613d64 patterns: Fixed crash when using a void expression in a placement
Fixes #822
2022-11-25 10:58:17 +01:00
André Blome
4aa314b3ab feat: Added quick "save project" action (#826)
* add quick -save project- action

* translation for -save project as- added

* removed machine translations; header file name extension fixed

* moved openProject() for consistency
2022-11-25 10:47:11 +01:00
iTrooz_
8e696e3fc4 git: Enable LTO on Linux (#819)
* Enable LTO on Fedora .spec

* CI: Enable LTO for Ubuntu and ArchLinux

* CI: remove lld to allow LTO
2022-11-25 10:40:07 +01:00
iTrooz_
217cf799c2 sys: Warn user if a net request fails while a proxy is set (#821)
* tell the user if he have a proxy set

* Improved log message

Co-authored-by: Nik <werwolv98@gmail.com>
2022-11-25 10:39:45 +01:00
iTrooz_
b10a59661e build: Tell users patterns are being downloaded (#820)
* Tell users patterns are being downloaded

* Improved log message

Co-authored-by: Nik <werwolv98@gmail.com>
2022-11-25 10:37:31 +01:00
WerWolv
0f028db856 sys: Don't load any external plugins in debug builds
Closes #833
2022-11-25 10:28:05 +01:00
WerWolv
c194588118 fix: File Provider adding zero bytes at the end of the data when saving
Fixes #835
2022-11-25 10:02:55 +01:00
WerWolv
398dc8101f patterns: Updated pattern language 2022-11-20 00:28:05 +01:00
WerWolv
13cb330711 patterns: Updated pattern language 2022-11-19 13:49:50 +01:00
WerWolv
c0740822a3 patterns: Updated pattern language 2022-11-19 11:59:57 +01:00
WerWolv
340e627af9 patterns: Updated pattern language 2022-11-19 11:55:00 +01:00
WerWolv
3089a710bd patterns: Updated pattern language 2022-11-19 11:32:09 +01:00
WerWolv
7d0474335a fix: Crash when closing section with selected bytes 2022-11-18 16:01:18 +01:00
WerWolv
3d5190f51a fix: Patterns not appearing in list if pattern editor is not open 2022-11-18 14:27:55 +01:00
WerWolv
de2de1e1d7 patterns: Updated pattern language 2022-11-18 14:27:31 +01:00
WerWolv
91a4f52f67 build: Potentially fix LTO 2022-11-14 10:42:09 +01:00
WerWolv
c8af25533d build: Bumped version to 1.25.0 2022-11-14 10:07:21 +01:00
WerWolv
b1f76aeda6 feat: Added new view provider 2022-11-14 10:02:46 +01:00
WerWolv
3fccd03bbb fix: Black screen issues when font atlas got too big 2022-11-14 10:02:34 +01:00
WerWolv
3bcfa7e10b ux: Make the pattern language text editor always insert spaces instead of tabs 2022-11-14 09:44:10 +01:00
WerWolv
cbd7c10f3d build: Updated libromfs 2022-11-13 22:53:41 +01:00
WerWolv
0d09c24840 build: Updated libromfs 2022-11-13 22:41:29 +01:00
WerWolv
d54d371ab7 build: Updated libromfs 2022-11-13 21:34:26 +01:00
WerWolv
c90aa0a742 fix: Crash after evaluating patterns a second time 2022-11-10 11:18:14 +01:00
WerWolv
7f0bdea212 fix: Opening multiple files by dragging them onto the window 2022-11-10 11:17:21 +01:00
WerWolv
b29d184488 patterns: Updated pattern language 2022-11-09 22:26:13 +01:00
WerWolv
168d6b2080 patterns: Updated pattern language 2022-11-09 20:54:01 +01:00
WerWolv
b2c970c3bd git: Removed macOS portable build again 2022-11-09 20:52:23 +01:00
WerWolv
a0445c4f7b lang: Added missing localizations 2022-11-09 19:03:57 +01:00
WerWolv
9074a6fcf1 fix: Edit menu items being always unavailable 2022-11-09 18:49:07 +01:00
WerWolv
4c5d2f6ebb feat: Finish up work on new pl section system 2022-11-08 21:43:22 +01:00
WerWolv
23ce2ec271 ui: Fixed some more macOS scaling issues 2022-11-08 18:09:48 +01:00
WerWolv
5bbc2fd94c feat: Added basic UI for the new pl section system 2022-11-07 00:04:47 +01:00
WerWolv
901b8f0424 sys: Refactored hex editor into its own reusable component 2022-11-06 12:19:12 +01:00
WerWolv
d2705988ac ui: Potentially fix weird scaling on macOS 2022-11-05 21:49:17 +01:00
WerWolv
291da649c1 ui: Limit window title length 2022-11-04 15:19:24 +01:00
WerWolv
48e9d3b4e9 patterns: Updated pattern language 2022-11-04 10:12:26 +01:00
WerWolv
45e2578c5b patterns: Updated pattern language 2022-11-04 09:50:26 +01:00
WerWolv
a6742de405 sys: Literally, fuck Valve 2022-11-02 08:24:00 +01:00
iTrooz_
948b5b2d9c ux: Change "Esc" key behavior on hex editor popups (#810)
* set same behaviour for PopupGoto and PopupFind

* Force close the popup when user is editing an input
2022-11-01 09:33:11 +01:00
iTrooz_
6cb9714f06 git: Automatically label created issues (#811) 2022-11-01 09:31:46 +01:00
Asvel
c35eaa7a4d fix: Pattern auto-loading issue on Windows (#808) 2022-10-30 13:39:40 +01:00
iTrooz_
bececff9e5 feat: Ask the users if they want to check for updates (#803)
* ask the users for updates

* Only treat 1 as enabled

* Fix formatting

* update locales

* comment to document value
2022-10-29 23:43:40 +02:00
iTrooz_
2826e6f325 git: Updated issue templates (#807)
* add "Additional context" option for feature request

* use placeholder instead of value

* Ask for installation type in bug reports
2022-10-29 20:38:22 +02:00
5idereal
6bc1f94b60 lang: Update zh_TW translation (#805) 2022-10-28 14:58:45 +02:00
WerWolv
9fd37221f6 fix: Static tooltips not rendering correctly 2022-10-28 14:33:26 +02:00
WerWolv
db3072630a feat: Allow multiple yara rules to be applied after each otherr 2022-10-28 14:32:56 +02:00
WerWolv
5cf6baca88 fix: Yara matching not being interruptable 2022-10-28 14:32:28 +02:00
WerWolv
582858c0d4 git: Download all artifacts to their own folders 2022-10-28 10:55:06 +02:00
WerWolv
7d56c64a9c git: Download only necessary artifacts in steam deploy job 2022-10-28 10:29:40 +02:00
WerWolv
902b35e189 git: Fix downloading artifacts in steam deploy job 2022-10-28 10:02:38 +02:00
WerWolv
5f6050aaec git: Fixed more build issues 2022-10-28 09:38:03 +02:00
WerWolv
cb94213a04 git: Fix some more steam deploy issues 2022-10-28 09:17:04 +02:00
WerWolv
fa6580f622 git: Move steam deploy to its own workflow 2022-10-28 09:14:01 +02:00
Frieder Bluemle
07effffa5e git: Fix various issues in the INSTALL guide (#800) 2022-10-28 08:17:10 +02:00
WerWolv
e15bcb51aa git: Fix setting of version env var on Windows 2022-10-27 14:12:46 +02:00
WerWolv
a04e2bc8f6 res: Update steam assets 2022-10-27 14:11:31 +02:00
WerWolv
6aad609a48 git: Fix more issues with the Steam Deployment 2022-10-27 14:05:06 +02:00
iTrooz_
24c0cc10a1 sys: Load Tips from a local file instead of querying an API (#797)
* store tips locally

* C++ random implementation

* show one different tip per day

* fix json conversion to string

* put tips.json in builtin romfs
2022-10-27 13:21:54 +02:00
Nik
e567061e3c git: Added automatic pushing of nightlies to Steam (#801)
* build: Upload nightly releases to steam

* git: Fixed build CI syntax

* git: Try fixing steam login

* git: Try steam TOTP login

* git: Fix steam-deploy branch

* git: Don't upload MacOS No-GPU version to Steam

* git: Added commit hash to steam nightlies, only upload on our repo

* git: Use full commit hash in steam nightly description

* git: Fixed workflow

* git: Make sure macOS doesn't upload steam releases when it shouldn't

* git: Fix macos CI again

* git: Use steam-deploy fork to fix Linux deployment
2022-10-27 13:19:06 +02:00
iTrooz_
32ab1c1a06 sys: Load content store content when it's first opened (#795)
* refresh store on open

* show the user if the request failed

* do not refresh if a refresh is in progress

This makes ImHex crash

* InProgress

* fix formatting

* use a localized message

* set localized message in other langs
2022-10-27 13:12:24 +02:00
iTrooz_
e76d5854b8 ux: Add a setting to disable loading of unicode characters (#798)
* Add setting to disable loading of unicode characters

* change message

* set message in other langs

* fix formatting
2022-10-27 13:11:09 +02:00
WerWolv
d3b6c2d0e6 nodes: Added a few new nodes 2022-10-26 09:07:09 +02:00
WerWolv
ef6cac6e92 patterns: Make more pattern editor things per-provider 2022-10-26 08:54:43 +02:00
WerWolv
0c5e72ab6a nodes: Improve precision of values passed between nodes 2022-10-26 08:54:08 +02:00
WerWolv
f67c9735c5 patterns: Fixed memory leak 2022-10-22 23:17:38 +02:00
WerWolv
858e1aed3b nodes: Fixed a few issues with locatizations, errors and overlays 2022-10-22 23:17:18 +02:00
WerWolv
3b7f2fbdaa pattern: Display evaluation time when pattern finished running 2022-10-22 15:47:50 +02:00
WerWolv
2c167d6d27 fix: Crash when scrolling to the end of a file that is multiples of 8 bytes long 2022-10-22 15:46:03 +02:00
WerWolv
f53d7fc9f3 fix: Format string syntax error 2022-10-22 13:46:48 +02:00
WerWolv
04a4957ccf fix: Null and MemFile providers dumping null into recent files 2022-10-22 09:08:18 +02:00
WerWolv
b5f7be2384 fix: Editing hex editor cells not working on some systems 2022-10-22 09:07:47 +02:00
WerWolv
33a0ee37fa build: Update ImHex-Rust-Plugin-Template on release 2022-10-21 14:59:43 +02:00
WerWolv
1eb9858f62 sys: Moved libimhex-rust out of project 2022-10-21 14:55:01 +02:00
WerWolv
b829abf56c fix: Paste all shortcut tooltip being wrong 2022-10-21 13:36:19 +02:00
WerWolv
139a379a09 feat: Added Paste all option to paste and resize file without checks
Closes #791
2022-10-21 12:14:35 +02:00
WerWolv
6a8611d98d ux: Make New File command create a new file in memory
Closes #792
2022-10-21 12:01:28 +02:00
WerWolv
241b93aab5 patterns: Added menu to Edit menu for placing types at current selection 2022-10-21 10:03:37 +02:00
WerWolv
6d08a4386d patterns: Updated pattern language 2022-10-20 22:45:46 +02:00
WerWolv
37b4d5e7b5 patterns: Updated pattern language 2022-10-20 09:48:06 +02:00
iTrooz_
f3b0971d00 sys: Improve various error messages (#789)
* Tell the user the net request which failed

* Show signal name

* Print execution time of startup tasks

* replace NULL with nullptr

* change wording for task logs

* Remove '..' from task name

* remove using namespace chrono
2022-10-20 08:28:29 +02:00
WerWolv
05e8e53451 patterns: Updated pattern language 2022-10-17 13:29:43 +02:00
iTrooz_
08251eeab7 feat: Add Ctrl+Shift+Z Redo shortcut (#787) 2022-10-17 13:28:05 +02:00
WerWolv
8c96ba1c58 patterns: Updated pattern language 2022-10-16 22:04:30 +02:00
WerWolv
e170c45556 patterns: Updated pattern language 2022-10-16 16:24:24 +02:00
iTrooz_
a537fe90a0 build: Added make uninstall (#784) 2022-10-14 15:35:45 +02:00
WerWolv
802ad96c49 patterns: Updated pattern language
Fixes #783
2022-10-13 22:11:01 +02:00
WerWolv
5d979da3e2 fix: Modified bytes on pages after the first one always displaying 0x00
Fixed #782
2022-10-13 21:23:26 +02:00
WerWolv
b843d8e98a build: Added steam resources 2022-10-13 15:15:06 +02:00
WerWolv
af6ad96cb6 fix: Detached tool windows not resizing correctly 2022-10-13 15:14:51 +02:00
WerWolv
f9e960070d nodes: Require shift to be held to enlarge visualizers 2022-10-13 15:14:16 +02:00
WerWolv
1ab949b7ef nodes: Added RGBA8 image visualizer 2022-10-13 15:13:53 +02:00
WerWolv
8b39c8f219 feat: Make all tool windows be detachable 2022-10-13 10:47:38 +02:00
iTrooz_
14b28ba899 ui: Show non existing folders in red in about view (#781)
* show non existing folders in red in about view

* use ImGuiCustomCol_ToolbarRed for theming

* Fix compilation problem for Ubuntu
2022-10-13 08:07:46 +02:00
WerWolv
dd9b6643e6 fix: Crash when loading a provider after evaluating patterns 2022-10-12 14:50:09 +02:00
WerWolv
e3f88395ec fix: Hidden attribute not applying to top-level patterns 2022-10-12 14:49:48 +02:00
391 changed files with 124782 additions and 42289 deletions

68
.clang-tidy Normal file
View File

@@ -0,0 +1,68 @@
# Generated from CLion Inspection settings
---
Checks: '-*,
mpi-*,
bugprone-*,
-bugprone-signal-handler,
-bugprone-narrowing-conversions,
-bugprone-redundant-branch-condition,
-bugprone-exception-escape,
-bugprone-shared-ptr-array-mismatch,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-signed-char-misuse,
-bugprone-unhandled-exception-at-new,
-bugprone-infinite-loop,
-bugprone-easily-swappable-parameters,
cert-err52-cpp,
cert-err60-cpp,
cert-err34-c,
cert-str34-c,
cert-dcl21-cpp,
cert-msc50-cpp,
cert-msc51-cpp,
cert-dcl58-cpp,
cert-flp30-c,
cppcoreguidelines-avoid-const-or-ref-data-members,
cppcoreguidelines-pro-type-member-init,
cppcoreguidelines-slicing,
cppcoreguidelines-interfaces-global-init,
cppcoreguidelines-pro-type-static-cast-downcast,
cppcoreguidelines-narrowing-conversions,
google-default-arguments,
google-runtime-operator,
google-explicit-constructor,
hicpp-multiway-paths-covered,
hicpp-exception-baseclass,
misc-*,
-misc-definitions-in-headers,
-misc-unused-parameters,
-misc-unused-alias-decls,
-misc-use-anonymous-namespace,
-misc-misleading-identifier,
-misc-confusable-identifiers,
-misc-misleading-bidirectional,
-misc-static-assert,
-misc-no-recursion,
-misc-const-correctness,
modernize-*,
-modernize-use-trailing-return-type,
openmp-use-default-none,
performance-*,
-performance-no-int-to-ptr,
portability-*,
-portability-restrict-system-includes,
readability-*,
-readability-redundant-preprocessor,
-readability-named-parameter,
-readability-function-size,
-readability-use-anyofallof,
-readability-identifier-length,
-readability-magic-numbers,
-readability-braces-around-statements,
-readability-suspicious-call-argument,
-readability-isolate-declaration,
-readability-else-after-return,
-readability-redundant-access-specifiers,
-readability-function-cognitive-complexity,
-readability-identifier-naming,
-readability-qualified-auto'

4
.gitattributes vendored
View File

@@ -1,3 +1 @@
lib/external/** linguist-vendored
lib/libimhex-rs/imgui-rs/** linguist-vendored
lib/libimhex-rs/imgui-sys/** linguist-vendored
lib/external/** linguist-vendored

View File

@@ -1,6 +1,7 @@
name: Bug Report
description: Something doesn't work correctly in ImHex.
title: "[Bug] "
labels: bug
body:
- type: dropdown
id: os
@@ -39,10 +40,17 @@ body:
label: ImHex Build Type
options:
- label: Nightly or built from sources
- type: input
attributes:
label: Installation type
description: |
How did you install ImHex ? MSI/Portable/DMG/AppImage/Fedora package/etc..
validations:
required: true
- type: textarea
attributes:
label: Additional context?
value: |
placeholder: |
- Additional information about your environment.
- If possible and useful, please upload the binary you've been editing when the bug occurred.
validations:

View File

@@ -1,6 +1,7 @@
name: Feature Request
description: Something you'd like to see added to ImHex in the future
title: "[Feature] "
labels: feature request
body:
- type: textarea
attributes:
@@ -20,3 +21,6 @@ body:
label: Request Type
options:
- label: I can provide a PoC for this feature or am willing to work on it myself and submit a PR
- type: textarea
attributes:
label: Additional context?

View File

@@ -28,8 +28,8 @@ jobs:
- name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build
key: ${{ runner.os }}-analysis-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
restore-keys: ${{ runner.os }}-analysis-${{ secrets.CACHE_VERSION }}-build
max-size: 50M
- name: 📜 Restore CMakeCache
@@ -37,8 +37,8 @@ jobs:
with:
path: |
build/CMakeCache.txt
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
key: ${{ runner.os }}-analysis-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
- name: ⬇️ Install dependencies
run: |
sudo apt update

View File

@@ -58,6 +58,11 @@ jobs:
mbedtls:p
freetype:p
dlfcn:p
libbacktrace:p
- name: 📜 Set version variable
run: |
echo "IMHEX_VERSION=`cat VERSION`" >> $GITHUB_ENV
# Windows cmake build
- name: 🛠️ Build
@@ -65,58 +70,51 @@ jobs:
mkdir -p build
cd build
cmake -G "MinGW Makefiles" \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
-DCREATE_PACKAGE=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
cmake -G "MinGW Makefiles" \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
-DCREATE_PACKAGE=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \
..
mingw32-make -j4 install
cpack
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
mv ImHex-*.msi ../imhex-${{env.IMHEX_VERSION}}-Windows-x86_64.msi
#- name: 🗝️ Sign Windows Installer
# if: github.event_name == 'push' && github.ref == 'refs/heads/master'
# shell: powershell
# env:
# WIN_SIGN_CERT: ${{ secrets.WIN_SIGN_CERT }}
# WIN_SIGN_PW: ${{ secrets.WIN_SIGN_PW }}
# run: |
# $buffer = [System.Convert]::FromBase64String($env:WIN_SIGN_CERT)
# $certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::New($buffer, $env:WIN_SIGN_PW)
# Get-ChildItem -Path ./build -Filter *.msi -Recurse | Set-AuthenticodeSignature -HashAlgorithm SHA256 -Certificate $certificate -TimestampServer http://timestamp.digicert.com
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: ⬆️ Upload Windows Installer
uses: actions/upload-artifact@v3
with:
name: Windows Installer
name: Windows Installer x86_64
path: |
build/*.msi
imhex-*.msi
- name: ⬆️ Upload Portable ZIP
uses: actions/upload-artifact@v3
with:
name: Windows Portable
name: Windows Portable x86_64
path: |
build/install/*
- name: ⬇️ Download Mesa3D for NoGPU version
shell: bash
run: |
echo "NoGPU version Powered by Mesa 3D : https://fdossena.com/?p=mesa%2Findex.frag" > build/install/MESA.md
curl https://downloads.fdossena.com/geth.php?r=mesa64-latest -L -o mesa.7z
curl https://werwolv.net/downloads/mesa/MesaForWindows-x64-latest.7z -L -o mesa.7z
7z e mesa.7z
mv opengl32.dll build/install
- name: ⬆️ Upload NoGPU Portable ZIP
uses: actions/upload-artifact@v3
with:
name: Windows Portable NoGPU
name: Windows Portable NoGPU x86_64
path: |
build/install/*
@@ -131,7 +129,7 @@ jobs:
custom_glfw: true
- suffix: ""
custom_glfw: false
name: 🍎 macOS 11.0${{matrix.suffix}}
steps:
@@ -143,7 +141,7 @@ jobs:
- name: 📜 Set version variable
run: |
echo "IMHEX_VERSION=`cat VERSION`" >> $GITHUB_ENV
- name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
@@ -151,7 +149,6 @@ jobs:
restore-keys: ${{ runner.os }}-${{ matrix.suffix }}-${{ secrets.CACHE_VERSION }}-build
max-size: 50M
- name: 📜 Restore CMakeCache
uses: actions/cache@v3
with:
@@ -169,7 +166,6 @@ jobs:
run: |
brew install glfw
- name: 🧰 Checkout glfw
if: ${{matrix.custom_glfw}}
uses: actions/checkout@v3
@@ -186,12 +182,15 @@ jobs:
mkdir build
cd build
cmake \
-DBUILD_SHARED_LIBS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
cmake \
-DBUILD_SHARED_LIBS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
-DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \
..
make -j 4 install
@@ -200,30 +199,33 @@ jobs:
run: |
mkdir -p build
cd build
CC=$(brew --prefix gcc@12)/bin/gcc-12 \
CXX=$(brew --prefix gcc@12)/bin/g++-12 \
OBJC=$(brew --prefix llvm)/bin/clang \
OBJCXX=$(brew --prefix llvm)/bin/clang++ \
PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \
MACOSX_DEPLOYMENT_TARGET="10.10" \
cmake \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCREATE_BUNDLE=ON \
-DCREATE_PACKAGE=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
-DCMAKE_OSX_DEPLOYMENT_TARGET="10.10" \
-DCPACK_PACKAGE_FILE_NAME="imhex-${{env.IMHEX_VERSION}}-macOS${{matrix.suffix}}" \
CC=$(brew --prefix gcc@12)/bin/gcc-12 \
CXX=$(brew --prefix gcc@12)/bin/g++-12 \
OBJC=$(brew --prefix llvm)/bin/clang \
OBJCXX=$(brew --prefix llvm)/bin/clang++ \
PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \
MACOSX_DEPLOYMENT_TARGET="10.10" \
cmake \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCREATE_BUNDLE=ON \
-DCREATE_PACKAGE=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \
-DCMAKE_OSX_DEPLOYMENT_TARGET="10.10" \
-DCPACK_PACKAGE_FILE_NAME="imhex-${{env.IMHEX_VERSION}}-macOS${{matrix.suffix}}-x86_64" \
..
make -j4 package
- name: ⬆️ Upload DMG
uses: actions/upload-artifact@v3
with:
name: macOS DMG${{matrix.suffix}}
name: macOS DMG${{matrix.suffix}} x86_64
path: build/*.dmg
# Ubuntu build
@@ -243,44 +245,34 @@ jobs:
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build
max-size: 50M
- name: 📜 Restore other caches
- name: 📜 Restore CMakeCache
uses: actions/cache@v3
with:
path: |
build/CMakeCache.txt
build-appimage/CMakeCache.txt
.flatpak-builder
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
- name: ⬇️ Install dependencies
run: |
sudo rm -rf /usr/share/dotnet
sudo rm -rf /opt/ghc
sudo rm -rf "/usr/local/share/boost"
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
sudo apt update
sudo bash dist/get_deps_debian.sh
sudo apt install -y python3-pip python3-setuptools desktop-file-utils libgdk-pixbuf2.0-dev fuse
sudo wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O /usr/local/bin/appimagetool
sudo chmod +x /usr/local/bin/appimagetool
sudo pip3 install appimage-builder
# Ubuntu cmake build
- name: 🛠️ Build
run: |
mkdir -p build
cd build
CC=gcc-12 CXX=g++-12 cmake \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_INSTALL_PREFIX="/usr" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
CC=gcc-12 CXX=g++-12 cmake \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_INSTALL_PREFIX="/usr" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
..
make -j 4 install DESTDIR=DebDir
@@ -288,36 +280,74 @@ jobs:
run: |
echo "IMHEX_VERSION=`cat VERSION`" >> $GITHUB_ENV
#- name: 📦 Bundle Flatpak
# run: |
# sudo apt install flatpak flatpak-builder
# flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
# flatpak --user install -y flathub org.freedesktop.Platform//20.08
# flatpak --user install -y flathub org.freedesktop.Sdk//20.08
# flatpak-builder --jobs=4 --repo=imhex _flatpak dist/net.werwolv.ImHex.yaml --ccache --keep-build-dirs
# flatpak build-bundle imhex imhex.flatpak net.werwolv.ImHex stable
- name: 📦 Bundle DEB
run: |
cp -r build/DEBIAN build/DebDir
dpkg-deb -Zgzip --build build/DebDir
mv build/DebDir.deb imhex-${{env.IMHEX_VERSION}}-Ubuntu-22.04.deb
mv build/DebDir.deb imhex-${{env.IMHEX_VERSION}}-Ubuntu-22.04-x86_64.deb
- name: ⬆️ Upload DEB
uses: actions/upload-artifact@v3
with:
name: Ubuntu 22.04 DEB x86_64
path: '*.deb'
# AppImage build
appimage:
runs-on: ubuntu-22.04
name: ⬇️ AppImage
steps:
- name: 🧰 Checkout
uses: actions/checkout@v3
with:
submodules: recursive
- name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ runner.os }}-appimage-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
restore-keys: ${{ runner.os }}-appimage-${{ secrets.CACHE_VERSION }}-build
max-size: 50M
- name: 📜 Restore CMakeCache
uses: actions/cache@v3
with:
path: |
build-appimage/CMakeCache.txt
key: ${{ runner.os }}-appimage-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
- name: ⬇️ Install dependencies
run: |
sudo apt update
sudo bash dist/get_deps_debian.sh
sudo apt install -y python3-pip python3-setuptools desktop-file-utils libgdk-pixbuf2.0-dev fuse
sudo wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O /usr/local/bin/appimagetool
sudo chmod +x /usr/local/bin/appimagetool
sudo pip3 install git+https://github.com/iTrooz/appimage-builder@dpkg-package-versions
- name: 📜 Set version variable
run: |
echo "IMHEX_VERSION=`cat VERSION`" >> $GITHUB_ENV
# AppImage cmake build
- name: 🛠️ Reconfigure build for AppImage
- name: 🛠️ Build
run: |
mkdir -p build-appimage
cd build-appimage
CC=gcc-12 CXX=g++-12 cmake \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_INSTALL_PREFIX="/usr" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_PLUGINS_IN_SHARE=ON \
-DIMHEX_USE_BUNDLED_CA=ON \
CC=gcc-12 CXX=g++-12 cmake \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_INSTALL_PREFIX="/usr" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
-DIMHEX_PLUGINS_IN_SHARE=ON \
-DIMHEX_USE_BUNDLED_CA=ON \
..
make -j 4 install DESTDIR=AppDir
@@ -326,38 +356,24 @@ jobs:
cd build-appimage
export VERSION=${{env.IMHEX_VERSION}}
appimage-builder --recipe ../dist/AppImageBuilder.yml
cd ..
#- name: ⬆️ Upload Flatpak
# uses: actions/upload-artifact@v3
# with:
# name: Linux Flatpak
# path: |
# imhex.flatpak
- name: ⬆️ Upload DEB
uses: actions/upload-artifact@v3
with:
name: Ubuntu 22.04 DEB
path: '*.deb'
- name: ⬆️ Upload AppImage
uses: actions/upload-artifact@v3
with:
name: Linux AppImage
name: Linux AppImage x86_64
path: 'build-appimage/*.AppImage'
- name: ⬆️ Upload AppImage zsync
uses: actions/upload-artifact@v3
with:
name: Linux AppImage zsync
name: Linux AppImage zsync x86_64
path: 'build-appimage/*.AppImage.zsync'
# ArchLinux build
archlinux-build:
name: 🐧 ArchLinux
runs-on: ubuntu-latest
container:
image: archlinux:base-devel
@@ -369,7 +385,7 @@ jobs:
- name: ⬇️ Install setup dependencies
run: |
pacman -Syu git ccache --noconfirm
- name: 🧰 Checkout
uses: actions/checkout@v3
with:
@@ -385,39 +401,41 @@ jobs:
key: archlinux-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
restore-keys: archlinux-${{ secrets.CACHE_VERSION }}-build
max-size: 50M
- name: 📜 Restore CMakeCache
uses: actions/cache@v3
with:
path: |
build/CMakeCache.txt
key: archlinux-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
# ArchLinux cmake build
- name: 🛠️ Build
run: |
mkdir -p build
cd build
CC=gcc CXX=g++ cmake \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_INSTALL_PREFIX="/usr" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
-DUSE_SYSTEM_CURL=ON \
-DUSE_SYSTEM_FMT=ON \
-DUSE_SYSTEM_YARA=ON \
-DUSE_SYSTEM_NLOHMANN_JSON=ON \
-DUSE_SYSTEM_CAPSTONE=OFF \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
CC=gcc CXX=g++ cmake \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_INSTALL_PREFIX="/usr" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DUSE_SYSTEM_CURL=ON \
-DUSE_SYSTEM_FMT=ON \
-DUSE_SYSTEM_YARA=ON \
-DUSE_SYSTEM_NLOHMANN_JSON=ON \
-DUSE_SYSTEM_CAPSTONE=OFF \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
..
make -j 4 install DESTDIR=installDir
- name: 📜 Set version variable
run: |
echo "IMHEX_VERSION=`cat VERSION`" >> $GITHUB_ENV
- name: ✒️ Prepare PKGBUILD
run: |
cp dist/Arch/PKGBUILD build
@@ -427,91 +445,146 @@ jobs:
- name: 📦 Package ArchLinux .pkg.tar.zst
run: |
cd build
# the name is a small trick to make makepkg recognize it as the source
# else, it would try to download the file from the release
tar -cvf imhex-${{env.IMHEX_VERSION}}-ArchLinux.pkg.tar.zst -C installDir .
tar -cvf imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst -C installDir .
chmod -R 777 .
sudo -u nobody makepkg
# Replace the old file
rm imhex-${{env.IMHEX_VERSION}}-ArchLinux.pkg.tar.zst
mv *.pkg.tar.zst imhex-${{env.IMHEX_VERSION}}-ArchLinux.pkg.tar.zst
rm imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
mv *.pkg.tar.zst imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
- name: ⬆️ Upload imhex-archlinux.pkg.tar.zst
uses: actions/upload-artifact@v3
with:
name: ArchLinux .pkg.tar.zst
name: ArchLinux .pkg.tar.zst x86_64
path: |
build/imhex-${{env.IMHEX_VERSION}}-ArchLinux.pkg.tar.zst
build/imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
# Fedora build
fedora-build:
# RPM distro builds
rpm-build:
strategy:
matrix:
include:
- docker_image: fedora:latest
release: Latest
- docker_image: fedora:rawhide
release: Rawhide
- name: Fedora
mock_release: rawhide
release_num: rawhide
mock_config: fedora-rawhide
- name: Fedora
mock_release: f38
release_num: 38
mock_config: fedora-38
- name: Fedora
mock_release: f37
release_num: 37
mock_config: fedora-37
- name: Fedora
mock_release: f36
release_num: 36
mock_config: fedora-36
- name: RHEL-AlmaLinux
mock_release: epel9
release_num: 9
mock_config: "alma+epel-9"
name: 🐧 Fedora ${{ matrix.release }}
name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }}
runs-on: ubuntu-latest
container:
image: "${{ matrix.docker_image }}"
image: "fedora:latest"
options: --privileged
steps:
- name: ⬇️ Update all packages
run: |
dnf upgrade -y
- name: ⬇️ Install git-core
run: dnf install --disablerepo="*" --enablerepo="fedora" git-core -y
- name: ⬇️ Install setup dependencies
run: |
dnf install -y \
ccache \
desktop-file-utils \
fmt-devel \
git \
json-devel \
libcurl-devel \
llvm-devel \
mbedtls-devel \
rpm-build \
yara-devel
- name: 🧰 Checkout
uses: actions/checkout@v3
with:
path: ImHex
submodules: recursive
- name: ⬇️ Install ImHex dependencies
- name: 📜 Setup DNF Cache
uses: actions/cache@v3
with:
path: /var/cache/dnf
key: ${{ matrix.mock_release }}-${{secrets.CACHE_VERSION }}-dnf-${{ github.run_id }}
restore-keys: |
${{ matrix.mock_release }}-${{secrets.CACHE_VERSION }}-dnf-
- name: ⬇️ Update all packages and install dependencies
run: |
dist/get_deps_fedora.sh
dnf upgrade --disablerepo="*" --enablerepo="fedora,updates" -y
dnf install --disablerepo="*" --enablerepo="fedora,updates" -y \
fedpkg \
ccache
- name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
uses: hendrikmuhs/ccache-action@v1.2.5
with:
key: fedora-${{ matrix.release }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
restore-keys: fedora-${{ matrix.release }}-${{ secrets.CACHE_VERSION }}-build
max-size: 50M
key: rpm-${{ matrix.mock_release }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
restore-keys: rpm-${{ matrix.mock_release }}-${{ secrets.CACHE_VERSION }}-build
max-size: 1G
- name: 📜 Set version variable
run: |
echo "IMHEX_VERSION=`cat VERSION`" >> $GITHUB_ENV
echo "IMHEX_VERSION=`cat ImHex/VERSION`" >> $GITHUB_ENV
- name: 🗜️ Create tarball from sources with dependencies
run: tar --exclude-vcs -czf $GITHUB_WORKSPACE/imhex-$IMHEX_VERSION.tar.gz ImHex
- name: ✒️ Modify spec file
run: |
sed -i \
-e 's/Version: [0-9]*\.[0-9]*\.[0-9]*$/Version: ${{env.IMHEX_VERSION}}/g' \
-e 's/IMHEX_OFFLINE_BUILD=ON/IMHEX_OFFLINE_BUILD=OFF/g' \
-e '/IMHEX_OFFLINE_BUILD=OFF/a -D IMHEX_PATTERNS_PULL_MASTER=ON \\' \
-e '/BuildRequires: cmake/a BuildRequires: git-core' \
-e '/%files/a %{_datadir}/%{name}/' \
$GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec
- name: 📜 Fix ccache on EL9
if: matrix.mock_release == 'epel9'
run: sed -i '/\. \/opt\/rh\/gcc-toolset-12\/enable/a PATH=/usr/lib64/ccache:$PATH' $GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec
- name: 🟩 Copy spec file to build root
run: mv $GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec $GITHUB_WORKSPACE/imhex.spec
- name: 📜 Enable ccache for mock
run: |
cat <<EOT > $GITHUB_WORKSPACE/mock.cfg
include('${{ matrix.mock_config }}-x86_64.cfg')
config_opts['plugin_conf']['ccache_enable'] = True
config_opts['plugin_conf']['ccache_opts']['max_cache_size'] = '1G'
config_opts['plugin_conf']['ccache_opts']['compress'] = True
config_opts['plugin_conf']['ccache_opts']['dir'] = "$GITHUB_WORKSPACE/.ccache"
EOT
- name: 📜 Setup Mock Cache
uses: actions/cache@v3
with:
path: /var/cache/mock
key: ${{ matrix.mock_release }}-${{ secrets.CACHE_VERSION }}-mock-${{ github.run_id }}
restore-keys: |
${{ matrix.mock_release }}-${{ secrets.CACHE_VERSION }}-mock-
# Fedora cmake build (in imhex.spec)
- name: 📦 Build RPM
run: |
rpmbuild -ba --define "_version ${{env.IMHEX_VERSION}}" --define "_src_path $GITHUB_WORKSPACE" --define "_build_type $BUILD_TYPE" $GITHUB_WORKSPACE/dist/rpm/imhex.spec
mv ~/rpmbuild/RPMS/x86_64/*.rpm imhex-${{env.IMHEX_VERSION}}-Fedora-${{matrix.release}}.rpm
fedpkg --path $GITHUB_WORKSPACE --release ${{ matrix.mock_release }} mockbuild --enable-network -N --root $GITHUB_WORKSPACE/mock.cfg extra_args -- -v
- name: 🟩 Move and rename finished RPM
run: |
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: ⬆️ Upload RPM
uses: actions/upload-artifact@v3
with:
name: Fedora ${{ matrix.release }} RPM
name: ${{ matrix.name }} ${{ matrix.release_num }} RPM x86_64
path: |
imhex-${{env.IMHEX_VERSION}}-Fedora-${{matrix.release}}.rpm
imhex-${{env.IMHEX_VERSION}}-${{matrix.name}}-${{matrix.release_num}}-x86_64.rpm

View File

@@ -9,9 +9,66 @@ on:
workflow_dispatch:
jobs:
release-common:
release-update-repos:
runs-on: ubuntu-latest
name: Release Common
name: Release Update Repos
steps:
- name: 📜 Verify version and set version variable
run: |
project_version=`cat ImHex/VERSION`
tag_version="${{github.event.release.tag_name}}"
tag_version="${tag_version:1}"
if [ "$project_version" != "$tag_version" ]; then
echo "::warning::$project_version and $tag_version are not the same ! Refusing to populate release"
exit 1
fi
echo "IMHEX_VERSION=$project_version" >> $GITHUB_ENV
- name: 🎫 Create PatternLanguage release
uses: ncipollo/release-action@v1
env:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
if: "${{ env.RELEASE_TOKEN != '' }}"
with:
tag: ImHex-v${{ env.IMHEX_VERSION }}
repo: PatternLanguage
token: ${{ secrets.RELEASE_TOKEN }}
- name: 🎫 Create ImHex-Patterns release
uses: ncipollo/release-action@v1
env:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
if: "${{ env.RELEASE_TOKEN != '' }}"
with:
tag: ImHex-v${{ env.IMHEX_VERSION }}
repo: ImHex-Patterns
token: ${{ secrets.RELEASE_TOKEN }}
- name: ✉️ Update C++ Plugin Template
uses: peter-evans/repository-dispatch@v2
env:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
if: "${{ env.RELEASE_TOKEN != '' }}"
with:
token: ${{ secrets.RELEASE_TOKEN }}
repository: WerWolv/ImHex-Cpp-Plugin-Template
event-type: update_submodule
- name: ✉️ Update Rust Plugin Template
uses: peter-evans/repository-dispatch@v2
env:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
if: "${{ env.RELEASE_TOKEN != '' }}"
with:
token: ${{ secrets.RELEASE_TOKEN }}
repository: WerWolv/ImHex-Rust-Plugin-Template
event-type: update_submodule
release-upload-artifacts:
runs-on: ubuntu-latest
name: Release Upload Artifacts
steps:
- name: 🧰 Checkout
@@ -34,7 +91,7 @@ jobs:
- name: 🗜️ Create tarball from sources with dependencies
run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex
- name: ⬇️ Download artifacts from latest workflow
uses: dawidd6/action-download-artifact@v2
with:
@@ -43,7 +100,7 @@ jobs:
branch: ${{ github.event.release.target_commitish }}
workflow_conclusion: success
skip_unpack: true
- name: 🗜️ Unzip files when needed
run: |
for zipfile in ./*.zip
@@ -60,8 +117,8 @@ jobs:
- name: 🟩 Rename artifacts when needed
run: |
mv "Windows Portable.zip" imhex-${{env.IMHEX_VERSION}}-Windows-Portable.zip
mv "Windows Portable NoGPU.zip" imhex-${{env.IMHEX_VERSION}}-Windows-Portable-NoGPU.zip
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
- name: ⬆️ Upload everything to release
uses: softprops/action-gh-release@v1
@@ -72,14 +129,13 @@ jobs:
run: |
cp ImHex/dist/Arch/PKGBUILD .
hash=`md5sum imhex-${{env.IMHEX_VERSION}}-ArchLinux.pkg.tar.zst | cut -d ' ' -f 1`
hash=`md5sum imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst | cut -d ' ' -f 1`
sed -i 's/%version%/${{env.IMHEX_VERSION}}/g' PKGBUILD
sed -i 's/%version%/${{ env.IMHEX_VERSION }}/g' PKGBUILD
sed -i "s/(SKIP)/($hash)/g" PKGBUILD
- name: ⬆️ Publish AUR package
# I couldn't make the condition in the env directly for some reason
env:
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
if: "${{ env.AUR_SSH_PRIVATE_KEY != '' }}"
@@ -91,49 +147,18 @@ jobs:
commit_username: iTrooz
commit_email: itrooz@protonmail.com
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
commit_message: Bump to version ${{env.IMHEX_VERSION}}
commit_message: Bump to version ${{ env.IMHEX_VERSION }}
ssh_keyscan_types: rsa,dsa,ecdsa,ed25519
- name: 🎫 Create PatternLanguage release
uses: ncipollo/release-action@v1
env:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
if: "${{ env.RELEASE_TOKEN != '' }}"
with:
tag: ImHex-v${{env.IMHEX_VERSION}}
repo: PatternLanguage
token: ${{ secrets.RELEASE_TOKEN }}
- name: 🎫 Create ImHex-Patterns release
uses: ncipollo/release-action@v1
env:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
if: "${{ env.RELEASE_TOKEN != '' }}"
with:
tag: ImHex-v${{env.IMHEX_VERSION}}
repo: ImHex-Patterns
token: ${{ secrets.RELEASE_TOKEN }}
- name: ✉️ Update C++ Plugin Template
uses: mvasigh/dispatch-action@main
env:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
if: "${{ env.RELEASE_TOKEN != '' }}"
with:
token: ${{ secrets.RELEASE_TOKEN }}
repo: ImHex-Cpp-Plugin-Template
owner: WerWolv
event_type: update_submodule
release-windows:
name: Release Windows
needs: release-common
runs-on: windows-2022
release-update-winget:
name: Release update winget package
needs: release-upload-artifacts
runs-on: windows-latest
steps:
- name: ⬇️ Download dependencies
shell: pwsh
run: |
iwr https://github.com/microsoft/winget-create/releases/download/v1.1.2.0/wingetcreate.exe -OutFile wingetcreate.exe
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
- name: ⬆️ Update winget manifest
shell: pwsh
env:
@@ -142,7 +167,7 @@ jobs:
run: |
$tagname = $env:GITHUB_REF.Replace("refs/tags/", "")
$version = $tagname.Replace("v", "")
$url = "https://github.com/WerWolv/ImHex/releases/download/${tagname}/imhex-${version}-win64.msi"
$url = "https://github.com/WerWolv/ImHex/releases/download/${tagname}/imhex-${version}-Windows-x86_64.msi"
.\wingetcreate.exe update WerWolv.ImHex -u $url --version $version
if ($version -notmatch "-") {
.\wingetcreate.exe submit .\manifests\w\WerWolv\ImHex\${version}\ --token $env:WINGET_GITHUB_TOKEN

View File

@@ -25,18 +25,18 @@ jobs:
- name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build
key: ${{ runner.os }}-tests-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
restore-keys: ${{ runner.os }}-tests-${{ secrets.CACHE_VERSION }}-build
max-size: 50M
- name: 📜 Restore CMakeCache
uses: actions/cache@v3
with:
path: |
build/CMakeCache.txt
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
key: ${{ runner.os }}-tests-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
- name: ⬇️ Install dependencies
run: |
sudo apt update
@@ -48,14 +48,13 @@ jobs:
cd build
CC=gcc-12 CXX=g++-12 cmake \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all" \
-DIMHEX_OFFLINE_BUILD=ON \
..
make -j4 unit_tests install
make -j4 unit_tests
- name: 🧪 Perform Unit Tests
run: |

9
.gitignore vendored
View File

@@ -2,15 +2,10 @@
.idea/
cmake-build-*/
build-linux/
build*/
venv/
*.mgc
imgui.ini
.DS_Store
plugins/.rustc_info.json
**/target
plugins/example_rust/Cargo.lock
./CMakeUserPresets.json

3
.gitmodules vendored
View File

@@ -29,3 +29,6 @@
[submodule "lib/external/pattern_language"]
path = lib/external/pattern_language
url = https://github.com/WerWolv/PatternLanguage
[submodule "lib/external/libwolv"]
path = lib/external/libwolv
url = https://github.com/WerWolv/libwolv

8
.idea/.gitignore generated vendored
View File

@@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/../../../../../:\_Dev\Cpp\HexEditor\.idea/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

1
.idea/.name generated
View File

@@ -1 +0,0 @@
imhex

14
.idea/deployment.xml generated
View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PublishConfigData" remoteFilesAllowedToDisappearOnAutoupload="false">
<serverData>
<paths name="WSL (e494f5fa-cb38-49f1-b2cb-b9524b92ed51)">
<serverdata>
<mappings>
<mapping local="$PROJECT_DIR$" web="/" />
</mappings>
</serverdata>
</paths>
</serverData>
</component>
</project>

2
.idea/imhex.iml generated
View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

4
.idea/misc.xml generated
View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

8
.idea/modules.xml generated
View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/imhex.iml" filepath="$PROJECT_DIR$/.idea/imhex.iml" />
</modules>
</component>
</project>

16
.idea/vcs.xml generated
View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/lib/external/capstone" vcs="Git" />
<mapping directory="$PROJECT_DIR$/lib/external/curl" vcs="Git" />
<mapping directory="$PROJECT_DIR$/lib/external/fmt" vcs="Git" />
<mapping directory="$PROJECT_DIR$/lib/external/libromfs" vcs="Git" />
<mapping directory="$PROJECT_DIR$/lib/external/nativefiledialog" vcs="Git" />
<mapping directory="$PROJECT_DIR$/lib/external/pattern_language" vcs="Git" />
<mapping directory="$PROJECT_DIR$/lib/external/pattern_language/external/cli11" vcs="Git" />
<mapping directory="$PROJECT_DIR$/lib/external/pattern_language/external/fmt" vcs="Git" />
<mapping directory="$PROJECT_DIR$/lib/external/xdgpp" vcs="Git" />
<mapping directory="$PROJECT_DIR$/lib/external/yara/yara" vcs="Git" />
</component>
</project>

View File

@@ -8,6 +8,9 @@ option(IMHEX_OFFLINE_BUILD "Enable offline build" OFF)
option(IMHEX_IGNORE_BAD_CLONE "Disable the bad clone prevention checks" OFF)
option(IMHEX_PATTERNS_PULL_MASTER "Download latest files from master branch of the ImHex-Patterns repo" OFF)
option(IMHEX_IGNORE_BAD_COMPILER "Allow compiling with an unsupported compiler" OFF)
option(IMHEX_USE_GTK_FILE_PICKER "Use GTK file picker instead of xdg-desktop-portals" OFF)
option(IMHEX_DISABLE_STACKTRACE "Disables support for printing stack traces" OFF)
option(IMHEX_DISABLE_UPDATE_CHECK "Disables built-in update check" OFF)
# Basic compiler and cmake configurations
set(CMAKE_CXX_STANDARD 23)
@@ -19,7 +22,11 @@ include("${IMHEX_BASE_FOLDER}/cmake/build_helpers.cmake")
# Setup project
loadVersion(IMHEX_VERSION)
setVariableInParent(IMHEX_VERSION ${IMHEX_VERSION})
project(imhex VERSION ${IMHEX_VERSION})
project(imhex
LANGUAGES C CXX VERSION ${IMHEX_VERSION}
DESCRIPTION "The ImHex Hex Editor"
HOMEPAGE_URL "https://imhex.werwolv.net"
)
# Make sure project is configured correctly
setDefaultBuiltTypeIfUnset()
@@ -35,13 +42,15 @@ set(PLUGINS
# Add various defines
detectOS()
detectArch()
addVersionDefines()
addDefines()
configurePackingResources()
setUninstallTarget()
addBundledLibraries()
# Add ImHex sources
add_subdirectory(lib/libimhex)
add_subdirectory(main)
add_custom_target(imhex_all ALL DEPENDS main)
add_custom_target(imhex_all ALL DEPENDS main libimhex)
# Add unit tests
enable_testing()

47
CMakePresets.json Normal file
View File

@@ -0,0 +1,47 @@
{
"version": 2,
"cmakeMinimumRequired": {
"major": 3,
"minor": 20,
"patch": 0
},
"configurePresets": [
{
"name": "base",
"displayName": "Base",
"description": "Base configuration for all builds",
"hidden": true,
"binaryDir": "${sourceDir}/build/${presetName}",
"generator": "Ninja",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_C_COMPILER": "gcc",
"CMAKE_CXX_COMPILER": "g++",
"CMAKE_C_COMPILER_LAUNCHER": "ccache",
"CMAKE_CXX_COMPILER_LAUNCHER": "ccache",
"CMAKE_C_FLAGS": "-fuse-ld=lld",
"CMAKE_CXX_FLAGS": "-fuse-ld=lld",
"IMHEX_PATTERNS_PULL_MASTER": "ON",
"CMAKE_INSTALL_PREFIX": "./install",
"USE_SYSTEM_CURL": "ON"
}
},
{
"name": "x86_64",
"displayName": "x86_64 Build",
"description": "x86_64 build",
"inherits": [ "base" ]
}
],
"buildPresets": [
{
"name": "x86_64",
"description": "x86_64 build",
"configurePreset": "x86_64",
"targets": [ "imhex_all" ]
}
],
"testPresets": [
]
}

128
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
Discord @WerWolv#1337.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

67
HACKING.md Normal file
View File

@@ -0,0 +1,67 @@
# Hacking guide
## Introduction
This document is a guide for developers who want to contribute to ImHex in any way. It contains information about the codebase, the build process and the general workflow.
## Codebase
ImHex is written in C++ and usually uses the latest compiler and standard library features available in gcc on all supported OSes. At the time of writing this is C++23.
### Structure
- `main`: Contains the main application code
- Important to understand here is that the main ImHex application is basically just an empty shell.
- All it does is create a Window and a OpenGL context using GLFW, load all available plugins, properly configure ImGui and render it to the screen.
- Everything else is done inside of plugins. ImHex comes with a few plugins by default, most notably the `builtin` plugin which contains the majority of the application code.
- In most cases, this code doesn't need to be modified. Most features should be self-contained inside a plugin.
- `lib`
- `libimhex`: Contains all helper utilities as well as various APIs for plugins to interact with ImHex.
- The library's main purpose is for Dependency Inversion. The ImHex main application as well as libimhex do not know about the existence of plugins at build time. Plugins and the main application instead link against libimhex and use it as a common API to interact with each other.
- Since libimhex is a doesn't know about the existence of plugins, it cannot depend on any of them. This includes localizations and things that get registered by plugins after launch.
- Even if the builtin plugin is technically always available, it is still a plugin and should be treated that way.
- All important APIs can be found in the `hex/api` include directory and are documented in the respective header file.
- `external`: All libraries that need custom patches or aren't typically available in package managers go into here.
- If you'd like to add new features to the Pattern language, please make a PR to https://github.com/WerWolv/PatternLanguage instead. ImHex usually depends on the latest commit of the master branch of this repo.
- `plugins`
- `builtin`: The builtin plugin. Contains the majority of the application code.
- It's the heart of ImHex's functionality. It contains most of the default views, providers, etc. so if you want to add new functionality to ImHex, this is the place to start.
- `tests`: Contains all unit tests for ImHex. These are run automatically by the CI and should be kept up to date, especially when adding new helper functions to libimhex.
### RomFS
ImHex uses a custom library called [libromfs](https://github.com/WerWolv/libromfs). It's a simple static library which uses CMake's code generation feature to embed files into the binary at compile time so they can be accessed at runtime.
All plugins have a `romfs` folder which contains all files that should be embedded into the binary. Resources that need to be embedded into the main application (this is usually not necessary), go into the `resources/romfs` folder.
When adding, changing files or removing files, make sure to re-run CMake to update the generated code. Otherwise, the changes might not be reflected in the binary.
## Development Environment
I personally use CLion for development since it makes configuring and building the project very easy on all platforms.
### Windows
- Install MSYS2 from https://www.msys2.org/ and use the `dist/get_deps_msys2.sh` script to install all dependencies.
### Linux
- Install all dependencies using one of the `dist/get_deps_*.sh` scripts depending on your distribution or install them manually with your package manager.
### macOS
- Install all dependencies using brew and the `dist/Brewfile` script.
## Making Changes
### Adding new features to ImHex
If you'd like to add new features, the best way to start is by joining our Discord and telling us about your idea. We can then discuss the best way to implement it and how it should be integrated into ImHex or if it should be done in a separate plugin.
There are standalone plugin templates that use ImHex as a submodule. You can find them here:
- https://github.com/WerWolv/ImHex-Cpp-Plugin-Template
- https://github.com/WerWolv/ImHex-Rust-Plugin-Template
### Adding a new language
If you'd like to support a new language in ImHex, the best way is by using the `dist/langtool.py` tool. It will create the necessary file for you and help you fill them out.
First, run the tool with `python3 dist/langtool.py create plugins/builtin/romfs/lang <iso_code>` where `<iso_code>` is the ISO 639-1 code of your language. This will create a new file in the language directory.
Afterwards follow the prompts of the program to populate the entire file. Once you're done, rerun cmake and rebuild ImHex. Your language should now be available in the settings.
### Updating an existing language
If you'd like to add missing keys to an existing language, you can also use the `dist/langtool.py` tool. Run it with `python3 dist/langtool.py translate plugins/builtin/romfs/lang <iso_code>` where `<iso_code>` is the ISO 639-1 code of the language.
This will one by one list all the missing translation keys that are present in the default translation file, and you can fill them in with the correct translation for your language.

View File

@@ -2,11 +2,60 @@
## Official Releases
The easiest way to install ImHex is to download the latest release from the [GitHub releases page](github.com/WerWolv/ImHex/releases/latest).
The easiest way to install ImHex is to download the latest release from the [GitHub Releases page](https://github.com/WerWolv/ImHex/releases/latest).
There's also a NoGPU version available for users who don't have a GPU or want to run ImHex in a VM without GPU passthrough.
## Nighly Builds
### Windows
#### Installer
Simply run the installer to install ImHex on your system
#### Portable
Extract the zip file to any location on your system.
### macOS
Simply use the drag-n-drop dmg package to install ImHex on your system. It's possible that you need to allow the app to run in the security settings.
### Linux
#### AppImage
To run the AppImage, make sure it's executable. Then simply run it.
```bash
chmod +x imhex-*.AppImage
./imhex-*.AppImage
```
#### Flatpak
To install the Flatpak, make sure you have the Flathub repository added to your system. Then simply run the following command:
```bash
flatpak install flathub net.werwolv.ImHex
```
#### Ubuntu DEB Package
To install the DEB package, simply run the following command:
```bash
sudo apt install ./imhex-*.deb
```
#### Arch Linux
To install the Arch Linux package, simply run the following command:
```bash
sudo pacman -U imhex-*.pkg.tar.zst
```
#### Fedora / RHEL / AlmaLinux RPM Package
To install the RPM package, simply run the following command:
```bash
sudo dnf install ./imhex-*.rpm
```
## Nightly Builds
The GitHub Actions CI builds a new release package on every commit made to repository. These builds are available on the [GitHub Actions page](https://github.com/WerWolv/ImHex/actions?query=workflow%3A%22Build%22).
These builds are not guaranteed to be stable and may contain bugs, however they also contain new features that are not yet available in the official releases.
@@ -15,7 +64,7 @@ These builds are not guaranteed to be stable and may contain bugs, however they
Build instructions for Windows, Linux and macOS can be found under `/dist/compiling`:
- Windows: [Link](dist/compiling/windows.md)
- macOS: [Link](dist/compiling/macOS.md)
- macOS: [Link](dist/compiling/macos.md)
- Linux: [Link](dist/compiling/linux.md)
## Package managers
@@ -24,10 +73,10 @@ ImHex is also available on various package managers. The officially supported on
### Windows
- **Cocolatey**
- **Chocolatey**
- [imhex](https://community.chocolatey.org/packages/imhex) (Thanks to @Jarcho)
- `choco install imhex`
- **winget**
- **Winget**
- [WerWolv.ImHex](https://github.com/microsoft/winget-pkgs/tree/master/manifests/w/WerWolv/ImHex)
- `winget install WerWolv.ImHex`

View File

@@ -1,11 +1,33 @@
<a href="https://imhex.werwolv.net"><h1 align="center" ><img height="100px" src="resources/projects/logo_text.svg"></h1></a>
<a href="https://imhex.werwolv.net">
<h1 align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./resources/projects/logo_text_light.svg">
<img height="100px" src="./resources/projects/logo_text_dark.svg">
</picture>
</h1>
</a>
<p align="center">A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.</p>
<p align="center">
<a title="'Build' workflow Status" href="https://github.com/WerWolv/ImHex/actions?query=workflow%3ABuild"><img alt="'Build' workflow Status" src="https://img.shields.io/github/workflow/status/WerWolv/ImHex/Build?longCache=true&style=for-the-badge&label=Build&logoColor=fff&logo=GitHub%20Actions"></a>
<a title="Discord Server" href="https://discord.gg/X63jZ36xBY"><img alt="Discord Server" src="https://img.shields.io/discord/789833418631675954?label=Discord&logo=Discord&style=for-the-badge"></a>
<a title="Total Downloads" href="https://github.com/WerWolv/ImHex/releases/latest"><img alt="Total Downloads" src="https://img.shields.io/github/downloads/WerWolv/ImHex/total?longCache=true&style=for-the-badge&label=Downloads&logoColor=fff&logo=GitHub"></a>
<a title="'Build' workflow Status" href="https://github.com/WerWolv/ImHex/actions?query=workflow%3ABuild">
<img alt="'Build' workflow Status" src="https://img.shields.io/github/actions/workflow/status/WerWolv/ImHex/build.yml?longCache=true&style=for-the-badge&label=Build&logoColor=fff&logo=GitHub%20Actions&branch=master">
</a>
<a title="Discord Server" href="https://discord.gg/X63jZ36xBY">
<img alt="Discord Server" src="https://img.shields.io/discord/789833418631675954?label=Discord&logo=Discord&logoColor=fff&style=for-the-badge">
</a>
<a title="Total Downloads" href="https://github.com/WerWolv/ImHex/releases/latest">
<img alt="Total Downloads" src="https://img.shields.io/github/downloads/WerWolv/ImHex/total?longCache=true&style=for-the-badge&label=Downloads&logoColor=fff&logo=GitHub">
</a>
<a title="Code Quality" href="https://www.codefactor.io/repository/github/werwolv/imhex">
<img alt="Code Quality" src="https://img.shields.io/codefactor/grade/github/WerWolv/ImHex?longCache=true&style=for-the-badge&label=Code%20Quality&logoColor=fff&logo=CodeFactor&branch=master">
</a>
<a title="Translation" href="https://weblate.werwolv.net/projects/imhex/">
<img alt="Translation" src="https://img.shields.io/weblate/progress/imhex?logo=weblate&logoColor=%23FFFFFF&server=https%3A%2F%2Fweblate.werwolv.net&style=for-the-badge">
</a>
<a title="Documentation" href="https://imhex.werwolv.net/docs">
<img alt="Documentation" src="https://img.shields.io/badge/Docs-Available-brightgreen?logo=gitbook&logoColor=%23FFFFFF&style=for-the-badge">
</a>
</p>
## Supporting
@@ -120,10 +142,12 @@ For format patterns, libraries, magic and constant files, check out the [ImHex-P
To use ImHex, the following minimal system requirements need to be met:
- **OS**: Windows 7 or higher, macOS 10.15 (Catalina) or higher, "Modern" Linux (Ubuntu 22.04, Fedora Stable/Rawhide, and Arch Linux have official packages, other distributions can use the AppImage)
- **OS**: Windows 7 or higher, macOS 10.15 (Catalina) or higher, "Modern" Linux (Ubuntu 22.04, Fedora 36/37, RHEL/AlmaLinux 9, and Arch Linux have official packages, other and older distributions can use the AppImage)
- **CPU**: x86_64 (64 Bit)
- **GPU**: OpenGL 3.0 or higher (preferable a dedicated GPU and not Intel HD Graphics)
- **RAM**: 512MB, more may be required for more complicated analysis
- **GPU**: OpenGL 3.0 or higher
- Intel HD drivers are really buggy and often cause graphic artifacts
- 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**: 100MB
## Installing

10
SECURITY.md Normal file
View File

@@ -0,0 +1,10 @@
# Security Policy
## Supported Versions
Supported is generally only the latest version that can be downloaded from the Release tab. If you have issues, you might get instructed to use the Nightly release version instead.
If you built ImHex yourself and experience issues that are not present in the version built by GitHub, you're on your own.
## Reporting a Vulnerability
Any critical vulnearabilities can be reported through Discord @WerWolv#1337

View File

@@ -1 +1 @@
1.24.3
1.29.0

View File

@@ -1,37 +1,58 @@
include(FetchContent)
if(IMHEX_STRIP_RELEASE)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s")
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set(CPACK_STRIP_FILES TRUE)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
add_link_options($<$<CONFIG:RELEASE>:-s>)
endif()
endif()
macro(addVersionDefines)
macro(addDefines)
if (NOT IMHEX_VERSION)
message(FATAL_ERROR "IMHEX_VERSION is not defined")
endif ()
if (IS_DIRECTORY "${CMAKE_SOURCE_DIR}/.git")
if (DEFINED IMHEX_COMMIT_HASH_LONG AND DEFINED IMHEX_COMMIT_HASH_SHORT AND DEFINED IMHEX_COMMIT_BRANCH)
add_compile_definitions(
GIT_COMMIT_HASH_LONG="${IMHEX_COMMIT_HASH_LONG}"
IMHEX_COMMIT_HASH_SHORT="${IMHEX_COMMIT_HASH_SHORT}"
GIT_BRANCH="${IMHEX_COMMIT_BRANCH}"
)
else()
# Get the current working branch
execute_process(
COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE RESULT_BRANCH
)
# Get the latest abbreviated commit hash of the working branch
execute_process(
COMMAND git log -1 --format=%h
COMMAND git log -1 --format=%h --abbrev=7
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_VARIABLE GIT_COMMIT_HASH_SHORT
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE RESULT_HASH_SHORT
)
add_compile_definitions(GIT_COMMIT_HASH="${GIT_COMMIT_HASH}" GIT_BRANCH="${GIT_BRANCH}")
execute_process(
COMMAND git log -1 --format=%H
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH_LONG
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE RESULT_HASH_LONG
)
if (RESULT_BRANCH EQUAL 0 AND RESULT_HASH_LONG EQUAL 0 AND RESULT_HASH_SHORT EQUAL 0)
add_compile_definitions(
GIT_COMMIT_HASH_SHORT="${GIT_COMMIT_HASH_SHORT}"
GIT_COMMIT_HASH_LONG="${GIT_COMMIT_HASH_LONG}"
GIT_BRANCH="${GIT_BRANCH}")
endif ()
endif ()
set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -DPROJECT_VERSION_MAJOR=${PROJECT_VERSION_MAJOR} -DPROJECT_VERSION_MINOR=${PROJECT_VERSION_MINOR} -DPROJECT_VERSION_PATCH=${PROJECT_VERSION_PATCH} ")
@@ -39,42 +60,23 @@ macro(addVersionDefines)
set(IMHEX_VERSION_STRING ${IMHEX_VERSION})
if (CMAKE_BUILD_TYPE STREQUAL "Release")
set(IMHEX_VERSION_STRING ${IMHEX_VERSION_STRING})
add_compile_definitions(NDEBUG)
elseif (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(IMHEX_VERSION_STRING ${IMHEX_VERSION_STRING}-Debug)
add_compile_definitions(DEBUG)
add_compile_definitions(DEBUG _GLIBCXX_DEBUG _GLIBCXX_VERBOSE)
elseif (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
set(IMHEX_VERSION_STRING ${IMHEX_VERSION_STRING}-RelWithDebInfo)
add_compile_definitions(NDEBUG)
elseif (CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
set(IMHEX_VERSION_STRING ${IMHEX_VERSION_STRING}-MinSizeRel)
add_compile_definitions(NDEBUG)
endif ()
add_compile_definitions(IMHEX_VERSION="${IMHEX_VERSION_STRING}")
endmacro()
macro(configurePython)
set(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL)
set(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC)
# Enforce that we use non system Python 3 on macOS.
set(Python_FIND_FRAMEWORK NEVER)
find_package(Python COMPONENTS Development REQUIRED)
if(Python_VERSION LESS 3)
message(STATUS ${PYTHON_VERSION_MAJOR_MINOR})
message(FATAL_ERROR "No valid version of Python 3 was found.")
if (NOT IMHEX_DISABLE_UPDATE_CHECK)
add_compile_definitions(HEX_UPDATE_CHECK)
endif()
string(REPLACE "." ";" PYTHON_VERSION_MAJOR_MINOR ${Python_VERSION})
list(LENGTH PYTHON_VERSION_MAJOR_MINOR PYTHON_VERSION_COMPONENT_COUNT)
if (PYTHON_VERSION_COMPONENT_COUNT EQUAL 3)
list(REMOVE_AT PYTHON_VERSION_MAJOR_MINOR 2)
endif ()
list(JOIN PYTHON_VERSION_MAJOR_MINOR "." PYTHON_VERSION_MAJOR_MINOR)
add_compile_definitions(PYTHON_VERSION_MAJOR_MINOR="${PYTHON_VERSION_MAJOR_MINOR}")
endmacro()
# Detect current OS / System
@@ -85,7 +87,9 @@ macro(detectOS)
set(CMAKE_INSTALL_LIBDIR ".")
set(PLUGINS_INSTALL_LOCATION "plugins")
SET(IMHEX_USE_BUNDLED_CA ON)
if (NOT USE_SYSTEM_CURL)
SET(IMHEX_USE_BUNDLED_CA ON)
endif ()
elseif (APPLE)
add_compile_definitions(OS_MACOS)
set(CMAKE_INSTALL_BINDIR ".")
@@ -135,12 +139,11 @@ macro(configurePackingResources)
if (WIN32)
set(APPLICATION_TYPE)
set(IMHEX_ICON "${IMHEX_BASE_FOLDER}/resources/resource.rc")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--allow-multiple-definition")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,-subsystem,windows")
if (CREATE_PACKAGE)
set(CPACK_GENERATOR "WIX")
set(CPACK_PACKAGE_NAME "imhex")
set(CPACK_PACKAGE_NAME "ImHex")
set(CPACK_PACKAGE_VENDOR "WerWolv")
set(CPACK_WIX_UPGRADE_GUID "05000E99-9659-42FD-A1CF-05C554B39285")
set(CPACK_WIX_PRODUCT_ICON "${PROJECT_SOURCE_DIR}/resources/dist/windows/icon.ico")
@@ -165,7 +168,7 @@ macro(configurePackingResources)
set(MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/resources/dist/macos/Info.plist.in")
set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "net.WerWolv.ImHex")
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_VERSION}-${GIT_COMMIT_HASH}")
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_VERSION}-${GIT_COMMIT_HASH_SHORT}")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
string(TIMESTAMP CURR_YEAR "%Y")
@@ -223,7 +226,6 @@ macro(createPackage)
# Grab all dynamically linked dependencies.
INSTALL(CODE "set(CMAKE_INSTALL_BINDIR \"${CMAKE_INSTALL_BINDIR}\")")
INSTALL(CODE "get_filename_component(PY_PARENT \"${Python_LIBRARIES}\" DIRECTORY)")
INSTALL(CODE "LIST(APPEND DEP_FOLDERS \${PY_PARENT})")
install(CODE [[
file(GET_RUNTIME_DEPENDENCIES
@@ -334,6 +336,7 @@ function(loadVersion version)
set(VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/VERSION")
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${VERSION_FILE})
file(READ "${VERSION_FILE}" read_version)
string(STRIP ${read_version} read_version)
set(${version} ${read_version} PARENT_SCOPE)
endfunction()
@@ -390,7 +393,9 @@ function(downloadImHexPatternsFiles dest)
GIT_TAG master
)
FetchContent_Populate(imhex_patterns)
message(STATUS "Downloading ImHex-Patterns repo branch ${PATTERNS_BRANCH}...")
FetchContent_MakeAvailable(imhex_patterns)
message(STATUS "Finished downloading ImHex-Patterns")
else ()
# Maybe patterns are cloned to a subdirectory
@@ -407,10 +412,165 @@ function(downloadImHexPatternsFiles dest)
endfunction()
macro(setupCompilerWarnings target)
set(IMHEX_COMMON_FLAGS "-Wall -Wextra -Werror")
set(IMHEX_C_FLAGS "${IMHEX_COMMON_FLAGS} -Wno-restrict -Wno-stringop-overread -Wno-stringop-overflow")
set(IMHEX_COMMON_FLAGS "-Wall -Wextra -Wpedantic -Werror")
set(IMHEX_C_FLAGS "${IMHEX_COMMON_FLAGS} -Wno-restrict -Wno-stringop-overread -Wno-stringop-overflow -Wno-array-bounds -Wno-dangling-reference")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${IMHEX_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${IMHEX_C_FLAGS}")
set(CMAKE_OBJC_FLAGS "${CMAKE_OBJC_FLAGS} ${IMHEX_COMMON_FLAGS}")
endmacro()
endmacro()
# uninstall target
macro(setUninstallTarget)
if(NOT TARGET uninstall)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif()
endmacro()
macro(addBundledLibraries)
find_package(PkgConfig REQUIRED)
set(EXTERN_LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/lib/external")
set(BUILD_SHARED_LIBS OFF)
add_subdirectory(${EXTERN_LIBS_FOLDER}/imgui)
set_target_properties(imgui PROPERTIES POSITION_INDEPENDENT_CODE ON)
add_subdirectory(${EXTERN_LIBS_FOLDER}/microtar EXCLUDE_FROM_ALL)
set_target_properties(microtar PROPERTIES POSITION_INDEPENDENT_CODE ON)
add_subdirectory(${EXTERN_LIBS_FOLDER}/libwolv EXCLUDE_FROM_ALL)
set_property(TARGET libwolv-types PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-utils PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-io PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-hash PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-containers PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-net PROPERTY POSITION_INDEPENDENT_CODE ON)
set(XDGPP_INCLUDE_DIRS "${EXTERN_LIBS_FOLDER}/xdgpp")
set(CURL_USE_MBEDTLS ON)
set(BUILD_CURL_EXE OFF)
set(FPHSA_NAME_MISMATCHED ON CACHE BOOL "")
if(NOT USE_SYSTEM_FMT)
add_subdirectory(${EXTERN_LIBS_FOLDER}/fmt EXCLUDE_FROM_ALL)
set_target_properties(fmt PROPERTIES POSITION_INDEPENDENT_CODE ON)
set(FMT_LIBRARIES fmt::fmt-header-only)
else()
find_package(fmt 8.0.0 REQUIRED)
set(FMT_LIBRARIES fmt::fmt)
endif()
if (IMHEX_USE_GTK_FILE_PICKER)
set(NFD_PORTAL OFF CACHE BOOL "Use Portals for Linux file dialogs" FORCE)
else ()
set(NFD_PORTAL ON CACHE BOOL "Use GTK for Linux file dialogs" FORCE)
endif ()
if (NOT USE_SYSTEM_NFD)
add_subdirectory(${EXTERN_LIBS_FOLDER}/nativefiledialog EXCLUDE_FROM_ALL)
set_target_properties(nfd PROPERTIES POSITION_INDEPENDENT_CODE ON)
set(NFD_LIBRARIES nfd)
else()
find_package(nfd)
set(NFD_LIBRARIES nfd)
endif()
if(NOT USE_SYSTEM_NLOHMANN_JSON)
add_subdirectory(${EXTERN_LIBS_FOLDER}/nlohmann_json EXCLUDE_FROM_ALL)
set(NLOHMANN_JSON_LIBRARIES nlohmann_json)
else()
find_package(nlohmann_json 3.10.2 REQUIRED)
set(NLOHMANN_JSON_LIBRARIES nlohmann_json::nlohmann_json)
endif()
if(NOT USE_SYSTEM_CURL)
add_subdirectory(${EXTERN_LIBS_FOLDER}/curl EXCLUDE_FROM_ALL)
set_target_properties(libcurl PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_compile_options(libcurl PRIVATE -Wno-deprecated-declarations)
set(LIBCURL_LIBRARIES libcurl)
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBCURL REQUIRED IMPORTED_TARGET libcurl>=7.76.1)
endif()
if (NOT USE_SYSTEM_LLVM)
add_subdirectory(${EXTERN_LIBS_FOLDER}/llvm-demangle EXCLUDE_FROM_ALL)
set_target_properties(LLVMDemangle PROPERTIES POSITION_INDEPENDENT_CODE ON)
else()
find_package(LLVM REQUIRED Demangle)
endif()
if (NOT USE_SYSTEM_YARA)
add_subdirectory(${EXTERN_LIBS_FOLDER}/yara EXCLUDE_FROM_ALL)
set_target_properties(libyara PROPERTIES POSITION_INDEPENDENT_CODE ON)
set(YARA_LIBRARIES libyara)
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(YARA REQUIRED IMPORTED_TARGET yara)
endif()
if (NOT USE_SYSTEM_MINIAUDIO)
add_subdirectory(${EXTERN_LIBS_FOLDER}/miniaudio EXCLUDE_FROM_ALL)
set_target_properties(miniaudio PROPERTIES POSITION_INDEPENDENT_CODE ON)
set(MINIAUDIO_LIBRARIES miniaudio)
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(miniaudio REQUIRED IMPORTED_TARGET miniaudio)
endif()
if (NOT USE_SYSTEM_CAPSTONE)
set(CAPSTONE_BUILD_STATIC_RUNTIME OFF CACHE BOOL "Disable shared library building")
set(CAPSTONE_BUILD_SHARED OFF CACHE BOOL "Disable shared library building")
set(CAPSTONE_BUILD_TESTS OFF CACHE BOOL "Disable tests")
add_subdirectory(${EXTERN_LIBS_FOLDER}/capstone EXCLUDE_FROM_ALL)
set_target_properties(capstone PROPERTIES POSITION_INDEPENDENT_CODE ON)
set(CAPSTONE_LIBRARIES "capstone")
set(CAPSTONE_INCLUDE_DIRS ${EXTERN_LIBS_FOLDER}/capstone/include)
else()
find_package(PkgConfig REQUIRED)
pkg_search_module(CAPSTONE 4.0.2 REQUIRED capstone)
endif()
add_subdirectory(${EXTERN_LIBS_FOLDER}/pattern_language EXCLUDE_FROM_ALL)
set_target_properties(libpl PROPERTIES POSITION_INDEPENDENT_CODE ON)
find_package(mbedTLS 2.26.0 REQUIRED)
pkg_search_module(MAGIC libmagic>=5.39)
if(NOT MAGIC_FOUND)
find_library(MAGIC 5.39 magic REQUIRED)
else()
set(MAGIC_INCLUDE_DIRS ${MAGIC_INCLUDEDIR})
endif()
if (NOT IMHEX_DISABLE_STACKTRACE)
if (WIN32)
message(STATUS "StackWalk enabled!")
set(LIBBACKTRACE_LIBRARIES DbgHelp.lib)
else ()
find_package(Backtrace)
if (${Backtrace_FOUND})
message(STATUS "Backtrace enabled! Header: ${Backtrace_HEADER}")
if (Backtrace_HEADER STREQUAL "execinfo.h")
set(LIBBACKTRACE_LIBRARIES ${Backtrace_LIBRARY})
set(LIBBACKTRACE_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR})
add_compile_definitions(BACKTRACE_HEADER=\"${Backtrace_HEADER}\")
add_compile_definitions(HEX_HAS_EXECINFO)
elseif (Backtrace_HEADER STREQUAL "backtrace.h")
set(LIBBACKTRACE_LIBRARIES ${Backtrace_LIBRARY})
set(LIBBACKTRACE_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR})
add_compile_definitions(BACKTRACE_HEADER=\"${Backtrace_HEADER}\")
add_compile_definitions(HEX_HAS_BACKTRACE)
endif ()
endif()
endif ()
endif ()
endmacro()

View File

@@ -0,0 +1,21 @@
if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt")
endif()
file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif()
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif()
endforeach()

View File

@@ -0,0 +1,91 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindBacktrace
-------------
Find provider for `backtrace(3) <https://man7.org/linux/man-pages/man3/backtrace.3.html>`__.
Checks if OS supports ``backtrace(3)`` via either ``libc`` or custom library.
This module defines the following variables:
``Backtrace_HEADER``
The header file needed for ``backtrace(3)``. Cached.
Could be forcibly set by user.
``Backtrace_INCLUDE_DIRS``
The include directories needed to use ``backtrace(3)`` header.
``Backtrace_LIBRARIES``
The libraries (linker flags) needed to use ``backtrace(3)``, if any.
``Backtrace_FOUND``
Is set if and only if ``backtrace(3)`` support detected.
The following cache variables are also available to set or use:
``Backtrace_LIBRARY``
The external library providing backtrace, if any.
``Backtrace_INCLUDE_DIR``
The directory holding the ``backtrace(3)`` header.
Typical usage is to generate of header file using :command:`configure_file`
with the contents like the following::
#cmakedefine01 Backtrace_FOUND
#if Backtrace_FOUND
# include <${Backtrace_HEADER}>
#endif
And then reference that generated header file in actual source.
#]=======================================================================]
include(CMakePushCheckState)
include(CheckSymbolExists)
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
# List of variables to be provided to find_package_handle_standard_args()
set(_Backtrace_STD_ARGS Backtrace_INCLUDE_DIR)
if(Backtrace_HEADER)
set(_Backtrace_HEADER_TRY "${Backtrace_HEADER}")
else(Backtrace_HEADER)
set(_Backtrace_HEADER_TRY "execinfo.h")
endif(Backtrace_HEADER)
find_path(Backtrace_INCLUDE_DIR "${_Backtrace_HEADER_TRY}")
set(Backtrace_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR})
if (NOT DEFINED Backtrace_LIBRARY)
# First, check if we already have backtrace(), e.g., in libc
cmake_push_check_state(RESET)
set(CMAKE_REQUIRED_INCLUDES ${Backtrace_INCLUDE_DIRS})
set(CMAKE_REQUIRED_QUIET ${Backtrace_FIND_QUIETLY})
check_symbol_exists("backtrace" "${_Backtrace_HEADER_TRY}" _Backtrace_SYM_FOUND)
cmake_pop_check_state()
endif()
if(_Backtrace_SYM_FOUND)
# Avoid repeating the message() call below each time CMake is run.
if(NOT Backtrace_FIND_QUIETLY AND NOT DEFINED Backtrace_LIBRARY)
message(STATUS "backtrace facility detected in default set of libraries")
endif()
set(Backtrace_LIBRARY "" CACHE FILEPATH "Library providing backtrace(3), empty for default set of libraries")
else()
# Check for external library, for non-glibc systems
if(Backtrace_INCLUDE_DIR)
# OpenBSD has libbacktrace renamed to libexecinfo
find_library(Backtrace_LIBRARY "execinfo")
else() # respect user wishes
set(_Backtrace_HEADER_TRY "backtrace.h")
find_path(Backtrace_INCLUDE_DIR ${_Backtrace_HEADER_TRY})
find_library(Backtrace_LIBRARY "backtrace")
endif()
# Prepend list with library path as it's more common practice
set(_Backtrace_STD_ARGS Backtrace_LIBRARY ${_Backtrace_STD_ARGS})
endif()
set(Backtrace_LIBRARIES ${Backtrace_LIBRARY})
set(Backtrace_HEADER "${_Backtrace_HEADER_TRY}" CACHE STRING "Header providing backtrace(3) facility")
find_package_handle_standard_args(Backtrace FOUND_VAR Backtrace_FOUND REQUIRED_VARS ${_Backtrace_STD_ARGS})
mark_as_advanced(Backtrace_HEADER Backtrace_INCLUDE_DIR Backtrace_LIBRARY)

View File

@@ -0,0 +1,611 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindPackageHandleStandardArgs
-----------------------------
This module provides functions intended to be used in :ref:`Find Modules`
implementing :command:`find_package(<PackageName>)` calls.
.. command:: find_package_handle_standard_args
This command handles the ``REQUIRED``, ``QUIET`` and version-related
arguments of :command:`find_package`. It also sets the
``<PackageName>_FOUND`` variable. The package is considered found if all
variables listed contain valid results, e.g. valid filepaths.
There are two signatures:
.. code-block:: cmake
find_package_handle_standard_args(<PackageName>
(DEFAULT_MSG|<custom-failure-message>)
<required-var>...
)
find_package_handle_standard_args(<PackageName>
[FOUND_VAR <result-var>]
[REQUIRED_VARS <required-var>...]
[VERSION_VAR <version-var>]
[HANDLE_VERSION_RANGE]
[HANDLE_COMPONENTS]
[CONFIG_MODE]
[NAME_MISMATCHED]
[REASON_FAILURE_MESSAGE <reason-failure-message>]
[FAIL_MESSAGE <custom-failure-message>]
)
The ``<PackageName>_FOUND`` variable will be set to ``TRUE`` if all
the variables ``<required-var>...`` are valid and any optional
constraints are satisfied, and ``FALSE`` otherwise. A success or
failure message may be displayed based on the results and on
whether the ``REQUIRED`` and/or ``QUIET`` option was given to
the :command:`find_package` call.
The options are:
``(DEFAULT_MSG|<custom-failure-message>)``
In the simple signature this specifies the failure message.
Use ``DEFAULT_MSG`` to ask for a default message to be computed
(recommended). Not valid in the full signature.
``FOUND_VAR <result-var>``
.. deprecated:: 3.3
Specifies either ``<PackageName>_FOUND`` or
``<PACKAGENAME>_FOUND`` as the result variable. This exists only
for compatibility with older versions of CMake and is now ignored.
Result variables of both names are always set for compatibility.
``REQUIRED_VARS <required-var>...``
Specify the variables which are required for this package.
These may be named in the generated failure message asking the
user to set the missing variable values. Therefore these should
typically be cache entries such as ``FOO_LIBRARY`` and not output
variables like ``FOO_LIBRARIES``.
.. versionchanged:: 3.18
If ``HANDLE_COMPONENTS`` is specified, this option can be omitted.
``VERSION_VAR <version-var>``
Specify the name of a variable that holds the version of the package
that has been found. This version will be checked against the
(potentially) specified required version given to the
:command:`find_package` call, including its ``EXACT`` option.
The default messages include information about the required
version and the version which has been actually found, both
if the version is ok or not.
``HANDLE_VERSION_RANGE``
.. versionadded:: 3.19
Enable handling of a version range, if one is specified. Without this
option, a developer warning will be displayed if a version range is
specified.
``HANDLE_COMPONENTS``
Enable handling of package components. In this case, the command
will report which components have been found and which are missing,
and the ``<PackageName>_FOUND`` variable will be set to ``FALSE``
if any of the required components (i.e. not the ones listed after
the ``OPTIONAL_COMPONENTS`` option of :command:`find_package`) are
missing.
``CONFIG_MODE``
Specify that the calling find module is a wrapper around a
call to ``find_package(<PackageName> NO_MODULE)``. This implies
a ``VERSION_VAR`` value of ``<PackageName>_VERSION``. The command
will automatically check whether the package configuration file
was found.
``REASON_FAILURE_MESSAGE <reason-failure-message>``
.. versionadded:: 3.16
Specify a custom message of the reason for the failure which will be
appended to the default generated message.
``FAIL_MESSAGE <custom-failure-message>``
Specify a custom failure message instead of using the default
generated message. Not recommended.
``NAME_MISMATCHED``
.. versionadded:: 3.17
Indicate that the ``<PackageName>`` does not match
``${CMAKE_FIND_PACKAGE_NAME}``. This is usually a mistake and raises a
warning, but it may be intentional for usage of the command for components
of a larger package.
Example for the simple signature:
.. code-block:: cmake
find_package_handle_standard_args(LibXml2 DEFAULT_MSG
LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR)
The ``LibXml2`` package is considered to be found if both
``LIBXML2_LIBRARY`` and ``LIBXML2_INCLUDE_DIR`` are valid.
Then also ``LibXml2_FOUND`` is set to ``TRUE``. If it is not found
and ``REQUIRED`` was used, it fails with a
:command:`message(FATAL_ERROR)`, independent whether ``QUIET`` was
used or not. If it is found, success will be reported, including
the content of the first ``<required-var>``. On repeated CMake runs,
the same message will not be printed again.
.. note::
If ``<PackageName>`` does not match ``CMAKE_FIND_PACKAGE_NAME`` for the
calling module, a warning that there is a mismatch is given. The
``FPHSA_NAME_MISMATCHED`` variable may be set to bypass the warning if using
the old signature and the ``NAME_MISMATCHED`` argument using the new
signature. To avoid forcing the caller to require newer versions of CMake for
usage, the variable's value will be used if defined when the
``NAME_MISMATCHED`` argument is not passed for the new signature (but using
both is an error)..
Example for the full signature:
.. code-block:: cmake
find_package_handle_standard_args(LibArchive
REQUIRED_VARS LibArchive_LIBRARY LibArchive_INCLUDE_DIR
VERSION_VAR LibArchive_VERSION)
In this case, the ``LibArchive`` package is considered to be found if
both ``LibArchive_LIBRARY`` and ``LibArchive_INCLUDE_DIR`` are valid.
Also the version of ``LibArchive`` will be checked by using the version
contained in ``LibArchive_VERSION``. Since no ``FAIL_MESSAGE`` is given,
the default messages will be printed.
Another example for the full signature:
.. code-block:: cmake
find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4)
find_package_handle_standard_args(Automoc4 CONFIG_MODE)
In this case, a ``FindAutmoc4.cmake`` module wraps a call to
``find_package(Automoc4 NO_MODULE)`` and adds an additional search
directory for ``automoc4``. Then the call to
``find_package_handle_standard_args`` produces a proper success/failure
message.
.. command:: find_package_check_version
.. versionadded:: 3.19
Helper function which can be used to check if a ``<version>`` is valid
against version-related arguments of :command:`find_package`.
.. code-block:: cmake
find_package_check_version(<version> <result-var>
[HANDLE_VERSION_RANGE]
[RESULT_MESSAGE_VARIABLE <message-var>]
)
The ``<result-var>`` will hold a boolean value giving the result of the check.
The options are:
``HANDLE_VERSION_RANGE``
Enable handling of a version range, if one is specified. Without this
option, a developer warning will be displayed if a version range is
specified.
``RESULT_MESSAGE_VARIABLE <message-var>``
Specify a variable to get back a message describing the result of the check.
Example for the usage:
.. code-block:: cmake
find_package_check_version(1.2.3 result HANDLE_VERSION_RANGE
RESULT_MESSAGE_VARIABLE reason)
if (result)
message (STATUS "${reason}")
else()
message (FATAL_ERROR "${reason}")
endif()
#]=======================================================================]
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake)
cmake_policy(PUSH)
# numbers and boolean constants
cmake_policy (SET CMP0012 NEW)
# IN_LIST operator
cmake_policy (SET CMP0057 NEW)
# internal helper macro
macro(_FPHSA_FAILURE_MESSAGE _msg)
set (__msg "${_msg}")
if (FPHSA_REASON_FAILURE_MESSAGE)
string(APPEND __msg "\n Reason given by package: ${FPHSA_REASON_FAILURE_MESSAGE}\n")
endif()
if (${_NAME}_FIND_REQUIRED)
message(FATAL_ERROR "${__msg}")
else ()
if (NOT ${_NAME}_FIND_QUIETLY)
message(STATUS "${__msg}")
endif ()
endif ()
endmacro()
# internal helper macro to generate the failure message when used in CONFIG_MODE:
macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
# <PackageName>_CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found:
if(${_NAME}_CONFIG)
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing:${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})")
else()
# If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version.
# List them all in the error message:
if(${_NAME}_CONSIDERED_CONFIGS)
set(configsText "")
list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount)
math(EXPR configsCount "${configsCount} - 1")
foreach(currentConfigIndex RANGE ${configsCount})
list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename)
list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
string(APPEND configsText "\n ${filename} (version ${version})")
endforeach()
if (${_NAME}_NOT_FOUND_MESSAGE)
if (FPHSA_REASON_FAILURE_MESSAGE)
string(PREPEND FPHSA_REASON_FAILURE_MESSAGE "${${_NAME}_NOT_FOUND_MESSAGE}\n ")
else()
set(FPHSA_REASON_FAILURE_MESSAGE "${${_NAME}_NOT_FOUND_MESSAGE}")
endif()
else()
string(APPEND configsText "\n")
endif()
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:${configsText}")
else()
# Simple case: No Config-file was found at all:
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}")
endif()
endif()
endmacro()
function(FIND_PACKAGE_CHECK_VERSION version result)
cmake_parse_arguments (PARSE_ARGV 2 FPCV "HANDLE_VERSION_RANGE;NO_AUTHOR_WARNING_VERSION_RANGE" "RESULT_MESSAGE_VARIABLE" "")
if (FPCV_UNPARSED_ARGUMENTS)
message (FATAL_ERROR "find_package_check_version(): ${FPCV_UNPARSED_ARGUMENTS}: unexpected arguments")
endif()
if ("RESULT_MESSAGE_VARIABLE" IN_LIST FPCV_KEYWORDS_MISSING_VALUES)
message (FATAL_ERROR "find_package_check_version(): RESULT_MESSAGE_VARIABLE expects an argument")
endif()
set (${result} FALSE PARENT_SCOPE)
if (FPCV_RESULT_MESSAGE_VARIABLE)
unset (${FPCV_RESULT_MESSAGE_VARIABLE} PARENT_SCOPE)
endif()
if (_CMAKE_FPHSA_PACKAGE_NAME)
set (package "${_CMAKE_FPHSA_PACKAGE_NAME}")
elseif (CMAKE_FIND_PACKAGE_NAME)
set (package "${CMAKE_FIND_PACKAGE_NAME}")
else()
message (FATAL_ERROR "find_package_check_version(): Cannot be used outside a 'Find Module'")
endif()
if (NOT FPCV_NO_AUTHOR_WARNING_VERSION_RANGE
AND ${package}_FIND_VERSION_RANGE AND NOT FPCV_HANDLE_VERSION_RANGE)
message(AUTHOR_WARNING
"`find_package()` specify a version range but the option "
"HANDLE_VERSION_RANGE` is not passed to `find_package_check_version()`. "
"Only the lower endpoint of the range will be used.")
endif()
set (version_ok FALSE)
unset (version_msg)
if (FPCV_HANDLE_VERSION_RANGE AND ${package}_FIND_VERSION_RANGE)
if ((${package}_FIND_VERSION_RANGE_MIN STREQUAL "INCLUDE"
AND version VERSION_GREATER_EQUAL ${package}_FIND_VERSION_MIN)
AND ((${package}_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE"
AND version VERSION_LESS_EQUAL ${package}_FIND_VERSION_MAX)
OR (${package}_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE"
AND version VERSION_LESS ${package}_FIND_VERSION_MAX)))
set (version_ok TRUE)
set(version_msg "(found suitable version \"${version}\", required range is \"${${package}_FIND_VERSION_RANGE}\")")
else()
set(version_msg "Found unsuitable version \"${version}\", required range is \"${${package}_FIND_VERSION_RANGE}\"")
endif()
elseif (DEFINED ${package}_FIND_VERSION)
if(${package}_FIND_VERSION_EXACT) # exact version required
# count the dots in the version string
string(REGEX REPLACE "[^.]" "" version_dots "${version}")
# add one dot because there is one dot more than there are components
string(LENGTH "${version_dots}." version_dots)
if (version_dots GREATER ${package}_FIND_VERSION_COUNT)
# Because of the C++ implementation of find_package() ${package}_FIND_VERSION_COUNT
# is at most 4 here. Therefore a simple lookup table is used.
if (${package}_FIND_VERSION_COUNT EQUAL 1)
set(version_regex "[^.]*")
elseif (${package}_FIND_VERSION_COUNT EQUAL 2)
set(version_regex "[^.]*\\.[^.]*")
elseif (${package}_FIND_VERSION_COUNT EQUAL 3)
set(version_regex "[^.]*\\.[^.]*\\.[^.]*")
else()
set(version_regex "[^.]*\\.[^.]*\\.[^.]*\\.[^.]*")
endif()
string(REGEX REPLACE "^(${version_regex})\\..*" "\\1" version_head "${version}")
if (NOT ${package}_FIND_VERSION VERSION_EQUAL version_head)
set(version_msg "Found unsuitable version \"${version}\", but required is exact version \"${${package}_FIND_VERSION}\"")
else ()
set(version_ok TRUE)
set(version_msg "(found suitable exact version \"${_FOUND_VERSION}\")")
endif ()
else ()
if (NOT ${package}_FIND_VERSION VERSION_EQUAL version)
set(version_msg "Found unsuitable version \"${version}\", but required is exact version \"${${package}_FIND_VERSION}\"")
else ()
set(version_ok TRUE)
set(version_msg "(found suitable exact version \"${version}\")")
endif ()
endif ()
else() # minimum version
if (${package}_FIND_VERSION VERSION_GREATER version)
set(version_msg "Found unsuitable version \"${version}\", but required is at least \"${${package}_FIND_VERSION}\"")
else()
set(version_ok TRUE)
set(version_msg "(found suitable version \"${version}\", minimum required is \"${${package}_FIND_VERSION}\")")
endif()
endif()
else ()
set(version_ok TRUE)
set(version_msg "(found version \"${version}\")")
endif()
set (${result} ${version_ok} PARENT_SCOPE)
if (FPCV_RESULT_MESSAGE_VARIABLE)
set (${FPCV_RESULT_MESSAGE_VARIABLE} "${version_msg}" PARENT_SCOPE)
endif()
endfunction()
function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
# Set up the arguments for `cmake_parse_arguments`.
set(options CONFIG_MODE HANDLE_COMPONENTS NAME_MISMATCHED HANDLE_VERSION_RANGE)
set(oneValueArgs FAIL_MESSAGE REASON_FAILURE_MESSAGE VERSION_VAR FOUND_VAR)
set(multiValueArgs REQUIRED_VARS)
# Check whether we are in 'simple' or 'extended' mode:
set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} )
list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX)
unset(FPHSA_NAME_MISMATCHED_override)
if (DEFINED FPHSA_NAME_MISMATCHED)
# If the variable NAME_MISMATCHED variable is set, error if it is passed as
# an argument. The former is for old signatures, the latter is for new
# signatures.
list(FIND ARGN "NAME_MISMATCHED" name_mismatched_idx)
if (NOT name_mismatched_idx EQUAL "-1")
message(FATAL_ERROR
"The `NAME_MISMATCHED` argument may only be specified by the argument or "
"the variable, not both.")
endif ()
# But use the variable if it is not an argument to avoid forcing minimum
# CMake version bumps for calling modules.
set(FPHSA_NAME_MISMATCHED_override "${FPHSA_NAME_MISMATCHED}")
endif ()
if(${INDEX} EQUAL -1)
set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG})
set(FPHSA_REQUIRED_VARS ${ARGN})
set(FPHSA_VERSION_VAR)
else()
cmake_parse_arguments(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN})
if(FPHSA_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"")
endif()
if(NOT FPHSA_FAIL_MESSAGE)
set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG")
endif()
# In config-mode, we rely on the variable <PackageName>_CONFIG, which is set by find_package()
# when it successfully found the config-file, including version checking:
if(FPHSA_CONFIG_MODE)
list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG)
list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS)
set(FPHSA_VERSION_VAR ${_NAME}_VERSION)
endif()
if(NOT FPHSA_REQUIRED_VARS AND NOT FPHSA_HANDLE_COMPONENTS)
message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()")
endif()
endif()
if (DEFINED FPHSA_NAME_MISMATCHED_override)
set(FPHSA_NAME_MISMATCHED "${FPHSA_NAME_MISMATCHED_override}")
endif ()
if (DEFINED CMAKE_FIND_PACKAGE_NAME
AND NOT FPHSA_NAME_MISMATCHED
AND NOT _NAME STREQUAL CMAKE_FIND_PACKAGE_NAME)
message(AUTHOR_WARNING
"The package name passed to `find_package_handle_standard_args` "
"(${_NAME}) does not match the name of the calling package "
"(${CMAKE_FIND_PACKAGE_NAME}). This can lead to problems in calling "
"code that expects `find_package` result variables (e.g., `_FOUND`) "
"to follow a certain pattern.")
endif ()
if (${_NAME}_FIND_VERSION_RANGE AND NOT FPHSA_HANDLE_VERSION_RANGE)
message(AUTHOR_WARNING
"`find_package()` specify a version range but the module ${_NAME} does "
"not support this capability. Only the lower endpoint of the range "
"will be used.")
endif()
# to propagate package name to FIND_PACKAGE_CHECK_VERSION
set(_CMAKE_FPHSA_PACKAGE_NAME "${_NAME}")
# now that we collected all arguments, process them
if("x${FPHSA_FAIL_MESSAGE}" STREQUAL "xDEFAULT_MSG")
set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}")
endif()
if (FPHSA_REQUIRED_VARS)
list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR)
endif()
string(TOUPPER ${_NAME} _NAME_UPPER)
string(TOLOWER ${_NAME} _NAME_LOWER)
if(FPHSA_FOUND_VAR)
set(_FOUND_VAR_UPPER ${_NAME_UPPER}_FOUND)
set(_FOUND_VAR_MIXED ${_NAME}_FOUND)
if(FPHSA_FOUND_VAR STREQUAL _FOUND_VAR_MIXED OR FPHSA_FOUND_VAR STREQUAL _FOUND_VAR_UPPER)
set(_FOUND_VAR ${FPHSA_FOUND_VAR})
else()
message(FATAL_ERROR "The argument for FOUND_VAR is \"${FPHSA_FOUND_VAR}\", but only \"${_FOUND_VAR_MIXED}\" and \"${_FOUND_VAR_UPPER}\" are valid names.")
endif()
else()
set(_FOUND_VAR ${_NAME_UPPER}_FOUND)
endif()
# collect all variables which were not found, so they can be printed, so the
# user knows better what went wrong (#6375)
set(MISSING_VARS "")
set(DETAILS "")
# check if all passed variables are valid
set(FPHSA_FOUND_${_NAME} TRUE)
foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS})
if(NOT ${_CURRENT_VAR})
set(FPHSA_FOUND_${_NAME} FALSE)
string(APPEND MISSING_VARS " ${_CURRENT_VAR}")
else()
string(APPEND DETAILS "[${${_CURRENT_VAR}}]")
endif()
endforeach()
if(FPHSA_FOUND_${_NAME})
set(${_NAME}_FOUND TRUE)
set(${_NAME_UPPER}_FOUND TRUE)
else()
set(${_NAME}_FOUND FALSE)
set(${_NAME_UPPER}_FOUND FALSE)
endif()
# component handling
unset(FOUND_COMPONENTS_MSG)
unset(MISSING_COMPONENTS_MSG)
if(FPHSA_HANDLE_COMPONENTS)
foreach(comp ${${_NAME}_FIND_COMPONENTS})
if(${_NAME}_${comp}_FOUND)
if(NOT DEFINED FOUND_COMPONENTS_MSG)
set(FOUND_COMPONENTS_MSG "found components:")
endif()
string(APPEND FOUND_COMPONENTS_MSG " ${comp}")
else()
if(NOT DEFINED MISSING_COMPONENTS_MSG)
set(MISSING_COMPONENTS_MSG "missing components:")
endif()
string(APPEND MISSING_COMPONENTS_MSG " ${comp}")
if(${_NAME}_FIND_REQUIRED_${comp})
set(${_NAME}_FOUND FALSE)
string(APPEND MISSING_VARS " ${comp}")
endif()
endif()
endforeach()
set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}")
string(APPEND DETAILS "[c${COMPONENT_MSG}]")
endif()
# version handling:
set(VERSION_MSG "")
set(VERSION_OK TRUE)
# check that the version variable is not empty to avoid emitting a misleading
# message (i.e. `Found unsuitable version ""`)
if (DEFINED ${_NAME}_FIND_VERSION)
if(DEFINED ${FPHSA_VERSION_VAR})
if(NOT "${${FPHSA_VERSION_VAR}}" STREQUAL "")
set(_FOUND_VERSION ${${FPHSA_VERSION_VAR}})
if (FPHSA_HANDLE_VERSION_RANGE)
set (FPCV_HANDLE_VERSION_RANGE HANDLE_VERSION_RANGE)
else()
set(FPCV_HANDLE_VERSION_RANGE NO_AUTHOR_WARNING_VERSION_RANGE)
endif()
find_package_check_version ("${_FOUND_VERSION}" VERSION_OK RESULT_MESSAGE_VARIABLE VERSION_MSG
${FPCV_HANDLE_VERSION_RANGE})
else()
set(VERSION_OK FALSE)
endif()
endif()
if("${${FPHSA_VERSION_VAR}}" STREQUAL "")
# if the package was not found, but a version was given, add that to the output:
if(${_NAME}_FIND_VERSION_EXACT)
set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")")
elseif (FPHSA_HANDLE_VERSION_RANGE AND ${_NAME}_FIND_VERSION_RANGE)
set(VERSION_MSG "(Required is version range \"${${_NAME}_FIND_VERSION_RANGE}\")")
else()
set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")")
endif()
endif()
else ()
# Check with DEFINED as the found version may be 0.
if(DEFINED ${FPHSA_VERSION_VAR})
set(VERSION_MSG "(found version \"${${FPHSA_VERSION_VAR}}\")")
endif()
endif ()
if(VERSION_OK)
string(APPEND DETAILS "[v${${FPHSA_VERSION_VAR}}(${${_NAME}_FIND_VERSION})]")
else()
set(${_NAME}_FOUND FALSE)
endif()
# print the result:
if (${_NAME}_FOUND)
FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}")
else ()
if(FPHSA_CONFIG_MODE)
_FPHSA_HANDLE_FAILURE_CONFIG_MODE()
else()
if(NOT VERSION_OK)
set(RESULT_MSG)
if (_FIRST_REQUIRED_VAR)
string (APPEND RESULT_MSG "found ${${_FIRST_REQUIRED_VAR}}")
endif()
if (COMPONENT_MSG)
if (RESULT_MSG)
string (APPEND RESULT_MSG ", ")
endif()
string (APPEND RESULT_MSG "${FOUND_COMPONENTS_MSG}")
endif()
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (${RESULT_MSG})")
else()
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing:${MISSING_VARS}) ${VERSION_MSG}")
endif()
endif()
endif ()
set(${_NAME}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE)
set(${_NAME_UPPER}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE)
endfunction()
cmake_policy(POP)

View File

@@ -0,0 +1,48 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindPackageMessage
------------------
.. code-block:: cmake
find_package_message(<name> "message for user" "find result details")
This function is intended to be used in FindXXX.cmake modules files.
It will print a message once for each unique find result. This is
useful for telling the user where a package was found. The first
argument specifies the name (XXX) of the package. The second argument
specifies the message to display. The third argument lists details
about the find result so that if they change the message will be
displayed again. The macro also obeys the QUIET argument to the
find_package command.
Example:
.. code-block:: cmake
if(X11_FOUND)
find_package_message(X11 "Found X11: ${X11_X11_LIB}"
"[${X11_X11_LIB}][${X11_INCLUDE_DIR}]")
else()
...
endif()
#]=======================================================================]
function(find_package_message pkg msg details)
# Avoid printing a message repeatedly for the same find result.
if(NOT ${pkg}_FIND_QUIETLY)
string(REPLACE "\n" "" details "${details}")
set(DETAILS_VAR FIND_PACKAGE_MESSAGE_DETAILS_${pkg})
if(NOT "${details}" STREQUAL "${${DETAILS_VAR}}")
# The message has not yet been printed.
message(STATUS "${msg}")
# Save the find details in the cache to avoid printing the same
# message again.
set("${DETAILS_VAR}" "${details}"
CACHE INTERNAL "Details about finding ${pkg}")
endif()
endif()
endfunction()

View File

@@ -46,7 +46,7 @@ endfunction()
include(BundleUtilities)
set(BU_CHMOD_BUNDLE_ITEMS ON)
fixup_bundle("${BUNDLE_PATH}" "${extra_libs}" "${extra_dirs}" IGNORE_ITEM "Python")
fixup_bundle("${BUNDLE_PATH}" "${extra_libs}" "${extra_dirs}")
if (CODE_SIGN_CERTIFICATE_ID)
# Hack around Apple Silicon signing bugs by copying the real app, signing it and moving it back.

View File

@@ -107,7 +107,6 @@ AppDir:
- /lib/x86_64-linux-gnu/libpcre2-8.so.0
- /lib/x86_64-linux-gnu/libpixman-1.so.0
- /lib/x86_64-linux-gnu/libpng16.so.16
- /lib/x86_64-linux-gnu/libpython3.10.so.1.0
- /lib/x86_64-linux-gnu/libsasl2.so.2
- /lib/x86_64-linux-gnu/libsensors.so.5
- /lib/x86_64-linux-gnu/libstdc++.so.6
@@ -136,5 +135,5 @@ AppDir:
- usr/share/doc/*/TODO.*
AppImage:
arch: x86_64
update-information: gh-releases-zsync|WerWolv|ImHex|latest|imhex-*.AppImage.zsync
file_name: imhex-{{VERSION}}.AppImage
update-information: gh-releases-zsync|WerWolv|ImHex|latest|imhex-*-x86_64.AppImage.zsync
file_name: imhex-{{VERSION}}-x86_64.AppImage

6
dist/Arch/PKGBUILD vendored
View File

@@ -1,4 +1,4 @@
# Maintainer: iTrooz_ <itrooz at protonmail dot com>
# Maintainer: iTrooz_ <aur at itrooz dot fr>
# Contributor: Morten Linderud <foxboron@archlinux.org>
pkgname=imhex-bin
@@ -8,11 +8,11 @@ pkgdesc="A Hex Editor for Reverse Engineers, Programmers and people who value th
arch=("x86_64")
url="https://github.com/WerWolv/ImHex"
license=('GPL2')
depends=(glfw mbedtls python freetype2 libglvnd dbus xdg-desktop-portal curl fmt yara nlohmann-json)
depends=(glfw mbedtls freetype2 libglvnd dbus xdg-desktop-portal curl fmt yara nlohmann-json)
makedepends=(git)
provides=(imhex)
conflicts=(imhex)
source=("$url/releases/download/v$pkgver/imhex-$pkgver-ArchLinux.pkg.tar.zst")
source=("$url/releases/download/v$pkgver/imhex-$pkgver-ArchLinux-x86_64.pkg.tar.zst")
md5sums=(SKIP)
package() {

2
dist/Brewfile vendored
View File

@@ -2,9 +2,9 @@ brew "mbedtls"
brew "nlohmann-json"
brew "cmake"
brew "ccache"
brew "python3"
brew "freetype2"
brew "libmagic"
brew "pkg-config"
brew "gcc@12"
brew "llvm"
brew "glfw"

View File

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

3
dist/Dockerfile vendored
View File

@@ -1,6 +1,6 @@
FROM archlinux:latest
LABEL maintainer="hey@werwolv.net" = WerWolv
LABEL maintainer="hey@werwolv.net WerWolv"
# Install dependencies
RUN pacman -Syy --needed --noconfirm
@@ -13,7 +13,6 @@ RUN pacman -S --needed --noconfirm \
glfw-x11 \
file \
mbedtls \
python3 \
freetype2 \
dbus \
xdg-desktop-portal

View File

@@ -9,20 +9,15 @@ HOMEPAGE="https://github.com/WerWolv/ImHex"
SRC_URI=""
EGIT_REPO_URI="https://github.com/WerWolv/ImHex.git"
PYTHON_COMPAT=( python3_{6,7,8,9} )
inherit git-r3 python-single-r1 cmake
inherit git-r3 cmake
LICENSE="GPL-2"
SLOT="0"
KEYWORDS="~amd64"
IUSE=""
REQUIRED_USE="${PYTHON_REQUIRED_USE}"
DEPEND=""
RDEPEND="${DEPEND}
${PYTHON_DEPS}
media-libs/glfw
sys-apps/file
dev-libs/mbedtls

View File

@@ -28,5 +28,5 @@ make -j4 package
```
If the build fails while trying to find the macOS libraries, make sure you have
XCode installed with `xcode-select --install`. Homebrew will also help get the
most recent SDK installed and configured with `brew doctor`.
Xcode installed with `xcode-select --install`. Homebrew will also help get the
most recent SDK installed and configured with `brew doctor`.

View File

@@ -7,7 +7,6 @@ pacman -S $@ --needed \
glfw \
file \
mbedtls \
python3 \
freetype2 \
dbus \
xdg-desktop-portal \

View File

@@ -19,7 +19,6 @@ apt install -y \
libglm-dev \
libmagic-dev \
libmbedtls-dev \
python3-dev \
libfreetype-dev \
libdbus-1-dev \
xdg-desktop-portal

View File

@@ -10,5 +10,4 @@ dnf install -y \
mesa-libGL-devel \
glfw-devel \
lld \
mbedtls-devel \
python3-devel
mbedtls-devel

View File

@@ -9,6 +9,5 @@ pacman -S --needed --noconfirm \
mingw-w64-x86_64-glfw \
mingw-w64-x86_64-file \
mingw-w64-x86_64-mbedtls \
mingw-w64-x86_64-python \
mingw-w64-x86_64-freetype \
mingw-w64-x86_64-dlfcn

104
dist/langtool.py vendored Normal file
View File

@@ -0,0 +1,104 @@
from pathlib import Path
import sys
import json
DEFAULT_LANG = "en_US"
INVALID_TRANSLATION = ""
def handle_missing_key(command, lang_data, key, value):
if command == "check":
print(f"Error: Translation {lang_data['code']} is missing translation for key '{key}'")
exit(2)
elif command == "translate" or command == "create":
print(f"Key \033[1m'{key}': '{value}'\033[0m is missing in translation '{lang_data['code']}'")
new_value = input("Enter translation: ")
lang_data["translations"][key] = new_value
elif command == "update":
lang_data["translations"][key] = INVALID_TRANSLATION
def main():
if len(sys.argv) < 3:
print(f"Usage: {Path(sys.argv[0]).name} <check|translate|update|create> <lang folder path> <language>")
return 1
command = sys.argv[1]
if command not in ["check", "translate", "update", "create"]:
print(f"Unknown command: {command}")
return 1
print(f"Using langtool in {command} mode")
lang_folder_path = Path(sys.argv[2])
if not lang_folder_path.exists():
print(f"Error: {lang_folder_path} does not exist")
return 1
if not lang_folder_path.is_dir():
print(f"Error: {lang_folder_path} is not a folder")
return 1
lang = sys.argv[3] if len(sys.argv) > 3 else ""
print(f"Processing language files in {lang_folder_path}...")
default_lang_file_path = lang_folder_path / Path(DEFAULT_LANG + ".json")
if not default_lang_file_path.exists():
print(f"Error: Default language file {default_lang_file_path} does not exist")
return 1
print(f"Using file '{default_lang_file_path.name}' as template language file")
with default_lang_file_path.open("r", encoding="utf-8") as default_lang_file:
default_lang_data = json.load(default_lang_file)
if command == "create" and lang != "":
lang_file_path = lang_folder_path / Path(lang + ".json")
if lang_file_path.exists():
print(f"Error: Language file {lang_file_path} already exists")
return 1
print(f"Creating new language file '{lang_file_path.name}'")
with lang_file_path.open("w", encoding="utf-8") as new_lang_file:
new_lang_data = {
"code": lang,
"language": input("Enter language: "),
"country": input("Enter country: "),
"translations": {}
}
json.dump(new_lang_data, new_lang_file, indent=4, ensure_ascii=False)
for additional_lang_file_path in lang_folder_path.glob("*.json"):
if not lang == "" and not additional_lang_file_path.stem == lang:
continue
if additional_lang_file_path.name.startswith(DEFAULT_LANG):
continue
print(f"\nProcessing file '{additional_lang_file_path.name}'\n----------------------------\n")
with additional_lang_file_path.open("r+", encoding="utf-8") as additional_lang_file:
additional_lang_data = json.load(additional_lang_file)
for key, value in default_lang_data["translations"].items():
if key not in additional_lang_data["translations"] or additional_lang_data["translations"][key] == INVALID_TRANSLATION:
handle_missing_key(command, additional_lang_data, key, value)
keys_to_remove = []
for key, value in additional_lang_data["translations"].items():
if key not in default_lang_data["translations"]:
keys_to_remove.append(key)
for key in keys_to_remove:
additional_lang_data["translations"].pop(key)
print(f"Removed unused key '{key}' from translation '{additional_lang_data['code']}'")
additional_lang_file.seek(0)
additional_lang_file.truncate()
json.dump(additional_lang_data, additional_lang_file, indent=4, sort_keys=True, ensure_ascii=False)
if __name__ == '__main__':
exit(main())

2
dist/msys2/PKGBUILD vendored
View File

@@ -7,7 +7,6 @@ pkgdesc="${_realname}: a Hex Editor for Reverse Engineers, Programmers and peopl
arch=('any')
url="https://github.com/WerWolv/ImHex"
license=('GPLv2')
depends=("${MINGW_PACKAGE_PREFIX}-python")
makedepends=("${MINGW_PACKAGE_PREFIX}-gcc"
"${MINGW_PACKAGE_PREFIX}-lld"
"${MINGW_PACKAGE_PREFIX}-cmake"
@@ -17,7 +16,6 @@ makedepends=("${MINGW_PACKAGE_PREFIX}-gcc"
"${MINGW_PACKAGE_PREFIX}-file"
"${MINGW_PACKAGE_PREFIX}-mbedtls"
"${MINGW_PACKAGE_PREFIX}-polly"
"${MINGW_PACKAGE_PREFIX}-python"
"${MINGW_PACKAGE_PREFIX}-freetype")
source=()

111
dist/rpm/imhex.spec vendored
View File

@@ -1,13 +1,14 @@
# ftbfs without this
%global _lto_cflags %{nil}
Name: imhex
Version: %{_version}
Version: 1.26.2
Release: 0%{?dist}
Summary: A hex editor for reverse engineers and programmers
License: GPL-2.0-only
License: GPL-2.0-only AND Zlib AND MIT AND Apache-2.0
# imhex is gplv2. capstone is custom. nativefiledialog is Zlib.
# see license dir for full breakdown
URL: https://imhex.werwolv.net/
# We need the archive with deps bundled
Source0: https://github.com/WerWolv/%{name}/releases/download/v%{version}/Full.Sources.tar.gz#/%{name}-%{version}.tar.gz
BuildRequires: cmake
BuildRequires: desktop-file-utils
@@ -16,17 +17,33 @@ BuildRequires: file-devel
BuildRequires: freetype-devel
BuildRequires: fmt-devel
BuildRequires: gcc-c++
BuildRequires: mesa-libGL-devel
BuildRequires: libappstream-glib
BuildRequires: libglvnd-devel
BuildRequires: glfw-devel
BuildRequires: json-devel
BuildRequires: libcurl-devel
BuildRequires: llvm-devel
BuildRequires: mbedtls-devel
BuildRequires: python3-devel
%if 0%{?fedora} >= 37
BuildRequires: yara-devel
BuildRequires: nativefiledialog-extended-devel
%if 0%{?rhel}
BuildRequires: gcc-toolset-12
%endif
Provides: bundled(gnulib)
Provides: bundled(capstone) = 5.0-rc2
Provides: bundled(imgui)
Provides: bundled(libromfs)
Provides: bundled(microtar)
Provides: bundled(libpl)
Provides: bundled(xdgpp)
# ftbfs on these arches. armv7hl might compile when capstone 5.x
# is released upstream and we can build against it
# [7:02 PM] WerWolv: We're not supporting 32 bit anyways soooo
# [11:38 AM] WerWolv: Officially supported are x86_64 and aarch64
ExclusiveArch: x86_64 %{arm64} ppc64le
%description
ImHex is a Hex Editor, a tool to display, decode and analyze binary data to
@@ -41,26 +58,26 @@ same time ImHex is completely free and open source under the GPLv2 language.
%prep
# don't use the setup macro since we're pulling from git
cp -r %{_src_path}/* %{_builddir}/
%autosetup -n ImHex
# remove bundled libs we aren't using
rm -rf lib/external/{curl,fmt,llvm,nlohmann_json,yara}
%build
%cmake \
-DCMAKE_BUILD_TYPE=%{_build_type} \
-D USE_SYSTEM_NLOHMANN_JSON=ON \
-D USE_SYSTEM_FMT=ON \
-D USE_SYSTEM_CURL=ON \
-D USE_SYSTEM_LLVM=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-D IMHEX_PATTERNS_PULL_MASTER=ON \
%if 0%{?fedora} >= 37
-D USE_SYSTEM_YARA=ON \
# if fedora <= 36 get updated to yara 4.2.x then they should \
# be able to build against system libs \
# https://bugzilla.redhat.com/show_bug.cgi?id=2112508 \
%if 0%{?rhel}
. /opt/rh/gcc-toolset-12/enable
%set_build_flags
CXXFLAGS+=" -std=gnu++2b"
%endif
%cmake \
-D CMAKE_BUILD_TYPE=Release \
-D IMHEX_STRIP_RELEASE=OFF \
-D IMHEX_OFFLINE_BUILD=ON \
-D USE_SYSTEM_NLOHMANN_JSON=ON \
-D USE_SYSTEM_FMT=ON \
-D USE_SYSTEM_CURL=ON \
-D USE_SYSTEM_LLVM=ON \
-D USE_SYSTEM_YARA=ON \
-D USE_SYSTEM_NFD=ON \
# when capstone >= 5.x is released we should be able to build against \
# system libs of it \
# -D USE_SYSTEM_CAPSTONE=ON
@@ -68,23 +85,45 @@ cp -r %{_src_path}/* %{_builddir}/
%cmake_build
%check
%if 0%{?rhel}
. /opt/rh/gcc-toolset-12/enable
%set_build_flags
CXXFLAGS+=" -std=gnu++2b"
%endif
# build binaries required for tests
%cmake_build --target unit_tests
%ctest --exclude-regex '(Helpers/StoreAPI|Helpers/TipsAPI|Helpers/ContentAPI)'
# Helpers/*API exclude tests that require network access
%install
%cmake_install
desktop-file-validate %{buildroot}%{_datadir}/applications/imhex.desktop
desktop-file-validate %{buildroot}%{_datadir}/applications/%{name}.desktop
# this is a symlink for the old appdata name that we don't need
rm -f %{buildroot}%{_metainfodir}/net.werwolv.%{name}.appdata.xml
# AppData
appstream-util validate-relax --nonet %{buildroot}%{_metainfodir}/net.werwolv.%{name}.metainfo.xml
# install licenses
cp -a lib/external/nativefiledialog/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/nativefiledialog-LICENSE
cp -a lib/external/capstone/LICENSE.TXT %{buildroot}%{_datadir}/licenses/%{name}/capstone-LICENSE
cp -a lib/external/capstone/suite/regress/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/capstone-regress-LICENSE
cp -a lib/external/microtar/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/microtar-LICENSE
cp -a lib/external/xdgpp/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/xdgpp-LICENSE
%files
%dir %{_datadir}/licenses/imhex
%license %{_datadir}/licenses/imhex/LICENSE
%license %{_datadir}/licenses/%{name}/
%doc README.md
%{_bindir}/imhex
%dir %{_datadir}/imhex
%{_datadir}/imhex/*
%{_datadir}/pixmaps/imhex.png
%{_datadir}/applications/imhex.desktop
%{_prefix}/lib64/libimhex.so.%{_version}
%{_prefix}/lib64/imhex/plugins/*
%{_metainfodir}/net.werwolv.imhex.metainfo.xml
%{_metainfodir}/net.werwolv.imhex.appdata.xml
%{_datadir}/pixmaps/%{name}.png
%{_datadir}/applications/%{name}.desktop
%{_libdir}/libimhex.so*
%{_libdir}/%{name}/
%{_metainfodir}/net.werwolv.%{name}.metainfo.xml
%changelog

View File

@@ -8,10 +8,6 @@ find_package(Freetype REQUIRED)
find_package(OpenGL REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
if (UNIX)
find_package(OpenGL REQUIRED)
endif ()
add_library(imgui OBJECT
source/imgui.cpp
source/imgui_demo.cpp
@@ -37,14 +33,9 @@ add_library(imgui OBJECT
source/fonts/unifont_font.c
)
add_compile_definitions(IMGUI_IMPL_OPENGL_LOADER_GLAD)
target_compile_definitions(imgui PUBLIC IMGUI_IMPL_OPENGL_LOADER_GLAD)
target_compile_options(imgui PRIVATE -Wno-stringop-overflow)
target_include_directories(imgui PUBLIC include ${FREETYPE_INCLUDE_DIRS} ${GLFW_INCLUDE_DIRS})
target_link_directories(imgui PUBLIC ${GLFW_LIBRARY_DIRS})
if (WIN32)
target_link_libraries(imgui PUBLIC Freetype::Freetype glfw3 opengl32.lib)
elseif (UNIX)
target_link_libraries(imgui PUBLIC Freetype::Freetype glfw OpenGL::GL)
endif()
target_include_directories(imgui PUBLIC include ${FREETYPE_INCLUDE_DIRS} ${GLFW_INCLUDE_DIRS} ${OpenGL_INCLUDE_DIRS})
target_link_directories(imgui PUBLIC ${GLFW_LIBRARY_DIRS} ${OpenGL_LIBRARY_DIRS})
target_link_libraries(imgui PUBLIC Freetype::Freetype ${GLFW_LIBRARIES} ${OPENGL_LIBRARIES})

View File

@@ -188,8 +188,8 @@ public:
void SetLanguageDefinition(const LanguageDefinition& aLanguageDef);
const LanguageDefinition& GetLanguageDefinition() const { return mLanguageDefinition; }
const Palette& GetPalette() const { return mPaletteBase; }
void SetPalette(const Palette& aValue);
static const Palette& GetPalette() { return sPaletteBase; }
static void SetPalette(const Palette& aValue);
void SetErrorMarkers(const ErrorMarkers& aMarkers) { mErrorMarkers = aMarkers; }
void SetBreakpoints(const Breakpoints& aMarkers) { mBreakpoints = aMarkers; }
@@ -372,7 +372,7 @@ private:
bool mIgnoreImGuiChild;
bool mShowWhitespaces;
Palette mPaletteBase;
static Palette sPaletteBase;
Palette mPalette;
LanguageDefinition mLanguageDefinition;
RegexList mRegexList;

File diff suppressed because it is too large Load Diff

View File

@@ -21,9 +21,10 @@ bool equals(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Bi
return first1 == last1 && first2 == last2;
}
TextEditor::Palette TextEditor::sPaletteBase = TextEditor::GetDarkPalette();
TextEditor::TextEditor()
: mLineSpacing(1.0f), mUndoIndex(0), mTabSize(4), mOverwrite(false), mReadOnly(false), mWithinRender(false), mScrollToCursor(false), mScrollToTop(false), mTextChanged(false), mColorizerEnabled(true), mTextStart(20.0f), mLeftMargin(10), mCursorPositionChanged(false), mColorRangeMin(0), mColorRangeMax(0), mSelectionMode(SelectionMode::Normal), mCheckComments(true), mLastClick(-1.0f), mHandleKeyboardInputs(true), mHandleMouseInputs(true), mIgnoreImGuiChild(false), mShowWhitespaces(true), mStartTime(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count()) {
SetPalette(GetDarkPalette());
SetLanguageDefinition(LanguageDefinition::HLSL());
mLines.push_back(Line());
}
@@ -42,7 +43,7 @@ void TextEditor::SetLanguageDefinition(const LanguageDefinition &aLanguageDef) {
}
void TextEditor::SetPalette(const Palette &aValue) {
mPaletteBase = aValue;
sPaletteBase = aValue;
}
std::string TextEditor::GetText(const Coordinates &aStart, const Coordinates &aEnd) const {
@@ -313,7 +314,7 @@ TextEditor::Coordinates TextEditor::FindWordStart(const Coordinates &aFrom) cons
while (cindex > 0 && isspace(line[cindex].mChar))
--cindex;
auto cstart = (PaletteIndex)line[cindex].mColorIndex;
auto cstart = line[cindex].mChar;
while (cindex > 0) {
auto c = line[cindex].mChar;
if ((c & 0xC0) != 0x80) // not UTF code sequence 10xxxxxx
@@ -322,8 +323,15 @@ TextEditor::Coordinates TextEditor::FindWordStart(const Coordinates &aFrom) cons
cindex++;
break;
}
if (cstart != (PaletteIndex)line[size_t(cindex - 1)].mColorIndex)
if (isalnum(cstart) || cstart == '_') {
if (!isalnum(c) && c != '_') {
cindex++;
break;
}
} else {
break;
}
}
--cindex;
}
@@ -631,10 +639,24 @@ void TextEditor::HandleKeyboardInputs() {
MoveEnd(shift);
else if (!IsReadOnly() && !ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Delete)))
Delete();
else if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Delete))) {
auto wordStart = GetCursorPosition();
MoveRight();
auto wordEnd = FindWordEnd(GetCursorPosition());
SetSelection(wordStart, wordEnd);
Backspace();
}
else if (!IsReadOnly() && !ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Backspace)))
Backspace();
else if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Backspace))) {
auto wordEnd = GetCursorPosition();
MoveLeft();
auto wordStart = FindWordStart(GetCursorPosition());
SetSelection(wordStart, wordEnd);
Backspace();
}
else if (!ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert)))
mOverwrite ^= true;
mOverwrite = !mOverwrite;
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert)))
Copy();
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_C)))
@@ -740,7 +762,7 @@ void TextEditor::Render() {
/* Update palette with the current alpha from style */
for (int i = 0; i < (int)PaletteIndex::Max; ++i) {
auto color = ImGui::ColorConvertU32ToFloat4(mPaletteBase[i]);
auto color = ImGui::ColorConvertU32ToFloat4(sPaletteBase[i]);
color.w *= ImGui::GetStyle().Alpha;
mPalette[i] = ImGui::ColorConvertFloat4ToU32(color);
}
@@ -1095,7 +1117,8 @@ void TextEditor::EnterCharacter(ImWchar aChar, bool aShift) {
}
}
} else {
line.insert(line.begin(), Glyph('\t', TextEditor::PaletteIndex::Background));
for (int j = start.mColumn % mTabSize; j < mTabSize; j++)
line.insert(line.begin(), Glyph(' ', PaletteIndex::Background));
modified = true;
}
}
@@ -1156,6 +1179,13 @@ void TextEditor::EnterCharacter(ImWchar aChar, bool aShift) {
line.erase(line.begin() + cindex, line.begin() + line.size());
SetCursorPosition(Coordinates(coord.mLine + 1, GetCharacterColumn(coord.mLine + 1, (int)whitespaceSize)));
u.mAdded = (char)aChar;
} else if (aChar == '\t') {
auto &line = mLines[coord.mLine];
auto cindex = GetCharacterIndex(coord);
auto spacesToInsert = mTabSize - (cindex % mTabSize);
for (int j = 0; j < spacesToInsert; j++)
line.insert(line.begin() + cindex, Glyph(' ', PaletteIndex::Background));
SetCursorPosition(Coordinates(coord.mLine, GetCharacterColumn(coord.mLine, cindex + spacesToInsert)));
} else {
char buf[7];
int e = ImTextCharToUtf8(buf, 7, aChar);
@@ -2032,7 +2062,9 @@ void TextEditor::ColorizeInternal() {
}
}
}
line[currentIndex].mPreprocessor = withinPreproc;
if (currentIndex < line.size())
line[currentIndex].mPreprocessor = withinPreproc;
currentIndex += UTF8CharLength(c);
if (currentIndex >= (int)line.size()) {
currentIndex = 0;
@@ -2112,7 +2144,7 @@ void TextEditor::EnsureCursorVisible() {
if (len + mTextStart < left + 4)
ImGui::SetScrollX(std::max(0.0f, len + mTextStart - 4));
if (len + mTextStart > right - 4)
ImGui::SetScrollX(std::max(0.0f, len + mTextStart + 4 - width));
ImGui::SetScrollX(std::max(0.0f, len + mTextStart + 4 - width + mCharAdvance.x * 2));
}
int TextEditor::GetPageSize() const {

View File

@@ -750,12 +750,41 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
else
{
// IMHEX PATCH BEGIN
if (!bd->BorderlessWindow) {
/*if (!bd->BorderlessWindow) {*/
// Show OS mouse cursor
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
#if defined(_WIN32)
switch (imgui_cursor) {
case ImGuiMouseCursor_Hand:
SetCursor(LoadCursor(nullptr, IDC_HAND));
break;
case ImGuiMouseCursor_ResizeEW:
SetCursor(LoadCursor(nullptr, IDC_SIZEWE));
break;
case ImGuiMouseCursor_ResizeNS:
SetCursor(LoadCursor(nullptr, IDC_SIZENS));
break;
case ImGuiMouseCursor_ResizeNWSE:
SetCursor(LoadCursor(nullptr, IDC_SIZENWSE));
break;
case ImGuiMouseCursor_ResizeNESW:
SetCursor(LoadCursor(nullptr, IDC_SIZENESW));
break;
case ImGuiMouseCursor_ResizeAll:
SetCursor(LoadCursor(nullptr, IDC_SIZEALL));
break;
case ImGuiMouseCursor_NotAllowed:
SetCursor(LoadCursor(nullptr, IDC_NO));
break;
case ImGuiMouseCursor_TextInput:
SetCursor(LoadCursor(nullptr, IDC_IBEAM));
break;
}
#else
glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
#endif
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
/*}*/
// IMHEX PATCH END
}
}
@@ -820,7 +849,12 @@ static void ImGui_ImplGlfw_UpdateMonitors()
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
int monitors_count = 0;
GLFWmonitor** glfw_monitors = glfwGetMonitors(&monitors_count);
platform_io.Monitors.resize(0);
// IMHEX PATCH BEGIN
if (monitors_count > 0)
platform_io.Monitors.resize(0);
// IMHEX PATCH END
for (int n = 0; n < monitors_count; n++)
{
ImGuiPlatformMonitor monitor;

View File

@@ -1565,8 +1565,8 @@ void ImGui::ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_exc
width_excess += items[n].Width - width_rounded;
items[n].Width = width_rounded;
}
while (width_excess > 0.0f)
for (int n = 0; n < count; n++)
while (width_excess >= 1.0f)
for (int n = 0; n < count && width_excess >= 1.0f; n++)
if (items[n].Width + 1.0f <= items[n].InitialWidth)
{
items[n].Width += 1.0f;
@@ -7638,7 +7638,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
width_excess = (section_0_w + section_2_w) - tab_bar->BarRect.GetWidth(); // Excess used to shrink leading/trailing section
// With ImGuiTabBarFlags_FittingPolicyScroll policy, we will only shrink leading/trailing if the central section is not visible anymore
if (width_excess > 0.0f && ((tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyResizeDown) || !central_section_is_visible))
if (width_excess >= 1.0f && ((tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyResizeDown) || !central_section_is_visible))
{
int shrink_data_count = (central_section_is_visible ? sections[1].TabCount : sections[0].TabCount + sections[2].TabCount);
int shrink_data_offset = (central_section_is_visible ? sections[0].TabCount + sections[2].TabCount : 0);

View File

@@ -1,9 +0,0 @@
cmake_minimum_required(VERSION 3.16)
project(intervaltree)
set(CMAKE_CXX_STANDARD20)
add_library(intervaltree INTERFACE)
target_include_directories(intervaltree INTERFACE include)
target_compile_options(intervaltree INTERFACE "-DUSE_INTERVAL_TREE_NAMESPACE")

View File

@@ -1,19 +0,0 @@
Copyright (c) 2011 Erik Garrison
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,37 +0,0 @@
# intervaltree
## Overview
An interval tree can be used to efficiently find a set of numeric intervals overlapping or containing another interval.
This library provides a basic implementation of an interval tree using C++ templates, allowing the insertion of arbitrary types into the tree.
## Usage
Add `#include "IntervalTree.h"` to the source files in which you will use the interval tree.
To make an IntervalTree to contain objects of class T, use:
```c++
vector<Interval<T> > intervals;
T a, b, c;
intervals.push_back(Interval<T>(2, 10, a));
intervals.push_back(Interval<T>(3, 4, b));
intervals.push_back(Interval<T>(20, 100, c));
IntervalTree<T> tree;
tree = IntervalTree<T>(intervals);
```
Now, it's possible to query the tree and obtain a set of intervals which are contained within the start and stop coordinates.
```c++
vector<Interval<T> > results;
tree.findContained(start, stop, results);
cout << "found " << results.size() << " overlapping intervals" << endl;
```
The function IntervalTree::findOverlapping provides a method to find all those intervals which are contained or partially overlap the interval (start, stop).
### Author: Erik Garrison <erik.garrison@gmail.com>
### License: MIT

View File

@@ -1,325 +0,0 @@
#ifndef __INTERVAL_TREE_H
#define __INTERVAL_TREE_H
#include <vector>
#include <algorithm>
#include <iostream>
#include <memory>
#include <cassert>
#include <limits>
#ifdef USE_INTERVAL_TREE_NAMESPACE
namespace interval_tree {
#endif
template <class Scalar, typename Value>
class Interval {
public:
Scalar start;
Scalar stop;
Value value;
Interval(const Scalar& s, const Scalar& e, const Value& v)
: start(std::min(s, e))
, stop(std::max(s, e))
, value(v)
{}
};
template <class Scalar, typename Value>
Value intervalStart(const Interval<Scalar,Value>& i) {
return i.start;
}
template <class Scalar, typename Value>
Value intervalStop(const Interval<Scalar, Value>& i) {
return i.stop;
}
template <class Scalar, typename Value>
std::ostream& operator<<(std::ostream& out, const Interval<Scalar, Value>& i) {
out << "Interval(" << i.start << ", " << i.stop << "): " << i.value;
return out;
}
template <class Scalar, class Value>
class IntervalTree {
public:
typedef Interval<Scalar, Value> interval;
typedef std::vector<interval> interval_vector;
struct IntervalStartCmp {
bool operator()(const interval& a, const interval& b) {
return a.start < b.start;
}
};
struct IntervalStopCmp {
bool operator()(const interval& a, const interval& b) {
return a.stop < b.stop;
}
};
IntervalTree()
: left(nullptr)
, right(nullptr)
, center(0)
{}
~IntervalTree() = default;
std::unique_ptr<IntervalTree> clone() const {
return std::unique_ptr<IntervalTree>(new IntervalTree(*this));
}
IntervalTree(const IntervalTree& other)
: intervals(other.intervals),
left(other.left ? other.left->clone() : nullptr),
right(other.right ? other.right->clone() : nullptr),
center(other.center)
{}
IntervalTree& operator=(IntervalTree&&) = default;
IntervalTree(IntervalTree&&) = default;
IntervalTree& operator=(const IntervalTree& other) {
center = other.center;
intervals = other.intervals;
left = other.left ? other.left->clone() : nullptr;
right = other.right ? other.right->clone() : nullptr;
return *this;
}
IntervalTree(
interval_vector&& ivals,
std::size_t depth = 16,
std::size_t minbucket = 64,
std::size_t maxbucket = 512,
Scalar leftextent = 0,
Scalar rightextent = 0)
: left(nullptr)
, right(nullptr)
{
--depth;
const auto minmaxStop = std::minmax_element(ivals.begin(), ivals.end(),
IntervalStopCmp());
const auto minmaxStart = std::minmax_element(ivals.begin(), ivals.end(),
IntervalStartCmp());
if (!ivals.empty()) {
center = (minmaxStart.first->start + minmaxStop.second->stop) / 2;
}
if (leftextent == 0 && rightextent == 0) {
// sort intervals by start
std::sort(ivals.begin(), ivals.end(), IntervalStartCmp());
} else {
assert(std::is_sorted(ivals.begin(), ivals.end(), IntervalStartCmp()));
}
if (depth == 0 || (ivals.size() < minbucket && ivals.size() < maxbucket)) {
std::sort(ivals.begin(), ivals.end(), IntervalStartCmp());
intervals = std::move(ivals);
assert(is_valid().first);
return;
} else {
Scalar leftp = 0;
Scalar rightp = 0;
if (leftextent || rightextent) {
leftp = leftextent;
rightp = rightextent;
} else {
leftp = ivals.front().start;
rightp = std::max_element(ivals.begin(), ivals.end(),
IntervalStopCmp())->stop;
}
interval_vector lefts;
interval_vector rights;
for (typename interval_vector::const_iterator i = ivals.begin();
i != ivals.end(); ++i) {
const interval& interval = *i;
if (interval.stop < center) {
lefts.push_back(interval);
} else if (interval.start > center) {
rights.push_back(interval);
} else {
assert(interval.start <= center);
assert(center <= interval.stop);
intervals.push_back(interval);
}
}
if (!lefts.empty()) {
left.reset(new IntervalTree(std::move(lefts),
depth, minbucket, maxbucket,
leftp, center));
}
if (!rights.empty()) {
right.reset(new IntervalTree(std::move(rights),
depth, minbucket, maxbucket,
center, rightp));
}
}
assert(is_valid().first);
}
// Call f on all intervals near the range [start, stop]:
template <class UnaryFunction>
void visit_near(const Scalar& start, const Scalar& stop, UnaryFunction f) const {
if (!intervals.empty() && ! (stop < intervals.front().start)) {
for (auto & i : intervals) {
f(i);
}
}
if (left && start <= center) {
left->visit_near(start, stop, f);
}
if (right && stop >= center) {
right->visit_near(start, stop, f);
}
}
// Call f on all intervals crossing pos
template <class UnaryFunction>
void visit_overlapping(const Scalar& pos, UnaryFunction f) const {
visit_overlapping(pos, pos, f);
}
// Call f on all intervals overlapping [start, stop]
template <class UnaryFunction>
void visit_overlapping(const Scalar& start, const Scalar& stop, UnaryFunction f) const {
auto filterF = [&](const interval& interval) {
if (interval.stop >= start && interval.start <= stop) {
// Only apply f if overlapping
f(interval);
}
};
visit_near(start, stop, filterF);
}
// Call f on all intervals contained within [start, stop]
template <class UnaryFunction>
void visit_contained(const Scalar& start, const Scalar& stop, UnaryFunction f) const {
auto filterF = [&](const interval& interval) {
if (start <= interval.start && interval.stop <= stop) {
f(interval);
}
};
visit_near(start, stop, filterF);
}
interval_vector findOverlapping(const Scalar& start, const Scalar& stop) const {
interval_vector result;
visit_overlapping(start, stop,
[&](const interval& interval) {
result.emplace_back(interval);
});
return result;
}
interval_vector findContained(const Scalar& start, const Scalar& stop) const {
interval_vector result;
visit_contained(start, stop,
[&](const interval& interval) {
result.push_back(interval);
});
return result;
}
bool empty() const {
if (left && !left->empty()) {
return false;
}
if (!intervals.empty()) {
return false;
}
if (right && !right->empty()) {
return false;
}
return true;
}
template <class UnaryFunction>
void visit_all(UnaryFunction f) const {
if (left) {
left->visit_all(f);
}
std::for_each(intervals.begin(), intervals.end(), f);
if (right) {
right->visit_all(f);
}
}
std::pair<Scalar, Scalar> extentBruitForce() const {
struct Extent {
std::pair<Scalar, Scalar> x = {std::numeric_limits<Scalar>::max(),
std::numeric_limits<Scalar>::min() };
void operator()(const interval & interval) {
x.first = std::min(x.first, interval.start);
x.second = std::max(x.second, interval.stop);
}
};
Extent extent;
visit_all([&](const interval & interval) { extent(interval); });
return extent.x;
}
// Check all constraints.
// If first is false, second is invalid.
std::pair<bool, std::pair<Scalar, Scalar>> is_valid() const {
const auto minmaxStop = std::minmax_element(intervals.begin(), intervals.end(),
IntervalStopCmp());
const auto minmaxStart = std::minmax_element(intervals.begin(), intervals.end(),
IntervalStartCmp());
std::pair<bool, std::pair<Scalar, Scalar>> result = {true, { std::numeric_limits<Scalar>::max(),
std::numeric_limits<Scalar>::min() }};
if (!intervals.empty()) {
result.second.first = std::min(result.second.first, minmaxStart.first->start);
result.second.second = std::min(result.second.second, minmaxStop.second->stop);
}
if (left) {
auto valid = left->is_valid();
result.first &= valid.first;
result.second.first = std::min(result.second.first, valid.second.first);
result.second.second = std::min(result.second.second, valid.second.second);
if (!result.first) { return result; }
if (valid.second.second >= center) {
result.first = false;
return result;
}
}
if (right) {
auto valid = right->is_valid();
result.first &= valid.first;
result.second.first = std::min(result.second.first, valid.second.first);
result.second.second = std::min(result.second.second, valid.second.second);
if (!result.first) { return result; }
if (valid.second.first <= center) {
result.first = false;
return result;
}
}
if (!std::is_sorted(intervals.begin(), intervals.end(), IntervalStartCmp())) {
result.first = false;
}
return result;
}
void clear() {
left.reset();
right.reset();
intervals.clear();
center = 0;
}
private:
interval_vector intervals;
std::unique_ptr<IntervalTree> left;
std::unique_ptr<IntervalTree> right;
Scalar center;
};
#ifdef USE_INTERVAL_TREE_NAMESPACE
}
#endif
#endif

1
lib/external/libwolv vendored Submodule

Submodule lib/external/libwolv added at 433d230331

12
lib/external/miniaudio/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.16)
project(miniaudio)
add_library(miniaudio STATIC
source/miniaudio.c
)
target_include_directories(miniaudio PUBLIC include)
if (APPLE)
set_source_files_properties(source/miniaudio.c PROPERTIES LANGUAGE OBJC)
endif ()

47
lib/external/miniaudio/LICENSE vendored Normal file
View File

@@ -0,0 +1,47 @@
This software is available as a choice of the following licenses. Choose
whichever you prefer.
===============================================================================
ALTERNATIVE 1 - Public Domain (www.unlicense.org)
===============================================================================
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
===============================================================================
ALTERNATIVE 2 - MIT No Attribution
===============================================================================
Copyright 2020 David Reid
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

7509
lib/external/miniaudio/include/miniaudio.h vendored Normal file

File diff suppressed because it is too large Load Diff

80169
lib/external/miniaudio/source/miniaudio.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -34,6 +34,8 @@ set(LIBYARA_INCLUDES
${LIBYARA_SOURCE_PATH}/include/yara/types.h
${LIBYARA_SOURCE_PATH}/include/yara/utils.h
${LIBYARA_SOURCE_PATH}/crypto.h
${LIBYARA_SOURCE_PATH}/tlshc/tlsh_impl.h
${LIBYARA_SOURCE_PATH}/tlshc/tlsh_util.h
)
set(LIBYARA_SOURCE
@@ -66,6 +68,7 @@ set(LIBYARA_SOURCE
${LIBYARA_SOURCE_PATH}/scan.c
${LIBYARA_SOURCE_PATH}/scanner.c
${LIBYARA_SOURCE_PATH}/sizedstr.c
${LIBYARA_SOURCE_PATH}/simple_str.c
${LIBYARA_SOURCE_PATH}/stack.c
${LIBYARA_SOURCE_PATH}/stopwatch.c
${LIBYARA_SOURCE_PATH}/strutils.c
@@ -78,6 +81,9 @@ set(LIBYARA_SOURCE
${LIBYARA_SOURCE_PATH}/hex_grammar.c
${LIBYARA_SOURCE_PATH}/re_grammar.c
${LIBYARA_SOURCE_PATH}/proc/none.c
${LIBYARA_SOURCE_PATH}/tlshc/tlsh.c
${LIBYARA_SOURCE_PATH}/tlshc/tlsh_impl.c
${LIBYARA_SOURCE_PATH}/tlshc/tlsh_util.c
)
set(LIBYARA_MODULES
@@ -91,27 +97,25 @@ set(LIBYARA_MODULES
${LIBYARA_SOURCE_PATH}/modules/math/math.c
${LIBYARA_SOURCE_PATH}/modules/pe/pe.c
${LIBYARA_SOURCE_PATH}/modules/pe/pe_utils.c
${LIBYARA_SOURCE_PATH}/modules/string/string.c
${LIBYARA_SOURCE_PATH}/modules/tests/tests.c
${LIBYARA_SOURCE_PATH}/modules/time/time.c
)
# Add mbedtls crypto wrappers
add_compile_definitions("HAVE_MBEDTLS")
add_compile_definitions("USE_NO_PROC")
add_compile_definitions("HASH_MODULE")
add_compile_definitions("DOTNET_MODULE")
add_compile_definitions("MAGIC_MODULE")
add_compile_definitions("MACHO_MODULE")
add_compile_definitions("DEX_MODULE")
find_package(mbedTLS 2.26.0 REQUIRED)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-shift-count-overflow")
add_library(libyara STATIC ${LIBYARA_SOURCE} ${LIBYARA_INCLUDES} ${LIBYARA_MODULES})
set_property(TARGET libyara PROPERTY POSITION_INDEPENDENT_CODE ON)
# Add mbedtls crypto wrappers
target_compile_definitions(libyara PRIVATE
HAVE_MBEDTLS
USE_NO_PROC BUCKETS_256 CHECKSUM_3B
HASH_MODULE DOTNET_MODULE MAGIC_MODULE MACHO_MODULE DEX_MODULE
)
target_compile_options(libyara PRIVATE -Wno-shift-count-overflow -Wno-stringop-overflow)
target_include_directories(
libyara
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/yara> $<BUILD_INTERFACE:${LIBYARA_SOURCE_PATH}/include> $<INSTALL_INTERFACE:include>
@@ -127,6 +131,6 @@ else ()
endif ()
include(GNUInstallDirs)
configure_file(${LIBYARA_SOURCE_PATH}/yara.pc.in
${LIBYARA_SOURCE_PATH}/yara.pc @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yara/yara.pc.in
${CMAKE_CURRENT_SOURCE_DIR}/yara/yara.pc @ONLY)
set(CMAKE_STATIC_LIBRARY_PREFIX "")

View File

@@ -1,808 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]]
name = "aquamarine"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96e14cb2a51c8b45d26a4219981985c7350fc05eacb7b5b2939bceb2ffefdf3e"
dependencies = [
"itertools 0.9.0",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocxx"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13e6384cb95b48be8c5b83764ef800858322436f57aa17974915d23dadb6a7d5"
dependencies = [
"aquamarine",
"autocxx-engine",
"autocxx-macro",
"cxx",
"moveit",
]
[[package]]
name = "autocxx-bindgen"
version = "0.59.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e603c1eb79e21068072ef990e5463f613e0cedddd6712ff11afeae2a90b2510"
dependencies = [
"bitflags",
"cexpr",
"clang-sys",
"clap",
"env_logger",
"itertools 0.10.3",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"which",
]
[[package]]
name = "autocxx-build"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f5b45a4fe71d3ac68d8b4fd11abe54c791046ec4def7effe27961269b6ab3"
dependencies = [
"autocxx-engine",
"env_logger",
"syn",
]
[[package]]
name = "autocxx-engine"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02323905bec49fde96ff028fcff1c478d0eba14fa34ea5eb5e4d17439748e42a"
dependencies = [
"aquamarine",
"autocxx-bindgen",
"autocxx-parser",
"cc",
"cxx",
"cxx-gen",
"indoc",
"itertools 0.10.3",
"log",
"once_cell",
"proc-macro2",
"quote",
"serde_json",
"strum_macros",
"syn",
"tempfile",
"unzip-n",
"version_check",
]
[[package]]
name = "autocxx-macro"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8106ca477cbe6edf188311f2e05606b81bf463c41748ce7120c31d1b11875515"
dependencies = [
"autocxx-parser",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "autocxx-parser"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad0ad08260adcecc119b08f460b0633b6e306ea2f6fda4f27e4dd28e20b9a2f4"
dependencies = [
"log",
"proc-macro2",
"quote",
"serde",
"serde_derive",
"syn",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0"
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chlorine"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd650552110e39b7c5058986cf177decd3365841836578ac50a286094eac0be6"
[[package]]
name = "clang-sys"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cc00842eed744b858222c4c9faf7243aafc6d33f92f96935263ef4d8a41ce21"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "clap"
version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "codespan-reporting"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
dependencies = [
"termcolor",
"unicode-width",
]
[[package]]
name = "cxx"
version = "1.0.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "638fb099591b763a988ca69e5f0ee4b82bedb8bc762b3c6cfbfdd3a6dc6b54b4"
dependencies = [
"cc",
"cxxbridge-flags",
"cxxbridge-macro",
"link-cplusplus",
]
[[package]]
name = "cxx-gen"
version = "0.7.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "836e95ae34fc21fb39c206444879afda2c6e704424c9c621662764f1b459e83a"
dependencies = [
"codespan-reporting",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "cxxbridge-flags"
version = "1.0.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d4bde25840be4cf0eb1d7e3a74634105189d5609b855bcc8d601ffb037f5f4"
[[package]]
name = "cxxbridge-macro"
version = "1.0.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3869bf8972075de8f0446b433d40026f2dfdbd8a9edbc24e9d645ca2ebf2f93a"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "env_logger"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "fastrand"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
dependencies = [
"instant",
]
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "imgui"
version = "0.8.0"
dependencies = [
"bitflags",
"imgui-sys",
"parking_lot",
]
[[package]]
name = "imgui-sys"
version = "0.8.0"
dependencies = [
"cc",
"chlorine",
]
[[package]]
name = "imhex-macros"
version = "0.1.0"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "indoc"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7906a9fababaeacb774f72410e497a1d18de916322e33797bb2cd29baa23c9e"
dependencies = [
"unindent",
]
[[package]]
name = "instant"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd"
dependencies = [
"cfg-if",
]
[[package]]
name = "itertools"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
[[package]]
name = "libimhex-rs"
version = "0.1.0"
dependencies = [
"autocxx",
"autocxx-build",
"cxx",
"imgui",
"imhex-macros",
]
[[package]]
name = "libloading"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
dependencies = [
"cfg-if",
"winapi",
]
[[package]]
name = "link-cplusplus"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1becd27d473556dc610b8afa1636ef90747b574a84553bc11e82371d5ef2d1"
dependencies = [
"cc",
]
[[package]]
name = "lock_api"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "moveit"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd833d6adefa6bcfc56948d061c1d697dfa3ab63711963c7ef4aa23eda945676"
dependencies = [
"cxx",
]
[[package]]
name = "nom"
version = "7.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109"
dependencies = [
"memchr",
"minimal-lexical",
"version_check",
]
[[package]]
name = "once_cell"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
[[package]]
name = "parking_lot"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
dependencies = [
"cfg-if",
"instant",
"libc",
"redox_syscall",
"smallvec",
"winapi",
]
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustversion"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
[[package]]
name = "ryu"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
version = "1.0.136"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
[[package]]
name = "serde_derive"
version = "1.0.136"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "shlex"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
[[package]]
name = "smallvec"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "strum_macros"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn",
]
[[package]]
name = "syn"
version = "1.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5239bc68e0fef57495900cfea4e8dc75596d9a319d7e16b1e0a440d24e6fe0a0"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "tempfile"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
dependencies = [
"cfg-if",
"fastrand",
"libc",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "unicode-segmentation"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "unindent"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "514672a55d7380da379785a4d70ca8386c8883ff7eaae877be4d2081cebe73d8"
[[package]]
name = "unzip-n"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2e7e85a0596447f0f2ac090e16bc4c516c6fe91771fb0c0ccf7fa3dae896b9c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "which"
version = "4.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a5a7e487e921cf220206864a94a89b6c6905bfc19f1057fa26a4cb360e5c1d2"
dependencies = [
"either",
"lazy_static",
"libc",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@@ -1,18 +0,0 @@
[package]
name = "libimhex-rs"
version = "0.1.0"
edition = "2018"
build = "build.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
imhex-macros = { path = "proc_macros" }
imgui = { path = "imgui-rs" }
cxx = "1.0.55"
autocxx = "0.16"
[build-dependencies]
autocxx-build = "0.16"
#cxx-build = "1.0.55"

View File

@@ -1,26 +0,0 @@
fn main() {
println!("cargo:rustc-link-lib=dylib=imhex");
println!(
"cargo:rustc-link-search=all={}",
env!("LIBIMHEX_OUTPUT_DIRECTORY")
);
println!("cargo:rerun-if-changed=src/lib.rs");
println!("cargo:rerun-if-changed=src/imhex_api.rs");
let include = format!("-I{}/include", env!("LIBIMHEX_SOURCE_DIRECTORY"));
let path = std::path::PathBuf::from("src");
let mut build = autocxx_build::Builder::new("src/lib.rs", &[&path])
.extra_clang_args(&[&include, "-x", "c++", "-std=gnu++20"])
.auto_allowlist(true)
.expect_build();
build
.include(format!("{}/include", env!("LIBIMHEX_SOURCE_DIRECTORY")))
.flag_if_supported("-std=gnu++20")
.flag_if_supported("-std=gnu++2a")
.flag_if_supported("-fconcepts")
.compiler(env!("CXX_COMPILER"))
.compile("libimhex-bridge");
}

View File

@@ -1,159 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chlorine"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd650552110e39b7c5058986cf177decd3365841836578ac50a286094eac0be6"
[[package]]
name = "imgui"
version = "0.8.0"
dependencies = [
"bitflags",
"imgui-sys",
"memoffset",
"parking_lot",
]
[[package]]
name = "imgui-sys"
version = "0.8.0"
dependencies = [
"cc",
"chlorine",
"pkg-config",
]
[[package]]
name = "instant"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd"
dependencies = [
"cfg-if",
]
[[package]]
name = "libc"
version = "0.2.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
[[package]]
name = "lock_api"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
dependencies = [
"scopeguard",
]
[[package]]
name = "memoffset"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
dependencies = [
"autocfg",
]
[[package]]
name = "parking_lot"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
dependencies = [
"cfg-if",
"instant",
"libc",
"redox_syscall",
"smallvec",
"winapi",
]
[[package]]
name = "pkg-config"
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb"
[[package]]
name = "redox_syscall"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [
"bitflags",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "smallvec"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@@ -1,31 +0,0 @@
[package]
name = "imgui"
version = "0.8.0"
edition = "2018"
authors = ["The imgui-rs Developers"]
description = "High-level Rust bindings to dear imgui"
homepage = "https://github.com/imgui-rs/imgui-rs"
repository = "https://github.com/imgui-rs/imgui-rs"
license = "MIT/Apache-2.0"
categories = ["gui", "api-bindings"]
readme = "../README.markdown"
exclude = ["/resources"]
[dependencies]
bitflags = "1"
imgui-sys = { path = "../imgui-sys" }
parking_lot = "0.11"
[features]
default = ["min-const-generics"]
wasm = ["imgui-sys/wasm"]
freetype = ["imgui-sys/freetype"]
min-const-generics = []
# this api is in beta in the upstream imgui crate. See issue #524 for more info.
# it should be stable and fine to use though.
tables-api = []
[dev-dependencies]
memoffset = "0.6"

View File

@@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -1,19 +0,0 @@
Copyright (c) 2015-2020 The imgui-rs Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1 +0,0 @@
../README.markdown

View File

@@ -1,142 +0,0 @@
use std::ffi::{CStr, CString};
use std::fmt;
use std::os::raw::{c_char, c_void};
use std::panic::catch_unwind;
use std::process;
use std::ptr;
// use crate::string::{ImStr, ImString};
use crate::Ui;
/// Trait for clipboard backends
pub trait ClipboardBackend: 'static {
/// Returns the current clipboard contents as an owned imgui-rs string, or None if the
/// clipboard is empty or inaccessible
fn get(&mut self) -> Option<String>;
/// Sets the clipboard contents to the given imgui-rs string slice.
fn set(&mut self, value: &str);
}
pub(crate) struct ClipboardContext {
backend: Box<dyn ClipboardBackend>,
// this is needed to keep ownership of the value when the raw C callback is called
last_value: CString,
}
impl ClipboardContext {
/// Creates a new [ClipboardContext]. This function previously took a `Box`, but now
/// is generic over the T it takes and boxes itself (which should be less strange).
pub fn new<T: ClipboardBackend>(backend: T) -> ClipboardContext {
ClipboardContext {
backend: Box::new(backend) as Box<dyn ClipboardBackend>,
last_value: CString::default(),
}
}
pub fn dummy() -> ClipboardContext {
Self {
backend: Box::new(DummyClipboardContext),
last_value: CString::default(),
}
}
}
pub struct DummyClipboardContext;
impl ClipboardBackend for DummyClipboardContext {
fn get(&mut self) -> Option<String> {
None
}
fn set(&mut self, _: &str) {
// empty
}
}
impl fmt::Debug for ClipboardContext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ClipboardContext")
// beautiful code, no?
.field("backend", &(&(*self.backend) as *const _))
.field("last_value", &self.last_value)
.finish()
}
}
pub(crate) unsafe extern "C" fn get_clipboard_text(user_data: *mut c_void) -> *const c_char {
let result = catch_unwind(|| {
let ctx = &mut *(user_data as *mut ClipboardContext);
match ctx.backend.get() {
Some(text) => {
ctx.last_value = CString::new(text).unwrap();
ctx.last_value.as_ptr()
}
None => ptr::null(),
}
});
result.unwrap_or_else(|_| {
eprintln!("Clipboard getter panicked");
process::abort();
})
}
pub(crate) unsafe extern "C" fn set_clipboard_text(user_data: *mut c_void, text: *const c_char) {
let result = catch_unwind(|| {
let ctx = &mut *(user_data as *mut ClipboardContext);
let text = CStr::from_ptr(text).to_owned();
ctx.backend.set(text.to_str().unwrap());
});
result.unwrap_or_else(|_| {
eprintln!("Clipboard setter panicked");
process::abort();
});
}
/// # Clipboard
#[allow(clippy::fn_address_comparisons)] // This is allowed because although function addresses wont be unique, we just care if its OURS
impl<'ui> Ui<'ui> {
/// Returns the current clipboard contents as text, or None if the clipboard is empty or cannot
/// be accessed
pub fn clipboard_text(&self) -> Option<String> {
let io = self.io();
io.get_clipboard_text_fn.and_then(|get_clipboard_text_fn| {
// Bypass FFI if we end up calling our own function anyway
if get_clipboard_text_fn == get_clipboard_text {
let ctx = unsafe { &mut *(io.clipboard_user_data as *mut ClipboardContext) };
ctx.backend.get()
} else {
unsafe {
let text_ptr = get_clipboard_text_fn(io.clipboard_user_data);
if text_ptr.is_null() || *text_ptr == b'\0' as c_char {
None
} else {
Some(
CStr::from_ptr(text_ptr)
.to_owned()
.to_str()
.ok()?
.to_owned(),
)
}
}
}
})
}
/// Sets the clipboard contents.
///
/// Does nothing if the clipboard cannot be accessed.
pub fn set_clipboard_text(&self, text: impl AsRef<str>) {
let io = self.io();
if let Some(set_clipboard_text_fn) = io.set_clipboard_text_fn {
// Bypass FFI if we end up calling our own function anyway
if set_clipboard_text_fn == set_clipboard_text {
let ctx = unsafe { &mut *(io.clipboard_user_data as *mut ClipboardContext) };
ctx.backend.set(text.as_ref());
} else {
unsafe {
set_clipboard_text_fn(io.clipboard_user_data, self.scratch_txt(text));
}
}
}
}
}

View File

@@ -1,370 +0,0 @@
/// Wraps u32 that represents a packed RGBA color. Mostly used by types in the
/// low level custom drawing API, such as [`DrawListMut`](crate::DrawListMut).
///
/// The bits of a color are in "`0xAABBGGRR`" format (e.g. RGBA as little endian
/// bytes). For clarity: we don't support an equivalent to the
/// `IMGUI_USE_BGRA_PACKED_COLOR` define.
///
/// This used to be named `ImColor32`, but was renamed to avoid confusion with
/// the type with that name in the C++ API (which uses 32 bits per channel).
///
/// While it doesn't provide methods to access the fields, they can be accessed
/// via the `Deref`/`DerefMut` impls it provides targeting
/// [`imgui::color::ImColor32Fields`](crate::color::ImColor32Fields), which has
/// no other meaningful uses.
///
/// # Example
/// ```
/// let mut c = imgui::ImColor32::from_rgba(0x80, 0xc0, 0x40, 0xff);
/// assert_eq!(c.to_bits(), 0xff_40_c0_80); // Note: 0xAA_BB_GG_RR
/// // Field access
/// assert_eq!(c.r, 0x80);
/// assert_eq!(c.g, 0xc0);
/// assert_eq!(c.b, 0x40);
/// assert_eq!(c.a, 0xff);
/// c.b = 0xbb;
/// assert_eq!(c.to_bits(), 0xff_bb_c0_80);
/// ```
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
pub struct ImColor32(u32); // TBH maybe the wrapped field should be `pub`.
impl ImColor32 {
/// Convenience constant for solid black.
pub const BLACK: Self = Self(0xff_00_00_00);
/// Convenience constant for solid white.
pub const WHITE: Self = Self(0xff_ff_ff_ff);
/// Convenience constant for full transparency.
pub const TRANSPARENT: Self = Self(0);
/// Construct a color from 4 single-byte `u8` channel values, which should
/// be between 0 and 255.
#[inline]
pub const fn from_rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
Self(
((a as u32) << Self::A_SHIFT)
| ((r as u32) << Self::R_SHIFT)
| ((g as u32) << Self::G_SHIFT)
| ((b as u32) << Self::B_SHIFT),
)
}
/// Construct a fully opaque color from 3 single-byte `u8` channel values.
/// Same as [`Self::from_rgba`] with a == 255
#[inline]
pub const fn from_rgb(r: u8, g: u8, b: u8) -> Self {
Self::from_rgba(r, g, b, 0xff)
}
/// Construct a fully opaque color from 4 `f32` channel values in the range
/// `0.0 ..= 1.0` (values outside this range are clamped to it, with NaN
/// mapped to 0.0).
///
/// Note: No alpha premultiplication is done, so your input should be have
/// premultiplied alpha if needed.
#[inline]
// not const fn because no float math in const eval yet 😩
pub fn from_rgba_f32s(r: f32, g: f32, b: f32, a: f32) -> Self {
Self::from_rgba(
f32_to_u8_sat(r),
f32_to_u8_sat(g),
f32_to_u8_sat(b),
f32_to_u8_sat(a),
)
}
/// Return the channels as an array of f32 in `[r, g, b, a]` order.
#[inline]
pub fn to_rgba_f32s(self) -> [f32; 4] {
let &ImColor32Fields { r, g, b, a } = &*self;
[
u8_to_f32_sat(r),
u8_to_f32_sat(g),
u8_to_f32_sat(b),
u8_to_f32_sat(a),
]
}
/// Return the channels as an array of u8 in `[r, g, b, a]` order.
#[inline]
pub fn to_rgba(self) -> [u8; 4] {
let &ImColor32Fields { r, g, b, a } = &*self;
[r, g, b, a]
}
/// Equivalent to [`Self::from_rgba_f32s`], but with an alpha of 1.0 (e.g.
/// opaque).
#[inline]
pub fn from_rgb_f32s(r: f32, g: f32, b: f32) -> Self {
Self::from_rgba(f32_to_u8_sat(r), f32_to_u8_sat(g), f32_to_u8_sat(b), 0xff)
}
/// Construct a color from the `u32` that makes up the bits in `0xAABBGGRR`
/// format.
///
/// Specifically, this takes the RGBA values as a little-endian u32 with 8
/// bits per channel.
///
/// Note that [`ImColor32::from_rgba`] may be a bit easier to use.
#[inline]
pub const fn from_bits(u: u32) -> Self {
Self(u)
}
/// Return the bits of the color as a u32. These are in "`0xAABBGGRR`" format, that
/// is, little-endian RGBA with 8 bits per channel.
#[inline]
pub const fn to_bits(self) -> u32 {
self.0
}
// These are public in C++ ImGui, should they be public here?
/// The number of bits to shift the byte of the red channel. Always 0.
const R_SHIFT: u32 = 0;
/// The number of bits to shift the byte of the green channel. Always 8.
const G_SHIFT: u32 = 8;
/// The number of bits to shift the byte of the blue channel. Always 16.
const B_SHIFT: u32 = 16;
/// The number of bits to shift the byte of the alpha channel. Always 24.
const A_SHIFT: u32 = 24;
}
impl Default for ImColor32 {
#[inline]
fn default() -> Self {
Self::TRANSPARENT
}
}
impl std::fmt::Debug for ImColor32 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ImColor32")
.field("r", &self.r)
.field("g", &self.g)
.field("b", &self.b)
.field("a", &self.a)
.finish()
}
}
/// A struct that exists to allow field access to [`ImColor32`]. It essentially
/// exists to be a `Deref`/`DerefMut` target and provide field access.
///
/// Note that while this is repr(C), be aware that on big-endian machines
/// (`cfg(target_endian = "big")`) the order of the fields is reversed, as this
/// is a view into a packed u32.
///
/// Generally should not be used, except as the target of the `Deref` impl of
/// [`ImColor32`].
#[derive(Copy, Clone, Debug)]
#[repr(C, align(4))]
// Should this be #[non_exhaustive] to discourage direct use?
#[rustfmt::skip]
pub struct ImColor32Fields {
#[cfg(target_endian = "little")] pub r: u8,
#[cfg(target_endian = "little")] pub g: u8,
#[cfg(target_endian = "little")] pub b: u8,
#[cfg(target_endian = "little")] pub a: u8,
// TODO(someday): i guess we should have BE tests, but for now I verified
// this locally.
#[cfg(target_endian = "big")] pub a: u8,
#[cfg(target_endian = "big")] pub b: u8,
#[cfg(target_endian = "big")] pub g: u8,
#[cfg(target_endian = "big")] pub r: u8,
}
// We assume that big and little are the only endiannesses, and that exactly one
// is set. That is, PDP endian is not in use, and the we aren't using a
// completely broken custom target json or something.
#[cfg(any(
all(target_endian = "little", target_endian = "big"),
all(not(target_endian = "little"), not(target_endian = "big")),
))]
compile_error!("`cfg(target_endian = \"little\")` must be `cfg(not(target_endian = \"big\")`");
// static assert sizes match
const _: [(); core::mem::size_of::<ImColor32>()] = [(); core::mem::size_of::<ImColor32Fields>()];
const _: [(); core::mem::align_of::<ImColor32>()] = [(); core::mem::align_of::<ImColor32Fields>()];
impl core::ops::Deref for ImColor32 {
type Target = ImColor32Fields;
#[inline]
fn deref(&self) -> &ImColor32Fields {
// Safety: we statically assert the size and align match, and neither
// type has any special invariants.
unsafe { &*(self as *const Self as *const ImColor32Fields) }
}
}
impl core::ops::DerefMut for ImColor32 {
#[inline]
fn deref_mut(&mut self) -> &mut ImColor32Fields {
// Safety: we statically assert the size and align match, and neither
// type has any special invariants.
unsafe { &mut *(self as *mut Self as *mut ImColor32Fields) }
}
}
impl From<ImColor32> for u32 {
#[inline]
fn from(color: ImColor32) -> Self {
color.0
}
}
impl From<u32> for ImColor32 {
#[inline]
fn from(color: u32) -> Self {
ImColor32(color)
}
}
impl From<[f32; 4]> for ImColor32 {
#[inline]
fn from(v: [f32; 4]) -> Self {
Self::from_rgba_f32s(v[0], v[1], v[2], v[3])
}
}
impl From<(f32, f32, f32, f32)> for ImColor32 {
#[inline]
fn from(v: (f32, f32, f32, f32)) -> Self {
Self::from_rgba_f32s(v.0, v.1, v.2, v.3)
}
}
impl From<[f32; 3]> for ImColor32 {
#[inline]
fn from(v: [f32; 3]) -> Self {
Self::from_rgb_f32s(v[0], v[1], v[2])
}
}
impl From<(f32, f32, f32)> for ImColor32 {
fn from(v: (f32, f32, f32)) -> Self {
Self::from_rgb_f32s(v.0, v.1, v.2)
}
}
impl From<ImColor32> for [f32; 4] {
#[inline]
fn from(v: ImColor32) -> Self {
v.to_rgba_f32s()
}
}
impl From<ImColor32> for (f32, f32, f32, f32) {
#[inline]
fn from(color: ImColor32) -> Self {
let [r, g, b, a]: [f32; 4] = color.into();
(r, g, b, a)
}
}
// These utilities might be worth making `pub` as free functions in
// `crate::color` so user code can ensure their numeric handling is
// consistent...
/// Clamp `v` to between 0.0 and 1.0, always returning a value between those.
///
/// Never returns NaN, or -0.0 — instead returns +0.0 for these (We differ from
/// C++ Dear ImGUI here which probably is just ignoring values like these).
#[inline]
pub(crate) fn saturate(v: f32) -> f32 {
// Note: written strangely so that special values (NaN/-0.0) are handled
// automatically with no extra checks.
if v > 0.0 {
if v <= 1.0 {
v
} else {
1.0
}
} else {
0.0
}
}
/// Quantize a value in `0.0..=1.0` to `0..=u8::MAX`. Input outside 0.0..=1.0 is
/// clamped. Uses a bias of 0.5, because we assume centered quantization is used
/// (and because C++ imgui does it too). See:
/// - https://github.com/ocornut/imgui/blob/e28b51786eae60f32c18214658c15952639085a2/imgui_internal.h#L218
/// - https://cbloomrants.blogspot.com/2020/09/topics-in-quantization-for-games.html
/// (see `quantize_centered`)
#[inline]
pub(crate) fn f32_to_u8_sat(f: f32) -> u8 {
let f = saturate(f) * 255.0 + 0.5;
// Safety: `saturate`'s result is between 0.0 and 1.0 (never NaN even for
// NaN input), and so for all inputs, `saturate(f) * 255.0 + 0.5` is inside
// `0.5 ..= 255.5`.
//
// This is verified for all f32 in `test_f32_to_u8_sat_exhaustive`.
//
// Also note that LLVM doesn't bother trying to figure this out so the
// unchecked does actually help. (That said, this likely doesn't matter
// for imgui-rs, but I had this code in another project and it felt
// silly to needlessly pessimize it).
unsafe { f.to_int_unchecked() }
}
/// Opposite of `f32_to_u8_sat`. Since we assume centered quantization, this is
/// equivalent to dividing by 255 (or, multiplying by 1.0/255.0)
#[inline]
pub(crate) fn u8_to_f32_sat(u: u8) -> f32 {
(u as f32) * (1.0 / 255.0)
}
#[test]
fn check_sat() {
assert_eq!(saturate(1.0), 1.0);
assert_eq!(saturate(0.5), 0.5);
assert_eq!(saturate(0.0), 0.0);
assert_eq!(saturate(-1.0), 0.0);
// next float from 1.0
assert_eq!(saturate(1.0 + f32::EPSILON), 1.0);
// prev float from 0.0 (Well, from -0.0)
assert_eq!(saturate(-f32::MIN_POSITIVE), 0.0);
// some NaNs.
assert_eq!(saturate(f32::NAN), 0.0);
assert_eq!(saturate(-f32::NAN), 0.0);
// neg zero comes through as +0
assert_eq!(saturate(-0.0).to_bits(), 0.0f32.to_bits());
}
// Check that the unsafe in `f32_to_u8_sat` is fine for all f32 (and that the
// comments I wrote about `saturate` are actually true). This is way too slow in
// debug mode, but finishes in ~15s on my machine for release (just this test).
// This is tested in CI, but will only run if invoked manually with something
// like: `cargo test -p imgui --release -- --ignored`.
#[test]
#[ignore]
fn test_f32_to_u8_sat_exhaustive() {
for f in (0..=u32::MAX).map(f32::from_bits) {
let v = saturate(f);
assert!(
(0.0..=1.0).contains(&v) && (v.to_bits() != (-0.0f32).to_bits()),
"sat({} [e.g. {:#x}]) => {} [e.g {:#x}]",
f,
f.to_bits(),
v,
v.to_bits(),
);
let sat = v * 255.0 + 0.5;
// Note: This checks what's required by is the safety predicate for
// `f32::to_int_unchecked`:
// https://doc.rust-lang.org/std/primitive.f32.html#method.to_int_unchecked
assert!(
sat.trunc() >= 0.0 && sat.trunc() <= (u8::MAX as f32) && sat.is_finite(),
"f32_to_u8_sat({} [e.g. {:#x}]) would be UB!",
f,
f.to_bits(),
);
}
}
#[test]
fn test_saturate_all_u8s() {
for u in 0..=u8::MAX {
let v = f32_to_u8_sat(u8_to_f32_sat(u));
assert_eq!(u, v);
}
}

View File

@@ -1,68 +0,0 @@
use crate::sys;
use crate::Ui;
/// # Columns
impl<'ui> Ui<'ui> {
#[doc(alias = "Columns")]
pub fn columns(&self, count: i32, id: impl AsRef<str>, border: bool) {
unsafe { sys::igColumns(count, self.scratch_txt(id), border) }
}
/// Switches to the next column.
///
/// If the current row is finished, switches to first column of the next row
#[doc(alias = "NextColumn")]
pub fn next_column(&self) {
unsafe { sys::igNextColumn() }
}
/// Returns the index of the current column
#[doc(alias = "GetColumnIndex")]
pub fn current_column_index(&self) -> i32 {
unsafe { sys::igGetColumnIndex() }
}
/// Returns the width of the current column (in pixels)
#[doc(alias = "GetColumnWidth")]
pub fn current_column_width(&self) -> f32 {
unsafe { sys::igGetColumnWidth(-1) }
}
#[doc(alias = "GetColumnWidth")]
/// Returns the width of the given column (in pixels)
pub fn column_width(&self, column_index: i32) -> f32 {
unsafe { sys::igGetColumnWidth(column_index) }
}
#[doc(alias = "SetColumnWidth")]
/// Sets the width of the current column (in pixels)
pub fn set_current_column_width(&self, width: f32) {
unsafe { sys::igSetColumnWidth(-1, width) };
}
#[doc(alias = "SetColumnWidth")]
/// Sets the width of the given column (in pixels)
pub fn set_column_width(&self, column_index: i32, width: f32) {
unsafe { sys::igSetColumnWidth(column_index, width) };
}
/// Returns the offset of the current column (in pixels from the left side of the content
/// region)
#[doc(alias = "GetColumnOffset")]
pub fn current_column_offset(&self) -> f32 {
unsafe { sys::igGetColumnOffset(-1) }
}
/// Returns the offset of the given column (in pixels from the left side of the content region)
#[doc(alias = "GetColumnOffset")]
pub fn column_offset(&self, column_index: i32) -> f32 {
unsafe { sys::igGetColumnOffset(column_index) }
}
/// Sets the offset of the current column (in pixels from the left side of the content region)
#[doc(alias = "SetColumnOffset")]
pub fn set_current_column_offset(&self, offset_x: f32) {
unsafe { sys::igSetColumnOffset(-1, offset_x) };
}
/// Sets the offset of the given column (in pixels from the left side of the content region)
#[doc(alias = "SetColumnOffset")]
pub fn set_column_offset(&self, column_index: i32, offset_x: f32) {
unsafe { sys::igSetColumnOffset(column_index, offset_x) };
}
/// Returns the current amount of columns
#[doc(alias = "GetColumnCount")]
pub fn column_count(&self) -> i32 {
unsafe { sys::igGetColumnsCount() }
}
}

View File

@@ -1,582 +0,0 @@
use parking_lot::ReentrantMutex;
use std::cell::{RefCell, UnsafeCell};
use std::ffi::{CStr, CString};
use std::mem::ManuallyDrop;
use std::ops::Drop;
use std::path::PathBuf;
use std::ptr;
use std::rc::Rc;
use crate::clipboard::{ClipboardBackend, ClipboardContext};
use crate::fonts::atlas::{FontAtlas, FontAtlasRefMut, FontId, SharedFontAtlas};
use crate::io::Io;
use crate::style::Style;
use crate::sys;
use crate::Ui;
/// An imgui-rs context.
///
/// A context needs to be created to access most library functions. Due to current Dear ImGui
/// design choices, at most one active Context can exist at any time. This limitation will likely
/// be removed in a future Dear ImGui version.
///
/// If you need more than one context, you can use suspended contexts. As long as only one context
/// is active at a time, it's possible to have multiple independent contexts.
///
/// # Examples
///
/// Creating a new active context:
/// ```
/// let ctx = imgui::Context::create();
/// // ctx is dropped naturally when it goes out of scope, which deactivates and destroys the
/// // context
/// ```
///
/// Never try to create an active context when another one is active:
///
/// ```should_panic
/// let ctx1 = imgui::Context::create();
///
/// let ctx2 = imgui::Context::create(); // PANIC
/// ```
///
/// Suspending an active context allows you to create another active context:
///
/// ```
/// let ctx1 = imgui::Context::create();
/// let suspended1 = ctx1.suspend();
/// let ctx2 = imgui::Context::create(); // this is now OK
/// ```
#[derive(Debug)]
pub struct Context {
raw: *mut sys::ImGuiContext,
shared_font_atlas: Option<Rc<RefCell<SharedFontAtlas>>>,
ini_filename: Option<CString>,
log_filename: Option<CString>,
platform_name: Option<CString>,
renderer_name: Option<CString>,
// we need to box this because we hand imgui a pointer to it,
// and we don't want to deal with finding `clipboard_ctx`.
// we also put it in an unsafecell since we're going to give
// imgui a mutable pointer to it.
clipboard_ctx: Box<UnsafeCell<ClipboardContext>>,
}
// This mutex needs to be used to guard all public functions that can affect the underlying
// Dear ImGui active context
static CTX_MUTEX: ReentrantMutex<()> = parking_lot::const_reentrant_mutex(());
fn clear_current_context() {
unsafe {
sys::igSetCurrentContext(ptr::null_mut());
}
}
fn no_current_context() -> bool {
let ctx = unsafe { sys::igGetCurrentContext() };
ctx.is_null()
}
impl Context {
/// Creates a new active imgui-rs context.
///
/// # Panics
///
/// Panics if an active context already exists
#[doc(alias = "CreateContext")]
pub fn create() -> Self {
Self::create_internal(None)
}
/// Creates a new active imgui-rs context with a shared font atlas.
///
/// # Panics
///
/// Panics if an active context already exists
#[doc(alias = "CreateContext")]
pub fn create_with_shared_font_atlas(shared_font_atlas: Rc<RefCell<SharedFontAtlas>>) -> Self {
Self::create_internal(Some(shared_font_atlas))
}
/// Suspends this context so another context can be the active context.
#[doc(alias = "CreateContext")]
pub fn suspend(self) -> SuspendedContext {
let _guard = CTX_MUTEX.lock();
assert!(
self.is_current_context(),
"context to be suspended is not the active context"
);
clear_current_context();
SuspendedContext(self)
}
/// Returns the path to the ini file, or None if not set
pub fn ini_filename(&self) -> Option<PathBuf> {
let io = self.io();
if io.ini_filename.is_null() {
None
} else {
let s = unsafe { CStr::from_ptr(io.ini_filename) };
Some(PathBuf::from(s.to_str().ok()?))
}
}
/// Sets the path to the ini file (default is "imgui.ini")
///
/// Pass None to disable automatic .Ini saving.
pub fn set_ini_filename<T: Into<Option<PathBuf>>>(&mut self, ini_filename: T) {
let ini_filename: Option<PathBuf> = ini_filename.into();
let ini_filename = ini_filename.and_then(|v| CString::new(v.to_str()?).ok());
self.io_mut().ini_filename = ini_filename
.as_ref()
.map(|x| x.as_ptr())
.unwrap_or(ptr::null());
self.ini_filename = ini_filename;
}
/// Returns the path to the log file, or None if not set
// TODO: why do we return an `Option<PathBuf>` instead of an `Option<&Path>`?
pub fn log_filename(&self) -> Option<PathBuf> {
let io = self.io();
if io.log_filename.is_null() {
None
} else {
let cstr = unsafe { CStr::from_ptr(io.log_filename) };
Some(PathBuf::from(cstr.to_str().ok()?))
}
}
/// Sets the log filename (default is "imgui_log.txt").
pub fn set_log_filename<T: Into<Option<PathBuf>>>(&mut self, log_filename: T) {
let log_filename = log_filename
.into()
.and_then(|v| CString::new(v.to_str()?).ok());
self.io_mut().log_filename = log_filename
.as_ref()
.map(|x| x.as_ptr())
.unwrap_or(ptr::null());
self.log_filename = log_filename;
}
/// Returns the backend platform name, or None if not set
pub fn platform_name(&self) -> Option<&str> {
let io = self.io();
if io.backend_platform_name.is_null() {
None
} else {
let cstr = unsafe { CStr::from_ptr(io.backend_platform_name) };
cstr.to_str().ok()
}
}
/// Sets the backend platform name
pub fn set_platform_name<T: Into<Option<String>>>(&mut self, platform_name: T) {
let platform_name: Option<CString> =
platform_name.into().and_then(|v| CString::new(v).ok());
self.io_mut().backend_platform_name = platform_name
.as_ref()
.map(|x| x.as_ptr())
.unwrap_or(ptr::null());
self.platform_name = platform_name;
}
/// Returns the backend renderer name, or None if not set
pub fn renderer_name(&self) -> Option<&str> {
let io = self.io();
if io.backend_renderer_name.is_null() {
None
} else {
let cstr = unsafe { CStr::from_ptr(io.backend_renderer_name) };
cstr.to_str().ok()
}
}
/// Sets the backend renderer name
pub fn set_renderer_name<T: Into<Option<String>>>(&mut self, renderer_name: T) {
let renderer_name: Option<CString> =
renderer_name.into().and_then(|v| CString::new(v).ok());
self.io_mut().backend_renderer_name = renderer_name
.as_ref()
.map(|x| x.as_ptr())
.unwrap_or(ptr::null());
self.renderer_name = renderer_name;
}
/// Loads settings from a string slice containing settings in .Ini file format
#[doc(alias = "LoadIniSettingsFromMemory")]
pub fn load_ini_settings(&mut self, data: &str) {
unsafe { sys::igLoadIniSettingsFromMemory(data.as_ptr() as *const _, data.len()) }
}
/// Saves settings to a mutable string buffer in .Ini file format
#[doc(alias = "SaveInitSettingsToMemory")]
pub fn save_ini_settings(&mut self, buf: &mut String) {
let data = unsafe { CStr::from_ptr(sys::igSaveIniSettingsToMemory(ptr::null_mut())) };
buf.push_str(&data.to_string_lossy());
}
/// Sets the clipboard backend used for clipboard operations
pub fn set_clipboard_backend<T: ClipboardBackend>(&mut self, backend: T) {
let clipboard_ctx: Box<UnsafeCell<_>> = Box::new(ClipboardContext::new(backend).into());
let io = self.io_mut();
io.set_clipboard_text_fn = Some(crate::clipboard::set_clipboard_text);
io.get_clipboard_text_fn = Some(crate::clipboard::get_clipboard_text);
io.clipboard_user_data = clipboard_ctx.get() as *mut _;
self.clipboard_ctx = clipboard_ctx;
}
fn create_internal(shared_font_atlas: Option<Rc<RefCell<SharedFontAtlas>>>) -> Self {
let _guard = CTX_MUTEX.lock();
assert!(
no_current_context(),
"A new active context cannot be created, because another one already exists"
);
let shared_font_atlas_ptr = match &shared_font_atlas {
Some(shared_font_atlas) => {
let borrowed_font_atlas = shared_font_atlas.borrow();
borrowed_font_atlas.0
}
None => ptr::null_mut(),
};
// Dear ImGui implicitly sets the current context during igCreateContext if the current
// context doesn't exist
let raw = unsafe { sys::igCreateContext(shared_font_atlas_ptr) };
Context {
raw,
shared_font_atlas,
ini_filename: None,
log_filename: None,
platform_name: None,
renderer_name: None,
clipboard_ctx: Box::new(ClipboardContext::dummy().into()),
}
}
fn is_current_context(&self) -> bool {
let ctx = unsafe { sys::igGetCurrentContext() };
self.raw == ctx
}
/// Get a reference to the current context
pub fn current() -> Option<ContextRef> {
let _guard = CTX_MUTEX.lock();
let raw = unsafe { sys::igGetCurrentContext() };
if raw.is_null() {
None
} else {
Some(ContextRef(ManuallyDrop::new(Context {
raw,
shared_font_atlas: None, // XXX: this might be needed tbh
ini_filename: None,
log_filename: None,
platform_name: None,
renderer_name: None,
clipboard_ctx: Box::new(ClipboardContext::dummy().into()),
})))
}
}
}
/// A reference to a [`Context`] object
#[derive(Debug)]
pub struct ContextRef(ManuallyDrop<Context>);
impl core::ops::Deref for ContextRef {
type Target = Context;
fn deref(&self) -> &Context {
&*self.0
}
}
impl core::ops::DerefMut for ContextRef {
fn deref_mut(&mut self) -> &mut Context {
&mut *self.0
}
}
impl Drop for Context {
#[doc(alias = "DestroyContext")]
fn drop(&mut self) {
let _guard = CTX_MUTEX.lock();
// If this context is the active context, Dear ImGui automatically deactivates it during
// destruction
unsafe {
sys::igDestroyContext(self.raw);
}
}
}
/// A suspended imgui-rs context.
///
/// A suspended context retains its state, but is not usable without activating it first.
///
/// # Examples
///
/// Suspended contexts are not directly very useful, but you can activate them:
///
/// ```
/// let suspended = imgui::SuspendedContext::create();
/// match suspended.activate() {
/// Ok(ctx) => {
/// // ctx is now the active context
/// },
/// Err(suspended) => {
/// // activation failed, so you get the suspended context back
/// }
/// }
/// ```
#[derive(Debug)]
pub struct SuspendedContext(Context);
impl SuspendedContext {
/// Creates a new suspended imgui-rs context.
#[doc(alias = "CreateContext")]
pub fn create() -> Self {
Self::create_internal(None)
}
/// Creates a new suspended imgui-rs context with a shared font atlas.
pub fn create_with_shared_font_atlas(shared_font_atlas: Rc<RefCell<SharedFontAtlas>>) -> Self {
Self::create_internal(Some(shared_font_atlas))
}
/// Attempts to activate this suspended context.
///
/// If there is no active context, this suspended context is activated and `Ok` is returned,
/// containing the activated context.
/// If there is already an active context, nothing happens and `Err` is returned, containing
/// the original suspended context.
#[doc(alias = "SetCurrentContext")]
pub fn activate(self) -> Result<Context, SuspendedContext> {
let _guard = CTX_MUTEX.lock();
if no_current_context() {
unsafe {
sys::igSetCurrentContext(self.0.raw);
}
Ok(self.0)
} else {
Err(self)
}
}
fn create_internal(shared_font_atlas: Option<Rc<RefCell<SharedFontAtlas>>>) -> Self {
let _guard = CTX_MUTEX.lock();
let raw = unsafe { sys::igCreateContext(ptr::null_mut()) };
let ctx = Context {
raw,
shared_font_atlas,
ini_filename: None,
log_filename: None,
platform_name: None,
renderer_name: None,
clipboard_ctx: Box::new(ClipboardContext::dummy().into()),
};
if ctx.is_current_context() {
// Oops, the context was activated -> deactivate
clear_current_context();
}
SuspendedContext(ctx)
}
}
#[test]
fn test_one_context() {
let _guard = crate::test::TEST_MUTEX.lock();
let _ctx = Context::create();
assert!(!no_current_context());
}
#[test]
fn test_drop_clears_current_context() {
let _guard = crate::test::TEST_MUTEX.lock();
{
let _ctx1 = Context::create();
assert!(!no_current_context());
}
assert!(no_current_context());
{
let _ctx2 = Context::create();
assert!(!no_current_context());
}
assert!(no_current_context());
}
#[test]
fn test_new_suspended() {
let _guard = crate::test::TEST_MUTEX.lock();
let ctx = Context::create();
let _suspended = SuspendedContext::create();
assert!(ctx.is_current_context());
::std::mem::drop(_suspended);
assert!(ctx.is_current_context());
}
#[test]
fn test_suspend() {
let _guard = crate::test::TEST_MUTEX.lock();
let ctx = Context::create();
assert!(!no_current_context());
let _suspended = ctx.suspend();
assert!(no_current_context());
let _ctx2 = Context::create();
}
#[test]
fn test_drop_suspended() {
let _guard = crate::test::TEST_MUTEX.lock();
let suspended = Context::create().suspend();
assert!(no_current_context());
let ctx2 = Context::create();
::std::mem::drop(suspended);
assert!(ctx2.is_current_context());
}
#[test]
fn test_suspend_activate() {
let _guard = crate::test::TEST_MUTEX.lock();
let suspended = Context::create().suspend();
assert!(no_current_context());
let ctx = suspended.activate().unwrap();
assert!(ctx.is_current_context());
}
#[test]
fn test_suspend_failure() {
let _guard = crate::test::TEST_MUTEX.lock();
let suspended = Context::create().suspend();
let _ctx = Context::create();
assert!(suspended.activate().is_err());
}
#[test]
fn test_shared_font_atlas() {
let _guard = crate::test::TEST_MUTEX.lock();
let atlas = Rc::new(RefCell::new(SharedFontAtlas::create()));
let suspended1 = SuspendedContext::create_with_shared_font_atlas(atlas.clone());
let mut ctx2 = Context::create_with_shared_font_atlas(atlas);
{
let _borrow = ctx2.fonts();
}
let _suspended2 = ctx2.suspend();
let mut ctx = suspended1.activate().unwrap();
let _borrow = ctx.fonts();
}
#[test]
#[should_panic]
fn test_shared_font_atlas_borrow_panic() {
let _guard = crate::test::TEST_MUTEX.lock();
let atlas = Rc::new(RefCell::new(SharedFontAtlas::create()));
let _suspended = SuspendedContext::create_with_shared_font_atlas(atlas.clone());
let mut ctx = Context::create_with_shared_font_atlas(atlas.clone());
let _borrow1 = atlas.borrow();
let _borrow2 = ctx.fonts();
}
#[test]
fn test_ini_load_save() {
let (_guard, mut ctx) = crate::test::test_ctx();
let data = "[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0";
ctx.load_ini_settings(data);
let mut buf = String::new();
ctx.save_ini_settings(&mut buf);
assert_eq!(data.trim(), buf.trim());
}
#[test]
fn test_default_ini_filename() {
let _guard = crate::test::TEST_MUTEX.lock();
let ctx = Context::create();
assert_eq!(ctx.ini_filename(), Some(PathBuf::from("imgui.ini")));
}
#[test]
fn test_set_ini_filename() {
let (_guard, mut ctx) = crate::test::test_ctx();
ctx.set_ini_filename(Some(PathBuf::from("test.ini")));
assert_eq!(ctx.ini_filename(), Some(PathBuf::from("test.ini")));
}
#[test]
fn test_default_log_filename() {
let _guard = crate::test::TEST_MUTEX.lock();
let ctx = Context::create();
assert_eq!(ctx.log_filename(), Some(PathBuf::from("imgui_log.txt")));
}
#[test]
fn test_set_log_filename() {
let (_guard, mut ctx) = crate::test::test_ctx();
ctx.set_log_filename(Some(PathBuf::from("test.log")));
assert_eq!(ctx.log_filename(), Some(PathBuf::from("test.log")));
}
impl Context {
/// Returns an immutable reference to the inputs/outputs object
pub fn io(&self) -> &Io {
unsafe {
// safe because Io is a transparent wrapper around sys::ImGuiIO
&*(sys::igGetIO() as *const Io)
}
}
/// Returns a mutable reference to the inputs/outputs object
pub fn io_mut(&mut self) -> &mut Io {
unsafe {
// safe because Io is a transparent wrapper around sys::ImGuiIO
&mut *(sys::igGetIO() as *mut Io)
}
}
/// Returns an immutable reference to the user interface style
#[doc(alias = "GetStyle")]
pub fn style(&self) -> &Style {
unsafe {
// safe because Style is a transparent wrapper around sys::ImGuiStyle
&*(sys::igGetStyle() as *const Style)
}
}
/// Returns a mutable reference to the user interface style
#[doc(alias = "GetStyle")]
pub fn style_mut(&mut self) -> &mut Style {
unsafe {
// safe because Style is a transparent wrapper around sys::ImGuiStyle
&mut *(sys::igGetStyle() as *mut Style)
}
}
/// Returns a mutable reference to the font atlas.
///
/// # Panics
///
/// Panics if the context uses a shared font atlas that is already borrowed
pub fn fonts(&mut self) -> FontAtlasRefMut<'_> {
match self.shared_font_atlas {
Some(ref font_atlas) => FontAtlasRefMut::Shared(font_atlas.borrow_mut()),
None => unsafe {
// safe because FontAtlas is a transparent wrapper around sys::ImFontAtlas
let fonts = &mut *(self.io_mut().fonts as *mut FontAtlas);
FontAtlasRefMut::Owned(fonts)
},
}
}
/// Starts a new frame and returns an `Ui` instance for constructing a user interface.
///
/// # Panics
///
/// Panics if the context uses a shared font atlas that is already borrowed
#[doc(alias = "NewFame")]
pub fn frame(&mut self) -> Ui<'_> {
// Clear default font if it no longer exists. This could be an error in the future
let default_font = self.io().font_default;
if !default_font.is_null() && self.fonts().get_font(FontId(default_font)).is_none() {
self.io_mut().font_default = ptr::null_mut();
}
// NewFrame/Render/EndFrame mutate the font atlas so we need exclusive access to it
let font_atlas = self
.shared_font_atlas
.as_ref()
.map(|font_atlas| font_atlas.borrow_mut());
// TODO: precondition checks
unsafe {
sys::igNewFrame();
}
Ui {
ctx: self,
font_atlas,
buffer: crate::UiBuffer::new(1024).into(),
}
}
}

View File

@@ -1,594 +0,0 @@
//! Structs to create a Drag and Drop sequence. Almost all structs are re-exported
//! and can be accessed from the crate root; some additional utilities can be found in here.
//!
//! A DragDrop is a UI mechanism where users can appear to "drag"
//! some data from one [source](DragDropSource) to one [target](DragDropTarget).
//! A source and a target must both have some `name` identifier, which is declared when they
//! are created. If these names are equal, then a `payload` of some kind
//! will be given to the target caller when the user releases their mouse button over
//! the target (additionally, the UI will reflect that the payload *can* be deposited
//! in the target).
//!
//! The complexity of this implementation is primarily in managing this payload. Users
//! can provide three different kinds of payloads:
//!
//! 1. Users can give an [empty payload](DragDropPayloadEmpty) with [begin](DragDropSource::begin).
//! This payload type is essentially just a notification system, but using some shared state,
//! this can be reasonably powerful, and is the safest way to transfer non-Copy data offered
//! right now.
//! 2. Users can give a [simple Copy payload](DragDropPayloadPod) with [begin](DragDropSource::begin_payload).
//! This allows users to copy data to Dear ImGui, which will take ownership over it, and then be given
//! it back to the Target. Please note: users are of course free to not drop any drag (cancel a drag),
//! so this data could easily be lost forever. Our `'static + Copy` bound is intended to keep users
//! to simplistic types.
//! 3. An unsafe implementation is provided which allows for any data to be unsafely copied. Note that once
//! you use this method, the safe implementations in #1 and #2 can create memory unsafety problems; notably,
//! they both assume that a payload has certain header information within it.
//!
//! For examples of each payload type, see [DragDropSource].
use std::{any, ffi, marker::PhantomData};
use crate::{sys, Condition, Ui};
use bitflags::bitflags;
bitflags!(
/// Flags for igBeginDragDropSource(), igAcceptDragDropPayload()
#[repr(transparent)]
pub struct DragDropFlags: u32 {
/// By default, a successful call to igBeginDragDropSource opens a tooltip so you can
/// display a preview or description of the source contents. This flag disable this
/// behavior.
const SOURCE_NO_PREVIEW_TOOLTIP = sys::ImGuiDragDropFlags_SourceNoPreviewTooltip;
/// By default, when dragging we clear data so that igIsItemHovered() will return false, to
/// avoid subsequent user code submitting tooltips. This flag disable this behavior so you
/// can still call igIsItemHovered() on the source item.
const SOURCE_NO_DISABLE_HOVER = sys::ImGuiDragDropFlags_SourceNoDisableHover;
/// Disable the behavior that allows to open tree nodes and collapsing header by holding
/// over them while dragging a source item.
const SOURCE_NO_HOLD_TO_OPEN_OTHERS = sys::ImGuiDragDropFlags_SourceNoHoldToOpenOthers;
/// Allow items such as igText(), igImage() that have no unique identifier to be used as
/// drag source, by manufacturing a temporary identifier based on their window-relative
/// position. This is extremely unusual within the dear imgui ecosystem and so we made it
/// explicit.
const SOURCE_ALLOW_NULL_ID = sys::ImGuiDragDropFlags_SourceAllowNullID;
/// External source (from outside of imgui), won't attempt to read current item/window
/// info. Will always return true. Only one Extern source can be active simultaneously.
const SOURCE_EXTERN = sys::ImGuiDragDropFlags_SourceExtern;
/// Automatically expire the payload if the source ceases to be submitted (otherwise
/// payloads are persisting while being dragged)
const SOURCE_AUTO_EXPIRE_PAYLOAD = sys::ImGuiDragDropFlags_SourceAutoExpirePayload;
/// igAcceptDragDropPayload() will returns true even before the mouse button is released.
/// You can then call igIsDelivery() to test if the payload needs to be delivered.
const ACCEPT_BEFORE_DELIVERY = sys::ImGuiDragDropFlags_AcceptBeforeDelivery;
/// Do not draw the default highlight rectangle when hovering over target.
const ACCEPT_NO_DRAW_DEFAULT_RECT = sys::ImGuiDragDropFlags_AcceptNoDrawDefaultRect;
/// Request hiding the igBeginDragDropSource tooltip from the igBeginDragDropTarget site.
const ACCEPT_NO_PREVIEW_TOOLTIP = sys::ImGuiDragDropFlags_AcceptNoPreviewTooltip;
/// For peeking ahead and inspecting the payload before delivery. This is just a convenience
/// flag for the intersection of `ACCEPT_BEFORE_DELIVERY` and `ACCEPT_NO_DRAW_DEFAULT_RECT`
const ACCEPT_PEEK_ONLY = sys::ImGuiDragDropFlags_AcceptPeekOnly;
}
);
/// Creates a source for drag drop data out of the last ID created.
///
/// ```no_run
/// # use imgui::*;
/// fn show_ui(ui: &Ui<'_>) {
/// ui.button("Hello, I am a drag source!");
///
/// // Creates an empty DragSource with no tooltip
/// DragDropSource::new("BUTTON_DRAG").begin(ui);
/// }
/// ```
///
/// Notice especially the `"BUTTON_DRAG"` name -- this is the identifier of this
/// DragDropSource; [DragDropTarget]'s will specify an identifier to *receive*, and these
/// names must match up. A single item should only have one [DragDropSource], though
/// a target may have multiple different targets.
///
/// DropDropSources don't do anything until you use one of the three `begin_` methods
/// on this struct. Each of these methods describes how you handle the Payload which ImGui
/// will manage, and then give to a [DragDropTarget], which will received the payload. The
/// simplest and safest Payload is the empty payload, created with [begin](Self::begin).
#[derive(Debug)]
pub struct DragDropSource<T> {
name: T,
flags: DragDropFlags,
cond: Condition,
}
impl<T: AsRef<str>> DragDropSource<T> {
/// Creates a new [DragDropSource] with no flags and the `Condition::Always` with the given name.
/// ImGui refers to this `name` field as a `type`, but really it's just an identifier to match up
/// Source/Target for DragDrop.
pub fn new(name: T) -> Self {
Self {
name,
flags: DragDropFlags::empty(),
cond: Condition::Always,
}
}
/// Sets the flags on the [DragDropSource]. Only the flags `SOURCE_NO_PREVIEW_TOOLTIP`,
/// `SOURCE_NO_DISABLE_HOVER`, `SOURCE_NO_HOLD_TO_OPEN_OTHERS`, `SOURCE_ALLOW_NULL_ID`,
/// `SOURCE_EXTERN`, `SOURCE_AUTO_EXPIRE_PAYLOAD` make semantic sense, but any other flags will
/// be accepted without panic.
#[inline]
pub fn flags(mut self, flags: DragDropFlags) -> Self {
self.flags = flags;
self
}
/// Sets the condition on the [DragDropSource]. Defaults to [Always](Condition::Always).
#[inline]
pub fn condition(mut self, cond: Condition) -> Self {
self.cond = cond;
self
}
/// Creates the source of a drag and returns a handle on the tooltip.
/// This handle can be immediately dropped without binding it, in which case a default empty
/// circle will be used for the "blank" tooltip as this item is being dragged around.
///
/// Otherwise, use this tooltip to add data which will display as this item is dragged.
/// If `SOURCE_NO_PREVIEW_TOOLTIP` is enabled, however, no preview will be displayed
/// and this returned token does nothing. Additionally, a given target may use the flag
/// `ACCEPT_NO_PREVIEW_TOOLTIP`, which will also prevent this tooltip from being shown.
///
/// This drag has no payload, but is still probably the most useful way in imgui-rs to handle payloads.
/// Using `once_cell` or some shared data, this pattern can be very powerful:
///
/// ```no_run
/// # use imgui::*;
/// fn show_ui(ui: &Ui<'_>, drop_message: &mut Option<String>) {
/// ui.button("Drag me!");
///
/// let drag_drop_name = "Test Drag";
///
/// // drag drop SOURCE
/// if DragDropSource::new(drag_drop_name).begin(ui).is_some() {
/// // warning -- this would allocate every frame if `DragDropSource` has
/// // condition `Always`, which it does by default. We're okay with that for
/// // this example, but real code probably wouldn't want to allocate so much.
/// *drop_message = Some("Test Payload".to_string());
/// }
///
/// ui.button("Target me!");
///
/// // drag drop TARGET
/// if let Some(target) = imgui::DragDropTarget::new(ui) {
/// if target
/// .accept_payload_empty(drag_drop_name, DragDropFlags::empty())
/// .is_some()
/// {
/// let msg = drop_message.take().unwrap();
/// assert_eq!(msg, "Test Payload");
/// }
///
/// target.pop();
/// }
/// }
/// ```
///
/// In the above, you'll see how the payload is really just a message passing service.
/// If you want to pass a simple integer or other "plain old data", take a look at
/// [begin_payload](Self::begin_payload).
#[inline]
pub fn begin<'ui>(self, ui: &Ui<'ui>) -> Option<DragDropSourceToolTip<'ui>> {
self.begin_payload(ui, ())
}
/// Creates the source of a drag and returns a handle on the tooltip.
/// This handle can be immediately dropped without binding it, in which case a default empty
/// circle will be used for the "blank" tooltip as this item is being dragged around.
///
/// Otherwise, use this tooltip to add data which will display as this item is dragged.
/// If `SOURCE_NO_PREVIEW_TOOLTIP` is enabled, however, no preview will be displayed
/// and this returned token does nothing. Additionally, a given target may use the flag
/// `ACCEPT_NO_PREVIEW_TOOLTIP`, which will also prevent this tooltip from being shown.
///
/// This function also takes a payload in the form of `T: Copy + 'static`. ImGui will
/// memcpy this data immediately to an internally held buffer, and will return the data
/// to [DragDropTarget].
///
/// ```no_run
/// # use imgui::*;
/// fn show_ui(ui: &Ui<'_>) {
/// ui.button("Drag me!");
///
/// let drag_drop_name = "Test Drag";
/// let msg_to_send = "hello there sailor";
///
/// // drag drop SOURCE
/// if let Some(tooltip) = DragDropSource::new(drag_drop_name).begin_payload(ui, msg_to_send) {
/// ui.text("Sending message!");
/// tooltip.end();
/// }
///
/// ui.button("Target me!");
///
/// // drag drop TARGET
/// if let Some(target) = imgui::DragDropTarget::new(ui) {
/// if let Some(Ok(payload_data)) = target
/// .accept_payload::<&'static str, _>(drag_drop_name, DragDropFlags::empty())
/// {
/// let msg = payload_data.data;
/// assert_eq!(msg, msg_to_send);
/// }
///
/// target.pop();
/// }
/// }
/// ```
#[inline]
pub fn begin_payload<'ui, P: Copy + 'static>(
self,
ui: &Ui<'ui>,
payload: P,
) -> Option<DragDropSourceToolTip<'ui>> {
unsafe {
let payload = TypedPayload::new(payload);
self.begin_payload_unchecked(
ui,
&payload as *const _ as *const ffi::c_void,
std::mem::size_of::<TypedPayload<P>>(),
)
}
}
/// Creates the source of a drag and returns a handle on the tooltip.
/// This handle can be immediately dropped without binding it, in which case a default empty
/// circle will be used for the "blank" tooltip as this item is being dragged around.
///
/// Otherwise, use this tooltip to add data which will display as this item is dragged.
/// If `SOURCE_NO_PREVIEW_TOOLTIP` is enabled, however, no preview will be displayed
/// and this returned token does nothing. Additionally, a given target may use the flag
/// `ACCEPT_NO_PREVIEW_TOOLTIP`, which will also prevent this tooltip from being shown.
///
/// This function also takes a payload of any `*const T`. ImGui will
/// memcpy this data immediately to an internally held buffer, and will return the data
/// to [DragDropTarget].
///
/// ## Safety
/// This function itself will not cause a panic, but using it directly opts you into
/// managing the lifetime of the pointer provided yourself. Dear ImGui will execute a memcpy on
/// the data passed in with the size (in bytes) given, but this is, of course, just a copy,
/// so if you pass in an `&String`, for example, the underlying String data will not be cloned,
/// and could easily dangle if the `String` is dropped.
///
/// Moreover, if `Condition::Always` is set (as it is by default), you will be copying in your data
/// every time this function is ran in your update loop, which if it involves an allocating and then
/// handing the allocation to ImGui, would result in a significant amount of data created.
///
/// Overall, users should be very sure that this function is needed before they reach for it, and instead
/// should consider either [begin](Self::begin) or [begin_payload](Self::begin_payload).
#[inline]
pub unsafe fn begin_payload_unchecked<'ui>(
&self,
ui: &Ui<'ui>,
ptr: *const ffi::c_void,
size: usize,
) -> Option<DragDropSourceToolTip<'ui>> {
let should_begin = sys::igBeginDragDropSource(self.flags.bits() as i32);
if should_begin {
sys::igSetDragDropPayload(ui.scratch_txt(&self.name), ptr, size, self.cond as i32);
Some(DragDropSourceToolTip::push())
} else {
None
}
}
}
/// A helper struct for RAII drag-drop support.
pub struct DragDropSourceToolTip<'ui>(PhantomData<Ui<'ui>>);
impl DragDropSourceToolTip<'_> {
/// Creates a new tooltip internally.
#[inline]
fn push() -> Self {
Self(PhantomData)
}
/// Ends the tooltip directly. You could choose to simply allow this to drop
/// by not calling this, which will also be fine.
#[inline]
pub fn end(self) {
// left empty to invoke drop...
}
}
impl Drop for DragDropSourceToolTip<'_> {
fn drop(&mut self) {
unsafe { sys::igEndDragDropSource() }
}
}
/// Creates a target for drag drop data out of the last ID created.
///
/// ```no_run
/// # use imgui::*;
/// fn show_ui(ui: &Ui<'_>) {
/// // Drop something on this button please!
/// ui.button("Hello, I am a drag Target!");
///
/// if let Some(target) = DragDropTarget::new(ui) {
/// // accepting an empty payload (which is really just raising an event)
/// if let Some(_payload_data) = target.accept_payload_empty("BUTTON_DRAG", DragDropFlags::empty()) {
/// println!("Nice job getting on the payload!");
/// }
///
/// // and we can accept multiple, different types of payloads with one drop target.
/// // this is a good pattern for handling different kinds of drag/drop situations with
/// // different kinds of data in them.
/// if let Some(Ok(payload_data)) = target.accept_payload::<usize, _>("BUTTON_ID", DragDropFlags::empty()) {
/// println!("Our payload's data was {}", payload_data.data);
/// }
/// }
/// }
/// ```
///
/// Notice especially the `"BUTTON_DRAG"` and `"BUTTON_ID"` name -- this is the identifier of this
/// DragDropTarget; [DragDropSource]s will specify an identifier when they send a payload, and these
/// names must match up. Notice how a target can have multiple acceptances on them -- this is a good
/// pattern to handle multiple kinds of data which could be passed around.
///
/// DropDropTargets don't do anything until you use one of the three `accept_` methods
/// on this struct. Each of these methods will spit out a _Payload struct with an increasing
/// amount of information on the Payload. The absolute safest solution is [accept_payload_empty](Self::accept_payload_empty).
#[derive(Debug)]
pub struct DragDropTarget<'ui>(&'ui Ui<'ui>);
impl<'ui> DragDropTarget<'ui> {
/// Creates a new DragDropTarget, holding the [Ui]'s lifetime for the duration
/// of its existence. This is required since this struct runs some code on its Drop
/// to end the DragDropTarget code.
#[doc(alias = "BeginDragDropTarget")]
pub fn new(ui: &'ui Ui<'ui>) -> Option<Self> {
let should_begin = unsafe { sys::igBeginDragDropTarget() };
if should_begin {
Some(Self(ui))
} else {
None
}
}
/// Accepts an empty payload. This is the safest option for raising named events
/// in the DragDrop API. See [DragDropSource::begin] for more information on how you
/// might use this pattern.
///
/// Note: If you began this operation with `begin_payload_unchecked` it always incorrect
/// to use this function. Use `accept_payload_unchecked` instead
pub fn accept_payload_empty(
&self,
name: impl AsRef<str>,
flags: DragDropFlags,
) -> Option<DragDropPayloadEmpty> {
self.accept_payload(name, flags)?
.ok()
.map(|payload_pod: DragDropPayloadPod<()>| DragDropPayloadEmpty {
preview: payload_pod.preview,
delivery: payload_pod.delivery,
})
}
/// Accepts a payload with plain old data in it. This returns a Result, since you can specify any
/// type. The sent type must match the return type (via TypeId) to receive an `Ok`.
///
/// Note: If you began this operation with `begin_payload_unchecked` it always incorrect
/// to use this function. Use `accept_payload_unchecked` instead
pub fn accept_payload<T: 'static + Copy, Name: AsRef<str>>(
&self,
name: Name,
flags: DragDropFlags,
) -> Option<Result<DragDropPayloadPod<T>, PayloadIsWrongType>> {
let output = unsafe { self.accept_payload_unchecked(name, flags) };
// convert the unsafe payload to our Result
output.map(|unsafe_payload| {
// sheering off the typeid...
let received =
unsafe { (unsafe_payload.data as *const TypedPayloadHeader).read_unaligned() };
let expected = any::TypeId::of::<T>();
if received.type_id == expected {
let data =
unsafe { (unsafe_payload.data as *const TypedPayload<T>).read_unaligned() }
.data;
Ok(DragDropPayloadPod {
data,
preview: unsafe_payload.preview,
delivery: unsafe_payload.delivery,
})
} else {
Err(PayloadIsWrongType {
received,
expected: TypedPayloadHeader::new::<T>(),
})
}
})
}
/// Accepts a drag and drop payload which contains a raw pointer to [c_void](std::ffi::c_void)
/// and a size in bytes. Users should generally avoid using this function
/// if one of the safer variants is acceptable.
///
/// ## Safety
///
/// Because this pointer comes from ImGui, absolutely no promises can be made on its
/// contents, alignment, or lifetime. Interacting with it is therefore extremely unsafe.
/// **Important:** a special note needs to be made to the [ACCEPT_BEFORE_DELIVERY](DragDropFlags::ACCEPT_BEFORE_DELIVERY) flag --
/// passing this flag will make this function return `Some(DragDropPayload)` **even before
/// the user has actually "dropped" the payload by release their mouse button.**
///
/// In safe functions, this works just fine, since the data can be freely copied
/// (or doesn't exist at all!). However, if you are working with your own data, you must
/// be extremely careful with this data, as you may, effectively, only have immutable access to it.
///
/// Moreover, if the `DragDropSource` has also used `Condition::Once` or similar when they sent the data,
/// ImGui will assume its data is still valid even after your preview, so corrupting that data could
/// lead to all sorts of unsafe behavior on ImGui's side. In summary, using this function for any data
/// which isn't truly `Copy` or "plain old data" is difficult, and requires substantial knowledge
/// of the various edge cases.
pub unsafe fn accept_payload_unchecked(
&self,
name: impl AsRef<str>,
flags: DragDropFlags,
) -> Option<DragDropPayload> {
let inner = sys::igAcceptDragDropPayload(self.0.scratch_txt(name), flags.bits() as i32);
if inner.is_null() {
None
} else {
let inner = *inner;
// @fixme: there are actually other fields on `inner` which I have shorn -- they're
// considered internal to imgui (such as id of who sent this), so i've left it for
// now this way.
Some(DragDropPayload {
data: inner.Data,
size: inner.DataSize as usize,
preview: inner.Preview,
delivery: inner.Delivery,
})
}
}
/// Ends the current target. Ironically, this doesn't really do anything in ImGui
/// or in imgui-rs, but it might in the future.
pub fn pop(self) {
// omitted...exists just to run Drop.
}
}
impl Drop for DragDropTarget<'_> {
fn drop(&mut self) {
unsafe { sys::igEndDragDropTarget() }
}
}
/// An empty DragDropPayload. It has no data in it, and just includes
/// two bools with status information.
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub struct DragDropPayloadEmpty {
/// Set when [`accept_payload_empty`](DragDropTarget::accept_payload_empty) was called
/// and mouse has been hovering the target item.
pub preview: bool,
/// Set when [`accept_payload_empty`](DragDropTarget::accept_payload_empty) was
/// called and mouse button is released over the target item.
pub delivery: bool,
}
/// A DragDropPayload with status information and some POD, or plain old data,
/// in it.
#[derive(Debug, Copy, Clone)]
#[non_exhaustive]
pub struct DragDropPayloadPod<T: 'static + Copy> {
/// The kind data which was requested.
pub data: T,
/// Set when [`accept_payload`](DragDropTarget::accept_payload) was called
/// and mouse has been hovering the target item.
pub preview: bool,
/// Set when [`accept_payload`](DragDropTarget::accept_payload) was
/// called and mouse button is released over the target item.
pub delivery: bool,
}
#[derive(Debug)]
#[non_exhaustive]
pub struct DragDropPayload {
/// Data which is copied and owned by ImGui. If you have accepted the payload, you can
/// take ownership of the data; otherwise, view it immutably. Interacting with `data` is
/// very unsafe.
pub data: *const ffi::c_void,
/// The size of the data in bytes.
pub size: usize,
/// Set when [`accept_payload_unchecked`](DragDropTarget::accept_payload_unchecked) was called
/// and mouse has been hovering the target item.
pub preview: bool,
/// Set when [`accept_payload_unchecked`](DragDropTarget::accept_payload_unchecked) was
/// called and mouse button is released over the target item. If this is set to false, then you
/// set DragDropFlags::ACCEPT_BEFORE_DELIVERY and shouldn't mutate `data`.
pub delivery: bool,
}
/// A typed payload.
#[derive(Debug, Clone, Copy)]
#[repr(C)]
struct TypedPayload<T> {
header: TypedPayloadHeader,
data: T,
}
impl<T: Copy + 'static> TypedPayload<T> {
/// Creates a new typed payload which contains this data.
fn new(data: T) -> Self {
Self {
header: TypedPayloadHeader::new::<T>(),
data,
}
}
}
/// A header for a typed payload.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
#[repr(C)]
struct TypedPayloadHeader {
type_id: any::TypeId,
#[cfg(debug_assertions)]
type_name: &'static str,
}
impl TypedPayloadHeader {
#[cfg(debug_assertions)]
fn new<T: 'static>() -> Self {
Self {
type_id: any::TypeId::of::<T>(),
type_name: any::type_name::<T>(),
}
}
#[cfg(not(debug_assertions))]
fn new<T: 'static>() -> Self {
Self {
type_id: any::TypeId::of::<T>(),
}
}
}
/// Indicates that an incorrect payload type was received. It is opaque,
/// but you can view useful information with Debug formatting when
/// `debug_assertions` are enabled.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
pub struct PayloadIsWrongType {
expected: TypedPayloadHeader,
received: TypedPayloadHeader,
}
#[cfg(debug_assertions)]
impl std::fmt::Display for PayloadIsWrongType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Payload is {} -- expected {}",
self.received.type_name, self.expected.type_name
)
}
}
#[cfg(not(debug_assertions))]
impl std::fmt::Display for PayloadIsWrongType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.pad("Payload is wrong type")
}
}
impl std::error::Error for PayloadIsWrongType {}

File diff suppressed because it is too large Load Diff

View File

@@ -1,508 +0,0 @@
use bitflags::bitflags;
use std::cell;
use std::f32;
use std::ops::{Deref, DerefMut};
use std::os::raw::{c_int, c_uchar, c_void};
use std::ptr;
use std::slice;
use crate::fonts::font::Font;
use crate::fonts::glyph_ranges::FontGlyphRanges;
use crate::internal::{ImVector, RawCast};
use crate::sys;
use crate::TextureId;
bitflags! {
/// Font atlas configuration flags
#[repr(transparent)]
pub struct FontAtlasFlags: u32 {
/// Don't round the height to next power of two
const NO_POWER_OF_TWO_HEIGHT = sys::ImFontAtlasFlags_NoPowerOfTwoHeight;
/// Don't build software mouse cursors into the atlas
const NO_MOUSE_CURSORS = sys::ImFontAtlasFlags_NoMouseCursors;
/// Don't build thick line textures into the atlas
const NO_BAKED_LINES = sys::ImFontAtlasFlags_NoBakedLines;
}
}
/// A font identifier
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct FontId(pub(crate) *const Font);
/// A font atlas that builds a single texture
#[repr(C)]
pub struct FontAtlas {
/// Configuration flags
pub flags: FontAtlasFlags,
/// Texture identifier
pub tex_id: TextureId,
/// Texture width desired by user before building the atlas.
///
/// Must be a power-of-two. If you have many glyphs and your graphics API has texture size
/// restrictions, you may want to increase texture width to decrease the height.
pub tex_desired_width: i32,
/// Padding between glyphs within texture in pixels.
///
/// Defaults to 1. If your rendering method doesn't rely on bilinear filtering, you may set
/// this to 0.
pub tex_glyph_padding: i32,
locked: bool,
text_ready: bool,
tex_pixels_use_colors: bool,
tex_pixels_alpha8: *mut u8,
tex_pixels_rgba32: *mut u32,
tex_width: i32,
tex_height: i32,
tex_uv_scale: [f32; 2],
tex_uv_white_pixel: [f32; 2],
fonts: ImVector<*mut Font>,
custom_rects: sys::ImVector_ImFontAtlasCustomRect,
config_data: sys::ImVector_ImFontConfig,
tex_uv_lines: [[f32; 4]; 64],
font_builder_io: *const sys::ImFontBuilderIO,
font_builder_flags: i32,
pack_id_mouse_cursors: i32,
pack_id_lines: i32,
}
unsafe impl RawCast<sys::ImFontAtlas> for FontAtlas {}
impl FontAtlas {
#[doc(alias = "AddFontDefault", alias = "AddFont")]
pub fn add_font(&mut self, font_sources: &[FontSource<'_>]) -> FontId {
let (head, tail) = font_sources.split_first().unwrap();
let font_id = self.add_font_internal(head, false);
for font in tail {
self.add_font_internal(font, true);
}
font_id
}
fn add_font_internal(&mut self, font_source: &FontSource<'_>, merge_mode: bool) -> FontId {
let mut raw_config = sys_font_config_default();
raw_config.MergeMode = merge_mode;
let raw_font = match font_source {
FontSource::DefaultFontData { config } => unsafe {
if let Some(config) = config {
config.apply_to_raw_config(&mut raw_config, self.raw_mut());
}
sys::ImFontAtlas_AddFontDefault(self.raw_mut(), &raw_config)
},
FontSource::TtfData {
data,
size_pixels,
config,
} => {
if let Some(config) = config {
unsafe {
config.apply_to_raw_config(&mut raw_config, self.raw_mut());
}
}
// We can't guarantee `data` is alive when the font atlas is built, so
// make a copy and move ownership of the data to the atlas
let data_copy = unsafe {
let ptr = sys::igMemAlloc(data.len()) as *mut u8;
assert!(!ptr.is_null());
slice::from_raw_parts_mut(ptr, data.len())
};
data_copy.copy_from_slice(data);
raw_config.FontData = data_copy.as_mut_ptr() as *mut c_void;
raw_config.FontDataSize = data_copy.len() as i32;
raw_config.FontDataOwnedByAtlas = true;
raw_config.SizePixels = *size_pixels;
unsafe { sys::ImFontAtlas_AddFont(self.raw_mut(), &raw_config) }
}
};
FontId(raw_font as *const _)
}
pub fn fonts(&self) -> Vec<FontId> {
let mut result = Vec::new();
unsafe {
for &font in self.fonts.as_slice() {
result.push((*font).id());
}
}
result
}
pub fn get_font(&self, id: FontId) -> Option<&Font> {
unsafe {
for &font in self.fonts.as_slice() {
if id == FontId(font) {
return Some(&*(font as *const Font));
}
}
}
None
}
/// Returns true if the font atlas has been built
#[doc(alias = "IsBuilt")]
pub fn is_built(&self) -> bool {
unsafe { sys::ImFontAtlas_IsBuilt(self.raw() as *const sys::ImFontAtlas as *mut _) }
}
/// Builds a 1 byte per-pixel font atlas texture
#[doc(alias = "GetTextDataAsAlpha8")]
pub fn build_alpha8_texture(&mut self) -> FontAtlasTexture<'_> {
let mut pixels: *mut c_uchar = ptr::null_mut();
let mut width: c_int = 0;
let mut height: c_int = 0;
let mut bytes_per_pixel: c_int = 0;
unsafe {
sys::ImFontAtlas_GetTexDataAsAlpha8(
self.raw_mut(),
&mut pixels,
&mut width,
&mut height,
&mut bytes_per_pixel,
);
assert!(width >= 0, "font texture width must be positive");
assert!(height >= 0, "font texture height must be positive");
assert!(
bytes_per_pixel >= 0,
"font texture bytes per pixel must be positive"
);
let height = height as usize;
// Check multiplication to avoid constructing an invalid slice in case of overflow
let pitch = width
.checked_mul(bytes_per_pixel)
.expect("Overflow in font texture pitch calculation")
as usize;
FontAtlasTexture {
width: width as u32,
height: height as u32,
data: slice::from_raw_parts(pixels, pitch * height),
}
}
}
/// Builds a 4 byte per-pixel font atlas texture
#[doc(alias = "GetTextDataAsRGBA32")]
pub fn build_rgba32_texture(&mut self) -> FontAtlasTexture<'_> {
let mut pixels: *mut c_uchar = ptr::null_mut();
let mut width: c_int = 0;
let mut height: c_int = 0;
let mut bytes_per_pixel: c_int = 0;
unsafe {
sys::ImFontAtlas_GetTexDataAsRGBA32(
self.raw_mut(),
&mut pixels,
&mut width,
&mut height,
&mut bytes_per_pixel,
);
assert!(width >= 0, "font texture width must be positive");
assert!(height >= 0, "font texture height must be positive");
assert!(
bytes_per_pixel >= 0,
"font texture bytes per pixel must be positive"
);
let height = height as usize;
// Check multiplication to avoid constructing an invalid slice in case of overflow
let pitch = width
.checked_mul(bytes_per_pixel)
.expect("Overflow in font texture pitch calculation")
as usize;
FontAtlasTexture {
width: width as u32,
height: height as u32,
data: slice::from_raw_parts(pixels, pitch * height),
}
}
}
/// Clears the font atlas completely (both input and output data)
#[doc(alias = "Clear")]
pub fn clear(&mut self) {
unsafe {
sys::ImFontAtlas_Clear(self.raw_mut());
}
}
/// Clears output font data (glyph storage, UV coordinates)
#[doc(alias = "ClearFonts")]
pub fn clear_fonts(&mut self) {
unsafe {
sys::ImFontAtlas_ClearFonts(self.raw_mut());
}
}
/// Clears output texture data.
///
/// Can be used to save RAM once the texture has been transferred to the GPU.
#[doc(alias = "ClearTexData")]
pub fn clear_tex_data(&mut self) {
unsafe {
sys::ImFontAtlas_ClearTexData(self.raw_mut());
}
}
/// Clears all the data used to build the textures and fonts
#[doc(alias = "ClearInputData")]
pub fn clear_input_data(&mut self) {
unsafe {
sys::ImFontAtlas_ClearInputData(self.raw_mut());
}
}
}
#[test]
#[cfg(test)]
fn test_font_atlas_memory_layout() {
use std::mem;
assert_eq!(
mem::size_of::<FontAtlas>(),
mem::size_of::<sys::ImFontAtlas>()
);
assert_eq!(
mem::align_of::<FontAtlas>(),
mem::align_of::<sys::ImFontAtlas>()
);
use sys::ImFontAtlas;
macro_rules! assert_field_offset {
($l:ident, $r:ident) => {
assert_eq!(
memoffset::offset_of!(FontAtlas, $l),
memoffset::offset_of!(ImFontAtlas, $r)
);
};
}
assert_field_offset!(locked, Locked);
assert_field_offset!(flags, Flags);
assert_field_offset!(tex_id, TexID);
assert_field_offset!(tex_desired_width, TexDesiredWidth);
assert_field_offset!(tex_glyph_padding, TexGlyphPadding);
assert_field_offset!(tex_pixels_use_colors, TexPixelsUseColors);
assert_field_offset!(tex_pixels_alpha8, TexPixelsAlpha8);
assert_field_offset!(tex_pixels_rgba32, TexPixelsRGBA32);
assert_field_offset!(tex_width, TexWidth);
assert_field_offset!(tex_height, TexHeight);
assert_field_offset!(tex_uv_scale, TexUvScale);
assert_field_offset!(tex_uv_white_pixel, TexUvWhitePixel);
assert_field_offset!(fonts, Fonts);
assert_field_offset!(custom_rects, CustomRects);
assert_field_offset!(config_data, ConfigData);
assert_field_offset!(tex_uv_lines, TexUvLines);
assert_field_offset!(pack_id_mouse_cursors, PackIdMouseCursors);
assert_field_offset!(pack_id_lines, PackIdLines);
}
/// A source for binary font data
#[derive(Clone, Debug)]
pub enum FontSource<'a> {
/// Default font included with the library (ProggyClean.ttf)
DefaultFontData { config: Option<FontConfig> },
/// Binary TTF/OTF font data
TtfData {
data: &'a [u8],
size_pixels: f32,
config: Option<FontConfig>,
},
}
/// Configuration settings for a font
#[derive(Clone, Debug)]
pub struct FontConfig {
/// Size in pixels for the rasterizer
pub size_pixels: f32,
/// Horizontal oversampling
pub oversample_h: i32,
/// Vertical oversampling
pub oversample_v: i32,
/// Align every glyph to pixel boundary
pub pixel_snap_h: bool,
/// Extra spacing (in pixels) between glyphs
pub glyph_extra_spacing: [f32; 2],
/// Offset for all glyphs in this font
pub glyph_offset: [f32; 2],
/// Unicode ranges to use from this font
pub glyph_ranges: FontGlyphRanges,
/// Minimum advance_x for glyphs
pub glyph_min_advance_x: f32,
/// Maximum advance_x for glyphs
pub glyph_max_advance_x: f32,
/// Settings for a custom font rasterizer if used
pub font_builder_flags: u32,
/// Brighten (>1.0) or darken (<1.0) font output
pub rasterizer_multiply: f32,
/// Explicitly specify the ellipsis character.
///
/// With multiple font sources the first specified ellipsis is used.
pub ellipsis_char: Option<char>,
pub name: Option<String>,
}
impl Default for FontConfig {
fn default() -> FontConfig {
FontConfig {
size_pixels: 0.0,
oversample_h: 3,
oversample_v: 1,
pixel_snap_h: false,
glyph_extra_spacing: [0.0, 0.0],
glyph_offset: [0.0, 0.0],
glyph_ranges: FontGlyphRanges::default(),
glyph_min_advance_x: 0.0,
glyph_max_advance_x: f32::MAX,
font_builder_flags: 0,
rasterizer_multiply: 1.0,
ellipsis_char: None,
name: None,
}
}
}
impl FontConfig {
fn apply_to_raw_config(&self, raw: &mut sys::ImFontConfig, atlas: *mut sys::ImFontAtlas) {
raw.SizePixels = self.size_pixels;
raw.OversampleH = self.oversample_h;
raw.OversampleV = self.oversample_v;
raw.PixelSnapH = self.pixel_snap_h;
raw.GlyphExtraSpacing = self.glyph_extra_spacing.into();
raw.GlyphOffset = self.glyph_offset.into();
raw.GlyphRanges = unsafe { self.glyph_ranges.to_ptr(atlas) };
raw.GlyphMinAdvanceX = self.glyph_min_advance_x;
raw.GlyphMaxAdvanceX = self.glyph_max_advance_x;
raw.FontBuilderFlags = self.font_builder_flags;
raw.RasterizerMultiply = self.rasterizer_multiply;
// char is used as "unset" for EllipsisChar
raw.EllipsisChar = self.ellipsis_char.map(|c| c as u32).unwrap_or(!0);
if let Some(name) = self.name.as_ref() {
let bytes = name.as_bytes();
let mut len = bytes.len().min(raw.Name.len() - 1);
while !name.is_char_boundary(len) {
len -= 1;
}
unsafe {
bytes.as_ptr().copy_to(raw.Name.as_mut_ptr() as _, len);
raw.Name[len] = 0;
}
}
}
}
fn sys_font_config_default() -> sys::ImFontConfig {
unsafe {
let heap_allocated = sys::ImFontConfig_ImFontConfig();
let copy = *heap_allocated;
sys::ImFontConfig_destroy(heap_allocated);
copy
}
}
#[test]
fn test_font_config_default() {
let sys_font_config = sys_font_config_default();
let font_config = FontConfig::default();
assert_eq!(font_config.size_pixels, sys_font_config.SizePixels);
assert_eq!(font_config.oversample_h, sys_font_config.OversampleH);
assert_eq!(font_config.oversample_v, sys_font_config.OversampleV);
assert_eq!(font_config.pixel_snap_h, sys_font_config.PixelSnapH);
assert_eq!(
font_config.glyph_extra_spacing[0],
sys_font_config.GlyphExtraSpacing.x
);
assert_eq!(
font_config.glyph_extra_spacing[1],
sys_font_config.GlyphExtraSpacing.y
);
assert_eq!(font_config.glyph_offset[0], sys_font_config.GlyphOffset.x);
assert_eq!(font_config.glyph_offset[1], sys_font_config.GlyphOffset.y);
assert_eq!(
font_config.glyph_min_advance_x,
sys_font_config.GlyphMinAdvanceX
);
assert_eq!(
font_config.glyph_max_advance_x,
sys_font_config.GlyphMaxAdvanceX
);
assert_eq!(
font_config.font_builder_flags,
sys_font_config.FontBuilderFlags
);
assert_eq!(
font_config.rasterizer_multiply,
sys_font_config.RasterizerMultiply
);
}
/// Handle to a font atlas texture
#[derive(Clone, Debug)]
pub struct FontAtlasTexture<'a> {
/// Texture width (in pixels)
pub width: u32,
/// Texture height (in pixels)
pub height: u32,
/// Raw texture data (in bytes).
///
/// The format depends on which function was called to obtain this data.
pub data: &'a [u8],
}
/// A font atlas that can be shared between contexts
#[derive(Debug)]
pub struct SharedFontAtlas(pub(crate) *mut sys::ImFontAtlas);
impl SharedFontAtlas {
#[doc(alias = "ImFontAtlas", alias = "ImFontAtlas::ImFontAtlas")]
pub fn create() -> SharedFontAtlas {
SharedFontAtlas(unsafe { sys::ImFontAtlas_ImFontAtlas() })
}
}
impl Drop for SharedFontAtlas {
#[doc(alias = "ImFontAtlas::Destroy")]
fn drop(&mut self) {
unsafe { sys::ImFontAtlas_destroy(self.0) };
}
}
impl Deref for SharedFontAtlas {
type Target = FontAtlas;
fn deref(&self) -> &FontAtlas {
unsafe { &*(self.0 as *const FontAtlas) }
}
}
impl DerefMut for SharedFontAtlas {
fn deref_mut(&mut self) -> &mut FontAtlas {
unsafe { &mut *(self.0 as *mut FontAtlas) }
}
}
/// An immutably borrowed reference to a (possibly shared) font atlas
pub enum FontAtlasRef<'a> {
Owned(&'a FontAtlas),
Shared(&'a cell::RefMut<'a, SharedFontAtlas>),
}
impl<'a> Deref for FontAtlasRef<'a> {
type Target = FontAtlas;
fn deref(&self) -> &FontAtlas {
use self::FontAtlasRef::*;
match self {
Owned(atlas) => atlas,
Shared(cell) => cell,
}
}
}
/// A mutably borrowed reference to a (possibly shared) font atlas
pub enum FontAtlasRefMut<'a> {
Owned(&'a mut FontAtlas),
Shared(cell::RefMut<'a, SharedFontAtlas>),
}
impl<'a> Deref for FontAtlasRefMut<'a> {
type Target = FontAtlas;
fn deref(&self) -> &FontAtlas {
use self::FontAtlasRefMut::*;
match self {
Owned(atlas) => atlas,
Shared(cell) => cell,
}
}
}
impl<'a> DerefMut for FontAtlasRefMut<'a> {
fn deref_mut(&mut self) -> &mut FontAtlas {
use self::FontAtlasRefMut::*;
match self {
Owned(atlas) => atlas,
Shared(cell) => cell,
}
}
}

View File

@@ -1,71 +0,0 @@
use std::os::raw::c_int;
use crate::fonts::atlas::{FontAtlas, FontId};
use crate::fonts::glyph::FontGlyph;
use crate::internal::{ImVector, RawCast};
use crate::sys;
/// Runtime data for a single font within a font atlas
#[repr(C)]
pub struct Font {
index_advance_x: ImVector<f32>,
pub fallback_advance_x: f32,
pub font_size: f32,
index_lookup: ImVector<sys::ImWchar>,
glyphs: ImVector<FontGlyph>,
fallback_glyph: *const FontGlyph,
container_atlas: *mut FontAtlas,
config_data: *const sys::ImFontConfig,
pub config_data_count: i16,
pub fallback_char: sys::ImWchar,
pub ellipsis_char: sys::ImWchar,
pub dot_char: sys::ImWchar,
pub dirty_lookup_tables: bool,
pub scale: f32,
pub ascent: f32,
pub descent: f32,
pub metrics_total_surface: c_int,
pub used_4k_pages_map: [u8; 34],
}
unsafe impl RawCast<sys::ImFont> for Font {}
impl Font {
/// Returns the identifier of this font
pub fn id(&self) -> FontId {
FontId(self as *const _)
}
}
#[test]
fn test_font_memory_layout() {
use std::mem;
assert_eq!(mem::size_of::<Font>(), mem::size_of::<sys::ImFont>());
assert_eq!(mem::align_of::<Font>(), mem::align_of::<sys::ImFont>());
use sys::ImFont;
macro_rules! assert_field_offset {
($l:ident, $r:ident) => {
assert_eq!(
memoffset::offset_of!(Font, $l),
memoffset::offset_of!(ImFont, $r)
);
};
}
assert_field_offset!(index_advance_x, IndexAdvanceX);
assert_field_offset!(fallback_advance_x, FallbackAdvanceX);
assert_field_offset!(font_size, FontSize);
assert_field_offset!(index_lookup, IndexLookup);
assert_field_offset!(glyphs, Glyphs);
assert_field_offset!(fallback_glyph, FallbackGlyph);
assert_field_offset!(container_atlas, ContainerAtlas);
assert_field_offset!(config_data, ConfigData);
assert_field_offset!(config_data_count, ConfigDataCount);
assert_field_offset!(fallback_char, FallbackChar);
assert_field_offset!(ellipsis_char, EllipsisChar);
assert_field_offset!(dirty_lookup_tables, DirtyLookupTables);
assert_field_offset!(scale, Scale);
assert_field_offset!(ascent, Ascent);
assert_field_offset!(descent, Descent);
assert_field_offset!(metrics_total_surface, MetricsTotalSurface);
assert_field_offset!(used_4k_pages_map, Used4kPagesMap);
}

View File

@@ -1,67 +0,0 @@
use crate::internal::RawCast;
use crate::sys;
/// A single font glyph
#[derive(Copy, Clone, Debug, PartialEq)]
#[repr(C)]
pub struct FontGlyph {
bitfields: u32,
pub advance_x: f32,
pub x0: f32,
pub y0: f32,
pub x1: f32,
pub y1: f32,
pub u0: f32,
pub v0: f32,
pub u1: f32,
pub v1: f32,
}
impl FontGlyph {
pub fn codepoint(&self) -> u32 {
unsafe { self.raw().Codepoint() }
}
pub fn set_codepoint(&mut self, codepoint: u32) {
unsafe { self.raw_mut().set_Codepoint(codepoint) };
}
pub fn visible(&self) -> bool {
unsafe { self.raw().Visible() != 0 }
}
pub fn set_visible(&mut self, visible: bool) {
unsafe { self.raw_mut().set_Visible(visible as u32) }
}
}
unsafe impl RawCast<sys::ImFontGlyph> for FontGlyph {}
#[test]
fn test_font_glyph_memory_layout() {
use std::mem;
assert_eq!(
mem::size_of::<FontGlyph>(),
mem::size_of::<sys::ImFontGlyph>()
);
assert_eq!(
mem::align_of::<FontGlyph>(),
mem::align_of::<sys::ImFontGlyph>()
);
use sys::ImFontGlyph;
macro_rules! assert_field_offset {
($l:ident, $r:ident) => {
assert_eq!(
memoffset::offset_of!(FontGlyph, $l),
memoffset::offset_of!(ImFontGlyph, $r)
);
};
}
assert_field_offset!(bitfields, _bitfield_1);
assert_field_offset!(advance_x, AdvanceX);
assert_field_offset!(x0, X0);
assert_field_offset!(y0, Y0);
assert_field_offset!(x1, X1);
assert_field_offset!(y1, Y1);
assert_field_offset!(u0, U0);
assert_field_offset!(v0, V0);
assert_field_offset!(u1, U1);
assert_field_offset!(v1, V1);
}

View File

@@ -1,164 +0,0 @@
use crate::sys;
#[derive(Clone, Eq, PartialEq, Debug)]
enum FontGlyphRangeData {
ChineseSimplifiedCommon,
ChineseFull,
Cyrillic,
Default,
Japanese,
Korean,
Thai,
Vietnamese,
Custom(*const sys::ImWchar),
}
/// A set of Unicode codepoints
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct FontGlyphRanges(FontGlyphRangeData);
impl FontGlyphRanges {
/// The default set of glyph ranges used by imgui.
pub fn default() -> FontGlyphRanges {
FontGlyphRanges(FontGlyphRangeData::Default)
}
/// A set of glyph ranges appropriate for use with simplified common Chinese text.
pub fn chinese_simplified_common() -> FontGlyphRanges {
FontGlyphRanges(FontGlyphRangeData::ChineseSimplifiedCommon)
}
/// A set of glyph ranges appropriate for use with Chinese text.
pub fn chinese_full() -> FontGlyphRanges {
FontGlyphRanges(FontGlyphRangeData::ChineseFull)
}
/// A set of glyph ranges appropriate for use with Cyrillic text.
pub fn cyrillic() -> FontGlyphRanges {
FontGlyphRanges(FontGlyphRangeData::Cyrillic)
}
/// A set of glyph ranges appropriate for use with Japanese text.
pub fn japanese() -> FontGlyphRanges {
FontGlyphRanges(FontGlyphRangeData::Japanese)
}
/// A set of glyph ranges appropriate for use with Korean text.
pub fn korean() -> FontGlyphRanges {
FontGlyphRanges(FontGlyphRangeData::Korean)
}
/// A set of glyph ranges appropriate for use with Thai text.
pub fn thai() -> FontGlyphRanges {
FontGlyphRanges(FontGlyphRangeData::Thai)
}
/// A set of glyph ranges appropriate for use with Vietnamese text.
pub fn vietnamese() -> FontGlyphRanges {
FontGlyphRanges(FontGlyphRangeData::Vietnamese)
}
/// Creates a glyph range from a static slice. The expected format is a series of pairs of
/// non-zero codepoints, each representing an inclusive range, followed by a single
/// zero terminating the range. The ranges must not overlap.
///
/// As the slice is expected to last as long as a font is used, and is written into global
/// state, it must be `'static`.
///
/// Panics
/// ======
///
/// This function will panic if the given slice is not a valid font range.
// TODO(thom): This takes `u32` for now, since I believe it's fine for it to
// contain surrogates? (It seems plausible that font data can describe what
// to show for unpaired surrogates) Would be nice to be sure, if so, this
// should accept `char` (we'd still have to check that the range doesn't
// fully contain the surrogate range though)
pub fn from_slice(slice: &'static [u32]) -> FontGlyphRanges {
assert_eq!(
slice.len() % 2,
1,
"The length of a glyph range must be odd."
);
assert_eq!(
slice.last(),
Some(&0),
"A glyph range must be zero-terminated."
);
for (i, &glyph) in slice.iter().enumerate().take(slice.len() - 1) {
assert_ne!(
glyph, 0,
"A glyph in a range cannot be zero. \
(Glyph is zero at index {})",
i
);
assert!(
glyph <= core::char::MAX as u32,
"A glyph in a range cannot exceed the maximum codepoint. \
(Glyph is {:#x} at index {})",
glyph,
i,
);
}
let mut ranges = Vec::new();
for i in 0..slice.len() / 2 {
let (start, end) = (slice[i * 2], slice[i * 2 + 1]);
assert!(
start <= end,
"The start of a range cannot be larger than its end. \
(At index {}, {} > {})",
i * 2,
start,
end
);
ranges.push((start, end));
}
ranges.sort_unstable_by_key(|x| x.0);
for i in 0..ranges.len() - 1 {
let (range_a, range_b) = (ranges[i], ranges[i + 1]);
if range_a.1 >= range_b.0 {
panic!(
"The glyph ranges {:?} and {:?} overlap between {:?}.",
range_a,
range_b,
(range_a.1, range_b.0)
);
}
}
unsafe { FontGlyphRanges::from_slice_unchecked(slice) }
}
/// Creates a glyph range from a static slice without checking its validity.
///
/// See [`FontGlyphRanges::from_slice`] for more information.
///
/// # Safety
///
/// It is up to the caller to guarantee the slice contents are valid.
pub unsafe fn from_slice_unchecked(slice: &'static [u32]) -> FontGlyphRanges {
FontGlyphRanges::from_ptr(slice.as_ptr())
}
/// Creates a glyph range from a pointer, without checking its validity or enforcing its
/// lifetime. The memory the pointer points to must be valid for as long as the font is
/// in use.
///
/// # Safety
///
/// It is up to the caller to guarantee the pointer is not null, remains valid forever, and
/// points to valid data.
pub unsafe fn from_ptr(ptr: *const u32) -> FontGlyphRanges {
FontGlyphRanges(FontGlyphRangeData::Custom(ptr))
}
pub(crate) unsafe fn to_ptr(&self, atlas: *mut sys::ImFontAtlas) -> *const sys::ImWchar {
match self.0 {
FontGlyphRangeData::ChineseFull => sys::ImFontAtlas_GetGlyphRangesChineseFull(atlas),
FontGlyphRangeData::ChineseSimplifiedCommon => {
sys::ImFontAtlas_GetGlyphRangesChineseSimplifiedCommon(atlas)
}
FontGlyphRangeData::Cyrillic => sys::ImFontAtlas_GetGlyphRangesCyrillic(atlas),
FontGlyphRangeData::Default => sys::ImFontAtlas_GetGlyphRangesDefault(atlas),
FontGlyphRangeData::Japanese => sys::ImFontAtlas_GetGlyphRangesJapanese(atlas),
FontGlyphRangeData::Korean => sys::ImFontAtlas_GetGlyphRangesKorean(atlas),
FontGlyphRangeData::Thai => sys::ImFontAtlas_GetGlyphRangesThai(atlas),
FontGlyphRangeData::Vietnamese => sys::ImFontAtlas_GetGlyphRangesVietnamese(atlas),
FontGlyphRangeData::Custom(ptr) => ptr,
}
}
}

View File

@@ -1,36 +0,0 @@
use crate::fonts::font::Font;
use crate::internal::RawCast;
use crate::Ui;
pub mod atlas;
pub mod font;
pub mod glyph;
pub mod glyph_ranges;
/// # Fonts
impl<'ui> Ui<'ui> {
/// Returns the current font
#[doc(alias = "GetFont")]
pub fn current_font(&self) -> &Font {
unsafe { Font::from_raw(&*sys::igGetFont()) }
}
/// Returns the current font size (= height in pixels) with font scale applied
#[doc(alias = "GetFontSize")]
pub fn current_font_size(&self) -> f32 {
unsafe { sys::igGetFontSize() }
}
/// Returns the UV coordinate for a white pixel.
///
/// Useful for drawing custom shapes with the draw list API.
#[doc(alias = "FontTexUvWhitePixel")]
pub fn font_tex_uv_white_pixel(&self) -> [f32; 2] {
let mut out = sys::ImVec2::zero();
unsafe { sys::igGetFontTexUvWhitePixel(&mut out) };
out.into()
}
/// Sets the font scale of the current window
#[doc(alias = "SetWindowFontScale")]
pub fn set_window_font_scale(&self, scale: f32) {
unsafe { sys::igSetWindowFontScale(scale) }
}
}

View File

@@ -1,215 +0,0 @@
use crate::sys;
use crate::Ui;
/// A key identifier
#[repr(u32)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum Key {
Tab = sys::ImGuiKey_Tab,
LeftArrow = sys::ImGuiKey_LeftArrow,
RightArrow = sys::ImGuiKey_RightArrow,
UpArrow = sys::ImGuiKey_UpArrow,
DownArrow = sys::ImGuiKey_DownArrow,
PageUp = sys::ImGuiKey_PageUp,
PageDown = sys::ImGuiKey_PageDown,
Home = sys::ImGuiKey_Home,
End = sys::ImGuiKey_End,
Insert = sys::ImGuiKey_Insert,
Delete = sys::ImGuiKey_Delete,
Backspace = sys::ImGuiKey_Backspace,
Space = sys::ImGuiKey_Space,
Enter = sys::ImGuiKey_Enter,
Escape = sys::ImGuiKey_Escape,
KeyPadEnter = sys::ImGuiKey_KeyPadEnter,
A = sys::ImGuiKey_A,
C = sys::ImGuiKey_C,
V = sys::ImGuiKey_V,
X = sys::ImGuiKey_X,
Y = sys::ImGuiKey_Y,
Z = sys::ImGuiKey_Z,
}
impl Key {
/// All possible `Key` variants
pub const VARIANTS: [Key; Key::COUNT] = [
Key::Tab,
Key::LeftArrow,
Key::RightArrow,
Key::UpArrow,
Key::DownArrow,
Key::PageUp,
Key::PageDown,
Key::Home,
Key::End,
Key::Insert,
Key::Delete,
Key::Backspace,
Key::Space,
Key::Enter,
Key::Escape,
Key::KeyPadEnter,
Key::A,
Key::C,
Key::V,
Key::X,
Key::Y,
Key::Z,
];
/// Total count of `Key` variants
pub const COUNT: usize = sys::ImGuiKey_COUNT as usize;
}
#[test]
fn test_key_variants() {
for (idx, &value) in Key::VARIANTS.iter().enumerate() {
assert_eq!(idx, value as usize);
}
}
/// Target widget selection for keyboard focus
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum FocusedWidget {
/// Previous widget
Previous,
/// Next widget
Next,
/// Widget using a relative positive offset (0 is the next widget).
///
/// Use this to access sub components of a multiple component widget.
Offset(u32),
}
impl FocusedWidget {
#[inline]
fn as_offset(self) -> i32 {
match self {
FocusedWidget::Previous => -1,
FocusedWidget::Next => 0,
FocusedWidget::Offset(offset) => offset as i32,
}
}
}
/// # Input: Keyboard
impl<'ui> Ui<'ui> {
/// Returns the key index of the given key identifier.
///
/// Equivalent to indexing the Io struct `key_map` field: `ui.io().key_map[key]`
#[inline]
#[doc(alias = "GetKeyIndex")]
fn key_index(&self, key: Key) -> i32 {
unsafe { sys::igGetKeyIndex(key as i32) }
}
/// Returns true if the key is being held.
///
/// Equivalent to indexing the Io struct `keys_down` field: `ui.io().keys_down[key_index]`
#[inline]
#[doc(alias = "IsKeyDown")]
pub fn is_key_down(&self, key: Key) -> bool {
let key_index = self.key_index(key);
self.is_key_index_down(key_index)
}
/// Same as [`is_key_down`](Self::is_key_down) but takes a key index. The meaning of
/// index is defined by your backend implementation.
#[inline]
#[doc(alias = "IsKeyDown")]
pub fn is_key_index_down(&self, key_index: i32) -> bool {
unsafe { sys::igIsKeyDown(key_index) }
}
/// Returns true if the key was pressed (went from !down to down).
///
/// Affected by key repeat settings (`io.key_repeat_delay`, `io.key_repeat_rate`)
#[inline]
#[doc(alias = "IsKeyPressed")]
pub fn is_key_pressed(&self, key: Key) -> bool {
let key_index = self.key_index(key);
self.is_key_index_pressed(key_index)
}
/// Same as [`is_key_pressed`](Self::is_key_pressed) but takes a key index.
///
/// The meaning of index is defined by your backend
/// implementation.
#[inline]
#[doc(alias = "IsKeyPressed")]
pub fn is_key_index_pressed(&self, key_index: i32) -> bool {
unsafe { sys::igIsKeyPressed(key_index, true) }
}
/// Returns true if the key was pressed (went from !down to down).
///
/// Is **not** affected by key repeat settings (`io.key_repeat_delay`, `io.key_repeat_rate`)
#[inline]
#[doc(alias = "IsKeyPressed")]
pub fn is_key_pressed_no_repeat(&self, key: Key) -> bool {
let key_index = self.key_index(key);
self.is_key_index_pressed_no_repeat(key_index)
}
/// Same as [`is_key_pressed_no_repeat`](Self::is_key_pressed_no_repeat)
/// but takes a key index.
///
/// The meaning of index is defined by your backend
/// implementation.
#[inline]
#[doc(alias = "IsKeyPressed")]
pub fn is_key_index_pressed_no_repeat(&self, key_index: i32) -> bool {
unsafe { sys::igIsKeyPressed(key_index, false) }
}
/// Returns true if the key was released (went from down to !down)
#[inline]
#[doc(alias = "IsKeyReleased")]
pub fn is_key_released(&self, key: Key) -> bool {
let key_index = self.key_index(key);
self.is_key_index_released(key_index)
}
/// Same as [`is_key_released`](Self::is_key_released) but takes a key index.
///
/// The meaning of index is defined by your backend
/// implementation.
#[inline]
#[doc(alias = "IsKeyReleased")]
pub fn is_key_index_released(&self, key_index: i32) -> bool {
unsafe { sys::igIsKeyReleased(key_index) }
}
/// Returns a count of key presses using the given repeat rate/delay settings.
///
/// Usually returns 0 or 1, but might be >1 if `rate` is small enough that `io.delta_time` >
/// `rate`.
#[inline]
#[doc(alias = "GetKeyPressedAmount")]
pub fn key_pressed_amount(&self, key: Key, repeat_delay: f32, rate: f32) -> u32 {
let key_index = self.key_index(key);
self.key_index_pressed_amount(key_index, repeat_delay, rate)
}
#[inline]
#[doc(alias = "GetKeyPressedAmount")]
pub fn key_index_pressed_amount(&self, key_index: i32, repeat_delay: f32, rate: f32) -> u32 {
unsafe { sys::igGetKeyPressedAmount(key_index, repeat_delay, rate) as u32 }
}
/// Focuses keyboard on the next widget.
///
/// This is the equivalent to [set_keyboard_focus_here_with_offset](Self::set_keyboard_focus_here_with_offset)
/// with `target_widget` set to `FocusedWidget::Next`.
#[inline]
#[doc(alias = "SetKeyboardFocusHere")]
pub fn set_keyboard_focus_here(&self) {
self.set_keyboard_focus_here_with_offset(FocusedWidget::Next);
}
/// Focuses keyboard on a widget relative to current position.
#[inline]
#[doc(alias = "SetKeyboardFocusHere")]
pub fn set_keyboard_focus_here_with_offset(&self, target_widget: FocusedWidget) {
unsafe {
sys::igSetKeyboardFocusHere(target_widget.as_offset());
}
}
}

View File

@@ -1,2 +0,0 @@
pub mod keyboard;
pub mod mouse;

View File

@@ -1,478 +0,0 @@
use std::ptr;
use crate::sys;
use crate::Ui;
/// Represents one of the supported mouse buttons
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum MouseButton {
Left = 0,
Right = 1,
Middle = 2,
Extra1 = 3,
Extra2 = 4,
}
impl MouseButton {
/// All possible `MouseButton` variants
pub const VARIANTS: [MouseButton; MouseButton::COUNT] = [
MouseButton::Left,
MouseButton::Right,
MouseButton::Middle,
MouseButton::Extra1,
MouseButton::Extra2,
];
/// Total count of `MouseButton` variants
pub const COUNT: usize = 5;
}
#[test]
fn test_mouse_button_variants() {
for (idx, &value) in MouseButton::VARIANTS.iter().enumerate() {
assert_eq!(idx, value as usize);
}
}
/// Mouse cursor type identifier
#[repr(i32)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
// TODO: this should just be `#[allow(clippy::upper_case_acronyms)]`, but doing
// so in a way that works before it stabilizes is a pain (in part because
// `unknown_clippy_lints` was renamed to unknown_lints). Oh well, it's over a
// small amount of code.
#[allow(warnings)]
pub enum MouseCursor {
Arrow = sys::ImGuiMouseCursor_Arrow,
/// Automatically used when hovering over text inputs, etc.
TextInput = sys::ImGuiMouseCursor_TextInput,
/// Not used automatically
ResizeAll = sys::ImGuiMouseCursor_ResizeAll,
/// Automatically used when hovering over a horizontal border
ResizeNS = sys::ImGuiMouseCursor_ResizeNS,
/// Automatically used when hovering over a vertical border or a column
ResizeEW = sys::ImGuiMouseCursor_ResizeEW,
/// Automatically used when hovering over the bottom-left corner of a window
ResizeNESW = sys::ImGuiMouseCursor_ResizeNESW,
/// Automatically used when hovering over the bottom-right corner of a window
ResizeNWSE = sys::ImGuiMouseCursor_ResizeNWSE,
/// Not used automatically, use for e.g. hyperlinks
Hand = sys::ImGuiMouseCursor_Hand,
/// When hovering something with disallowed interactions.
///
/// Usually a crossed circle.
NotAllowed = sys::ImGuiMouseCursor_NotAllowed,
}
impl MouseCursor {
/// All possible `MouseCursor` variants
pub const VARIANTS: [MouseCursor; MouseCursor::COUNT] = [
MouseCursor::Arrow,
MouseCursor::TextInput,
MouseCursor::ResizeAll,
MouseCursor::ResizeNS,
MouseCursor::ResizeEW,
MouseCursor::ResizeNESW,
MouseCursor::ResizeNWSE,
MouseCursor::Hand,
MouseCursor::NotAllowed,
];
/// Total count of `MouseCursor` variants
pub const COUNT: usize = sys::ImGuiMouseCursor_COUNT as usize;
}
#[test]
fn test_mouse_cursor_variants() {
for (idx, &value) in MouseCursor::VARIANTS.iter().enumerate() {
assert_eq!(idx, value as usize);
}
}
/// # Input: Mouse
impl<'ui> Ui<'ui> {
/// Returns true if the given mouse button is held down.
///
/// Equivalent to indexing the Io struct with the button, e.g. `ui.io()[button]`.
#[doc(alias = "IsMouseDown")]
pub fn is_mouse_down(&self, button: MouseButton) -> bool {
unsafe { sys::igIsMouseDown(button as i32) }
}
/// Returns true if any mouse button is held down
#[doc(alias = "IsAnyMouseDown")]
pub fn is_any_mouse_down(&self) -> bool {
unsafe { sys::igIsAnyMouseDown() }
}
/// Returns true if the given mouse button was clicked (went from !down to down)
#[doc(alias = "IsMouseClicked")]
pub fn is_mouse_clicked(&self, button: MouseButton) -> bool {
unsafe { sys::igIsMouseClicked(button as i32, false) }
}
/// Returns true if the given mouse button was double-clicked
#[doc(alias = "IsMouseDoubleClicked")]
pub fn is_mouse_double_clicked(&self, button: MouseButton) -> bool {
unsafe { sys::igIsMouseDoubleClicked(button as i32) }
}
/// Returns true if the given mouse button was released (went from down to !down)
#[doc(alias = "IsMouseReleased")]
pub fn is_mouse_released(&self, button: MouseButton) -> bool {
unsafe { sys::igIsMouseReleased(button as i32) }
}
/// Returns true if the mouse is currently dragging with the given mouse button held down
#[doc(alias = "IsMouseDragging")]
pub fn is_mouse_dragging(&self, button: MouseButton) -> bool {
unsafe { sys::igIsMouseDragging(button as i32, -1.0) }
}
/// Returns true if the mouse is currently dragging with the given mouse button held down.
///
/// If the given threshold is invalid or negative, the global distance threshold is used
/// (`io.mouse_drag_threshold`).
#[doc(alias = "IsMouseDragging")]
pub fn is_mouse_dragging_with_threshold(&self, button: MouseButton, threshold: f32) -> bool {
unsafe { sys::igIsMouseDragging(button as i32, threshold) }
}
/// Returns true if the mouse is hovering over the given bounding rect.
///
/// Clipped by current clipping settings, but disregards other factors like focus, window
/// ordering, modal popup blocking.
pub fn is_mouse_hovering_rect(&self, r_min: [f32; 2], r_max: [f32; 2]) -> bool {
unsafe { sys::igIsMouseHoveringRect(r_min.into(), r_max.into(), true) }
}
/// Returns the mouse position backed up at the time of opening a popup
#[doc(alias = "GetMousePosOnOpeningCurrentPopup")]
pub fn mouse_pos_on_opening_current_popup(&self) -> [f32; 2] {
let mut out = sys::ImVec2::zero();
unsafe { sys::igGetMousePosOnOpeningCurrentPopup(&mut out) };
out.into()
}
/// Returns the delta from the initial position when the left mouse button clicked.
///
/// This is locked and returns [0.0, 0.0] until the mouse has moved past the global distance
/// threshold (`io.mouse_drag_threshold`).
///
/// This is the same as [mouse_drag_delta_with_button](Self::mouse_drag_delta_with_button) with
/// `button` set to `MouseButton::Left`.
#[doc(alias = "GetMouseDragDelta")]
pub fn mouse_drag_delta(&self) -> [f32; 2] {
self.mouse_drag_delta_with_button(MouseButton::Left)
}
/// Returns the delta from the initial position when the given button was clicked.
///
/// This is locked and returns [0.0, 0.0] until the mouse has moved past the global distance
/// threshold (`io.mouse_drag_threshold`).
///
/// This is the same as [mouse_drag_delta_with_threshold](Self::mouse_drag_delta_with_threshold) with
/// `threshold` set to `-1.0`, which uses the global threshold `io.mouse_drag_threshold`.
#[doc(alias = "GetMouseDragDelta")]
pub fn mouse_drag_delta_with_button(&self, button: MouseButton) -> [f32; 2] {
self.mouse_drag_delta_with_threshold(button, -1.0)
}
/// Returns the delta from the initial clicking position.
///
/// This is locked and returns [0.0, 0.0] until the mouse has moved past the given threshold.
/// If the given threshold is invalid or negative, the global distance threshold is used
/// (`io.mouse_drag_threshold`).
#[doc(alias = "GetMouseDragDelta")]
pub fn mouse_drag_delta_with_threshold(&self, button: MouseButton, threshold: f32) -> [f32; 2] {
let mut out = sys::ImVec2::zero();
unsafe { sys::igGetMouseDragDelta(&mut out, button as i32, threshold) };
out.into()
}
/// Resets the current delta from initial clicking position.
#[doc(alias = "ResetMouseDragDelta")]
pub fn reset_mouse_drag_delta(&self, button: MouseButton) {
// This mutates the Io struct, but targets an internal field so there can't be any
// references to it
unsafe { sys::igResetMouseDragDelta(button as i32) }
}
/// Returns the currently desired mouse cursor type.
///
/// Returns `None` if no cursor should be displayed
#[doc(alias = "GetMouseCursor")]
pub fn mouse_cursor(&self) -> Option<MouseCursor> {
match unsafe { sys::igGetMouseCursor() } {
sys::ImGuiMouseCursor_Arrow => Some(MouseCursor::Arrow),
sys::ImGuiMouseCursor_TextInput => Some(MouseCursor::TextInput),
sys::ImGuiMouseCursor_ResizeAll => Some(MouseCursor::ResizeAll),
sys::ImGuiMouseCursor_ResizeNS => Some(MouseCursor::ResizeNS),
sys::ImGuiMouseCursor_ResizeEW => Some(MouseCursor::ResizeEW),
sys::ImGuiMouseCursor_ResizeNESW => Some(MouseCursor::ResizeNESW),
sys::ImGuiMouseCursor_ResizeNWSE => Some(MouseCursor::ResizeNWSE),
sys::ImGuiMouseCursor_Hand => Some(MouseCursor::Hand),
sys::ImGuiMouseCursor_NotAllowed => Some(MouseCursor::NotAllowed),
_ => None,
}
}
/// Sets the desired mouse cursor type.
///
/// Passing `None` hides the mouse cursor.
#[doc(alias = "SetMouseCursor")]
pub fn set_mouse_cursor(&self, cursor_type: Option<MouseCursor>) {
unsafe {
sys::igSetMouseCursor(
cursor_type
.map(|x| x as i32)
.unwrap_or(sys::ImGuiMouseCursor_None),
);
}
}
#[doc(alias = "IsMousePosValid")]
pub fn is_current_mouse_pos_valid(&self) -> bool {
unsafe { sys::igIsMousePosValid(ptr::null()) }
}
#[doc(alias = "IsMousePosValid")]
pub fn is_mouse_pos_valid(&self, mouse_pos: [f32; 2]) -> bool {
unsafe { sys::igIsMousePosValid(&mouse_pos.into()) }
}
}
#[test]
fn test_mouse_down_clicked_released() {
for &button in MouseButton::VARIANTS.iter() {
let (_guard, mut ctx) = crate::test::test_ctx_initialized();
{
ctx.io_mut().mouse_down = [false; 5];
let ui = ctx.frame();
assert!(!ui.is_mouse_down(button));
assert!(!ui.is_any_mouse_down());
assert!(!ui.is_mouse_clicked(button));
assert!(!ui.is_mouse_released(button));
}
{
ctx.io_mut()[button] = true;
let ui = ctx.frame();
assert!(ui.is_mouse_down(button));
assert!(ui.is_any_mouse_down());
assert!(ui.is_mouse_clicked(button));
assert!(!ui.is_mouse_released(button));
}
{
let ui = ctx.frame();
assert!(ui.is_mouse_down(button));
assert!(ui.is_any_mouse_down());
assert!(!ui.is_mouse_clicked(button));
assert!(!ui.is_mouse_released(button));
}
{
ctx.io_mut()[button] = false;
let ui = ctx.frame();
assert!(!ui.is_mouse_down(button));
assert!(!ui.is_any_mouse_down());
assert!(!ui.is_mouse_clicked(button));
assert!(ui.is_mouse_released(button));
}
{
let ui = ctx.frame();
assert!(!ui.is_mouse_down(button));
assert!(!ui.is_any_mouse_down());
assert!(!ui.is_mouse_clicked(button));
assert!(!ui.is_mouse_released(button));
}
}
}
#[test]
fn test_mouse_double_click() {
let (_guard, mut ctx) = crate::test::test_ctx_initialized();
// Workaround for dear imgui bug/feature:
// If a button is clicked before io.mouse_double_click_time seconds has passed after the
// context is initialized, the single click is interpreted as a double-click. This happens
// because internally g.IO.MouseClickedTime is set to 0.0, so the context creation is
// considered a "click".
{
// Pass one second of time
ctx.io_mut().delta_time = 1.0;
let _ = ctx.frame();
}
// Fast clicks
ctx.io_mut().delta_time = 1.0 / 60.0;
for &button in MouseButton::VARIANTS.iter() {
{
ctx.io_mut().mouse_down = [false; 5];
let ui = ctx.frame();
assert!(!ui.is_mouse_clicked(button));
assert!(!ui.is_mouse_double_clicked(button));
}
{
ctx.io_mut()[button] = true;
let ui = ctx.frame();
assert!(ui.is_mouse_clicked(button));
assert!(!ui.is_mouse_double_clicked(button));
}
{
let ui = ctx.frame();
assert!(!ui.is_mouse_clicked(button));
assert!(!ui.is_mouse_double_clicked(button));
}
{
ctx.io_mut()[button] = false;
let ui = ctx.frame();
assert!(!ui.is_mouse_clicked(button));
assert!(!ui.is_mouse_double_clicked(button));
}
{
ctx.io_mut()[button] = true;
let ui = ctx.frame();
assert!(ui.is_mouse_clicked(button));
assert!(ui.is_mouse_double_clicked(button));
}
{
let ui = ctx.frame();
assert!(!ui.is_mouse_clicked(button));
assert!(!ui.is_mouse_double_clicked(button));
}
}
// Slow clicks
ctx.io_mut().delta_time = 1.0;
for &button in MouseButton::VARIANTS.iter() {
{
ctx.io_mut().mouse_down = [false; 5];
let ui = ctx.frame();
assert!(!ui.is_mouse_clicked(button));
assert!(!ui.is_mouse_double_clicked(button));
}
{
ctx.io_mut()[button] = true;
let ui = ctx.frame();
assert!(ui.is_mouse_clicked(button));
assert!(!ui.is_mouse_double_clicked(button));
}
{
let ui = ctx.frame();
assert!(!ui.is_mouse_clicked(button));
assert!(!ui.is_mouse_double_clicked(button));
}
{
ctx.io_mut()[button] = false;
let ui = ctx.frame();
assert!(!ui.is_mouse_clicked(button));
assert!(!ui.is_mouse_double_clicked(button));
}
{
ctx.io_mut()[button] = true;
let ui = ctx.frame();
assert!(ui.is_mouse_clicked(button));
assert!(!ui.is_mouse_double_clicked(button));
}
{
let ui = ctx.frame();
assert!(!ui.is_mouse_clicked(button));
assert!(!ui.is_mouse_double_clicked(button));
}
}
}
#[test]
fn test_set_get_mouse_cursor() {
let (_guard, mut ctx) = crate::test::test_ctx_initialized();
let ui = ctx.frame();
ui.set_mouse_cursor(None);
assert_eq!(None, ui.mouse_cursor());
ui.set_mouse_cursor(Some(MouseCursor::Hand));
assert_eq!(Some(MouseCursor::Hand), ui.mouse_cursor());
}
#[test]
fn test_mouse_drags() {
for &button in MouseButton::VARIANTS.iter() {
let (_guard, mut ctx) = crate::test::test_ctx_initialized();
{
ctx.io_mut().mouse_pos = [0.0, 0.0];
ctx.io_mut().mouse_down = [false; 5];
let ui = ctx.frame();
assert!(!ui.is_mouse_dragging(button));
assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0));
assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 0.0]);
assert_eq!(
ui.mouse_drag_delta_with_threshold(button, 200.0),
[0.0, 0.0]
);
}
{
ctx.io_mut()[button] = true;
let ui = ctx.frame();
assert!(!ui.is_mouse_dragging(button));
assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0));
assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 0.0]);
assert_eq!(
ui.mouse_drag_delta_with_threshold(button, 200.0),
[0.0, 0.0]
);
}
{
ctx.io_mut().mouse_pos = [0.0, 100.0];
let ui = ctx.frame();
assert!(ui.is_mouse_dragging(button));
assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0));
assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 100.0]);
assert_eq!(
ui.mouse_drag_delta_with_threshold(button, 200.0),
[0.0, 0.0]
);
}
{
ctx.io_mut().mouse_pos = [0.0, 200.0];
let ui = ctx.frame();
assert!(ui.is_mouse_dragging(button));
assert!(ui.is_mouse_dragging_with_threshold(button, 200.0));
assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 200.0]);
assert_eq!(
ui.mouse_drag_delta_with_threshold(button, 200.0),
[0.0, 200.0]
);
}
{
ctx.io_mut().mouse_pos = [10.0, 10.0];
ctx.io_mut()[button] = false;
let ui = ctx.frame();
assert!(!ui.is_mouse_dragging(button));
assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0));
assert_eq!(ui.mouse_drag_delta_with_button(button), [10.0, 10.0]);
assert_eq!(
ui.mouse_drag_delta_with_threshold(button, 200.0),
[10.0, 10.0]
);
}
{
ctx.io_mut()[button] = true;
let ui = ctx.frame();
assert!(!ui.is_mouse_dragging(button));
assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0));
assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 0.0]);
assert_eq!(
ui.mouse_drag_delta_with_threshold(button, 200.0),
[0.0, 0.0]
);
}
{
ctx.io_mut().mouse_pos = [180.0, 180.0];
let ui = ctx.frame();
assert!(ui.is_mouse_dragging(button));
assert!(ui.is_mouse_dragging_with_threshold(button, 200.0));
assert_eq!(ui.mouse_drag_delta_with_button(button), [170.0, 170.0]);
assert_eq!(
ui.mouse_drag_delta_with_threshold(button, 200.0),
[170.0, 170.0]
);
ui.reset_mouse_drag_delta(button);
assert!(ui.is_mouse_dragging(button));
assert!(ui.is_mouse_dragging_with_threshold(button, 200.0));
assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 0.0]);
assert_eq!(
ui.mouse_drag_delta_with_threshold(button, 200.0),
[0.0, 0.0]
);
}
{
ctx.io_mut().mouse_pos = [200.0, 200.0];
let ui = ctx.frame();
assert!(ui.is_mouse_dragging(button));
assert!(ui.is_mouse_dragging_with_threshold(button, 200.0));
assert_eq!(ui.mouse_drag_delta_with_button(button), [20.0, 20.0]);
assert_eq!(
ui.mouse_drag_delta_with_threshold(button, 200.0),
[20.0, 20.0]
);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,159 +0,0 @@
//! Internal raw utilities (don't use unless you know what you're doing!)
use std::slice;
/// A generic version of the raw imgui-sys ImVector struct types
#[repr(C)]
pub struct ImVector<T> {
size: i32,
capacity: i32,
pub(crate) data: *mut T,
}
impl<T> ImVector<T> {
#[inline]
pub fn as_slice(&self) -> &[T] {
unsafe { slice::from_raw_parts(self.data, self.size as usize) }
}
}
#[test]
#[cfg(test)]
fn test_imvector_memory_layout() {
use std::mem;
assert_eq!(
mem::size_of::<ImVector<u8>>(),
mem::size_of::<sys::ImVector_char>()
);
assert_eq!(
mem::align_of::<ImVector<u8>>(),
mem::align_of::<sys::ImVector_char>()
);
use sys::ImVector_char;
type VectorChar = ImVector<u8>;
macro_rules! assert_field_offset {
($l:ident, $r:ident) => {
assert_eq!(
memoffset::offset_of!(VectorChar, $l),
memoffset::offset_of!(ImVector_char, $r)
);
};
}
assert_field_offset!(size, Size);
assert_field_offset!(capacity, Capacity);
assert_field_offset!(data, Data);
}
/// Marks a type as a transparent wrapper over a raw type
pub trait RawWrapper {
/// Wrapped raw type
type Raw;
/// Returns an immutable reference to the wrapped raw value
///
/// # Safety
///
/// It is up to the caller to use the returned raw reference without causing undefined
/// behaviour or breaking safety rules.
unsafe fn raw(&self) -> &Self::Raw;
/// Returns a mutable reference to the wrapped raw value
///
/// # Safety
///
/// It is up to the caller to use the returned mutable raw reference without causing undefined
/// behaviour or breaking safety rules.
unsafe fn raw_mut(&mut self) -> &mut Self::Raw;
}
/// Casting from/to a raw type that has the same layout and alignment as the target type
pub unsafe trait RawCast<T>: Sized {
/// Casts an immutable reference from the raw type
///
/// # Safety
///
/// It is up to the caller to guarantee the cast is valid.
#[inline]
unsafe fn from_raw(raw: &T) -> &Self {
&*(raw as *const _ as *const Self)
}
/// Casts a mutable reference from the raw type
///
/// # Safety
///
/// It is up to the caller to guarantee the cast is valid.
#[inline]
unsafe fn from_raw_mut(raw: &mut T) -> &mut Self {
&mut *(raw as *mut _ as *mut Self)
}
/// Casts an immutable reference to the raw type
///
/// # Safety
///
/// It is up to the caller to guarantee the cast is valid.
#[inline]
unsafe fn raw(&self) -> &T {
&*(self as *const _ as *const T)
}
/// Casts a mutable reference to the raw type
///
/// # Safety
///
/// It is up to the caller to guarantee the cast is valid.
#[inline]
unsafe fn raw_mut(&mut self) -> &mut T {
&mut *(self as *mut _ as *mut T)
}
}
/// A primary data type
#[repr(u32)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum DataType {
I8 = sys::ImGuiDataType_S8,
U8 = sys::ImGuiDataType_U8,
I16 = sys::ImGuiDataType_S16,
U16 = sys::ImGuiDataType_U16,
I32 = sys::ImGuiDataType_S32,
U32 = sys::ImGuiDataType_U32,
I64 = sys::ImGuiDataType_S64,
U64 = sys::ImGuiDataType_U64,
F32 = sys::ImGuiDataType_Float,
F64 = sys::ImGuiDataType_Double,
}
/// Primitive type marker.
///
/// If this trait is implemented for a type, it is assumed to have *exactly* the same
/// representation in memory as the primitive value described by the associated `KIND` constant.
pub unsafe trait DataTypeKind: Copy {
const KIND: DataType;
}
unsafe impl DataTypeKind for i8 {
const KIND: DataType = DataType::I8;
}
unsafe impl DataTypeKind for u8 {
const KIND: DataType = DataType::U8;
}
unsafe impl DataTypeKind for i16 {
const KIND: DataType = DataType::I16;
}
unsafe impl DataTypeKind for u16 {
const KIND: DataType = DataType::U16;
}
unsafe impl DataTypeKind for i32 {
const KIND: DataType = DataType::I32;
}
unsafe impl DataTypeKind for u32 {
const KIND: DataType = DataType::U32;
}
unsafe impl DataTypeKind for i64 {
const KIND: DataType = DataType::I64;
}
unsafe impl DataTypeKind for u64 {
const KIND: DataType = DataType::U64;
}
unsafe impl DataTypeKind for f32 {
const KIND: DataType = DataType::F32;
}
unsafe impl DataTypeKind for f64 {
const KIND: DataType = DataType::F64;
}

View File

@@ -1,506 +0,0 @@
use bitflags::bitflags;
use std::f32;
use std::ops::{Index, IndexMut};
use std::os::raw::{c_char, c_int, c_void};
use std::time::Duration;
use crate::fonts::atlas::FontAtlas;
use crate::fonts::font::Font;
use crate::input::keyboard::Key;
use crate::input::mouse::MouseButton;
use crate::internal::{ImVector, RawCast};
use crate::sys;
bitflags! {
/// Configuration flags
#[repr(transparent)]
pub struct ConfigFlags: u32 {
/// Master keyboard navigation enable flag.
///
/// `frame()` will automatically fill `io.nav_inputs` based on `io.keys_down`.
const NAV_ENABLE_KEYBOARD = sys::ImGuiConfigFlags_NavEnableKeyboard;
/// Master gamepad navigation enable flag.
///
/// This is mostly to instruct the backend to fill `io.nav_inputs`. The backend
/// also needs to set `BackendFlags::HasGamepad`.
const NAV_ENABLE_GAMEPAD = sys::ImGuiConfigFlags_NavEnableGamepad;
/// Instruction navigation to move the mouse cursor.
///
/// May be useful on TV/console systems where moving a virtual mouse is awkward.
/// Will update `io.mouse_pos` and set `io.want_set_mouse_pos = true`. If enabled,
/// you *must* honor `io.want_set_mouse_pos`, or imgui-rs will react as if the mouse is
/// jumping around back and forth.
const NAV_ENABLE_SET_MOUSE_POS = sys::ImGuiConfigFlags_NavEnableSetMousePos;
/// Instruction navigation to not set the `io.want_capture_keyboard` flag when
/// `io.nav_active` is set.
const NAV_NO_CAPTURE_KEYBOARD = sys::ImGuiConfigFlags_NavNoCaptureKeyboard;
/// Instruction imgui-rs to clear mouse position/buttons in `frame()`.
///
/// This allows ignoring the mouse information set by the backend.
const NO_MOUSE = sys::ImGuiConfigFlags_NoMouse;
/// Instruction backend to not alter mouse cursor shape and visibility.
///
/// Use if the backend cursor changes are interfering with yours and you don't want to use
/// `set_mouse_cursor` to change the mouse cursor. You may want to honor requests from
/// imgui-rs by reading `get_mouse_cursor` yourself instead.
const NO_MOUSE_CURSOR_CHANGE = sys::ImGuiConfigFlags_NoMouseCursorChange;
/// Application is SRGB-aware.
///
/// Not used by core imgui-rs.
const IS_SRGB = sys::ImGuiConfigFlags_IsSRGB;
/// Application is using a touch screen instead of a mouse.
///
/// Not used by core imgui-rs.
const IS_TOUCH_SCREEN = sys::ImGuiConfigFlags_IsTouchScreen;
}
}
bitflags! {
/// Backend capabilities
#[repr(transparent)]
pub struct BackendFlags: u32 {
/// Backend supports gamepad and currently has one connected
const HAS_GAMEPAD = sys::ImGuiBackendFlags_HasGamepad;
/// Backend supports honoring `get_mouse_cursor` value to change the OS cursor shape
const HAS_MOUSE_CURSORS = sys::ImGuiBackendFlags_HasMouseCursors;
/// Backend supports `io.want_set_mouse_pos` requests to reposition the OS mouse position.
///
/// Only used if `ConfigFlags::NavEnableSetMousePos` is set.
const HAS_SET_MOUSE_POS = sys::ImGuiBackendFlags_HasSetMousePos;
/// Backend renderer supports DrawCmd::vtx_offset.
///
/// This enables output of large meshes (64K+ vertices) while still using 16-bits indices.
const RENDERER_HAS_VTX_OFFSET = sys::ImGuiBackendFlags_RendererHasVtxOffset;
}
}
/// An input identifier for navigation
#[repr(u32)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum NavInput {
Activate = sys::ImGuiNavInput_Activate,
Cancel = sys::ImGuiNavInput_Cancel,
Input = sys::ImGuiNavInput_Input,
Menu = sys::ImGuiNavInput_Menu,
DpadLeft = sys::ImGuiNavInput_DpadLeft,
DpadRight = sys::ImGuiNavInput_DpadRight,
DpadUp = sys::ImGuiNavInput_DpadUp,
DpadDown = sys::ImGuiNavInput_DpadDown,
LStickLeft = sys::ImGuiNavInput_LStickLeft,
LStickRight = sys::ImGuiNavInput_LStickRight,
LStickUp = sys::ImGuiNavInput_LStickUp,
LStickDown = sys::ImGuiNavInput_LStickDown,
FocusPrev = sys::ImGuiNavInput_FocusPrev,
FocusNext = sys::ImGuiNavInput_FocusNext,
TweakSlow = sys::ImGuiNavInput_TweakSlow,
TweakFast = sys::ImGuiNavInput_TweakFast,
}
impl NavInput {
/// All possible `NavInput` variants
pub const VARIANTS: [NavInput; NavInput::COUNT] = [
NavInput::Activate,
NavInput::Cancel,
NavInput::Input,
NavInput::Menu,
NavInput::DpadLeft,
NavInput::DpadRight,
NavInput::DpadUp,
NavInput::DpadDown,
NavInput::LStickLeft,
NavInput::LStickRight,
NavInput::LStickUp,
NavInput::LStickDown,
NavInput::FocusPrev,
NavInput::FocusNext,
NavInput::TweakSlow,
NavInput::TweakFast,
];
/// Amount of internal/hidden variants (not exposed by imgui-rs)
const INTERNAL_COUNT: usize = 4;
/// Total count of `NavInput` variants
pub const COUNT: usize = sys::ImGuiNavInput_COUNT as usize - NavInput::INTERNAL_COUNT;
}
#[test]
fn test_nav_input_variants() {
for (idx, &value) in NavInput::VARIANTS.iter().enumerate() {
assert_eq!(idx, value as usize);
}
}
/// Settings and inputs/outputs for imgui-rs
#[repr(C)]
pub struct Io {
/// Flags set by user/application
pub config_flags: ConfigFlags,
/// Flags set by backend
pub backend_flags: BackendFlags,
/// Main display size in pixels
pub display_size: [f32; 2],
/// Time elapsed since last frame, in seconds
pub delta_time: f32,
/// Minimum time between saving positions/sizes to .ini file, in seconds
pub ini_saving_rate: f32,
pub(crate) ini_filename: *const c_char,
pub(crate) log_filename: *const c_char,
/// Time for a double-click, in seconds
pub mouse_double_click_time: f32,
/// Distance threshold to stay in to validate a double-click, in pixels
pub mouse_double_click_max_dist: f32,
/// Distance threshold before considering we are dragging
pub mouse_drag_threshold: f32,
/// Map of indices into the `keys_down` entries array, which represent your "native" keyboard
/// state
pub key_map: [u32; sys::ImGuiKey_COUNT as usize],
/// When holding a key/button, time before it starts repeating, in seconds
pub key_repeat_delay: f32,
/// When holding a key/button, rate at which it repeats, in seconds
pub key_repeat_rate: f32,
user_data: *mut c_void,
pub(crate) fonts: *mut FontAtlas,
/// Global scale for all fonts
pub font_global_scale: f32,
/// Allow user to scale text of individual window with CTRL+wheel
pub font_allow_user_scaling: bool,
pub(crate) font_default: *mut Font,
/// For retina display or other situations where window coordinates are different from
/// framebuffer coordinates
pub display_framebuffer_scale: [f32; 2],
/// Request imgui-rs to draw a mouse cursor for you
pub mouse_draw_cursor: bool,
/// macOS-style input behavior.
///
/// Defaults to true on Apple platforms. Changes in behavior:
///
/// * Text editing cursor movement using Alt instead of Ctrl
/// * Shortcuts using Cmd/Super instead of Ctrl
/// * Line/text start and end using Cmd+Arrows instead of Home/End
/// * Double-click selects by word instead of selecting the whole text
/// * Multi-selection in lists uses Cmd/Super instead of Ctrl
pub config_mac_os_behaviors: bool,
/// Set to false to disable blinking cursor
pub config_input_text_cursor_blink: bool,
/// Enable turning DragXXX widgets into text input with a simple mouse
/// click-release (without moving). Not desirable on devices without a
/// keyboard.
pub config_drag_click_to_input_text: bool,
/// Enable resizing of windows from their edges and from the lower-left corner.
///
/// Requires `HasMouserCursors` in `backend_flags`, because it needs mouse cursor feedback.
pub config_windows_resize_from_edges: bool,
/// Set to true to only allow moving windows when clicked+dragged from the title bar.
///
/// Windows without a title bar are not affected.
pub config_windows_move_from_title_bar_only: bool,
/// Compact memory usage when unused.
///
/// Set to -1.0 to disable.
pub config_memory_compact_timer: f32,
pub(crate) backend_platform_name: *const c_char,
pub(crate) backend_renderer_name: *const c_char,
backend_platform_user_data: *mut c_void,
backend_renderer_user_data: *mut c_void,
backend_language_user_data: *mut c_void,
pub(crate) get_clipboard_text_fn:
Option<unsafe extern "C" fn(user_data: *mut c_void) -> *const c_char>,
pub(crate) set_clipboard_text_fn:
Option<unsafe extern "C" fn(user_data: *mut c_void, text: *const c_char)>,
pub(crate) clipboard_user_data: *mut c_void,
ime_set_input_screen_pos_fn: Option<unsafe extern "C" fn(x: c_int, y: c_int)>,
ime_window_handle: *mut c_void,
/// Mouse position, in pixels.
///
/// Set to [f32::MAX, f32::MAX] if mouse is unavailable (on another screen, etc.).
pub mouse_pos: [f32; 2],
/// Mouse buttons: 0=left, 1=right, 2=middle + extras
pub mouse_down: [bool; 5],
/// Mouse wheel (vertical).
///
/// 1 unit scrolls about 5 lines of text.
pub mouse_wheel: f32,
/// Mouse wheel (horizontal).
///
/// Most users don't have a mouse with a horizontal wheel, and may not be filled by all
/// backends.
pub mouse_wheel_h: f32,
/// Keyboard modifier pressed: Control
pub key_ctrl: bool,
/// Keyboard modifier pressed: Shift
pub key_shift: bool,
/// Keyboard modifier pressed: Alt
pub key_alt: bool,
/// Keyboard modifier pressed: Cmd/Super/Windows
pub key_super: bool,
/// Keyboard keys that are pressed (indexing defined by the user/application)
pub keys_down: [bool; 512],
/// Gamepad inputs.
///
/// Cleared back to zero after each frame. Keyboard keys will be auto-mapped and written
/// here by `frame()`.
pub nav_inputs: [f32; NavInput::COUNT + NavInput::INTERNAL_COUNT],
/// When true, imgui-rs will use the mouse inputs, so do not dispatch them to your main
/// game/application
pub want_capture_mouse: bool,
/// When true, imgui-rs will use the keyboard inputs, so do not dispatch them to your main
/// game/application
pub want_capture_keyboard: bool,
/// Mobile/console: when true, you may display an on-screen keyboard.
///
/// This is set by imgui-rs when it wants textual keyboard input to happen.
pub want_text_input: bool,
/// Mouse position has been altered, so the backend should reposition the mouse on the next
/// frame.
///
/// Set only when `ConfigFlags::NavEnableSetMousePos` is enabled.
pub want_set_mouse_pos: bool,
/// When manual .ini load/save is active (`ini_filename` is `None`), this will be set to notify
/// your application that you can call `save_ini_settings` and save the settings yourself.
///
/// *Important*: You need to clear this flag yourself
pub want_save_ini_settings: bool,
/// Keyboard/Gamepad navigation is currently allowed
pub nav_active: bool,
/// Keyboard/Gamepad navigation is visible and allowed
pub nav_visible: bool,
/// Application framerate estimation, in frames per second.
///
/// Rolling average estimation based on `io.delta_time` over 120 frames.
pub framerate: f32,
/// Vertices output during last rendering
pub metrics_render_vertices: i32,
/// Indices output during last rendering (= number of triangles * 3)
pub metrics_render_indices: i32,
/// Number of visible windows
pub metrics_render_windows: i32,
/// Number of active windows
pub metrics_active_windows: i32,
/// Number of active internal imgui-rs allocations
pub metrics_active_allocations: i32,
/// Mouse delta.
///
/// Note that this is zero if either current or previous position is invalid ([f32::MAX,
/// f32::MAX]), so a disappearing/reappearing mouse won't have a huge delta.
pub mouse_delta: [f32; 2],
key_mods: sys::ImGuiKeyModFlags,
key_mods_prev: sys::ImGuiKeyModFlags,
mouse_pos_prev: [f32; 2],
mouse_clicked_pos: [[f32; 2]; 5],
mouse_clicked_time: [f64; 5],
mouse_clicked: [bool; 5],
mouse_double_clicked: [bool; 5],
mouse_released: [bool; 5],
mouse_down_owned: [bool; 5],
mouse_down_was_double_click: [bool; 5],
mouse_down_duration: [f32; 5],
mouse_down_duration_prev: [f32; 5],
mouse_drag_max_distance_abs: [[f32; 2]; 5],
mouse_drag_max_distance_sqr: [f32; 5],
keys_down_duration: [f32; 512],
keys_down_duration_prev: [f32; 512],
nav_inputs_down_duration: [f32; NavInput::COUNT + NavInput::INTERNAL_COUNT],
nav_inputs_down_duration_prev: [f32; NavInput::COUNT + NavInput::INTERNAL_COUNT],
pen_pressure: f32,
input_queue_surrogate: sys::ImWchar16,
input_queue_characters: ImVector<sys::ImWchar>,
}
unsafe impl RawCast<sys::ImGuiIO> for Io {}
impl Io {
/// Queue new character input
#[doc(alias = "AddInputCharactersUTF8")]
pub fn add_input_character(&mut self, character: char) {
let mut buf = [0; 5];
character.encode_utf8(&mut buf);
unsafe {
sys::ImGuiIO_AddInputCharactersUTF8(self.raw_mut(), buf.as_ptr() as *const _);
}
}
/// Clear character input buffer
#[doc(alias = "ClearCharacters")]
pub fn clear_input_characters(&mut self) {
unsafe {
sys::ImGuiIO_ClearInputCharacters(self.raw_mut());
}
}
/// Peek character input buffer, return a copy of entire buffer
pub fn peek_input_characters(&self) -> String {
self.input_queue_characters().collect()
}
/// Returns a view of the data in the input queue (without copying it).
///
/// The returned iterator is a simple mapping over a slice more or less what
/// you need for random access to the data (Rust has no
/// `RandomAccessIterator`, or we'd use that).
pub fn input_queue_characters(
&self,
) -> impl Iterator<Item = char> + DoubleEndedIterator + ExactSizeIterator + Clone + '_ {
self.input_queue_characters
.as_slice()
.iter()
// TODO: are the values in the buffer guaranteed to be valid unicode
// scalar values? if so we can just expose this as a `&[char]`...
.map(|c| core::char::from_u32(*c).unwrap_or(core::char::REPLACEMENT_CHARACTER))
}
pub fn update_delta_time(&mut self, delta: Duration) {
let delta_s = delta.as_secs() as f32 + delta.subsec_nanos() as f32 / 1_000_000_000.0;
if delta_s > 0.0 {
self.delta_time = delta_s;
} else {
self.delta_time = f32::MIN_POSITIVE;
}
self.delta_time = delta_s;
}
}
impl Index<Key> for Io {
type Output = u32;
fn index(&self, index: Key) -> &u32 {
&self.key_map[index as usize]
}
}
impl IndexMut<Key> for Io {
fn index_mut(&mut self, index: Key) -> &mut u32 {
&mut self.key_map[index as usize]
}
}
impl Index<NavInput> for Io {
type Output = f32;
fn index(&self, index: NavInput) -> &f32 {
&self.nav_inputs[index as usize]
}
}
impl IndexMut<NavInput> for Io {
fn index_mut(&mut self, index: NavInput) -> &mut f32 {
&mut self.nav_inputs[index as usize]
}
}
impl Index<MouseButton> for Io {
type Output = bool;
fn index(&self, index: MouseButton) -> &bool {
&self.mouse_down[index as usize]
}
}
impl IndexMut<MouseButton> for Io {
fn index_mut(&mut self, index: MouseButton) -> &mut bool {
&mut self.mouse_down[index as usize]
}
}
#[test]
#[cfg(test)]
fn test_io_memory_layout() {
use std::mem;
assert_eq!(mem::size_of::<Io>(), mem::size_of::<sys::ImGuiIO>());
assert_eq!(mem::align_of::<Io>(), mem::align_of::<sys::ImGuiIO>());
use sys::ImGuiIO;
macro_rules! assert_field_offset {
($l:ident, $r:ident) => {
assert_eq!(
memoffset::offset_of!(Io, $l),
memoffset::offset_of!(ImGuiIO, $r)
);
};
}
assert_field_offset!(config_flags, ConfigFlags);
assert_field_offset!(backend_flags, BackendFlags);
assert_field_offset!(display_size, DisplaySize);
assert_field_offset!(delta_time, DeltaTime);
assert_field_offset!(ini_saving_rate, IniSavingRate);
assert_field_offset!(ini_filename, IniFilename);
assert_field_offset!(log_filename, LogFilename);
assert_field_offset!(mouse_double_click_time, MouseDoubleClickTime);
assert_field_offset!(mouse_double_click_max_dist, MouseDoubleClickMaxDist);
assert_field_offset!(mouse_drag_threshold, MouseDragThreshold);
assert_field_offset!(key_map, KeyMap);
assert_field_offset!(key_repeat_delay, KeyRepeatDelay);
assert_field_offset!(key_repeat_rate, KeyRepeatRate);
assert_field_offset!(user_data, UserData);
assert_field_offset!(fonts, Fonts);
assert_field_offset!(font_global_scale, FontGlobalScale);
assert_field_offset!(font_allow_user_scaling, FontAllowUserScaling);
assert_field_offset!(font_default, FontDefault);
assert_field_offset!(display_framebuffer_scale, DisplayFramebufferScale);
assert_field_offset!(mouse_draw_cursor, MouseDrawCursor);
assert_field_offset!(config_mac_os_behaviors, ConfigMacOSXBehaviors);
assert_field_offset!(config_input_text_cursor_blink, ConfigInputTextCursorBlink);
assert_field_offset!(
config_windows_resize_from_edges,
ConfigWindowsResizeFromEdges
);
assert_field_offset!(
config_windows_move_from_title_bar_only,
ConfigWindowsMoveFromTitleBarOnly
);
assert_field_offset!(backend_platform_name, BackendPlatformName);
assert_field_offset!(backend_renderer_name, BackendRendererName);
assert_field_offset!(backend_platform_user_data, BackendPlatformUserData);
assert_field_offset!(backend_renderer_user_data, BackendRendererUserData);
assert_field_offset!(backend_language_user_data, BackendLanguageUserData);
assert_field_offset!(get_clipboard_text_fn, GetClipboardTextFn);
assert_field_offset!(set_clipboard_text_fn, SetClipboardTextFn);
assert_field_offset!(clipboard_user_data, ClipboardUserData);
assert_field_offset!(ime_set_input_screen_pos_fn, ImeSetInputScreenPosFn);
assert_field_offset!(ime_window_handle, ImeWindowHandle);
assert_field_offset!(mouse_pos, MousePos);
assert_field_offset!(mouse_down, MouseDown);
assert_field_offset!(mouse_wheel, MouseWheel);
assert_field_offset!(mouse_wheel_h, MouseWheelH);
assert_field_offset!(key_ctrl, KeyCtrl);
assert_field_offset!(key_shift, KeyShift);
assert_field_offset!(key_alt, KeyAlt);
assert_field_offset!(key_super, KeySuper);
assert_field_offset!(keys_down, KeysDown);
assert_field_offset!(nav_inputs, NavInputs);
assert_field_offset!(want_capture_mouse, WantCaptureMouse);
assert_field_offset!(want_capture_keyboard, WantCaptureKeyboard);
assert_field_offset!(want_text_input, WantTextInput);
assert_field_offset!(want_set_mouse_pos, WantSetMousePos);
assert_field_offset!(want_save_ini_settings, WantSaveIniSettings);
assert_field_offset!(nav_active, NavActive);
assert_field_offset!(nav_visible, NavVisible);
assert_field_offset!(framerate, Framerate);
assert_field_offset!(metrics_render_vertices, MetricsRenderVertices);
assert_field_offset!(metrics_render_indices, MetricsRenderIndices);
assert_field_offset!(metrics_render_windows, MetricsRenderWindows);
assert_field_offset!(metrics_active_windows, MetricsActiveWindows);
assert_field_offset!(metrics_active_allocations, MetricsActiveAllocations);
assert_field_offset!(mouse_delta, MouseDelta);
assert_field_offset!(key_mods, KeyMods);
assert_field_offset!(mouse_pos_prev, MousePosPrev);
assert_field_offset!(mouse_clicked_pos, MouseClickedPos);
assert_field_offset!(mouse_clicked_time, MouseClickedTime);
assert_field_offset!(mouse_clicked, MouseClicked);
assert_field_offset!(mouse_double_clicked, MouseDoubleClicked);
assert_field_offset!(mouse_released, MouseReleased);
assert_field_offset!(mouse_down_owned, MouseDownOwned);
assert_field_offset!(mouse_down_was_double_click, MouseDownWasDoubleClick);
assert_field_offset!(mouse_down_duration, MouseDownDuration);
assert_field_offset!(mouse_down_duration_prev, MouseDownDurationPrev);
assert_field_offset!(mouse_drag_max_distance_abs, MouseDragMaxDistanceAbs);
assert_field_offset!(mouse_drag_max_distance_sqr, MouseDragMaxDistanceSqr);
assert_field_offset!(keys_down_duration, KeysDownDuration);
assert_field_offset!(keys_down_duration_prev, KeysDownDurationPrev);
assert_field_offset!(nav_inputs_down_duration, NavInputsDownDuration);
assert_field_offset!(nav_inputs_down_duration_prev, NavInputsDownDurationPrev);
assert_field_offset!(pen_pressure, PenPressure);
assert_field_offset!(input_queue_surrogate, InputQueueSurrogate);
assert_field_offset!(input_queue_characters, InputQueueCharacters);
}

View File

@@ -1,176 +0,0 @@
use crate::sys;
use crate::Ui;
create_token!(
/// Tracks a layout group that can be ended with `end` or by dropping.
pub struct GroupToken<'ui>;
/// Drops the layout group manually. You can also just allow this token
/// to drop on its own.
drop { sys::igEndGroup() }
);
/// # Cursor / Layout
impl<'ui> Ui<'ui> {
/// Renders a separator (generally horizontal).
///
/// This becomes a vertical separator inside a menu bar or in horizontal layout mode.
#[doc(alias = "Separator")]
pub fn separator(&self) {
unsafe { sys::igSeparator() }
}
/// Call between widgets or groups to layout them horizontally.
///
/// X position is given in window coordinates.
///
/// This is equivalent to calling [same_line_with_pos](Self::same_line_with_pos)
/// with the `pos` set to 0.0, which uses `Style::item_spacing`.
#[doc(alias = "SameLine")]
pub fn same_line(&self) {
self.same_line_with_pos(0.0);
}
/// Call between widgets or groups to layout them horizontally.
///
/// X position is given in window coordinates.
///
/// This is equivalent to calling [same_line_with_spacing](Self::same_line_with_spacing)
/// with the `spacing` set to -1.0, which means no extra spacing.
#[doc(alias = "SameLine")]
pub fn same_line_with_pos(&self, pos_x: f32) {
self.same_line_with_spacing(pos_x, -1.0)
}
/// Call between widgets or groups to layout them horizontally.
///
/// X position is given in window coordinates.
#[doc(alias = "SameLine")]
pub fn same_line_with_spacing(&self, pos_x: f32, spacing_w: f32) {
unsafe { sys::igSameLine(pos_x, spacing_w) }
}
/// Undo a `same_line` call or force a new line when in horizontal layout mode
#[doc(alias = "NewLine")]
pub fn new_line(&self) {
unsafe { sys::igNewLine() }
}
/// Adds vertical spacing
#[doc(alias = "Spacing")]
pub fn spacing(&self) {
unsafe { sys::igSpacing() }
}
/// Fills a space of `size` in pixels with nothing on the current window.
///
/// Can be used to move the cursor on the window.
#[doc(alias = "Dummy")]
pub fn dummy(&self, size: [f32; 2]) {
unsafe { sys::igDummy(size.into()) }
}
/// Moves content position to the right by `Style::indent_spacing`
///
/// This is equivalent to [indent_by](Self::indent_by) with `width` set to
/// `Style::ident_spacing`.
#[doc(alias = "Indent")]
pub fn indent(&self) {
self.indent_by(0.0)
}
/// Moves content position to the right by `width`
#[doc(alias = "Indent")]
pub fn indent_by(&self, width: f32) {
unsafe { sys::igIndent(width) };
}
/// Moves content position to the left by `Style::indent_spacing`
///
/// This is equivalent to [unindent_by](Self::unindent_by) with `width` set to
/// `Style::ident_spacing`.
#[doc(alias = "Unindent")]
pub fn unindent(&self) {
self.unindent_by(0.0)
}
/// Moves content position to the left by `width`
#[doc(alias = "Unindent")]
pub fn unindent_by(&self, width: f32) {
unsafe { sys::igUnindent(width) };
}
/// Groups items together as a single item.
///
/// May be useful to handle the same mouse event on a group of items, for example.
///
/// Returns a `GroupToken` that must be ended by calling `.end()`
#[doc(alias = "BeginGroup")]
pub fn begin_group(&self) -> GroupToken<'_> {
unsafe { sys::igBeginGroup() };
GroupToken::new(self)
}
/// Creates a layout group and runs a closure to construct the contents.
///
/// May be useful to handle the same mouse event on a group of items, for example.
#[doc(alias = "BeginGroup")]
pub fn group<R, F: FnOnce() -> R>(&self, f: F) -> R {
let group = self.begin_group();
let result = f();
group.end();
result
}
/// Returns the cursor position (in window coordinates)
#[doc(alias = "GetCursorPos")]
pub fn cursor_pos(&self) -> [f32; 2] {
let mut out = sys::ImVec2::zero();
unsafe { sys::igGetCursorPos(&mut out) };
out.into()
}
/// Sets the cursor position (in window coordinates).
///
/// This sets the point on which the next widget will be drawn.
#[doc(alias = "SetCursorPos")]
pub fn set_cursor_pos(&self, pos: [f32; 2]) {
unsafe { sys::igSetCursorPos(pos.into()) };
}
/// Returns the initial cursor position (in window coordinates)
#[doc(alias = "GetCursorStartPos")]
pub fn cursor_start_pos(&self) -> [f32; 2] {
let mut out = sys::ImVec2::zero();
unsafe { sys::igGetCursorStartPos(&mut out) };
out.into()
}
/// Returns the cursor position (in absolute screen coordinates).
///
/// This is especially useful for drawing, as the drawing API uses screen coordinates.
#[doc(alias = "GetCursorScreenPos")]
pub fn cursor_screen_pos(&self) -> [f32; 2] {
let mut out = sys::ImVec2::zero();
unsafe { sys::igGetCursorScreenPos(&mut out) };
out.into()
}
/// Sets the cursor position (in absolute screen coordinates)
#[doc(alias = "SetCursorScreenPos")]
pub fn set_cursor_screen_pos(&self, pos: [f32; 2]) {
unsafe { sys::igSetCursorScreenPos(pos.into()) }
}
/// Vertically aligns text baseline so that it will align properly to regularly frame items.
///
/// Call this if you have text on a line before a framed item.
#[doc(alias = "AlignTextToFramePadding")]
pub fn align_text_to_frame_padding(&self) {
unsafe { sys::igAlignTextToFramePadding() };
}
#[doc(alias = "GetTextLineHeight")]
pub fn text_line_height(&self) -> f32 {
unsafe { sys::igGetTextLineHeight() }
}
#[doc(alias = "GetTextLineHeightWithSpacing")]
pub fn text_line_height_with_spacing(&self) -> f32 {
unsafe { sys::igGetTextLineHeightWithSpacing() }
}
#[doc(alias = "GetFrameHeight")]
pub fn frame_height(&self) -> f32 {
unsafe { sys::igGetFrameHeight() }
}
#[doc(alias = "GetFrameLineHeightWithSpacing")]
pub fn frame_height_with_spacing(&self) -> f32 {
unsafe { sys::igGetFrameHeightWithSpacing() }
}
}

View File

@@ -1,753 +0,0 @@
#![cfg_attr(test, allow(clippy::float_cmp))]
#![deny(rust_2018_idioms)]
// #![deny(missing_docs)]
pub extern crate imgui_sys as sys;
use std::cell;
use std::ffi::CStr;
use std::os::raw::{c_char, c_void};
use std::ptr;
use std::str;
use std::thread;
pub use self::clipboard::*;
pub use self::color::ImColor32;
pub use self::context::*;
pub use self::drag_drop::{DragDropFlags, DragDropSource, DragDropTarget};
pub use self::draw_list::{ChannelsSplit, DrawListMut};
pub use self::fonts::atlas::*;
pub use self::fonts::font::*;
pub use self::fonts::glyph::*;
pub use self::fonts::glyph_ranges::*;
pub use self::input::keyboard::*;
pub use self::input::mouse::*;
pub use self::input_widget::*;
pub use self::io::*;
pub use self::layout::*;
pub use self::list_clipper::ListClipper;
pub use self::plothistogram::PlotHistogram;
pub use self::plotlines::PlotLines;
pub use self::popups::*;
pub use self::render::draw_data::*;
pub use self::render::renderer::*;
pub use self::stacks::*;
pub use self::string::*;
pub use self::style::*;
#[cfg(feature = "tables-api")]
pub use self::tables::*;
pub use self::utils::*;
pub use self::widget::color_editors::*;
pub use self::widget::combo_box::*;
pub use self::widget::drag::*;
pub use self::widget::image::*;
pub use self::widget::list_box::*;
pub use self::widget::menu::*;
pub use self::widget::misc::*;
pub use self::widget::progress_bar::*;
pub use self::widget::selectable::*;
pub use self::widget::slider::*;
pub use self::widget::tab::*;
pub use self::widget::tree::*;
pub use self::window::child_window::*;
pub use self::window::*;
use internal::RawCast;
#[macro_use]
mod string;
#[macro_use]
mod tokens;
mod clipboard;
pub mod color;
mod columns;
mod context;
pub mod drag_drop;
pub mod draw_list;
mod fonts;
mod input;
mod input_widget;
pub mod internal;
mod io;
mod layout;
mod list_clipper;
mod plothistogram;
mod plotlines;
mod popups;
mod render;
mod stacks;
mod style;
#[cfg(feature = "tables-api")]
mod tables;
#[cfg(test)]
mod test;
mod utils;
mod widget;
mod window;
// Used by macros. Underscores are just to make it clear it's not part of the
// public API.
#[doc(hidden)]
pub use core as __core;
/// Returns the underlying Dear ImGui library version
#[doc(alias = "GetVersion")]
pub fn dear_imgui_version() -> &'static str {
unsafe {
let bytes = CStr::from_ptr(sys::igGetVersion()).to_bytes();
str::from_utf8_unchecked(bytes)
}
}
impl Context {
/// Returns the global imgui-rs time.
///
/// Incremented by Io::delta_time every frame.
#[doc(alias = "GetTime")]
pub fn time(&self) -> f64 {
unsafe { sys::igGetTime() }
}
/// Returns the global imgui-rs frame count.
///
/// Incremented by 1 every frame.
#[doc(alias = "GetFrameCount")]
pub fn frame_count(&self) -> i32 {
unsafe { sys::igGetFrameCount() }
}
}
/// A temporary reference for building the user interface for one frame
#[derive(Debug)]
pub struct Ui<'ui> {
ctx: &'ui Context,
font_atlas: Option<cell::RefMut<'ui, SharedFontAtlas>>,
// imgui isn't multi-threaded -- so no one will ever access twice.
buffer: cell::UnsafeCell<string::UiBuffer>,
}
impl<'ui> Ui<'ui> {
/// Internal method to push a single text to our scratch buffer.
fn scratch_txt(&self, txt: impl AsRef<str>) -> *const sys::cty::c_char {
unsafe {
let handle = &mut *self.buffer.get();
handle.scratch_txt(txt)
}
}
/// Internal method to push an option text to our scratch buffer.
fn scratch_txt_opt(&self, txt: Option<impl AsRef<str>>) -> *const sys::cty::c_char {
unsafe {
let handle = &mut *self.buffer.get();
handle.scratch_txt_opt(txt)
}
}
fn scratch_txt_two(
&self,
txt_0: impl AsRef<str>,
txt_1: impl AsRef<str>,
) -> (*const sys::cty::c_char, *const sys::cty::c_char) {
unsafe {
let handle = &mut *self.buffer.get();
handle.scratch_txt_two(txt_0, txt_1)
}
}
fn scratch_txt_with_opt(
&self,
txt_0: impl AsRef<str>,
txt_1: Option<impl AsRef<str>>,
) -> (*const sys::cty::c_char, *const sys::cty::c_char) {
unsafe {
let handle = &mut *self.buffer.get();
handle.scratch_txt_with_opt(txt_0, txt_1)
}
}
/// Returns an immutable reference to the inputs/outputs object
#[doc(alias = "GetIO")]
pub fn io(&self) -> &Io {
unsafe { &*(sys::igGetIO() as *const Io) }
}
/// Returns an immutable reference to the font atlas
pub fn fonts(&self) -> FontAtlasRef<'_> {
match self.font_atlas {
Some(ref font_atlas) => FontAtlasRef::Shared(font_atlas),
None => unsafe {
let fonts = &*(self.io().fonts as *const FontAtlas);
FontAtlasRef::Owned(fonts)
},
}
}
/// Returns a clone of the user interface style
pub fn clone_style(&self) -> Style {
*self.ctx.style()
}
/// Renders the frame and returns a reference to the resulting draw data
#[doc(alias = "Render", alias = "GetDrawData")]
pub fn render(self) -> &'ui DrawData {
unsafe {
sys::igRender();
&*(sys::igGetDrawData() as *mut DrawData)
}
}
}
impl<'a> Drop for Ui<'a> {
#[doc(alias = "EndFrame")]
fn drop(&mut self) {
if !thread::panicking() {
unsafe {
sys::igEndFrame();
}
}
}
}
/// # Demo, debug, information
impl<'ui> Ui<'ui> {
/// Renders a demo window (previously called a test window), which demonstrates most
/// Dear Imgui features.
#[doc(alias = "ShowDemoWindow")]
pub fn show_demo_window(&self, opened: &mut bool) {
unsafe {
sys::igShowDemoWindow(opened);
}
}
/// Renders an about window.
///
/// Displays the Dear ImGui version/credits, and build/system information.
#[doc(alias = "ShowAboutWindow")]
pub fn show_about_window(&self, opened: &mut bool) {
unsafe {
sys::igShowAboutWindow(opened);
}
}
/// Renders a metrics/debug window.
///
/// Displays Dear ImGui internals: draw commands (with individual draw calls and vertices),
/// window list, basic internal state, etc.
#[doc(alias = "ShowMetricsWindow")]
pub fn show_metrics_window(&self, opened: &mut bool) {
unsafe {
sys::igShowMetricsWindow(opened);
}
}
/// Renders a style editor block (not a window) for the given `Style` structure
#[doc(alias = "ShowStyleEditor")]
pub fn show_style_editor(&self, style: &mut Style) {
unsafe {
sys::igShowStyleEditor(style.raw_mut());
}
}
/// Renders a style editor block (not a window) for the currently active style
#[doc(alias = "ShowStyleEditor")]
pub fn show_default_style_editor(&self) {
unsafe { sys::igShowStyleEditor(ptr::null_mut()) };
}
/// Renders a basic help/info block (not a window)
#[doc(alias = "ShowUserGuide")]
pub fn show_user_guide(&self) {
unsafe { sys::igShowUserGuide() };
}
}
/// Unique ID used by widgets
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Id<'a> {
Int(i32),
Str(&'a str),
Ptr(*const c_void),
}
impl From<i32> for Id<'static> {
#[inline]
fn from(i: i32) -> Self {
Id::Int(i)
}
}
impl<'a, T: ?Sized + AsRef<str>> From<&'a T> for Id<'a> {
#[inline]
fn from(s: &'a T) -> Self {
Id::Str(s.as_ref())
}
}
impl<T> From<*const T> for Id<'static> {
#[inline]
fn from(p: *const T) -> Self {
Id::Ptr(p as *const c_void)
}
}
impl<T> From<*mut T> for Id<'static> {
#[inline]
fn from(p: *mut T) -> Self {
Id::Ptr(p as *const T as *const c_void)
}
}
impl<'a> Id<'a> {
// this is used in the tables-api and possibly elsewhere,
// but not with just default features...
#[allow(dead_code)]
fn as_imgui_id(&self) -> sys::ImGuiID {
unsafe {
match self {
Id::Ptr(p) => sys::igGetID_Ptr(*p),
Id::Str(s) => {
let s1 = s.as_ptr() as *const std::os::raw::c_char;
let s2 = s1.add(s.len());
sys::igGetID_StrStr(s1, s2)
}
Id::Int(i) => {
let p = *i as *const std::os::raw::c_void;
sys::igGetID_Ptr(p)
} // Id::ImGuiID(n) => *n,
}
}
}
}
impl<'a> Default for Id<'a> {
fn default() -> Self {
Self::Int(0)
}
}
// Widgets: Input
impl<'ui> Ui<'ui> {
#[doc(alias = "InputText", alias = "InputTextWithHint")]
pub fn input_text<'p, L: AsRef<str>>(
&'ui self,
label: L,
buf: &'p mut String,
) -> InputText<'ui, 'p, L> {
InputText::new(self, label, buf)
}
#[doc(alias = "InputText", alias = "InputTextMultiline")]
pub fn input_text_multiline<'p, L: AsRef<str>>(
&'ui self,
label: L,
buf: &'p mut String,
size: [f32; 2],
) -> InputTextMultiline<'ui, 'p, L> {
InputTextMultiline::new(self, label, buf, size)
}
#[doc(alias = "InputFloat2")]
pub fn input_float<'p, L: AsRef<str>>(
&'ui self,
label: L,
value: &'p mut f32,
) -> InputFloat<'ui, 'p, L> {
InputFloat::new(self, label, value)
}
pub fn input_float2<'p, L: AsRef<str>>(
&'ui self,
label: L,
value: &'p mut [f32; 2],
) -> InputFloat2<'ui, 'p, L> {
InputFloat2::new(self, label, value)
}
#[doc(alias = "InputFloat3")]
pub fn input_float3<'p, L: AsRef<str>>(
&'ui self,
label: L,
value: &'p mut [f32; 3],
) -> InputFloat3<'ui, 'p, L> {
InputFloat3::new(self, label, value)
}
#[doc(alias = "InputFloat4")]
pub fn input_float4<'p, L: AsRef<str>>(
&'ui self,
label: L,
value: &'p mut [f32; 4],
) -> InputFloat4<'ui, 'p, L> {
InputFloat4::new(self, label, value)
}
#[doc(alias = "InputInt")]
pub fn input_int<'p, L: AsRef<str>>(
&'ui self,
label: L,
value: &'p mut i32,
) -> InputInt<'ui, 'p, L> {
InputInt::new(self, label, value)
}
#[doc(alias = "InputInt2")]
pub fn input_int2<'p, L: AsRef<str>>(
&'ui self,
label: L,
value: &'p mut [i32; 2],
) -> InputInt2<'ui, 'p, L> {
InputInt2::new(self, label, value)
}
#[doc(alias = "InputInt3")]
pub fn input_int3<'p, L: AsRef<str>>(
&'ui self,
label: L,
value: &'p mut [i32; 3],
) -> InputInt3<'ui, 'p, L> {
InputInt3::new(self, label, value)
}
#[doc(alias = "InputInt4")]
pub fn input_int4<'p, L: AsRef<str>>(
&'ui self,
label: L,
value: &'p mut [i32; 4],
) -> InputInt4<'ui, 'p, L> {
InputInt4::new(self, label, value)
}
}
create_token!(
/// Tracks a layout tooltip that can be ended by calling `.end()` or by dropping.
pub struct TooltipToken<'ui>;
/// Drops the layout tooltip manually. You can also just allow this token
/// to drop on its own.
drop { sys::igEndTooltip() }
);
/// # Tooltips
impl<'ui> Ui<'ui> {
/// Construct a tooltip window that can have any kind of content.
///
/// Typically used with `Ui::is_item_hovered()` or some other conditional check.
///
/// # Examples
///
/// ```
/// # use imgui::*;
/// fn user_interface(ui: &Ui) {
/// ui.text("Hover over me");
/// if ui.is_item_hovered() {
/// ui.tooltip(|| {
/// ui.text_colored([1.0, 0.0, 0.0, 1.0], im_str!("I'm red!"));
/// });
/// }
/// }
/// ```
#[doc(alias = "BeginTooltip", alias = "EndTooltip")]
pub fn tooltip<F: FnOnce()>(&self, f: F) {
unsafe { sys::igBeginTooltip() };
f();
unsafe { sys::igEndTooltip() };
}
/// Construct a tooltip window that can have any kind of content.
///
/// Returns a `TooltipToken` that must be ended by calling `.end()`
#[doc(alias = "BeginTooltip")]
pub fn begin_tooltip(&self) -> TooltipToken<'_> {
unsafe { sys::igBeginTooltip() };
TooltipToken::new(self)
}
/// Construct a tooltip window with simple text content.
///
/// Typically used with `Ui::is_item_hovered()` or some other conditional check.
///
/// # Examples
///
/// ```
/// # use imgui::*;
/// fn user_interface(ui: &Ui) {
/// ui.text("Hover over me");
/// if ui.is_item_hovered() {
/// ui.tooltip_text("I'm a tooltip!");
/// }
/// }
/// ```
#[doc(alias = "BeginTooltip", alias = "EndTooltip")]
pub fn tooltip_text<T: AsRef<str>>(&self, text: T) {
self.tooltip(|| self.text(text));
}
}
create_token!(
/// Starts a scope where interaction is disabled. Ends be calling `.end()` or when the token is dropped.
pub struct DisabledToken<'ui>;
/// Drops the layout tooltip manually. You can also just allow this token
/// to drop on its own.
drop { sys::igEndDisabled() }
);
/// # Disabling widgets
///
/// imgui can disable widgets so they don't react to mouse/keyboard
/// inputs, and are displayed differently (currently dimmed by an
/// amount set in [`Style::disabled_alpha`])
impl<'ui> Ui<'ui> {
/// Creates a scope where interactions are disabled.
///
/// Scope ends when returned token is dropped, or `.end()` is
/// explicitly called
///
/// # Examples
///
/// ```
/// # use imgui::*;
/// fn user_interface(ui: &Ui) {
/// let disable_buttons = true;
/// let _d = ui.begin_disabled(disable_buttons);
/// ui.button(im_str!("Dangerous button"));
/// }
/// ```
#[doc(alias = "BeginDisabled")]
pub fn begin_disabled(&self, disabled: bool) -> DisabledToken<'_> {
unsafe { sys::igBeginDisabled(disabled) };
DisabledToken::new(self)
}
/// Identical to [`Ui::begin_disabled`] but exists to allow avoiding a
/// double-negative, for example `begin_enabled(enable_buttons)`
/// instead of `begin_disabled(!enable_buttons)`)
#[doc(alias = "BeginDisabled")]
pub fn begin_enabled(&self, enabled: bool) -> DisabledToken<'_> {
self.begin_disabled(!enabled)
}
/// Helper to create a disabled section of widgets
///
/// # Examples
///
/// ```
/// # use imgui::*;
/// fn user_interface(ui: &Ui) {
/// let safe_mode = true;
/// ui.disabled(safe_mode, || {
/// ui.button(im_str!("Dangerous button"));
/// });
/// }
/// ```
#[doc(alias = "BeginDisabled", alias = "EndDisabled")]
pub fn disabled<F: FnOnce()>(&self, disabled: bool, f: F) {
unsafe { sys::igBeginDisabled(disabled) };
f();
unsafe { sys::igEndDisabled() };
}
/// Same as [`Ui::disabled`] but with logic reversed. See
/// [`Ui::begin_enabled`].
#[doc(alias = "BeginDisabled", alias = "EndDisabled")]
pub fn enabled<F: FnOnce()>(&self, enabled: bool, f: F) {
unsafe { sys::igBeginDisabled(!enabled) };
f();
unsafe { sys::igEndDisabled() };
}
}
// Widgets: ListBox
impl<'ui> Ui<'ui> {
#[doc(alias = "ListBox")]
pub fn list_box<'p, StringType: AsRef<str> + ?Sized>(
&self,
label: impl AsRef<str>,
current_item: &mut i32,
items: &'p [&'p StringType],
height_in_items: i32,
) -> bool {
let (label_ptr, items_inner) = unsafe {
let handle = &mut *self.buffer.get();
handle.refresh_buffer();
let label_ptr = handle.push(label);
let items_inner: Vec<_> = items.iter().map(|&v| handle.push(v)).collect();
(label_ptr, items_inner)
};
unsafe {
sys::igListBox_Str_arr(
label_ptr,
current_item,
items_inner.as_ptr() as *mut *const c_char,
items_inner.len() as i32,
height_in_items,
)
}
}
// written out for the future times...
// #[doc(alias = "ListBox")]
// pub fn list_box_const<'p, StringType: AsRef<str> + ?Sized, const N: usize>(
// &self,
// label: impl AsRef<str>,
// current_item: &mut i32,
// items: [&'p StringType; N],
// height_in_items: i32,
// ) -> bool {
// let (label_ptr, items_inner) = unsafe {
// let handle = &mut *self.buffer.get();
// handle.refresh_buffer();
// let label_ptr = handle.push(label);
// let mut items_inner: [*const i8; N] = [std::ptr::null(); N];
// for (i, item) in items.iter().enumerate() {
// items_inner[i] = handle.push(item);
// }
// (label_ptr, items_inner)
// };
// unsafe {
// sys::igListBoxStr_arr(
// label_ptr,
// current_item,
// items_inner.as_ptr() as *mut *const c_char,
// items_inner.len() as i32,
// height_in_items,
// )
// }
// }
}
impl<'ui> Ui<'ui> {
#[doc(alias = "PlotLines")]
pub fn plot_lines<'p, Label: AsRef<str>>(
&'ui self,
label: Label,
values: &'p [f32],
) -> PlotLines<'ui, 'p, Label> {
PlotLines::new(self, label, values)
}
}
impl<'ui> Ui<'ui> {
#[doc(alias = "PlotHistogram")]
pub fn plot_histogram<'p, Label: AsRef<str>>(
&'ui self,
label: Label,
values: &'p [f32],
) -> PlotHistogram<'ui, 'p, Label> {
PlotHistogram::new(self, label, values)
}
}
impl<'ui> Ui<'ui> {
/// Calculate the size required for a given text string.
///
/// This is the same as [calc_text_size_with_opts](Self::calc_text_size_with_opts)
/// with `hide_text_after_double_hash` set to false and `wrap_width` set to `-1.0`.
#[doc(alias = "CalcTextSize")]
pub fn calc_text_size<T: AsRef<str>>(&self, text: T) -> [f32; 2] {
self.calc_text_size_with_opts(text, false, -1.0)
}
/// Calculate the size required for a given text string.
///
/// hide_text_after_double_hash allows the user to insert comments into their text, using a double hash-tag prefix.
/// This is a feature of imgui.
///
/// wrap_width allows you to request a width at which to wrap the text to a newline for the calculation.
#[doc(alias = "CalcTextSize")]
pub fn calc_text_size_with_opts<T: AsRef<str>>(
&self,
text: T,
hide_text_after_double_hash: bool,
wrap_width: f32,
) -> [f32; 2] {
let mut out = sys::ImVec2::zero();
let text = text.as_ref();
unsafe {
let start = text.as_ptr();
let end = start.add(text.len());
sys::igCalcTextSize(
&mut out,
start as *const c_char,
end as *const c_char,
hide_text_after_double_hash,
wrap_width,
)
};
out.into()
}
}
/// # Draw list for custom drawing
impl<'ui> Ui<'ui> {
/// Get access to drawing API
///
/// # Examples
///
/// ```rust,no_run
/// # use imgui::*;
/// fn custom_draw(ui: &Ui) {
/// let draw_list = ui.get_window_draw_list();
/// // Draw a line
/// const WHITE: [f32; 3] = [1.0, 1.0, 1.0];
/// draw_list.add_line([100.0, 100.0], [200.0, 200.0], WHITE).build();
/// // Continue drawing ...
/// }
/// ```
///
/// This function will panic if several instances of [`DrawListMut`]
/// coexist. Before a new instance is got, a previous instance should be
/// dropped.
///
/// ```rust
/// # use imgui::*;
/// fn custom_draw(ui: &Ui) {
/// let draw_list = ui.get_window_draw_list();
/// // Draw something...
///
/// // This second call will panic!
/// let draw_list = ui.get_window_draw_list();
/// }
/// ```
#[must_use]
#[doc(alias = "GetWindowDrawList")]
pub fn get_window_draw_list(&'ui self) -> DrawListMut<'ui> {
DrawListMut::window(self)
}
#[must_use]
#[doc(alias = "GetBackgroundDrawList")]
pub fn get_background_draw_list(&'ui self) -> DrawListMut<'ui> {
DrawListMut::background(self)
}
#[must_use]
#[doc(alias = "GetForegroundDrawList")]
pub fn get_foreground_draw_list(&'ui self) -> DrawListMut<'ui> {
DrawListMut::foreground(self)
}
}
/// Condition for applying a setting
#[repr(i8)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Condition {
/// Never apply the setting
Never = -1,
/// Always apply the setting
Always = sys::ImGuiCond_Always as i8,
/// Apply the setting once per runtime session (only the first call will succeed)
Once = sys::ImGuiCond_Once as i8,
/// Apply the setting if the object/window has no persistently saved data (no entry in .ini
/// file)
FirstUseEver = sys::ImGuiCond_FirstUseEver as i8,
/// Apply the setting if the object/window is appearing after being hidden/inactive (or the
/// first time)
Appearing = sys::ImGuiCond_Appearing as i8,
}
/// A cardinal direction
#[repr(i32)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Direction {
None = sys::ImGuiDir_None,
Left = sys::ImGuiDir_Left,
Right = sys::ImGuiDir_Right,
Up = sys::ImGuiDir_Up,
Down = sys::ImGuiDir_Down,
}

View File

@@ -1,81 +0,0 @@
use std::marker::PhantomData;
use std::thread;
use crate::sys;
use crate::Ui;
pub struct ListClipper {
items_count: i32,
items_height: f32,
}
impl ListClipper {
pub const fn new(items_count: i32) -> Self {
ListClipper {
items_count,
items_height: -1.0,
}
}
pub const fn items_height(mut self, items_height: f32) -> Self {
self.items_height = items_height;
self
}
pub fn begin<'ui>(self, ui: &Ui<'ui>) -> ListClipperToken<'ui> {
let list_clipper = unsafe {
let list_clipper = sys::ImGuiListClipper_ImGuiListClipper();
sys::ImGuiListClipper_Begin(list_clipper, self.items_count, self.items_height);
list_clipper
};
ListClipperToken::new(ui, list_clipper)
}
}
pub struct ListClipperToken<'ui> {
list_clipper: *mut sys::ImGuiListClipper,
_phantom: PhantomData<&'ui Ui<'ui>>,
}
impl<'ui> ListClipperToken<'ui> {
fn new(_: &Ui<'ui>, list_clipper: *mut sys::ImGuiListClipper) -> Self {
Self {
list_clipper,
_phantom: PhantomData,
}
}
pub fn step(&mut self) -> bool {
unsafe { sys::ImGuiListClipper_Step(self.list_clipper) }
}
pub fn end(&mut self) {
unsafe {
sys::ImGuiListClipper_End(self.list_clipper);
}
}
pub fn display_start(&self) -> i32 {
unsafe { (*self.list_clipper).DisplayStart }
}
pub fn display_end(&self) -> i32 {
unsafe { (*self.list_clipper).DisplayEnd }
}
}
impl<'ui> Drop for ListClipperToken<'ui> {
fn drop(&mut self) {
if !self.step() {
unsafe {
sys::ImGuiListClipper_destroy(self.list_clipper);
};
} else if !thread::panicking() {
panic!(
"Forgot to call End(), or to Step() until false? \
This is the only token in the repository which users must call `.end()` or `.step()` \
with. See https://github.com/imgui-rs/imgui-rs/issues/438"
);
}
}
}

View File

@@ -1,87 +0,0 @@
use std::os::raw::c_float;
use std::{f32, mem};
use super::Ui;
#[must_use]
pub struct PlotHistogram<'ui, 'p, Label, Overlay = &'static str> {
label: Label,
values: &'p [f32],
values_offset: usize,
overlay_text: Option<Overlay>,
scale_min: f32,
scale_max: f32,
graph_size: [f32; 2],
ui: &'ui Ui<'ui>,
}
impl<'ui, 'p, Label: AsRef<str>> PlotHistogram<'ui, 'p, Label> {
pub fn new(ui: &'ui Ui<'ui>, label: Label, values: &'p [f32]) -> Self {
PlotHistogram {
label,
values,
values_offset: 0usize,
overlay_text: None,
scale_min: f32::MAX,
scale_max: f32::MAX,
graph_size: [0.0, 0.0],
ui,
}
}
}
impl<'ui, 'p, Label: AsRef<str>, Overlay: AsRef<str>> PlotHistogram<'ui, 'p, Label, Overlay> {
pub fn values_offset(mut self, values_offset: usize) -> Self {
self.values_offset = values_offset;
self
}
pub fn overlay_text<NewOverlay: AsRef<str>>(
self,
overlay_text: NewOverlay,
) -> PlotHistogram<'ui, 'p, Label, NewOverlay> {
PlotHistogram {
label: self.label,
values: self.values,
values_offset: self.values_offset,
overlay_text: Some(overlay_text),
scale_min: self.scale_min,
scale_max: self.scale_max,
graph_size: self.graph_size,
ui: self.ui,
}
}
pub fn scale_min(mut self, scale_min: f32) -> Self {
self.scale_min = scale_min;
self
}
pub fn scale_max(mut self, scale_max: f32) -> Self {
self.scale_max = scale_max;
self
}
pub fn graph_size(mut self, graph_size: [f32; 2]) -> Self {
self.graph_size = graph_size;
self
}
pub fn build(self) {
unsafe {
let (label, overlay_text) = self.ui.scratch_txt_with_opt(self.label, self.overlay_text);
sys::igPlotHistogram_FloatPtr(
label,
self.values.as_ptr() as *const c_float,
self.values.len() as i32,
self.values_offset as i32,
overlay_text,
self.scale_min,
self.scale_max,
self.graph_size.into(),
mem::size_of::<f32>() as i32,
);
}
}
}

View File

@@ -1,87 +0,0 @@
use std::os::raw::c_float;
use std::{f32, mem};
use super::Ui;
#[must_use]
pub struct PlotLines<'ui, 'p, Label, Overlay = &'static str> {
label: Label,
values: &'p [f32],
values_offset: usize,
overlay_text: Option<Overlay>,
scale_min: f32,
scale_max: f32,
graph_size: [f32; 2],
ui: &'ui Ui<'ui>,
}
impl<'ui, 'p, Label: AsRef<str>> PlotLines<'ui, 'p, Label> {
pub fn new(ui: &'ui Ui<'ui>, label: Label, values: &'p [f32]) -> Self {
PlotLines {
label,
values,
values_offset: 0usize,
overlay_text: None,
scale_min: f32::MAX,
scale_max: f32::MAX,
graph_size: [0.0, 0.0],
ui,
}
}
}
impl<'ui, 'p, Label: AsRef<str>, Overlay: AsRef<str>> PlotLines<'ui, 'p, Label, Overlay> {
pub fn values_offset(mut self, values_offset: usize) -> Self {
self.values_offset = values_offset;
self
}
pub fn overlay_text<Overlay2: AsRef<str>>(
self,
overlay_text: Overlay2,
) -> PlotLines<'ui, 'p, Label, Overlay2> {
PlotLines {
label: self.label,
values: self.values,
values_offset: self.values_offset,
overlay_text: Some(overlay_text),
scale_min: self.scale_min,
scale_max: self.scale_max,
graph_size: self.graph_size,
ui: self.ui,
}
}
pub fn scale_min(mut self, scale_min: f32) -> Self {
self.scale_min = scale_min;
self
}
pub fn scale_max(mut self, scale_max: f32) -> Self {
self.scale_max = scale_max;
self
}
pub fn graph_size(mut self, graph_size: [f32; 2]) -> Self {
self.graph_size = graph_size;
self
}
pub fn build(self) {
unsafe {
let (label, overlay) = self.ui.scratch_txt_with_opt(self.label, self.overlay_text);
sys::igPlotLines_FloatPtr(
label,
self.values.as_ptr() as *const c_float,
self.values.len() as i32,
self.values_offset as i32,
overlay,
self.scale_min,
self.scale_max,
self.graph_size.into(),
mem::size_of::<f32>() as i32,
);
}
}
}

View File

@@ -1,214 +0,0 @@
use std::ptr;
use crate::sys;
use crate::window::WindowFlags;
use crate::Ui;
/// Create a modal pop-up.
///
/// # Example
/// ```rust,no_run
/// # use imgui::*;
/// # let mut imgui = Context::create();
/// # let ui = imgui.frame();
/// if ui.button(im_str!("Show modal")) {
/// ui.open_popup(im_str!("modal"));
/// }
/// if let Some(_token) = PopupModal::new(im_str!("modal")).begin_popup(&ui) {
/// ui.text("Content of my modal");
/// if ui.button(im_str!("OK")) {
/// ui.close_current_popup();
/// }
/// };
/// ```
#[must_use]
pub struct PopupModal<'p, Label> {
label: Label,
opened: Option<&'p mut bool>,
flags: WindowFlags,
}
impl<'p, Label: AsRef<str>> PopupModal<'p, Label> {
pub fn new(label: Label) -> Self {
PopupModal {
label,
opened: None,
flags: WindowFlags::empty(),
}
}
/// Pass a mutable boolean which will be updated to refer to the current
/// "open" state of the modal.
pub fn opened(mut self, opened: &'p mut bool) -> Self {
self.opened = Some(opened);
self
}
pub fn flags(mut self, flags: WindowFlags) -> Self {
self.flags = flags;
self
}
pub fn title_bar(mut self, value: bool) -> Self {
self.flags.set(WindowFlags::NO_TITLE_BAR, !value);
self
}
pub fn resizable(mut self, value: bool) -> Self {
self.flags.set(WindowFlags::NO_RESIZE, !value);
self
}
pub fn movable(mut self, value: bool) -> Self {
self.flags.set(WindowFlags::NO_MOVE, !value);
self
}
pub fn scroll_bar(mut self, value: bool) -> Self {
self.flags.set(WindowFlags::NO_SCROLLBAR, !value);
self
}
pub fn scrollable(mut self, value: bool) -> Self {
self.flags.set(WindowFlags::NO_SCROLL_WITH_MOUSE, !value);
self
}
pub fn collapsible(mut self, value: bool) -> Self {
self.flags.set(WindowFlags::NO_COLLAPSE, !value);
self
}
pub fn always_auto_resize(mut self, value: bool) -> Self {
self.flags.set(WindowFlags::ALWAYS_AUTO_RESIZE, value);
self
}
pub fn save_settings(mut self, value: bool) -> Self {
self.flags.set(WindowFlags::NO_SAVED_SETTINGS, !value);
self
}
pub fn inputs(mut self, value: bool) -> Self {
self.flags.set(WindowFlags::NO_INPUTS, !value);
self
}
pub fn menu_bar(mut self, value: bool) -> Self {
self.flags.set(WindowFlags::MENU_BAR, value);
self
}
pub fn horizontal_scrollbar(mut self, value: bool) -> Self {
self.flags.set(WindowFlags::HORIZONTAL_SCROLLBAR, value);
self
}
pub fn no_focus_on_appearing(mut self, value: bool) -> Self {
self.flags.set(WindowFlags::NO_FOCUS_ON_APPEARING, value);
self
}
pub fn no_bring_to_front_on_focus(mut self, value: bool) -> Self {
self.flags
.set(WindowFlags::NO_BRING_TO_FRONT_ON_FOCUS, value);
self
}
pub fn always_vertical_scrollbar(mut self, value: bool) -> Self {
self.flags
.set(WindowFlags::ALWAYS_VERTICAL_SCROLLBAR, value);
self
}
pub fn always_horizontal_scrollbar(mut self, value: bool) -> Self {
self.flags
.set(WindowFlags::ALWAYS_HORIZONTAL_SCROLLBAR, value);
self
}
pub fn always_use_window_padding(mut self, value: bool) -> Self {
self.flags
.set(WindowFlags::ALWAYS_USE_WINDOW_PADDING, value);
self
}
/// Consume and draw the PopupModal.
/// Returns the result of the closure, if it is called.
#[doc(alias = "BeginPopupModal")]
pub fn build<T, F: FnOnce() -> T>(self, ui: &Ui<'_>, f: F) -> Option<T> {
self.begin_popup(ui).map(|_popup| f())
}
/// Consume and draw the PopupModal.
/// Construct a popup that can have any kind of content.
///
/// This should be called *per frame*, whereas [`Ui::open_popup`]
/// should be called *once* when you want to actual create the popup.
#[doc(alias = "BeginPopupModal")]
pub fn begin_popup<'ui>(self, ui: &Ui<'ui>) -> Option<PopupToken<'ui>> {
let render = unsafe {
sys::igBeginPopupModal(
ui.scratch_txt(self.label),
self.opened
.map(|x| x as *mut bool)
.unwrap_or(ptr::null_mut()),
self.flags.bits() as i32,
)
};
if render {
Some(PopupToken::new(ui))
} else {
None
}
}
}
// Widgets: Popups
impl<'ui> Ui<'ui> {
/// Instructs ImGui to open a popup, which must be began with either [`begin_popup`](Self::begin_popup)
/// or [`popup`](Self::popup). You also use this function to begin [PopupModal].
///
/// The confusing aspect to popups is that ImGui holds "control" over the popup fundamentally, so that ImGui
/// can also force close a popup when a user clicks outside a popup. If you do not want users to be
/// able to close a popup without selected an option, use [`PopupModal`].
#[doc(alias = "OpenPopup")]
pub fn open_popup(&self, str_id: impl AsRef<str>) {
unsafe { sys::igOpenPopup_Str(self.scratch_txt(str_id), 0) };
}
/// Construct a popup that can have any kind of content.
///
/// This should be called *per frame*, whereas [`open_popup`](Self::open_popup) should be called *once*
/// when you want to actual create the popup.
#[doc(alias = "BeginPopup")]
pub fn begin_popup(&self, str_id: impl AsRef<str>) -> Option<PopupToken<'_>> {
let render = unsafe {
sys::igBeginPopup(self.scratch_txt(str_id), WindowFlags::empty().bits() as i32)
};
if render {
Some(PopupToken::new(self))
} else {
None
}
}
/// Construct a popup that can have any kind of content.
///
/// This should be called *per frame*, whereas [`open_popup`](Self::open_popup) should be called *once*
/// when you want to actual create the popup.
#[doc(alias = "BeginPopup")]
pub fn popup<F>(&self, str_id: impl AsRef<str>, f: F)
where
F: FnOnce(),
{
if let Some(_t) = self.begin_popup(str_id) {
f();
}
}
/// Creates a PopupModal directly.
pub fn popup_modal<'p, Label: AsRef<str>>(&self, str_id: Label) -> PopupModal<'p, Label> {
PopupModal::new(str_id)
}
/// Close a popup. Should be called within the closure given as argument to
/// [`Ui::popup`] or [`Ui::popup_modal`].
#[doc(alias = "CloseCurrentPopup")]
pub fn close_current_popup(&self) {
unsafe { sys::igCloseCurrentPopup() };
}
}
create_token!(
/// Tracks a popup token that can be ended with `end` or by dropping.
pub struct PopupToken<'ui>;
/// Drops the popup token manually. You can also just allow this token
/// to drop on its own.
drop { sys::igEndPopup() }
);

View File

@@ -1,285 +0,0 @@
use std::slice;
use crate::internal::{RawCast, RawWrapper};
use crate::render::renderer::TextureId;
use crate::sys;
/// All draw data to render a Dear ImGui frame.
#[repr(C)]
pub struct DrawData {
/// Only valid after render() is called and before the next new frame() is called.
valid: bool,
/// Number of DrawList to render.
cmd_lists_count: i32,
/// For convenience, sum of all draw list index buffer sizes.
pub total_idx_count: i32,
/// For convenience, sum of all draw list vertex buffer sizes.
pub total_vtx_count: i32,
// Array of DrawList.
cmd_lists: *mut *mut DrawList,
/// Upper-left position of the viewport to render.
///
/// (= upper-left corner of the orthogonal projection matrix to use)
pub display_pos: [f32; 2],
/// Size of the viewport to render.
///
/// (= display_pos + display_size == lower-right corner of the orthogonal matrix to use)
pub display_size: [f32; 2],
/// Amount of pixels for each unit of display_size.
///
/// Based on io.display_frame_buffer_scale. Typically [1.0, 1.0] on normal displays, and
/// [2.0, 2.0] on Retina displays, but fractional values are also possible.
pub framebuffer_scale: [f32; 2],
}
unsafe impl RawCast<sys::ImDrawData> for DrawData {}
impl DrawData {
/// Returns an iterator over the draw lists included in the draw data.
#[inline]
pub fn draw_lists(&self) -> DrawListIterator<'_> {
unsafe {
DrawListIterator {
iter: self.cmd_lists().iter(),
}
}
}
/// Returns the number of draw lists included in the draw data.
#[inline]
pub fn draw_lists_count(&self) -> usize {
use std::convert::TryInto;
self.cmd_lists_count.try_into().unwrap()
}
#[inline]
pub(crate) unsafe fn cmd_lists(&self) -> &[*const DrawList] {
slice::from_raw_parts(
self.cmd_lists as *const *const DrawList,
self.cmd_lists_count as usize,
)
}
/// Converts all buffers from indexed to non-indexed, in case you cannot render indexed
/// buffers.
///
/// **This is slow and most likely a waste of resources. Always prefer indexed rendering!**
#[doc(alias = "DeIndexAllBuffers")]
pub fn deindex_all_buffers(&mut self) {
unsafe {
sys::ImDrawData_DeIndexAllBuffers(self.raw_mut());
}
}
/// Scales the clip rect of each draw command.
///
/// Can be used if your final output buffer is at a different scale than imgui-rs expects, or
/// if there is a difference between your window resolution and framebuffer resolution.
#[doc(alias = "ScaleClipRects")]
pub fn scale_clip_rects(&mut self, fb_scale: [f32; 2]) {
unsafe {
sys::ImDrawData_ScaleClipRects(self.raw_mut(), fb_scale.into());
}
}
}
/// Iterator over draw lists
pub struct DrawListIterator<'a> {
iter: std::slice::Iter<'a, *const DrawList>,
}
impl<'a> Iterator for DrawListIterator<'a> {
type Item = &'a DrawList;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|&ptr| unsafe { &*ptr })
}
}
#[test]
#[cfg(test)]
fn test_drawdata_memory_layout() {
use std::mem;
assert_eq!(
mem::size_of::<DrawData>(),
mem::size_of::<sys::ImDrawData>()
);
assert_eq!(
mem::align_of::<DrawData>(),
mem::align_of::<sys::ImDrawData>()
);
use sys::ImDrawData;
macro_rules! assert_field_offset {
($l:ident, $r:ident) => {
assert_eq!(
memoffset::offset_of!(DrawData, $l),
memoffset::offset_of!(ImDrawData, $r)
);
};
}
assert_field_offset!(valid, Valid);
assert_field_offset!(cmd_lists, CmdLists);
assert_field_offset!(cmd_lists_count, CmdListsCount);
assert_field_offset!(total_idx_count, TotalIdxCount);
assert_field_offset!(total_vtx_count, TotalVtxCount);
assert_field_offset!(display_pos, DisplayPos);
assert_field_offset!(display_size, DisplaySize);
assert_field_offset!(framebuffer_scale, FramebufferScale);
}
/// Draw command list
#[repr(transparent)]
pub struct DrawList(sys::ImDrawList);
impl RawWrapper for DrawList {
type Raw = sys::ImDrawList;
#[inline]
unsafe fn raw(&self) -> &sys::ImDrawList {
&self.0
}
#[inline]
unsafe fn raw_mut(&mut self) -> &mut sys::ImDrawList {
&mut self.0
}
}
impl DrawList {
#[inline]
pub(crate) unsafe fn cmd_buffer(&self) -> &[sys::ImDrawCmd] {
slice::from_raw_parts(
self.0.CmdBuffer.Data as *const sys::ImDrawCmd,
self.0.CmdBuffer.Size as usize,
)
}
#[inline]
pub fn idx_buffer(&self) -> &[DrawIdx] {
unsafe {
slice::from_raw_parts(
self.0.IdxBuffer.Data as *const DrawIdx,
self.0.IdxBuffer.Size as usize,
)
}
}
#[inline]
pub fn vtx_buffer(&self) -> &[DrawVert] {
unsafe {
slice::from_raw_parts(
self.0.VtxBuffer.Data as *const DrawVert,
self.0.VtxBuffer.Size as usize,
)
}
}
/// # Safety
/// This is equivalent to `transmute(self.vtx_buffer())` with a little more
/// checking, and thus inherits the safety considerations of `transmute`ing
/// slices.
pub unsafe fn transmute_vtx_buffer<VTy: Copy>(&self) -> &[VTy] {
// these checks are constant and thus are removed from release builds
assert_eq!(
core::mem::size_of::<VTy>(),
core::mem::size_of::<DrawVert>(),
);
assert!(core::mem::align_of::<VTy>() <= core::mem::align_of::<DrawVert>());
slice::from_raw_parts(self.0.VtxBuffer.Data.cast(), self.0.VtxBuffer.Size as usize)
}
#[inline]
pub fn commands(&self) -> DrawCmdIterator<'_> {
unsafe {
DrawCmdIterator {
iter: self.cmd_buffer().iter(),
}
}
}
}
pub struct DrawCmdIterator<'a> {
iter: std::slice::Iter<'a, sys::ImDrawCmd>,
}
impl<'a> Iterator for DrawCmdIterator<'a> {
type Item = DrawCmd;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|cmd| {
let cmd_params = DrawCmdParams {
clip_rect: cmd.ClipRect.into(),
texture_id: TextureId::from(cmd.TextureId),
vtx_offset: cmd.VtxOffset as usize,
idx_offset: cmd.IdxOffset as usize,
};
match cmd.UserCallback {
Some(raw_callback) if raw_callback as usize == -1isize as usize => {
DrawCmd::ResetRenderState
}
Some(raw_callback) => DrawCmd::RawCallback {
callback: raw_callback,
raw_cmd: cmd,
},
None => DrawCmd::Elements {
count: cmd.ElemCount as usize,
cmd_params,
},
}
})
}
}
/// A vertex index
pub type DrawIdx = sys::ImDrawIdx;
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct DrawCmdParams {
/// left, up, right, down
pub clip_rect: [f32; 4],
pub texture_id: TextureId,
pub vtx_offset: usize,
pub idx_offset: usize,
}
/// A draw command
pub enum DrawCmd {
Elements {
/// The number of indices used for this draw command
count: usize,
cmd_params: DrawCmdParams,
},
ResetRenderState,
RawCallback {
callback: unsafe extern "C" fn(*const sys::ImDrawList, cmd: *const sys::ImDrawCmd),
raw_cmd: *const sys::ImDrawCmd,
},
}
/// A single vertex
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct DrawVert {
pub pos: [f32; 2],
pub uv: [f32; 2],
pub col: [u8; 4],
}
#[test]
#[cfg(test)]
fn test_drawvert_memory_layout() {
use std::mem;
assert_eq!(
mem::size_of::<DrawVert>(),
mem::size_of::<sys::ImDrawVert>()
);
assert_eq!(
mem::align_of::<DrawVert>(),
mem::align_of::<sys::ImDrawVert>()
);
use sys::ImDrawVert;
macro_rules! assert_field_offset {
($l:ident, $r:ident) => {
assert_eq!(
memoffset::offset_of!(DrawVert, $l),
memoffset::offset_of!(ImDrawVert, $r)
);
};
}
assert_field_offset!(pos, pos);
assert_field_offset!(uv, uv);
assert_field_offset!(col, col);
}

View File

@@ -1,2 +0,0 @@
pub mod draw_data;
pub mod renderer;

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