mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-28 15:57:03 -05:00
Compare commits
540 Commits
feature/ru
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a8f19cc90 | ||
|
|
854535fec6 | ||
|
|
a109e14ee3 | ||
|
|
eca7597aca | ||
|
|
936b5b6312 | ||
|
|
cea63f6561 | ||
|
|
7083b6ab3e | ||
|
|
432e16e0c4 | ||
|
|
8d691b2e6a | ||
|
|
f3ccbb9b84 | ||
|
|
a4af283a37 | ||
|
|
27935b1234 | ||
|
|
ea0b97a066 | ||
|
|
e668feb807 | ||
|
|
21a94d67c2 | ||
|
|
fbd6d6b9fc | ||
|
|
257d122a9f | ||
|
|
f7f70a16da | ||
|
|
aa5a83444d | ||
|
|
d25c80c0a5 | ||
|
|
6f83b050cd | ||
|
|
72e177aafc | ||
|
|
5648378837 | ||
|
|
c1cdef7ca1 | ||
|
|
4b07f7745b | ||
|
|
a2fc9325c9 | ||
|
|
380b1dbce3 | ||
|
|
04a8bd6798 | ||
|
|
0cf27b9e9e | ||
|
|
4a091f452e | ||
|
|
ffa8b0d0db | ||
|
|
ff65217b7e | ||
|
|
1b90bb2c34 | ||
|
|
1018aea395 | ||
|
|
d20d6736b3 | ||
|
|
5333a33775 | ||
|
|
0d9ea8a1d1 | ||
|
|
b6a90aa89d | ||
|
|
060f0e6e56 | ||
|
|
800a24b42e | ||
|
|
a5008722aa | ||
|
|
a0b0082d98 | ||
|
|
f476842008 | ||
|
|
d39d107de4 | ||
|
|
7f889a75bb | ||
|
|
70fdbd4a48 | ||
|
|
71c71c5bbf | ||
|
|
ade8c8f68d | ||
|
|
16b02caf7a | ||
|
|
dc1c205fb1 | ||
|
|
b974533f96 | ||
|
|
81e561d47b | ||
|
|
b9e0a9f0e6 | ||
|
|
954bcadd75 | ||
|
|
d6781e7f93 | ||
|
|
fc38c27769 | ||
|
|
96a5a5d34c | ||
|
|
928e0f227a | ||
|
|
93fc6f2de1 | ||
|
|
cdc260b45c | ||
|
|
0e41813cfc | ||
|
|
a7e94e31c9 | ||
|
|
2903a97941 | ||
|
|
753e1ceff6 | ||
|
|
06f4d12f10 | ||
|
|
684c2e66fb | ||
|
|
4a311ed69f | ||
|
|
220b5f9772 | ||
|
|
42fd5b0fef | ||
|
|
c28492e51d | ||
|
|
d8ff84672c | ||
|
|
2af967d788 | ||
|
|
8cb23e8200 | ||
|
|
9a058efc79 | ||
|
|
06c8cb51e3 | ||
|
|
01e8ae1b5c | ||
|
|
b052cb001c | ||
|
|
d004eb3048 | ||
|
|
dccd74667e | ||
|
|
6b6470850f | ||
|
|
f09b1aae23 | ||
|
|
68487bc903 | ||
|
|
ebd78e1526 | ||
|
|
6d0dfcfe2e | ||
|
|
5b01d23ed7 | ||
|
|
d9eb01b526 | ||
|
|
9e165ac4a1 | ||
|
|
25ab371a81 | ||
|
|
d62abaed8d | ||
|
|
1fb7a318ed | ||
|
|
e29ae631fc | ||
|
|
3cc0b9294e | ||
|
|
e80f7fa14f | ||
|
|
9261fd7190 | ||
|
|
58c714b350 | ||
|
|
5cd3f5c255 | ||
|
|
0d443d7d00 | ||
|
|
38fecca489 | ||
|
|
f655ea59a8 | ||
|
|
aa7daa5c54 | ||
|
|
f4b2be9334 | ||
|
|
edbd8a811e | ||
|
|
ea9b197d36 | ||
|
|
a0a049a920 | ||
|
|
550fe8e4aa | ||
|
|
2064aea3b6 | ||
|
|
3411bc4577 | ||
|
|
6eedb469e9 | ||
|
|
684373b88b | ||
|
|
08aa03bab6 | ||
|
|
62bc953d53 | ||
|
|
5263f81487 | ||
|
|
8272ebf68f | ||
|
|
90d8e03f2c | ||
|
|
0d34edc7f6 | ||
|
|
63fd61e245 | ||
|
|
58fe8a22a9 | ||
|
|
03dd20c263 | ||
|
|
712a125be7 | ||
|
|
49e14e6e7c | ||
|
|
e8a6e102c3 | ||
|
|
b2cc09852d | ||
|
|
60627b8325 | ||
|
|
8fc2d6b225 | ||
|
|
051cdfa305 | ||
|
|
bfa807ca8b | ||
|
|
598914a67a | ||
|
|
3274649b77 | ||
|
|
5756105347 | ||
|
|
ed583d8bd1 | ||
|
|
731cf10207 | ||
|
|
cb898ce8cf | ||
|
|
892334e31a | ||
|
|
a16e16853f | ||
|
|
5cec83b3ef | ||
|
|
a628784c6d | ||
|
|
fd8b70fb12 | ||
|
|
3dad5a43a1 | ||
|
|
89dea86b3b | ||
|
|
42da24e31d | ||
|
|
5b9b5d4f1f | ||
|
|
5332a26294 | ||
|
|
54d9f8ec5c | ||
|
|
73a17308cc | ||
|
|
b835c48a0c | ||
|
|
40b604c6e4 | ||
|
|
1fd3580f97 | ||
|
|
e28f3b75a4 | ||
|
|
53153ca3e0 | ||
|
|
a496b14a0f | ||
|
|
da6e7240d6 | ||
|
|
89981c6994 | ||
|
|
fe22a43e09 | ||
|
|
3e1a797ea7 | ||
|
|
b23ce7ba18 | ||
|
|
6165f891ca | ||
|
|
7df4b1157c | ||
|
|
64cbd5fc8d | ||
|
|
ba7e789a80 | ||
|
|
d6d70ca076 | ||
|
|
88c37bb7d9 | ||
|
|
59b4f4efce | ||
|
|
ed1f120b0b | ||
|
|
bf461abfec | ||
|
|
d42665db88 | ||
|
|
33c4dc3347 | ||
|
|
6d976fb785 | ||
|
|
39b43cec2d | ||
|
|
691b56b4ac | ||
|
|
bf1f613052 | ||
|
|
721ed9f2a2 | ||
|
|
f760b1ba83 | ||
|
|
1dba144fca | ||
|
|
ebc1b531ff | ||
|
|
5ecf122686 | ||
|
|
56ed18882c | ||
|
|
86c555d053 | ||
|
|
49ec30899e | ||
|
|
d4a2b617bd | ||
|
|
8e7bd4b98a | ||
|
|
ea359285e0 | ||
|
|
d4bfa5d284 | ||
|
|
4433006842 | ||
|
|
646ebcdd00 | ||
|
|
8b53b36b20 | ||
|
|
64db392699 | ||
|
|
bff78704cc | ||
|
|
40651e8dfd | ||
|
|
e5d9d9ec9e | ||
|
|
4e628826c3 | ||
|
|
018bedb2bd | ||
|
|
33e315709a | ||
|
|
8b14a4775b | ||
|
|
fa8fdb0170 | ||
|
|
f856e16917 | ||
|
|
3b5271ab77 | ||
|
|
428fbddbbb | ||
|
|
5774837a6e | ||
|
|
17c2dfcbd0 | ||
|
|
a1711ccfa6 | ||
|
|
261610dcf1 | ||
|
|
92cfdf1145 | ||
|
|
155465b8c6 | ||
|
|
6f49bbdd41 | ||
|
|
3badaa5cba | ||
|
|
a66747a0d0 | ||
|
|
c376759be0 | ||
|
|
1c17f3ee43 | ||
|
|
5f549cc8aa | ||
|
|
f97be02087 | ||
|
|
2d82776e62 | ||
|
|
fdee0ac3e3 | ||
|
|
d775b80a44 | ||
|
|
2047a41498 | ||
|
|
f88890a052 | ||
|
|
5500faa57e | ||
|
|
89004574d3 | ||
|
|
c11c05a399 | ||
|
|
baa3329e7f | ||
|
|
e696d384c2 | ||
|
|
932c281223 | ||
|
|
858fe0384e | ||
|
|
e904cd749f | ||
|
|
6b16f39be4 | ||
|
|
021c7e5fdb | ||
|
|
c161a5c71b | ||
|
|
76ccdbccea | ||
|
|
553ee89787 | ||
|
|
cb6247b16e | ||
|
|
cfac7ff0ba | ||
|
|
49bbe7dc77 | ||
|
|
07b6fa0e2e | ||
|
|
67396f2009 | ||
|
|
a20ff87cc9 | ||
|
|
e02e57a729 | ||
|
|
225dc53795 | ||
|
|
e7404376db | ||
|
|
d6aec341fe | ||
|
|
3a3c2fb204 | ||
|
|
e9b5cdbccf | ||
|
|
3f30e63d95 | ||
|
|
f9c6866c7b | ||
|
|
388dccfd9f | ||
|
|
1676342e28 | ||
|
|
62732de227 | ||
|
|
63e777c84c | ||
|
|
ab95cdf3e5 | ||
|
|
827b5b01dd | ||
|
|
bfa9788099 | ||
|
|
de25ce7fbb | ||
|
|
21e61bfce6 | ||
|
|
82e168c438 | ||
|
|
48583a2b6e | ||
|
|
0db0982fa7 | ||
|
|
6a28ce9e4b | ||
|
|
1db79f6117 | ||
|
|
f234103320 | ||
|
|
45c382a19a | ||
|
|
fb7ef61d06 | ||
|
|
2586645d02 | ||
|
|
e23cb5509d | ||
|
|
5cbd53ae7a | ||
|
|
a4ee590875 | ||
|
|
495608ed7c | ||
|
|
4d10d9a195 | ||
|
|
4914a34dd9 | ||
|
|
ab0fb3131d | ||
|
|
7922d3b3cb | ||
|
|
6427f53b5a | ||
|
|
994df0a3a4 | ||
|
|
e6eee55810 | ||
|
|
855e4c4913 | ||
|
|
c2e07bf7b2 | ||
|
|
77b9e3eac8 | ||
|
|
790487eea6 | ||
|
|
eb83354179 | ||
|
|
9ba8754f97 | ||
|
|
84346119b3 | ||
|
|
2b3abd06db | ||
|
|
8267aad79e | ||
|
|
3f9ce561b9 | ||
|
|
347fc3ed9f | ||
|
|
0488c996e9 | ||
|
|
37bfd97d93 | ||
|
|
c8652b0576 | ||
|
|
1208d2eb5e | ||
|
|
ab34fed0c5 | ||
|
|
0906e5f9cf | ||
|
|
47b1c603b3 | ||
|
|
4bda321e7a | ||
|
|
691ff11fbc | ||
|
|
83650c908d | ||
|
|
afa297bb53 | ||
|
|
00986d0ea8 | ||
|
|
633914316a | ||
|
|
205bb81a0a | ||
|
|
60a69e3a54 | ||
|
|
5c629494da | ||
|
|
95f010395c | ||
|
|
d575d0f724 | ||
|
|
bdbdb46005 | ||
|
|
efc28a3177 | ||
|
|
5d50653495 | ||
|
|
24c55beb9c | ||
|
|
04547ad6af | ||
|
|
d2951d06b2 | ||
|
|
926910bf6e | ||
|
|
6652750044 | ||
|
|
ab3853eb9d | ||
|
|
4f4af83699 | ||
|
|
df3200f936 | ||
|
|
7374a06faa | ||
|
|
22b13f5ba6 | ||
|
|
031301e1bb | ||
|
|
3ad508c6fc | ||
|
|
c3421aef8c | ||
|
|
f2e8d402dd | ||
|
|
ab54acb176 | ||
|
|
7585e191d0 | ||
|
|
a4f6795a44 | ||
|
|
3529bce009 | ||
|
|
bc3afbb271 | ||
|
|
a0d0621725 | ||
|
|
c2d70dbd50 | ||
|
|
e2fdd91956 | ||
|
|
2a84534ced | ||
|
|
94b53592d9 | ||
|
|
09006588fc | ||
|
|
9d5cdaeb33 | ||
|
|
d4df465633 | ||
|
|
da0c1674a6 | ||
|
|
18aa11117a | ||
|
|
ed32439645 | ||
|
|
5c890e710e | ||
|
|
d15b7862b8 | ||
|
|
0e5136196a | ||
|
|
46fdbd5bc0 | ||
|
|
da755ec75b | ||
|
|
d610f787b9 | ||
|
|
1ab1f7ada0 | ||
|
|
56cb1f2747 | ||
|
|
413c6b5116 | ||
|
|
f4753a5bd8 | ||
|
|
980438008c | ||
|
|
8f57dd86af | ||
|
|
a2ce89af32 | ||
|
|
67008288e2 | ||
|
|
4caa0ce570 | ||
|
|
4e2dcef7d7 | ||
|
|
f47a248768 | ||
|
|
862462c5bb | ||
|
|
375471160f | ||
|
|
4000e7c886 | ||
|
|
48095671c3 | ||
|
|
c96b47f345 | ||
|
|
b250172bb5 | ||
|
|
257b248f34 | ||
|
|
a8fe63ee93 | ||
|
|
d359a21a66 | ||
|
|
e5cdf22753 | ||
|
|
c33d53b728 | ||
|
|
e5829a316b | ||
|
|
569bf474bd | ||
|
|
06ecd5d571 | ||
|
|
9ae233a41c | ||
|
|
989f7f7678 | ||
|
|
a75947e611 | ||
|
|
1d4233514f | ||
|
|
fa780e9706 | ||
|
|
cba93e87eb | ||
|
|
f3a2fe5b0d | ||
|
|
ebee8ff0a6 | ||
|
|
34971162cb | ||
|
|
58eec483c9 | ||
|
|
c57f071f0c | ||
|
|
b30e2bcfa4 | ||
|
|
b56c3c5a46 | ||
|
|
120c4202b4 | ||
|
|
1f257290ab | ||
|
|
4d585d17de | ||
|
|
2c7da65242 | ||
|
|
95ff52b025 | ||
|
|
b1e2185966 | ||
|
|
5d77402211 | ||
|
|
f762cc2906 | ||
|
|
7ca2e558c9 | ||
|
|
e388d0c5e8 | ||
|
|
05f8d9302d | ||
|
|
8f277f00a4 | ||
|
|
59f9da59e2 | ||
|
|
8d4415fe15 | ||
|
|
fd54b2b803 | ||
|
|
ba6953fda4 | ||
|
|
c0f667ce20 | ||
|
|
c93c15563a | ||
|
|
d0340c13dc | ||
|
|
c6caa1d067 | ||
|
|
2f0efa1197 | ||
|
|
a76eae2c11 | ||
|
|
b82c1f051c | ||
|
|
1b6a150624 | ||
|
|
265360229f | ||
|
|
98e9729267 | ||
|
|
cfe16ee2c5 | ||
|
|
c9f856b219 | ||
|
|
3c167c3306 | ||
|
|
fedbce6f9e | ||
|
|
28be4cea97 | ||
|
|
05fb2bfd23 | ||
|
|
3905335c53 | ||
|
|
4dc3f9e033 | ||
|
|
07a6a9b7d4 | ||
|
|
fac7dff77f | ||
|
|
60c7ced335 | ||
|
|
8f981e7707 | ||
|
|
725cc10a92 | ||
|
|
d3896ccfda | ||
|
|
de3e532a5c | ||
|
|
98369600c3 | ||
|
|
d9aaef29d2 | ||
|
|
48f4410a2a | ||
|
|
ca0b232ada | ||
|
|
75efe39298 | ||
|
|
84342f7a7b | ||
|
|
67efea6444 | ||
|
|
f08b182bf2 | ||
|
|
3c83a62aef | ||
|
|
821db4d2a1 | ||
|
|
3c661842a2 | ||
|
|
920578003e | ||
|
|
22aadcc1ae | ||
|
|
efc65479c6 | ||
|
|
dcbba9cbfc | ||
|
|
6169078c04 | ||
|
|
955f48f532 | ||
|
|
d7a830ca95 | ||
|
|
96b27645d6 | ||
|
|
8b6346ae41 | ||
|
|
c1619820c7 | ||
|
|
88ccb0e075 | ||
|
|
12564dd78f | ||
|
|
b0c4db7a64 | ||
|
|
310ca6c6dc | ||
|
|
32e3a4e74f | ||
|
|
be66e3fe79 | ||
|
|
d794734f1d | ||
|
|
8661b6551d | ||
|
|
a0326c4371 | ||
|
|
b039bc14c6 | ||
|
|
d08853df8c | ||
|
|
d8dd287cdf | ||
|
|
d62b64c27a | ||
|
|
52952652de | ||
|
|
790c19a1cd | ||
|
|
9659381378 | ||
|
|
4598fc098d | ||
|
|
2f6fde1e61 | ||
|
|
16dc199431 | ||
|
|
715e970d99 | ||
|
|
53535ab9be | ||
|
|
24f9df90b8 | ||
|
|
4cfdbb8095 | ||
|
|
fe4cb8575f | ||
|
|
06ac7eb85f | ||
|
|
0e14ff5a3d | ||
|
|
c65015fcc7 | ||
|
|
c8caf6124e | ||
|
|
76bb0e420d | ||
|
|
d2c1b2a31b | ||
|
|
e30f073809 | ||
|
|
e1079d751a | ||
|
|
a9d45d837f | ||
|
|
bcbe5eb105 | ||
|
|
6ab1f8e4e2 | ||
|
|
90f26d53d3 | ||
|
|
281921d1de | ||
|
|
9135153dc9 | ||
|
|
c70b505b3a | ||
|
|
cde9dc37e5 | ||
|
|
ab1e5eb359 | ||
|
|
aec9f7a145 | ||
|
|
bf08ed563a | ||
|
|
ff70518882 | ||
|
|
72364db768 | ||
|
|
92fa72eac7 | ||
|
|
9e2c1de0f5 | ||
|
|
57ac73b9d4 | ||
|
|
2757c577e4 | ||
|
|
704af30421 | ||
|
|
1e8a005d0e | ||
|
|
8a04d2f477 | ||
|
|
a7c37bfb93 | ||
|
|
d1801ea438 | ||
|
|
f6f856cd56 | ||
|
|
8515cd43fa | ||
|
|
8a4cdbb371 | ||
|
|
7fef133505 | ||
|
|
5f206a33e2 | ||
|
|
228385ceaa | ||
|
|
bd9e9a7dcf | ||
|
|
abffb8c138 | ||
|
|
e353802e9f | ||
|
|
130055af22 | ||
|
|
db573840b0 | ||
|
|
e0fccacc32 | ||
|
|
18890f47b6 | ||
|
|
204cc1ccb3 | ||
|
|
a063eb96c6 | ||
|
|
145c8ff804 | ||
|
|
f0d2f94aef | ||
|
|
0c12cb683a | ||
|
|
56b5d026df | ||
|
|
40ccbd0d86 | ||
|
|
c1a14cb4d4 | ||
|
|
df2448e121 | ||
|
|
ca323c392b | ||
|
|
395dd37d33 | ||
|
|
e91689a715 | ||
|
|
861988f8dc | ||
|
|
f26f1298cf | ||
|
|
66efcf91d3 | ||
|
|
0178ba014a | ||
|
|
254bd88e6b | ||
|
|
3808b78487 | ||
|
|
a80c35aa94 | ||
|
|
d0f51d0462 | ||
|
|
013fa85c1c | ||
|
|
fcda856198 | ||
|
|
e385487a6b | ||
|
|
f8fa029ee3 | ||
|
|
d1a0f8ec97 | ||
|
|
d02e147dc3 | ||
|
|
5c481d4247 | ||
|
|
f4cbdde8f6 | ||
|
|
0ac09fc57b | ||
|
|
99c28c93b4 | ||
|
|
0e800723f5 | ||
|
|
fc2ed47676 | ||
|
|
5c2309bcf7 | ||
|
|
ba71a300ec |
166
.clang-tidy
166
.clang-tidy
@@ -1,69 +1,97 @@
|
||||
# Generated from CLion Inspection settings
|
||||
---
|
||||
Checks: '-*,
|
||||
mpi-*,
|
||||
bugprone-*,
|
||||
-bugprone-signal-handler,
|
||||
-bugprone-narrowing-conversions,
|
||||
-bugprone-redundant-branch-condition,
|
||||
-bugprone-exception-escape,
|
||||
-bugprone-shared-ptr-array-mismatch,
|
||||
-bugprone-implicit-widening-of-multiplication-result,
|
||||
-bugprone-signed-char-misuse,
|
||||
-bugprone-unhandled-exception-at-new,
|
||||
-bugprone-infinite-loop,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
cert-err52-cpp,
|
||||
cert-err60-cpp,
|
||||
cert-err34-c,
|
||||
cert-str34-c,
|
||||
cert-dcl21-cpp,
|
||||
cert-msc50-cpp,
|
||||
cert-msc51-cpp,
|
||||
cert-dcl58-cpp,
|
||||
cert-flp30-c,
|
||||
cppcoreguidelines-avoid-const-or-ref-data-members,
|
||||
cppcoreguidelines-pro-type-member-init,
|
||||
cppcoreguidelines-slicing,
|
||||
cppcoreguidelines-interfaces-global-init,
|
||||
cppcoreguidelines-pro-type-static-cast-downcast,
|
||||
cppcoreguidelines-narrowing-conversions,
|
||||
google-default-arguments,
|
||||
google-runtime-operator,
|
||||
google-explicit-constructor,
|
||||
hicpp-multiway-paths-covered,
|
||||
hicpp-exception-baseclass,
|
||||
misc-*,
|
||||
-misc-definitions-in-headers,
|
||||
-misc-unused-parameters,
|
||||
-misc-unused-alias-decls,
|
||||
-misc-use-anonymous-namespace,
|
||||
-misc-misleading-identifier,
|
||||
-misc-confusable-identifiers,
|
||||
-misc-misleading-bidirectional,
|
||||
-misc-static-assert,
|
||||
-misc-no-recursion,
|
||||
-misc-const-correctness,
|
||||
modernize-*,
|
||||
-modernize-use-trailing-return-type,
|
||||
openmp-use-default-none,
|
||||
performance-*,
|
||||
-performance-no-int-to-ptr,
|
||||
portability-*,
|
||||
-portability-restrict-system-includes,
|
||||
readability-*,
|
||||
-readability-redundant-preprocessor,
|
||||
-readability-named-parameter,
|
||||
-readability-function-size,
|
||||
-readability-use-anyofallof,
|
||||
-readability-identifier-length,
|
||||
-readability-magic-numbers,
|
||||
-readability-braces-around-statements,
|
||||
-readability-suspicious-call-argument,
|
||||
-readability-isolate-declaration,
|
||||
-readability-else-after-return,
|
||||
-readability-redundant-access-specifiers,
|
||||
-readability-function-cognitive-complexity,
|
||||
-readability-identifier-naming,
|
||||
*-include-cleaner,
|
||||
-readability-qualified-auto'
|
||||
# All rules should have a comment associated
|
||||
# Directives that do not have any effect (e.g. disabling a rule that is not enabled) can be done to add an explanation comment.
|
||||
# Or at least an empty comment # to show they were put here explicitely,
|
||||
# and not as part of the historical CLion-generated rules
|
||||
# Note: `- -X` means disable X
|
||||
# CLI usage: go to the build directory and run: `run-clang-tidy -allow-no-checks -source-filter ".*/lib/.*" -fix -j`
|
||||
|
||||
Checks:
|
||||
- -*
|
||||
- mpi-*
|
||||
- bugprone-*
|
||||
- -bugprone-signal-handler
|
||||
- -bugprone-narrowing-conversions
|
||||
- -bugprone-redundant-branch-condition
|
||||
- -bugprone-exception-escape
|
||||
- -bugprone-shared-ptr-array-mismatch
|
||||
- -bugprone-implicit-widening-of-multiplication-result
|
||||
- -bugprone-signed-char-misuse
|
||||
- -bugprone-unhandled-exception-at-new
|
||||
- -bugprone-infinite-loop
|
||||
- -bugprone-easily-swappable-parameters
|
||||
- -bugprone-float-loop-counter #
|
||||
- -bugprone-unchecked-string-to-number-conversion # Unfortunately no alternative
|
||||
- -bugprone-branch-clone # Mostly warns about one-line duplicates
|
||||
- cert-err52-cpp
|
||||
- cert-err60-cpp
|
||||
- cert-str34-c
|
||||
- cert-dcl21-cpp
|
||||
- cert-msc50-cpp
|
||||
- cert-msc51-cpp
|
||||
- cert-dcl58-cpp
|
||||
- cppcoreguidelines-avoid-const-or-ref-data-members
|
||||
- cppcoreguidelines-pro-type-member-init # We want to use default member initializers
|
||||
- cppcoreguidelines-slicing
|
||||
- cppcoreguidelines-interfaces-global-init
|
||||
- -cppcoreguidelines-pro-type-static-cast-downcast # dynamic_cast has a runtime overhead
|
||||
- -cppcoreguidelines-narrowing-conversions #
|
||||
- google-runtime-operator
|
||||
- google-explicit-constructor
|
||||
- -google-default-arguments # Provider and ViewProvider read() is a good example of why this is useful
|
||||
- hicpp-multiway-paths-covered
|
||||
- hicpp-exception-baseclass
|
||||
- misc-*
|
||||
- -misc-definitions-in-headers
|
||||
- -misc-unused-parameters
|
||||
- -misc-unused-alias-decls
|
||||
- -misc-use-anonymous-namespace
|
||||
- -misc-misleading-identifier
|
||||
- -misc-confusable-identifiers
|
||||
- -misc-misleading-bidirectional
|
||||
- -misc-static-assert
|
||||
- -misc-no-recursion
|
||||
- -misc-const-correctness
|
||||
- -misc-use-internal-linkage # False positives if header where function is defined is not included
|
||||
- -misc-include-cleaner # Allow indirect includes
|
||||
- -misc-non-private-member-variables-in-classes #
|
||||
- modernize-*
|
||||
- -modernize-use-trailing-return-type
|
||||
- -modernize-use-std-print # We want to use fmt::print instead
|
||||
- -modernize-use-integer-sign-comparison # Too much occurrences to change
|
||||
- openmp-use-default-none
|
||||
- performance-*
|
||||
- -performance-no-int-to-ptr
|
||||
- portability-*
|
||||
- -portability-restrict-system-includes
|
||||
- readability-*
|
||||
- -readability-redundant-preprocessor
|
||||
- -readability-named-parameter
|
||||
- -readability-function-size
|
||||
- -readability-use-anyofallof
|
||||
- -readability-identifier-length
|
||||
- -readability-magic-numbers
|
||||
- -readability-braces-around-statements
|
||||
- -readability-suspicious-call-argument
|
||||
- -readability-isolate-declaration
|
||||
- -readability-else-after-return
|
||||
- -readability-redundant-access-specifiers
|
||||
- -readability-function-cognitive-complexity
|
||||
- -readability-identifier-naming
|
||||
- -readability-qualified-auto
|
||||
- -readability-use-std-min-max # Less readable imo
|
||||
- -readability-math-missing-parentheses # Basic math
|
||||
- -readability-implicit-bool-conversion # Not much of a problem ?
|
||||
- -readability-convert-member-functions-to-static #
|
||||
- -readability-use-concise-preprocessor-directives # We do not use #ifdef
|
||||
- -readability-uppercase-literal-suffix # Not important enough
|
||||
- -readability-redundant-string-cstr # Sometimes used to stop at first null byte
|
||||
- -readability-static-accessed-through-instance #
|
||||
- -readability-ambiguous-smartptr-reset-call # Fix is hard to read
|
||||
|
||||
# Will fix later
|
||||
- -modernize-avoid-c-arrays
|
||||
- -readability-make-member-function-const # idk + lots of occurences
|
||||
- -readability-misleading-indentation # We need to handle cases with #if defined()
|
||||
- -bugprone-unchecked-optional-access
|
||||
- -performance-unnecessary-value-param # idk
|
||||
- -readability-avoid-nested-conditional-operator
|
||||
|
||||
4
.github/FUNDING.yml
vendored
4
.github/FUNDING.yml
vendored
@@ -1,5 +1,5 @@
|
||||
# Sponsor links
|
||||
|
||||
patreon: werwolv
|
||||
custom: https://werwolv.net/donate
|
||||
github: WerWolv
|
||||
ko_fi: WerWolv
|
||||
custom: "https://werwolv.net/donate"
|
||||
|
||||
7
.github/scripts/delete-artifact.sh
vendored
Executable file
7
.github/scripts/delete-artifact.sh
vendored
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
set -xe
|
||||
ARTIFACT_NAME="$1"
|
||||
|
||||
ARTIFACT_ID=$(gh api repos/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID/artifacts --jq ".artifacts[] | select(.name==\"$ARTIFACT_NAME\") | .id")
|
||||
gh api -X DELETE repos/$GITHUB_REPOSITORY/actions/artifacts/$ARTIFACT_ID
|
||||
echo "Deleted artifact $ARTIFACT_NAME with ID $ARTIFACT_ID"
|
||||
19
.github/workflows/analysis.yml
vendored
19
.github/workflows/analysis.yml
vendored
@@ -49,15 +49,16 @@ jobs:
|
||||
set -x
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=gcc-14 CXX=g++-14 cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
|
||||
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
|
||||
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
||||
-G Ninja \
|
||||
CC=gcc-14 CXX=g++-14 cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
|
||||
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
|
||||
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
||||
-DIMHEX_EXCLUDE_PLUGINS="script_loader" \
|
||||
-G Ninja \
|
||||
..
|
||||
ninja install
|
||||
|
||||
|
||||
290
.github/workflows/build.yml
vendored
290
.github/workflows/build.yml
vendored
@@ -1,5 +1,9 @@
|
||||
name: Build
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
@@ -23,10 +27,10 @@ jobs:
|
||||
include:
|
||||
- architecture_name: "x86_64"
|
||||
msystem: "mingw64"
|
||||
runner_os: runs-on=${{ github.run_id }}/image=windows22-base-x64/family=c7a.16xlarge
|
||||
runner_os: "windows-2025"
|
||||
- architecture_name: "arm64"
|
||||
msystem: "clangarm64"
|
||||
runner_os: windows-11-arm
|
||||
runner_os: "windows-11-arm"
|
||||
|
||||
runs-on: ${{ matrix.runner_os }}
|
||||
name: 🪟 Windows MSYS2 ${{ matrix.architecture_name }}
|
||||
@@ -49,7 +53,7 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: 📜 Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@main
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
id: cache-ccache
|
||||
with:
|
||||
key: ${{ runner.os }}-mingw-ccache-${{ github.run_id }}
|
||||
@@ -95,7 +99,6 @@ jobs:
|
||||
-DIMHEX_GENERATE_PDBS=ON \
|
||||
-DIMHEX_REPLACE_DWARF_WITH_PDB=ON \
|
||||
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" \
|
||||
-DCPACK_WIX_VERSION="4" \
|
||||
-DCPACK_WIX_ROOT="$(echo "$USERPROFILE" | tr '\\' '/')/.dotnet/tools" \
|
||||
..
|
||||
|
||||
@@ -106,8 +109,8 @@ jobs:
|
||||
|
||||
- name: 🕯️ Install WiX Toolkit
|
||||
run: |
|
||||
"C:/Program Files/dotnet/dotnet.exe" tool install --global wix
|
||||
"$(echo "$USERPROFILE" | tr '\\' '/')/.dotnet/tools/wix" extension add -g WixToolset.UI.wixext
|
||||
"C:/Program Files/dotnet/dotnet.exe" tool install --global wix@6.0.2
|
||||
"$(echo "$USERPROFILE" | tr '\\' '/')/.dotnet/tools/wix" extension add --global WixToolset.UI.wixext/6.0.2
|
||||
|
||||
- name: 🪲 Create PDBs for MSI
|
||||
run: |
|
||||
@@ -166,6 +169,7 @@ jobs:
|
||||
|
||||
- name: ⬆️ Upload Windows Installer
|
||||
uses: actions/upload-artifact@v4
|
||||
id: upload-installer
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: Windows Installer ${{ matrix.architecture_name }}
|
||||
@@ -186,7 +190,7 @@ jobs:
|
||||
run: |
|
||||
set -x
|
||||
echo "NoGPU version Powered by Mesa 3D : https://fdossena.com/?p=mesa%2Findex.frag" > build/install/MESA.md
|
||||
curl https://downloads.fdossena.com/geth.php?r=mesa64-latest -L -o mesa.7z
|
||||
curl --connect-timeout 30 --retry 5 --retry-delay 0 --retry-max-time 30 https://downloads.fdossena.com/geth.php?r=mesa64-latest -L -o mesa.7z
|
||||
7z e mesa.7z
|
||||
mv opengl32.dll build/install
|
||||
|
||||
@@ -206,10 +210,10 @@ jobs:
|
||||
include:
|
||||
- architecture_name: "x86_64"
|
||||
vs_arch: "amd64"
|
||||
runner_os: runs-on=${{ github.run_id }}/image=windows22-base-x64/family=c7a.16xlarge
|
||||
runner_os: "windows-2025"
|
||||
- architecture_name: "arm64"
|
||||
vs_arch: "amd64_arm64"
|
||||
runner_os: windows-11-arm
|
||||
runner_os: "windows-11-arm"
|
||||
|
||||
runs-on: ${{ matrix.runner_os }}
|
||||
name: 🪟 Windows MSVC ${{ matrix.architecture_name }}
|
||||
@@ -233,7 +237,7 @@ jobs:
|
||||
arch: ${{ matrix.vs_arch }}
|
||||
|
||||
- name: 📜 Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@main
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
id: cache-ccache
|
||||
with:
|
||||
key: ${{ runner.os }}-msvc-${{ matrix.vs_arch }}-ccache-${{ github.run_id }}
|
||||
@@ -242,7 +246,7 @@ jobs:
|
||||
|
||||
- name: 📦 Install vcpkg
|
||||
uses: friendlyanon/setup-vcpkg@v1
|
||||
with: { committish: ef7dbf94b9198bc58f45951adcf1f041fcbc5ea0 }
|
||||
with: { committish: 66c0373dc7fca549e5803087b9487edfe3aca0a1 }
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
run: |
|
||||
@@ -279,7 +283,6 @@ jobs:
|
||||
-DIMHEX_COMMIT_HASH_LONG="$env:GITHUB_SHA" `
|
||||
-DIMHEX_COMMIT_BRANCH="$($env:GITHUB_REF -replace '.*/', '')" `
|
||||
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" `
|
||||
-DCPACK_WIX_VERSION="4" `
|
||||
-DCPACK_WIX_ROOT="$($env:USERPROFILE -replace '\\','/')/.dotnet/tools" `
|
||||
.
|
||||
|
||||
@@ -290,8 +293,8 @@ jobs:
|
||||
|
||||
- name: 🕯️ Install WiX Toolkit
|
||||
run: |
|
||||
& "C:/Program Files/dotnet/dotnet.exe" tool install --global wix
|
||||
& "$($env:USERPROFILE -replace '\\','/')/.dotnet/tools/wix" extension add -g WixToolset.UI.wixext
|
||||
& "C:/Program Files/dotnet/dotnet.exe" tool install --global wix@6.0.2
|
||||
& "$($env:USERPROFILE -replace '\\','/')/.dotnet/tools/wix" extension add --global WixToolset.UI.wixext/6.0.2
|
||||
|
||||
- name: 📦 Bundle MSI
|
||||
run: |
|
||||
@@ -316,7 +319,7 @@ jobs:
|
||||
imhex-*.msi
|
||||
|
||||
win-plugin-template-test:
|
||||
runs-on: runs-on=${{ github.run_id }}/image=windows22-base-x64/family=c7a.16xlarge
|
||||
runs-on: windows-2022
|
||||
name: 🧪 Plugin Template Test
|
||||
|
||||
defaults:
|
||||
@@ -380,24 +383,13 @@ jobs:
|
||||
|
||||
# MacOS build
|
||||
macos-x86:
|
||||
runs-on: macos-13
|
||||
runs-on: macos-15-intel
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- file_suffix: "-NoGPU"
|
||||
name_suffix: "NoGPU"
|
||||
custom_glfw: true
|
||||
- file_suffix: ""
|
||||
name_suffix: ""
|
||||
custom_glfw: false
|
||||
|
||||
name: 🍎 macOS 13 x86_64 ${{ matrix.name_suffix }}
|
||||
name: 🍎 macOS 10.15 x86_64
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
@@ -412,76 +404,55 @@ jobs:
|
||||
- name: 📜 Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: ${{ runner.os }}${{ matrix.file_suffix }}-ccache-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}${{ matrix.file_suffix }}-ccache
|
||||
key: ${{ runner.os }}-ccache-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-ccache
|
||||
max-size: 1G
|
||||
|
||||
- name: Set Xcode version
|
||||
run: sudo xcode-select -s /Library/Developer/CommandLineTools
|
||||
run: |
|
||||
sudo xcode-select --install || true
|
||||
sudo xcode-select -s /Library/Developer/CommandLineTools
|
||||
|
||||
- name: 📦 Install MacPorts
|
||||
run: |
|
||||
wget https://github.com/macports/macports-base/releases/download/v2.11.6/MacPorts-2.11.6-15-Sequoia.pkg
|
||||
sudo installer -pkg MacPorts-2.11.6-15-Sequoia.pkg -target /
|
||||
export PATH=/opt/local/bin:/opt/local/sbin:$PATH
|
||||
echo "PATH=/opt/local/bin:/opt/local/sbin:$PATH" >> $GITHUB_ENV
|
||||
echo "MACOSX_DEPLOYMENT_TARGET=10.15" >> $GITHUB_ENV
|
||||
echo "universal_target 10.15" | sudo tee -a /opt/local/etc/macports/macports.conf
|
||||
echo "macos_deployment_target 10.15" | sudo tee -a /opt/local/etc/macports/macports.conf
|
||||
echo "macosx_sdk_version 10.15" | sudo tee -a /opt/local/etc/macports/macports.conf
|
||||
sudo port selfupdate
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
env:
|
||||
# Make brew not display useless errors
|
||||
HOMEBREW_TESTS: 1
|
||||
run: |
|
||||
brew reinstall python --quiet || true
|
||||
brew link --overwrite --quiet python 2>/dev/null || true
|
||||
brew bundle --quiet --file dist/macOS/Brewfile || true
|
||||
rm -rf /usr/local/Cellar/capstone
|
||||
|
||||
- name: ⬇️ Install classic glfw
|
||||
if: ${{! matrix.custom_glfw }}
|
||||
run: |
|
||||
brew install --quiet glfw || true
|
||||
brew install llvm@21 automake
|
||||
sudo -E port install mbedtls3 nlohmann-json ccache freetype libmagic pkgconfig curl glfw ninja zlib xz bzip2 zstd libssh2 md4c
|
||||
|
||||
- name: ⬇️ Install .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '8.0.100'
|
||||
|
||||
- name: 🧰 Checkout glfw
|
||||
if: ${{ matrix.custom_glfw }}
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: glfw/glfw
|
||||
path: glfw
|
||||
|
||||
# GLFW custom build (to allow software rendering)
|
||||
- name: ⬇️ Patch and install custom glfw
|
||||
if: ${{ matrix.custom_glfw }}
|
||||
run: |
|
||||
set -x
|
||||
cd glfw
|
||||
git apply ../dist/macOS/0001-glfw-SW.patch
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||
-DBUILD_SHARED_LIBS=ON \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
||||
..
|
||||
ninja install
|
||||
|
||||
# MacOS cmake build
|
||||
- name: 🛠️ Configure CMake
|
||||
run: |
|
||||
set -x
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=$(brew --prefix llvm)/bin/clang \
|
||||
CXX=$(brew --prefix llvm)/bin/clang++ \
|
||||
OBJC=$(brew --prefix llvm)/bin/clang \
|
||||
OBJCXX=$(brew --prefix llvm)/bin/clang++ \
|
||||
PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \
|
||||
CC=$(brew --prefix llvm@21)/bin/clang \
|
||||
CXX=$(brew --prefix llvm@21)/bin/clang++ \
|
||||
OBJC=$(brew --prefix llvm@21)/bin/clang \
|
||||
OBJCXX=$(brew --prefix llvm@21)/bin/clang++ \
|
||||
cmake -G "Ninja" \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 \
|
||||
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||
-DIMHEX_GENERATE_PACKAGE=ON \
|
||||
-DIMHEX_SYSTEM_LIBRARY_PATH="$(brew --prefix llvm)/lib;$(brew --prefix llvm)/lib/unwind;$(brew --prefix llvm)/lib/c++;$(brew --prefix)/lib" \
|
||||
-DIMHEX_SYSTEM_LIBRARY_PATH="$(brew --prefix llvm@21)/lib;$(brew --prefix llvm@21)/lib/unwind;$(brew --prefix llvm@21)/lib/c++;$(brew --prefix)/lib" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||
@@ -499,7 +470,6 @@ jobs:
|
||||
run: |
|
||||
set -x
|
||||
cd build/install
|
||||
mv imhex.app ImHex.app
|
||||
codesign --remove-signature ImHex.app
|
||||
codesign --force --deep --sign - ImHex.app
|
||||
|
||||
@@ -528,7 +498,7 @@ jobs:
|
||||
break;
|
||||
fi
|
||||
done
|
||||
mv *.dmg ../../imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.file_suffix }}-x86_64.dmg
|
||||
mv *.dmg ../../imhex-${{ env.IMHEX_VERSION }}-macOS-x86_64.dmg
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
@@ -541,12 +511,12 @@ jobs:
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: macOS DMG ${{ matrix.name_suffix }} x86_64
|
||||
name: macOS DMG x86_64
|
||||
path: ./*.dmg
|
||||
|
||||
macos-arm64:
|
||||
runs-on: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
|
||||
name: 🍎 macOS 13 arm64
|
||||
runs-on: ubuntu-24.04
|
||||
name: 🍎 macOS 11 arm64
|
||||
|
||||
outputs:
|
||||
IMHEX_VERSION: ${{ steps.build.outputs.IMHEX_VERSION }}
|
||||
@@ -590,11 +560,11 @@ jobs:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache
|
||||
gh actions-cache delete "build-macos-arm64-cache" --confirm || true
|
||||
gh cache delete "macos-arm64-cache" --confirm || true
|
||||
|
||||
macos-arm64-package:
|
||||
runs-on: macos-13
|
||||
name: 🍎 macOS 13 arm64 Packaging
|
||||
runs-on: macos-15-intel
|
||||
name: 🍎 macOS 11 arm64 Packaging
|
||||
needs: macos-arm64
|
||||
|
||||
env:
|
||||
@@ -620,7 +590,6 @@ jobs:
|
||||
run: |
|
||||
set -x
|
||||
cd out
|
||||
mv imhex.app ImHex.app
|
||||
codesign --remove-signature ImHex.app
|
||||
codesign --force --deep --entitlements Entitlements.plist --sign - ImHex.app
|
||||
|
||||
@@ -671,15 +640,21 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- release_num: "24.04"
|
||||
- release_num: "24.10"
|
||||
- release_num: "25.04"
|
||||
- name: "Ubuntu"
|
||||
release_num: "24.04"
|
||||
image: "ubuntu:24.04"
|
||||
- name: "Ubuntu"
|
||||
release_num: "25.10"
|
||||
image: "ubuntu:25.10"
|
||||
- name: "Debian"
|
||||
release_num: "13"
|
||||
image: "debian:13"
|
||||
|
||||
name: 🐧 Ubuntu ${{ matrix.release_num }}
|
||||
runs-on: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
|
||||
name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }} x86_64
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
container:
|
||||
image: "ubuntu:${{ matrix.release_num }}"
|
||||
image: "${{ matrix.image }}"
|
||||
options: --privileged
|
||||
|
||||
permissions:
|
||||
@@ -698,8 +673,8 @@ jobs:
|
||||
- name: 📜 Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: Ubuntu-${{ matrix.release_num }}-ccache-${{ github.run_id }}
|
||||
restore-keys: Ubuntu-${{ matrix.release_num }}-ccache
|
||||
key: ${{ matrix.image }}-ccache-${{ github.run_id }}
|
||||
restore-keys: ${{ matrix.image }}-ccache
|
||||
max-size: 1G
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
@@ -744,7 +719,7 @@ jobs:
|
||||
run: |
|
||||
cp -r build/DEBIAN build/DebDir
|
||||
dpkg-deb -Zzstd --build build/DebDir
|
||||
mv build/DebDir.deb imhex-${{ env.IMHEX_VERSION }}-Ubuntu-${{ matrix.release_num }}-x86_64.deb
|
||||
mv build/DebDir.deb imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.deb
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
@@ -757,7 +732,7 @@ jobs:
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: Ubuntu ${{ matrix.release_num }} DEB x86_64
|
||||
name: ${{ matrix.name }} ${{ matrix.release_num }} DEB x86_64
|
||||
path: '*.deb'
|
||||
|
||||
# AppImage build
|
||||
@@ -769,11 +744,11 @@ jobs:
|
||||
- architecture: "x86_64"
|
||||
architecture_package: "amd64"
|
||||
architecture_appimage_builder: "x86_64"
|
||||
image: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
|
||||
image: ubuntu-24.04
|
||||
- architecture: "arm64"
|
||||
architecture_package: "arm64"
|
||||
architecture_appimage_builder: "aarch64"
|
||||
image: runs-on=${{ github.run_id }}/runner=16cpu-linux-arm64/image=ubuntu24-full-arm64
|
||||
image: ubuntu-24.04-arm
|
||||
|
||||
runs-on: ${{ matrix.image }}
|
||||
name: ⬇️ AppImage ${{ matrix.architecture }}
|
||||
@@ -832,8 +807,8 @@ jobs:
|
||||
|
||||
# ArchLinux build
|
||||
archlinux-build:
|
||||
name: 🐧 ArchLinux
|
||||
runs-on: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
|
||||
name: 🐧 ArchLinux x86_64
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
container:
|
||||
image: archlinux:base-devel
|
||||
@@ -948,20 +923,11 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- name: Fedora
|
||||
release_num: rawhide
|
||||
mock_config: fedora-rawhide
|
||||
- name: Fedora
|
||||
release_num: 42
|
||||
mock_config: fedora-42
|
||||
- name: Fedora
|
||||
release_num: 41
|
||||
mock_config: fedora-41
|
||||
- name: RHEL-AlmaLinux
|
||||
release_num: 9
|
||||
mock_config: "alma+epel-9"
|
||||
release_num: 43
|
||||
mock_config: fedora-43
|
||||
|
||||
name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }}
|
||||
runs-on: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
|
||||
name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }} x86_64
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
container:
|
||||
image: "almalinux:10"
|
||||
@@ -1086,9 +1052,9 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- architecture: "x86_64"
|
||||
image: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
|
||||
image: ubuntu-24.04
|
||||
- architecture: "arm64"
|
||||
image: runs-on=${{ github.run_id }}/runner=16cpu-linux-arm64/image=ubuntu24-full-arm64
|
||||
image: ubuntu-24.04-arm
|
||||
name: 🐧 Snap ${{ matrix.architecture }}
|
||||
runs-on: ${{ matrix.image }}
|
||||
|
||||
@@ -1117,12 +1083,18 @@ jobs:
|
||||
run: |
|
||||
export IMHEX_VERSION=$(cat VERSION)
|
||||
echo "IMHEX_VERSION=$IMHEX_VERSION" >> $GITHUB_ENV
|
||||
|
||||
if [[ "$IMHEX_VERSION" == *.WIP ]]; then
|
||||
echo "IMHEX_VERSION_STRING=$IMHEX_VERSION-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "IMHEX_VERSION_STRING=$IMHEX_VERSION" >> $GITHUB_ENV
|
||||
fi
|
||||
echo "CCACHE=ccache" >> $GITHUB_ENV
|
||||
|
||||
- name: 📜 Move snap directory to root
|
||||
run: |
|
||||
mkdir -p ./snap
|
||||
envsubst '${IMHEX_VERSION},${CCACHE}' < ./dist/snap/snapcraft.yaml > ./snap/snapcraft.yaml
|
||||
envsubst '${IMHEX_VERSION_STRING},${CCACHE}' < ./dist/snap/snapcraft.yaml > ./snap/snapcraft.yaml
|
||||
|
||||
- name: 📜 Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
@@ -1135,6 +1107,10 @@ jobs:
|
||||
run: |
|
||||
sudo snapcraft --destructive-mode
|
||||
|
||||
- name: 🟩 Rename Snap
|
||||
run: |
|
||||
mv *.snap imhex-${{ env.IMHEX_VERSION }}-${{ matrix.architecture }}.snap
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: ${{ github.event.repository.fork == false && github.event_name != 'pull_request' }}
|
||||
@@ -1157,10 +1133,10 @@ jobs:
|
||||
include:
|
||||
- architecture: "x86_64"
|
||||
flatpak_arch: "x86_64"
|
||||
image: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
|
||||
image: ubuntu-24.04
|
||||
- architecture: "arm64"
|
||||
flatpak_arch: "aarch64"
|
||||
image: runs-on=${{ github.run_id }}/runner=16cpu-linux-arm64/image=ubuntu24-full-arm64
|
||||
image: ubuntu-24.04-arm
|
||||
name: 🐧 Flatpak ${{ matrix.architecture }}
|
||||
runs-on: ${{ matrix.image }}
|
||||
|
||||
@@ -1211,12 +1187,8 @@ jobs:
|
||||
imhex-${{ env.IMHEX_VERSION }}-${{ matrix.architecture }}.flatpak
|
||||
|
||||
webassembly-build:
|
||||
runs-on: runs-on=${{ github.run_id }}/runner=16cpu-linux-x64/image=ubuntu24-full-x64
|
||||
runs-on: ubuntu-24.04
|
||||
name: 🌍 Web
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
actions: write
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -1236,17 +1208,20 @@ jobs:
|
||||
cache-source: cache
|
||||
cache-target: /cache
|
||||
|
||||
- name: 🛠️ Build using docker
|
||||
- name: 🔨 Copy necessary files
|
||||
run: |
|
||||
mkdir -p out/nightly
|
||||
cp dist/web/serve.py out/nightly/start_imhex_web.py
|
||||
|
||||
- name: 🛠️ Build using docker
|
||||
run: |
|
||||
docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out/nightly --target raw
|
||||
|
||||
- name: ⬇️ Download Release
|
||||
- name: ⬇️ Download Release artifact
|
||||
if: ${{ github.event.repository.fork == false }}
|
||||
uses: robinraju/release-downloader@v1
|
||||
with:
|
||||
latest: true
|
||||
fileName: 'imhex-*-Web.zip'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: gh --repo $GITHUB_REPOSITORY release download --pattern "imhex-*-Web.zip"
|
||||
|
||||
- name: 🔨 Fix permissions
|
||||
if: ${{ github.event.repository.fork == false }}
|
||||
@@ -1259,10 +1234,6 @@ jobs:
|
||||
with:
|
||||
path: out/
|
||||
|
||||
- name: 🔨 Copy necessary files
|
||||
run: |
|
||||
cp dist/web/serve.py out/nightly/start_imhex_web.py
|
||||
|
||||
- name: ⬆️ Upload package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -1281,7 +1252,7 @@ jobs:
|
||||
|
||||
webassembly-deploy:
|
||||
environment:
|
||||
name: github-pages
|
||||
name: ImHex Web
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
permissions:
|
||||
pages: write
|
||||
@@ -1294,11 +1265,64 @@ jobs:
|
||||
needs: webassembly-build
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: 🌍 Deploy WebAssembly Build to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
|
||||
- name: 🗑️ Delete artifact
|
||||
uses: geekyeggo/delete-artifact@v5
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
.github/scripts/delete-artifact.sh "github-pages"
|
||||
|
||||
webassembly-docker-image-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/master'
|
||||
needs: webassembly-build
|
||||
name: 🐋 Deploy to ghcr.io
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: ⬇️ Download artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: github-pages
|
||||
name: ImHex Web
|
||||
path: out
|
||||
|
||||
- name: 📜 Login to ghcr.io
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: ⛓️ Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ghcr.io/${{ github.repository }}/imhex-web
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=sha
|
||||
|
||||
- name: 🔨 Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
env:
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
with:
|
||||
context: .
|
||||
file: dist/web/Host.Dockerfile
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
47
.github/workflows/dl-cache.yml
vendored
Normal file
47
.github/workflows/dl-cache.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
# https://gist.github.com/iTrooz/d5bacca32c0974edc6c1ac3ad3ee82f3
|
||||
# See https://github.com/cli/cli/issues/9125
|
||||
# Extract archive with `tar -xf cache.tzst --transform 's@\.\./@#@g' -P` to avoid ../ errors
|
||||
name: Download cache key
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
cache_key:
|
||||
description: 'Cache key'
|
||||
required: true
|
||||
type: string
|
||||
jobs:
|
||||
cache-download:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Query cache version
|
||||
id: version
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
VERSION=$(gh api repos/$GITHUB_REPOSITORY/actions/caches \
|
||||
--jq "
|
||||
.actions_caches[]
|
||||
| select(.ref == \"refs/heads/$GITHUB_REF_NAME\")
|
||||
| select(.key == \"${{ github.event.inputs.cache_key }}\")
|
||||
| .version
|
||||
")
|
||||
echo "version=$VERSION" | tee $GITHUB_OUTPUT
|
||||
|
||||
- name: Restore cache
|
||||
uses: iTrooz/cache/restore@restore_with_version
|
||||
with:
|
||||
# Path won't be actually used, we will match by 'version'.
|
||||
path: .
|
||||
key: ${{ github.event.inputs.cache_key }}
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
|
||||
- name: Upload cached folder as artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cache-artifact
|
||||
path: |
|
||||
/home/runner/work/**/*.tzst
|
||||
47
.github/workflows/nightly_release.yml
vendored
47
.github/workflows/nightly_release.yml
vendored
@@ -11,8 +11,7 @@ on:
|
||||
jobs:
|
||||
nightly-release:
|
||||
runs-on: ubuntu-24.04
|
||||
name: Update Nightly Release
|
||||
|
||||
name: 🌃 Update Nightly Release
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -22,27 +21,35 @@ jobs:
|
||||
fetch-tags: true
|
||||
|
||||
- name: 🌃 Check for new commits
|
||||
id: check_commits
|
||||
run: |
|
||||
cd ImHex
|
||||
git config --global --add safe.directory $(pwd)
|
||||
if [ -z "$(git log nightly..HEAD --oneline)" ]; then
|
||||
echo "No new commits since last nightly. Exiting."
|
||||
exit 0
|
||||
echo "::set-output name=should_run::false"
|
||||
else
|
||||
echo "::set-output name=should_run::true"
|
||||
fi
|
||||
|
||||
- name: 📜 Set version variable
|
||||
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
|
||||
run: |
|
||||
project_version=`cat ImHex/VERSION`
|
||||
echo "IMHEX_VERSION=$project_version" >> $GITHUB_ENV
|
||||
|
||||
|
||||
# TODO: Replace by Github CLI when github.com/cli/cli/pull/12435 is closed
|
||||
- name: ⬇️ Download artifacts from latest workflow
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
workflow: build.yml
|
||||
branch: ${{ github.event.release.target_commitish }}
|
||||
branch: master
|
||||
workflow_conclusion: success
|
||||
skip_unpack: true
|
||||
|
||||
- name: 🗜️ Unzip files when needed
|
||||
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
|
||||
run: |
|
||||
set -x
|
||||
for zipfile in ./*.zip
|
||||
@@ -58,32 +65,33 @@ jobs:
|
||||
done
|
||||
|
||||
- name: 🟩 Rename artifacts when needed
|
||||
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
|
||||
run: |
|
||||
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip
|
||||
mv "Windows Portable arm64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-arm64.zip
|
||||
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip
|
||||
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-Web.zip
|
||||
mv ./*_amd64.snap $(echo ./*_amd64.snap | sed 's/_amd64\.snap$/-x86_64.snap/' | sed 's/_/-/1')
|
||||
mv ./*_arm64.snap $(echo ./*_arm64.snap | sed 's/_arm64\.snap$/-arm64.snap/' | sed 's/_/-/1')
|
||||
rm artifact.tar || true
|
||||
|
||||
- name: 📖 Generate Release Notes
|
||||
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
|
||||
id: release_notes
|
||||
continue-on-error: true
|
||||
run: |
|
||||
cd ImHex
|
||||
echo "## Nightly ${GITHUB_SHA::7} Changelog" > changelog.md
|
||||
git fetch --tags --recurse-submodules=no
|
||||
git log nightly..HEAD --oneline --no-merges --pretty=format:'* %s' >> changelog.md
|
||||
git log nightly..origin/master --oneline --no-merges --pretty=format:'* %s' >> changelog.md
|
||||
|
||||
- name: 📦 Update Pre-Release
|
||||
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
|
||||
run: |
|
||||
set -e
|
||||
|
||||
cd ImHex
|
||||
|
||||
# Move nightly tag to latest commit
|
||||
git tag -f nightly HEAD
|
||||
git tag -f nightly origin/master
|
||||
git push origin nightly --force
|
||||
|
||||
# Auth for GitHub CLI
|
||||
@@ -101,6 +109,8 @@ jobs:
|
||||
gh release upload nightly ../*.* --clobber
|
||||
|
||||
- name: ⬆️ Publish x86_64 Snap package
|
||||
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
|
||||
continue-on-error: true
|
||||
uses: snapcore/action-publish@v1
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
||||
@@ -109,9 +119,26 @@ jobs:
|
||||
release: edge
|
||||
|
||||
- name: ⬆️ Publish arm64 Snap package
|
||||
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
|
||||
continue-on-error: true
|
||||
uses: snapcore/action-publish@v1
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
||||
with:
|
||||
snap: imhex-${{ env.IMHEX_VERSION }}-arm64.snap
|
||||
release: edge
|
||||
release: edge
|
||||
|
||||
website_update:
|
||||
name: 🌍 Update ImHex Landing Website
|
||||
needs: nightly-release
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
WEBSITE_DISPATCH_TOKEN: ${{ secrets.WEBSITE_DISPATCH_TOKEN }}
|
||||
steps:
|
||||
- name: ✉️ Dispatch Landing page update
|
||||
if: ${{ env.WEBSITE_DISPATCH_TOKEN != '' }}
|
||||
uses: peter-evans/repository-dispatch@v4
|
||||
with:
|
||||
token: ${{ secrets.WEBSITE_DISPATCH_TOKEN }}
|
||||
repository: WerWolv/ImHexWebsite
|
||||
event-type: update_page
|
||||
108
.github/workflows/release.yml
vendored
108
.github/workflows/release.yml
vendored
@@ -7,6 +7,12 @@ on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
commit_hash:
|
||||
type: string
|
||||
description: 'The commit hash to build (defaults to the latest commit on the default branch)'
|
||||
required: false
|
||||
default: ''
|
||||
|
||||
jobs:
|
||||
release-update-repos:
|
||||
@@ -25,7 +31,7 @@ jobs:
|
||||
project_version=`cat ImHex/VERSION`
|
||||
tag_version="${{github.event.release.tag_name}}"
|
||||
tag_version="${tag_version:1}"
|
||||
if [ "$project_version" != "$tag_version" ]; then
|
||||
if [ "$project_version" != "$tag_version" ] && [ ! -z "$tag_version" ]; then
|
||||
echo "::warning::$project_version and $tag_version are not the same ! Refusing to populate release"
|
||||
exit 1
|
||||
fi
|
||||
@@ -41,6 +47,7 @@ jobs:
|
||||
tag: ImHex-v${{ env.IMHEX_VERSION }}
|
||||
repo: PatternLanguage
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
skipIfReleaseExists: true
|
||||
|
||||
- name: 🎫 Create ImHex-Patterns release
|
||||
uses: ncipollo/release-action@v1
|
||||
@@ -51,6 +58,7 @@ jobs:
|
||||
tag: ImHex-v${{ env.IMHEX_VERSION }}
|
||||
repo: ImHex-Patterns
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
skipIfReleaseExists: true
|
||||
|
||||
- name: 🎫 Create imhex-download-sdk release
|
||||
uses: ncipollo/release-action@v1
|
||||
@@ -61,11 +69,13 @@ jobs:
|
||||
tag: v${{ env.IMHEX_VERSION }}
|
||||
repo: imhex-download-sdk
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
skipIfReleaseExists: true
|
||||
|
||||
release-upload-artifacts:
|
||||
runs-on: ubuntu-24.04
|
||||
name: Release Upload Artifacts
|
||||
|
||||
outputs:
|
||||
IMHEX_VERSION: ${{ steps.verify_version.outputs.IMHEX_VERSION }}
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -74,17 +84,19 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: 📜 Verify version and set version variable
|
||||
id: verify_version
|
||||
run: |
|
||||
set -x
|
||||
project_version=`cat ImHex/VERSION`
|
||||
tag_version="${{github.event.release.tag_name}}"
|
||||
tag_version="${tag_version:1}"
|
||||
if [ "$project_version" != "$tag_version" ]; then
|
||||
if [ "$project_version" != "$tag_version" ] && [ ! -z "$tag_version" ]; then
|
||||
echo "::warning::$project_version and $tag_version are not the same ! Refusing to populate release"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "IMHEX_VERSION=$project_version" >> $GITHUB_ENV
|
||||
echo "IMHEX_VERSION=$project_version" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: 🗜️ Create tarball from sources with dependencies
|
||||
run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex
|
||||
@@ -97,6 +109,7 @@ jobs:
|
||||
branch: ${{ github.event.release.target_commitish }}
|
||||
workflow_conclusion: success
|
||||
skip_unpack: true
|
||||
commit: ${{ github.event.inputs.commit_hash }}
|
||||
|
||||
- name: 🗜️ Unzip files when needed
|
||||
run: |
|
||||
@@ -115,27 +128,87 @@ jobs:
|
||||
|
||||
- name: 🟩 Rename artifacts when needed
|
||||
run: |
|
||||
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip
|
||||
mv "Windows Portable arm64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-arm64.zip
|
||||
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip
|
||||
mv ./*_amd64.snap $(echo ./*_amd64.snap | sed 's/_amd64\.snap$/-x86_64.snap/' | sed 's/_/-/1')
|
||||
mv ./*_arm64.snap $(echo ./*_arm64.snap | sed 's/_arm64\.snap$/-arm64.snap/' | sed 's/_/-/1')
|
||||
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-Web.zip
|
||||
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip || true
|
||||
mv "Windows Portable arm64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-arm64.zip || true
|
||||
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip || true
|
||||
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-Web.zip || true
|
||||
rm artifact.tar || true
|
||||
|
||||
- name: ⬆️ Upload Unsigned x86_64 Windows Installer
|
||||
uses: actions/upload-artifact@v4
|
||||
id: upload-installer-x86_64
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: Windows Installer x86_64
|
||||
path: |
|
||||
imhex-*-x86_64.msi
|
||||
|
||||
- name: ⬆️ Upload Unsigned ARM64 Windows Installer
|
||||
if: false
|
||||
uses: actions/upload-artifact@v4
|
||||
id: upload-installer-arm64
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: Windows Installer ARM64
|
||||
path: |
|
||||
imhex-*-arm64.msi
|
||||
|
||||
- name: 🗑️ Delete unsigned installers
|
||||
run: |
|
||||
rm imhex-*-x86_64.msi
|
||||
|
||||
- name: 🗝️ Sign x86_64 Installer
|
||||
uses: signpath/github-action-submit-signing-request@v1
|
||||
with:
|
||||
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
|
||||
organization-id: 'f605a0e8-86cd-411c-bb6f-e05025afcc33'
|
||||
project-slug: 'ImHex'
|
||||
signing-policy-slug: 'release-signing'
|
||||
github-artifact-id: '${{ steps.upload-installer-x86_64.outputs.artifact-id }}'
|
||||
wait-for-completion: true
|
||||
output-artifact-directory: '.'
|
||||
|
||||
- name: 🗝️ Sign ARM64 Installer
|
||||
if: false
|
||||
uses: signpath/github-action-submit-signing-request@v1
|
||||
with:
|
||||
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
|
||||
organization-id: 'f605a0e8-86cd-411c-bb6f-e05025afcc33'
|
||||
project-slug: 'ImHex'
|
||||
signing-policy-slug: 'release-signing'
|
||||
github-artifact-id: '${{ steps.upload-installer-arm64.outputs.artifact-id }}'
|
||||
wait-for-completion: true
|
||||
output-artifact-directory: '.'
|
||||
|
||||
- name: ⬆️ Upload everything to release
|
||||
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
|
||||
with:
|
||||
files: '*'
|
||||
|
||||
release-update-aur:
|
||||
name: Release update AUR package
|
||||
needs: release-upload-artifacts
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: ImHex
|
||||
|
||||
- name: ⬇️ Download artifacts
|
||||
run: |
|
||||
tagname=${GITHUB_REF#refs/tags/}
|
||||
version=${tagname#v}
|
||||
wget https://github.com/WerWolv/ImHex/releases/download/${tagname}/imhex-${version}-ArchLinux-x86_64.pkg.tar.zst
|
||||
|
||||
- name: ✒️ Prepare PKGBUILD
|
||||
run: |
|
||||
set -x
|
||||
cp ImHex/dist/Arch/PKGBUILD .
|
||||
|
||||
hash=`md5sum imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst | cut -d ' ' -f 1`
|
||||
hash=`md5sum imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst | cut -d ' ' -f 1`
|
||||
|
||||
sed -i 's/%version%/${{ env.IMHEX_VERSION }}/g' PKGBUILD
|
||||
sed -i 's/%version%/${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}/g' PKGBUILD
|
||||
sed -i "s/(SKIP)/($hash)/g" PKGBUILD
|
||||
|
||||
- name: ⬆️ Publish AUR package
|
||||
@@ -149,9 +222,9 @@ jobs:
|
||||
pkgname: imhex-bin
|
||||
pkgbuild: ./PKGBUILD
|
||||
commit_username: iTrooz
|
||||
commit_email: itrooz@protonmail.com
|
||||
commit_email: hey@itrooz.fr
|
||||
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
||||
commit_message: Bump to version ${{ env.IMHEX_VERSION }}
|
||||
commit_message: Bump to version ${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}
|
||||
ssh_keyscan_types: rsa,ecdsa,ed25519
|
||||
|
||||
release-update-winget:
|
||||
@@ -163,6 +236,7 @@ jobs:
|
||||
shell: pwsh
|
||||
run: |
|
||||
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
|
||||
|
||||
- name: ⬆️ Update winget manifest
|
||||
shell: pwsh
|
||||
env:
|
||||
@@ -180,7 +254,7 @@ jobs:
|
||||
release-update-snapstore:
|
||||
name: Release update snapstore package
|
||||
needs: release-upload-artifacts
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: ⬇️ Download artifacts
|
||||
run: |
|
||||
@@ -190,17 +264,19 @@ jobs:
|
||||
wget https://github.com/WerWolv/ImHex/releases/download/${tagname}/imhex-${version}-arm64.snap
|
||||
|
||||
- name: ⬆️ Publish x86_64 Snap package
|
||||
continue-on-error: true
|
||||
uses: snapcore/action-publish@v1
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
||||
with:
|
||||
snap: imhex-${{ env.IMHEX_VERSION }}-x86_64.snap
|
||||
snap: imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-x86_64.snap
|
||||
release: stable
|
||||
|
||||
- name: ⬆️ Publish arm64 Snap package
|
||||
continue-on-error: true
|
||||
uses: snapcore/action-publish@v1
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
||||
with:
|
||||
snap: imhex-${{ env.IMHEX_VERSION }}-arm64.snap
|
||||
snap: imhex-${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}-arm64.snap
|
||||
release: stable
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -12,6 +12,8 @@
|
||||
/install/
|
||||
/out/
|
||||
|
||||
/dist/ImHex.run.xml
|
||||
|
||||
*.mgc
|
||||
*.kdev4
|
||||
imgui.ini
|
||||
|
||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -18,10 +18,6 @@
|
||||
path = lib/third_party/capstone
|
||||
url = https://github.com/capstone-engine/capstone
|
||||
ignore = dirty
|
||||
[submodule "lib/third_party/jthread/jthread"]
|
||||
path = lib/third_party/jthread/jthread
|
||||
url = https://github.com/josuttis/jthread
|
||||
ignore = dirty
|
||||
[submodule "lib/third_party/edlib"]
|
||||
path = lib/third_party/edlib
|
||||
url = https://github.com/Martinsos/edlib
|
||||
@@ -49,4 +45,4 @@
|
||||
url = https://github.com/WerWolv/Disassembler
|
||||
[submodule "lib/third_party/md4c"]
|
||||
path = lib/third_party/md4c
|
||||
url = https://github.com/mity/md4c
|
||||
url = https://github.com/mity/md4c
|
||||
@@ -1,33 +1,39 @@
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
|
||||
# Options
|
||||
option(IMHEX_PLUGINS_IN_SHARE "Put the plugins in share/imhex/plugins instead of lib[..]/imhex/plugins (Linux only)" OFF)
|
||||
## General
|
||||
option(IMHEX_STRIP_RELEASE "Strip the release builds" ON )
|
||||
option(IMHEX_OFFLINE_BUILD "Enable offline build" OFF)
|
||||
option(IMHEX_IGNORE_BAD_CLONE "Disable the bad clone prevention checks" OFF)
|
||||
option(IMHEX_PATTERNS_PULL_MASTER "Download latest files from master branch of the ImHex-Patterns repo" OFF)
|
||||
option(IMHEX_IGNORE_BAD_COMPILER "Allow compiling with an unsupported compiler" OFF)
|
||||
option(IMHEX_USE_GTK_FILE_PICKER "Use GTK file picker instead of xdg-desktop-portals (Linux only)" OFF)
|
||||
option(IMHEX_DISABLE_STACKTRACE "Disables support for printing stack traces" OFF)
|
||||
option(IMHEX_BUNDLE_DOTNET "Bundle .NET runtime" ON )
|
||||
option(IMHEX_ENABLE_LTO "Enables Link Time Optimizations if possible" OFF)
|
||||
option(IMHEX_USE_DEFAULT_BUILD_SETTINGS "Use default build settings" OFF)
|
||||
option(IMHEX_STRICT_WARNINGS "Enable most available warnings and treat them as errors" ON )
|
||||
option(IMHEX_BUILD_HARDENING "Enable hardening flags for build" ON )
|
||||
option(IMHEX_STATIC_LINK_PLUGINS "Statically link all plugins into the main executable" OFF)
|
||||
option(IMHEX_GENERATE_PACKAGE "Specify if a native package should be built. (Windows and MacOS only)" OFF)
|
||||
option(IMHEX_GENERATE_PACKAGE "Specify if a cpack package should be built. (Windows only)" OFF)
|
||||
option(IMHEX_MACOS_CREATE_BUNDLE "Creates a macOS .app bundle when building (macOS only)" ON )
|
||||
option(IMHEX_ENABLE_UNITY_BUILD "Enables building ImHex as a unity build." OFF)
|
||||
option(IMHEX_GENERATE_PDBS "Enable generating PDB files in non-debug builds (Windows only)" OFF)
|
||||
option(IMHEX_REPLACE_DWARF_WITH_PDB "Remove DWARF information from binaries when generating PDBS (Windows only)" OFF)
|
||||
option(IMHEX_ENABLE_STD_ASSERTS "Enable debug asserts in the C++ std library. (Breaks Plugin ABI!)" OFF)
|
||||
option(IMHEX_ENABLE_UNIT_TESTS "Enable building unit tests" ON )
|
||||
option(IMHEX_ENABLE_PLUGIN_TESTS "Enable building plugin tests" ON )
|
||||
option(IMHEX_ENABLE_IMGUI_TEST_ENGINE "Enable the ImGui Test Engine" OFF)
|
||||
option(IMHEX_ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF)
|
||||
option(IMHEX_COMPRESS_DEBUG_INFO "Compress debug information" ON )
|
||||
option(IMHEX_ENABLE_CXX_MODULES "Enable C++20 Module compilation. Testing only!" OFF)
|
||||
option(IMHEX_ENABLE_CPPCHECK "Enable cppcheck static analysis" OFF)
|
||||
option(IMHEX_BUNDLE_PLUGIN_SDK "Enable bundling of Plugin SDK into install package" ON )
|
||||
## Testing
|
||||
option(IMHEX_ENABLE_UNIT_TESTS "Enable building unit tests" ON )
|
||||
option(IMHEX_ENABLE_IMGUI_TEST_ENGINE "Enable the ImGui Test Engine" OFF)
|
||||
option(IMHEX_ENABLE_STD_ASSERTS "Enable debug asserts in the C++ std library. (Breaks Plugin ABI!)" OFF)
|
||||
## Debug info
|
||||
option(IMHEX_COMPRESS_DEBUG_INFO "Compress debug information" ON )
|
||||
option(IMHEX_GENERATE_PDBS "Enable generating PDB files in non-debug builds (Windows only)" OFF)
|
||||
option(IMHEX_REPLACE_DWARF_WITH_PDB "Remove DWARF information from binaries when generating PDBS (Windows only)" OFF)
|
||||
option(IMHEX_STRICT_WARNINGS "Enable most available warnings and treat them as errors" ON )
|
||||
option(IMHEX_DISABLE_STACKTRACE "Disables support for printing stack traces" OFF)
|
||||
## Plugins
|
||||
option(IMHEX_STATIC_LINK_PLUGINS "Statically link all plugins into the main executable" OFF)
|
||||
option(IMHEX_ENABLE_PLUGIN_TESTS "Enable building plugin tests" ON )
|
||||
option(IMHEX_INCLUDE_PLUGINS "Semicolon-separated list of plugins to include in the build (empty = build all)" "" )
|
||||
option(IMHEX_EXCLUDE_PLUGINS "Semicolon-separated list of plugins to exclude from the build" "" )
|
||||
|
||||
set(IMHEX_BASE_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules")
|
||||
@@ -47,7 +53,7 @@ loadVersion(IMHEX_VERSION IMHEX_VERSION_PLAIN)
|
||||
setVariableInParent(IMHEX_VERSION ${IMHEX_VERSION})
|
||||
|
||||
configureCMake()
|
||||
project(imhex
|
||||
project(ImHex
|
||||
LANGUAGES C CXX
|
||||
VERSION ${IMHEX_VERSION_PLAIN}
|
||||
DESCRIPTION "The ImHex Hex Editor"
|
||||
|
||||
@@ -59,13 +59,14 @@
|
||||
{
|
||||
"name": "vs2022-x86",
|
||||
"displayName": "Visual Studio 2022 x86",
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build/${presetName}",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_GENERATOR_PLATFORM": "Win32",
|
||||
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
|
||||
"VCPKG_MANIFEST_DIR": "${sourceDir}/dist"
|
||||
},
|
||||
"environment": {
|
||||
"VSCMD_ARG_TGT_ARCH": "x86"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
45
README.md
45
README.md
@@ -29,14 +29,23 @@
|
||||
|
||||
## Supporting
|
||||
|
||||
If you like my work, please consider supporting me on GitHub Sponsors, Patreon or PayPal. Thanks a lot!
|
||||
If you like my work, please consider supporting me on GitHub Sponsors, Ko-Fi or PayPal. Thanks a lot!
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/sponsors/WerWolv"><img src="https://werwolv.net/assets/github_banner.png" alt="GitHub donate button" /></a>
|
||||
<a href="https://www.patreon.com/werwolv"><img src="https://c5.patreon.com/external/logo/become_a_patron_button.png" alt="Patreon donate button" /></a>
|
||||
<a href="https://ko-fi.com/WerWolv"><img src="https://werwolv.net/assets/kofi_banner.png" alt="Ko-Fi donate button" /></a>
|
||||
<a href="https://werwolv.net/donate"><img src="https://werwolv.net/assets/paypal_banner.png" alt="PayPal donate button" /></a>
|
||||
</p>
|
||||
|
||||
### Notable Sponsors
|
||||
| | |
|
||||
|:---------------------------------------------------------------------------------------------------:|-----------------------------------------------------------------------------------|
|
||||
| [](https://www.jetbrains.com) | JetBrains, providing us with free All Products Pack licenses for development |
|
||||
| [](https://signpath.io/) | SignPath, providing us with free Code Signing Certificates for our Windows builds |
|
||||
| [](https://aws.amazon.com) | Amazon, providing us with free AWS Cloud Credits for our CI |
|
||||
|
||||
Would you like to appear here as well? Contact us at [imhex@werwolv.net](mailto:imhex@werwolv.net)!
|
||||
|
||||
## Screenshots
|
||||

|
||||

|
||||
@@ -327,8 +336,8 @@ To use ImHex, the following minimal system requirements need to be met.
|
||||
|
||||
- **OS**:
|
||||
- **Windows**: Windows 7 or higher (Windows 10/11 recommended)
|
||||
- **macOS**: macOS 13 (Ventura) or higher,
|
||||
- Lower versions should still work too, but you'll need to compile ImHex yourself. The release binaries will NOT work due to GitHub not having any macOS 12 or lower CI runners available.
|
||||
- **macOS**: macOS 15 (Sequoia) or higher,
|
||||
- Lower versions should still work too, but you'll need to compile ImHex yourself. The release binaries will NOT work due to GitHub not having any macOS 15 or lower CI runners available.
|
||||
- The macOS build is not signed and will require you to manually allow them in the Security & Privacy settings.
|
||||
- **Linux**: "Modern" Linux. The following distributions have official releases available. Other distros are supported through the AppImage, Flatpak and Snap releases.
|
||||
- Ubuntu and Debian
|
||||
@@ -366,9 +375,20 @@ For more information, check out the [Compiling](/dist/compiling) guide.
|
||||
## Contributing
|
||||
See [Contributing](/CONTRIBUTING.md)
|
||||
|
||||
## Plugin development
|
||||
|
||||
## Plugin development
|
||||
To develop plugins for ImHex, use the following template project to get started. You then have access to the entirety of libimhex as well as the ImHex API and the Content Registry to interact with ImHex or to add new content.
|
||||
To build a plugin, you will need to use our SDK
|
||||
|
||||
### Getting the SDK locally
|
||||
You can build the SDK by compiling ImHex like this:
|
||||
- `cmake -G Ninja -DIMHEX_BUNDLE_PLUGIN_SDK=ON -B build`
|
||||
- `cd build`
|
||||
- `DESTDIR=install ninja install`
|
||||
The SDK will then be available at `install/usr/local/share/imhex/sdk`. You will need to set the variable `IMHEX_SDK_PATH` to that (absolute) path.
|
||||
|
||||
### Getting the SDK in a Github Actions CI
|
||||
You can use [this action](https://github.com/WerWolv/imhex-download-sdk) to automatically download the SDK to your Github Runner
|
||||
- [ImHex Plugin Template](https://github.com/WerWolv/ImHex-Plugin-Template)
|
||||
|
||||
|
||||
@@ -410,3 +430,18 @@ Notable exceptions to this are the following parts which are under the LGPLv2.1
|
||||
- **/plugins/ui**: The UI plugin library that contains some common UI elements that can be used by other plugins
|
||||
|
||||
The reason for this is to allow for proprietary plugins to be developed for ImHex.
|
||||
|
||||
### Code Signing Policy
|
||||
|
||||
Free code signing provided by [SignPath.io](https://about.signpath.io/),
|
||||
certificate by [SignPath Foundation](https://signpath.org/).
|
||||
|
||||
This program will not transfer any information to other networked systems
|
||||
unless specifically requested by the user or the person installing or
|
||||
operating it.
|
||||
|
||||
#### People with direct push access
|
||||
- [WerWolv](https://github.com/WerWolv)
|
||||
- [iTrooz](https://github.com/iTrooz)
|
||||
- [jumanji144](https://github.com/jumanji144)
|
||||
- [AxCut](https://github.com/paxcut)
|
||||
|
||||
0
changelog.md
Normal file
0
changelog.md
Normal file
@@ -175,15 +175,11 @@ macro(detectOS)
|
||||
endif()
|
||||
include(GNUInstallDirs)
|
||||
|
||||
if(IMHEX_PLUGINS_IN_SHARE)
|
||||
set(PLUGINS_INSTALL_LOCATION "share/imhex/plugins")
|
||||
else()
|
||||
set(PLUGINS_INSTALL_LOCATION "${CMAKE_INSTALL_LIBDIR}/imhex/plugins")
|
||||
set(PLUGINS_INSTALL_LOCATION "${CMAKE_INSTALL_LIBDIR}/imhex/plugins")
|
||||
|
||||
# Add System plugin location for plugins to be loaded from
|
||||
# IMPORTANT: This does not work for Sandboxed or portable builds such as the Flatpak or AppImage release
|
||||
add_compile_definitions(SYSTEM_PLUGINS_LOCATION="${CMAKE_INSTALL_FULL_LIBDIR}/imhex")
|
||||
endif()
|
||||
# Add System plugin location for plugins to be loaded from
|
||||
# IMPORTANT: This does not work for Sandboxed or portable builds such as the Flatpak or AppImage release
|
||||
add_compile_definitions(SYSTEM_PLUGINS_LOCATION="${CMAKE_INSTALL_FULL_LIBDIR}/imhex")
|
||||
|
||||
else ()
|
||||
message(FATAL_ERROR "Unknown / unsupported system!")
|
||||
@@ -205,11 +201,18 @@ macro(configurePackingResources)
|
||||
set(CPACK_GENERATOR "WIX")
|
||||
set(CPACK_PACKAGE_NAME "ImHex")
|
||||
set(CPACK_PACKAGE_VENDOR "WerWolv")
|
||||
set(CPACK_WIX_VERSION 4)
|
||||
set(CPACK_WIX_PRODUCT_GUID "*")
|
||||
set(CPACK_WIX_UPGRADE_GUID "05000E99-9659-42FD-A1CF-05C554B39285")
|
||||
set(CPACK_WIX_PRODUCT_ICON "${PROJECT_SOURCE_DIR}/resources/dist/windows/icon.ico")
|
||||
set(CPACK_WIX_UI_BANNER "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_banner.png")
|
||||
set(CPACK_WIX_UI_DIALOG "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_dialog.png")
|
||||
set(CPACK_WIX_CULTURES "en-US;de-DE;ja-JP;it-IT;pt-BR;zh-CN;zh-TW;ru-RU")
|
||||
set(CPACK_WIX_TEMPLATE "${PROJECT_SOURCE_DIR}/resources/dist/windows/WIX.template.in")
|
||||
set(CPACK_WIX_EXTENSIONS "WixToolset.UI.wixext")
|
||||
|
||||
file(GLOB_RECURSE CPACK_WIX_EXTRA_SOURCES "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix/*.wxs")
|
||||
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "ImHex")
|
||||
set_property(INSTALL "$<TARGET_FILE_NAME:main>"
|
||||
PROPERTY CPACK_START_MENU_SHORTCUTS "ImHex"
|
||||
@@ -218,9 +221,9 @@ macro(configurePackingResources)
|
||||
endif()
|
||||
elseif (APPLE OR ${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set(IMHEX_ICON "${IMHEX_BASE_FOLDER}/resources/dist/macos/AppIcon.icns")
|
||||
set(BUNDLE_NAME "imhex.app")
|
||||
set(BUNDLE_NAME "ImHex.app")
|
||||
|
||||
if (IMHEX_GENERATE_PACKAGE)
|
||||
if (IMHEX_MACOS_CREATE_BUNDLE)
|
||||
set(APPLICATION_TYPE MACOSX_BUNDLE)
|
||||
set_source_files_properties(${IMHEX_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
|
||||
set(MACOSX_BUNDLE_ICON_FILE "AppIcon.icns")
|
||||
@@ -236,9 +239,9 @@ macro(configurePackingResources)
|
||||
string(TIMESTAMP CURR_YEAR "%Y")
|
||||
set(MACOSX_BUNDLE_COPYRIGHT "Copyright © 2020 - ${CURR_YEAR} WerWolv. All rights reserved." )
|
||||
if ("${CMAKE_GENERATOR}" STREQUAL "Xcode")
|
||||
set (IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${BUNDLE_NAME}")
|
||||
set(IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${BUNDLE_NAME}")
|
||||
else ()
|
||||
set (IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${BUNDLE_NAME}")
|
||||
set(IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${BUNDLE_NAME}")
|
||||
endif()
|
||||
|
||||
set(PLUGINS_INSTALL_LOCATION "${IMHEX_BUNDLE_PATH}/Contents/MacOS/plugins")
|
||||
@@ -256,7 +259,7 @@ macro(addPluginDirectories)
|
||||
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${IMHEX_MAIN_OUTPUT_DIRECTORY}/plugins")
|
||||
|
||||
if (APPLE)
|
||||
if (IMHEX_GENERATE_PACKAGE)
|
||||
if (IMHEX_MACOS_CREATE_BUNDLE)
|
||||
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGINS_INSTALL_LOCATION})
|
||||
endif ()
|
||||
else ()
|
||||
@@ -312,7 +315,7 @@ macro(createPackage)
|
||||
POST_EXCLUDE_REGEXES ".*system32/.*\\.dll"
|
||||
)
|
||||
|
||||
if(_c_deps_FILENAMES AND NOT _c_deps STREQUAL "")
|
||||
if(_c_deps_FILENAMES AND _c_deps AND NOT (_c_deps STREQUAL ""))
|
||||
message(WARNING "Conflicting dependencies for library: \"${_c_deps}\"!")
|
||||
endif()
|
||||
|
||||
@@ -333,41 +336,47 @@ macro(createPackage)
|
||||
|
||||
downloadImHexPatternsFiles(".")
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
|
||||
set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION})
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dist/DEBIAN/control.in ${CMAKE_BINARY_DIR}/DEBIAN/control)
|
||||
configure_file(${IMHEX_BASE_FOLDER}/dist/DEBIAN/control.in ${CMAKE_BINARY_DIR}/DEBIAN/control)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.mime.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages RENAME imhex.xml)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.svg DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.svg)
|
||||
install(FILES ${IMHEX_BASE_FOLDER}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex)
|
||||
install(FILES ${IMHEX_BASE_FOLDER}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
|
||||
install(FILES ${IMHEX_BASE_FOLDER}/dist/imhex.mime.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages RENAME imhex.xml)
|
||||
install(FILES ${IMHEX_BASE_FOLDER}/resources/icon.svg DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.svg)
|
||||
downloadImHexPatternsFiles("./share/imhex")
|
||||
|
||||
# install AppStream file
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/net.werwolv.ImHex.metainfo.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo)
|
||||
install(FILES ${IMHEX_BASE_FOLDER}/dist/net.werwolv.ImHex.metainfo.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
if (IMHEX_GENERATE_PACKAGE)
|
||||
if (IMHEX_MACOS_CREATE_BUNDLE)
|
||||
set(EXTRA_BUNDLE_LIBRARY_PATHS ${EXTRA_BUNDLE_LIBRARY_PATHS} "${IMHEX_SYSTEM_LIBRARY_PATH}")
|
||||
include(PostprocessBundle)
|
||||
|
||||
set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION})
|
||||
|
||||
set_property(TARGET main PROPERTY MACOSX_BUNDLE_INFO_PLIST ${MACOSX_BUNDLE_INFO_PLIST})
|
||||
set_property(TARGET main PROPERTY MACOSX_BUNDLE_BUNDLE_NAME "${MACOSX_BUNDLE_BUNDLE_NAME}")
|
||||
|
||||
# Fix rpath
|
||||
install(CODE "execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath \"@executable_path/../Frameworks/\" $<TARGET_FILE:main>)")
|
||||
|
||||
add_custom_target(build-time-make-plugins-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${IMHEX_BUNDLE_PATH}/Contents/MacOS/plugins")
|
||||
add_custom_target(build-time-make-resources-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${IMHEX_BUNDLE_PATH}/Contents/Resources")
|
||||
install(CODE "execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath \"@executable_path/../Frameworks/\" $<TARGET_FILE:updater>)")
|
||||
|
||||
downloadImHexPatternsFiles("${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/MacOS")
|
||||
|
||||
install(FILES ${IMHEX_ICON} DESTINATION "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Resources")
|
||||
install(TARGETS main BUNDLE DESTINATION ".")
|
||||
install(TARGETS updater BUNDLE DESTINATION ".")
|
||||
install(TARGETS updater DESTINATION "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/MacOS")
|
||||
install(
|
||||
FILES ${IMHEX_BASE_FOLDER}/dist/cli/imhex.sh
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/MacOS/cli"
|
||||
RENAME imhex
|
||||
PERMISSIONS
|
||||
OWNER_READ OWNER_WRITE OWNER_EXECUTE
|
||||
GROUP_READ GROUP_EXECUTE
|
||||
WORLD_READ WORLD_EXECUTE
|
||||
)
|
||||
|
||||
# Update library references to make the bundle portable
|
||||
postprocess_bundle(imhex_all main)
|
||||
@@ -398,9 +407,31 @@ macro(createPackage)
|
||||
if (TARGET main-forwarder)
|
||||
install(TARGETS main-forwarder BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
install(
|
||||
FILES ${IMHEX_BASE_FOLDER}/dist/cli/imhex.bat
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}/cli
|
||||
RENAME imhex.bat
|
||||
PERMISSIONS
|
||||
OWNER_READ OWNER_WRITE OWNER_EXECUTE
|
||||
GROUP_READ GROUP_EXECUTE
|
||||
WORLD_READ WORLD_EXECUTE
|
||||
)
|
||||
else()
|
||||
install(
|
||||
FILES ${IMHEX_BASE_FOLDER}/dist/cli/imhex.sh
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/imhex
|
||||
RENAME imhex
|
||||
PERMISSIONS
|
||||
OWNER_READ OWNER_WRITE OWNER_EXECUTE
|
||||
GROUP_READ GROUP_EXECUTE
|
||||
WORLD_READ WORLD_EXECUTE
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (IMHEX_GENERATE_PACKAGE)
|
||||
if (IMHEX_MACOS_CREATE_BUNDLE)
|
||||
set(CPACK_BUNDLE_NAME "ImHex")
|
||||
|
||||
include(CPack)
|
||||
@@ -529,6 +560,9 @@ function(detectBadClone)
|
||||
|
||||
file (GLOB EXTERNAL_DIRS "lib/external/*" "lib/third_party/*")
|
||||
foreach (EXTERNAL_DIR ${EXTERNAL_DIRS})
|
||||
if(NOT IS_DIRECTORY "${EXTERNAL_DIR}")
|
||||
continue()
|
||||
endif()
|
||||
file(GLOB_RECURSE RESULT "${EXTERNAL_DIR}/*")
|
||||
list(LENGTH RESULT ENTRY_COUNT)
|
||||
if(ENTRY_COUNT LESS_EQUAL 1)
|
||||
@@ -556,7 +590,9 @@ endfunction()
|
||||
macro(detectBundledPlugins)
|
||||
file(GLOB PLUGINS_DIRS "plugins/*")
|
||||
|
||||
if (NOT DEFINED IMHEX_INCLUDE_PLUGINS)
|
||||
if (IMHEX_INCLUDE_PLUGINS)
|
||||
set(PLUGINS ${IMHEX_INCLUDE_PLUGINS})
|
||||
else()
|
||||
foreach(PLUGIN_DIR ${PLUGINS_DIRS})
|
||||
if (EXISTS "${PLUGIN_DIR}/CMakeLists.txt")
|
||||
get_filename_component(PLUGIN_NAME ${PLUGIN_DIR} NAME)
|
||||
@@ -565,8 +601,6 @@ macro(detectBundledPlugins)
|
||||
endif ()
|
||||
endif()
|
||||
endforeach()
|
||||
else()
|
||||
set(PLUGINS ${IMHEX_INCLUDE_PLUGINS})
|
||||
endif()
|
||||
|
||||
foreach(PLUGIN_NAME ${PLUGINS})
|
||||
@@ -577,9 +611,13 @@ macro(detectBundledPlugins)
|
||||
message(FATAL_ERROR "No bundled plugins enabled")
|
||||
endif()
|
||||
|
||||
if (NOT ("builtin" IN_LIST PLUGINS))
|
||||
message(FATAL_ERROR "The 'builtin' plugin is required for ImHex to work!")
|
||||
endif ()
|
||||
set(REQUIRED_PLUGINS builtin fonts ui)
|
||||
foreach(PLUGIN ${REQUIRED_PLUGINS})
|
||||
list(FIND PLUGINS ${PLUGIN} PLUGIN_INDEX)
|
||||
if (PLUGIN_INDEX EQUAL -1)
|
||||
message(FATAL_ERROR "Required plugin '${PLUGIN}' is not enabled!")
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
macro(setVariableInParent variable value)
|
||||
@@ -605,17 +643,15 @@ function(downloadImHexPatternsFiles dest)
|
||||
install(CODE "set(imhex_patterns_SOURCE_DIR \"${imhex_patterns_SOURCE_DIR}\")")
|
||||
install(CODE [[
|
||||
message(STATUS "Downloading ImHex patterns from branch '${PATTERNS_BRANCH}'...")
|
||||
if (EXISTS "${imhex_patterns_SOURCE_DIR}")
|
||||
file(REMOVE_RECURSE "${imhex_patterns_SOURCE_DIR}")
|
||||
else ()
|
||||
if (NOT EXISTS "${imhex_patterns_SOURCE_DIR}")
|
||||
file(MAKE_DIRECTORY "${imhex_patterns_SOURCE_DIR}")
|
||||
|
||||
execute_process(
|
||||
COMMAND
|
||||
git clone --recurse-submodules --branch ${PATTERNS_BRANCH} https://github.com/WerWolv/ImHex-Patterns.git "${imhex_patterns_SOURCE_DIR}"
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
)
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND
|
||||
git clone --recurse-submodules --branch ${PATTERNS_BRANCH} https://github.com/WerWolv/ImHex-Patterns.git "${imhex_patterns_SOURCE_DIR}"
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
)
|
||||
]])
|
||||
else ()
|
||||
set(imhex_patterns_SOURCE_DIR "")
|
||||
@@ -745,15 +781,19 @@ macro(setupCompilerFlags target)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND APPLE)
|
||||
execute_process(COMMAND brew --prefix llvm OUTPUT_VARIABLE LLVM_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
|
||||
addCCXXFlag("-Wno-unknown-warning-option" ${target})
|
||||
|
||||
# On macOS, when using clang from Homebrew, properly setup the libc++ library path so
|
||||
# it's using the one from Homebrew instead of the system one.
|
||||
execute_process(COMMAND brew --prefix llvm OUTPUT_VARIABLE LLVM_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if (NOT LLVM_PREFIX STREQUAL "" AND ${CMAKE_CXX_COMPILER} STREQUAL "${LLVM_PREFIX}/bin/clang++")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
|
||||
endif()
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_compile_definitions(_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG)
|
||||
else()
|
||||
add_compile_definitions(_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -810,6 +850,13 @@ macro(setUninstallTarget)
|
||||
endmacro()
|
||||
|
||||
macro(addBundledLibraries)
|
||||
# Make sure the build is using vcpkg on Windows and Emscripten, otherwise none of these dependencies will be found
|
||||
if (MSVC OR EMSCRIPTEN)
|
||||
if (NOT (CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg"))
|
||||
message(AUTHOR_WARNING "Your current environment probably needs to be setup to use vcpkg, otherwise none of the dependencies will be found!")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(EXTERNAL_LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/lib/external")
|
||||
set(THIRD_PARTY_LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/lib/third_party")
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
@@ -883,18 +930,6 @@ macro(addBundledLibraries)
|
||||
find_package(LLVM REQUIRED Demangle)
|
||||
endif()
|
||||
|
||||
if (NOT USE_SYSTEM_JTHREAD)
|
||||
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/jthread EXCLUDE_FROM_ALL)
|
||||
set(JTHREAD_LIBRARIES jthread)
|
||||
else()
|
||||
find_path(JOSUTTIS_JTHREAD_INCLUDE_DIRS "condition_variable_any2.hpp")
|
||||
include_directories(${JOSUTTIS_JTHREAD_INCLUDE_DIRS})
|
||||
|
||||
add_library(jthread INTERFACE)
|
||||
target_include_directories(jthread INTERFACE ${JOSUTTIS_JTHREAD_INCLUDE_DIRS})
|
||||
set(JTHREAD_LIBRARIES jthread)
|
||||
endif()
|
||||
|
||||
if (USE_SYSTEM_BOOST)
|
||||
find_package(Boost REQUIRED CONFIG COMPONENTS regex)
|
||||
set(BOOST_LIBRARIES Boost::regex)
|
||||
|
||||
@@ -2,11 +2,7 @@ find_path(LIBMAGIC_INCLUDE_DIR magic.h)
|
||||
|
||||
find_library(LIBMAGIC_LIBRARY NAMES magic)
|
||||
|
||||
if (LIBMAGIC_INCLUDE_DIR AND LIBMAGIC_LIBRARY)
|
||||
set(LIBMAGIC_FOUND TRUE)
|
||||
endif (LIBMAGIC_INCLUDE_DIR AND LIBMAGIC_LIBRARY)
|
||||
|
||||
find_package_handle_standard_args("libmagic" DEFAULT_MSG
|
||||
find_package_handle_standard_args(Magic DEFAULT_MSG
|
||||
LIBMAGIC_LIBRARY
|
||||
LIBMAGIC_INCLUDE_DIR
|
||||
)
|
||||
@@ -14,5 +10,5 @@ find_package_handle_standard_args("libmagic" DEFAULT_MSG
|
||||
mark_as_advanced(
|
||||
LIBMAGIC_INCLUDE_DIR
|
||||
LIBMAGIC_LIBRARY
|
||||
LIBMAGIC_FOUND
|
||||
)
|
||||
Magic_FOUND
|
||||
)
|
||||
|
||||
@@ -26,8 +26,9 @@ SET(MBEDTLS_FIND_QUIETLY TRUE)
|
||||
FIND_LIBRARY(MBEDTLS_LIBRARY NAMES mbedtls libmbedtls libmbedx509)
|
||||
FIND_LIBRARY(MBEDX509_LIBRARY NAMES mbedx509 libmbedx509)
|
||||
FIND_LIBRARY(MBEDCRYPTO_LIBRARY NAMES mbedcrypto libmbedcrypto)
|
||||
FIND_LIBRARY(TFPSACRYPTO_LIBRARY NAMES libtfpsacrypto tfpsacrypto)
|
||||
|
||||
IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND MBEDCRYPTO_LIBRARY)
|
||||
IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND (MBEDCRYPTO_LIBRARY OR TFPSACRYPTO_LIBRARY))
|
||||
SET(MBEDTLS_FOUND TRUE)
|
||||
ENDIF()
|
||||
|
||||
@@ -37,14 +38,24 @@ IF(MBEDTLS_FOUND)
|
||||
GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY} NAME_WE)
|
||||
GET_FILENAME_COMPONENT(MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY} NAME_WE)
|
||||
GET_FILENAME_COMPONENT(MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY} NAME_WE)
|
||||
GET_FILENAME_COMPONENT(TFPSACRYPTO_LIBRARY_FILE ${TFPSACRYPTO_LIBRARY} NAME_WE)
|
||||
STRING(REGEX REPLACE "^lib" "" MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY_FILE})
|
||||
STRING(REGEX REPLACE "^lib" "" MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY_FILE})
|
||||
STRING(REGEX REPLACE "^lib" "" MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE})
|
||||
STRING(REGEX REPLACE "^lib" "" TFPSACRYPTO_LIBRARY_FILE ${TFPSACRYPTO_LIBRARY_FILE})
|
||||
|
||||
if (TFPSACRYPTO_LIBRARY)
|
||||
SET(MBEDTLS_CRYPTO_LIBRARY_FILE ${TFPSACRYPTO_LIBRARY_FILE})
|
||||
elseif (MBEDCRYPTO_LIBRARY)
|
||||
SET(MBEDTLS_CRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE})
|
||||
else ()
|
||||
MESSAGE(FATAL_ERROR "Could not find mbedTLS Crypto library")
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
SET(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY_FILE}.lib ${MBEDX509_LIBRARY_FILE}.lib ${MBEDCRYPTO_LIBRARY_FILE}.lib)
|
||||
SET(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY_FILE}.lib ${MBEDX509_LIBRARY_FILE}.lib ${MBEDTLS_CRYPTO_LIBRARY_FILE}.lib)
|
||||
else()
|
||||
SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}")
|
||||
SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDTLS_CRYPTO_LIBRARY_FILE}")
|
||||
endif()
|
||||
|
||||
IF(NOT MBEDTLS_FIND_QUIETLY)
|
||||
|
||||
@@ -65,9 +65,9 @@ elseif (APPLE)
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/trace/include")
|
||||
else()
|
||||
set_target_properties(libimhex PROPERTIES
|
||||
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../libimhex.so"
|
||||
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/libimhex.so"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex/include")
|
||||
set_target_properties(tracing PROPERTIES
|
||||
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../libtracing.a"
|
||||
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libtracing.a"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/trace/include")
|
||||
endif()
|
||||
|
||||
4
dist/AppImage/AppImageBuilder.yml
vendored
4
dist/AppImage/AppImageBuilder.yml
vendored
@@ -15,8 +15,8 @@ AppDir:
|
||||
- "{{ARCHITECTURE_PACKAGE}}"
|
||||
allow_unauthenticated: true
|
||||
sources:
|
||||
- sourceline: 'deb [arch=amd64] http://us.archive.ubuntu.com/ubuntu/ oracular main restricted universe multiverse'
|
||||
- sourceline: 'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ oracular main restricted universe multiverse'
|
||||
- sourceline: 'deb [arch=amd64] https://us.archive.ubuntu.com/ubuntu/ noble main restricted universe multiverse'
|
||||
- sourceline: 'deb [arch=arm64] https://ports.ubuntu.com/ubuntu-ports/ noble main restricted universe multiverse'
|
||||
include:
|
||||
- libgdk-pixbuf2.0-0
|
||||
- libgdk-pixbuf2.0-common
|
||||
|
||||
30
dist/AppImage/Dockerfile
vendored
30
dist/AppImage/Dockerfile
vendored
@@ -1,4 +1,4 @@
|
||||
FROM ubuntu:24.10 as build
|
||||
FROM ubuntu:24.04 as build
|
||||
|
||||
# Used to invalidate layer cache but not mount cache
|
||||
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493
|
||||
@@ -30,9 +30,9 @@ ARG LTO=ON
|
||||
ARG BUILD_TYPE=RelWithDebInfo
|
||||
ARG GIT_COMMIT_HASH
|
||||
ARG GIT_BRANCH
|
||||
ARG ARCHITECTURE_PACKAGE
|
||||
ARG ARCHITECTURE_FILE_NAME
|
||||
ARG ARCHITECTURE_APPIMAGE_BUILDER
|
||||
ARG ARCHITECTURE_PACKAGE=x86_64
|
||||
ARG ARCHITECTURE_FILE_NAME=amd64
|
||||
ARG ARCHITECTURE_APPIMAGE_BUILDER=x86_64
|
||||
WORKDIR /build
|
||||
|
||||
# Ubuntu sh doesnt support string substitution
|
||||
@@ -42,16 +42,18 @@ RUN <<EOF
|
||||
# Prepare ImHex build
|
||||
set -xe
|
||||
|
||||
CC=gcc-14 CXX=g++-14 cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
||||
-DIMHEX_COMMIT_HASH_LONG="${GIT_COMMIT_HASH}" \
|
||||
-DIMHEX_COMMIT_BRANCH="${GIT_BRANCH}" \
|
||||
-DIMHEX_ENABLE_LTO=${LTO} \
|
||||
-DIMHEX_PLUGINS_IN_SHARE=ON \
|
||||
CC=gcc-14 CXX=g++-14 cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
||||
-DIMHEX_COMMIT_HASH_LONG="${GIT_COMMIT_HASH}" \
|
||||
-DIMHEX_COMMIT_BRANCH="${GIT_BRANCH}" \
|
||||
-DIMHEX_ENABLE_LTO=${LTO} \
|
||||
-DIMHEX_BUNDLE_PLUGIN_SDK=OFF \
|
||||
`# To prevent using a libdir with an architecture-specific name` \
|
||||
-DCMAKE_INSTALL_LIBDIR="lib" \
|
||||
/imhex
|
||||
EOF
|
||||
|
||||
|
||||
2
dist/DEBIAN/control.in
vendored
2
dist/DEBIAN/control.in
vendored
@@ -4,7 +4,7 @@ Section: editors
|
||||
Priority: optional
|
||||
Architecture: amd64
|
||||
License: GNU GPL-2
|
||||
Depends: libfontconfig1, libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal, libssh2-1, md4c
|
||||
Depends: libfontconfig1, libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal, libssh2-1, libmd4c0
|
||||
Maintainer: WerWolv <hey@werwolv.net>
|
||||
Description: ImHex Hex Editor
|
||||
A Hex Editor for Reverse Engineers, Programmers and
|
||||
|
||||
13
dist/ImHex.run.xml
vendored
Normal file
13
dist/ImHex.run.xml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="ImHex" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" WORKING_DIR="file://$CMakeCurrentBuildDir$" PASS_PARENT_ENVS_2="true" PROJECT_NAME="ImHex" TARGET_NAME="imhex_all" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="ImHex" RUN_TARGET_NAME="main">
|
||||
<envs>
|
||||
<env name="NO_DEBUG_BANNER" value="1" />
|
||||
</envs>
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration default="false" name="CMake Debug" type="CMakeListConfigurationType" factoryName="CMakeListConfigurationFactory">
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
3
dist/cli/imhex.bat
vendored
Normal file
3
dist/cli/imhex.bat
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
|
||||
start "" "%~dp0..\imhex.exe" %*
|
||||
5
dist/cli/imhex.sh
vendored
Normal file
5
dist/cli/imhex.sh
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
script_path=$(readlink -f "$0")
|
||||
script_dir=$(dirname "${script_path}")
|
||||
"${script_dir}/../imhex" "$@" > /dev/null 2>&1 &
|
||||
4
dist/compiling/macos.md
vendored
4
dist/compiling/macos.md
vendored
@@ -3,7 +3,7 @@
|
||||
On macOS, ImHex is built through regular GCC and LLVM clang.
|
||||
|
||||
1. Clone the repo using `git clone https://github.com/WerWolv/ImHex --recurse-submodules`
|
||||
2. Install all the dependencies using `brew bundle --no-lock --file dist/macOS/Brewfile`
|
||||
2. Install all the dependencies using `brew bundle --file dist/macOS/Brewfile`
|
||||
3. Build ImHex itself using the following commands:
|
||||
```sh
|
||||
cd ImHex
|
||||
@@ -20,3 +20,5 @@ cmake -G "Ninja" \
|
||||
..
|
||||
ninja install
|
||||
```
|
||||
|
||||
If your MacOS installation doesn't have graphic acceleration, you can check the [MacOS NoGPU guide](./macos_nogpu.md)
|
||||
10
dist/compiling/macos_nogpu.md
vendored
Normal file
10
dist/compiling/macos_nogpu.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
### Compiling and running ImHex on macOS without a GPU
|
||||
|
||||
In order to run ImHex on a macOS installation without a GPU, you need a custom build of GLFW. You can build it this way:
|
||||
|
||||
Note: only tested on macOS x86
|
||||
|
||||
1. `git clone --depth 1 https://github.com/glfw/glfw`
|
||||
2. `git apply {IMHEX_DIR}/dist/macOS/0001-glfw-SW.patch` (file is [here](../macOS/0001-glfw-SW.patch) in the ImHex repository. [Source](https://github.com/glfw/glfw/issues/2080).)
|
||||
3. `cmake -G "Ninja" -DBUILD_SHARED_LIBS=ON ..`
|
||||
4. `ninja install`, or `ninja` and figure out how to make ImHex detect the shared library
|
||||
54
dist/flake.nix
vendored
Normal file
54
dist/flake.nix
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
description = "ImHex";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs }:
|
||||
let
|
||||
supportedSystems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin" ];
|
||||
forAllSystems = f: nixpkgs.lib.genAttrs supportedSystems (system: f system);
|
||||
in {
|
||||
devShells = forAllSystems (system:
|
||||
let
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
in
|
||||
{
|
||||
default = pkgs.mkShell {
|
||||
buildInputs = [
|
||||
pkgs.cmake
|
||||
pkgs.clang
|
||||
pkgs.lld
|
||||
|
||||
pkgs.nghttp3
|
||||
pkgs.pkg-config
|
||||
pkgs.glfw
|
||||
pkgs.fontconfig
|
||||
pkgs.file
|
||||
pkgs.mbedtls
|
||||
pkgs.freetype
|
||||
pkgs.dbus
|
||||
pkgs.gtk3
|
||||
pkgs.curl
|
||||
pkgs.fmt
|
||||
pkgs.yara
|
||||
pkgs.nlohmann_json
|
||||
pkgs.ninja
|
||||
pkgs.zlib
|
||||
pkgs.bzip2
|
||||
pkgs.xz
|
||||
pkgs.zstd
|
||||
pkgs.lz4
|
||||
pkgs.libssh2
|
||||
pkgs.md4c
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
export CC=${pkgs.clang}/bin/clang
|
||||
export CXX=${pkgs.clang}/bin/clang++
|
||||
'';
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
||||
1
dist/flatpak/net.werwolv.ImHex.yaml
vendored
1
dist/flatpak/net.werwolv.ImHex.yaml
vendored
@@ -120,6 +120,7 @@ modules:
|
||||
- -DUSE_SYSTEM_FMT=ON
|
||||
- -DUSE_SYSTEM_YARA=ON
|
||||
- -DIMHEX_OFFLINE_BUILD=ON
|
||||
- -DIMHEX_BUNDLE_PLUGIN_SDK=OFF
|
||||
- -DCMAKE_INSTALL_LIBDIR=lib
|
||||
- -DCMAKE_INSTALL_RPATH='$ORIGIN/../lib:$ORIGIN/../lib64'
|
||||
sources:
|
||||
|
||||
2
dist/macOS/0001-glfw-SW.patch
vendored
2
dist/macOS/0001-glfw-SW.patch
vendored
@@ -1,5 +1,5 @@
|
||||
From 9c8665af4c2e2ce66555c15c05c72027bfdf0cb6 Mon Sep 17 00:00:00 2001
|
||||
From: iTrooz <itrooz@protonmail.com>
|
||||
From: iTrooz <hey@itrooz.fr>
|
||||
Date: Mon, 29 Aug 2022 17:29:38 +0200
|
||||
Subject: [PATCH] Use software rendering on MacOS
|
||||
|
||||
|
||||
31
dist/macOS/arm64.Dockerfile
vendored
31
dist/macOS/arm64.Dockerfile
vendored
@@ -1,7 +1,7 @@
|
||||
# This base image is also known as "crosscompile". See arm64.crosscompile.Dockerfile
|
||||
FROM ghcr.io/werwolv/macos-crosscompile:clang20-nosdk as build
|
||||
FROM ghcr.io/werwolv/macos-crosscompile:6d89b20ac5ebedb6f680f94637591c94cb36f40b as build
|
||||
|
||||
ENV MACOSX_DEPLOYMENT_TARGET 13.0
|
||||
ENV MACOSX_DEPLOYMENT_TARGET 11.0
|
||||
|
||||
# -- DOWNLOADING STUFF
|
||||
|
||||
@@ -17,13 +17,13 @@ cp /tmp/arm-osx-mytriplet.cmake /vcpkg/triplets/community/arm-osx-mytriplet.cmak
|
||||
EOF
|
||||
|
||||
## Install make
|
||||
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y make
|
||||
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y make cmake
|
||||
|
||||
## fix environment
|
||||
### add install_name_tool for cmake command that won't have the right env set (see PostprocessBundle.cmake function postprocess_bundle())
|
||||
RUN cp /osxcross/build/cctools-port/cctools/misc/install_name_tool /usr/bin/install_name_tool
|
||||
### a cmake thing wants 'otool' and not '' apparently
|
||||
RUN cp /osxcross/target/bin/aarch64-apple-darwin23-otool /usr/bin/otool
|
||||
RUN cp /osxcross/target/bin/aarch64-apple-darwin24-otool /usr/bin/otool
|
||||
|
||||
## Clone glfw
|
||||
RUN <<EOF
|
||||
@@ -36,10 +36,10 @@ EOF
|
||||
RUN --mount=type=cache,target=/cache <<EOF
|
||||
## Download SDK is missing (it may have been removed from the image)
|
||||
set -xe
|
||||
if [ ! -d /osxcross/target/SDK/MacOSX14.0.sdk ]; then
|
||||
wget https://github.com/joseluisq/macosx-sdks/releases/download/14.0/MacOSX14.0.sdk.tar.xz -O /cache/MacOSX14.0.sdk.tar.xz -nc || true
|
||||
if [ ! -d /osxcross/target/SDK/MacOSX15.0.sdk ]; then
|
||||
wget https://github.com/joseluisq/macosx-sdks/releases/download/15.0/MacOSX15.0.sdk.tar.xz -O /cache/MacOSX15.0.sdk.tar.xz -nc || true
|
||||
mkdir -p /osxcross/target/SDK
|
||||
tar -C /osxcross/target/SDK -xf /cache/MacOSX14.0.sdk.tar.xz
|
||||
tar -C /osxcross/target/SDK -xf /cache/MacOSX15.0.sdk.tar.xz
|
||||
fi
|
||||
EOF
|
||||
|
||||
@@ -101,7 +101,7 @@ RUN --mount=type=cache,target=/cache <<EOF
|
||||
make -j $JOBS install
|
||||
|
||||
# Now, we cross-compile it and install it in the libraries folder
|
||||
CC=/osxcross/target/bin/aarch64-apple-darwin23-clang CXX=/osxcross/target/bin/aarch64-apple-darwin23-clang++ ./configure --prefix /vcpkg/installed/arm-osx-mytriplet --host $OSXCROSS_HOST
|
||||
CC=/osxcross/target/bin/aarch64-apple-darwin24-clang CXX=/osxcross/target/bin/aarch64-apple-darwin24-clang++ ./configure --prefix /vcpkg/installed/arm-osx-mytriplet --host $OSXCROSS_HOST
|
||||
make -j $JOBS
|
||||
make install
|
||||
|
||||
@@ -132,6 +132,7 @@ if [ "$CUSTOM_GLFW" ]; then
|
||||
mkdir build
|
||||
cd build
|
||||
CC=o64-clang CXX=o64-clang++ cmake -G "Ninja" \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DBUILD_SHARED_LIBS=ON \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
@@ -139,7 +140,7 @@ if [ "$CUSTOM_GLFW" ]; then
|
||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_INSTALL_PREFIX=/vcpkg/installed/arm-osx-mytriplet \
|
||||
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 \
|
||||
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=13.3 \
|
||||
..
|
||||
ninja -j $JOBS install
|
||||
|
||||
@@ -150,25 +151,25 @@ EOF
|
||||
# Build ImHex
|
||||
## Copy ImHex
|
||||
COPY --from=imhex / /mnt/ImHex
|
||||
## Patch ImHex with hacks
|
||||
# COPY toolchain.cmake.2 /osxcross/target/toolchain.cmake
|
||||
# Configure ImHex build
|
||||
## Configure ImHex build
|
||||
RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/_deps \
|
||||
cd /mnt/ImHex && \
|
||||
# compilers
|
||||
CC=o64-clang CXX=o64-clang++ OBJC=/osxcross/target/bin/aarch64-apple-darwin23-clang OBJCXX=/osxcross/target/bin/aarch64-apple-darwin23-clang++ \
|
||||
CC=o64-clang CXX=o64-clang++ OBJC=/osxcross/target/bin/aarch64-apple-darwin24-clang OBJCXX=/osxcross/target/bin/aarch64-apple-darwin24-clang++ \
|
||||
cmake -G "Ninja" \
|
||||
`# ccache flags` \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_OBJC_COMPILER_LAUNCHER=ccache -DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
||||
`# MacOS cross-compiling flags` \
|
||||
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 \
|
||||
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=13.3 \
|
||||
`# Override compilers for code generators` \
|
||||
-DNATIVE_CMAKE_C_COMPILER=/usr/bin/clang -DNATIVE_CMAKE_CXX_COMPILER=/usr/bin/clang++ \
|
||||
`# Normal ImHex flags` \
|
||||
-DIMHEX_GENERATE_PACKAGE=ON -DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
`# other flags` \
|
||||
-DIMHEX_STRICT_WARNINGS=OFF \
|
||||
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=/mnt/ImHex/build/install \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \
|
||||
-B build
|
||||
## Build ImHex
|
||||
RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/_deps <<EOF
|
||||
@@ -183,4 +184,4 @@ EOF
|
||||
|
||||
|
||||
FROM scratch
|
||||
COPY --from=build /mnt/ImHex/build/install/imhex.app imhex.app
|
||||
COPY --from=build /mnt/ImHex/build/install/ImHex.app ImHex.app
|
||||
|
||||
4
dist/macOS/arm64.crosscompile.Dockerfile
vendored
4
dist/macOS/arm64.crosscompile.Dockerfile
vendored
@@ -4,9 +4,9 @@ FROM ubuntu:22.04
|
||||
ENV PATH $PATH:/osxcross/target/bin
|
||||
ENV LD_LIBRARY_PATH /osxcross/target/lib
|
||||
ENV OSXCROSS_SDK /osxcross/target/SDK/MacOSX14.0.sdk
|
||||
ENV OSXCROSS_TARGET darwin23
|
||||
ENV OSXCROSS_TARGET darwin24
|
||||
ENV OSXCROSS_TARGET_DIR /osxcross/target
|
||||
ENV OSXCROSS_HOST aarch64-apple-darwin23
|
||||
ENV OSXCROSS_HOST aarch64-apple-darwin24
|
||||
|
||||
# -- DOWNLOADING STUFF
|
||||
|
||||
|
||||
11
dist/macOS/osx_10_15/x64-osx.cmake
vendored
Normal file
11
dist/macOS/osx_10_15/x64-osx.cmake
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
set(VCPKG_TARGET_ARCHITECTURE x64)
|
||||
set(VCPKG_BUILD_TYPE release)
|
||||
set(VCPKG_CRT_LINKAGE dynamic)
|
||||
set(VCPKG_LIBRARY_LINKAGE static)
|
||||
|
||||
set(VCPKG_CMAKE_SYSTEM_NAME Darwin)
|
||||
set(VCPKG_OSX_ARCHITECTURES x86_64)
|
||||
set(VCPKG_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "" FORCE)
|
||||
set(VCPKG_C_FLAGS "-mmacosx-version-min=10.15")
|
||||
set(VCPKG_CXX_FLAGS "-mmacosx-version-min=10.15")
|
||||
set(ENV{MACOSX_DEPLOYMENT_TARGET} "10.15")
|
||||
6
dist/net.werwolv.ImHex.metainfo.xml
vendored
6
dist/net.werwolv.ImHex.metainfo.xml
vendored
@@ -38,7 +38,7 @@
|
||||
<url type="homepage">https://imhex.werwolv.net</url>
|
||||
<url type="bugtracker">https://github.com/WerWolv/ImHex/issues</url>
|
||||
<url type="help">https://docs.werwolv.net/imhex</url>
|
||||
<url type="donation">https://www.patreon.com/werwolv</url>
|
||||
<url type="donation">https://github.com/sponsors/WerWolv</url>
|
||||
<url type="contact">https://imhex.werwolv.net/discord</url>
|
||||
<url type="vcs-browser">https://github.com/WerWolv/ImHex</url>
|
||||
<url type="contribute">https://github.com/WerWolv/ImHex/blob/master/CONTRIBUTING.md</url>
|
||||
@@ -64,4 +64,8 @@
|
||||
</release>
|
||||
</releases>
|
||||
<update_contact>hey@werwolv.net</update_contact>
|
||||
<recommends>
|
||||
<control>keyboard</control>
|
||||
<control>pointing</control>
|
||||
</recommends>
|
||||
</component>
|
||||
4
dist/rpm/imhex.spec
vendored
4
dist/rpm/imhex.spec
vendored
@@ -145,8 +145,7 @@ appstream-util validate-relax --nonet %{buildroot}%{_metainfodir}/net.werwolv.Im
|
||||
|
||||
# install licenses
|
||||
%if 0%{?rhel} == 9
|
||||
cp -a lib/third_party/capstone/LICENSE.TXT %{buildroot}%{_datadir}/licenses/%{name}/capstone-LICENSE
|
||||
cp -a lib/third_party/capstone/suite/regress/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/capstone-regress-LICENSE
|
||||
cp -a lib/third_party/capstone/LICENSES/LICENSE.TXT %{buildroot}%{_datadir}/licenses/%{name}/capstone-LICENSE
|
||||
%endif
|
||||
cp -a lib/third_party/microtar/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/microtar-LICENSE
|
||||
cp -a lib/third_party/xdgpp/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/xdgpp-LICENSE
|
||||
@@ -156,6 +155,7 @@ cp -a lib/third_party/xdgpp/LICENSE %{buildroot
|
||||
%license %{_datadir}/licenses/%{name}/
|
||||
%doc README.md
|
||||
%{_bindir}/imhex
|
||||
%{_datadir}/imhex/imhex
|
||||
%{_datadir}/pixmaps/%{name}.*
|
||||
%{_datadir}/applications/%{name}.desktop
|
||||
%{_libdir}/libimhex.so.*
|
||||
|
||||
4
dist/snap/snapcraft.yaml
vendored
4
dist/snap/snapcraft.yaml
vendored
@@ -1,7 +1,7 @@
|
||||
name: imhex
|
||||
title: ImHex
|
||||
base: core24
|
||||
version: ${IMHEX_VERSION}
|
||||
version: ${IMHEX_VERSION_STRING}
|
||||
summary: Hex editor for reverse engineering
|
||||
description: ImHex is a hex editor for reverse engineering, reverse engineering, and analyzing binary files. It provides a powerful and flexible interface for working with binary data, including features like pattern matching, scripting, and a customizable user interface.
|
||||
grade: stable
|
||||
@@ -40,6 +40,8 @@ parts:
|
||||
- -DCMAKE_BUILD_TYPE=Release
|
||||
- -DCMAKE_C_COMPILER_LAUNCHER=${CCACHE}
|
||||
- -DCMAKE_CXX_COMPILER_LAUNCHER=${CCACHE}
|
||||
- -DIMHEX_PATTERNS_PULL_MASTER=ON
|
||||
- -DIMHEX_BUNDLE_PLUGIN_SDK=OFF
|
||||
cmake-generator: Ninja
|
||||
build-packages:
|
||||
- cmake
|
||||
|
||||
2
dist/vcpkg.json
vendored
2
dist/vcpkg.json
vendored
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "vcpkg",
|
||||
"version": "1.0.0",
|
||||
"builtin-baseline": "7e21420f775f72ae938bdeb5e6068f722088f06a",
|
||||
"builtin-baseline": "66c0373dc7fca549e5803087b9487edfe3aca0a1",
|
||||
"dependencies": [
|
||||
"libmagic",
|
||||
"freetype",
|
||||
|
||||
14
dist/web/Dockerfile
vendored
14
dist/web/Dockerfile
vendored
@@ -1,8 +1,8 @@
|
||||
FROM emscripten/emsdk:4.0.8 AS build
|
||||
FROM emscripten/emsdk:4.0.21 AS build
|
||||
|
||||
# Used to invalidate layer cache but not mount cache
|
||||
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493
|
||||
ARG UNIQUEKEY 1
|
||||
ARG UNIQUEKEY=1
|
||||
|
||||
RUN apt update
|
||||
RUN apt install -y git ccache autoconf automake libtool pkg-config ninja-build
|
||||
@@ -12,13 +12,13 @@ RUN <<EOF
|
||||
# Note: we are a patch on the libmagic port
|
||||
set -xe
|
||||
|
||||
git clone https://github.com/microsoft/vcpkg /vcpkg
|
||||
git -C /vcpkg pull
|
||||
git clone --depth 1 https://github.com/microsoft/vcpkg /vcpkg
|
||||
/vcpkg/bootstrap-vcpkg.sh
|
||||
sed -i 's/vcpkg_install_make(${EXTRA_ARGS})/vcpkg_install_make(${EXTRA_ARGS} SUBPATH src)/g' /vcpkg/ports/libmagic/portfile.cmake
|
||||
EOF
|
||||
|
||||
# Patch vcpkg build instructions to add -pthread
|
||||
# Patch vcpkg build instructions to add -pthread flag
|
||||
# Even dependencies must be built with -pthread to be able to use USE_PTHREADS=1
|
||||
RUN <<EOF
|
||||
set -xe
|
||||
|
||||
@@ -50,6 +50,7 @@ ENV CCACHE_DIR=/cache/ccache
|
||||
|
||||
RUN mkdir /build
|
||||
WORKDIR /build
|
||||
ARG BUILD_TYPE=Release
|
||||
RUN --mount=type=cache,target=/cache \
|
||||
--mount=type=bind,source=.,target=/imhex <<EOF
|
||||
|
||||
@@ -70,7 +71,7 @@ ccache -zs
|
||||
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
|
||||
-DLIBROMFS_COMPRESS_RESOURCES=OFF \
|
||||
-DIMHEX_ENABLE_PLUGIN_TESTS=OFF \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
||||
|
||||
ninja -j $JOBS
|
||||
|
||||
@@ -106,3 +107,4 @@ COPY --from=build [ \
|
||||
|
||||
FROM nginx
|
||||
COPY --from=raw . /usr/share/nginx/html
|
||||
RUN chmod -R 755 /usr/share/nginx/html
|
||||
|
||||
9
dist/web/Host.Dockerfile
vendored
Normal file
9
dist/web/Host.Dockerfile
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
FROM python:3.12-slim
|
||||
|
||||
WORKDIR /imhex
|
||||
|
||||
COPY ./out/ .
|
||||
|
||||
EXPOSE 9090
|
||||
|
||||
CMD [ "python", "/imhex/start_imhex_web.py" ]
|
||||
1
dist/web/compose.yml
vendored
1
dist/web/compose.yml
vendored
@@ -1,5 +1,4 @@
|
||||
# docker compose -f dist/web/compose.yml up --build
|
||||
version: '3'
|
||||
services:
|
||||
imhex_web:
|
||||
image: imhex_web:latest
|
||||
|
||||
2
dist/web/serve.py
vendored
2
dist/web/serve.py
vendored
@@ -10,6 +10,6 @@ class MyHttpRequestHandler(http.server.SimpleHTTPRequestHandler):
|
||||
|
||||
if __name__ == '__main__':
|
||||
os.chdir(".")
|
||||
httpd = http.server.HTTPServer(("localhost", 9090), MyHttpRequestHandler)
|
||||
httpd = http.server.HTTPServer(("0.0.0.0", 9090), MyHttpRequestHandler)
|
||||
print(f"Serving {os.getcwd()} on http://{httpd.server_address[0]}:{httpd.server_address[1]}")
|
||||
httpd.serve_forever()
|
||||
|
||||
16
dist/web/source/index.html
vendored
16
dist/web/source/index.html
vendored
@@ -15,17 +15,17 @@
|
||||
|
||||
<!-- Open Graph / Facebook -->
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://imhex.werwolv.net/">
|
||||
<meta property="og:url" content="https://web.imhex.werwolv.net/">
|
||||
<meta property="og:title" content="ImHex Web - Online Hex Editor">
|
||||
<meta property="og:image" content="https://imhex.werwolv.net/assets/splash_wasm.png">
|
||||
<meta property="og:image" content="splash_wasm.png">
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta property="twitter:card" content="summary_large_image">
|
||||
<meta property="twitter:url" content="https://imhex.werwolv.net/">
|
||||
<meta property="twitter:url" content="https://web.imhex.werwolv.net/">
|
||||
<meta property="twitter:title" content="ImHex Web - Online Hex Editor">
|
||||
<meta property="twitter:description"
|
||||
content="A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.">
|
||||
<meta property="twitter:image" content="https://imhex.werwolv.net/assets/splash_wasm.png">
|
||||
<meta property="twitter:image" content="splash_wasm.png">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
"email": "hey@werwolv.net",
|
||||
"founder": "WerWolv",
|
||||
"slogan": "A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.",
|
||||
"url": "https://imhex.werwolv.net",
|
||||
"logo": "https://imhex.werwolv.net/assets/logos/logo.svg"
|
||||
"url": "https://web.imhex.werwolv.net",
|
||||
"logo": "https://web.imhex.werwolv.net/icon.svg"
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -96,7 +96,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
|
||||
<div id="canvas-wrapper" class="imhex-web-canvas-wrapper">
|
||||
<canvas class="imhex-web-canvas canvas-fixed" id="canvas" ></canvas>
|
||||
</div>
|
||||
|
||||
<script src="wasm-config.js"></script>
|
||||
<script async src="imhex.js"></script>
|
||||
|
||||
BIN
dist/web/source/splash_wasm.png
vendored
Normal file
BIN
dist/web/source/splash_wasm.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 478 KiB |
19
dist/web/source/style.css
vendored
19
dist/web/source/style.css
vendored
@@ -185,4 +185,23 @@ a:hover {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.imhex-web-canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
image-rendering: smooth;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.imhex-web-canvas-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
96
dist/web/source/wasm-config.js
vendored
96
dist/web/source/wasm-config.js
vendored
@@ -59,8 +59,14 @@ monkeyPatch((file, done) => {
|
||||
const mibTotal = (wasmSize / 1024**2).toFixed(1);
|
||||
|
||||
let root = document.querySelector(':root');
|
||||
root.style.setProperty("--progress", `${percent}%`)
|
||||
document.getElementById("progress-bar-content").innerHTML = `${percent}% [${mibNow} MiB / ${mibTotal} MiB]`;
|
||||
if (root != null) {
|
||||
root.style.setProperty("--progress", `${percent}%`)
|
||||
let progressBar = document.getElementById("progress-bar-content");
|
||||
|
||||
if (progressBar != null) {
|
||||
progressBar.innerHTML = `${percent}% [${mibNow} MiB / ${mibTotal} MiB]`;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function glfwSetCursorCustom(wnd, shape) {
|
||||
@@ -100,81 +106,17 @@ var notWorkingTimer = setTimeout(() => {
|
||||
}, 5000);
|
||||
|
||||
var Module = {
|
||||
preRun: [],
|
||||
preRun: () => {
|
||||
ENV.IMHEX_SKIP_SPLASH_SCREEN = "1";
|
||||
},
|
||||
postRun: function() {
|
||||
// Patch the emscripten GLFW module to send mouse and touch events in the right order
|
||||
// For ImGui interactions to correctly work with touch input, MousePos events need
|
||||
// to be processed first and then MouseButton events in the next frame. By default,
|
||||
// GLFW does the exact opposite, which causes buttons to require two taps to register
|
||||
// and windows get "stuck" to the cursor when dragged or resized
|
||||
GLFW.onMousemove = event => {
|
||||
if (event.type === "touchmove") {
|
||||
event.preventDefault();
|
||||
let primaryChanged = false;
|
||||
for (let i of event.changedTouches) {
|
||||
if (GLFW.primaryTouchId === i.identifier) {
|
||||
Browser.setMouseCoords(i.pageX, i.pageY);
|
||||
primaryChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!primaryChanged) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Browser.calculateMouseEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
GLFW.onMouseButtonChanged = (event, status) => {
|
||||
if (!GLFW.active) return;
|
||||
if (event.target != Module["canvas"]) return;
|
||||
const isTouchType = event.type === "touchstart" || event.type === "touchend" || event.type === "touchcancel";
|
||||
let eventButton = 0;
|
||||
if (isTouchType) {
|
||||
event.preventDefault();
|
||||
let primaryChanged = false;
|
||||
if (GLFW.primaryTouchId === null && event.type === "touchstart" && event.targetTouches.length > 0) {
|
||||
const chosenTouch = event.targetTouches[0];
|
||||
GLFW.primaryTouchId = chosenTouch.identifier;
|
||||
Browser.setMouseCoords(chosenTouch.pageX, chosenTouch.pageY);
|
||||
primaryChanged = true;
|
||||
} else if (event.type === "touchend" || event.type === "touchcancel") {
|
||||
for (let i of event.changedTouches) {
|
||||
if (GLFW.primaryTouchId === i.identifier) {
|
||||
GLFW.primaryTouchId = null;
|
||||
primaryChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!primaryChanged) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Browser.calculateMouseEvent(event);
|
||||
eventButton = GLFW.DOMToGLFWMouseButton(event);
|
||||
}
|
||||
if (status == 1) {
|
||||
GLFW.active.buttons |= (1 << eventButton);
|
||||
try {
|
||||
event.target.setCapture();
|
||||
} catch (e) {}
|
||||
} else {
|
||||
GLFW.active.buttons &= ~(1 << eventButton);
|
||||
}
|
||||
|
||||
if (GLFW.active.cursorPosFunc) {
|
||||
getWasmTableEntry(GLFW.active.cursorPosFunc)(GLFW.active.id, Browser.mouseX, Browser.mouseY);
|
||||
}
|
||||
if (GLFW.active.mouseButtonFunc) {
|
||||
getWasmTableEntry(GLFW.active.mouseButtonFunc)(GLFW.active.id, eventButton, status, GLFW.getModBits(GLFW.active));
|
||||
}
|
||||
};
|
||||
},
|
||||
onRuntimeInitialized: function() {
|
||||
// Triggered when the wasm module is loaded and ready to use.
|
||||
document.getElementById("loading").style.display = "none"
|
||||
let loading = document.getElementById("loading");
|
||||
if (loading != null)
|
||||
document.getElementById("loading").style.display = "none"
|
||||
document.getElementById("canvas").style.display = "initial"
|
||||
|
||||
clearTimeout(notWorkingTimer);
|
||||
@@ -257,16 +199,6 @@ if (urlParams.has("lang")) {
|
||||
Module["arguments"].push(urlParams.get("save-editor"));
|
||||
}
|
||||
|
||||
window.addEventListener('resize', js_resizeCanvas, false);
|
||||
function js_resizeCanvas() {
|
||||
let canvas = document.getElementById('canvas');
|
||||
|
||||
canvas.top = document.documentElement.clientTop;
|
||||
canvas.left = document.documentElement.clientLeft;
|
||||
canvas.width = Math.min(document.documentElement.clientWidth, window.innerWidth || 0);
|
||||
canvas.height = Math.min(document.documentElement.clientHeight, window.innerHeight || 0);
|
||||
}
|
||||
|
||||
// Prevent some default browser shortcuts from preventing ImHex ones to work
|
||||
document.addEventListener('keydown', e => {
|
||||
if (e.ctrlKey) {
|
||||
|
||||
2
lib/external/disassembler
vendored
2
lib/external/disassembler
vendored
Submodule lib/external/disassembler updated: 7235352627...c66e624157
2
lib/external/libwolv
vendored
2
lib/external/libwolv
vendored
Submodule lib/external/libwolv updated: 8427d4da72...1063613e87
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
Submodule lib/external/pattern_language updated: 7e00014c35...9adb36901a
@@ -42,6 +42,7 @@ set(LIBIMHEX_SOURCES
|
||||
source/helpers/keys.cpp
|
||||
source/helpers/udp_server.cpp
|
||||
source/helpers/scaling.cpp
|
||||
source/helpers/binary_pattern.cpp
|
||||
|
||||
source/test/tests.cpp
|
||||
|
||||
@@ -56,19 +57,13 @@ set(LIBIMHEX_SOURCES
|
||||
source/ui/toast.cpp
|
||||
source/ui/banner.cpp
|
||||
|
||||
source/mcp/client.cpp
|
||||
source/mcp/server.cpp
|
||||
|
||||
source/subcommands/subcommands.cpp
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
set(OSX_SDK_PATH /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.sdk)
|
||||
if (NOT CMAKE_OSX_SYSROOT)
|
||||
if (IS_DIRECTORY ${OSX_SDK_PATH})
|
||||
set(CMAKE_OSX_SYSROOT ${OSX_SDK_PATH})
|
||||
else ()
|
||||
message(WARNING "CMAKE_OSX_SYSROOT not set and macOS SDK not found! Using default one.")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
set(LIBIMHEX_SOURCES ${LIBIMHEX_SOURCES}
|
||||
source/helpers/utils_macos.m
|
||||
source/helpers/macos_menu.m
|
||||
|
||||
@@ -145,62 +145,17 @@ EXPORT_MODULE namespace hex {
|
||||
* @brief Returns the icon of the achievement
|
||||
* @return Icon of the achievement
|
||||
*/
|
||||
[[nodiscard]] const ImGuiExt::Texture &getIcon() const {
|
||||
if (m_iconData.empty())
|
||||
return m_icon;
|
||||
|
||||
if (m_icon.isValid())
|
||||
return m_icon;
|
||||
|
||||
m_icon = ImGuiExt::Texture::fromImage(m_iconData.data(), m_iconData.size(), ImGuiExt::Texture::Filter::Linear);
|
||||
|
||||
return m_icon;
|
||||
[[nodiscard]] const char* getIcon() const {
|
||||
return m_icon.c_str();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the icon of the achievement
|
||||
* @param data Icon data
|
||||
* @param icon Icon glyph
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& setIcon(std::span<const std::byte> data) {
|
||||
m_iconData.reserve(data.size());
|
||||
for (auto &byte : data)
|
||||
m_iconData.emplace_back(static_cast<u8>(byte));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the icon of the achievement
|
||||
* @param data Icon data
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& setIcon(std::span<const u8> data) {
|
||||
m_iconData.assign(data.begin(), data.end());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the icon of the achievement
|
||||
* @param data Icon data
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& setIcon(std::vector<u8> data) {
|
||||
m_iconData = std::move(data);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the icon of the achievement
|
||||
* @param data Icon data
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& setIcon(const std::vector<std::byte> &data) {
|
||||
m_iconData.reserve(data.size());
|
||||
for (auto &byte : data)
|
||||
m_iconData.emplace_back(static_cast<u8>(byte));
|
||||
Achievement& setIcon(std::string icon) {
|
||||
m_icon = std::move(icon);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -284,8 +239,7 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
std::function<void(Achievement &)> m_clickCallback;
|
||||
|
||||
std::vector<u8> m_iconData;
|
||||
mutable ImGuiExt::Texture m_icon;
|
||||
std::string m_icon;
|
||||
|
||||
u32 m_progress = 0;
|
||||
u32 m_maxProgress = 1;
|
||||
|
||||
@@ -16,7 +16,7 @@ EXPORT_MODULE namespace hex {
|
||||
void stopServices();
|
||||
}
|
||||
|
||||
void registerService(const UnlocalizedString &unlocalizedString, const impl::Callback &callback);
|
||||
void registerService(const UnlocalizedString &unlocalizedName, const impl::Callback &callback);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <hex/mcp/server.hpp>
|
||||
|
||||
EXPORT_MODULE namespace hex {
|
||||
|
||||
/* Network Communication Interface Registry. Allows adding new communication interface endpoints */
|
||||
@@ -22,4 +24,19 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::MCP {
|
||||
|
||||
namespace impl {
|
||||
std::unique_ptr<mcp::Server>& getMcpServerInstance();
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
}
|
||||
|
||||
bool isEnabled();
|
||||
bool isConnected();
|
||||
|
||||
void registerTool(std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json ¶ms)> function);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,9 +27,10 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
struct FindOccurrence {
|
||||
Region region;
|
||||
enum class DecodeType { ASCII, UTF8, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
|
||||
std::endian endian = std::endian::native;
|
||||
enum class DecodeType : u8 { ASCII, UTF8, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
|
||||
bool selected;
|
||||
std::string string;
|
||||
};
|
||||
|
||||
using FindExporterCallback = std::function<std::vector<u8>(const std::vector<FindOccurrence>&, std::function<std::string(FindOccurrence)>)>;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <bit>
|
||||
|
||||
EXPORT_MODULE namespace hex {
|
||||
|
||||
@@ -22,8 +23,10 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
namespace impl {
|
||||
|
||||
struct DoNotUseThisByItselfTag {};
|
||||
|
||||
using DisplayFunction = std::function<std::string()>;
|
||||
using EditingFunction = std::function<std::vector<u8>(std::string, std::endian)>;
|
||||
using EditingFunction = std::function<std::optional<std::vector<u8>>(std::string&, std::endian, DoNotUseThisByItselfTag)>;
|
||||
using GeneratorFunction = std::function<DisplayFunction(const std::vector<u8> &, std::endian, NumberDisplayStyle)>;
|
||||
|
||||
struct Entry {
|
||||
@@ -38,6 +41,35 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace EditWidget {
|
||||
|
||||
class Widget {
|
||||
public:
|
||||
using Function = std::function<std::vector<u8>(const std::string&, std::endian)>;
|
||||
|
||||
explicit Widget(const Function &function) : m_function(function) {}
|
||||
|
||||
virtual ~Widget() = default;
|
||||
virtual std::optional<std::vector<u8>> draw(std::string &value, std::endian endian) = 0;
|
||||
std::optional<std::vector<u8>> operator()(std::string &value, std::endian endian, impl::DoNotUseThisByItselfTag) {
|
||||
return draw(value, endian);
|
||||
}
|
||||
|
||||
std::vector<u8> getBytes(const std::string &value, std::endian endian) const {
|
||||
return m_function(value, endian);
|
||||
}
|
||||
|
||||
private:
|
||||
Function m_function;
|
||||
};
|
||||
|
||||
struct TextInput : Widget {
|
||||
explicit TextInput(const Function &function) : Widget(function) {}
|
||||
std::optional<std::vector<u8>> draw(std::string &value, std::endian endian) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a new entry to the data inspector
|
||||
* @param unlocalizedName The unlocalized name of the entry
|
||||
|
||||
@@ -38,24 +38,14 @@ EXPORT_MODULE namespace hex {
|
||||
[[nodiscard]] const Hash *getType() const { return m_type; }
|
||||
[[nodiscard]] const std::string& getName() const { return m_name; }
|
||||
|
||||
const std::vector<u8>& get(const Region& region, prv::Provider *provider) {
|
||||
if (m_cache.empty()) {
|
||||
m_cache = m_callback(region, provider);
|
||||
}
|
||||
|
||||
return m_cache;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_cache.clear();
|
||||
std::vector<u8> get(const Region& region, prv::Provider *provider) const {
|
||||
return m_callback(region, provider);
|
||||
}
|
||||
|
||||
private:
|
||||
Hash *m_type;
|
||||
std::string m_name;
|
||||
Callback m_callback;
|
||||
|
||||
std::vector<u8> m_cache;
|
||||
};
|
||||
|
||||
virtual void draw() { }
|
||||
|
||||
@@ -19,7 +19,7 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
void addProviderName(const UnlocalizedString &unlocalizedName, const char *icon);
|
||||
|
||||
using ProviderCreationFunction = std::function<std::unique_ptr<prv::Provider>()>;
|
||||
using ProviderCreationFunction = std::function<std::shared_ptr<prv::Provider>()>;
|
||||
void add(const std::string &typeName, ProviderCreationFunction creationFunction);
|
||||
|
||||
struct Entry {
|
||||
|
||||
@@ -52,7 +52,7 @@ EXPORT_MODULE namespace hex {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Interface& setTooltip(const std::string &tooltip) {
|
||||
Interface& setTooltip(const UnlocalizedString &tooltip) {
|
||||
m_tooltip = tooltip;
|
||||
|
||||
return *this;
|
||||
@@ -239,6 +239,14 @@ EXPORT_MODULE namespace hex {
|
||||
nlohmann::json store() override { return {}; }
|
||||
};
|
||||
|
||||
class Spacer : public Widget {
|
||||
public:
|
||||
bool draw(const std::string &name) override;
|
||||
|
||||
void load(const nlohmann::json &) override {}
|
||||
nlohmann::json store() override { return {}; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace impl {
|
||||
@@ -290,8 +298,8 @@ EXPORT_MODULE namespace hex {
|
||||
public:
|
||||
SettingsValue(nlohmann::json value) : m_value(std::move(value)) {}
|
||||
|
||||
template<typename T>
|
||||
T get(std::common_type_t<T> defaultValue) const {
|
||||
template<typename T> requires (!(std::is_reference_v<T> || std::is_const_v<T>))
|
||||
[[nodiscard]] T get(T defaultValue) const {
|
||||
try {
|
||||
auto result = m_value;
|
||||
if (result.is_number() && std::same_as<T, bool>)
|
||||
@@ -308,8 +316,8 @@ EXPORT_MODULE namespace hex {
|
||||
nlohmann::json m_value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] T read(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const std::common_type_t<T> &defaultValue) {
|
||||
template<typename T> requires (!(std::is_reference_v<T> || std::is_const_v<T>))
|
||||
[[nodiscard]] T read(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, T defaultValue) {
|
||||
auto setting = impl::getSetting(unlocalizedCategory, unlocalizedName, defaultValue);
|
||||
|
||||
try {
|
||||
@@ -326,8 +334,8 @@ EXPORT_MODULE namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void write(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const std::common_type_t<T> &value) {
|
||||
template<typename T> requires (!(std::is_reference_v<T> || std::is_const_v<T>))
|
||||
void write(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, T value) {
|
||||
impl::getSetting(unlocalizedCategory, unlocalizedName, value) = value;
|
||||
impl::runOnChangeHandlers(unlocalizedCategory, unlocalizedName, value);
|
||||
|
||||
@@ -336,10 +344,75 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
using OnChangeCallback = std::function<void(const SettingsValue &)>;
|
||||
u64 onChange(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const OnChangeCallback &callback);
|
||||
void removeOnChangeHandler(u64 id);
|
||||
|
||||
using OnSaveCallback = std::function<void()>;
|
||||
u64 onSave(const OnSaveCallback &callback);
|
||||
|
||||
template<typename T, wolv::type::StaticString UnlocalizedCategory, wolv::type::StaticString UnlocalizedName>
|
||||
requires (!(std::is_reference_v<T> || std::is_const_v<T>))
|
||||
class SettingsVariable {
|
||||
public:
|
||||
explicit(false) SettingsVariable(T defaultValue) noexcept : m_defaultValue(std::move(defaultValue)) { }
|
||||
|
||||
SettingsVariable(const SettingsVariable&) = delete;
|
||||
SettingsVariable& operator=(const SettingsVariable&) = delete;
|
||||
|
||||
SettingsVariable(SettingsVariable&&) = delete;
|
||||
SettingsVariable& operator=(SettingsVariable&&) = delete;
|
||||
|
||||
~SettingsVariable() {
|
||||
if (m_onChangeId > 0)
|
||||
removeOnChangeHandler(m_onChangeId);
|
||||
}
|
||||
|
||||
[[nodiscard]] T get() const {
|
||||
registerChangeHandler();
|
||||
if (!m_value.has_value()) {
|
||||
m_value = read<T>(
|
||||
UnlocalizedCategory.value.data(),
|
||||
UnlocalizedName.value.data(),
|
||||
m_defaultValue
|
||||
);
|
||||
}
|
||||
|
||||
return m_value.value_or(m_defaultValue);
|
||||
}
|
||||
|
||||
void set(T value) {
|
||||
registerChangeHandler();
|
||||
write<T>(
|
||||
UnlocalizedCategory.value.data(),
|
||||
UnlocalizedName.value.data(),
|
||||
std::move(value)
|
||||
);
|
||||
}
|
||||
|
||||
explicit(false) operator T() const {
|
||||
return get();
|
||||
}
|
||||
|
||||
SettingsVariable& operator=(T value) {
|
||||
set(std::move(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
void registerChangeHandler() const {
|
||||
if (m_onChangeId > 0)
|
||||
return;
|
||||
|
||||
m_onChangeId = onChange(UnlocalizedCategory.value.data(), UnlocalizedName.value.data(), [this](const SettingsValue &value) {
|
||||
m_value = value.get<T>(m_defaultValue);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::optional<T> m_value;
|
||||
T m_defaultValue;
|
||||
mutable u64 m_onChangeId = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -68,6 +68,7 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
constexpr static auto SeparatorValue = "$SEPARATOR$";
|
||||
constexpr static auto SubMenuValue = "$SUBMENU$";
|
||||
constexpr static auto TaskBarMenuValue = "$TASKBAR$";
|
||||
|
||||
const std::multimap<u32, MainMenuItem>& getMainMenuItems();
|
||||
|
||||
@@ -159,13 +160,15 @@ EXPORT_MODULE namespace hex {
|
||||
* @param function The function to call when the entry is clicked
|
||||
* @param enabledCallback The function to call to determine if the entry is enabled
|
||||
* @param view The view to use for the entry. If nullptr, the item will always be visible
|
||||
* @param showOnWelcomeScreen If this entry should be shown on the welcome screen
|
||||
*/
|
||||
void addMenuItemSubMenu(
|
||||
std::vector<UnlocalizedString> unlocalizedMainMenuNames,
|
||||
u32 priority,
|
||||
const impl::MenuCallback &function,
|
||||
const impl::EnabledCallback& enabledCallback = []{ return true; },
|
||||
View *view = nullptr
|
||||
View *view = nullptr,
|
||||
bool showOnWelcomeScreen = false
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -176,6 +179,7 @@ EXPORT_MODULE namespace hex {
|
||||
* @param function The function to call when the entry is clicked
|
||||
* @param enabledCallback The function to call to determine if the entry is enabled
|
||||
* @param view The view to use for the entry. If nullptr, the item will always be visible
|
||||
* @param showOnWelcomeScreen If this entry should be shown on the welcome screen
|
||||
*/
|
||||
void addMenuItemSubMenu(
|
||||
std::vector<UnlocalizedString> unlocalizedMainMenuNames,
|
||||
@@ -183,7 +187,8 @@ EXPORT_MODULE namespace hex {
|
||||
u32 priority,
|
||||
const impl::MenuCallback &function,
|
||||
const impl::EnabledCallback& enabledCallback = []{ return true; },
|
||||
View *view = nullptr
|
||||
View *view = nullptr,
|
||||
bool showOnWelcomeScreen = false
|
||||
);
|
||||
|
||||
|
||||
@@ -195,6 +200,19 @@ EXPORT_MODULE namespace hex {
|
||||
*/
|
||||
void addMenuItemSeparator(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, View *view = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Adds a new main menu entry
|
||||
* @param unlocalizedMainMenuNames The unlocalized names of the main menu entries
|
||||
* @param priority The priority of the entry. Lower values are displayed first
|
||||
* @param function The function to call when the entry is clicked
|
||||
* @param enabledCallback The function to call to determine if the entry is enabled
|
||||
*/
|
||||
void addTaskBarMenuItem(
|
||||
std::vector<UnlocalizedString> unlocalizedMainMenuNames,
|
||||
u32 priority,
|
||||
const impl::MenuCallback &function,
|
||||
const impl::EnabledCallback& enabledCallback
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Adds a new welcome screen entry
|
||||
@@ -216,10 +234,10 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Adds a menu item to the toolbar
|
||||
* @param unlocalizedName Unlocalized name of the menu item
|
||||
* @param unlocalizedNames Unlocalized name of the menu item
|
||||
* @param color Color of the toolbar icon
|
||||
*/
|
||||
void addMenuItemToToolbar(const UnlocalizedString &unlocalizedName, ImGuiCustomCol color);
|
||||
void addMenuItemToToolbar(const std::vector<UnlocalizedString> &unlocalizedNames, ImGuiCustomCol color);
|
||||
|
||||
/**
|
||||
* @brief Reconstructs the toolbar items list after they have been modified
|
||||
|
||||
@@ -79,6 +79,11 @@ namespace hex {
|
||||
*/
|
||||
EVENT_DEF(EventProjectOpened);
|
||||
|
||||
/**
|
||||
* @brief Called when a project is saved/saved as
|
||||
*/
|
||||
EVENT_DEF(EventProjectSaved);
|
||||
|
||||
/**
|
||||
* @brief Called when a native message was received from another ImHex instance
|
||||
* @param rawData Raw bytes received from other instance
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace hex {
|
||||
* This event is responsible for (optionally) initializing the provider and calling EventProviderOpened
|
||||
* (although the event can also be called manually without problem)
|
||||
*/
|
||||
EVENT_DEF(EventProviderCreated, prv::Provider *);
|
||||
EVENT_DEF(EventProviderCreated, std::shared_ptr<prv::Provider>);
|
||||
|
||||
/**
|
||||
* @brief Called as a continuation of EventProviderCreated
|
||||
|
||||
@@ -8,7 +8,12 @@ namespace hex {
|
||||
/**
|
||||
* @brief Creates a provider from its unlocalized name, and add it to the provider list
|
||||
*/
|
||||
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, hex::prv::Provider **);
|
||||
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, std::shared_ptr<hex::prv::Provider> *);
|
||||
|
||||
/**
|
||||
* @brief Used internally when opening a provider through the API
|
||||
*/
|
||||
EVENT_DEF(RequestOpenProvider, std::shared_ptr<prv::Provider>);
|
||||
|
||||
/**
|
||||
* @brief Move the data from all PerProvider instances from one provider to another
|
||||
|
||||
@@ -86,7 +86,7 @@ EXPORT_MODULE namespace hex {
|
||||
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
|
||||
* @param select Whether to select the provider after adding it
|
||||
*/
|
||||
void add(std::unique_ptr<prv::Provider> &&provider, bool skipLoadInterface = false, bool select = true);
|
||||
void add(std::shared_ptr<prv::Provider> &&provider, bool skipLoadInterface = false, bool select = true);
|
||||
|
||||
/**
|
||||
* @brief Creates a new provider and adds it to the list of providers
|
||||
@@ -111,12 +111,18 @@ EXPORT_MODULE namespace hex {
|
||||
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
|
||||
* @param select Whether to select the provider after adding it
|
||||
*/
|
||||
prv::Provider* createProvider(
|
||||
std::shared_ptr<prv::Provider> createProvider(
|
||||
const UnlocalizedString &unlocalizedName,
|
||||
bool skipLoadInterface = false,
|
||||
bool select = true
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Opens a provider, making its data available to ImHex and handling any error that may occur
|
||||
* @param provider The provider to open
|
||||
*/
|
||||
void openProvider(std::shared_ptr<prv::Provider> provider);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -62,6 +62,7 @@ EXPORT_MODULE namespace hex {
|
||||
void setMainWindowSize(u32 width, u32 height);
|
||||
void setMainDockSpaceId(ImGuiID id);
|
||||
void setMainWindowHandle(GLFWwindow *window);
|
||||
void setMainWindowFocusState(bool focused);
|
||||
|
||||
void setGlobalScale(float scale);
|
||||
void setNativeScale(float scale);
|
||||
@@ -161,6 +162,12 @@ EXPORT_MODULE namespace hex {
|
||||
*/
|
||||
GLFWwindow* getMainWindowHandle();
|
||||
|
||||
/**
|
||||
* @brief Checks if the main window is currently focused
|
||||
* @return Whether the main window is focused
|
||||
*/
|
||||
bool isMainWindowFocused();
|
||||
|
||||
/**
|
||||
* @brief Checks if borderless window mode is enabled currently
|
||||
* @return Whether borderless window mode is enabled
|
||||
@@ -171,7 +178,7 @@ EXPORT_MODULE namespace hex {
|
||||
* @brief Checks if multi-window mode is enabled currently
|
||||
* @return Whether multi-window mode is enabled
|
||||
*/
|
||||
bool isMutliWindowModeEnabled();
|
||||
bool isMultiWindowModeEnabled();
|
||||
|
||||
/**
|
||||
* @brief Gets the init arguments passed to ImHex from the splash screen
|
||||
@@ -276,7 +283,7 @@ EXPORT_MODULE namespace hex {
|
||||
* @brief Gets the current ImHex version
|
||||
* @return ImHex version
|
||||
*/
|
||||
SemanticVersion getImHexVersion();
|
||||
const SemanticVersion& getImHexVersion();
|
||||
|
||||
/**
|
||||
* @brief Gets the current git commit hash
|
||||
|
||||
@@ -27,6 +27,7 @@ EXPORT_MODULE namespace hex {
|
||||
LanguageId id;
|
||||
std::string name, nativeName;
|
||||
LanguageId fallbackLanguageId;
|
||||
bool hidden;
|
||||
|
||||
std::vector<PathEntry> languageFilePaths;
|
||||
};
|
||||
@@ -58,7 +59,6 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
private:
|
||||
std::size_t m_entryHash;
|
||||
std::string m_unlocalizedString;
|
||||
};
|
||||
|
||||
class LangConst {
|
||||
@@ -102,6 +102,14 @@ EXPORT_MODULE namespace hex {
|
||||
UnlocalizedString(const std::string &string) : m_unlocalizedString(string) { }
|
||||
UnlocalizedString(const char *string) : m_unlocalizedString(string) { }
|
||||
UnlocalizedString(const Lang& arg) = delete;
|
||||
UnlocalizedString(std::string &&string) : m_unlocalizedString(std::move(string)) { }
|
||||
UnlocalizedString(UnlocalizedString &&) = default;
|
||||
UnlocalizedString(const UnlocalizedString &) = default;
|
||||
|
||||
UnlocalizedString &operator=(const UnlocalizedString &) = default;
|
||||
UnlocalizedString &operator=(UnlocalizedString &&) = default;
|
||||
UnlocalizedString &operator=(const std::string &string) { m_unlocalizedString = string; return *this; }
|
||||
UnlocalizedString &operator=(std::string &&string) { m_unlocalizedString = std::move(string); return *this; }
|
||||
|
||||
[[nodiscard]] operator std::string() const {
|
||||
return m_unlocalizedString;
|
||||
|
||||
@@ -151,6 +151,8 @@ EXPORT_MODULE namespace hex {
|
||||
*/
|
||||
static void clearShortcuts();
|
||||
|
||||
static Shortcut getShortcutByName(const std::vector<UnlocalizedString> &unlocalizedName, const View *view = nullptr);
|
||||
|
||||
static void resumeShortcuts();
|
||||
static void pauseShortcuts();
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <condition_variable>
|
||||
#include <source_location>
|
||||
#include <thread>
|
||||
#include <hex/trace/exceptions.hpp>
|
||||
|
||||
EXPORT_MODULE namespace hex {
|
||||
|
||||
@@ -22,7 +23,7 @@ EXPORT_MODULE namespace hex {
|
||||
class Task {
|
||||
public:
|
||||
Task() = default;
|
||||
Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function);
|
||||
Task(UnlocalizedString unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function);
|
||||
|
||||
Task(const Task&) = delete;
|
||||
Task(Task &&other) noexcept;
|
||||
@@ -70,6 +71,8 @@ EXPORT_MODULE namespace hex {
|
||||
[[nodiscard]] u64 getValue() const;
|
||||
[[nodiscard]] u64 getMaxValue() const;
|
||||
|
||||
void wait() const;
|
||||
|
||||
private:
|
||||
void finish();
|
||||
void interruption();
|
||||
@@ -87,12 +90,21 @@ EXPORT_MODULE namespace hex {
|
||||
std::atomic<bool> m_background = true;
|
||||
std::atomic<bool> m_blocking = false;
|
||||
|
||||
std::atomic<bool> m_interrupted = false;
|
||||
std::atomic<bool> m_finished = false;
|
||||
std::atomic<bool> m_hadException = false;
|
||||
std::atomic_flag m_interrupted;
|
||||
std::atomic_flag m_finished;
|
||||
std::atomic_flag m_hadException;
|
||||
std::string m_exceptionMessage;
|
||||
|
||||
struct TaskInterruptor { virtual ~TaskInterruptor() = default; };
|
||||
struct TaskInterruptor: public std::exception {
|
||||
TaskInterruptor() {
|
||||
trace::disableExceptionCaptureForCurrentThread();
|
||||
}
|
||||
virtual ~TaskInterruptor() = default;
|
||||
|
||||
[[nodiscard]] const char* what() const noexcept override {
|
||||
return "Task Interrupted";
|
||||
}
|
||||
};
|
||||
|
||||
friend class TaskHolder;
|
||||
friend class TaskManager;
|
||||
@@ -114,6 +126,7 @@ EXPORT_MODULE namespace hex {
|
||||
[[nodiscard]] u32 getProgress() const;
|
||||
|
||||
void interrupt() const;
|
||||
void wait() const;
|
||||
private:
|
||||
std::weak_ptr<Task> m_task;
|
||||
};
|
||||
@@ -239,6 +252,8 @@ EXPORT_MODULE namespace hex {
|
||||
static const std::list<std::shared_ptr<Task>>& getRunningTasks();
|
||||
static void runDeferredCalls();
|
||||
|
||||
static void addTaskCompletionCallback(const std::function<void(Task&)>& function);
|
||||
|
||||
private:
|
||||
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function);
|
||||
};
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#include <hex/ui/imgui_imhex_extensions.h>
|
||||
|
||||
struct ImRect;
|
||||
|
||||
EXPORT_MODULE namespace hex {
|
||||
|
||||
class TutorialManager {
|
||||
@@ -22,6 +24,8 @@ EXPORT_MODULE namespace hex {
|
||||
Right = 8
|
||||
};
|
||||
|
||||
using DrawFunction = std::function<void()>;
|
||||
|
||||
struct Tutorial {
|
||||
Tutorial() = delete;
|
||||
Tutorial(const UnlocalizedString &unlocalizedName, const UnlocalizedString &unlocalizedDescription) :
|
||||
@@ -101,6 +105,7 @@ EXPORT_MODULE namespace hex {
|
||||
std::vector<Highlight> m_highlights;
|
||||
std::optional<Message> m_message;
|
||||
std::function<void()> m_onAppear, m_onComplete;
|
||||
DrawFunction m_drawFunction;
|
||||
};
|
||||
|
||||
Step& addStep();
|
||||
@@ -146,6 +151,7 @@ EXPORT_MODULE namespace hex {
|
||||
* @param unlocalizedName Name of tutorial to start
|
||||
*/
|
||||
static void startTutorial(const UnlocalizedString &unlocalizedName);
|
||||
static void stopCurrentTutorial();
|
||||
|
||||
static void startHelpHover();
|
||||
static void addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString);
|
||||
@@ -166,6 +172,10 @@ EXPORT_MODULE namespace hex {
|
||||
*/
|
||||
static void reset();
|
||||
|
||||
static void setRenderer(std::function<DrawFunction(const std::string &)> renderer);
|
||||
|
||||
static void postElementRendered(ImGuiID id, const ImRect &boundingBox);
|
||||
|
||||
private:
|
||||
TutorialManager() = delete;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <set>
|
||||
#include <span>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
@@ -49,9 +50,15 @@ namespace hex::dp {
|
||||
virtual void store(nlohmann::json &j) const { std::ignore = j; }
|
||||
virtual void load(const nlohmann::json &j) { std::ignore = j; }
|
||||
|
||||
struct NodeError {
|
||||
struct NodeError: public std::exception {
|
||||
Node *node;
|
||||
std::string message;
|
||||
|
||||
NodeError(Node *node, std::string message) : node(node), message(std::move(message)) {}
|
||||
|
||||
[[nodiscard]] const char* what() const noexcept override {
|
||||
return this->message.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
void resetOutputData() {
|
||||
@@ -102,7 +109,7 @@ namespace hex::dp {
|
||||
void unmarkInputProcessed(u32 index);
|
||||
|
||||
protected:
|
||||
[[noreturn]] void throwNodeError(const std::string &message);
|
||||
[[noreturn]] void throwNodeError(const std::string &msg);
|
||||
|
||||
void setOverlayData(u64 address, const std::vector<u8> &data);
|
||||
void setAttributes(std::vector<Attribute> attributes);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/imhex_api/system.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -9,6 +10,9 @@ namespace hex {
|
||||
class AutoResetBase {
|
||||
public:
|
||||
virtual ~AutoResetBase() = default;
|
||||
|
||||
private:
|
||||
friend void ImHexApi::System::impl::cleanup();
|
||||
virtual void reset() = 0;
|
||||
};
|
||||
|
||||
@@ -19,16 +23,20 @@ namespace hex {
|
||||
public:
|
||||
using Type = T;
|
||||
|
||||
AutoReset() {
|
||||
ImHexApi::System::impl::addAutoResetObject(this);
|
||||
AutoReset() noexcept {
|
||||
try {
|
||||
ImHexApi::System::impl::addAutoResetObject(this);
|
||||
} catch (std::exception &e) {
|
||||
log::error("Failed to register AutoReset object: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
AutoReset(const T &value) : AutoReset() {
|
||||
explicit(false) AutoReset(const T &value) : AutoReset() {
|
||||
m_value = value;
|
||||
m_valid = true;
|
||||
}
|
||||
|
||||
AutoReset(T &&value) noexcept : AutoReset() {
|
||||
explicit(false) AutoReset(T &&value) noexcept : AutoReset() {
|
||||
m_value = std::move(value);
|
||||
m_valid = true;
|
||||
}
|
||||
@@ -61,29 +69,27 @@ namespace hex {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
T& operator=(const T &value) {
|
||||
AutoReset& operator=(const T &value) {
|
||||
m_value = value;
|
||||
m_valid = true;
|
||||
return m_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T& operator=(T &&value) noexcept {
|
||||
AutoReset& operator=(T &&value) noexcept {
|
||||
m_value = std::move(value);
|
||||
m_valid = true;
|
||||
return m_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool isValid() const {
|
||||
[[nodiscard]] bool isValid() const {
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
private:
|
||||
friend void ImHexApi::System::impl::cleanup();
|
||||
|
||||
void reset() override {
|
||||
if constexpr (requires { m_value.reset(); }) {
|
||||
if constexpr (requires(T t) { t.reset(); }) {
|
||||
m_value.reset();
|
||||
} else if constexpr (requires { m_value.clear(); }) {
|
||||
} else if constexpr (requires(T t) { t.clear(); }) {
|
||||
m_value.clear();
|
||||
} else if constexpr (std::is_pointer_v<T>) {
|
||||
m_value = nullptr; // cppcheck-suppress nullPointer
|
||||
|
||||
@@ -10,92 +10,19 @@ namespace hex {
|
||||
|
||||
class BinaryPattern {
|
||||
public:
|
||||
BinaryPattern() = default;
|
||||
explicit BinaryPattern(const std::string &pattern);
|
||||
|
||||
[[nodiscard]] bool isValid() const;
|
||||
[[nodiscard]] u64 getSize() const;
|
||||
|
||||
[[nodiscard]] bool matches(const std::vector<u8> &bytes) const;
|
||||
[[nodiscard]] bool matchesByte(u8 byte, u32 offset) const;
|
||||
|
||||
struct Pattern {
|
||||
u8 mask, value;
|
||||
};
|
||||
|
||||
BinaryPattern() = default;
|
||||
explicit BinaryPattern(const std::string &pattern) : m_patterns(parseBinaryPatternString(pattern)) { }
|
||||
|
||||
[[nodiscard]] bool isValid() const { return !m_patterns.empty(); }
|
||||
|
||||
[[nodiscard]] bool matches(const std::vector<u8> &bytes) const {
|
||||
if (bytes.size() < m_patterns.size())
|
||||
return false;
|
||||
|
||||
for (u32 i = 0; i < m_patterns.size(); i++) {
|
||||
if (!this->matchesByte(bytes[i], i))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool matchesByte(u8 byte, u32 offset) const {
|
||||
const auto &pattern = m_patterns[offset];
|
||||
|
||||
return (byte & pattern.mask) == pattern.value;
|
||||
}
|
||||
|
||||
[[nodiscard]] u64 getSize() const {
|
||||
return m_patterns.size();
|
||||
}
|
||||
|
||||
private:
|
||||
static std::vector<Pattern> parseBinaryPatternString(std::string string) {
|
||||
std::vector<Pattern> result;
|
||||
|
||||
if (string.length() < 2)
|
||||
return { };
|
||||
|
||||
bool inString = false;
|
||||
while (string.length() > 0) {
|
||||
Pattern pattern = { 0, 0 };
|
||||
if (string.starts_with("\"")) {
|
||||
inString = !inString;
|
||||
string = string.substr(1);
|
||||
continue;
|
||||
} else if (inString) {
|
||||
pattern = { 0xFF, u8(string.front()) };
|
||||
string = string.substr(1);
|
||||
} else if (string.starts_with("??")) {
|
||||
pattern = { 0x00, 0x00 };
|
||||
string = string.substr(2);
|
||||
} else if ((std::isxdigit(string.front()) || string.front() == '?') && string.length() >= 2) {
|
||||
const auto hex = string.substr(0, 2);
|
||||
|
||||
for (const auto &c : hex) {
|
||||
pattern.mask <<= 4;
|
||||
pattern.value <<= 4;
|
||||
|
||||
if (std::isxdigit(c)) {
|
||||
pattern.mask |= 0x0F;
|
||||
|
||||
if (auto hexValue = hex::hexCharToValue(c); hexValue.has_value())
|
||||
pattern.value |= hexValue.value();
|
||||
else
|
||||
return { };
|
||||
} else if (c != '?') {
|
||||
return { };
|
||||
}
|
||||
}
|
||||
|
||||
string = string.substr(2);
|
||||
} else if (std::isspace(string.front())) {
|
||||
string = string.substr(1);
|
||||
continue;
|
||||
} else {
|
||||
return { };
|
||||
}
|
||||
|
||||
result.push_back(pattern);
|
||||
}
|
||||
|
||||
if (inString)
|
||||
return { };
|
||||
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
std::vector<Pattern> m_patterns;
|
||||
};
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
static_assert(false, "Debug variables are only intended for use during development.");
|
||||
#endif
|
||||
|
||||
namespace hex::trace {
|
||||
struct StackTraceResult;
|
||||
}
|
||||
|
||||
namespace hex::dbg {
|
||||
|
||||
namespace impl {
|
||||
@@ -47,4 +51,6 @@ namespace hex::dbg {
|
||||
bool debugModeEnabled();
|
||||
void setDebugModeEnabled(bool enabled);
|
||||
|
||||
void printStackTrace(const trace::StackTraceResult &stackTrace);
|
||||
|
||||
}
|
||||
@@ -27,10 +27,11 @@ namespace hex {
|
||||
EncodingFile& operator=(const EncodingFile &other);
|
||||
EncodingFile& operator=(EncodingFile &&other) noexcept;
|
||||
|
||||
[[nodiscard]] std::pair<std::string_view, size_t> getEncodingFor(std::span<u8> buffer) const;
|
||||
[[nodiscard]] std::pair<std::string_view, size_t> getEncodingFor(std::span<const u8> buffer) const;
|
||||
[[nodiscard]] u64 getEncodingLengthFor(std::span<u8> buffer) const;
|
||||
[[nodiscard]] u64 getShortestSequence() const { return m_shortestSequence; }
|
||||
[[nodiscard]] u64 getLongestSequence() const { return m_longestSequence; }
|
||||
[[nodiscard]] std::string decodeAll(std::span<const u8> buffer) const;
|
||||
|
||||
[[nodiscard]] bool valid() const { return m_valid; }
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/helpers/literals.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -27,4 +29,14 @@ namespace hex::magic {
|
||||
|
||||
bool isValidMIMEType(const std::string &mimeType);
|
||||
|
||||
struct FoundPattern {
|
||||
std::fs::path patternFilePath;
|
||||
std::string author;
|
||||
std::string description;
|
||||
std::optional<std::string> mimeType;
|
||||
std::optional<u64> magicOffset;
|
||||
};
|
||||
|
||||
std::vector<FoundPattern> findViablePatterns(prv::Provider *provider, Task* task = nullptr);
|
||||
|
||||
}
|
||||
@@ -12,6 +12,9 @@ namespace hex::menu {
|
||||
bool beginMenu(const char *label, bool enabled = true);
|
||||
void endMenu();
|
||||
|
||||
bool beginTaskBarMenu();
|
||||
void endTaskBarMenu();
|
||||
|
||||
bool beginMenuEx(const char* label, const char* icon, bool enabled = true);
|
||||
|
||||
bool menuItem(const char *label, const Shortcut &shortcut = Shortcut::None, bool selected = false, bool enabled = true);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <numbers>
|
||||
#include <array>
|
||||
|
||||
#include <opengl_support.h>
|
||||
#include "imgui.h"
|
||||
@@ -935,7 +936,7 @@ namespace hex::gl {
|
||||
void attachTexture(const Texture &texture) const;
|
||||
|
||||
private:
|
||||
GLuint m_frameBuffer, m_renderBuffer;
|
||||
GLuint m_frameBuffer = 0, m_renderBuffer = 0;
|
||||
};
|
||||
|
||||
class AxesVectors {
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <wolv/utils/charconv.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
#if !defined(HEX_MODULE_EXPORT)
|
||||
@@ -96,6 +98,8 @@ namespace hex {
|
||||
|
||||
void startProgram(const std::vector<std::string> &command);
|
||||
int executeCommand(const std::string &command);
|
||||
std::optional<std::string> executeCommandWithOutput(const std::string &command);
|
||||
void executeCommandDetach(const std::string &command);
|
||||
void openWebpage(std::string url);
|
||||
|
||||
extern "C" void registerFont(const char *fontName, const char *fontPath);
|
||||
@@ -261,7 +265,11 @@ namespace hex {
|
||||
if (!std::isxdigit(byteString[i]) || !std::isxdigit(byteString[i + 1]))
|
||||
return {};
|
||||
|
||||
result.push_back(std::strtoul(byteString.substr(i, 2).c_str(), nullptr, 16));
|
||||
auto value = wolv::util::from_chars<u64>(byteString.substr(i, 2), 16);
|
||||
if (!value.has_value())
|
||||
return {};
|
||||
|
||||
result.push_back(*value);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -362,7 +370,7 @@ namespace hex {
|
||||
|
||||
[[nodiscard]] std::optional<std::string> getEnvironmentVariable(const std::string &env);
|
||||
|
||||
[[nodiscard]] std::string limitStringLength(const std::string &string, size_t maxLength);
|
||||
[[nodiscard]] std::string limitStringLength(const std::string &string, size_t maxLength, bool fromBothEnds = true);
|
||||
|
||||
[[nodiscard]] std::optional<std::fs::path> getInitialFilePath();
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
void macosInstallEventListener();
|
||||
|
||||
void toastMessageMacos(const char *title, const char *message);
|
||||
void macosSetupDockMenu(void);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
15
lib/libimhex/include/hex/mcp/client.hpp
Normal file
15
lib/libimhex/include/hex/mcp/client.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace hex::mcp {
|
||||
|
||||
class Client {
|
||||
public:
|
||||
Client() = default;
|
||||
~Client() = default;
|
||||
|
||||
int run(std::istream &input, std::ostream &output);
|
||||
};
|
||||
|
||||
}
|
||||
123
lib/libimhex/include/hex/mcp/server.hpp
Normal file
123
lib/libimhex/include/hex/mcp/server.hpp
Normal file
@@ -0,0 +1,123 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <wolv/net/socket_server.hpp>
|
||||
|
||||
namespace hex::mcp {
|
||||
|
||||
class JsonRpc {
|
||||
public:
|
||||
explicit JsonRpc(std::string request) : m_request(std::move(request)){ }
|
||||
|
||||
struct MethodNotFoundException : std::exception {};
|
||||
struct InvalidParametersException : std::exception {};
|
||||
|
||||
enum class ErrorCode: i16 {
|
||||
ParseError = -32700,
|
||||
InvalidRequest = -32600,
|
||||
MethodNotFound = -32601,
|
||||
InvalidParams = -32602,
|
||||
InternalError = -32603,
|
||||
};
|
||||
|
||||
using Callback = std::function<nlohmann::json(const std::string &method, const nlohmann::json ¶ms)>;
|
||||
std::optional<std::string> execute(const Callback &callback);
|
||||
void setError(ErrorCode code, std::string message);
|
||||
|
||||
private:
|
||||
std::optional<nlohmann::json> handleMessage(const nlohmann::json &request, const Callback &callback);
|
||||
std::optional<nlohmann::json> handleBatchedMessages(const nlohmann::json &request, const Callback &callback);
|
||||
|
||||
nlohmann::json createDefaultMessage();
|
||||
nlohmann::json createErrorMessage(ErrorCode code, const std::string &message);
|
||||
nlohmann::json createResponseMessage(const nlohmann::json &result);
|
||||
|
||||
private:
|
||||
std::string m_request;
|
||||
std::optional<int> m_id;
|
||||
|
||||
struct Error {
|
||||
ErrorCode code;
|
||||
std::string message;
|
||||
};
|
||||
std::optional<Error> m_error;
|
||||
};
|
||||
|
||||
struct TextContent {
|
||||
std::string text;
|
||||
|
||||
operator nlohmann::json() const {
|
||||
nlohmann::json result;
|
||||
result["content"] = nlohmann::json::array({
|
||||
nlohmann::json::object({
|
||||
{ "type", "text" },
|
||||
{ "text", text }
|
||||
})
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
struct StructuredContent {
|
||||
std::string text;
|
||||
nlohmann::json data;
|
||||
|
||||
operator nlohmann::json() const {
|
||||
nlohmann::json result;
|
||||
result["content"] = nlohmann::json::array({
|
||||
nlohmann::json::object({
|
||||
{ "type", "text" },
|
||||
{ "text", text }
|
||||
})
|
||||
});
|
||||
result["structuredContent"] = data;
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
class Server {
|
||||
public:
|
||||
constexpr static auto McpInternalPort = 19743;
|
||||
|
||||
Server();
|
||||
~Server();
|
||||
|
||||
void listen();
|
||||
void shutdown();
|
||||
void disconnect();
|
||||
bool isConnected();
|
||||
|
||||
void addPrimitive(std::string type, std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json ¶ms)> function);
|
||||
|
||||
struct ClientInfo {
|
||||
std::string name;
|
||||
std::string version;
|
||||
std::string protocolVersion;
|
||||
};
|
||||
|
||||
const ClientInfo& getClientInfo() const {
|
||||
return m_clientInfo;
|
||||
}
|
||||
|
||||
private:
|
||||
nlohmann::json handleInitialize(const nlohmann::json ¶ms);
|
||||
void handleNotifications(const std::string &method, const nlohmann::json ¶ms);
|
||||
|
||||
struct Primitive {
|
||||
nlohmann::json capabilities;
|
||||
std::function<nlohmann::json(const nlohmann::json ¶ms)> function;
|
||||
};
|
||||
|
||||
std::map<std::string, std::map<std::string, Primitive>> m_primitives;
|
||||
|
||||
wolv::net::SocketServer m_server;
|
||||
bool m_connected = false;
|
||||
ClientInfo m_clientInfo;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -46,7 +46,7 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
|
||||
|
||||
[[maybe_unused]] static auto& getFeaturesImpl() {
|
||||
static hex::AutoReset<std::vector<hex::Feature>> features;
|
||||
return features;
|
||||
return *features;
|
||||
}
|
||||
|
||||
#if defined (IMHEX_STATIC_LINK_PLUGINS)
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace hex::prv {
|
||||
CachedProvider(size_t cacheBlockSize = 4096, size_t maxBlocks = 1024);
|
||||
~CachedProvider() override;
|
||||
|
||||
bool open() override;
|
||||
OpenResult open() override;
|
||||
void close() override;
|
||||
|
||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace hex::prv {
|
||||
[[nodiscard]] bool isSavable() const override { return m_name.empty(); }
|
||||
[[nodiscard]] bool isSavableAsRecent() const override { return false; }
|
||||
|
||||
[[nodiscard]] bool open() override;
|
||||
[[nodiscard]] OpenResult open() override;
|
||||
void close() override { }
|
||||
|
||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||
|
||||
@@ -72,6 +72,21 @@ namespace hex::prv {
|
||||
[[nodiscard]] virtual std::vector<Description> getDataDescription() const = 0;
|
||||
};
|
||||
|
||||
class IProviderDataBackupable {
|
||||
public:
|
||||
explicit IProviderDataBackupable(Provider *provider);
|
||||
virtual ~IProviderDataBackupable() = default;
|
||||
|
||||
void createBackupIfNeeded(const std::fs::path &inputFilePath);
|
||||
private:
|
||||
Provider *m_provider = nullptr;
|
||||
bool m_backupCreated = false;
|
||||
|
||||
bool m_shouldCreateBackups = true;
|
||||
u64 m_maxSize;
|
||||
std::string m_backupExtension;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represent the data source for a tab in the UI
|
||||
*/
|
||||
@@ -79,6 +94,65 @@ namespace hex::prv {
|
||||
public:
|
||||
constexpr static u64 MaxPageSize = 0xFFFF'FFFF'FFFF'FFFF;
|
||||
|
||||
class OpenResult {
|
||||
public:
|
||||
OpenResult() : m_result(std::monostate{}) {}
|
||||
|
||||
[[nodiscard]] static OpenResult failure(std::string errorMessage) {
|
||||
OpenResult result;
|
||||
result.m_result = std::move(errorMessage);
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] static OpenResult warning(std::string warningMessage) {
|
||||
OpenResult result;
|
||||
result.m_result = std::move(warningMessage);
|
||||
result.m_warning = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] static OpenResult redirect(Provider *provider) {
|
||||
OpenResult result;
|
||||
result.m_result = provider;
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isSuccess() const {
|
||||
return std::holds_alternative<std::monostate>(m_result);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isFailure() const {
|
||||
return std::holds_alternative<std::string>(m_result) && !m_warning;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isWarning() const {
|
||||
return std::holds_alternative<std::string>(m_result) && m_warning;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isRedirecting() const {
|
||||
return std::holds_alternative<Provider*>(m_result);
|
||||
}
|
||||
|
||||
[[nodiscard]] Provider* getRedirectProvider() const {
|
||||
if (std::holds_alternative<Provider*>(m_result)) {
|
||||
return std::get<Provider*>(m_result);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string_view getErrorMessage() const {
|
||||
if (std::holds_alternative<std::string>(m_result)) {
|
||||
return std::get<std::string>(m_result);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private:
|
||||
std::variant<std::monostate, std::string, Provider*> m_result;
|
||||
bool m_warning = false;
|
||||
};
|
||||
|
||||
Provider();
|
||||
virtual ~Provider();
|
||||
Provider(const Provider&) = delete;
|
||||
@@ -94,7 +168,7 @@ namespace hex::prv {
|
||||
* @note This is not related to the EventProviderOpened event
|
||||
* @return true if the provider was opened successfully, else false
|
||||
*/
|
||||
[[nodiscard]] virtual bool open() = 0;
|
||||
[[nodiscard]] virtual OpenResult open() = 0;
|
||||
|
||||
/**
|
||||
* @brief Closes this provider
|
||||
@@ -262,9 +336,6 @@ namespace hex::prv {
|
||||
void skipLoadInterface() { m_skipLoadInterface = true; }
|
||||
[[nodiscard]] bool shouldSkipLoadInterface() const { return m_skipLoadInterface; }
|
||||
|
||||
void setErrorMessage(const std::string &errorMessage) { m_errorMessage = errorMessage; }
|
||||
[[nodiscard]] const std::string& getErrorMessage() const { return m_errorMessage; }
|
||||
|
||||
template<std::derived_from<undo::Operation> T>
|
||||
bool addUndoableOperation(auto && ... args) {
|
||||
return m_undoRedoStack.add<T>(std::forward<decltype(args)...>(args)...);
|
||||
@@ -296,8 +367,6 @@ namespace hex::prv {
|
||||
*/
|
||||
bool m_skipLoadInterface = false;
|
||||
|
||||
std::string m_errorMessage = "Unspecified error";
|
||||
|
||||
u64 m_pageSize = MaxPageSize;
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace hex::prv {
|
||||
@@ -40,6 +41,8 @@ namespace hex::prv::undo {
|
||||
|
||||
bool add(std::unique_ptr<Operation> &&operation);
|
||||
|
||||
static std::recursive_mutex& getMutex();
|
||||
|
||||
const std::vector<std::unique_ptr<Operation>> &getAppliedOperations() const {
|
||||
return m_undoStack;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace hex::test {
|
||||
|
||||
[[nodiscard]] UnlocalizedString getTypeName() const override { return "hex.test.provider.test"; }
|
||||
|
||||
bool open() override { return true; }
|
||||
OpenResult open() override { return {}; }
|
||||
void close() override { }
|
||||
|
||||
nlohmann::json storeSettings(nlohmann::json) const override { return {}; }
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/concepts.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/scaling.hpp>
|
||||
|
||||
#include <wolv/utils/string.hpp>
|
||||
|
||||
@@ -133,8 +134,8 @@ namespace ImGuiExt {
|
||||
bool IconHyperlink(const char *icon, const char *label, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||
bool Hyperlink(const char *label, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||
bool BulletHyperlink(const char *label, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||
bool DescriptionButton(const char *label, const char *description, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||
bool DescriptionButtonProgress(const char *label, const char *description, float fraction, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||
bool DescriptionButton(const char *label, const char *description, const char *icon, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||
bool DescriptionButtonProgress(const char *label, const char *description, const char *icon, float fraction, const ImVec2 &size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||
|
||||
void HelpHover(const char *text, const char *icon = "(?)", ImU32 iconColor = ImGui::GetColorU32(ImGuiCol_ButtonActive));
|
||||
|
||||
@@ -253,11 +254,12 @@ namespace ImGuiExt {
|
||||
}
|
||||
|
||||
void TextFormattedWrappedSelectable(std::string_view fmt, auto &&...args) {
|
||||
using namespace hex;
|
||||
// Manually wrap text, using the letter M (generally the widest character in non-monospaced fonts) to calculate the character width to use.
|
||||
auto text = wolv::util::trim(wolv::util::wrapMonospacedString(
|
||||
fmt::format(fmt::runtime(fmt), std::forward<decltype(args)>(args)...),
|
||||
ImGui::CalcTextSize("M").x,
|
||||
ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize - ImGui::GetStyle().FrameBorderSize
|
||||
std::max(100_scaled, ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize - ImGui::GetStyle().FrameBorderSize)
|
||||
));
|
||||
|
||||
auto textSize = ImGui::CalcTextSize(text.c_str());
|
||||
@@ -268,7 +270,7 @@ namespace ImGuiExt {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0F);
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4());
|
||||
|
||||
ImGui::PushItemWidth(ImGui::CalcTextSize(text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2);
|
||||
ImGui::PushItemWidth(textSize.x + ImGui::GetStyle().FramePadding.x * 2);
|
||||
ImGui::InputTextMultiline(
|
||||
"##",
|
||||
const_cast<char *>(text.c_str()),
|
||||
@@ -312,11 +314,12 @@ namespace ImGuiExt {
|
||||
|
||||
bool BitCheckbox(const char* label, bool* v);
|
||||
|
||||
bool DimmedButton(const char* label, ImVec2 size = ImVec2(0, 0));
|
||||
bool DimmedButton(const char* label, ImVec2 size = ImVec2(0, 0), ImGuiButtonFlags flags = ImGuiButtonFlags_None);
|
||||
bool DimmedIconButton(const char *symbol, ImVec4 color, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
|
||||
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
|
||||
bool DimmedIconToggle(const char *icon, bool *v);
|
||||
bool DimmedIconToggle(const char *iconOn, const char *iconOff, bool *v);
|
||||
bool DimmedArrowButton(const char *id, ImGuiDir dir, ImVec2 size = ImVec2(ImGui::GetFrameHeight(), ImGui::GetFrameHeight()));
|
||||
|
||||
void TextOverlay(const char *text, ImVec2 pos, float maxWidth = -1);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <hex/api/task_manager.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -51,11 +52,11 @@ namespace hex {
|
||||
|
||||
template<typename ...Args>
|
||||
static void open(Args && ... args) {
|
||||
std::lock_guard lock(getMutex());
|
||||
|
||||
auto toast = std::make_unique<T>(std::forward<Args>(args)...);
|
||||
getQueuedToasts().emplace_back(std::move(toast));
|
||||
TaskManager::doLater([=] {
|
||||
auto toast = std::make_unique<T>(args...);
|
||||
getQueuedToasts().emplace_back(std::move(toast));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace hex {
|
||||
* @brief Draws the view
|
||||
* @note Do not override this method. Override drawContent() instead
|
||||
*/
|
||||
virtual void draw() = 0;
|
||||
virtual void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) = 0;
|
||||
|
||||
/**
|
||||
* @brief Draws the content of the view
|
||||
@@ -82,10 +82,12 @@ namespace hex {
|
||||
*/
|
||||
[[nodiscard]] virtual View* getMenuItemInheritView() const { return nullptr; }
|
||||
|
||||
|
||||
[[nodiscard]] const char *getIcon() const { return m_icon; }
|
||||
[[nodiscard]] const UnlocalizedString& getUnlocalizedName() const;
|
||||
[[nodiscard]] std::string getName() const;
|
||||
|
||||
[[nodiscard]] virtual bool shouldDefaultFocus() const { return false; }
|
||||
[[nodiscard]] virtual bool shouldStoreWindowState() const { return true; }
|
||||
|
||||
[[nodiscard]] bool &getWindowOpenState();
|
||||
@@ -108,10 +110,22 @@ namespace hex {
|
||||
void trackViewState();
|
||||
void setFocused(bool focused);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Called when this view is opened (i.e. made visible).
|
||||
*/
|
||||
virtual void onOpen() {}
|
||||
|
||||
/**
|
||||
* @brief Called when this view is closed (i.e. made invisible).
|
||||
*/
|
||||
virtual void onClose() {}
|
||||
|
||||
public:
|
||||
class Window;
|
||||
class Special;
|
||||
class Floating;
|
||||
class Scrolling;
|
||||
class Modal;
|
||||
class FullScreen;
|
||||
|
||||
@@ -133,17 +147,24 @@ namespace hex {
|
||||
class View::Window : public View {
|
||||
public:
|
||||
explicit Window(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon) {}
|
||||
[[nodiscard]] ImGuiWindow *getFocusedSubWindow() const { return m_focusedSubWindow; }
|
||||
|
||||
void draw() final {
|
||||
if (this->shouldDraw()) {
|
||||
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
||||
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
|
||||
if (ImGui::Begin(title.c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse | this->getWindowFlags())) {
|
||||
this->drawContent();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
/**
|
||||
* @brief Draws help text for the view
|
||||
*/
|
||||
virtual void drawHelpText() = 0;
|
||||
|
||||
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) override;
|
||||
|
||||
[[nodiscard]] virtual bool allowScroll() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
void handleFocusRestoration();
|
||||
|
||||
private:
|
||||
ImGuiWindow *m_focusedSubWindow{nullptr};
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -154,12 +175,7 @@ namespace hex {
|
||||
public:
|
||||
explicit Special(UnlocalizedString unlocalizedName) : View(std::move(unlocalizedName), "") {}
|
||||
|
||||
void draw() final {
|
||||
if (this->shouldDraw()) {
|
||||
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
||||
this->drawContent();
|
||||
}
|
||||
}
|
||||
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -169,10 +185,25 @@ namespace hex {
|
||||
public:
|
||||
explicit Floating(UnlocalizedString unlocalizedName, const char *icon) : Window(std::move(unlocalizedName), icon) {}
|
||||
|
||||
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override { return ImGuiWindowFlags_NoDocking; }
|
||||
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||
|
||||
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A view that draws all its content at once without any scrolling being done by the window itself
|
||||
*/
|
||||
class View::Scrolling : public View::Window {
|
||||
public:
|
||||
explicit Scrolling(UnlocalizedString unlocalizedName, const char *icon) : Window(std::move(unlocalizedName), icon) {}
|
||||
|
||||
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||
|
||||
[[nodiscard]] bool allowScroll() const final {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A view that draws a modal window. The window will always be drawn on top and will block input to other windows
|
||||
*/
|
||||
@@ -180,24 +211,7 @@ namespace hex {
|
||||
public:
|
||||
explicit Modal(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon) {}
|
||||
|
||||
void draw() final {
|
||||
if (this->shouldDraw()) {
|
||||
if (this->getWindowOpenState())
|
||||
ImGui::OpenPopup(View::toWindowName(this->getUnlocalizedName()).c_str());
|
||||
|
||||
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
|
||||
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
||||
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
|
||||
if (ImGui::BeginPopupModal(title.c_str(), this->hasCloseButton() ? &this->getWindowOpenState() : nullptr, ImGuiWindowFlags_NoCollapse | this->getWindowFlags())) {
|
||||
this->drawContent();
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Escape))
|
||||
this->getWindowOpenState() = false;
|
||||
}
|
||||
}
|
||||
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||
|
||||
[[nodiscard]] virtual bool hasCloseButton() const { return true; }
|
||||
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
|
||||
@@ -207,10 +221,7 @@ namespace hex {
|
||||
public:
|
||||
explicit FullScreen() : View("FullScreen", "") {}
|
||||
|
||||
void draw() final {
|
||||
this->drawContent();
|
||||
this->drawAlwaysVisibleContent();
|
||||
}
|
||||
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,8 +264,7 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
if (json.empty())
|
||||
return;
|
||||
if (json.empty()) return;
|
||||
|
||||
#if defined(OS_WEB)
|
||||
auto data = json.dump();
|
||||
|
||||
@@ -594,6 +594,12 @@ namespace hex {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Spacer::draw(const std::string& name) {
|
||||
std::ignore = name;
|
||||
ImGui::NewLine();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -624,22 +630,22 @@ namespace hex {
|
||||
void add(Type type, const std::string &command, const UnlocalizedString &unlocalizedDescription, const impl::DisplayCallback &displayCallback, const impl::ExecuteCallback &executeCallback) {
|
||||
log::debug("Registered new command palette command: {}", command);
|
||||
|
||||
impl::s_entries->push_back(impl::Entry { type, command, unlocalizedDescription, displayCallback, executeCallback });
|
||||
impl::s_entries->push_back(impl::Entry { .type=type, .command=command, .unlocalizedDescription=unlocalizedDescription, .displayCallback=displayCallback, .executeCallback=executeCallback });
|
||||
}
|
||||
|
||||
void addHandler(Type type, const std::string &command, const impl::QueryCallback &queryCallback, const impl::DisplayCallback &displayCallback) {
|
||||
log::debug("Registered new command palette command handler: {}", command);
|
||||
|
||||
impl::s_handlers->push_back(impl::Handler { type, command, queryCallback, displayCallback });
|
||||
impl::s_handlers->push_back(impl::Handler { .type=type, .command=command, .queryCallback=queryCallback, .displayCallback=displayCallback });
|
||||
}
|
||||
|
||||
void setDisplayedContent(const impl::ContentDisplayCallback &displayCallback) {
|
||||
impl::s_displayedContent = impl::ContentDisplay { true, displayCallback };
|
||||
impl::s_displayedContent = impl::ContentDisplay { .showSearchBox=true, .callback=displayCallback };
|
||||
}
|
||||
|
||||
void openWithContent(const impl::ContentDisplayCallback &displayCallback) {
|
||||
RequestOpenCommandPalette::post();
|
||||
impl::s_displayedContent = impl::ContentDisplay { false, displayCallback };
|
||||
impl::s_displayedContent = impl::ContentDisplay { .showSearchBox=false, .callback=displayCallback };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -777,12 +783,12 @@ namespace hex {
|
||||
|
||||
void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount) {
|
||||
log::debug("Registered new pattern visualizer function: {}", name);
|
||||
(*impl::s_visualizers)[name] = impl::Visualizer { parameterCount, function };
|
||||
(*impl::s_visualizers)[name] = impl::Visualizer { .parameterCount=parameterCount, .callback=function };
|
||||
}
|
||||
|
||||
void addInlineVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount) {
|
||||
log::debug("Registered new inline pattern visualizer function: {}", name);
|
||||
(*impl::s_inlineVisualizers)[name] = impl::Visualizer { parameterCount, function };
|
||||
(*impl::s_inlineVisualizers)[name] = impl::Visualizer { .parameterCount=parameterCount, .callback=function };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -848,7 +854,7 @@ namespace hex {
|
||||
void add(const UnlocalizedString &unlocalizedName, const char *icon, const impl::Callback &function) {
|
||||
log::debug("Registered new tool: {}", unlocalizedName.get());
|
||||
|
||||
impl::s_tools->emplace_back(impl::Entry { unlocalizedName, icon, function });
|
||||
impl::s_tools->emplace_back(impl::Entry { .unlocalizedName=unlocalizedName, .icon=icon, .function=function });
|
||||
}
|
||||
|
||||
}
|
||||
@@ -864,6 +870,18 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace EditWidget {
|
||||
std::optional<std::vector<u8>> TextInput::draw(std::string &value, std::endian endian) {
|
||||
if (ImGui::InputText("##InspectorLineEditing", value,
|
||||
ImGuiInputTextFlags_EnterReturnsTrue |
|
||||
ImGuiInputTextFlags_AutoSelectAll)) {
|
||||
return getBytes(value, endian);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
void add(const UnlocalizedString &unlocalizedName, size_t requiredSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction) {
|
||||
log::debug("Registered new data inspector format: {}", unlocalizedName.get());
|
||||
|
||||
@@ -991,7 +1009,7 @@ namespace hex {
|
||||
coloredIcon.color = ImGuiCustomCol_ToolbarGray;
|
||||
|
||||
impl::s_menuItems->insert({
|
||||
priority, impl::MenuItem { unlocalizedMainMenuNames, coloredIcon, shortcut, view, function, enabledCallback, selectedCallback, -1 }
|
||||
priority, impl::MenuItem { .unlocalizedNames=unlocalizedMainMenuNames, .icon=coloredIcon, .shortcut=shortcut, .view=view, .callback=function, .enabledCallback=enabledCallback, .selectedCallback=selectedCallback, .toolbarIndex=-1 }
|
||||
});
|
||||
|
||||
if (shortcut != Shortcut::None) {
|
||||
@@ -1006,23 +1024,32 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
void addMenuItemSubMenu(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback, View *view) {
|
||||
addMenuItemSubMenu(std::move(unlocalizedMainMenuNames), "", priority, function, enabledCallback, view);
|
||||
void addMenuItemSubMenu(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback, View *view, bool showOnWelcomeScreen) {
|
||||
addMenuItemSubMenu(std::move(unlocalizedMainMenuNames), "", priority, function, enabledCallback, view, showOnWelcomeScreen);
|
||||
}
|
||||
|
||||
void addMenuItemSubMenu(std::vector<UnlocalizedString> unlocalizedMainMenuNames, const char *icon, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback, View *view) {
|
||||
void addMenuItemSubMenu(std::vector<UnlocalizedString> unlocalizedMainMenuNames, const char *icon, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback, View *view, bool showOnWelcomeScreen) {
|
||||
log::debug("Added new menu item sub menu to menu {} with priority {}", unlocalizedMainMenuNames[0].get(), priority);
|
||||
|
||||
unlocalizedMainMenuNames.emplace_back(impl::SubMenuValue);
|
||||
impl::s_menuItems->insert({
|
||||
priority, impl::MenuItem { unlocalizedMainMenuNames, icon, Shortcut::None, view, function, enabledCallback, []{ return false; }, -1 }
|
||||
priority, impl::MenuItem { .unlocalizedNames=unlocalizedMainMenuNames, .icon=icon, .shortcut=showOnWelcomeScreen ? Shortcut({ ShowOnWelcomeScreen }) : Shortcut::None, .view=view, .callback=function, .enabledCallback=enabledCallback, .selectedCallback=[]{ return false; }, .toolbarIndex=-1 }
|
||||
});
|
||||
}
|
||||
|
||||
void addMenuItemSeparator(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, View *view) {
|
||||
unlocalizedMainMenuNames.emplace_back(impl::SeparatorValue);
|
||||
impl::s_menuItems->insert({
|
||||
priority, impl::MenuItem { unlocalizedMainMenuNames, "", Shortcut::None, view, []{}, []{ return true; }, []{ return false; }, -1 }
|
||||
priority, impl::MenuItem { .unlocalizedNames=unlocalizedMainMenuNames, .icon="", .shortcut=Shortcut::None, .view=view, .callback=[]{}, .enabledCallback=[]{ return true; }, .selectedCallback=[]{ return false; }, .toolbarIndex=-1 }
|
||||
});
|
||||
}
|
||||
|
||||
void addTaskBarMenuItem(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback) {
|
||||
log::debug("Added new taskbar menu item to menu {} ", unlocalizedMainMenuNames[0].get());
|
||||
|
||||
unlocalizedMainMenuNames.insert(unlocalizedMainMenuNames.begin(), impl::TaskBarMenuValue);
|
||||
impl::s_menuItems->insert({
|
||||
priority, impl::MenuItem { .unlocalizedNames=unlocalizedMainMenuNames, .icon="", .shortcut=Shortcut::None, .view=nullptr, .callback=function, .enabledCallback=enabledCallback, .selectedCallback=[]{ return false; }, .toolbarIndex=-1 }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1038,13 +1065,13 @@ namespace hex {
|
||||
impl::s_toolbarItems->push_back(function);
|
||||
}
|
||||
|
||||
void addMenuItemToToolbar(const UnlocalizedString& unlocalizedName, ImGuiCustomCol color) {
|
||||
void addMenuItemToToolbar(const std::vector<UnlocalizedString>& unlocalizedNames, ImGuiCustomCol color) {
|
||||
const auto maxIndex = std::ranges::max_element(impl::getMenuItems(), [](const auto &a, const auto &b) {
|
||||
return a.second.toolbarIndex < b.second.toolbarIndex;
|
||||
})->second.toolbarIndex;
|
||||
|
||||
for (auto &[priority, menuItem] : *impl::s_menuItems) {
|
||||
if (menuItem.unlocalizedNames.back() == unlocalizedName) {
|
||||
if (menuItem.unlocalizedNames == unlocalizedNames) {
|
||||
menuItem.toolbarIndex = maxIndex + 1;
|
||||
menuItem.icon.color = color;
|
||||
updateToolbarItems();
|
||||
@@ -1096,18 +1123,18 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::Provider {
|
||||
|
||||
|
||||
namespace impl {
|
||||
namespace ContentRegistry::Provider::impl {
|
||||
|
||||
void add(const std::string &typeName, ProviderCreationFunction creationFunction) {
|
||||
(void)RequestCreateProvider::subscribe([expectedName = typeName, creationFunction](const std::string &name, bool skipLoadInterface, bool selectProvider, prv::Provider **provider) {
|
||||
(void)RequestCreateProvider::subscribe([expectedName = typeName, creationFunction](const std::string &name, bool skipLoadInterface, bool selectProvider, std::shared_ptr<prv::Provider> *provider) {
|
||||
if (name != expectedName) return;
|
||||
|
||||
auto newProvider = creationFunction();
|
||||
|
||||
if (provider != nullptr) {
|
||||
*provider = newProvider.get();
|
||||
*provider = newProvider;
|
||||
ImHexApi::Provider::add(std::move(newProvider), skipLoadInterface, selectProvider);
|
||||
}
|
||||
});
|
||||
@@ -1127,7 +1154,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace ContentRegistry::DataFormatter {
|
||||
|
||||
@@ -1283,47 +1310,42 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::Diffing {
|
||||
|
||||
namespace impl {
|
||||
namespace ContentRegistry::Diffing::impl {
|
||||
|
||||
static AutoReset<std::vector<std::unique_ptr<Algorithm>>> s_algorithms;
|
||||
const std::vector<std::unique_ptr<Algorithm>>& getAlgorithms() {
|
||||
return *s_algorithms;
|
||||
}
|
||||
|
||||
void addAlgorithm(std::unique_ptr<Algorithm> &&hash) {
|
||||
s_algorithms->emplace_back(std::move(hash));
|
||||
}
|
||||
static AutoReset<std::vector<std::unique_ptr<Algorithm>>> s_algorithms;
|
||||
const std::vector<std::unique_ptr<Algorithm>>& getAlgorithms() {
|
||||
return *s_algorithms;
|
||||
}
|
||||
|
||||
void addAlgorithm(std::unique_ptr<Algorithm> &&hash) {
|
||||
s_algorithms->emplace_back(std::move(hash));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::Hashes {
|
||||
|
||||
namespace impl {
|
||||
namespace ContentRegistry::Hashes::impl {
|
||||
|
||||
static AutoReset<std::vector<std::unique_ptr<Hash>>> s_hashes;
|
||||
const std::vector<std::unique_ptr<Hash>>& getHashes() {
|
||||
return *s_hashes;
|
||||
}
|
||||
|
||||
void add(std::unique_ptr<Hash> &&hash) {
|
||||
s_hashes->emplace_back(std::move(hash));
|
||||
}
|
||||
static AutoReset<std::vector<std::unique_ptr<Hash>>> s_hashes;
|
||||
const std::vector<std::unique_ptr<Hash>>& getHashes() {
|
||||
return *s_hashes;
|
||||
}
|
||||
|
||||
void add(std::unique_ptr<Hash> &&hash) {
|
||||
s_hashes->emplace_back(std::move(hash));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace ContentRegistry::BackgroundServices {
|
||||
|
||||
namespace impl {
|
||||
|
||||
class Service {
|
||||
public:
|
||||
Service(const UnlocalizedString &unlocalizedName, std::jthread thread) : m_unlocalizedName(std::move(unlocalizedName)), m_thread(std::move(thread)) { }
|
||||
Service(UnlocalizedString unlocalizedName, std::jthread thread) : m_unlocalizedName(std::move(unlocalizedName)), m_thread(std::move(thread)) { }
|
||||
Service(const Service&) = delete;
|
||||
Service(Service &&) = default;
|
||||
~Service() {
|
||||
@@ -1395,6 +1417,40 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::MCP {
|
||||
|
||||
namespace impl {
|
||||
|
||||
std::unique_ptr<mcp::Server>& getMcpServerInstance() {
|
||||
static std::unique_ptr<mcp::Server> server;
|
||||
|
||||
if (server == nullptr)
|
||||
server = std::make_unique<mcp::Server>();
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
static bool s_mcpEnabled = false;
|
||||
void setEnabled(bool enabled) {
|
||||
s_mcpEnabled = enabled;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool isEnabled() {
|
||||
return impl::s_mcpEnabled;
|
||||
}
|
||||
|
||||
bool isConnected() {
|
||||
return impl::getMcpServerInstance()->isConnected();
|
||||
}
|
||||
|
||||
void registerTool(std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json ¶ms)> function) {
|
||||
impl::getMcpServerInstance()->addPrimitive("tools", capabilities, function);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::Experiments {
|
||||
|
||||
namespace impl {
|
||||
@@ -1488,22 +1544,19 @@ namespace hex {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace ContentRegistry::Disassemblers {
|
||||
namespace ContentRegistry::Disassemblers::impl {
|
||||
|
||||
namespace impl {
|
||||
static AutoReset<std::map<std::string, impl::CreatorFunction>> s_architectures;
|
||||
|
||||
static AutoReset<std::map<std::string, impl::CreatorFunction>> s_architectures;
|
||||
|
||||
void addArchitectureCreator(impl::CreatorFunction function) {
|
||||
const auto arch = function();
|
||||
(*s_architectures)[arch->getName()] = std::move(function);
|
||||
}
|
||||
|
||||
const std::map<std::string, impl::CreatorFunction>& getArchitectures() {
|
||||
return *s_architectures;
|
||||
}
|
||||
void addArchitectureCreator(impl::CreatorFunction function) {
|
||||
const auto arch = function();
|
||||
(*s_architectures)[arch->getName()] = std::move(function);
|
||||
}
|
||||
|
||||
const std::map<std::string, impl::CreatorFunction>& getArchitectures() {
|
||||
return *s_architectures;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <algorithm>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
namespace hex {
|
||||
@@ -35,7 +36,7 @@ namespace hex {
|
||||
|
||||
void EventManager::unsubscribe(void *token, impl::EventId id) {
|
||||
auto &tokenStore = getTokenStore();
|
||||
auto iter = std::find_if(tokenStore.begin(), tokenStore.end(), [&](auto &item) {
|
||||
auto iter = std::ranges::find_if(tokenStore, [&](auto &item) {
|
||||
return item.first == token && item.second->first == id;
|
||||
});
|
||||
|
||||
|
||||
@@ -47,6 +47,10 @@
|
||||
|
||||
#if defined(OS_WEB)
|
||||
#include <emscripten.h>
|
||||
#elif defined(OS_MACOS)
|
||||
extern "C" {
|
||||
void macosRegisterFont(const unsigned char *data, size_t size);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace hex {
|
||||
@@ -257,7 +261,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
void setSelection(u64 address, size_t size, prv::Provider *provider) {
|
||||
setSelection({ { address, size }, provider == nullptr ? Provider::get() : provider });
|
||||
setSelection({ { .address=address, .size=size }, provider == nullptr ? Provider::get() : provider });
|
||||
}
|
||||
|
||||
void addVirtualFile(const std::string &path, std::vector<u8> data, Region region) {
|
||||
@@ -281,7 +285,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
u64 add(u64 address, size_t size, const std::string &name, const std::string &comment, u32 color) {
|
||||
return add(Region { address, size }, name, comment, color);
|
||||
return add(Region { .address=address, .size=size }, name, comment, color);
|
||||
}
|
||||
|
||||
void remove(u64 id) {
|
||||
@@ -294,8 +298,8 @@ namespace hex {
|
||||
namespace ImHexApi::Provider {
|
||||
|
||||
static i64 s_currentProvider = -1;
|
||||
static AutoReset<std::vector<std::unique_ptr<prv::Provider>>> s_providers;
|
||||
static AutoReset<std::map<prv::Provider*, std::unique_ptr<prv::Provider>>> s_providersToRemove;
|
||||
static AutoReset<std::vector<std::shared_ptr<prv::Provider>>> s_providers;
|
||||
static AutoReset<std::map<prv::Provider*, std::shared_ptr<prv::Provider>>> s_providersToRemove;
|
||||
|
||||
namespace impl {
|
||||
|
||||
@@ -382,7 +386,7 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
void add(std::unique_ptr<prv::Provider> &&provider, bool skipLoadInterface, bool select) {
|
||||
void add(std::shared_ptr<prv::Provider> &&provider, bool skipLoadInterface, bool select) {
|
||||
std::scoped_lock lock(impl::s_providerMutex);
|
||||
|
||||
if (TaskManager::getRunningTaskCount() > 0)
|
||||
@@ -391,7 +395,7 @@ namespace hex {
|
||||
if (skipLoadInterface)
|
||||
provider->skipLoadInterface();
|
||||
|
||||
EventProviderCreated::post(provider.get());
|
||||
EventProviderCreated::post(provider);
|
||||
s_providers->emplace_back(std::move(provider));
|
||||
|
||||
if (select || s_providers->size() == 1)
|
||||
@@ -491,13 +495,17 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
prv::Provider* createProvider(const UnlocalizedString &unlocalizedName, bool skipLoadInterface, bool select) {
|
||||
prv::Provider* result = nullptr;
|
||||
std::shared_ptr<prv::Provider> createProvider(const UnlocalizedString &unlocalizedName, bool skipLoadInterface, bool select) {
|
||||
std::shared_ptr<prv::Provider> result = nullptr;
|
||||
RequestCreateProvider::post(unlocalizedName, skipLoadInterface, select, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void openProvider(std::shared_ptr<prv::Provider> provider) {
|
||||
RequestOpenProvider::post(provider);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ImHexApi::System {
|
||||
@@ -530,6 +538,11 @@ namespace hex {
|
||||
s_mainWindowHandle = window;
|
||||
}
|
||||
|
||||
static bool s_mainWindowFocused = false;
|
||||
void setMainWindowFocusState(bool focused) {
|
||||
s_mainWindowFocused = focused;
|
||||
}
|
||||
|
||||
|
||||
static float s_globalScale = 1.0;
|
||||
void setGlobalScale(float scale) {
|
||||
@@ -667,13 +680,15 @@ namespace hex {
|
||||
if (!sessionType.has_value() || sessionType == "x11")
|
||||
return 1.0F;
|
||||
else {
|
||||
float xScale = 0, yScale = 0;
|
||||
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &xScale, &yScale);
|
||||
int windowW, windowH;
|
||||
int displayW, displayH;
|
||||
glfwGetWindowSize(getMainWindowHandle(), &windowW, &windowH);
|
||||
glfwGetFramebufferSize(getMainWindowHandle(), &displayW, &displayH);
|
||||
|
||||
return std::midpoint(xScale, yScale);
|
||||
return (windowW > 0) ? float(displayW) / windowW : 1.0f;
|
||||
}
|
||||
#elif defined(OS_WEB)
|
||||
return 1.0F;
|
||||
return emscripten_get_device_pixel_ratio();
|
||||
#else
|
||||
return 1.0F;
|
||||
#endif
|
||||
@@ -700,11 +715,15 @@ namespace hex {
|
||||
return impl::s_mainWindowHandle;
|
||||
}
|
||||
|
||||
bool isMainWindowFocused() {
|
||||
return impl::s_mainWindowFocused;
|
||||
}
|
||||
|
||||
bool isBorderlessWindowModeEnabled() {
|
||||
return impl::s_borderlessWindowMode;
|
||||
}
|
||||
|
||||
bool isMutliWindowModeEnabled() {
|
||||
bool isMultiWindowModeEnabled() {
|
||||
return impl::s_multiWindowMode;
|
||||
}
|
||||
|
||||
@@ -896,15 +915,16 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
return { { name, version } };
|
||||
return { { .name=name, .version=version } };
|
||||
}
|
||||
|
||||
SemanticVersion getImHexVersion() {
|
||||
const SemanticVersion& getImHexVersion() {
|
||||
#if defined(IMHEX_VERSION)
|
||||
static auto version = SemanticVersion(IMHEX_VERSION);
|
||||
return version;
|
||||
#else
|
||||
return {};
|
||||
static auto version = SemanticVersion();
|
||||
return version;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -946,7 +966,9 @@ namespace hex {
|
||||
}
|
||||
|
||||
bool isNightlyBuild() {
|
||||
return getImHexVersion().nightly();
|
||||
const static bool isNightly = getImHexVersion().nightly();
|
||||
|
||||
return isNightly;
|
||||
}
|
||||
|
||||
std::optional<std::string> checkForUpdate() {
|
||||
@@ -979,7 +1001,13 @@ namespace hex {
|
||||
|
||||
const auto nightlyUpdateTime = hex::parseTime("%Y-%m-%dT%H:%M:%SZ", firstAsset["updated_at"].get<std::string>());
|
||||
const auto imhexBuildTime = ImHexApi::System::getBuildTime();
|
||||
if (nightlyUpdateTime.has_value() && imhexBuildTime.has_value() && *nightlyUpdateTime > *imhexBuildTime) {
|
||||
|
||||
// Give a bit of time leniency for the update time check
|
||||
// We're comparing here the binary build time to the release upload time. If we were to strictly compare
|
||||
// upload time to be greater than current build time, the check would always be true since the CI
|
||||
// takes a few minutes after the build to actually upload the artifact.
|
||||
// TODO: Is there maybe a better way to handle this without downloading the artifact just to check the build time?
|
||||
if (nightlyUpdateTime.has_value() && imhexBuildTime.has_value() && *nightlyUpdateTime > *imhexBuildTime + std::chrono::hours(1)) {
|
||||
return "Nightly";
|
||||
}
|
||||
} else {
|
||||
@@ -1192,6 +1220,10 @@ namespace hex {
|
||||
offset,
|
||||
fontSizeMultiplier
|
||||
);
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
macosRegisterFont(data.data(), data.size_bytes());
|
||||
#endif
|
||||
}
|
||||
|
||||
void registerFont(const Font& font) {
|
||||
@@ -1203,7 +1235,7 @@ namespace hex {
|
||||
|
||||
if (it == impl::s_fontDefinitions->end()) {
|
||||
const auto defaultFont = ImGui::GetDefaultFont();
|
||||
return { defaultFont, defaultFont, defaultFont };
|
||||
return { .regular=defaultFont, .bold=defaultFont, .italic=defaultFont };
|
||||
} else
|
||||
return it->second;
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
void LayoutManager::lockLayout(bool locked) {
|
||||
log::info("Layout {}", locked ? "locked" : "unlocked");
|
||||
log::debug("Layout {}", locked ? "locked" : "unlocked");
|
||||
s_layoutLocked = locked;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <mutex>
|
||||
#include <hex/helpers/debugging.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -49,9 +50,13 @@ namespace hex {
|
||||
definition.fallbackLanguageId = item["fallback"].get<std::string>();
|
||||
}
|
||||
|
||||
if (item.contains("hidden") && item["hidden"].get<bool>()) {
|
||||
definition.hidden = true;
|
||||
}
|
||||
|
||||
const auto path = item["path"].get<std::string>();
|
||||
|
||||
definition.languageFilePaths.emplace_back(PathEntry{ path, callback });
|
||||
definition.languageFilePaths.emplace_back(PathEntry{ .path=path, .callback=callback });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,9 +104,21 @@ namespace hex {
|
||||
|
||||
for (const auto &entry : json.items()) {
|
||||
auto value = entry.value().get<std::string>();
|
||||
|
||||
// Skip empty values
|
||||
if (value.empty())
|
||||
continue;
|
||||
|
||||
// Handle references to files
|
||||
if (value.starts_with("#@")) {
|
||||
try {
|
||||
value = path.callback(value.substr(2));
|
||||
} catch (std::exception &e) {
|
||||
log::error("Failed to load localization file reference '{}': {}", entry.key(), e.what());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
localizations.try_emplace(LangConst::hash(entry.key()), std::move(value));
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
@@ -138,7 +155,7 @@ namespace hex {
|
||||
static AutoReset<std::unordered_map<std::size_t, std::string>> loadedLocalization;
|
||||
static std::mutex mutex;
|
||||
|
||||
std::lock_guard lock(mutex);
|
||||
std::scoped_lock lock(mutex);
|
||||
if (*currentLanguageId != languageId) {
|
||||
currentLanguageId = languageId;
|
||||
loadedLocalization->clear();
|
||||
@@ -154,16 +171,33 @@ namespace hex {
|
||||
|
||||
const LanguageDefinition& getLanguageDefinition(const LanguageId &languageId) {
|
||||
const auto bestMatch = findBestLanguageMatch(languageId);
|
||||
return (*s_languageDefinitions)[bestMatch];
|
||||
const auto &result = (*s_languageDefinitions)[bestMatch];
|
||||
|
||||
if (!dbg::debugModeEnabled()) {
|
||||
if (result.hidden)
|
||||
return getLanguageDefinition(result.fallbackLanguageId);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Lang::Lang(const char *unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)), m_unlocalizedString(unlocalizedString) { }
|
||||
Lang::Lang(const std::string &unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)), m_unlocalizedString(unlocalizedString) { }
|
||||
Lang::Lang(const LangConst &localizedString) : m_entryHash(localizedString.m_entryHash), m_unlocalizedString(localizedString.m_unlocalizedString) { }
|
||||
Lang::Lang(const UnlocalizedString &unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString.get())), m_unlocalizedString(unlocalizedString.get()) { }
|
||||
Lang::Lang(std::string_view unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)), m_unlocalizedString(unlocalizedString) { }
|
||||
static AutoReset<std::map<std::size_t, std::string>> s_unlocalizedNames;
|
||||
|
||||
Lang::Lang(std::string_view unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)) {
|
||||
if (!s_unlocalizedNames->contains(m_entryHash)) [[unlikely]] {
|
||||
s_unlocalizedNames->emplace(m_entryHash, unlocalizedString);
|
||||
}
|
||||
}
|
||||
Lang::Lang(const char *unlocalizedString) : Lang(std::string_view(unlocalizedString)) { }
|
||||
Lang::Lang(const std::string &unlocalizedString) : Lang(std::string_view(unlocalizedString)) { }
|
||||
Lang::Lang(const LangConst &localizedString) : m_entryHash(localizedString.m_entryHash) {
|
||||
if (!s_unlocalizedNames->contains(m_entryHash)) [[unlikely]] {
|
||||
s_unlocalizedNames->emplace(m_entryHash, localizedString.m_unlocalizedString);
|
||||
}
|
||||
}
|
||||
Lang::Lang(const UnlocalizedString &unlocalizedString) : Lang(unlocalizedString.get()) { }
|
||||
|
||||
Lang::operator std::string() const {
|
||||
return get();
|
||||
@@ -182,7 +216,11 @@ namespace hex {
|
||||
|
||||
const auto it = lang.find(m_entryHash);
|
||||
if (it == lang.end()) {
|
||||
return m_unlocalizedString.c_str();
|
||||
if (auto unlocalizedIt = s_unlocalizedNames->find(m_entryHash); unlocalizedIt != s_unlocalizedNames->end()) {
|
||||
return unlocalizedIt->second.c_str();
|
||||
} else {
|
||||
return "<unlocalized>";
|
||||
}
|
||||
} else {
|
||||
return it->second.c_str();
|
||||
}
|
||||
@@ -211,4 +249,4 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
Plugin::Plugin(const std::string &name, const hex::PluginFunctions &functions) :
|
||||
m_handle(0), m_path(name), m_addedManually(true), m_functions(functions) { }
|
||||
m_path(name), m_addedManually(true), m_functions(functions) { }
|
||||
|
||||
|
||||
Plugin::Plugin(Plugin &&other) noexcept {
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
std::fs::path ProjectFile::getPath() {
|
||||
return s_currProjectPath;
|
||||
return *s_currProjectPath;
|
||||
}
|
||||
|
||||
void ProjectFile::setPath(const std::fs::path &path) {
|
||||
|
||||
@@ -260,8 +260,11 @@ namespace hex {
|
||||
case CTRLCMD.getKeyCode():
|
||||
result.cmd = true;
|
||||
break;
|
||||
case CurrentView.getKeyCode(): break;
|
||||
case AllowWhileTyping.getKeyCode(): break;
|
||||
case CurrentView.getKeyCode():
|
||||
case AllowWhileTyping.getKeyCode():
|
||||
case ShowOnWelcomeScreen.getKeyCode():
|
||||
// Ignore flags that are only used internally by the ShortcutManager
|
||||
break;
|
||||
default:
|
||||
macosGetKey(Keys(key.getKeyCode()), &result.key);
|
||||
break;
|
||||
@@ -278,25 +281,25 @@ namespace hex {
|
||||
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, unlocalizedName, callback, enabledCallback } });
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { .shortcut=shortcut, .unlocalizedName=unlocalizedName, .callback=callback, .enabledCallback=enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, { unlocalizedName }, callback, enabledCallback } });
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { .shortcut=shortcut, .unlocalizedName={ unlocalizedName }, .callback=callback, .enabledCallback=enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback, enabledCallback } });
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { .shortcut=shortcut, .unlocalizedName=unlocalizedName, .callback=callback, .enabledCallback=enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, { unlocalizedName }, callback, enabledCallback } });
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { .shortcut=shortcut, .unlocalizedName={ unlocalizedName }, .callback=callback, .enabledCallback=enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
@@ -326,12 +329,13 @@ namespace hex {
|
||||
if (ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId))
|
||||
return true;
|
||||
|
||||
const bool currentlyTyping = ImGui::GetIO().WantTextInput;
|
||||
|
||||
auto it = shortcuts.find(shortcut + AllowWhileTyping);
|
||||
if (!currentlyTyping && it == shortcuts.end()) {
|
||||
auto it = shortcuts.end();
|
||||
if (ImGui::GetIO().WantTextInput) {
|
||||
it = shortcuts.find(shortcut + AllowWhileTyping);
|
||||
} else {
|
||||
it = shortcuts.find(shortcut);
|
||||
if (it == shortcuts.end())
|
||||
it = shortcuts.find(shortcut);
|
||||
it = shortcuts.find(shortcut + AllowWhileTyping);
|
||||
}
|
||||
|
||||
if (it != shortcuts.end()) {
|
||||
@@ -363,7 +367,17 @@ namespace hex {
|
||||
if (keyCode != 0)
|
||||
s_prevShortcut = Shortcut(pressedShortcut.getKeys());
|
||||
|
||||
runShortcut(pressedShortcut, currentView);
|
||||
std::set<const View*> processedViews;
|
||||
while (true) {
|
||||
if (runShortcut(pressedShortcut, currentView)) {
|
||||
break;
|
||||
}
|
||||
|
||||
processedViews.insert(currentView);
|
||||
currentView = currentView->getMenuItemInheritView();
|
||||
if (currentView == nullptr || processedViews.contains(currentView))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ShortcutManager::processGlobals(bool ctrl, bool alt, bool shift, bool super, u32 keyCode) {
|
||||
@@ -387,6 +401,24 @@ namespace hex {
|
||||
s_globalShortcuts->clear();
|
||||
}
|
||||
|
||||
Shortcut ShortcutManager::getShortcutByName(const std::vector<UnlocalizedString> &unlocalizedName, const View *view) {
|
||||
if (view != nullptr) {
|
||||
for (const auto &[shortcut, entry] : view->m_shortcuts) {
|
||||
if (entry.unlocalizedName == unlocalizedName) {
|
||||
return entry.shortcut;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const auto &[shortcut, entry] : *s_globalShortcuts) {
|
||||
if (entry.unlocalizedName == unlocalizedName) {
|
||||
return entry.shortcut;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Shortcut::None;
|
||||
}
|
||||
|
||||
void ShortcutManager::resumeShortcuts() {
|
||||
s_paused = false;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#include <ranges>
|
||||
|
||||
#include <jthread.hpp>
|
||||
#include <hex/helpers/debugging.hpp>
|
||||
#include <hex/trace/exceptions.hpp>
|
||||
#include <utility>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#include <windows.h>
|
||||
@@ -52,6 +55,7 @@ namespace hex {
|
||||
std::list<std::function<void()>> s_deferredCalls;
|
||||
std::unordered_map<SourceLocationWrapper, std::function<void()>> s_onceDeferredCalls;
|
||||
std::list<std::function<void()>> s_tasksFinishedCallbacks;
|
||||
std::list<std::function<void(Task&)>> s_taskCompletionCallbacks;
|
||||
|
||||
std::mutex s_queueMutex;
|
||||
std::condition_variable s_jobCondVar;
|
||||
@@ -64,7 +68,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
Task::Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function)
|
||||
Task::Task(UnlocalizedString unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function)
|
||||
: m_unlocalizedName(std::move(unlocalizedName)),
|
||||
m_maxValue(maxValue),
|
||||
m_function(std::move(function)),
|
||||
@@ -82,9 +86,17 @@ namespace hex {
|
||||
m_maxValue = u64(other.m_maxValue);
|
||||
m_currValue = u64(other.m_currValue);
|
||||
|
||||
m_finished = bool(other.m_finished);
|
||||
m_hadException = bool(other.m_hadException);
|
||||
m_interrupted = bool(other.m_interrupted);
|
||||
if (other.m_finished.test())
|
||||
m_finished.test_and_set();
|
||||
if (other.m_hadException.test())
|
||||
m_hadException.test_and_set();
|
||||
if (other.m_interrupted.test())
|
||||
m_interrupted.test_and_set();
|
||||
|
||||
m_finished.notify_all();
|
||||
m_hadException.notify_all();
|
||||
m_interrupted.notify_all();
|
||||
|
||||
m_shouldInterrupt = bool(other.m_shouldInterrupt);
|
||||
}
|
||||
|
||||
@@ -143,11 +155,11 @@ namespace hex {
|
||||
|
||||
|
||||
bool Task::isFinished() const {
|
||||
return m_finished;
|
||||
return m_finished.test();
|
||||
}
|
||||
|
||||
bool Task::hadException() const {
|
||||
return m_hadException;
|
||||
return m_hadException.test();
|
||||
}
|
||||
|
||||
bool Task::shouldInterrupt() const {
|
||||
@@ -155,11 +167,11 @@ namespace hex {
|
||||
}
|
||||
|
||||
bool Task::wasInterrupted() const {
|
||||
return m_interrupted;
|
||||
return m_interrupted.test();
|
||||
}
|
||||
|
||||
void Task::clearException() {
|
||||
m_hadException = false;
|
||||
m_hadException.clear();
|
||||
}
|
||||
|
||||
std::string Task::getExceptionMessage() const {
|
||||
@@ -180,12 +192,18 @@ namespace hex {
|
||||
return m_maxValue;
|
||||
}
|
||||
|
||||
void Task::wait() const {
|
||||
m_finished.wait(false);
|
||||
}
|
||||
|
||||
void Task::finish() {
|
||||
m_finished = true;
|
||||
m_finished.test_and_set();
|
||||
m_finished.notify_all();
|
||||
}
|
||||
|
||||
void Task::interruption() {
|
||||
m_interrupted = true;
|
||||
m_interrupted.test_and_set();
|
||||
m_interrupted.notify_all();
|
||||
}
|
||||
|
||||
void Task::exception(const char *message) {
|
||||
@@ -193,7 +211,8 @@ namespace hex {
|
||||
|
||||
// Store information about the caught exception
|
||||
m_exceptionMessage = message;
|
||||
m_hadException = true;
|
||||
m_hadException.test_and_set();
|
||||
m_hadException.notify_all();
|
||||
|
||||
// Call the interrupt callback on the current thread if one is set
|
||||
if (m_interruptCallback)
|
||||
@@ -241,6 +260,14 @@ namespace hex {
|
||||
task->interrupt();
|
||||
}
|
||||
|
||||
void TaskHolder::wait() const {
|
||||
const auto &task = m_task.lock();
|
||||
if (!task)
|
||||
return;
|
||||
|
||||
task->wait();
|
||||
}
|
||||
|
||||
u32 TaskHolder::getProgress() const {
|
||||
const auto &task = m_task.lock();
|
||||
if (!task)
|
||||
@@ -287,6 +314,8 @@ namespace hex {
|
||||
}
|
||||
|
||||
try {
|
||||
trace::enableExceptionCaptureForCurrentThread();
|
||||
|
||||
// Set the thread name to the name of the task
|
||||
TaskManager::setCurrentThreadName(Lang(task->m_unlocalizedName));
|
||||
|
||||
@@ -294,21 +323,34 @@ namespace hex {
|
||||
task->m_function(*task);
|
||||
|
||||
log::debug("Task '{}' finished", task->m_unlocalizedName.get());
|
||||
|
||||
{
|
||||
std::scoped_lock lock(s_tasksFinishedMutex);
|
||||
|
||||
for (const auto &callback : s_taskCompletionCallbacks)
|
||||
callback(*task);
|
||||
}
|
||||
} catch (const Task::TaskInterruptor &) {
|
||||
// Handle the task being interrupted by user request
|
||||
task->interruption();
|
||||
} catch (const std::exception &e) {
|
||||
log::error("Exception in task '{}': {}", task->m_unlocalizedName.get(), e.what());
|
||||
|
||||
dbg::printStackTrace(trace::getStackTrace());
|
||||
|
||||
// Handle the task throwing an uncaught exception
|
||||
task->exception(e.what());
|
||||
} catch (...) {
|
||||
log::error("Exception in task '{}'", task->m_unlocalizedName.get());
|
||||
|
||||
dbg::printStackTrace(trace::getStackTrace());
|
||||
|
||||
// Handle the task throwing an uncaught exception of unknown type
|
||||
task->exception("Unknown Exception");
|
||||
}
|
||||
|
||||
trace::disableExceptionCaptureForCurrentThread();
|
||||
|
||||
s_currentTask = nullptr;
|
||||
task->finish();
|
||||
}
|
||||
@@ -327,7 +369,10 @@ namespace hex {
|
||||
thread.request_stop();
|
||||
|
||||
// Wake up all the idle worker threads so they can exit
|
||||
s_jobCondVar.notify_all();
|
||||
{
|
||||
std::unique_lock lock(s_queueMutex);
|
||||
s_jobCondVar.notify_all();
|
||||
}
|
||||
|
||||
// Wait for all worker threads to exit
|
||||
s_workers.clear();
|
||||
@@ -338,13 +383,14 @@ namespace hex {
|
||||
s_deferredCalls.clear();
|
||||
s_onceDeferredCalls.clear();
|
||||
s_tasksFinishedCallbacks.clear();
|
||||
s_taskCompletionCallbacks.clear();
|
||||
}
|
||||
|
||||
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task&)> function) {
|
||||
std::scoped_lock lock(s_queueMutex);
|
||||
|
||||
// Construct new task
|
||||
auto task = std::make_shared<Task>(std::move(unlocalizedName), maxValue, background, blocking, std::move(function));
|
||||
auto task = std::make_shared<Task>(unlocalizedName, maxValue, background, blocking, std::move(function));
|
||||
|
||||
s_tasks.emplace_back(task);
|
||||
|
||||
@@ -359,12 +405,12 @@ namespace hex {
|
||||
|
||||
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function) {
|
||||
log::debug("Creating task {}", unlocalizedName.get());
|
||||
return createTask(std::move(unlocalizedName), maxValue, false, false, std::move(function));
|
||||
return createTask(unlocalizedName, maxValue, false, false, std::move(function));
|
||||
}
|
||||
|
||||
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function) {
|
||||
log::debug("Creating task {}", unlocalizedName.get());
|
||||
return createTask(std::move(unlocalizedName), maxValue, false, false,
|
||||
return createTask(unlocalizedName, maxValue, false, false,
|
||||
[function = std::move(function)](Task&) {
|
||||
function();
|
||||
}
|
||||
@@ -373,12 +419,12 @@ namespace hex {
|
||||
|
||||
TaskHolder TaskManager::createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void(Task &)> function) {
|
||||
log::debug("Creating background task {}", unlocalizedName.get());
|
||||
return createTask(std::move(unlocalizedName), 0, true, false, std::move(function));
|
||||
return createTask(unlocalizedName, 0, true, false, std::move(function));
|
||||
}
|
||||
|
||||
TaskHolder TaskManager::createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void()> function) {
|
||||
log::debug("Creating background task {}", unlocalizedName.get());
|
||||
return createTask(std::move(unlocalizedName), 0, true, false,
|
||||
return createTask(unlocalizedName, 0, true, false,
|
||||
[function = std::move(function)](Task&) {
|
||||
function();
|
||||
}
|
||||
@@ -387,12 +433,12 @@ namespace hex {
|
||||
|
||||
TaskHolder TaskManager::createBlockingTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function) {
|
||||
log::debug("Creating blocking task {}", unlocalizedName.get());
|
||||
return createTask(std::move(unlocalizedName), maxValue, true, true, std::move(function));
|
||||
return createTask(unlocalizedName, maxValue, true, true, std::move(function));
|
||||
}
|
||||
|
||||
TaskHolder TaskManager::createBlockingTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function) {
|
||||
log::debug("Creating blocking task {}", unlocalizedName.get());
|
||||
return createTask(std::move(unlocalizedName), maxValue, true, true,
|
||||
return createTask(unlocalizedName, maxValue, true, true,
|
||||
[function = std::move(function)](Task&) {
|
||||
function();
|
||||
}
|
||||
@@ -546,5 +592,13 @@ namespace hex {
|
||||
return s_mainThreadId == std::this_thread::get_id();
|
||||
}
|
||||
|
||||
void TaskManager::addTaskCompletionCallback(const std::function<void(Task &)> &function) {
|
||||
std::scoped_lock lock(s_tasksFinishedMutex);
|
||||
|
||||
for (const auto &task : s_tasks) {
|
||||
task->interrupt();
|
||||
}
|
||||
|
||||
s_taskCompletionCallbacks.push_back(function);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace hex {
|
||||
void ThemeManager::addThemeHandler(const std::string &name, const ColorMap &colorMap, const std::function<ImColor(u32)> &getFunction, const std::function<void(u32, ImColor)> &setFunction) {
|
||||
std::unique_lock lock(s_themeMutex);
|
||||
|
||||
(*s_themeHandlers)[name] = { colorMap, getFunction, setFunction };
|
||||
(*s_themeHandlers)[name] = { .colorMap=colorMap, .getFunction=getFunction, .setFunction=setFunction };
|
||||
}
|
||||
|
||||
void ThemeManager::addStyleHandler(const std::string &name, const StyleMap &styleMap) {
|
||||
|
||||
@@ -32,6 +32,8 @@ namespace hex {
|
||||
ImGuiID s_activeHelpId;
|
||||
bool s_helpHoverActive = false;
|
||||
|
||||
AutoReset<std::function<std::function<void()>(const std::string &)>> s_renderer;
|
||||
|
||||
|
||||
class IDStack {
|
||||
public:
|
||||
@@ -55,7 +57,7 @@ namespace hex {
|
||||
|
||||
void add(const void *pointer) {
|
||||
const ImGuiID seed = idStack.back();
|
||||
const ImGuiID id = ImHashData(&pointer, sizeof(pointer), seed);
|
||||
const ImGuiID id = ImHashData((const void*) &pointer, sizeof(pointer), seed);
|
||||
|
||||
idStack.push_back(id);
|
||||
}
|
||||
@@ -94,35 +96,47 @@ namespace hex {
|
||||
}
|
||||
|
||||
void TutorialManager::init() {
|
||||
EventImGuiElementRendered::subscribe([](ImGuiID id, const std::array<float, 4> bb){
|
||||
const auto boundingBox = ImRect(bb[0], bb[1], bb[2], bb[3]);
|
||||
if (*s_renderer == nullptr) {
|
||||
*s_renderer = [](const std::string &message) {
|
||||
return [message] {
|
||||
ImGui::PushTextWrapPos(300_scaled);
|
||||
ImGui::TextUnformatted(message.c_str());
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::NewLine();
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const auto element = hex::s_highlights->find(id);
|
||||
if (element != hex::s_highlights->end()) {
|
||||
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
|
||||
void TutorialManager::postElementRendered(ImGuiID id, const ImRect &boundingBox) {
|
||||
if (!ImGui::IsRectVisible(boundingBox.Min, boundingBox.Max))
|
||||
return;
|
||||
|
||||
const auto window = ImGui::GetCurrentWindow();
|
||||
if (window != nullptr && window->DockNode != nullptr && window->DockNode->TabBar != nullptr)
|
||||
window->DockNode->TabBar->NextSelectedTabId = window->TabId;
|
||||
}
|
||||
{
|
||||
const auto element = hex::s_highlights->find(id);
|
||||
if (element != hex::s_highlights->end()) {
|
||||
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
|
||||
|
||||
const auto window = ImGui::GetCurrentWindow();
|
||||
if (window != nullptr && window->DockNode != nullptr && window->DockNode->TabBar != nullptr)
|
||||
window->DockNode->TabBar->NextSelectedTabId = window->TabId;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const auto element = s_interactiveHelpItems->find(id);
|
||||
if (element != s_interactiveHelpItems->end()) {
|
||||
(*s_interactiveHelpDisplays)[id] = boundingBox;
|
||||
}
|
||||
|
||||
{
|
||||
const auto element = s_interactiveHelpItems->find(id);
|
||||
if (element != s_interactiveHelpItems->end()) {
|
||||
(*s_interactiveHelpDisplays)[id] = boundingBox;
|
||||
}
|
||||
}
|
||||
|
||||
if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
|
||||
if ((s_hoveredRect.GetArea() == 0 || boundingBox.GetArea() < s_hoveredRect.GetArea()) && s_interactiveHelpItems->contains(id)) {
|
||||
s_hoveredRect = boundingBox;
|
||||
s_hoveredId = id;
|
||||
}
|
||||
|
||||
if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
|
||||
if ((s_hoveredRect.GetArea() == 0 || boundingBox.GetArea() < s_hoveredRect.GetArea()) && s_interactiveHelpItems->contains(id)) {
|
||||
s_hoveredRect = boundingBox;
|
||||
s_hoveredId = id;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const std::map<std::string, TutorialManager::Tutorial>& TutorialManager::getTutorials() {
|
||||
@@ -201,9 +215,13 @@ namespace hex {
|
||||
s_currentTutorial->second.start();
|
||||
}
|
||||
|
||||
void TutorialManager::stopCurrentTutorial() {
|
||||
s_currentTutorial = s_tutorials->end();
|
||||
}
|
||||
|
||||
void TutorialManager::drawHighlights() {
|
||||
if (s_helpHoverActive) {
|
||||
const auto &drawList = ImGui::GetForegroundDrawList();
|
||||
const auto &drawList = ImGui::GetForegroundDrawList(ImGui::GetMainViewport());
|
||||
drawList->AddText(ImGui::GetMousePos() + scaled({ 10, -5, }), ImGui::GetColorU32(ImGuiCol_Text), "?");
|
||||
|
||||
for (const auto &[id, boundingBox] : *s_interactiveHelpDisplays) {
|
||||
@@ -251,6 +269,7 @@ namespace hex {
|
||||
{
|
||||
auto highlightColor = ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_Highlight);
|
||||
highlightColor.w *= ImSin(ImGui::GetTime() * 6.0F) / 4.0F + 0.75F;
|
||||
ImHexApi::System::unlockFrameRate();
|
||||
|
||||
drawList->AddRect(rect.Min - ImVec2(5, 5), rect.Max + ImVec2(5, 5), ImColor(highlightColor), 5.0F, ImDrawFlags_None, 2.0F);
|
||||
}
|
||||
@@ -299,10 +318,10 @@ namespace hex {
|
||||
|
||||
if (!message.has_value()) {
|
||||
message = Tutorial::Step::Message {
|
||||
Position::None,
|
||||
"",
|
||||
"",
|
||||
false
|
||||
.position=Position::None,
|
||||
.unlocalizedTitle="",
|
||||
.unlocalizedMessage="",
|
||||
.allowSkip=false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -329,34 +348,39 @@ namespace hex {
|
||||
|
||||
ImGui::SetNextWindowPos(position, ImGuiCond_Always, pivot);
|
||||
ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID);
|
||||
if (ImGui::Begin("##TutorialMessage", nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing)) {
|
||||
ImGui::SetNextWindowSize(ImVec2(300_scaled, 0));
|
||||
|
||||
bool open = true;
|
||||
if (ImGui::Begin(message->unlocalizedTitle.empty() ? "##TutorialMessage" : Lang(message->unlocalizedTitle), &open, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoFocusOnAppearing)) {
|
||||
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindowRead());
|
||||
|
||||
if (!message->unlocalizedTitle.empty())
|
||||
ImGuiExt::Header(Lang(message->unlocalizedTitle), true);
|
||||
|
||||
auto &step = s_currentTutorial->second.m_currentStep;
|
||||
if (!message->unlocalizedMessage.empty()) {
|
||||
ImGui::PushTextWrapPos(300_scaled);
|
||||
ImGui::TextUnformatted(Lang(message->unlocalizedMessage));
|
||||
ImGui::PopTextWrapPos();
|
||||
step->m_drawFunction();
|
||||
ImGui::NewLine();
|
||||
ImGui::NewLine();
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(s_currentTutorial->second.m_currentStep == s_currentTutorial->second.m_steps.begin());
|
||||
if (ImGui::ArrowButton("Backwards", ImGuiDir_Left)) {
|
||||
ImGui::BeginDisabled(step == s_currentTutorial->second.m_steps.begin());
|
||||
if (ImGuiExt::DimmedArrowButton("Backwards", ImGuiDir_Left)) {
|
||||
s_currentTutorial->second.m_currentStep->advance(-1);
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginDisabled(!message->allowSkip && s_currentTutorial->second.m_currentStep == s_currentTutorial->second.m_latestStep);
|
||||
if (ImGui::ArrowButton("Forwards", ImGuiDir_Right)) {
|
||||
s_currentTutorial->second.m_currentStep->advance(1);
|
||||
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - ImGui::GetFrameHeight() - ImGui::GetStyle().WindowPadding.x);
|
||||
ImGui::BeginDisabled(!message->allowSkip && step == s_currentTutorial->second.m_latestStep);
|
||||
if (ImGuiExt::DimmedArrowButton("Forwards", ImGuiDir_Right)) {
|
||||
step->advance(1);
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
if (!open) {
|
||||
stopCurrentTutorial();
|
||||
}
|
||||
}
|
||||
|
||||
void TutorialManager::drawTutorial() {
|
||||
@@ -383,6 +407,10 @@ namespace hex {
|
||||
s_highlightDisplays->clear();
|
||||
}
|
||||
|
||||
void TutorialManager::setRenderer(std::function<DrawFunction(const std::string &)> renderer) {
|
||||
s_renderer = std::move(renderer);
|
||||
}
|
||||
|
||||
TutorialManager::Tutorial::Step& TutorialManager::Tutorial::addStep() {
|
||||
auto &newStep = m_steps.emplace_back(this);
|
||||
m_currentStep = m_steps.end();
|
||||
@@ -398,6 +426,9 @@ namespace hex {
|
||||
return;
|
||||
|
||||
m_currentStep->addHighlights();
|
||||
|
||||
if (m_currentStep->m_message.has_value())
|
||||
m_currentStep->m_drawFunction = (*s_renderer)(Lang(m_currentStep->m_message->unlocalizedMessage));
|
||||
}
|
||||
|
||||
void TutorialManager::Tutorial::Step::addHighlights() const {
|
||||
@@ -422,8 +453,12 @@ namespace hex {
|
||||
std::advance(m_parent->m_latestStep, steps);
|
||||
std::advance(m_parent->m_currentStep, steps);
|
||||
|
||||
if (m_parent->m_currentStep != m_parent->m_steps.end())
|
||||
if (m_parent->m_currentStep != m_parent->m_steps.end()) {
|
||||
m_parent->m_currentStep->addHighlights();
|
||||
|
||||
if (m_message.has_value())
|
||||
m_parent->m_currentStep->m_drawFunction = (*s_renderer)(Lang(m_parent->m_currentStep->m_message->unlocalizedMessage));
|
||||
}
|
||||
else
|
||||
s_currentTutorial = s_tutorials->end();
|
||||
}
|
||||
@@ -446,10 +481,10 @@ namespace hex {
|
||||
|
||||
TutorialManager::Tutorial::Step& TutorialManager::Tutorial::Step::setMessage(const UnlocalizedString &unlocalizedTitle, const UnlocalizedString &unlocalizedMessage, Position position) {
|
||||
m_message = Message {
|
||||
position,
|
||||
unlocalizedTitle,
|
||||
unlocalizedMessage,
|
||||
false
|
||||
.position=position,
|
||||
.unlocalizedTitle=unlocalizedTitle,
|
||||
.unlocalizedMessage=unlocalizedMessage,
|
||||
.allowSkip=false
|
||||
};
|
||||
|
||||
return *this;
|
||||
@@ -460,10 +495,10 @@ namespace hex {
|
||||
m_message->allowSkip = true;
|
||||
} else {
|
||||
m_message = Message {
|
||||
Position::Bottom | Position::Right,
|
||||
"",
|
||||
"",
|
||||
true
|
||||
.position=Position::Bottom | Position::Right,
|
||||
.unlocalizedTitle="",
|
||||
.unlocalizedMessage="",
|
||||
.allowSkip=true
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user