mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-28 15:57:03 -05:00
Compare commits
489 Commits
v1.36.1
...
releases/v
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f8131b7c4 | ||
|
|
b6b24dfd29 | ||
|
|
041f113402 | ||
|
|
5f61fe2c4f | ||
|
|
96cc7e8ba8 | ||
|
|
22b3daf082 | ||
|
|
1deb27a6df | ||
|
|
73fdc3c6ea | ||
|
|
cae0f772d5 | ||
|
|
51547dc941 | ||
|
|
1508efac7a | ||
|
|
16dc239e0f | ||
|
|
899f00ed2f | ||
|
|
9ebfffd346 | ||
|
|
76b2c09450 | ||
|
|
69246de145 | ||
|
|
aee4b4fdf6 | ||
|
|
a6a78cef00 | ||
|
|
30b25a39a7 | ||
|
|
1f0b5e1ee1 | ||
|
|
d6658c3471 | ||
|
|
398eecaa1d | ||
|
|
b6616c1a0f | ||
|
|
5d3315f51c | ||
|
|
ec7298f0c0 | ||
|
|
92c2018f71 | ||
|
|
956952021d | ||
|
|
f112123d39 | ||
|
|
1a1ef9e7e0 | ||
|
|
39543fbda8 | ||
|
|
835863523b | ||
|
|
e6c8c69fda | ||
|
|
e2d30eeba2 | ||
|
|
1da82d1403 | ||
|
|
73b9df24cf | ||
|
|
f93e1194d6 | ||
|
|
677cff244d | ||
|
|
8d88e328fa | ||
|
|
acb5ef561d | ||
|
|
444b5219e2 | ||
|
|
a4c7e0db90 | ||
|
|
f4e1824b7b | ||
|
|
fcb5e18102 | ||
|
|
70d4e21c4b | ||
|
|
2e2d5d31bc | ||
|
|
01f4595aab | ||
|
|
bf10d333cd | ||
|
|
267ef37cb6 | ||
|
|
879e4c9d58 | ||
|
|
67340e1526 | ||
|
|
6ec8f9efe5 | ||
|
|
c2b0560d91 | ||
|
|
388071557e | ||
|
|
f6e3ede178 | ||
|
|
a907550567 | ||
|
|
c75a15dc3b | ||
|
|
83904aa1f1 | ||
|
|
7d527fd2a6 | ||
|
|
007e04bf37 | ||
|
|
caff49504e | ||
|
|
aad38beaf5 | ||
|
|
bdad733331 | ||
|
|
bc26ade57e | ||
|
|
ee52ff3b11 | ||
|
|
40b95f02e4 | ||
|
|
8777a85630 | ||
|
|
870aeb34fc | ||
|
|
b03be212b3 | ||
|
|
c8f7dbf85e | ||
|
|
9e826b4c8b | ||
|
|
05d528b39a | ||
|
|
6828c7c077 | ||
|
|
54f3bc0262 | ||
|
|
e232a2b33d | ||
|
|
73a3b217a4 | ||
|
|
19f925c60b | ||
|
|
5fb488236b | ||
|
|
c84786f9ee | ||
|
|
c1925ddf8d | ||
|
|
cf194e332c | ||
|
|
d8877e7d8b | ||
|
|
8b2184f8e3 | ||
|
|
a42e4c5299 | ||
|
|
419787e17c | ||
|
|
2d6da52a86 | ||
|
|
b46deb3fa0 | ||
|
|
b70120a248 | ||
|
|
3a6a4011d0 | ||
|
|
999c4d07b7 | ||
|
|
44b182c6ae | ||
|
|
de7bec547a | ||
|
|
5542c0bc00 | ||
|
|
83e0ce0042 | ||
|
|
4685dea075 | ||
|
|
599f63bc67 | ||
|
|
199f2aea77 | ||
|
|
bff9b8b4b1 | ||
|
|
a83610bc06 | ||
|
|
b3d208e6e6 | ||
|
|
e8b391c0f6 | ||
|
|
02b5df03ab | ||
|
|
e1580e51cf | ||
|
|
3a7578879f | ||
|
|
ea3d4b41a9 | ||
|
|
e0c2a39ce7 | ||
|
|
1fa27b7f09 | ||
|
|
f980f1dae2 | ||
|
|
b81ad53449 | ||
|
|
a9727171e2 | ||
|
|
a1634fb337 | ||
|
|
94a2f9460e | ||
|
|
18cd39270a | ||
|
|
72c2bca363 | ||
|
|
4c153dc76d | ||
|
|
e63606f6bb | ||
|
|
ed6da7fe14 | ||
|
|
a588c96440 | ||
|
|
4c284b224e | ||
|
|
96afa650d1 | ||
|
|
f17d0d3ae1 | ||
|
|
930d2b4280 | ||
|
|
f67b78bd91 | ||
|
|
540e8ed602 | ||
|
|
99cb51e813 | ||
|
|
db000c4b12 | ||
|
|
0cd557a686 | ||
|
|
6142bf859b | ||
|
|
b6498b5c2d | ||
|
|
c15030e96e | ||
|
|
cd2acd73b4 | ||
|
|
cfe06ea1b6 | ||
|
|
ca5c3e0e94 | ||
|
|
6252fd399a | ||
|
|
de571e2c2a | ||
|
|
0cbd052b91 | ||
|
|
aa3ec3ece8 | ||
|
|
6b11028b72 | ||
|
|
269c3e7398 | ||
|
|
08335041f5 | ||
|
|
d75b9cf942 | ||
|
|
b55c40523f | ||
|
|
99a2dee7a2 | ||
|
|
c94265c77b | ||
|
|
7ddfba1b4c | ||
|
|
9ecdd28eea | ||
|
|
d8b36242f6 | ||
|
|
3f470aabe9 | ||
|
|
1e8dd54b3e | ||
|
|
0a6681ccb7 | ||
|
|
0140e24822 | ||
|
|
9fb38922ea | ||
|
|
7752354598 | ||
|
|
497670c4c3 | ||
|
|
84954cd2f1 | ||
|
|
8b6eab401e | ||
|
|
71c11a5923 | ||
|
|
f345edb252 | ||
|
|
be40fd9563 | ||
|
|
5ee2ebfb4f | ||
|
|
cfa6b706a8 | ||
|
|
42f2a62d62 | ||
|
|
41b6ef930a | ||
|
|
948cbe0a9c | ||
|
|
18669f3230 | ||
|
|
4e9f944204 | ||
|
|
fe18cbaa41 | ||
|
|
ed3712e1b9 | ||
|
|
20dc4f31f0 | ||
|
|
19f9296a40 | ||
|
|
06c019387c | ||
|
|
645b43e9cc | ||
|
|
ed37a3711f | ||
|
|
a3460de9dc | ||
|
|
5084009d62 | ||
|
|
e5c003d726 | ||
|
|
327a02b87d | ||
|
|
e9bf1a9f7a | ||
|
|
0c6fa768ea | ||
|
|
483468a6c7 | ||
|
|
8039ae1b90 | ||
|
|
466b372d41 | ||
|
|
3f6b5203ca | ||
|
|
8d1352ddff | ||
|
|
e6ab2c3b7e | ||
|
|
e603c75bd3 | ||
|
|
4f28f97141 | ||
|
|
d0b32e5224 | ||
|
|
2062a23347 | ||
|
|
8c9236a066 | ||
|
|
2f981ef91e | ||
|
|
6725c170ea | ||
|
|
c8cf6e7c08 | ||
|
|
e0b4acee12 | ||
|
|
803ebe34ed | ||
|
|
e981eff1e6 | ||
|
|
aee7a09b6c | ||
|
|
e74e4e92a0 | ||
|
|
6dba15defd | ||
|
|
fee7a16692 | ||
|
|
141030344b | ||
|
|
4fa9586206 | ||
|
|
fbbc430b7c | ||
|
|
bfc68c4d28 | ||
|
|
53fc018ada | ||
|
|
d45dd45720 | ||
|
|
19a9786bbf | ||
|
|
b8caf41423 | ||
|
|
0b3866a56a | ||
|
|
53a7577416 | ||
|
|
f5515417d6 | ||
|
|
24e7c2f3db | ||
|
|
6e6c5bbc67 | ||
|
|
f4403ff480 | ||
|
|
098da20761 | ||
|
|
ef2373e8c0 | ||
|
|
b2c8ed17d5 | ||
|
|
bb594a459f | ||
|
|
7340a30650 | ||
|
|
403104dda1 | ||
|
|
8334fbb236 | ||
|
|
0a0323ce5d | ||
|
|
726d36ba3d | ||
|
|
8bb1521963 | ||
|
|
9457c1f2b9 | ||
|
|
2b24330f9f | ||
|
|
9329170e59 | ||
|
|
98f3de828a | ||
|
|
3f38f42259 | ||
|
|
058a8cdc15 | ||
|
|
d0c1213ea0 | ||
|
|
30967bac6d | ||
|
|
09c9bcb046 | ||
|
|
93f1f5d076 | ||
|
|
93e5d62782 | ||
|
|
4d7021ece1 | ||
|
|
f976988c75 | ||
|
|
1eee31fdbb | ||
|
|
048c483903 | ||
|
|
b646ece14b | ||
|
|
35e8acd69d | ||
|
|
de4135d1ad | ||
|
|
a44959ce1b | ||
|
|
f4bad0053a | ||
|
|
26af5987a5 | ||
|
|
9cf3250751 | ||
|
|
acc77205bb | ||
|
|
a6b4f62d75 | ||
|
|
69c5d553b5 | ||
|
|
637cdd7084 | ||
|
|
8978e193db | ||
|
|
242b100aa3 | ||
|
|
3a888d48df | ||
|
|
721de39dbb | ||
|
|
07e29f2030 | ||
|
|
c117d9b3e5 | ||
|
|
16eae89151 | ||
|
|
95cb6d8ee6 | ||
|
|
af27c09204 | ||
|
|
5e3532267c | ||
|
|
7c0331df65 | ||
|
|
04ab87cd8e | ||
|
|
91f5e84250 | ||
|
|
b1edd95ebc | ||
|
|
758738da5c | ||
|
|
41c8be275b | ||
|
|
117eb1e2a7 | ||
|
|
3129d6e8fd | ||
|
|
2ba7db184b | ||
|
|
2cb0df4080 | ||
|
|
3adc2c44e6 | ||
|
|
6d3ff64894 | ||
|
|
cf84ad6196 | ||
|
|
6259190ad9 | ||
|
|
181be1a58e | ||
|
|
771e191f28 | ||
|
|
d4d6893eb3 | ||
|
|
9e75562662 | ||
|
|
2b3168163b | ||
|
|
252c06eb12 | ||
|
|
2a51d8169a | ||
|
|
7405c4b411 | ||
|
|
309ae7b619 | ||
|
|
64ef56a0df | ||
|
|
fbfe7b0d25 | ||
|
|
8c7e1a3b2d | ||
|
|
bf249cdafe | ||
|
|
59ba6f50cc | ||
|
|
8d6e7c7d44 | ||
|
|
52934ae166 | ||
|
|
56c4f2aa47 | ||
|
|
a1d8cbd7ba | ||
|
|
63a219a32b | ||
|
|
14fb256a6a | ||
|
|
95df7a23c3 | ||
|
|
bb17690cf5 | ||
|
|
a943b02e43 | ||
|
|
199f78347f | ||
|
|
d3d9a42d57 | ||
|
|
1fa45a8c84 | ||
|
|
0b6316ea23 | ||
|
|
466a843263 | ||
|
|
b6ade8b101 | ||
|
|
ff66b97e90 | ||
|
|
c604ec8fb9 | ||
|
|
7564651dd5 | ||
|
|
cad17ddefd | ||
|
|
25d2f209e5 | ||
|
|
8d660c3ffe | ||
|
|
209055d0b0 | ||
|
|
599b55965a | ||
|
|
69a9af5322 | ||
|
|
0303cd0ad0 | ||
|
|
8eb7e9fb05 | ||
|
|
6a1de5fc4e | ||
|
|
a4af55cb66 | ||
|
|
1e17422f5e | ||
|
|
8abaafab79 | ||
|
|
71e1465524 | ||
|
|
3d2ea3753b | ||
|
|
88530eff8b | ||
|
|
df3decf71b | ||
|
|
565ee4cb2d | ||
|
|
40fc325ba9 | ||
|
|
6aca16102d | ||
|
|
cb11b57ab1 | ||
|
|
d504937d50 | ||
|
|
6bfdb7ca4e | ||
|
|
e1637824c6 | ||
|
|
e36f2f2bcb | ||
|
|
1a54e08f11 | ||
|
|
ecc86ee429 | ||
|
|
185a593bc2 | ||
|
|
4a916ebb89 | ||
|
|
1c305ca762 | ||
|
|
17fff56fa0 | ||
|
|
ec1b1c2b7d | ||
|
|
7bae22f56f | ||
|
|
21e5eeef16 | ||
|
|
bf5eea80f6 | ||
|
|
9f9a6d9827 | ||
|
|
ae622e6d75 | ||
|
|
68fbff631f | ||
|
|
6cdce75095 | ||
|
|
f699e76c56 | ||
|
|
a729329cd4 | ||
|
|
d5020ce9bb | ||
|
|
126868c251 | ||
|
|
b206e9fc95 | ||
|
|
4b6ff68464 | ||
|
|
b23a0febb5 | ||
|
|
05ad547341 | ||
|
|
f10af882a7 | ||
|
|
98f32ebcad | ||
|
|
e2c302836f | ||
|
|
f1d9642cf6 | ||
|
|
5c58e5b545 | ||
|
|
803cb335e1 | ||
|
|
ae4dde8255 | ||
|
|
cb34f68b1b | ||
|
|
96ef983cfb | ||
|
|
d8c3d67dfe | ||
|
|
5de5153663 | ||
|
|
1e747b6831 | ||
|
|
fbe9d16073 | ||
|
|
d02c0073a0 | ||
|
|
1090b9879c | ||
|
|
5a6af976cd | ||
|
|
55e39a5d30 | ||
|
|
c9b1ddfb59 | ||
|
|
f7dd696ffc | ||
|
|
70f210ac5d | ||
|
|
cad1c11f8b | ||
|
|
f7fa305e82 | ||
|
|
f96c51e854 | ||
|
|
c19705d3e5 | ||
|
|
1190511994 | ||
|
|
69ee7ef63c | ||
|
|
fc95e5a9a8 | ||
|
|
6ecc495d43 | ||
|
|
6e861001cf | ||
|
|
c56af08c7e | ||
|
|
e68abefe48 | ||
|
|
fd0635cb82 | ||
|
|
baa3cfb354 | ||
|
|
aea9bab853 | ||
|
|
48de609f53 | ||
|
|
71f4f87288 | ||
|
|
48b202c56b | ||
|
|
d975019a7b | ||
|
|
6009b5013b | ||
|
|
24979d7fbd | ||
|
|
b4bf42e377 | ||
|
|
f94819351a | ||
|
|
8da69c11d9 | ||
|
|
635a825095 | ||
|
|
bbffdbf56f | ||
|
|
1c30533d19 | ||
|
|
dcd80fe6ad | ||
|
|
525ab8d945 | ||
|
|
d8fb3f526a | ||
|
|
a55df1d111 | ||
|
|
2cf32ba38d | ||
|
|
c82907153e | ||
|
|
165403da67 | ||
|
|
0e4d94946e | ||
|
|
9f9c5abf35 | ||
|
|
6a3b10111f | ||
|
|
0a55f4bf83 | ||
|
|
493d66d991 | ||
|
|
268b495a29 | ||
|
|
180f4926f8 | ||
|
|
c853349b78 | ||
|
|
ee555e0da9 | ||
|
|
3dec4cc698 | ||
|
|
d7b2b94cec | ||
|
|
c9e88586aa | ||
|
|
1d641504b1 | ||
|
|
655e068b9b | ||
|
|
67a9f314cc | ||
|
|
ff2b58e8a3 | ||
|
|
a1482cb40e | ||
|
|
89111059f9 | ||
|
|
0ae823716a | ||
|
|
dab3f722e8 | ||
|
|
0dc1af0747 | ||
|
|
021206e052 | ||
|
|
cb09cf3734 | ||
|
|
f0525d6463 | ||
|
|
e22424ffa4 | ||
|
|
6e666c64e8 | ||
|
|
5f5f6ac539 | ||
|
|
3024c79f4f | ||
|
|
ba96d86dc2 | ||
|
|
40ec7195d1 | ||
|
|
f10dfa0c20 | ||
|
|
6a5473f6fe | ||
|
|
f79de6fbe8 | ||
|
|
ec4ee3132b | ||
|
|
1298f2b688 | ||
|
|
534a2f1d28 | ||
|
|
c8e95cf3c3 | ||
|
|
c4918a963c | ||
|
|
bf6f738d2e | ||
|
|
1605904eb1 | ||
|
|
138517f116 | ||
|
|
d4a4cb2e80 | ||
|
|
9a9dc328e3 | ||
|
|
50eea0a4f1 | ||
|
|
528a8b5b46 | ||
|
|
0db0bc53fa | ||
|
|
0297c267e9 | ||
|
|
5af85f24f6 | ||
|
|
5110a7578e | ||
|
|
5af28670f0 | ||
|
|
efa2b781dd | ||
|
|
979f151181 | ||
|
|
6f125f18c3 | ||
|
|
edba7051f0 | ||
|
|
fa1ae8d746 | ||
|
|
a476617432 | ||
|
|
ffac13bfef | ||
|
|
f877bf21ba | ||
|
|
4bc4882b1f | ||
|
|
084c17dc26 | ||
|
|
26c39d6822 | ||
|
|
aefc173227 | ||
|
|
bf44a1cce6 | ||
|
|
a76c6c653d | ||
|
|
f11205bba7 | ||
|
|
72d9c5019c | ||
|
|
58d66e3e97 | ||
|
|
43c88a2fab | ||
|
|
9ce64ec6e1 | ||
|
|
c749d6a7dc | ||
|
|
f3e6d35c98 | ||
|
|
0be539b8a5 | ||
|
|
0454a369e5 | ||
|
|
010025cbfa | ||
|
|
61cae0a9f8 | ||
|
|
9e83d9e68c | ||
|
|
248acd5e26 | ||
|
|
42c1f5601a | ||
|
|
9c1a673047 | ||
|
|
99b90f90ac | ||
|
|
6ead8d8b49 | ||
|
|
9b12232e9f | ||
|
|
c1ed1baaad | ||
|
|
ab34312089 | ||
|
|
a25d92fbb7 |
393
.github/workflows/build.yml
vendored
393
.github/workflows/build.yml
vendored
@@ -6,6 +6,7 @@ on:
|
||||
- 'master'
|
||||
- 'releases/**'
|
||||
- 'tests/**'
|
||||
- 'feature/**'
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -14,15 +15,22 @@ env:
|
||||
|
||||
jobs:
|
||||
|
||||
# Windows build
|
||||
win:
|
||||
# Windows MINGW build
|
||||
win_mingw:
|
||||
runs-on: windows-2022
|
||||
name: 🪟 Windows MINGW64
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
|
||||
env:
|
||||
CCACHE_DIR: "${{ github.workspace }}/.ccache"
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -33,8 +41,8 @@ jobs:
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
id: cache-ccache
|
||||
with:
|
||||
key: ${{ runner.os }}-ccache-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-ccache
|
||||
key: ${{ runner.os }}-mingw-ccache-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-mingw-ccache
|
||||
max-size: 1G
|
||||
|
||||
- name: 🟦 Install msys2
|
||||
@@ -81,11 +89,62 @@ jobs:
|
||||
run: |
|
||||
cd build
|
||||
ninja install
|
||||
|
||||
- name: 🪲 Create PDBs for MSI
|
||||
run: |
|
||||
cd build
|
||||
|
||||
mkdir cv2pdb
|
||||
cd cv2pdb
|
||||
wget https://github.com/rainers/cv2pdb/releases/download/v0.52/cv2pdb-0.52.zip
|
||||
unzip cv2pdb-0.52.zip
|
||||
cd ..
|
||||
|
||||
cv2pdb/cv2pdb.exe imhex.exe
|
||||
cv2pdb/cv2pdb.exe imhex-gui.exe
|
||||
cv2pdb/cv2pdb.exe libimhex.dll
|
||||
|
||||
for plugin in plugins/*.hexplug; do
|
||||
cv2pdb/cv2pdb.exe $plugin
|
||||
done
|
||||
|
||||
rm -rf cv2pdb
|
||||
|
||||
- name: 📦 Bundle MSI
|
||||
run: |
|
||||
cd build
|
||||
cpack
|
||||
mv ImHex-*.msi ../imhex-${{ env.IMHEX_VERSION }}-Windows-x86_64.msi
|
||||
|
||||
echo "ImHex checks for the existence of this file to determine if it is running in portable mode. You should not delete this file" > $PWD/install/PORTABLE
|
||||
|
||||
- name: 🪲 Create PDBs for ZIP
|
||||
run: |
|
||||
cd build/install
|
||||
|
||||
mkdir cv2pdb
|
||||
cd cv2pdb
|
||||
wget https://github.com/rainers/cv2pdb/releases/download/v0.52/cv2pdb-0.52.zip
|
||||
unzip cv2pdb-0.52.zip
|
||||
cd ..
|
||||
|
||||
cv2pdb/cv2pdb.exe imhex.exe
|
||||
cv2pdb/cv2pdb.exe imhex-gui.exe
|
||||
cv2pdb/cv2pdb.exe libimhex.dll
|
||||
|
||||
for plugin in plugins/*.hexplug; do
|
||||
cv2pdb/cv2pdb.exe $plugin
|
||||
done
|
||||
|
||||
rm -rf cv2pdb
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: ${{ github.event.repository.fork == false && github.event_name != 'pull_request' }}
|
||||
with:
|
||||
subject-path: |
|
||||
imhex-*.msi
|
||||
|
||||
- name: ⬆️ Upload Windows Installer
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -119,15 +178,93 @@ jobs:
|
||||
path: |
|
||||
build/install/*
|
||||
|
||||
win_msvc:
|
||||
runs-on: windows-2022
|
||||
name: 🪟 Windows MSVC
|
||||
|
||||
env:
|
||||
CCACHE_DIR: "${{ github.workspace }}/.ccache"
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: 🫧 Setup Visual Studio Dev Environment
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: amd64
|
||||
|
||||
- name: 📜 Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
id: cache-ccache
|
||||
with:
|
||||
key: ${{ runner.os }}-msvc-ccache-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-msvc-ccache
|
||||
max-size: 1G
|
||||
|
||||
- name: 📦 Install vcpkg
|
||||
uses: friendlyanon/setup-vcpkg@v1
|
||||
with: { committish: 7e21420f775f72ae938bdeb5e6068f722088f06a }
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
run: |
|
||||
cp dist/vcpkg.json vcpkg.json
|
||||
|
||||
- name: ⬇️ Install CMake and Ninja
|
||||
uses: lukka/get-cmake@latest
|
||||
|
||||
- name: ⬇️ Install .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '8.0.100'
|
||||
|
||||
- name: 📜 Set version variable
|
||||
run: |
|
||||
"IMHEX_VERSION=$(Get-Content VERSION -Raw)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
|
||||
# Windows cmake build
|
||||
- name: 🛠️ Configure CMake
|
||||
run: |
|
||||
mkdir -p build
|
||||
|
||||
cmake -G "Ninja" -B build `
|
||||
--preset vs2022 `
|
||||
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" `
|
||||
-DCMAKE_C_COMPILER="$($(Get-Command cl.exe).Path)" `
|
||||
-DCMAKE_CXX_COMPILER="$($(Get-Command cl.exe).Path)" `
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache `
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache `
|
||||
-DCMAKE_BUILD_TYPE="$env:BUILD_TYPE" `
|
||||
-DIMHEX_PATTERNS_PULL_MASTER=ON `
|
||||
-DIMHEX_COMMIT_HASH_LONG="$env:GITHUB_SHA" `
|
||||
-DIMHEX_COMMIT_BRANCH="$($env:GITHUB_REF -replace '.*/', '')" `
|
||||
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" `
|
||||
.
|
||||
|
||||
- name: 🛠️ Build
|
||||
run: |
|
||||
cd build
|
||||
ninja
|
||||
|
||||
win-plugin-template-test:
|
||||
runs-on: windows-2022
|
||||
name: 🧪 Plugin Template Test
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
needs: win
|
||||
|
||||
needs: win_mingw
|
||||
|
||||
env:
|
||||
IMHEX_SDK_PATH: "${{ github.workspace }}/out/sdk"
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout ImHex
|
||||
uses: actions/checkout@v4
|
||||
@@ -173,9 +310,13 @@ jobs:
|
||||
ninja
|
||||
|
||||
# MacOS build
|
||||
macos:
|
||||
macos-x86:
|
||||
runs-on: macos-13
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -205,10 +346,13 @@ jobs:
|
||||
max-size: 1G
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
env:
|
||||
# Make brew not display useless errors
|
||||
HOMEBREW_TESTS: 1
|
||||
run: |
|
||||
brew reinstall python --quiet || true
|
||||
brew link --overwrite --quiet python || true
|
||||
brew bundle --no-lock --quiet --file dist/Brewfile || true
|
||||
brew link --overwrite --quiet python 2>/dev/null || true
|
||||
brew bundle --no-lock --quiet --file dist/macOS/Brewfile || true
|
||||
rm -rf /usr/local/Cellar/capstone
|
||||
|
||||
- name: ⬇️ Install classic glfw
|
||||
@@ -299,19 +443,25 @@ jobs:
|
||||
|
||||
- name: 📦 Create DMG
|
||||
run: |
|
||||
set -x
|
||||
mkdir bundle
|
||||
mv build/install/ImHex.app bundle
|
||||
cd bundle
|
||||
ln -s /Applications Applications
|
||||
cd ..
|
||||
brew install graphicsmagick imagemagick
|
||||
git clone https://github.com/sindresorhus/create-dmg
|
||||
cd create-dmg
|
||||
npm i && npm -g i
|
||||
cd ../build/install
|
||||
for i in $(seq 1 10); do
|
||||
if hdiutil create -volname "ImHex" -srcfolder bundle -ov -format UDZO imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.suffix }}-x86_64.dmg; then
|
||||
echo "Created dmg after ${i} attempts"
|
||||
break
|
||||
fi
|
||||
sleep 10
|
||||
create-dmg ImHex.app || true
|
||||
if ls -d *.dmg 1>/dev/null 2>/dev/null; then
|
||||
break;
|
||||
fi
|
||||
done
|
||||
mv *.dmg ../../imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.suffix }}-x86_64.dmg
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: ${{ github.event.repository.fork == false && github.event_name != 'pull_request' }}
|
||||
with:
|
||||
subject-path: |
|
||||
./*.dmg
|
||||
|
||||
- name: ⬆️ Upload DMG
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -320,11 +470,13 @@ jobs:
|
||||
name: macOS DMG${{ matrix.suffix }} x86_64
|
||||
path: ./*.dmg
|
||||
|
||||
macos-arm64-build:
|
||||
macos-arm64:
|
||||
runs-on: ubuntu-24.04
|
||||
name: 🍎 macOS 13 arm64
|
||||
|
||||
outputs:
|
||||
IMHEX_VERSION: ${{ steps.build.outputs.IMHEX_VERSION }}
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -348,6 +500,7 @@ jobs:
|
||||
run: |
|
||||
echo "IMHEX_VERSION=`cat VERSION`" >> $GITHUB_OUTPUT
|
||||
docker buildx build . -f dist/macOS/arm64.Dockerfile --progress=plain --build-arg 'JOBS=4' --build-arg "BUILD_TYPE=$(BUILD_TYPE)" --build-context imhex=$(pwd) --output out
|
||||
cp resources/dist/macos/Entitlements.plist out/Entitlements.plist
|
||||
|
||||
- name: ⬆️ Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -367,9 +520,15 @@ jobs:
|
||||
macos-arm64-package:
|
||||
runs-on: macos-13
|
||||
name: 🍎 macOS 13 arm64 Packaging
|
||||
needs: macos-arm64-build
|
||||
needs: macos-arm64
|
||||
|
||||
env:
|
||||
IMHEX_VERSION: ${{ needs.macos-arm64-build.outputs.IMHEX_VERSION }}
|
||||
IMHEX_VERSION: ${{ needs.macos-arm64.outputs.IMHEX_VERSION }}
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
- name: ⬇️ Download artifact
|
||||
uses: actions/download-artifact@v4
|
||||
@@ -388,7 +547,7 @@ jobs:
|
||||
cd out
|
||||
mv imhex.app ImHex.app
|
||||
codesign --remove-signature ImHex.app
|
||||
codesign --force --deep --sign - ImHex.app
|
||||
codesign --force --deep --entitlements Entitlements.plist --sign - ImHex.app
|
||||
|
||||
- name: 📁 Fix permissions
|
||||
run: |
|
||||
@@ -404,19 +563,25 @@ jobs:
|
||||
|
||||
- name: 📦 Create DMG
|
||||
run: |
|
||||
set -x
|
||||
mkdir bundle
|
||||
mv out/ImHex.app bundle
|
||||
cd bundle
|
||||
ln -s /Applications Applications
|
||||
cd ..
|
||||
brew install graphicsmagick imagemagick
|
||||
git clone https://github.com/sindresorhus/create-dmg
|
||||
cd create-dmg
|
||||
npm i && npm -g i
|
||||
cd ../out
|
||||
for i in $(seq 1 10); do
|
||||
if hdiutil create -volname "ImHex" -srcfolder bundle -ov -format UDZO imhex-${{ env.IMHEX_VERSION }}-macOS-arm64.dmg; then
|
||||
echo "Created dmg after ${i} attempts"
|
||||
break
|
||||
fi
|
||||
sleep 10
|
||||
create-dmg ImHex.app || true
|
||||
if ls -d *.dmg 1>/dev/null 2>/dev/null; then
|
||||
break;
|
||||
fi
|
||||
done
|
||||
mv *.dmg ../imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.suffix }}-arm64.dmg
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: ${{ github.event.repository.fork == false && github.event_name != 'pull_request' }}
|
||||
with:
|
||||
subject-path: |
|
||||
./*.dmg
|
||||
|
||||
- name: ⬆️ Upload DMG
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -441,6 +606,10 @@ jobs:
|
||||
image: "ubuntu:${{ matrix.release_num }}"
|
||||
options: --privileged
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
- name: ⬇️ Install setup dependencies
|
||||
run: apt update && apt install -y git curl
|
||||
@@ -498,9 +667,16 @@ jobs:
|
||||
- name: 📦 Bundle DEB
|
||||
run: |
|
||||
cp -r build/DEBIAN build/DebDir
|
||||
dpkg-deb -Zgzip --build build/DebDir
|
||||
dpkg-deb -Zzstd --build build/DebDir
|
||||
mv build/DebDir.deb imhex-${{ env.IMHEX_VERSION }}-Ubuntu-${{ matrix.release_num }}-x86_64.deb
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: ${{ github.event.repository.fork == false && github.event_name != 'pull_request' }}
|
||||
with:
|
||||
subject-path: |
|
||||
./*.deb
|
||||
|
||||
- name: ⬆️ Upload DEB
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -510,8 +686,26 @@ jobs:
|
||||
|
||||
# AppImage build
|
||||
appimage:
|
||||
runs-on: ubuntu-24.04
|
||||
name: ⬇️ AppImage
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- architecture: "x86_64"
|
||||
architecture_package: "amd64"
|
||||
architecture_appimage_builder: "x86_64"
|
||||
image: ubuntu-24.04
|
||||
- architecture: "arm64"
|
||||
architecture_package: "arm64"
|
||||
architecture_appimage_builder: "aarch64"
|
||||
image: ubuntu-24.04-arm
|
||||
|
||||
runs-on: ${{ matrix.image }}
|
||||
name: ⬇️ AppImage ${{ matrix.architecture }}
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -522,8 +716,8 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: cache
|
||||
key: appimage-ccache-${{ github.run_id }}
|
||||
restore-keys: appimage-cache
|
||||
key: appimage-ccache-${{ matrix.architecture }}-${{ github.run_id }}
|
||||
restore-keys: appimage-ccache-${{ matrix.architecture }}
|
||||
|
||||
- name: 🐳 Inject /cache into docker
|
||||
uses: reproducible-containers/buildkit-cache-dance@v2
|
||||
@@ -533,22 +727,31 @@ jobs:
|
||||
|
||||
- name: 🛠️ Build using docker
|
||||
run: |
|
||||
docker buildx build . -f dist/appimage/Dockerfile --progress=plain --build-arg "BUILD_TYPE=$BUILD_TYPE" \
|
||||
--build-arg "GIT_COMMIT_HASH=$GITHUB_SHA" --build-arg "GIT_BRANCH=${GITHUB_REF##*/}" --output out
|
||||
docker buildx build . -f dist/AppImage/Dockerfile --progress=plain --build-arg "BUILD_TYPE=$BUILD_TYPE" \
|
||||
--build-arg "GIT_COMMIT_HASH=$GITHUB_SHA" --build-arg "GIT_BRANCH=${GITHUB_REF##*/}" \
|
||||
--build-arg "ARCHITECTURE_PACKAGE=${{ matrix.architecture_package }}" --build-arg "ARCHITECTURE_FILE_NAME=${{ matrix.architecture }}" --build-arg "ARCHITECTURE_APPIMAGE_BUILDER=${{ matrix.architecture_appimage_builder }}" \
|
||||
--output out
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: ${{ github.event.repository.fork == false && github.event_name != 'pull_request' }}
|
||||
with:
|
||||
subject-path: |
|
||||
out/*.AppImage
|
||||
out/*.AppImage.zsync
|
||||
|
||||
- name: ⬆️ Upload AppImage
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: Linux AppImage x86_64
|
||||
name: Linux AppImage ${{ matrix.architecture }}
|
||||
path: 'out/*.AppImage'
|
||||
|
||||
- name: ⬆️ Upload AppImage zsync
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: Linux AppImage zsync x86_64
|
||||
name: Linux AppImage zsync ${{ matrix.architecture }}
|
||||
path: 'out/*.AppImage.zsync'
|
||||
|
||||
# ArchLinux build
|
||||
@@ -559,6 +762,10 @@ jobs:
|
||||
container:
|
||||
image: archlinux:base-devel
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
- name: ⬇️ Update all packages
|
||||
run: |
|
||||
@@ -642,6 +849,13 @@ jobs:
|
||||
rm *imhex-bin-debug* # rm debug package which is created for some reason
|
||||
mv *.pkg.tar.zst imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: ${{ github.event.repository.fork == false && github.event_name != 'pull_request' }}
|
||||
with:
|
||||
subject-path: |
|
||||
build/imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst
|
||||
|
||||
- name: ⬆️ Upload imhex-archlinux.pkg.tar.zst
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -680,6 +894,10 @@ jobs:
|
||||
image: "almalinux:9"
|
||||
options: --privileged --pid=host --security-opt apparmor=unconfined
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
# This, together with the `--pid=host --security-opt apparmor=unconfined` docker options is required to allow
|
||||
# fedpkg to work inside a Docker container running on Ubuntu again.
|
||||
@@ -775,6 +993,13 @@ jobs:
|
||||
mv $GITHUB_WORKSPACE/results_imhex/${{ env.IMHEX_VERSION }}/*/imhex-${{ env.IMHEX_VERSION }}-0.*.x86_64.rpm \
|
||||
$GITHUB_WORKSPACE/imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.rpm
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: ${{ github.event.repository.fork == false && github.event_name != 'pull_request' }}
|
||||
with:
|
||||
subject-path: |
|
||||
imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.rpm
|
||||
|
||||
- name: ⬆️ Upload RPM
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -782,3 +1007,85 @@ jobs:
|
||||
name: ${{ matrix.name }} ${{ matrix.release_num }} RPM x86_64
|
||||
path: |
|
||||
imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.rpm
|
||||
|
||||
webassembly-build:
|
||||
runs-on: ubuntu-24.04
|
||||
name: 🌍 Web
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
actions: write
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: 📁 Restore docker /cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: cache
|
||||
key: web-cache-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: 🐳 Inject /cache into docker
|
||||
uses: reproducible-containers/buildkit-cache-dance@v2
|
||||
with:
|
||||
cache-source: cache
|
||||
cache-target: /cache
|
||||
|
||||
- name: 🛠️ Build using docker
|
||||
run: |
|
||||
docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out --target raw
|
||||
|
||||
- name: 🔨 Fix permissions
|
||||
run: |
|
||||
chmod -c -R +rX "out/"
|
||||
|
||||
- name: ⬆️ Upload artifacts
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: out/
|
||||
|
||||
- name: 🔨 Copy necessary files
|
||||
run: |
|
||||
cp dist/web/serve.py out/start_imhex_web.py
|
||||
|
||||
- name: ⬆️ Upload package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: ImHex Web
|
||||
path: out/*
|
||||
|
||||
# See https://github.com/actions/cache/issues/342#issuecomment-1711054115
|
||||
- name: 🗑️ Delete old cache
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache || true
|
||||
gh actions-cache delete "build-web-cache" --confirm || true
|
||||
|
||||
webassembly-deploy:
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
actions: write
|
||||
name: 📃 Deploy to GitHub Pages
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
if: ${{ github.ref == 'refs/heads/master' && github.event.repository.fork == false }}
|
||||
needs: webassembly-build
|
||||
|
||||
steps:
|
||||
- name: 🌍 Deploy WebAssembly Build to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
|
||||
- name: 🗑️ Delete artifact
|
||||
uses: geekyeggo/delete-artifact@v5
|
||||
with:
|
||||
name: github-pages
|
||||
|
||||
79
.github/workflows/build_web.yml
vendored
79
.github/workflows/build_web.yml
vendored
@@ -1,79 +0,0 @@
|
||||
name: Build for the web
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/**'
|
||||
- 'tests/**'
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
actions: write
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
name: 🌍 WebAssembly
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: 📁 Restore docker /cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: cache
|
||||
key: web-cache-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: 🐳 Inject /cache into docker
|
||||
uses: reproducible-containers/buildkit-cache-dance@v2
|
||||
with:
|
||||
cache-source: cache
|
||||
cache-target: /cache
|
||||
|
||||
- name: 🛠️ Build using docker
|
||||
run: |
|
||||
docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out --target raw
|
||||
|
||||
- name: 🔨 Fix permissions
|
||||
run: |
|
||||
chmod -c -R +rX "out/"
|
||||
|
||||
- name: ⬆️ Upload artifacts
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: out/
|
||||
|
||||
# See https://github.com/actions/cache/issues/342#issuecomment-1711054115
|
||||
- name: 🗑️ Delete old cache
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache || true
|
||||
gh actions-cache delete "build-web-cache" --confirm || true
|
||||
|
||||
deploy:
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
|
||||
name: 📃 Deploy to GitHub Pages
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
if: ${{ github.ref == 'refs/heads/master' && github.event.repository.fork == false }}
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- name: 🌍 Deploy
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
@@ -63,7 +63,7 @@ jobs:
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
|
||||
release-upload-artifacts:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
name: Release Upload Artifacts
|
||||
|
||||
steps:
|
||||
@@ -117,6 +117,7 @@ jobs:
|
||||
run: |
|
||||
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip
|
||||
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip
|
||||
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-web.zip
|
||||
|
||||
- name: ⬆️ Upload everything to release
|
||||
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
|
||||
|
||||
2
.github/workflows/stale_issues.yml
vendored
2
.github/workflows/stale_issues.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
|
||||
jobs:
|
||||
close-issues:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
1
.github/workflows/tests.yml
vendored
1
.github/workflows/tests.yml
vendored
@@ -6,6 +6,7 @@ on:
|
||||
- 'master'
|
||||
- 'releases/**'
|
||||
- 'tests/**'
|
||||
- 'feature/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'master'
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -7,6 +7,7 @@ build*/
|
||||
local/
|
||||
venv/
|
||||
.cache/
|
||||
install/
|
||||
|
||||
*.mgc
|
||||
*.kdev4
|
||||
@@ -14,3 +15,6 @@ imgui.ini
|
||||
.DS_Store
|
||||
CMakeUserPresets.json
|
||||
Brewfile.lock.json
|
||||
|
||||
.vs/
|
||||
vcpkg.json
|
||||
|
||||
5
.gitmodules
vendored
5
.gitmodules
vendored
@@ -43,4 +43,7 @@
|
||||
|
||||
[submodule "lib/third_party/HashLibPlus"]
|
||||
path = lib/third_party/HashLibPlus
|
||||
url = https://github.com/WerWolv/HashLibPlus
|
||||
url = https://github.com/WerWolv/HashLibPlus
|
||||
[submodule "lib/external/disassembler"]
|
||||
path = lib/external/disassembler
|
||||
url = https://github.com/WerWolv/Disassembler
|
||||
|
||||
@@ -81,7 +81,6 @@ if (IMHEX_ENABLE_UNIT_TESTS)
|
||||
endif ()
|
||||
|
||||
# Configure more resources that will be added to the install package
|
||||
generatePDBs()
|
||||
generateSDKDirectory()
|
||||
|
||||
# Handle package generation
|
||||
|
||||
@@ -45,6 +45,15 @@
|
||||
|
||||
"IMHEX_IDE_HELPERS_OVERRIDE_XCODE_COMPILER": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "vs2022",
|
||||
"displayName": "Visual Studio 2022",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build/${presetName}",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
|
||||
@@ -27,6 +27,11 @@ chmod +x imhex-*.AppImage
|
||||
./imhex-*.AppImage
|
||||
```
|
||||
|
||||
If you're experiencing glib / libgtk assertion failures, you might need to setup your `XDG_DATA_DIRS` env var correctly. In this case, run the following command before executing the AppImage. (See issue [ImHex/#2038](https://github.com/WerWolv/ImHex/issues/2038))
|
||||
```bash
|
||||
export XDG_DATA_DIRS="/usr/local/share:/usr/share"
|
||||
```
|
||||
|
||||
#### Flatpak
|
||||
To install the Flatpak, make sure you have the Flathub repository added to your system. Then simply run the following command:
|
||||
|
||||
|
||||
16
README.md
16
README.md
@@ -38,8 +38,8 @@ If you like my work, please consider supporting me on GitHub Sponsors, Patreon o
|
||||
</p>
|
||||
|
||||
## Screenshots
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
<details>
|
||||
<summary><strong>More Screenshots</strong></summary>
|
||||
@@ -328,12 +328,12 @@ To use ImHex, the following minimal system requirements need to be met.
|
||||
- RHEL/AlmaLinux
|
||||
- Arch Linux
|
||||
- Basically any other distro will work as well when compiling ImHex from sources.
|
||||
- **CPU**: x86_64 (64 Bit)
|
||||
- **CPU**: Officially supported are x86_64 and ARM64, though any Little Endian 64 bit CPU should work.
|
||||
- **GPU**: OpenGL 3.0 or higher
|
||||
- Integrated Intel HD iGPUs are supported, however certain drivers are known to cause various graphical artifacts, especially on Windows. Use at your own risk.
|
||||
- In case you don't have a GPU available, there are software rendered releases available for Windows and macOS
|
||||
- **RAM**: 256MB, more may be required for more complicated analysis
|
||||
- **Storage**: 150MB
|
||||
- **RAM**: ~150MiB, more is required for more complex analysis
|
||||
- **Storage**: 150MiB
|
||||
|
||||
## Installing
|
||||
|
||||
@@ -342,8 +342,10 @@ Information on how to install ImHex can be found in the [Install](/INSTALL.md) g
|
||||
## Compiling
|
||||
|
||||
To compile ImHex on any platform, GCC (or Clang) is required with a version that supports C++23 or higher.
|
||||
On macOS, Clang is also required to compile some ObjC code.
|
||||
All releases are being built using latest available GCC.
|
||||
Windows and Linux releases are being built using latest available GCC.
|
||||
MacOS releases are being built using latest available LLVM Clang.
|
||||
|
||||
Important to note is, the MSVC and AppleClang compilers are both **NOT** supported since they're both generally severely outdated and lack features GCC and LLVM Clang have.
|
||||
|
||||
> [!NOTE]
|
||||
> Many dependencies are bundled into the repository using submodules so make sure to clone it using the `--recurse-submodules` option.
|
||||
|
||||
@@ -1,3 +1,73 @@
|
||||
# Some libraries we use set the BUILD_SHARED_LIBS variable to ON, which causes CMake to
|
||||
# display a warning about options being set using set() instead of option().
|
||||
# Explicitly set the policy to NEW to suppress the warning.
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
||||
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW)
|
||||
|
||||
if (POLICY CMP0177)
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0177 OLD)
|
||||
cmake_policy(SET CMP0177 OLD)
|
||||
endif()
|
||||
|
||||
function(getTarget target type)
|
||||
get_target_property(IMPORTED_TARGET ${target} IMPORTED)
|
||||
if (IMPORTED_TARGET)
|
||||
set(${type} INTERFACE PARENT_SCOPE)
|
||||
else()
|
||||
set(${type} PRIVATE PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(addCFlag)
|
||||
if (ARGC EQUAL 1)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:C>:${ARGV0}>)
|
||||
elseif (ARGC EQUAL 2)
|
||||
getTarget(${ARGV1} TYPE)
|
||||
target_compile_options(${ARGV1} ${TYPE} $<$<COMPILE_LANGUAGE:C>:${ARGV0}>)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(addCXXFlag)
|
||||
if (ARGC EQUAL 1)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:${ARGV0}>)
|
||||
elseif (ARGC EQUAL 2)
|
||||
getTarget(${ARGV1} TYPE)
|
||||
target_compile_options(${ARGV1} ${TYPE} $<$<COMPILE_LANGUAGE:CXX>:${ARGV0}>)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(addObjCFlag)
|
||||
if (ARGC EQUAL 1)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:OBJC>:${ARGV0}>)
|
||||
elseif (ARGC EQUAL 2)
|
||||
getTarget(${ARGV1} TYPE)
|
||||
target_compile_options(${ARGV1} ${TYPE} $<$<COMPILE_LANGUAGE:OBJC>:${ARGV0}>)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(addLinkerFlag)
|
||||
if (ARGC EQUAL 1)
|
||||
add_link_options(${ARGV0})
|
||||
elseif (ARGC EQUAL 2)
|
||||
getTarget(${ARGV1} TYPE)
|
||||
target_link_options(${ARGV1} ${TYPE} ${ARGV0})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(addCCXXFlag)
|
||||
addCFlag(${ARGV0} ${ARGV1})
|
||||
addCXXFlag(${ARGV0} ${ARGV1})
|
||||
endfunction()
|
||||
|
||||
function(addCommonFlag)
|
||||
addCFlag(${ARGV0} ${ARGV1})
|
||||
addCXXFlag(${ARGV0} ${ARGV1})
|
||||
addObjCFlag(${ARGV0} ${ARGV1})
|
||||
endfunction()
|
||||
|
||||
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Disable deprecated warnings" FORCE)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
if(IMHEX_STRIP_RELEASE)
|
||||
@@ -59,7 +129,9 @@ macro(detectOS)
|
||||
set(CMAKE_INSTALL_LIBDIR ".")
|
||||
set(PLUGINS_INSTALL_LOCATION "plugins")
|
||||
add_compile_definitions(WIN32_LEAN_AND_MEAN)
|
||||
add_compile_definitions(NOMINMAX)
|
||||
add_compile_definitions(UNICODE)
|
||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||||
elseif (APPLE)
|
||||
add_compile_definitions(OS_MACOS)
|
||||
set(CMAKE_INSTALL_BINDIR ".")
|
||||
@@ -110,7 +182,7 @@ macro(configurePackingResources)
|
||||
set(CPACK_WIX_PRODUCT_ICON "${PROJECT_SOURCE_DIR}/resources/dist/windows/icon.ico")
|
||||
set(CPACK_WIX_UI_BANNER "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_banner.png")
|
||||
set(CPACK_WIX_UI_DIALOG "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_dialog.png")
|
||||
set(CPACK_WIX_CULTURES "en-US;de-DE;ja-JP;it-IT;pt-BR;zh-CN;zh-TW")
|
||||
set(CPACK_WIX_CULTURES "en-US;de-DE;ja-JP;it-IT;pt-BR;zh-CN;zh-TW;ru-RU")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "ImHex")
|
||||
set_property(INSTALL "$<TARGET_FILE_NAME:main>"
|
||||
PROPERTY CPACK_START_MENU_SHORTCUTS "ImHex"
|
||||
@@ -226,7 +298,7 @@ macro(createPackage)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.mime.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages RENAME imhex.xml)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.png)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.svg DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.svg)
|
||||
downloadImHexPatternsFiles("./share/imhex")
|
||||
|
||||
# install AppStream file
|
||||
@@ -257,6 +329,7 @@ macro(createPackage)
|
||||
|
||||
install(FILES ${IMHEX_ICON} DESTINATION "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Resources")
|
||||
install(TARGETS main BUNDLE DESTINATION ".")
|
||||
install(TARGETS updater BUNDLE DESTINATION ".")
|
||||
|
||||
# Update library references to make the bundle portable
|
||||
postprocess_bundle(imhex_all main)
|
||||
@@ -309,6 +382,10 @@ endfunction()
|
||||
macro(configureCMake)
|
||||
message(STATUS "Configuring ImHex v${IMHEX_VERSION}")
|
||||
|
||||
if (DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||
message(STATUS "Using toolchain file: \"${CMAKE_TOOLCHAIN_FILE}\"")
|
||||
endif()
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE BOOL "Enable position independent code for all targets" FORCE)
|
||||
|
||||
# Configure use of recommended build tools
|
||||
@@ -343,9 +420,9 @@ macro(configureCMake)
|
||||
if (LD_LLD_PATH)
|
||||
set(CMAKE_LINKER ${LD_LLD_PATH})
|
||||
|
||||
if (NOT XCODE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=lld")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=lld")
|
||||
if (NOT XCODE AND NOT MSVC)
|
||||
set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} -fuse-ld=lld)
|
||||
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -fuse-ld=lld)
|
||||
endif()
|
||||
else ()
|
||||
message(WARNING "lld not found, using default linker!")
|
||||
@@ -370,15 +447,6 @@ macro(configureCMake)
|
||||
message(WARNING "LTO is not supported: ${output_error}")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Some libraries we use set the BUILD_SHARED_LIBS variable to ON, which causes CMake to
|
||||
# display a warning about options being set using set() instead of option().
|
||||
# Explicitly set the policy to NEW to suppress the warning.
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
||||
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW)
|
||||
|
||||
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Disable deprecated warnings" FORCE)
|
||||
endmacro()
|
||||
|
||||
function(configureProject)
|
||||
@@ -434,6 +502,8 @@ function(verifyCompiler)
|
||||
message(FATAL_ERROR "ImHex requires GCC 12.0.0 or newer. Please use the latest GCC version.")
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "17.0.0")
|
||||
message(FATAL_ERROR "ImHex requires Clang 17.0.0 or newer. Please use the latest Clang version.")
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
|
||||
elseif (NOT (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
|
||||
message(FATAL_ERROR "ImHex can only be compiled with GCC or Clang. ${CMAKE_CXX_COMPILER_ID} is not supported.")
|
||||
endif()
|
||||
@@ -501,16 +571,16 @@ function(downloadImHexPatternsFiles dest)
|
||||
|
||||
# Maybe patterns are cloned to a subdirectory
|
||||
if (NOT EXISTS ${imhex_patterns_SOURCE_DIR})
|
||||
set(imhex_patterns_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ImHex-Patterns")
|
||||
set(imhex_patterns_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ImHex-Patterns")
|
||||
endif()
|
||||
|
||||
# Or a sibling directory
|
||||
if (NOT EXISTS ${imhex_patterns_SOURCE_DIR})
|
||||
set(imhex_patterns_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../ImHex-Patterns")
|
||||
set(imhex_patterns_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../ImHex-Patterns")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if (NOT EXISTS ${imhex_patterns_SOURCE_DIR})
|
||||
if (NOT EXISTS ${imhex_patterns_SOURCE_DIR})
|
||||
message(WARNING "Failed to locate ImHex-Patterns repository, some resources will be missing during install!")
|
||||
elseif(XCODE)
|
||||
# The Xcode build has multiple configurations, which each need a copy of these files
|
||||
@@ -553,34 +623,64 @@ macro(setupDebugCompressionFlag)
|
||||
elseif (COMPRESS_AVAILABLE_COMPILER AND COMPRESS_AVAILABLE_LINKER)
|
||||
message("Using default compression for debug info because both compiler and linker support it")
|
||||
set(DEBUG_COMPRESSION_FLAG "-gz" CACHE STRING "Cache to use for debug info compression")
|
||||
else()
|
||||
set(DEBUG_COMPRESSION_FLAG "" CACHE STRING "Cache to use for debug info compression")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} ${DEBUG_COMPRESSION_FLAG}")
|
||||
addCommonFlag(${DEBUG_COMPRESSION_FLAG})
|
||||
endmacro()
|
||||
|
||||
macro(setupCompilerFlags target)
|
||||
# IMHEX_COMMON_FLAGS: flags common for C, C++, Objective C, etc.. compilers
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
addCommonFlag("/W4" ${target})
|
||||
addCommonFlag("/wd4127" ${target}) # conditional expression is constant
|
||||
addCommonFlag("/wd4242" ${target}) # 'identifier': conversion from 'type1' to 'type2', possible loss of data
|
||||
addCommonFlag("/wd4244" ${target}) # 'conversion': conversion from 'type1' to 'type2', possible loss of data
|
||||
addCommonFlag("/wd4267" ${target}) # 'var': conversion from 'size_t' to 'type', possible loss of data
|
||||
addCommonFlag("/wd4305" ${target}) # truncation from 'double' to 'float'
|
||||
addCommonFlag("/wd4996" ${target}) # 'function': was declared deprecated
|
||||
|
||||
if (IMHEX_STRICT_WARNINGS)
|
||||
addCommonFlag("/WX" ${target})
|
||||
endif()
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
addCommonFlag("-Wall" ${target})
|
||||
addCommonFlag("-Wextra" ${target})
|
||||
addCommonFlag("-Wpedantic" ${target})
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
# Define strict compilation flags
|
||||
if (IMHEX_STRICT_WARNINGS)
|
||||
set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} -Wall -Wextra -Wpedantic -Werror")
|
||||
addCommonFlag("-Werror" ${target})
|
||||
endif()
|
||||
|
||||
if (UNIX AND NOT APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} -rdynamic")
|
||||
addCommonFlag("-rdynamic" ${target})
|
||||
endif()
|
||||
|
||||
set(IMHEX_CXX_FLAGS "-fexceptions -frtti")
|
||||
addCXXFlag("-fexceptions" ${target})
|
||||
addCXXFlag("-frtti" ${target})
|
||||
|
||||
# Disable some warnings
|
||||
set(IMHEX_C_CXX_FLAGS "-Wno-array-bounds -Wno-deprecated-declarations -Wno-unknown-pragmas")
|
||||
addCCXXFlag("-Wno-array-bounds" ${target})
|
||||
addCCXXFlag("-Wno-deprecated-declarations" ${target})
|
||||
addCCXXFlag("-Wno-unknown-pragmas" ${target})
|
||||
|
||||
# Enable hardening flags
|
||||
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
addCommonFlag("-U_FORTIFY_SOURCE" ${target})
|
||||
addCommonFlag("-D_FORTIFY_SOURCE=3" ${target})
|
||||
|
||||
if (NOT EMSCRIPTEN)
|
||||
addCommonFlag("-fstack-protector-strong" ${target})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
if (IMHEX_ENABLE_UNITY_BUILD AND WIN32)
|
||||
set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} -Wa,-mbig-obj")
|
||||
if (WIN32)
|
||||
addLinkerFlag("-Wa,mbig-obj" ${target})
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
@@ -588,36 +688,51 @@ macro(setupCompilerFlags target)
|
||||
execute_process(COMMAND brew --prefix llvm OUTPUT_VARIABLE LLVM_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
|
||||
set(IMHEX_C_CXX_FLAGS "-Wno-unknown-warning-option")
|
||||
addCCXXFlag("-Wno-unknown-warning-option" ${target})
|
||||
|
||||
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()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
addCommonFlag("/bigobj" ${target})
|
||||
addCFlag("/std:clatest" ${target})
|
||||
addCXXFlag("/std:c++latest" ${target})
|
||||
endif()
|
||||
|
||||
# Disable some warnings for gcc
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
set(IMHEX_C_CXX_FLAGS "${IMHEX_C_CXX_FLAGS} -Wno-restrict -Wno-stringop-overread -Wno-stringop-overflow -Wno-dangling-reference")
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
addCCXXFlag("-Wno-restrict" ${target})
|
||||
addCCXXFlag("-Wno-stringop-overread" ${target})
|
||||
addCCXXFlag("-Wno-stringop-overflow" ${target})
|
||||
addCCXXFlag("-Wno-dangling-reference" ${target})
|
||||
endif()
|
||||
|
||||
# Define emscripten-specific disabled warnings
|
||||
if (EMSCRIPTEN)
|
||||
set(IMHEX_C_CXX_FLAGS "${IMHEX_C_CXX_FLAGS} -pthread -Wno-dollar-in-identifier-extension -Wno-pthreads-mem-growth")
|
||||
addCCXXFlag("-pthread" ${target})
|
||||
addCCXXFlag("-Wno-dollar-in-identifier-extension" ${target})
|
||||
addCCXXFlag("-Wno-pthreads-mem-growth" ${target})
|
||||
endif ()
|
||||
|
||||
if (IMHEX_COMPRESS_DEBUG_INFO)
|
||||
setupDebugCompressionFlag()
|
||||
endif()
|
||||
|
||||
# Set actual CMake flags
|
||||
set_target_properties(${target} PROPERTIES COMPILE_FLAGS "${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS} ${IMHEX_CXX_FLAGS}")
|
||||
set(CMAKE_OBJC_FLAGS "${CMAKE_OBJC_FLAGS} ${IMHEX_COMMON_FLAGS}")
|
||||
|
||||
# Only generate minimal debug information for stacktraces in RelWithDebInfo builds
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -g1")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g1")
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
# Add flags for debug info in inline functions
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -gstatement-frontiers -ginline-points")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -gstatement-frontiers -ginline-points")
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
addCCXXFlag("-g1" ${target})
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
# Add flags for debug info in inline functions
|
||||
addCCXXFlag("-gstatement-frontiers" ${target})
|
||||
addCCXXFlag("-ginline-points" ${target})
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
@@ -649,6 +764,7 @@ macro(addBundledLibraries)
|
||||
set(FPHSA_NAME_MISMATCHED ON CACHE BOOL "")
|
||||
|
||||
if(NOT USE_SYSTEM_FMT)
|
||||
set(FMT_INSTALL OFF CACHE BOOL "Disable install targets for libfmt" FORCE)
|
||||
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/fmt EXCLUDE_FROM_ALL)
|
||||
set(FMT_LIBRARIES fmt::fmt-header-only)
|
||||
else()
|
||||
@@ -688,8 +804,8 @@ macro(addBundledLibraries)
|
||||
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/lunasvg EXCLUDE_FROM_ALL)
|
||||
set(LUNASVG_LIBRARIES lunasvg)
|
||||
else()
|
||||
find_package(LunaSVG REQUIRED)
|
||||
set(LUNASVG_LIBRARIES lunasvg)
|
||||
find_package(lunasvg REQUIRED)
|
||||
set(LUNASVG_LIBRARIES lunasvg::lunasvg)
|
||||
endif()
|
||||
|
||||
if (NOT USE_SYSTEM_LLVM)
|
||||
@@ -721,13 +837,10 @@ macro(addBundledLibraries)
|
||||
set(LIBPL_BUILD_CLI_AS_EXECUTABLE OFF CACHE BOOL "" FORCE)
|
||||
set(LIBPL_ENABLE_PRECOMPILED_HEADERS ${IMHEX_ENABLE_PRECOMPILED_HEADERS} CACHE BOOL "" FORCE)
|
||||
|
||||
if (WIN32)
|
||||
set(LIBPL_SHARED_LIBRARY ON CACHE BOOL "" FORCE)
|
||||
else()
|
||||
set(LIBPL_SHARED_LIBRARY OFF CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
set(LIBPL_SHARED_LIBRARY OFF CACHE BOOL "" FORCE)
|
||||
|
||||
add_subdirectory(${EXTERNAL_LIBS_FOLDER}/pattern_language EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(${EXTERNAL_LIBS_FOLDER}/disassembler EXCLUDE_FROM_ALL)
|
||||
|
||||
if (LIBPL_SHARED_LIBRARY)
|
||||
install(
|
||||
@@ -784,70 +897,20 @@ function(enableUnityBuild TARGET)
|
||||
endif ()
|
||||
endfunction()
|
||||
|
||||
function(generatePDBs)
|
||||
if (NOT IMHEX_GENERATE_PDBS)
|
||||
return()
|
||||
endif ()
|
||||
|
||||
if (NOT WIN32 OR CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
return()
|
||||
endif ()
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
cv2pdb
|
||||
URL "https://github.com/rainers/cv2pdb/releases/download/v0.52/cv2pdb-0.52.zip"
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP ON
|
||||
)
|
||||
FetchContent_Populate(cv2pdb)
|
||||
|
||||
set(PDBS_TO_GENERATE main main-forwarder libimhex ${PLUGINS})
|
||||
foreach (PDB ${PDBS_TO_GENERATE})
|
||||
if (PDB STREQUAL "main")
|
||||
set(GENERATED_PDB imhex)
|
||||
elseif (PDB STREQUAL "main-forwarder")
|
||||
set(GENERATED_PDB imhex-gui)
|
||||
elseif (PDB STREQUAL "libimhex")
|
||||
set(GENERATED_PDB libimhex)
|
||||
else ()
|
||||
set(GENERATED_PDB plugins/${PDB})
|
||||
endif ()
|
||||
|
||||
if (IMHEX_REPLACE_DWARF_WITH_PDB)
|
||||
set(PDB_OUTPUT_PATH ${CMAKE_BINARY_DIR}/${GENERATED_PDB})
|
||||
else ()
|
||||
set(PDB_OUTPUT_PATH)
|
||||
endif()
|
||||
|
||||
add_custom_target(${PDB}_pdb DEPENDS ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb)
|
||||
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMAND
|
||||
(
|
||||
${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb &&
|
||||
${cv2pdb_SOURCE_DIR}/cv2pdb64.exe $<TARGET_FILE:${PDB}> ${PDB_OUTPUT_PATH} &&
|
||||
${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/${GENERATED_PDB}
|
||||
) || (exit 0)
|
||||
COMMAND_EXPAND_LISTS)
|
||||
|
||||
install(FILES ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb DESTINATION ".")
|
||||
|
||||
add_dependencies(imhex_all ${PDB}_pdb)
|
||||
endforeach ()
|
||||
function(setSDKPaths)
|
||||
if (WIN32)
|
||||
set(SDK_PATH "./sdk" PARENT_SCOPE)
|
||||
elseif (APPLE)
|
||||
set(SDK_PATH "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Resources/sdk" PARENT_SCOPE)
|
||||
else()
|
||||
set(SDK_PATH "share/imhex/sdk" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
set(SDK_BUILD_PATH "${CMAKE_BINARY_DIR}/sdk" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(generateSDKDirectory)
|
||||
if (WIN32)
|
||||
set(SDK_PATH "./sdk")
|
||||
elseif (APPLE)
|
||||
set(SDK_PATH "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Resources/sdk")
|
||||
else()
|
||||
set(SDK_PATH "share/imhex/sdk")
|
||||
endif()
|
||||
|
||||
set(SDK_BUILD_PATH "${CMAKE_BINARY_DIR}/sdk")
|
||||
|
||||
setSDKPaths()
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/libimhex DESTINATION "${SDK_PATH}/lib" PATTERN "**/source/*" EXCLUDE)
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/external DESTINATION "${SDK_PATH}/lib")
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/imgui DESTINATION "${SDK_PATH}/lib/third_party" PATTERN "**/source/*" EXCLUDE)
|
||||
@@ -865,6 +928,18 @@ function(generateSDKDirectory)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/cmake/build_helpers.cmake DESTINATION "${SDK_PATH}/cmake")
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/sdk/ DESTINATION "${SDK_PATH}")
|
||||
install(TARGETS libimhex ARCHIVE DESTINATION "${SDK_PATH}/lib")
|
||||
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/plugins/ui/include DESTINATION "${SDK_PATH}/lib/ui/include")
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/plugins/ui/CMakeLists.txt DESTINATION "${SDK_PATH}/lib/ui/")
|
||||
if (WIN32)
|
||||
install(TARGETS ui ARCHIVE DESTINATION "${SDK_PATH}/lib")
|
||||
endif()
|
||||
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/plugins/fonts/include DESTINATION "${SDK_PATH}/lib/fonts/include")
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/plugins/fonts/CMakeLists.txt DESTINATION "${SDK_PATH}/lib/fonts/")
|
||||
if (WIN32)
|
||||
install(TARGETS fonts ARCHIVE DESTINATION "${SDK_PATH}/lib")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(addIncludesFromLibrary target library)
|
||||
@@ -885,4 +960,4 @@ function(precompileHeaders target includeFolder)
|
||||
PUBLIC
|
||||
"$<$<COMPILE_LANGUAGE:CXX>:${INCLUDES}>"
|
||||
)
|
||||
endfunction()
|
||||
endfunction()
|
||||
|
||||
@@ -40,7 +40,12 @@ IF(MBEDTLS_FOUND)
|
||||
STRING(REGEX REPLACE "^lib" "" MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY_FILE})
|
||||
STRING(REGEX REPLACE "^lib" "" MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY_FILE})
|
||||
STRING(REGEX REPLACE "^lib" "" MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE})
|
||||
SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}")
|
||||
|
||||
if (MSVC)
|
||||
SET(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY_FILE}.lib ${MBEDX509_LIBRARY_FILE}.lib ${MBEDCRYPTO_LIBRARY_FILE}.lib)
|
||||
else()
|
||||
SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}")
|
||||
endif()
|
||||
|
||||
IF(NOT MBEDTLS_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found mbedTLS:")
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
macro(add_imhex_plugin)
|
||||
setSDKPaths()
|
||||
# Parse arguments
|
||||
set(options LIBRARY_PLUGIN)
|
||||
set(oneValueArgs NAME IMHEX_VERSION)
|
||||
@@ -28,6 +29,10 @@ macro(add_imhex_plugin)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (IMHEX_PLUGIN_LIBRARY_PLUGIN)
|
||||
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION "${SDK_PATH}/lib/plugins/${IMHEX_PLUGIN_NAME}")
|
||||
endif()
|
||||
|
||||
# Define new project for plugin
|
||||
project(${IMHEX_PLUGIN_NAME})
|
||||
|
||||
@@ -62,7 +67,11 @@ macro(add_imhex_plugin)
|
||||
)
|
||||
|
||||
# Set rpath of plugin libraries to the plugins folder
|
||||
if (APPLE)
|
||||
if (WIN32)
|
||||
if (IMHEX_PLUGIN_LIBRARY_PLUGIN)
|
||||
set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
|
||||
endif()
|
||||
elseif (APPLE)
|
||||
set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES BUILD_RPATH "@executable_path/../Frameworks;@executable_path/plugins")
|
||||
endif()
|
||||
|
||||
@@ -147,4 +156,4 @@ macro (enable_plugin_feature feature)
|
||||
|
||||
remove_definitions(-DIMHEX_PLUGIN_${IMHEX_PLUGIN_NAME}_FEATURE_${feature}=0)
|
||||
add_definitions(-DIMHEX_PLUGIN_${IMHEX_PLUGIN_NAME}_FEATURE_${feature}=1)
|
||||
endmacro()
|
||||
endmacro()
|
||||
|
||||
@@ -38,11 +38,6 @@ add_subdirectory(lib/external/libwolv EXCLUDE_FROM_ALL)
|
||||
set(LIBPL_ENABLE_CLI OFF CACHE BOOL "" FORCE)
|
||||
add_subdirectory(lib/external/pattern_language EXCLUDE_FROM_ALL)
|
||||
|
||||
find_package(CURL REQUIRED)
|
||||
find_package(mbedTLS 3.4.0 REQUIRED)
|
||||
set(CURL_LIBRARIES ${CURL_LIBRARIES} PARENT_SCOPE)
|
||||
set(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARIES} PARENT_SCOPE)
|
||||
|
||||
add_subdirectory(lib/libimhex)
|
||||
|
||||
if (WIN32)
|
||||
|
||||
@@ -11,32 +11,23 @@ AppDir:
|
||||
exec_args: $@
|
||||
apt:
|
||||
arch:
|
||||
- amd64
|
||||
- "{{ARCHITECTURE_PACKAGE}}"
|
||||
allow_unauthenticated: true
|
||||
sources:
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular main restricted
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular-updates main restricted
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular universe
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular-updates universe
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular multiverse
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular-updates multiverse
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular-backports main restricted
|
||||
universe multiverse
|
||||
- sourceline: deb http://security.ubuntu.com/ubuntu oracular-security main restricted
|
||||
- sourceline: deb http://security.ubuntu.com/ubuntu oracular-security universe
|
||||
- sourceline: deb http://security.ubuntu.com/ubuntu oracular-security multiverse
|
||||
- sourceline: 'deb [arch=amd64] http://us.archive.ubuntu.com/ubuntu/ oracular main restricted universe multiverse'
|
||||
- sourceline: 'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ oracular main restricted universe multiverse'
|
||||
include:
|
||||
- librsvg2-common
|
||||
- libbz2-1.0:amd64
|
||||
- libcap2:amd64
|
||||
- libdbus-1-3:amd64
|
||||
- libfontconfig1:amd64
|
||||
- libgpg-error0:amd64
|
||||
- liblzma5:amd64
|
||||
- libnss-mdns:amd64
|
||||
- libpcre3:amd64
|
||||
- libselinux1:amd64
|
||||
- libtinfo6:amd64
|
||||
- libbz2-1.0
|
||||
- libcap2
|
||||
- libdbus-1-3
|
||||
- libfontconfig1
|
||||
- libgpg-error0
|
||||
- liblzma5
|
||||
- libnss-mdns
|
||||
- libpcre3
|
||||
- libselinux1
|
||||
- libtinfo6
|
||||
files:
|
||||
include:
|
||||
- /lib/x86_64-linux-gnu/libLLVM-13.so.1
|
||||
@@ -133,6 +124,6 @@ AppDir:
|
||||
- usr/share/doc/*/NEWS.*
|
||||
- usr/share/doc/*/TODO.*
|
||||
AppImage:
|
||||
arch: x86_64
|
||||
update-information: gh-releases-zsync|WerWolv|ImHex|latest|imhex-*-x86_64.AppImage.zsync
|
||||
file_name: imhex-{{VERSION}}-x86_64.AppImage
|
||||
arch: "{{ARCHITECTURE_APPIMAGE_BUILDER}}"
|
||||
update-information: gh-releases-zsync|WerWolv|ImHex|latest|imhex-*-{{ARCHITECTURE_FILE_NAME}}.AppImage.zsync
|
||||
file_name: imhex-{{VERSION}}-{{ARCHITECTURE_FILE_NAME}}.AppImage
|
||||
@@ -30,8 +30,14 @@ ARG LTO=ON
|
||||
ARG BUILD_TYPE=RelWithDebInfo
|
||||
ARG GIT_COMMIT_HASH
|
||||
ARG GIT_BRANCH
|
||||
ARG ARCHITECTURE_PACKAGE
|
||||
ARG ARCHITECTURE_FILE_NAME
|
||||
ARG ARCHITECTURE_APPIMAGE_BUILDER
|
||||
WORKDIR /build
|
||||
SHELL ["bash", "-c"] # Ubuntu sh doesnt support string substitution
|
||||
|
||||
# Ubuntu sh doesnt support string substitution
|
||||
SHELL ["bash", "-c"]
|
||||
|
||||
RUN <<EOF
|
||||
# Prepare ImHex build
|
||||
set -xe
|
||||
@@ -73,7 +79,10 @@ pip3 install git+https://github.com/AppImageCrafters/appimage-builder@f38699e
|
||||
|
||||
# Package ImHex as AppImage
|
||||
export VERSION=$(cat /imhex/VERSION)
|
||||
appimage-builder --recipe /imhex/dist/AppImageBuilder.yml
|
||||
export ARCHITECTURE_PACKAGE=${ARCHITECTURE_PACKAGE}
|
||||
export ARCHITECTURE_FILE_NAME=${ARCHITECTURE_FILE_NAME}
|
||||
export ARCHITECTURE_APPIMAGE_BUILDER=${ARCHITECTURE_APPIMAGE_BUILDER}
|
||||
appimage-builder --recipe /imhex/dist/AppImage/AppImageBuilder.yml
|
||||
EOF
|
||||
|
||||
FROM scratch
|
||||
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/Brewfile`
|
||||
2. Install all the dependencies using `brew bundle --no-lock --file dist/macOS/Brewfile`
|
||||
3. Build ImHex itself using the following commands:
|
||||
```sh
|
||||
cd ImHex
|
||||
@@ -19,4 +19,4 @@ cmake -G "Ninja" \
|
||||
-DIMHEX_GENERATE_PACKAGE=ON \
|
||||
..
|
||||
ninja install
|
||||
```
|
||||
```
|
||||
|
||||
2
dist/get_deps_msys2.sh
vendored
2
dist/get_deps_msys2.sh
vendored
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
pacman -S --needed --noconfirm pactoys
|
||||
pacman -S --needed --noconfirm pactoys unzip
|
||||
pacboy -S --needed --noconfirm \
|
||||
gcc:p \
|
||||
lld:p \
|
||||
|
||||
6
dist/imhex.desktop
vendored
6
dist/imhex.desktop
vendored
@@ -1,4 +1,5 @@
|
||||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Name=ImHex
|
||||
Comment=ImHex Hex Editor
|
||||
GenericName=Hex Editor
|
||||
@@ -10,3 +11,8 @@ Categories=Development;IDE;
|
||||
StartupWMClass=imhex
|
||||
Keywords=static-analysis;reverse-engineering;disassembler;disassembly;hacking;forensics;hex-editor;cybersecurity;security;binary-analysis;
|
||||
MimeType=application/vnd.imhex.proj;
|
||||
Actions=NewFile;
|
||||
|
||||
[Desktop Action NewFile]
|
||||
Exec=imhex --new
|
||||
Name=Create New File
|
||||
0
dist/Brewfile → dist/macOS/Brewfile
vendored
0
dist/Brewfile → dist/macOS/Brewfile
vendored
15
dist/macOS/arm64.Dockerfile
vendored
15
dist/macOS/arm64.Dockerfile
vendored
@@ -1,10 +1,21 @@
|
||||
# This base image is also known as "crosscompile". See arm64.crosscompile.Dockerfile
|
||||
FROM ghcr.io/itrooz/macos-crosscompile:clang17-nosdk as build
|
||||
FROM ghcr.io/itrooz/macos-crosscompile:clang19-nosdk as build
|
||||
|
||||
ENV MACOSX_DEPLOYMENT_TARGET 13.0
|
||||
|
||||
# -- DOWNLOADING STUFF
|
||||
|
||||
# Update vcpkg
|
||||
RUN <<EOF
|
||||
cp /vcpkg/triplets/community/arm-osx-mytriplet.cmake /tmp/arm-osx-mytriplet.cmake
|
||||
git -C /vcpkg clean -ffdx
|
||||
git -C /vcpkg checkout origin/master
|
||||
git -C /vcpkg reset --hard
|
||||
git -C /vcpkg pull
|
||||
/vcpkg/bootstrap-vcpkg.sh
|
||||
cp /tmp/arm-osx-mytriplet.cmake /vcpkg/triplets/community/arm-osx-mytriplet.cmake
|
||||
EOF
|
||||
|
||||
## Install make
|
||||
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y make
|
||||
|
||||
@@ -35,7 +46,7 @@ EOF
|
||||
|
||||
## Download libmagic
|
||||
### Clone libmagic
|
||||
RUN git clone --depth 1 --branch FILE5_45 https://github.com/file/file /mnt/file
|
||||
RUN git clone --depth 1 --branch FILE5_46 https://github.com/file/file /mnt/file
|
||||
### Download libmagic dependencies
|
||||
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y libtool autoconf
|
||||
|
||||
|
||||
2
dist/macOS/arm64.crosscompile.Dockerfile
vendored
2
dist/macOS/arm64.crosscompile.Dockerfile
vendored
@@ -1,4 +1,4 @@
|
||||
# This image is is provided for reference, but a (probably more up to date) image should be available at https://github.com/iTrooz/macos-crosscompile
|
||||
# This image is provided for reference, but a (probably more up to date) image should be available at https://github.com/iTrooz/macos-crosscompile
|
||||
FROM ubuntu:22.04
|
||||
|
||||
ENV PATH $PATH:/osxcross/target/bin
|
||||
|
||||
3
dist/rpm/imhex.spec
vendored
3
dist/rpm/imhex.spec
vendored
@@ -123,9 +123,10 @@ cp -a lib/third_party/xdgpp/LICENSE %{buildroot
|
||||
%doc README.md
|
||||
%{_bindir}/imhex
|
||||
%{_bindir}/imhex-updater
|
||||
%{_datadir}/pixmaps/%{name}.png
|
||||
%{_datadir}/pixmaps/%{name}.svg
|
||||
%{_datadir}/applications/%{name}.desktop
|
||||
%{_datadir}/mime/packages/%{name}.xml
|
||||
%{_libdir}/libimhex.so*
|
||||
%{_libdir}/%{name}/
|
||||
/usr/lib/debug/%{_libdir}/*.debug
|
||||
%{_metainfodir}/net.werwolv.%{name}.metainfo.xml
|
||||
16
dist/vcpkg.json
vendored
Normal file
16
dist/vcpkg.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "vcpkg",
|
||||
"version": "1.0.0",
|
||||
"builtin-baseline": "7e21420f775f72ae938bdeb5e6068f722088f06a",
|
||||
"dependencies": [
|
||||
"libmagic",
|
||||
"freetype",
|
||||
"mbedtls",
|
||||
"zlib",
|
||||
"bzip2",
|
||||
"liblzma",
|
||||
"zstd",
|
||||
"glfw3",
|
||||
"curl"
|
||||
]
|
||||
}
|
||||
12
dist/web/Dockerfile
vendored
12
dist/web/Dockerfile
vendored
@@ -1,4 +1,4 @@
|
||||
FROM emscripten/emsdk:3.1.51 as build
|
||||
FROM emscripten/emsdk:3.1.51 AS build
|
||||
|
||||
# Used to invalidate layer cache but not mount cache
|
||||
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493
|
||||
@@ -13,6 +13,7 @@ RUN <<EOF
|
||||
set -xe
|
||||
|
||||
git clone https://github.com/microsoft/vcpkg /vcpkg
|
||||
git -C /vcpkg pull
|
||||
/vcpkg/bootstrap-vcpkg.sh
|
||||
sed -i 's/vcpkg_install_make(${EXTRA_ARGS})/vcpkg_install_make(${EXTRA_ARGS} SUBPATH src)/g' /vcpkg/ports/libmagic/portfile.cmake
|
||||
EOF
|
||||
@@ -27,7 +28,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||
' >> /emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake
|
||||
EOF
|
||||
|
||||
ENV VCPKG_DEFAULT_BINARY_CACHE /cache/vcpkg
|
||||
ENV VCPKG_DEFAULT_BINARY_CACHE=/cache/vcpkg
|
||||
RUN --mount=type=cache,target=/cache <<EOF
|
||||
# Install dependencies with vcpkg
|
||||
set -xe
|
||||
@@ -45,7 +46,7 @@ EOF
|
||||
|
||||
# Build ImHex
|
||||
ARG JOBS=4
|
||||
ENV CCACHE_DIR /cache/ccache
|
||||
ENV CCACHE_DIR=/cache/ccache
|
||||
|
||||
RUN mkdir /build
|
||||
WORKDIR /build
|
||||
@@ -67,6 +68,7 @@ cmake /imhex
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake \
|
||||
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
|
||||
-DLIBROMFS_COMPRESS_RESOURCES=OFF \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
ninja -j $JOBS
|
||||
@@ -79,7 +81,7 @@ EOF
|
||||
# See https://stackoverflow.com/questions/41701849/cannot-modify-accept-encoding-with-fetch https://github.com/AnthumChris/fetch-progress-indicators/issues/13
|
||||
RUN du -b /build/imhex.wasm | cut -f1 > imhex.wasm.size
|
||||
|
||||
FROM scratch as raw
|
||||
FROM scratch AS raw
|
||||
COPY --from=build [ \
|
||||
# ImHex \
|
||||
"/build/imhex.wasm", \
|
||||
@@ -93,7 +95,7 @@ COPY --from=build [ \
|
||||
"/build/wasm-config.js", \
|
||||
"/build/enable-threads.js", \
|
||||
"/build/favicon.ico", \
|
||||
"/build/icon.png", \
|
||||
"/build/icon.svg", \
|
||||
"/build/manifest.json", \
|
||||
"/build/robots.txt", \
|
||||
"/build/sitemap.xml", \
|
||||
|
||||
BIN
dist/web/source/favicon.ico
vendored
BIN
dist/web/source/favicon.ico
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 162 KiB |
BIN
dist/web/source/icon.png
vendored
BIN
dist/web/source/icon.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 157 KiB |
11
dist/web/source/icon.svg
vendored
Normal file
11
dist/web/source/icon.svg
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" version="1">
|
||||
<rect style="opacity:0.2" width="55" height="10" x="5" y="-60" rx="1.41" transform="rotate(90)"/>
|
||||
<rect style="fill:#2b50a1" width="55" height="10" x="4" y="-60" rx="1.41" transform="rotate(90)"/>
|
||||
<rect style="fill:#2b50a1" width="55" height="10" x="4" y="-14" rx="1.41" transform="rotate(90)"/>
|
||||
<rect style="fill:#2b50a1" width="55" height="10" x="4" y="-33" rx="1.41" transform="rotate(90)"/>
|
||||
<path style="opacity:0.2" d="M 5.3808594,5 C 4.6158118,5 4,5.6158118 4,6.3808594 V 13.619141 C 4,14.384188 4.6158118,15 5.3808594,15 H 31.619141 C 32.384188,15 33,14.384188 33,13.619141 V 6.3808594 C 33,5.6158118 32.384188,5 31.619141,5 Z M 40.400391,5 C 39.624791,5 39,5.6247906 39,6.4003906 V 13.599609 C 39,14.375209 39.624791,15 40.400391,15 H 58.599609 C 59.375209,15 60,14.375209 60,13.599609 V 6.4003906 C 60,5.6247906 59.375209,5 58.599609,5 Z M 5.3808594,50 C 4.6158118,50 4,50.615812 4,51.380859 v 7.238282 C 4,59.384188 4.6158118,60 5.3808594,60 H 31.619141 C 32.384188,60 33,59.384188 33,58.619141 V 51.380859 C 33,50.615812 32.384188,50 31.619141,50 Z"/>
|
||||
<rect style="fill:#3a6be0" width="29" height="10" x="4" y="4" rx="1.381"/>
|
||||
<rect style="fill:#3a6be0" width="21" height="10" x="39" y="4" rx="1.4"/>
|
||||
<rect style="fill:#3a6be0" width="29" height="10" x="4" y="49" rx="1.381"/>
|
||||
<path style="fill:#ffffff;opacity:0.1" d="M 5.3808594 4 C 4.6158118 4 4 4.6158118 4 5.3808594 L 4 6.3808594 C 4 5.6158118 4.6158118 5 5.3808594 5 L 31.619141 5 C 32.384188 5 33 5.6158118 33 6.3808594 L 33 5.3808594 C 33 4.6158118 32.384188 4 31.619141 4 L 5.3808594 4 z M 40.400391 4 C 39.624791 4 39 4.6247906 39 5.4003906 L 39 6.4003906 C 39 5.6247906 39.624791 5 40.400391 5 L 58.599609 5 C 59.375209 5 60 5.6247906 60 6.4003906 L 60 5.4003906 C 60 4.6247906 59.375209 4 58.599609 4 L 40.400391 4 z M 5.3808594 49 C 4.6158118 49 4 49.615812 4 50.380859 L 4 51.380859 C 4 50.615812 4.6158118 50 5.3808594 50 L 31.619141 50 C 32.384188 50 33 50.615812 33 51.380859 L 33 50.380859 C 33 49.615812 32.384188 49 31.619141 49 L 5.3808594 49 z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
4
dist/web/source/index.html
vendored
4
dist/web/source/index.html
vendored
@@ -11,7 +11,7 @@
|
||||
<meta name="title" content="ImHex">
|
||||
<meta name="description" content="Free and extremely powerful Online Hex Editor for your Web Browser. ImHex is a free and open source Hex Editor for Reverse Engineers and Developers and Data Analysts.">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<link rel="apple-touch-icon" href="icon.png">
|
||||
<link rel="apple-touch-icon" href="icon.svg">
|
||||
|
||||
<!-- Open Graph / Facebook -->
|
||||
<meta property="og:type" content="website">
|
||||
@@ -38,7 +38,7 @@
|
||||
"founder": "WerWolv",
|
||||
"slogan": "A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.",
|
||||
"url": "https://imhex.werwolv.net",
|
||||
"logo": "https://imhex.werwolv.net/assets/logos/logo.png"
|
||||
"logo": "https://imhex.werwolv.net/assets/logos/logo.svg"
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
4
dist/web/source/manifest.json
vendored
4
dist/web/source/manifest.json
vendored
@@ -10,8 +10,8 @@
|
||||
],
|
||||
"icons": [
|
||||
{
|
||||
"src": "icon.png",
|
||||
"type": "image/png",
|
||||
"src": "icon.svg",
|
||||
"type": "image/svg",
|
||||
"sizes": "640x640"
|
||||
}
|
||||
],
|
||||
|
||||
5
dist/web/source/sitemap.xml
vendored
5
dist/web/source/sitemap.xml
vendored
@@ -57,6 +57,11 @@
|
||||
<loc>https://web.imhex.werwolv.net?lang=it-IT</loc>
|
||||
<lastmod>2024-01-02T11:44:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<title>Русский</title>
|
||||
<loc>https://web.imhex.werwolv.net?lang=ru-RU</loc>
|
||||
<lastmod>2024-01-02T11:44:00+00:00</lastmod>
|
||||
</url>
|
||||
|
||||
|
||||
</urlset>
|
||||
9
dist/web/source/wasm-config.js
vendored
9
dist/web/source/wasm-config.js
vendored
@@ -261,4 +261,11 @@ function js_resizeCanvas() {
|
||||
canvas.left = document.documentElement.clientLeft;
|
||||
canvas.width = Math.min(document.documentElement.clientWidth, window.innerWidth || 0);
|
||||
canvas.height = Math.min(document.documentElement.clientHeight, window.innerHeight || 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent some default browser shortcuts from preventing ImHex ones to work
|
||||
document.addEventListener('keydown', e => {
|
||||
if (e.ctrlKey) {
|
||||
if (e.which == 83) e.preventDefault();
|
||||
}
|
||||
})
|
||||
1
lib/external/disassembler
vendored
Submodule
1
lib/external/disassembler
vendored
Submodule
Submodule lib/external/disassembler added at a2217dd3bc
2
lib/external/libromfs
vendored
2
lib/external/libromfs
vendored
Submodule lib/external/libromfs updated: 03adcfdde0...4f42f099b2
2
lib/external/libwolv
vendored
2
lib/external/libwolv
vendored
Submodule lib/external/libwolv updated: b9d7f4abaf...00021679c2
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
Submodule lib/external/pattern_language updated: f45156a55c...9833500589
@@ -38,6 +38,8 @@ set(LIBIMHEX_SOURCES
|
||||
source/helpers/debugging.cpp
|
||||
source/helpers/default_paths.cpp
|
||||
source/helpers/imgui_hooks.cpp
|
||||
source/helpers/semantic_version.cpp
|
||||
source/helpers/keys.cpp
|
||||
|
||||
source/test/tests.cpp
|
||||
|
||||
@@ -49,6 +51,7 @@ set(LIBIMHEX_SOURCES
|
||||
source/ui/view.cpp
|
||||
source/ui/popup.cpp
|
||||
source/ui/toast.cpp
|
||||
source/ui/banner.cpp
|
||||
|
||||
source/subcommands/subcommands.cpp
|
||||
)
|
||||
@@ -63,7 +66,10 @@ if (APPLE)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
set(LIBIMHEX_SOURCES ${LIBIMHEX_SOURCES} source/helpers/utils_macos.m)
|
||||
set(LIBIMHEX_SOURCES ${LIBIMHEX_SOURCES}
|
||||
source/helpers/utils_macos.m
|
||||
source/helpers/macos_menu.m
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (IMHEX_EXTERNAL_PLUGIN_BUILD)
|
||||
@@ -120,31 +126,41 @@ setupCompilerFlags(libimhex)
|
||||
include(GenerateExportHeader)
|
||||
generate_export_header(libimhex)
|
||||
|
||||
target_include_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} include ${XDGPP_INCLUDE_DIRS} ${MBEDTLS_INCLUDE_DIR} ${MAGIC_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS} ${FMT_INCLUDE_DIRS} ${LIBBACKTRACE_INCLUDE_DIRS})
|
||||
target_link_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_LIBRARY_DIR} ${MAGIC_LIBRARY_DIRS})
|
||||
|
||||
if (NOT EMSCRIPTEN)
|
||||
# curl is only used in non-emscripten builds
|
||||
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} CURL::libcurl)
|
||||
endif()
|
||||
|
||||
target_include_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} include ${XDGPP_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS} ${FMT_INCLUDE_DIRS})
|
||||
|
||||
if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
|
||||
if (WIN32)
|
||||
set_target_properties(libimhex PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
|
||||
target_link_options(libimhex PRIVATE -Wl,--export-all-symbols)
|
||||
if (NOT MSVC)
|
||||
target_link_options(libimhex PRIVATE -Wl,--export-all-symbols)
|
||||
endif()
|
||||
target_link_libraries(libimhex PRIVATE Netapi32.lib)
|
||||
target_compile_definitions(libimhex PRIVATE EXPORT_SYMBOLS=1)
|
||||
elseif (APPLE)
|
||||
find_library(FOUNDATION NAMES Foundation)
|
||||
target_link_libraries(libimhex PUBLIC ${FOUNDATION})
|
||||
endif ()
|
||||
|
||||
target_link_libraries(libimhex PRIVATE microtar libwolv ${NFD_LIBRARIES} magic dl ${JTHREAD_LIBRARIES})
|
||||
target_link_libraries(libimhex PUBLIC libpl ${IMGUI_LIBRARIES})
|
||||
target_link_libraries(libimhex PRIVATE libpl microtar ${NFD_LIBRARIES} magic)
|
||||
target_link_libraries(libimhex PUBLIC libwolv libpl_includes libpl-gen ${IMGUI_LIBRARIES} ${JTHREAD_LIBRARIES})
|
||||
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(libimhex PRIVATE dl)
|
||||
endif()
|
||||
|
||||
if (NOT EMSCRIPTEN)
|
||||
# curl is only used in non-emscripten builds
|
||||
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} CURL::libcurl)
|
||||
endif()
|
||||
|
||||
target_include_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_INCLUDE_DIR} ${LIBBACKTRACE_INCLUDE_DIRS} ${MAGIC_INCLUDE_DIRS})
|
||||
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_LIBRARIES})
|
||||
target_link_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_LIBRARY_DIR} ${MAGIC_LIBRARY_DIRS})
|
||||
|
||||
precompileHeaders(libimhex "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
endif()
|
||||
|
||||
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${NLOHMANN_JSON_LIBRARIES} imgui_all_includes ${MBEDTLS_LIBRARIES} ${FMT_LIBRARIES} ${LUNASVG_LIBRARIES} ${BOOST_LIBRARIES})
|
||||
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${NLOHMANN_JSON_LIBRARIES} imgui_all_includes ${FMT_LIBRARIES} ${LUNASVG_LIBRARIES} ${BOOST_LIBRARIES})
|
||||
|
||||
set_property(TARGET libimhex PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE)
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <imgui.h>
|
||||
#include <hex/ui/imgui_imhex_extensions.h>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/helpers/auto_reset.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -361,7 +362,7 @@ namespace hex {
|
||||
* @brief Returns all registered achievements
|
||||
* @return All achievements
|
||||
*/
|
||||
static const std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>>& getAchievements();
|
||||
static const std::unordered_map<UnlocalizedString, std::unordered_map<UnlocalizedString, std::unique_ptr<Achievement>>>& getAchievements();
|
||||
|
||||
/**
|
||||
* @brief Returns all achievement start nodes
|
||||
@@ -369,14 +370,14 @@ namespace hex {
|
||||
* @param rebuild Whether to rebuild the list of start nodes
|
||||
* @return All achievement start nodes
|
||||
*/
|
||||
static const std::unordered_map<std::string, std::vector<AchievementNode*>>& getAchievementStartNodes(bool rebuild = true);
|
||||
static const std::unordered_map<UnlocalizedString, std::vector<AchievementNode*>>& getAchievementStartNodes(bool rebuild = true);
|
||||
|
||||
/**
|
||||
* @brief Returns all achievement nodes
|
||||
* @param rebuild Whether to rebuild the list of nodes
|
||||
* @return All achievement nodes
|
||||
*/
|
||||
static const std::unordered_map<std::string, std::list<AchievementNode>>& getAchievementNodes(bool rebuild = true);
|
||||
static const std::unordered_map<UnlocalizedString, std::list<AchievementNode>>& getAchievementNodes(bool rebuild = true);
|
||||
|
||||
/**
|
||||
* @brief Loads the progress of all achievements from the achievements save file
|
||||
@@ -405,4 +406,4 @@ namespace hex {
|
||||
static Achievement& addAchievementImpl(std::unique_ptr<Achievement> &&newAchievement);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ using ImGuiDataType = int;
|
||||
using ImGuiInputTextFlags = int;
|
||||
struct ImColor;
|
||||
enum ImGuiCustomCol : int;
|
||||
typedef int ImGuiColorEditFlags;
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -43,7 +44,6 @@ namespace hex {
|
||||
plugins when needed.
|
||||
*/
|
||||
namespace ContentRegistry {
|
||||
|
||||
/* Settings Registry. Allows adding of new entries into the ImHex preferences window. */
|
||||
namespace Settings {
|
||||
|
||||
@@ -177,7 +177,7 @@ namespace hex {
|
||||
|
||||
class SliderDataSize : public Widget {
|
||||
public:
|
||||
SliderDataSize(u64 defaultValue, u64 min, u64 max) : m_value(defaultValue), m_min(min), m_max(max) { }
|
||||
SliderDataSize(u64 defaultValue, u64 min, u64 max, u64 stepSize) : m_value(defaultValue), m_min(min), m_max(max), m_stepSize(stepSize) { }
|
||||
bool draw(const std::string &name) override;
|
||||
|
||||
void load(const nlohmann::json &data) override;
|
||||
@@ -188,11 +188,12 @@ namespace hex {
|
||||
protected:
|
||||
u64 m_value;
|
||||
u64 m_min, m_max;
|
||||
u64 m_stepSize;
|
||||
};
|
||||
|
||||
class ColorPicker : public Widget {
|
||||
public:
|
||||
explicit ColorPicker(ImColor defaultColor);
|
||||
explicit ColorPicker(ImColor defaultColor, ImGuiColorEditFlags flags = 0);
|
||||
|
||||
bool draw(const std::string &name) override;
|
||||
|
||||
@@ -202,12 +203,14 @@ namespace hex {
|
||||
[[nodiscard]] ImColor getColor() const;
|
||||
|
||||
protected:
|
||||
std::array<float, 4> m_value{};
|
||||
std::array<float, 4> m_value = {}, m_defaultValue = {};
|
||||
ImGuiColorEditFlags m_flags;
|
||||
};
|
||||
|
||||
class DropDown : public Widget {
|
||||
public:
|
||||
explicit DropDown(const std::vector<std::string> &items, const std::vector<nlohmann::json> &settingsValues, const nlohmann::json &defaultItem) : m_items(items), m_settingsValues(settingsValues), m_defaultItem(defaultItem) { }
|
||||
explicit DropDown(const std::vector<std::string> &items, const std::vector<nlohmann::json> &settingsValues, const nlohmann::json &defaultItem) : m_items(items.begin(), items.end()), m_settingsValues(settingsValues), m_defaultItem(defaultItem) { }
|
||||
explicit DropDown(const std::vector<UnlocalizedString> &items, const std::vector<nlohmann::json> &settingsValues, const nlohmann::json &defaultItem) : m_items(items), m_settingsValues(settingsValues), m_defaultItem(defaultItem) { }
|
||||
|
||||
bool draw(const std::string &name) override;
|
||||
|
||||
@@ -218,7 +221,7 @@ namespace hex {
|
||||
const nlohmann::json& getValue() const;
|
||||
|
||||
protected:
|
||||
std::vector<std::string> m_items;
|
||||
std::vector<UnlocalizedString> m_items;
|
||||
std::vector<nlohmann::json> m_settingsValues;
|
||||
nlohmann::json m_defaultItem;
|
||||
|
||||
@@ -325,7 +328,7 @@ namespace hex {
|
||||
result = defaultValue;
|
||||
|
||||
return result.get<T>();
|
||||
} catch (const nlohmann::json::exception &e) {
|
||||
} catch (const nlohmann::json::exception &) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
@@ -573,7 +576,7 @@ namespace hex {
|
||||
namespace impl {
|
||||
|
||||
void add(std::unique_ptr<View> &&view);
|
||||
const std::map<std::string, std::unique_ptr<View>>& getEntries();
|
||||
const std::map<UnlocalizedString, std::unique_ptr<View>>& getEntries();
|
||||
|
||||
}
|
||||
|
||||
@@ -594,6 +597,12 @@ namespace hex {
|
||||
* @return The view if it exists, nullptr otherwise
|
||||
*/
|
||||
View* getViewByName(const UnlocalizedString &unlocalizedName);
|
||||
|
||||
/**
|
||||
* @brief Gets the currently focused view
|
||||
* @return The view that is focused right now. nullptr if none is focused
|
||||
*/
|
||||
View* getFocusedView();
|
||||
}
|
||||
|
||||
/* Tools Registry. Allows adding new entries to the tools window */
|
||||
@@ -623,8 +632,7 @@ namespace hex {
|
||||
/* Data Inspector Registry. Allows adding of new types to the data inspector */
|
||||
namespace DataInspector {
|
||||
|
||||
enum class NumberDisplayStyle
|
||||
{
|
||||
enum class NumberDisplayStyle : u8 {
|
||||
Decimal,
|
||||
Hexadecimal,
|
||||
Octal
|
||||
@@ -678,6 +686,13 @@ namespace hex {
|
||||
std::optional<impl::EditingFunction> editingFunction = std::nullopt
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Allows adding new menu items to data inspector row context menus. Call this function inside the
|
||||
* draw function of the data inspector row definition.
|
||||
* @param function Callback that will draw menu items
|
||||
*/
|
||||
void drawMenuItems(const std::function<void()> &function);
|
||||
|
||||
}
|
||||
|
||||
/* Data Processor Node Registry. Allows adding new processor nodes to be used in the data processor */
|
||||
@@ -712,7 +727,7 @@ namespace hex {
|
||||
add(impl::Entry {
|
||||
unlocalizedCategory,
|
||||
unlocalizedName,
|
||||
[=, ...args = std::forward<Args>(args)] mutable {
|
||||
[=, ...args = std::forward<Args>(args)]() mutable {
|
||||
auto node = std::make_unique<T>(std::forward<Args>(args)...);
|
||||
node->setUnlocalizedName(unlocalizedName);
|
||||
return node;
|
||||
@@ -993,7 +1008,7 @@ namespace hex {
|
||||
void add(bool addToList = true) {
|
||||
auto typeName = T().getTypeName();
|
||||
|
||||
impl::add(typeName, [] -> std::unique_ptr<prv::Provider> {
|
||||
impl::add(typeName, []() -> std::unique_ptr<prv::Provider> {
|
||||
return std::make_unique<T>();
|
||||
});
|
||||
|
||||
@@ -1008,7 +1023,7 @@ namespace hex {
|
||||
|
||||
namespace impl {
|
||||
|
||||
using Callback = std::function<std::string(prv::Provider *provider, u64 address, size_t size)>;
|
||||
using Callback = std::function<std::string(prv::Provider *provider, u64 address, size_t size, bool preview)>;
|
||||
struct ExportMenuEntry {
|
||||
UnlocalizedString unlocalizedName;
|
||||
Callback callback;
|
||||
@@ -1016,7 +1031,7 @@ namespace hex {
|
||||
|
||||
struct FindOccurrence {
|
||||
Region region;
|
||||
enum class DecodeType { ASCII, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
|
||||
enum class DecodeType { ASCII, UTF8, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
|
||||
std::endian endian = std::endian::native;
|
||||
bool selected;
|
||||
};
|
||||
@@ -1101,9 +1116,9 @@ namespace hex {
|
||||
|
||||
[[nodiscard]] const UnlocalizedString& getUnlocalizedName() const { return m_unlocalizedName; }
|
||||
|
||||
protected:
|
||||
const static int TextInputFlags;
|
||||
[[nodiscard]] static int DefaultTextInputFlags();
|
||||
|
||||
protected:
|
||||
bool drawDefaultScalarEditingTextBox(u64 address, const char *format, ImGuiDataType dataType, u8 *data, ImGuiInputTextFlags flags) const;
|
||||
bool drawDefaultTextEditingTextBox(u64 address, std::string &data, ImGuiInputTextFlags flags) const;
|
||||
|
||||
@@ -1354,6 +1369,7 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
/* Data Information Registry. Allows adding new analyzers to the data information view */
|
||||
namespace DataInformation {
|
||||
|
||||
class InformationSection {
|
||||
@@ -1420,6 +1436,54 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
/* Disassembler Registry. Allows adding new disassembler architectures */
|
||||
namespace Disassembler {
|
||||
|
||||
struct Instruction {
|
||||
u64 address;
|
||||
u64 offset;
|
||||
size_t size;
|
||||
std::string bytes;
|
||||
std::string mnemonic;
|
||||
std::string operators;
|
||||
};
|
||||
|
||||
class Architecture {
|
||||
public:
|
||||
explicit Architecture(std::string name) : m_name(std::move(name)) {}
|
||||
virtual ~Architecture() = default;
|
||||
|
||||
virtual bool start() = 0;
|
||||
virtual void end() = 0;
|
||||
|
||||
virtual std::optional<Instruction> disassemble(u64 imageBaseAddress, u64 instructionLoadAddress, u64 instructionDataAddress, std::span<const u8> code) = 0;
|
||||
virtual void drawSettings() = 0;
|
||||
|
||||
[[nodiscard]] const std::string& getName() const { return m_name; }
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
using CreatorFunction = std::function<std::unique_ptr<Architecture>()>;
|
||||
|
||||
void addArchitectureCreator(CreatorFunction function);
|
||||
|
||||
const std::map<std::string, CreatorFunction>& getArchitectures();
|
||||
|
||||
}
|
||||
|
||||
template<std::derived_from<Architecture> T>
|
||||
void add(auto && ...args) {
|
||||
impl::addArchitectureCreator([...args = std::move(args)] {
|
||||
return std::make_unique<T>(args...);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/helpers/patches.hpp>
|
||||
|
||||
#include <wolv/types/type_name.hpp>
|
||||
|
||||
@@ -32,15 +31,6 @@
|
||||
#define EVENT_DEF_NO_LOG(event_name, ...) EVENT_DEF_IMPL(event_name, #event_name, false, __VA_ARGS__)
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
struct GLFWwindow;
|
||||
namespace hex {
|
||||
class Achievement;
|
||||
class View;
|
||||
}
|
||||
|
||||
namespace pl::ptrn { class Pattern; }
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace impl {
|
||||
@@ -100,7 +90,8 @@ namespace hex {
|
||||
|
||||
/**
|
||||
* @brief The EventManager allows subscribing to and posting events to different parts of the program.
|
||||
* To create a new event, use the EVENT_DEF macro. This will create a new event type with the given name and parameters
|
||||
* To create a new event, use the EVENT_DEF macro. This will create a new event type with the given name and parameters.
|
||||
* Events should be created in an `events_*.hpp` category file under the `events` folder, and never directly here.
|
||||
*/
|
||||
class EventManager {
|
||||
public:
|
||||
@@ -200,122 +191,4 @@ namespace hex {
|
||||
static void unsubscribe(void *token, impl::EventId id);
|
||||
};
|
||||
|
||||
/* Default Events */
|
||||
|
||||
/**
|
||||
* @brief Called when Imhex finished startup, and will enter the main window rendering loop
|
||||
*/
|
||||
EVENT_DEF(EventImHexStartupFinished);
|
||||
|
||||
EVENT_DEF(EventFileLoaded, std::fs::path);
|
||||
EVENT_DEF(EventDataChanged, prv::Provider *);
|
||||
EVENT_DEF(EventHighlightingChanged);
|
||||
EVENT_DEF(EventWindowClosing, GLFWwindow *);
|
||||
EVENT_DEF(EventRegionSelected, ImHexApi::HexEditor::ProviderRegion);
|
||||
EVENT_DEF(EventAbnormalTermination, int);
|
||||
EVENT_DEF(EventThemeChanged);
|
||||
EVENT_DEF(EventOSThemeChanged);
|
||||
EVENT_DEF(EventDPIChanged, float, float);
|
||||
EVENT_DEF(EventWindowFocused, bool);
|
||||
|
||||
/**
|
||||
* @brief Called when the provider is created.
|
||||
* This event is responsible for (optionally) initializing the provider and calling EventProviderOpened
|
||||
* (although the event can also be called manually without problem)
|
||||
*/
|
||||
EVENT_DEF(EventProviderCreated, prv::Provider *);
|
||||
EVENT_DEF(EventProviderChanged, prv::Provider *, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Called as a continuation of EventProviderCreated
|
||||
* this event is normally called immediately after EventProviderCreated successfully initialized the provider.
|
||||
* If no initialization (Provider::skipLoadInterface() has been set), this event should be called manually
|
||||
* If skipLoadInterface failed, this event is not called
|
||||
*
|
||||
* @note this is not related to Provider::open()
|
||||
*/
|
||||
EVENT_DEF(EventProviderOpened, prv::Provider *);
|
||||
EVENT_DEF(EventProviderClosing, prv::Provider *, bool *);
|
||||
EVENT_DEF(EventProviderClosed, prv::Provider *);
|
||||
EVENT_DEF(EventProviderDeleted, prv::Provider *);
|
||||
EVENT_DEF(EventProviderSaved, prv::Provider *);
|
||||
EVENT_DEF(EventWindowInitialized);
|
||||
EVENT_DEF(EventWindowDeinitializing, GLFWwindow *);
|
||||
EVENT_DEF(EventBookmarkCreated, ImHexApi::Bookmarks::Entry&);
|
||||
|
||||
/**
|
||||
* @brief Called upon creation of an IPS patch.
|
||||
* As for now, the event only serves a purpose for the achievement unlock.
|
||||
*/
|
||||
EVENT_DEF(EventPatchCreated, const u8*, u64, const PatchKind);
|
||||
EVENT_DEF(EventPatternEvaluating);
|
||||
EVENT_DEF(EventPatternExecuted, const std::string&);
|
||||
EVENT_DEF(EventPatternEditorChanged, const std::string&);
|
||||
EVENT_DEF(EventStoreContentDownloaded, const std::fs::path&);
|
||||
EVENT_DEF(EventStoreContentRemoved, const std::fs::path&);
|
||||
EVENT_DEF(EventImHexClosing);
|
||||
EVENT_DEF(EventAchievementUnlocked, const Achievement&);
|
||||
EVENT_DEF(EventSearchBoxClicked, u32);
|
||||
EVENT_DEF(EventViewOpened, View*);
|
||||
EVENT_DEF(EventFirstLaunch);
|
||||
|
||||
EVENT_DEF(EventFileDragged, bool);
|
||||
EVENT_DEF(EventFileDropped, std::fs::path);
|
||||
|
||||
EVENT_DEF(EventProviderDataModified, prv::Provider *, u64, u64, const u8*);
|
||||
EVENT_DEF(EventProviderDataInserted, prv::Provider *, u64, u64);
|
||||
EVENT_DEF(EventProviderDataRemoved, prv::Provider *, u64, u64);
|
||||
EVENT_DEF(EventProviderDirtied, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Called when a project has been loaded
|
||||
*/
|
||||
EVENT_DEF(EventProjectOpened);
|
||||
|
||||
EVENT_DEF_NO_LOG(EventFrameBegin);
|
||||
EVENT_DEF_NO_LOG(EventFrameEnd);
|
||||
EVENT_DEF_NO_LOG(EventSetTaskBarIconState, u32, u32, u32);
|
||||
EVENT_DEF_NO_LOG(EventImGuiElementRendered, ImGuiID, const std::array<float, 4>&);
|
||||
|
||||
EVENT_DEF(RequestAddInitTask, std::string, bool, std::function<bool()>);
|
||||
EVENT_DEF(RequestAddExitTask, std::string, std::function<bool()>);
|
||||
EVENT_DEF(RequestOpenWindow, std::string);
|
||||
EVENT_DEF(RequestHexEditorSelectionChange, Region);
|
||||
EVENT_DEF(RequestPatternEditorSelectionChange, u32, u32);
|
||||
EVENT_DEF(RequestJumpToPattern, const pl::ptrn::Pattern*);
|
||||
EVENT_DEF(RequestAddBookmark, Region, std::string, std::string, color_t, u64*);
|
||||
EVENT_DEF(RequestRemoveBookmark, u64);
|
||||
EVENT_DEF(RequestSetPatternLanguageCode, std::string);
|
||||
EVENT_DEF(RequestRunPatternCode);
|
||||
EVENT_DEF(RequestLoadPatternLanguageFile, std::fs::path);
|
||||
EVENT_DEF(RequestSavePatternLanguageFile, std::fs::path);
|
||||
EVENT_DEF(RequestUpdateWindowTitle);
|
||||
EVENT_DEF(RequestCloseImHex, bool);
|
||||
EVENT_DEF(RequestRestartImHex);
|
||||
EVENT_DEF(RequestOpenFile, std::fs::path);
|
||||
EVENT_DEF(RequestChangeTheme, std::string);
|
||||
EVENT_DEF(RequestOpenPopup, std::string);
|
||||
EVENT_DEF(RequestAddVirtualFile, std::fs::path, std::vector<u8>, Region);
|
||||
|
||||
/**
|
||||
* @brief Creates a provider from it's unlocalized name, and add it to the provider list
|
||||
*/
|
||||
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, hex::prv::Provider **);
|
||||
EVENT_DEF(RequestInitThemeHandlers);
|
||||
|
||||
/**
|
||||
* @brief Send an event to the main Imhex instance
|
||||
*/
|
||||
EVENT_DEF(SendMessageToMainInstance, const std::string, const std::vector<u8>&);
|
||||
|
||||
/**
|
||||
* Move the data from all PerProvider instances from one provider to another.
|
||||
* The 'from' provider should not have any per provider data after this, and should be immediately deleted
|
||||
*/
|
||||
EVENT_DEF(MovePerProviderData, prv::Provider *, prv::Provider *);
|
||||
|
||||
/**
|
||||
* Called when ImHex managed to catch an error in a general try/catch to prevent/recover from a crash
|
||||
*/
|
||||
EVENT_DEF(EventCrashRecovered, const std::exception &);
|
||||
}
|
||||
120
lib/libimhex/include/hex/api/events/events_gui.hpp
Normal file
120
lib/libimhex/include/hex/api/events/events_gui.hpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Forward declarations */
|
||||
struct GLFWwindow;
|
||||
namespace hex { class View; }
|
||||
|
||||
/* GUI events definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Signals a newly opened window
|
||||
*
|
||||
* This event is sent when the window has just been opened and docked by the Window manager.
|
||||
*
|
||||
* FIXME: In the event that a newly created window is already docked, this will not be sent.
|
||||
*
|
||||
* FIXME: This is currently only used for the introduction tutorial.
|
||||
* If the event's only purpose is this, maybe rename it?
|
||||
*
|
||||
* @param view the new view reference
|
||||
*/
|
||||
EVENT_DEF(EventViewOpened, View*);
|
||||
|
||||
/**
|
||||
* @brief Signals a change in the DPI scale.
|
||||
*
|
||||
* This event is called once at startup to signal native scale definition (by passing the same value twice).
|
||||
* On Windows OS, this event can also be posted if the window DPI has been changed.
|
||||
*
|
||||
* @param oldScale the old scale
|
||||
* @param newScale the current scale that's now in use
|
||||
*/
|
||||
EVENT_DEF(EventDPIChanged, float, float);
|
||||
|
||||
/**
|
||||
* @brief Signals the focus of the ImHex main window.
|
||||
*
|
||||
* This is directly tied as a GLFW window focus callback, and will be called accordingly when GLFW detects
|
||||
* a change in focus.
|
||||
*
|
||||
* @param isFocused true if the window is focused
|
||||
*/
|
||||
EVENT_DEF(EventWindowFocused, bool);
|
||||
|
||||
/**
|
||||
* @brief Signals a window being closed.
|
||||
*
|
||||
* Allows reactive clean up of running tasks, and prevents ImHex from closing
|
||||
* by displaying an exit confirmation popup.
|
||||
*
|
||||
* @param window The window reference
|
||||
*/
|
||||
EVENT_DEF(EventWindowClosing, GLFWwindow*);
|
||||
|
||||
/**
|
||||
* @brief Informs that the main window is initialized
|
||||
*
|
||||
* On Windows OS, it is used to initialize system theme, if ImHex's theme is following it.
|
||||
*
|
||||
* FIXME: Change event name to reflect Theme detection, if it's only used for that purpose?
|
||||
*/
|
||||
EVENT_DEF(EventWindowInitialized);
|
||||
|
||||
/**
|
||||
* @brief Informs that the main window is deinitializing
|
||||
*
|
||||
* Allows for lifecycle cleanup before ImHex shutdown.
|
||||
*
|
||||
* @param window The window reference
|
||||
*/
|
||||
EVENT_DEF(EventWindowDeinitializing, GLFWwindow*);
|
||||
|
||||
/**
|
||||
* @brief Signals a theme change in the host OS
|
||||
*
|
||||
* Allows ImHex to react to OS theme changes dynamically during execution.
|
||||
*/
|
||||
EVENT_DEF(EventOSThemeChanged);
|
||||
|
||||
}
|
||||
|
||||
/* silent (no-logging) GUI events definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Signals the start of a new ImGui frame
|
||||
*/
|
||||
EVENT_DEF_NO_LOG(EventFrameBegin);
|
||||
|
||||
/**
|
||||
* @brief Signals the end of an ImGui frame
|
||||
*/
|
||||
EVENT_DEF_NO_LOG(EventFrameEnd);
|
||||
|
||||
/**
|
||||
* @brief Windows OS: Sets the taskbar icon state
|
||||
*
|
||||
* This event is used on Windows OS to display progress through the taskbar icon (the famous "green loading bar"
|
||||
* in the taskbar).
|
||||
*
|
||||
* @param progressState the progress state (converted from the TaskProgressState enum)
|
||||
* @param progressType the type of progress (converted from the TaskProgressType enum)
|
||||
* @param percentage actual progress percentage (expected from 0 to 100)
|
||||
*
|
||||
* @see hex::ImHexApi::System::TaskProgressState
|
||||
* @see hex::ImHexApi::System::TaskProgressType
|
||||
*/
|
||||
EVENT_DEF_NO_LOG(EventSetTaskBarIconState, u32, u32, u32);
|
||||
|
||||
/**
|
||||
* @brief Informs of an ImGui element being rendered
|
||||
*
|
||||
* @param elementId the element's ID
|
||||
* @param boundingBox the bounding box (composed of 4 floats)
|
||||
*/
|
||||
EVENT_DEF_NO_LOG(EventImGuiElementRendered, ImGuiID, const std::array<float, 4>&);
|
||||
|
||||
}
|
||||
158
lib/libimhex/include/hex/api/events/events_interaction.hpp
Normal file
158
lib/libimhex/include/hex/api/events/events_interaction.hpp
Normal file
@@ -0,0 +1,158 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/helpers/patches.hpp>
|
||||
|
||||
/* Forward declarations */
|
||||
namespace hex { class Achievement; }
|
||||
|
||||
/* Interaction events definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Signals a file was loaded
|
||||
*
|
||||
* FIXME: this event is unused and should be scrapped.
|
||||
*
|
||||
* @param path the loaded file's path
|
||||
*/
|
||||
EVENT_DEF(EventFileLoaded, std::fs::path);
|
||||
|
||||
/**
|
||||
* @brief Signals a change in the current data
|
||||
*
|
||||
* Enables provider reaction to data change, especially the data inspector.
|
||||
*
|
||||
* This is caused by the following:
|
||||
* - an explicit provider reload, requested by the user (Ctrl+R)
|
||||
* - any user action that results in the creation of an "undo" stack action (generally a data modification)
|
||||
*
|
||||
* @param provider the Provider subject to the data change
|
||||
*/
|
||||
EVENT_DEF(EventDataChanged, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals a change in highlighting
|
||||
*
|
||||
* The event's only purpose is for the Hex editor to clear highlights when receiving this event.
|
||||
*/
|
||||
EVENT_DEF(EventHighlightingChanged);
|
||||
|
||||
/**
|
||||
* @brief Informs of a provider region being selected
|
||||
*
|
||||
* This is very generally used to signal user actions that select a specific region within the provider.
|
||||
* It is also used to pass on regions when the provider changes.
|
||||
*
|
||||
* @param providerRegion the provider-aware region being selected
|
||||
*/
|
||||
EVENT_DEF(EventRegionSelected, ImHexApi::HexEditor::ProviderRegion);
|
||||
|
||||
/**
|
||||
* @brief Signals a theme change
|
||||
*
|
||||
* On Windows OS, this is used to reflect the theme color onto the window frame.
|
||||
*/
|
||||
EVENT_DEF(EventThemeChanged);
|
||||
|
||||
/**
|
||||
* @brief Signals that a bookmark was created
|
||||
*
|
||||
* For now, this event's only purpose is to unlock an achievement.
|
||||
*
|
||||
* @param entry the new bookmark
|
||||
*/
|
||||
EVENT_DEF(EventBookmarkCreated, ImHexApi::Bookmarks::Entry&);
|
||||
|
||||
/**
|
||||
* @brief Called upon creation of an IPS patch.
|
||||
* As for now, the event only serves a purpose for the achievement unlock.
|
||||
*
|
||||
* @param data the pointer to the patch content's start
|
||||
* @param size the patch data size
|
||||
* @param kind the patch's kind
|
||||
*/
|
||||
EVENT_DEF(EventPatchCreated, const u8*, u64, const PatchKind);
|
||||
|
||||
/**
|
||||
* @brief Signals the beginning of evaluation of the current pattern
|
||||
*
|
||||
* This allows resetting the drawer view for the pattern data while we wait for the execution completion.
|
||||
*/
|
||||
EVENT_DEF(EventPatternEvaluating);
|
||||
|
||||
/**
|
||||
* @brief Signals the completion of the pattern evaluation
|
||||
*
|
||||
* This causes another reset in the drawer view, to refresh the table displayed to the user.
|
||||
*
|
||||
* @param code the execution's status code
|
||||
*/
|
||||
EVENT_DEF(EventPatternExecuted, const std::string&);
|
||||
|
||||
/**
|
||||
* @brief Denotes when pattern editor has changed
|
||||
*
|
||||
* FIXME: this event is unused and should be scrapped.
|
||||
*/
|
||||
EVENT_DEF(EventPatternEditorChanged, const std::string&);
|
||||
|
||||
/**
|
||||
* @brief Signals that a Content Store item was downloaded
|
||||
*
|
||||
* FIXME: this event is unused and should be scrapped.
|
||||
*
|
||||
* @param path the item's path on the filesystem
|
||||
*/
|
||||
EVENT_DEF(EventStoreContentDownloaded, const std::fs::path&);
|
||||
|
||||
/**
|
||||
* @brief Signals the removal of a Content Store item
|
||||
*
|
||||
* Note: at the time of the event firing, the item has already been removed from the filesystem.
|
||||
*
|
||||
* FIXME: this event is unused and should be scrapped.
|
||||
*
|
||||
* @param path the item's old file path where it used to be in the filesystem
|
||||
*/
|
||||
EVENT_DEF(EventStoreContentRemoved, const std::fs::path&);
|
||||
|
||||
/**
|
||||
* @brief Signals the unlocking of an achievement
|
||||
*
|
||||
* This is used by the achievement manager to refresh the achievement display, as well as store progress to
|
||||
* the appropriate storage file.
|
||||
*
|
||||
* @param achievement the achievement that was unlocked
|
||||
*/
|
||||
EVENT_DEF(EventAchievementUnlocked, const Achievement&);
|
||||
|
||||
/**
|
||||
* @brief Signals a click on the search box
|
||||
*
|
||||
* As there are different behaviours depending on the click (left or right) done by the user,
|
||||
* this allows the consequences of said click to be registered in their own components.
|
||||
*
|
||||
* @param button the ImGuiMouseButton's value
|
||||
*/
|
||||
EVENT_DEF(EventSearchBoxClicked, u32);
|
||||
|
||||
/**
|
||||
* @brief Updates on whether a file is being dragged into ImHex
|
||||
*
|
||||
* Allows ImGUi to display a file dragging information on screen when a file is being dragged.
|
||||
*
|
||||
* @param isFileDragged true if a file is being dragged
|
||||
*/
|
||||
EVENT_DEF(EventFileDragged, bool);
|
||||
|
||||
/**
|
||||
* @brief Triggers loading when a file is dropped
|
||||
*
|
||||
* The event fires when a file is dropped into ImHex, which passes it to file handlers to load it.
|
||||
*
|
||||
* @param path the dropped file's path
|
||||
*/
|
||||
EVENT_DEF(EventFileDropped, std::fs::path);
|
||||
|
||||
}
|
||||
78
lib/libimhex/include/hex/api/events/events_lifecycle.hpp
Normal file
78
lib/libimhex/include/hex/api/events/events_lifecycle.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Lifecycle events definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Called when Imhex finished startup, and will enter the main window rendering loop
|
||||
*/
|
||||
EVENT_DEF(EventImHexStartupFinished);
|
||||
|
||||
/**
|
||||
* @brief Called when ImHex is closing, to trigger the last shutdown hooks
|
||||
*
|
||||
* This is the last event to fire before complete graceful shutdown.
|
||||
*/
|
||||
EVENT_DEF(EventImHexClosing);
|
||||
|
||||
/**
|
||||
* @brief Signals that it's ImHex first launch ever
|
||||
*
|
||||
* This event allows for the launch of the ImHex tutorial (also called Out of Box experience).
|
||||
*/
|
||||
EVENT_DEF(EventFirstLaunch);
|
||||
|
||||
/**
|
||||
* FIXME: this event is unused and should be scrapped.
|
||||
*/
|
||||
EVENT_DEF(EventAnySettingChanged);
|
||||
|
||||
/**
|
||||
* @brief Ensures correct plugin cleanup on crash
|
||||
*
|
||||
* This event is fired when catching an unexpected error that cannot be recovered and
|
||||
* which forces Imhex to close immediately.
|
||||
*
|
||||
* Subscribing to this event ensures that the plugin can correctly clean up any mission-critical tasks
|
||||
* before forceful shutdown.
|
||||
*
|
||||
* @param signal the POSIX signal code
|
||||
*/
|
||||
EVENT_DEF(EventAbnormalTermination, int);
|
||||
|
||||
/**
|
||||
* @brief Informs of the ImHex versions (and difference, if any)
|
||||
*
|
||||
* Called on every startup to inform subscribers of the two versions picked up:
|
||||
* - the version of the previous launch, gathered from the settings file
|
||||
* - the current version, gathered directly from C++ code
|
||||
*
|
||||
* In most cases, and unless ImHex was updated, the two parameters will be the same.
|
||||
*
|
||||
* FIXME: Maybe rename the event to signal a startup information, instead of the misleading
|
||||
* title that the event could be fired when ImHex detects that it was updated since last launch?
|
||||
*
|
||||
* @param previousLaunchVersion ImHex's version during the previous launch
|
||||
* @param currentVersion ImHex's current version for this startup
|
||||
*/
|
||||
EVENT_DEF(EventImHexUpdated, SemanticVersion, SemanticVersion);
|
||||
|
||||
/**
|
||||
* @brief Called when ImHex managed to catch an error in a general try/catch to prevent/recover from a crash
|
||||
*/
|
||||
EVENT_DEF(EventCrashRecovered, const std::exception &);
|
||||
|
||||
/**
|
||||
* @brief Called when a project has been loaded
|
||||
*/
|
||||
EVENT_DEF(EventProjectOpened);
|
||||
|
||||
/**
|
||||
* @brief Called when a native message was received from another ImHex instance
|
||||
* @param rawData Raw bytes received from other instance
|
||||
*/
|
||||
EVENT_DEF(EventNativeMessageReceived, std::vector<u8>);
|
||||
|
||||
}
|
||||
113
lib/libimhex/include/hex/api/events/events_provider.hpp
Normal file
113
lib/libimhex/include/hex/api/events/events_provider.hpp
Normal file
@@ -0,0 +1,113 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Provider events definitions */
|
||||
namespace hex {
|
||||
/**
|
||||
* @brief Called when the provider is created.
|
||||
* This event is responsible for (optionally) initializing the provider and calling EventProviderOpened
|
||||
* (although the event can also be called manually without problem)
|
||||
*/
|
||||
EVENT_DEF(EventProviderCreated, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Called as a continuation of EventProviderCreated
|
||||
* this event is normally called immediately after EventProviderCreated successfully initialized the provider.
|
||||
* If no initialization (Provider::skipLoadInterface() has been set), this event should be called manually
|
||||
* If skipLoadInterface failed, this event is not called
|
||||
*
|
||||
* @note this is not related to Provider::open()
|
||||
*/
|
||||
EVENT_DEF(EventProviderOpened, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals a change in provider (in-place)
|
||||
*
|
||||
* Note: if the provider was deleted, the new ("current") provider will be `nullptr`
|
||||
*
|
||||
* @param oldProvider the old provider
|
||||
* @param currentProvider the current provider
|
||||
*/
|
||||
EVENT_DEF(EventProviderChanged, prv::Provider *, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals that a provider was saved
|
||||
*
|
||||
* @param provider the saved provider
|
||||
*/
|
||||
EVENT_DEF(EventProviderSaved, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals a provider is closing
|
||||
*
|
||||
* FIXME: as for now, this behaves as a request more than an event. Also, the boolean is always set to true,
|
||||
* and serves no purpose. This should be moved into the Provider requests section and declared accordingly.
|
||||
*
|
||||
* @param provider the closing provider
|
||||
* @param shouldClose whether the provider should close
|
||||
*/
|
||||
EVENT_DEF(EventProviderClosing, prv::Provider *, bool *);
|
||||
|
||||
/**
|
||||
* @brief Signals that a provider was closed
|
||||
*
|
||||
* As this is a closure information broadcast, the provider should generally not be accessed, as it could
|
||||
* result in problems.
|
||||
*
|
||||
* @param provider the now-closed provider
|
||||
*/
|
||||
EVENT_DEF(EventProviderClosed, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals that a provider is being deleted
|
||||
*
|
||||
* Provider's data should not be accessed.
|
||||
*
|
||||
* @param provider the provider
|
||||
*/
|
||||
EVENT_DEF(EventProviderDeleted, prv::Provider *);
|
||||
|
||||
}
|
||||
|
||||
/* Provider data events definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Signals the dirtying of a provider
|
||||
*
|
||||
* Any data modification that occurs in a provider dirties it, until its state is either saved or restored.
|
||||
* This event signals that fact to subscribers so additional code can be executed for certain cases.
|
||||
*/
|
||||
EVENT_DEF(EventProviderDirtied, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals an insertion of new data into a provider
|
||||
*
|
||||
* @param provider the provider
|
||||
* @param offset the start of the insertion
|
||||
* @param size the new data's size
|
||||
*/
|
||||
EVENT_DEF(EventProviderDataInserted, prv::Provider *, u64, u64);
|
||||
|
||||
/**
|
||||
* @brief Signals a modification in the provider's data
|
||||
*
|
||||
* @param provider the provider
|
||||
* @param offset the data modification's offset (start address)
|
||||
* @param size the buffer's size
|
||||
* @param buffer the modified data written at this address
|
||||
*/
|
||||
EVENT_DEF(EventProviderDataModified, prv::Provider *, u64, u64, const u8*);
|
||||
|
||||
/**
|
||||
* @brief Signals a removal of some of the provider's data
|
||||
*
|
||||
* @param provider the provider
|
||||
* @param offset the deletion offset (start address)
|
||||
* @param size the deleted data's size
|
||||
*/
|
||||
EVENT_DEF(EventProviderDataRemoved, prv::Provider *, u64, u64);
|
||||
|
||||
}
|
||||
37
lib/libimhex/include/hex/api/events/requests_gui.hpp
Normal file
37
lib/libimhex/include/hex/api/events/requests_gui.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* GUI requests definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Requests the opening of a new window.
|
||||
*
|
||||
* @param name the window's name
|
||||
*/
|
||||
EVENT_DEF(RequestOpenWindow, std::string);
|
||||
|
||||
/**
|
||||
* @brief Centralized request to update ImHex's main window title
|
||||
*
|
||||
* This request can be called to make ImHex refresh its main window title, taking into account a new project
|
||||
* or file opened/closed.
|
||||
*/
|
||||
EVENT_DEF(RequestUpdateWindowTitle);
|
||||
|
||||
/**
|
||||
* @brief Requests a theme type (light or dark) change
|
||||
*
|
||||
* @param themeType either `Light` or `Dark`
|
||||
*/
|
||||
EVENT_DEF(RequestChangeTheme, std::string);
|
||||
|
||||
/**
|
||||
* @brief Requests the opening of a popup
|
||||
*
|
||||
* @param name the popup's name
|
||||
*/
|
||||
EVENT_DEF(RequestOpenPopup, std::string);
|
||||
|
||||
}
|
||||
116
lib/libimhex/include/hex/api/events/requests_interaction.hpp
Normal file
116
lib/libimhex/include/hex/api/events/requests_interaction.hpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Forward declarations */
|
||||
namespace pl::ptrn { class Pattern; }
|
||||
|
||||
/* Interaction requests definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Requests a selection change in the Hex editor
|
||||
*
|
||||
* This request is handled by the Hex editor, which proceeds to check if the selection is valid.
|
||||
* If it is invalid, the Hex editor fires the `EventRegionSelected` event with nullptr region info.
|
||||
*
|
||||
* @param region the region that should be selected
|
||||
*/
|
||||
EVENT_DEF(RequestHexEditorSelectionChange, ImHexApi::HexEditor::ProviderRegion);
|
||||
|
||||
/**
|
||||
* @brief Requests the Pattern editor to move selection
|
||||
*
|
||||
* Requests the Pattern editor to move the cursor's position to reflect the user's click or movement.
|
||||
*
|
||||
* @param line the target line
|
||||
* @param column the target column
|
||||
*/
|
||||
EVENT_DEF(RequestPatternEditorSelectionChange, u32, u32);
|
||||
|
||||
/**
|
||||
* @brief Requests a jump to a given pattern
|
||||
*
|
||||
* This request is fired by the Hex editor when the user asks to jump to the pattern.
|
||||
* It is then caught and reflected by the Pattern data component.
|
||||
*
|
||||
* @param pattern the pattern to jump to
|
||||
*/
|
||||
EVENT_DEF(RequestJumpToPattern, const pl::ptrn::Pattern*);
|
||||
|
||||
/**
|
||||
* @brief Requests to add a bookmark
|
||||
*
|
||||
* @param region the region to be bookmarked
|
||||
* @param name the bookmark's name
|
||||
* @param comment a comment
|
||||
* @param color the color
|
||||
* @param id the bookmark's unique ID
|
||||
*/
|
||||
EVENT_DEF(RequestAddBookmark, Region, std::string, std::string, color_t, u64*);
|
||||
|
||||
/**
|
||||
* @brief Requests a bookmark removal
|
||||
*
|
||||
* @param id the bookmark's unique ID
|
||||
*/
|
||||
EVENT_DEF(RequestRemoveBookmark, u64);
|
||||
|
||||
/**
|
||||
* @brief Request the Pattern editor to set its code
|
||||
*
|
||||
* This request allows the rest of ImHex to interface with the Pattern editor component, by setting its code.
|
||||
* This allows for `.hexpat` file loading, and more.
|
||||
*
|
||||
* @param code the code's string
|
||||
*/
|
||||
EVENT_DEF(RequestSetPatternLanguageCode, std::string);
|
||||
|
||||
/**
|
||||
* @brief Requests the Pattern editor to run the current code
|
||||
*
|
||||
* This is only ever used in the introduction tutorial.
|
||||
*
|
||||
* FIXME: the name is misleading, as for now this activates the pattern's auto-evaluation rather than a
|
||||
* one-off execution
|
||||
*/
|
||||
EVENT_DEF(RequestRunPatternCode);
|
||||
|
||||
/**
|
||||
* @brief Request to load a pattern language file
|
||||
*
|
||||
* FIXME: this request is unused, as now another component is responsible for pattern file loading.
|
||||
* This request should be scrapped.
|
||||
*
|
||||
* @param path the pattern file's path
|
||||
*/
|
||||
EVENT_DEF(RequestLoadPatternLanguageFile, std::fs::path);
|
||||
|
||||
/**
|
||||
* @brief Request to save a pattern language file
|
||||
*
|
||||
* FIXME: this request is unused, as now another component is responsible for pattern file saving.
|
||||
* This request should be scrapped.
|
||||
*
|
||||
* @param path the pattern file's path
|
||||
*/
|
||||
EVENT_DEF(RequestSavePatternLanguageFile, std::fs::path);
|
||||
|
||||
/**
|
||||
* @brief Requests ImHex to open and process a file
|
||||
*
|
||||
* @param path the file's path
|
||||
*/
|
||||
EVENT_DEF(RequestOpenFile, std::fs::path);
|
||||
|
||||
/**
|
||||
* @brief Adds a virtual file in the Pattern editor
|
||||
*
|
||||
* @param path the file's path
|
||||
* @param data the file's data
|
||||
* @param region the impacted region
|
||||
*/
|
||||
EVENT_DEF(RequestAddVirtualFile, std::fs::path, std::vector<u8>, Region);
|
||||
|
||||
}
|
||||
84
lib/libimhex/include/hex/api/events/requests_lifecycle.hpp
Normal file
84
lib/libimhex/include/hex/api/events/requests_lifecycle.hpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Lifecycle requests definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Emit a request to add an initialization task to the list
|
||||
*
|
||||
* These tasks will be executed at startup.
|
||||
*
|
||||
* @param name Name of the init task
|
||||
* @param isAsync Whether the task is asynchronous (true if yes)
|
||||
* @param callbackFunction The function to call to execute the task
|
||||
*/
|
||||
EVENT_DEF(RequestAddInitTask, std::string, bool, std::function<bool()>);
|
||||
|
||||
/**
|
||||
* @brief Emit a request to add an exit task to the list
|
||||
*
|
||||
* These tasks will be executed during the exit phase.
|
||||
*
|
||||
* FIXME: request is unused and should be scrapped.
|
||||
*
|
||||
* @param name Name of the exit task
|
||||
* @param callbackFunction The function to call to execute the task
|
||||
*/
|
||||
EVENT_DEF(RequestAddExitTask, std::string, std::function<bool()>);
|
||||
|
||||
/**
|
||||
* @brief Requests ImHex's graceful shutdown
|
||||
*
|
||||
* If there are no questions (bool set to true), ImHex closes immediately.
|
||||
* If set to false, there is a procedure run to prompt a confirmation to the user.
|
||||
*
|
||||
* @param noQuestions true if no questions
|
||||
*/
|
||||
EVENT_DEF(RequestCloseImHex, bool);
|
||||
|
||||
/**
|
||||
* @brief Requests ImHex's restart
|
||||
*
|
||||
* This event is necessary for ImHex to restart in the main loop for native and web platforms,
|
||||
* as ImHex cannot simply close and re-open.
|
||||
*
|
||||
* This event serves no purpose on Linux, Windows and macOS platforms.
|
||||
*/
|
||||
EVENT_DEF(RequestRestartImHex);
|
||||
|
||||
/**
|
||||
* @brief Requests the initialization of theme handlers
|
||||
*
|
||||
* This is called during ImGui bootstrapping, and should not be called at any other time.
|
||||
*/
|
||||
EVENT_DEF(RequestInitThemeHandlers);
|
||||
|
||||
/**
|
||||
* @brief Requests version and first-startup checks
|
||||
*
|
||||
* This request is called during ImHex's startup, and allows ImHex to check if it was updated since last launch.
|
||||
* It also ensures newcomers (that open ImHex for the first time) are greeted with the tutorial.
|
||||
*
|
||||
* FIXME: the name is misleading, as this request does not effectively start any migration. It only executes
|
||||
* checks about ImHex's version. The name should be changed to reflect this behaviour.
|
||||
*/
|
||||
EVENT_DEF(RequestStartMigration);
|
||||
|
||||
/**
|
||||
* @brief Send a subcommand to the main Imhex instance
|
||||
*
|
||||
* This request is called to send a subcommand to the main ImHex instance.
|
||||
* This subcommand will then be executed by a handler when ImHex finishing initializing
|
||||
* (`EventImHexStartupFinished`).
|
||||
*
|
||||
* FIXME: change the name so that it is prefixed with "Request" like every other request.
|
||||
*
|
||||
* @param name the subcommand's name
|
||||
* @param data the subcommand's data
|
||||
*/
|
||||
EVENT_DEF(SendMessageToMainInstance, const std::string, const std::vector<u8>&);
|
||||
|
||||
}
|
||||
22
lib/libimhex/include/hex/api/events/requests_provider.hpp
Normal file
22
lib/libimhex/include/hex/api/events/requests_provider.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Provider requests definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Creates a provider from its unlocalized name, and add it to the provider list
|
||||
*/
|
||||
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, hex::prv::Provider **);
|
||||
|
||||
/**
|
||||
* @brief Move the data from all PerProvider instances from one provider to another
|
||||
*
|
||||
* The 'from' provider should not have any per provider data after this, and should be immediately deleted
|
||||
*
|
||||
* FIXME: rename with the "Request" prefix to apply standard naming convention.
|
||||
*/
|
||||
EVENT_DEF(MovePerProviderData, prv::Provider *, prv::Provider *);
|
||||
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/helpers/semantic_version.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
@@ -10,8 +12,7 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <wolv/io/fs.hpp>
|
||||
#include <memory>
|
||||
|
||||
using ImGuiID = unsigned int;
|
||||
struct ImVec2;
|
||||
@@ -443,6 +444,8 @@ namespace hex {
|
||||
bool isWindowResizable();
|
||||
|
||||
void addAutoResetObject(hex::impl::AutoResetBase *object);
|
||||
void removeAutoResetObject(hex::impl::AutoResetBase *object);
|
||||
|
||||
void cleanup();
|
||||
|
||||
}
|
||||
@@ -492,6 +495,7 @@ namespace hex {
|
||||
*/
|
||||
float getNativeScale();
|
||||
|
||||
float getBackingScaleFactor();
|
||||
|
||||
/**
|
||||
* @brief Gets the current main window position
|
||||
@@ -580,6 +584,14 @@ namespace hex {
|
||||
*/
|
||||
const std::string& getGLRenderer();
|
||||
|
||||
/**
|
||||
* @brief Checks if ImHex is being run in a "Corporate Environment"
|
||||
* This function simply checks for common telltale signs such as if the machine is joined a
|
||||
* domain. It's not super accurate, but it's still useful for statistics
|
||||
* @return True if it is
|
||||
*/
|
||||
bool isCorporateEnvironment();
|
||||
|
||||
/**
|
||||
* @brief Checks if ImHex is running in portable mode
|
||||
* @return Whether ImHex is running in portable mode
|
||||
@@ -618,7 +630,7 @@ namespace hex {
|
||||
* @brief Gets the current ImHex version
|
||||
* @return ImHex version
|
||||
*/
|
||||
std::string getImHexVersion(bool withBuildType = true);
|
||||
SemanticVersion getImHexVersion();
|
||||
|
||||
/**
|
||||
* @brief Gets the current git commit hash
|
||||
@@ -695,6 +707,13 @@ namespace hex {
|
||||
*/
|
||||
void* getLibImHexModuleHandle();
|
||||
|
||||
/**
|
||||
* Adds a new migration routine that will be executed when upgrading from a lower version than specified in migrationVersion
|
||||
* @param migrationVersion Upgrade point version
|
||||
* @param function Function to run
|
||||
*/
|
||||
void addMigrationRoutine(SemanticVersion migrationVersion, std::function<void()> function);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -736,11 +755,8 @@ namespace hex {
|
||||
|
||||
const std::vector<Font>& getFonts();
|
||||
|
||||
void setCustomFontPath(const std::fs::path &path);
|
||||
void setFontSize(float size);
|
||||
void setFontAtlas(ImFontAtlas *fontAtlas);
|
||||
std::map<UnlocalizedString, ImFont*>& getFontDefinitions();
|
||||
|
||||
void setFonts(ImFont *bold, ImFont *italic);
|
||||
}
|
||||
|
||||
GlyphRange glyph(const char *glyph);
|
||||
@@ -753,26 +769,8 @@ namespace hex {
|
||||
|
||||
constexpr static float DefaultFontSize = 13.0;
|
||||
|
||||
ImFont* Bold();
|
||||
ImFont* Italic();
|
||||
|
||||
/**
|
||||
* @brief Gets the current custom font path
|
||||
* @return The current custom font path
|
||||
*/
|
||||
const std::filesystem::path& getCustomFontPath();
|
||||
|
||||
/**
|
||||
* @brief Gets the current font size
|
||||
* @return The current font size
|
||||
*/
|
||||
float getFontSize();
|
||||
|
||||
/**
|
||||
* @brief Gets the current font atlas
|
||||
* @return Current font atlas
|
||||
*/
|
||||
ImFontAtlas* getFontAtlas();
|
||||
void registerFont(const UnlocalizedString &fontName);
|
||||
ImFont* getFont(const UnlocalizedString &fontName);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
void loadLanguage(const std::string &language);
|
||||
void loadLanguage(std::string language);
|
||||
std::string getLocalizedString(const std::string &unlocalizedString, const std::string &language = "");
|
||||
|
||||
[[nodiscard]] const std::map<std::string, std::string> &getSupportedLanguages();
|
||||
@@ -101,10 +101,9 @@ namespace hex {
|
||||
public:
|
||||
UnlocalizedString() = default;
|
||||
|
||||
template<typename T>
|
||||
UnlocalizedString(T &&arg) : m_unlocalizedString(std::forward<T>(arg)) {
|
||||
static_assert(!std::same_as<std::remove_cvref_t<T>, Lang>, "Expected a unlocalized name, got a localized one!");
|
||||
}
|
||||
UnlocalizedString(const std::string &string) : m_unlocalizedString(string) { }
|
||||
UnlocalizedString(const char *string) : m_unlocalizedString(string) { }
|
||||
UnlocalizedString(const Lang& arg) = delete;
|
||||
|
||||
[[nodiscard]] operator std::string() const {
|
||||
return m_unlocalizedString;
|
||||
@@ -149,3 +148,10 @@ namespace hex {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
struct std::hash<hex::UnlocalizedString> {
|
||||
std::size_t operator()(const hex::UnlocalizedString &string) const noexcept {
|
||||
return std::hash<std::string>{}(string.get());
|
||||
}
|
||||
};
|
||||
@@ -15,11 +15,17 @@ struct ImGuiContext;
|
||||
namespace hex {
|
||||
|
||||
struct SubCommand {
|
||||
enum class Type : u8 {
|
||||
Option,
|
||||
SubCommand
|
||||
};
|
||||
|
||||
std::string commandLong;
|
||||
std::string commandShort;
|
||||
|
||||
std::string commandDescription;
|
||||
std::function<void(const std::vector<std::string>&)> callback;
|
||||
Type type = Type::Option;
|
||||
};
|
||||
|
||||
struct Feature {
|
||||
|
||||
@@ -2,137 +2,25 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/helpers/keys.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
struct ImGuiWindow;
|
||||
|
||||
struct KeyEquivalent {
|
||||
bool valid;
|
||||
bool ctrl, opt, cmd, shift;
|
||||
int key;
|
||||
};
|
||||
|
||||
namespace hex {
|
||||
|
||||
class View;
|
||||
|
||||
enum class Keys : u32 {
|
||||
Space = GLFW_KEY_SPACE,
|
||||
Apostrophe = GLFW_KEY_APOSTROPHE,
|
||||
Comma = GLFW_KEY_COMMA,
|
||||
Minus = GLFW_KEY_MINUS,
|
||||
Period = GLFW_KEY_PERIOD,
|
||||
Slash = GLFW_KEY_SLASH,
|
||||
Num0 = GLFW_KEY_0,
|
||||
Num1 = GLFW_KEY_1,
|
||||
Num2 = GLFW_KEY_2,
|
||||
Num3 = GLFW_KEY_3,
|
||||
Num4 = GLFW_KEY_4,
|
||||
Num5 = GLFW_KEY_5,
|
||||
Num6 = GLFW_KEY_6,
|
||||
Num7 = GLFW_KEY_7,
|
||||
Num8 = GLFW_KEY_8,
|
||||
Num9 = GLFW_KEY_9,
|
||||
Semicolon = GLFW_KEY_SEMICOLON,
|
||||
Equals = GLFW_KEY_EQUAL,
|
||||
A = GLFW_KEY_A,
|
||||
B = GLFW_KEY_B,
|
||||
C = GLFW_KEY_C,
|
||||
D = GLFW_KEY_D,
|
||||
E = GLFW_KEY_E,
|
||||
F = GLFW_KEY_F,
|
||||
G = GLFW_KEY_G,
|
||||
H = GLFW_KEY_H,
|
||||
I = GLFW_KEY_I,
|
||||
J = GLFW_KEY_J,
|
||||
K = GLFW_KEY_K,
|
||||
L = GLFW_KEY_L,
|
||||
M = GLFW_KEY_M,
|
||||
N = GLFW_KEY_N,
|
||||
O = GLFW_KEY_O,
|
||||
P = GLFW_KEY_P,
|
||||
Q = GLFW_KEY_Q,
|
||||
R = GLFW_KEY_R,
|
||||
S = GLFW_KEY_S,
|
||||
T = GLFW_KEY_T,
|
||||
U = GLFW_KEY_U,
|
||||
V = GLFW_KEY_V,
|
||||
W = GLFW_KEY_W,
|
||||
X = GLFW_KEY_X,
|
||||
Y = GLFW_KEY_Y,
|
||||
Z = GLFW_KEY_Z,
|
||||
LeftBracket = GLFW_KEY_LEFT_BRACKET,
|
||||
Backslash = GLFW_KEY_BACKSLASH,
|
||||
RightBracket = GLFW_KEY_RIGHT_BRACKET,
|
||||
GraveAccent = GLFW_KEY_GRAVE_ACCENT,
|
||||
World1 = GLFW_KEY_WORLD_1,
|
||||
World2 = GLFW_KEY_WORLD_2,
|
||||
Escape = GLFW_KEY_ESCAPE,
|
||||
Enter = GLFW_KEY_ENTER,
|
||||
Tab = GLFW_KEY_TAB,
|
||||
Backspace = GLFW_KEY_BACKSPACE,
|
||||
Insert = GLFW_KEY_INSERT,
|
||||
Delete = GLFW_KEY_DELETE,
|
||||
Right = GLFW_KEY_RIGHT,
|
||||
Left = GLFW_KEY_LEFT,
|
||||
Down = GLFW_KEY_DOWN,
|
||||
Up = GLFW_KEY_UP,
|
||||
PageUp = GLFW_KEY_PAGE_UP,
|
||||
PageDown = GLFW_KEY_PAGE_DOWN,
|
||||
Home = GLFW_KEY_HOME,
|
||||
End = GLFW_KEY_END,
|
||||
CapsLock = GLFW_KEY_CAPS_LOCK,
|
||||
ScrollLock = GLFW_KEY_SCROLL_LOCK,
|
||||
NumLock = GLFW_KEY_NUM_LOCK,
|
||||
PrintScreen = GLFW_KEY_PRINT_SCREEN,
|
||||
Pause = GLFW_KEY_PAUSE,
|
||||
F1 = GLFW_KEY_F1,
|
||||
F2 = GLFW_KEY_F2,
|
||||
F3 = GLFW_KEY_F3,
|
||||
F4 = GLFW_KEY_F4,
|
||||
F5 = GLFW_KEY_F5,
|
||||
F6 = GLFW_KEY_F6,
|
||||
F7 = GLFW_KEY_F7,
|
||||
F8 = GLFW_KEY_F8,
|
||||
F9 = GLFW_KEY_F9,
|
||||
F10 = GLFW_KEY_F10,
|
||||
F11 = GLFW_KEY_F11,
|
||||
F12 = GLFW_KEY_F12,
|
||||
F13 = GLFW_KEY_F13,
|
||||
F14 = GLFW_KEY_F14,
|
||||
F15 = GLFW_KEY_F15,
|
||||
F16 = GLFW_KEY_F16,
|
||||
F17 = GLFW_KEY_F17,
|
||||
F18 = GLFW_KEY_F18,
|
||||
F19 = GLFW_KEY_F19,
|
||||
F20 = GLFW_KEY_F20,
|
||||
F21 = GLFW_KEY_F21,
|
||||
F22 = GLFW_KEY_F22,
|
||||
F23 = GLFW_KEY_F23,
|
||||
F24 = GLFW_KEY_F24,
|
||||
F25 = GLFW_KEY_F25,
|
||||
KeyPad0 = GLFW_KEY_KP_0,
|
||||
KeyPad1 = GLFW_KEY_KP_1,
|
||||
KeyPad2 = GLFW_KEY_KP_2,
|
||||
KeyPad3 = GLFW_KEY_KP_3,
|
||||
KeyPad4 = GLFW_KEY_KP_4,
|
||||
KeyPad5 = GLFW_KEY_KP_5,
|
||||
KeyPad6 = GLFW_KEY_KP_6,
|
||||
KeyPad7 = GLFW_KEY_KP_7,
|
||||
KeyPad8 = GLFW_KEY_KP_8,
|
||||
KeyPad9 = GLFW_KEY_KP_9,
|
||||
KeyPadDecimal = GLFW_KEY_KP_DECIMAL,
|
||||
KeyPadDivide = GLFW_KEY_KP_DIVIDE,
|
||||
KeyPadMultiply = GLFW_KEY_KP_MULTIPLY,
|
||||
KeyPadSubtract = GLFW_KEY_KP_SUBTRACT,
|
||||
KeyPadAdd = GLFW_KEY_KP_ADD,
|
||||
KeyPadEnter = GLFW_KEY_KP_ENTER,
|
||||
KeyPadEqual = GLFW_KEY_KP_EQUAL,
|
||||
Menu = GLFW_KEY_MENU,
|
||||
};
|
||||
|
||||
|
||||
class Key {
|
||||
public:
|
||||
constexpr Key() = default;
|
||||
@@ -153,12 +41,7 @@ namespace hex {
|
||||
constexpr static auto SUPER = Key(static_cast<Keys>(0x0800'0000));
|
||||
constexpr static auto CurrentView = Key(static_cast<Keys>(0x1000'0000));
|
||||
constexpr static auto AllowWhileTyping = Key(static_cast<Keys>(0x2000'0000));
|
||||
|
||||
#if defined (OS_MACOS)
|
||||
constexpr static auto CTRLCMD = SUPER;
|
||||
#else
|
||||
constexpr static auto CTRLCMD = CTRL;
|
||||
#endif
|
||||
constexpr static auto CTRLCMD = Key(static_cast<Keys>(0x4000'0000));
|
||||
|
||||
class Shortcut {
|
||||
public:
|
||||
@@ -180,6 +63,7 @@ namespace hex {
|
||||
|
||||
bool isLocal() const;
|
||||
std::string toString() const;
|
||||
KeyEquivalent toKeyEquivalent() const;
|
||||
const std::set<Key>& getKeys() const;
|
||||
bool has(Key key) const;
|
||||
bool matches(const Shortcut &other) const;
|
||||
@@ -199,10 +83,12 @@ namespace hex {
|
||||
class ShortcutManager {
|
||||
public:
|
||||
using Callback = std::function<void()>;
|
||||
using EnabledCallback = std::function<bool()>;
|
||||
struct ShortcutEntry {
|
||||
Shortcut shortcut;
|
||||
std::vector<UnlocalizedString> unlocalizedName;
|
||||
Callback callback;
|
||||
EnabledCallback enabledCallback;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -210,9 +96,10 @@ namespace hex {
|
||||
* @param shortcut The shortcut to add.
|
||||
* @param unlocalizedName The unlocalized name of the shortcut
|
||||
* @param callback The callback to call when the shortcut is triggered.
|
||||
* @param enabledCallback Callback that's called to check if this shortcut is enabled
|
||||
*/
|
||||
static void addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback);
|
||||
static void addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback);
|
||||
static void addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||
static void addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||
|
||||
/**
|
||||
* @brief Add a view-specific shortcut. View-specific shortcuts can only be triggered when the specified view is focused.
|
||||
@@ -220,9 +107,10 @@ namespace hex {
|
||||
* @param shortcut The shortcut to add.
|
||||
* @param unlocalizedName The unlocalized name of the shortcut
|
||||
* @param callback The callback to call when the shortcut is triggered.
|
||||
* @param enabledCallback Callback that's called to check if this shortcut is enabled
|
||||
*/
|
||||
static void addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback);
|
||||
static void addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback);
|
||||
static void addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||
static void addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||
|
||||
|
||||
/**
|
||||
@@ -247,6 +135,14 @@ namespace hex {
|
||||
*/
|
||||
static void processGlobals(bool ctrl, bool alt, bool shift, bool super, u32 keyCode);
|
||||
|
||||
/**
|
||||
* @brief Runs the callback of a shortcut as if it was pressed on the keyboard
|
||||
* @param shortcut Shortcut to run
|
||||
* @param view View the shortcut belongs to or nullptr to run a global shortcut
|
||||
* @return True if a callback was executed, false if not
|
||||
*/
|
||||
static bool runShortcut(const Shortcut &shortcut, const View *view = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Clear all shortcuts
|
||||
*/
|
||||
@@ -255,6 +151,11 @@ namespace hex {
|
||||
static void resumeShortcuts();
|
||||
static void pauseShortcuts();
|
||||
|
||||
static void enableMacOSMode();
|
||||
|
||||
[[nodiscard]] static std::optional<UnlocalizedString> getLastActivatedMenu();
|
||||
static void resetLastActivatedMenu();
|
||||
|
||||
[[nodiscard]] static std::optional<Shortcut> getPreviousShortcut();
|
||||
|
||||
[[nodiscard]] static std::vector<ShortcutEntry> getGlobalShortcuts();
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace hex {
|
||||
class Task {
|
||||
public:
|
||||
Task() = default;
|
||||
Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function);
|
||||
Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function);
|
||||
|
||||
Task(const Task&) = delete;
|
||||
Task(Task &&other) noexcept;
|
||||
@@ -57,6 +57,7 @@ namespace hex {
|
||||
void setInterruptCallback(std::function<void()> callback);
|
||||
|
||||
[[nodiscard]] bool isBackgroundTask() const;
|
||||
[[nodiscard]] bool isBlocking() const;
|
||||
[[nodiscard]] bool isFinished() const;
|
||||
[[nodiscard]] bool hadException() const;
|
||||
[[nodiscard]] bool wasInterrupted() const;
|
||||
@@ -84,6 +85,7 @@ namespace hex {
|
||||
|
||||
std::atomic<bool> m_shouldInterrupt = false;
|
||||
std::atomic<bool> m_background = true;
|
||||
std::atomic<bool> m_blocking = false;
|
||||
|
||||
std::atomic<bool> m_interrupted = false;
|
||||
std::atomic<bool> m_finished = false;
|
||||
@@ -162,6 +164,24 @@ namespace hex {
|
||||
*/
|
||||
static TaskHolder createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void()> function);
|
||||
|
||||
/**
|
||||
* @brief Creates a new asynchronous task that shows a blocking modal window
|
||||
* @param unlocalizedName Name of the task
|
||||
* @param maxValue Maximum value of the task
|
||||
* @param function Function to be executed
|
||||
* @return A TaskHolder holding a weak reference to the task
|
||||
*/
|
||||
static TaskHolder createBlockingTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function);
|
||||
|
||||
/**
|
||||
* @brief Creates a new asynchronous task that shows a blocking modal window
|
||||
* @param unlocalizedName Name of the task
|
||||
* @param maxValue Maximum value of the task
|
||||
* @param function Function to be executed
|
||||
* @return A TaskHolder holding a weak reference to the task
|
||||
*/
|
||||
static TaskHolder createBlockingTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function);
|
||||
|
||||
/**
|
||||
* @brief Creates a new synchronous task that will execute the given function at the start of the next frame
|
||||
* @param function Function to be executed
|
||||
@@ -202,12 +222,13 @@ namespace hex {
|
||||
|
||||
static size_t getRunningTaskCount();
|
||||
static size_t getRunningBackgroundTaskCount();
|
||||
static size_t getRunningBlockingTaskCount();
|
||||
|
||||
static const std::list<std::shared_ptr<Task>>& getRunningTasks();
|
||||
static void runDeferredCalls();
|
||||
|
||||
private:
|
||||
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function);
|
||||
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -67,6 +67,7 @@ namespace hex {
|
||||
|
||||
static void reset();
|
||||
|
||||
static void setAccentColor(const ImColor &color);
|
||||
|
||||
public:
|
||||
struct ThemeHandler {
|
||||
@@ -82,6 +83,7 @@ namespace hex {
|
||||
static const std::map<std::string, ThemeHandler>& getThemeHandlers();
|
||||
static const std::map<std::string, StyleHandler>& getStyleHandlers();
|
||||
|
||||
|
||||
private:
|
||||
ThemeManager() = default;
|
||||
};
|
||||
|
||||
@@ -151,6 +151,9 @@ namespace hex {
|
||||
static void addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString);
|
||||
static void addInteractiveHelpLink(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, std::string link);
|
||||
|
||||
static void setLastItemInteractiveHelpPopup(std::function<void()> callback);
|
||||
static void setLastItemInteractiveHelpLink(std::string link);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Draws the tutorial
|
||||
|
||||
@@ -24,8 +24,8 @@ namespace hex {
|
||||
|
||||
static void removeWorkspace(const std::string &name);
|
||||
|
||||
static const auto& getWorkspaces() { return *s_workspaces; }
|
||||
static const auto& getCurrentWorkspace() { return s_currentWorkspace; }
|
||||
static const std::map<std::string, Workspace>& getWorkspaces();
|
||||
static const std::map<std::string, Workspace>::iterator& getCurrentWorkspace();
|
||||
|
||||
static void reset();
|
||||
static void reload();
|
||||
@@ -34,9 +34,6 @@ namespace hex {
|
||||
|
||||
private:
|
||||
WorkspaceManager() = default;
|
||||
|
||||
static AutoReset<std::map<std::string, Workspace>> s_workspaces;
|
||||
static decltype(s_workspaces)::Type::iterator s_currentWorkspace, s_previousWorkspace, s_workspaceToRemove;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
|
||||
namespace hex {
|
||||
@@ -24,6 +23,20 @@ namespace hex {
|
||||
ImHexApi::System::impl::addAutoResetObject(this);
|
||||
}
|
||||
|
||||
AutoReset(const T &value) : AutoReset() {
|
||||
m_value = value;
|
||||
m_valid = true;
|
||||
}
|
||||
|
||||
AutoReset(T &&value) noexcept : AutoReset() {
|
||||
m_value = std::move(value);
|
||||
m_valid = true;
|
||||
}
|
||||
|
||||
~AutoReset() {
|
||||
ImHexApi::System::impl::removeAutoResetObject(this);
|
||||
}
|
||||
|
||||
T* operator->() {
|
||||
return &m_value;
|
||||
}
|
||||
|
||||
@@ -44,4 +44,7 @@ namespace hex::dbg {
|
||||
}
|
||||
}
|
||||
|
||||
bool debugModeEnabled();
|
||||
void setDebugModeEnabled(bool enabled);
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
namespace hex::paths {
|
||||
@@ -82,8 +83,9 @@ namespace hex::paths {
|
||||
const static inline impl::DataPath Nodes("scripts/nodes");
|
||||
const static inline impl::DataPath Layouts("layouts");
|
||||
const static inline impl::DataPath Workspaces("workspaces");
|
||||
const static inline impl::DataPath Disassemblers("disassemblers");
|
||||
|
||||
constexpr static inline std::array<const impl::DefaultPath*, 20> All = {
|
||||
constexpr static inline std::array<const impl::DefaultPath*, 21> All = {
|
||||
&Config,
|
||||
&Recent,
|
||||
|
||||
@@ -106,6 +108,7 @@ namespace hex::paths {
|
||||
&Nodes,
|
||||
&Layouts,
|
||||
&Workspaces,
|
||||
&Disassemblers
|
||||
};
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <string_view>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/ranges.h>
|
||||
#include <fmt/ostream.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
|
||||
@@ -12,10 +12,6 @@
|
||||
|
||||
#if defined(OS_WEB)
|
||||
#include <emscripten/fetch.h>
|
||||
|
||||
using curl_off_t = long;
|
||||
#else
|
||||
#include <curl/curl.h>
|
||||
#endif
|
||||
|
||||
typedef void CURL;
|
||||
@@ -121,18 +117,18 @@ namespace hex {
|
||||
|
||||
static std::string urlDecode(const std::string &input);
|
||||
|
||||
protected:
|
||||
void setDefaultConfig();
|
||||
void setProgress(float progress) { m_progress = progress; }
|
||||
bool isCanceled() const { return m_canceled; }
|
||||
|
||||
static size_t writeToVector(void *contents, size_t size, size_t nmemb, void *userdata);
|
||||
static size_t writeToFile(void *contents, size_t size, size_t nmemb, void *userdata);
|
||||
|
||||
template<typename T>
|
||||
Result<T> executeImpl(std::vector<u8> &data);
|
||||
|
||||
static size_t writeToVector(void *contents, size_t size, size_t nmemb, void *userdata);
|
||||
static size_t writeToFile(void *contents, size_t size, size_t nmemb, void *userdata);
|
||||
static int progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow);
|
||||
|
||||
private:
|
||||
static void checkProxyErrors();
|
||||
void setDefaultConfig();
|
||||
|
||||
private:
|
||||
#if defined(OS_WEB)
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#include <string>
|
||||
#include <future>
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
|
||||
@@ -14,14 +12,26 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace impl {
|
||||
|
||||
void setWriteFunctions(CURL *curl, wolv::io::File &file);
|
||||
void setWriteFunctions(CURL *curl, std::vector<u8> &data);
|
||||
void setupFileUpload(CURL *curl, wolv::io::File &file, const std::string &fileName, const std::string &mimeName);
|
||||
void setupFileUpload(CURL *curl, const std::vector<u8> &data, const std::fs::path &fileName, const std::string &mimeName);
|
||||
int executeCurl(CURL *curl, const std::string &url, const std::string &method, const std::string &body, std::map<std::string, std::string> &headers);
|
||||
long getStatusCode(CURL *curl);
|
||||
std::string getStatusText(int result);
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
std::future<HttpRequest::Result<T>> HttpRequest::downloadFile(const std::fs::path &path) {
|
||||
return std::async(std::launch::async, [this, path] {
|
||||
std::vector<u8> response;
|
||||
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToFile);
|
||||
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &file);
|
||||
impl::setWriteFunctions(m_curl, file);
|
||||
|
||||
return this->executeImpl<T>(response);
|
||||
});
|
||||
@@ -31,40 +41,12 @@
|
||||
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(const std::fs::path &path, const std::string &mimeName) {
|
||||
return std::async(std::launch::async, [this, path, mimeName]{
|
||||
auto fileName = wolv::util::toUTF8String(path.filename());
|
||||
|
||||
curl_mime *mime = curl_mime_init(m_curl);
|
||||
curl_mimepart *part = curl_mime_addpart(mime);
|
||||
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Read);
|
||||
|
||||
curl_mime_data_cb(part, file.getSize(),
|
||||
[](char *buffer, size_t size, size_t nitems, void *arg) -> size_t {
|
||||
auto handle = static_cast<FILE*>(arg);
|
||||
|
||||
return fread(buffer, size, nitems, handle);
|
||||
},
|
||||
[](void *arg, curl_off_t offset, int origin) -> int {
|
||||
auto handle = static_cast<FILE*>(arg);
|
||||
|
||||
if (fseek(handle, offset, origin) != 0)
|
||||
return CURL_SEEKFUNC_CANTSEEK;
|
||||
else
|
||||
return CURL_SEEKFUNC_OK;
|
||||
},
|
||||
[](void *arg) {
|
||||
auto handle = static_cast<FILE*>(arg);
|
||||
|
||||
fclose(handle);
|
||||
},
|
||||
file.getHandle());
|
||||
curl_mime_filename(part, fileName.c_str());
|
||||
curl_mime_name(part, mimeName.c_str());
|
||||
|
||||
curl_easy_setopt(m_curl, CURLOPT_MIMEPOST, mime);
|
||||
impl::setupFileUpload(m_curl, file, fileName, mimeName);
|
||||
|
||||
std::vector<u8> responseData;
|
||||
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
|
||||
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &responseData);
|
||||
impl::setWriteFunctions(m_curl, responseData);
|
||||
|
||||
return this->executeImpl<T>(responseData);
|
||||
});
|
||||
@@ -73,19 +55,10 @@
|
||||
template<typename T>
|
||||
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(std::vector<u8> data, const std::string &mimeName, const std::fs::path &fileName) {
|
||||
return std::async(std::launch::async, [this, data = std::move(data), mimeName, fileName]{
|
||||
curl_mime *mime = curl_mime_init(m_curl);
|
||||
curl_mimepart *part = curl_mime_addpart(mime);
|
||||
|
||||
curl_mime_data(part, reinterpret_cast<const char *>(data.data()), data.size());
|
||||
auto fileNameStr = wolv::util::toUTF8String(fileName.filename());
|
||||
curl_mime_filename(part, fileNameStr.c_str());
|
||||
curl_mime_name(part, mimeName.c_str());
|
||||
|
||||
curl_easy_setopt(m_curl, CURLOPT_MIMEPOST, mime);
|
||||
impl::setupFileUpload(m_curl, data, fileName, mimeName);
|
||||
|
||||
std::vector<u8> responseData;
|
||||
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
|
||||
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &responseData);
|
||||
impl::setWriteFunctions(m_curl, responseData);
|
||||
|
||||
return this->executeImpl<T>(responseData);
|
||||
});
|
||||
@@ -96,8 +69,7 @@
|
||||
return std::async(std::launch::async, [this] {
|
||||
|
||||
std::vector<u8> responseData;
|
||||
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
|
||||
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &responseData);
|
||||
impl::setWriteFunctions(m_curl, responseData);
|
||||
|
||||
return this->executeImpl<T>(responseData);
|
||||
});
|
||||
@@ -105,43 +77,16 @@
|
||||
|
||||
template<typename T>
|
||||
HttpRequest::Result<T> HttpRequest::executeImpl(std::vector<u8> &data) {
|
||||
curl_easy_setopt(m_curl, CURLOPT_URL, m_url.c_str());
|
||||
curl_easy_setopt(m_curl, CURLOPT_CUSTOMREQUEST, m_method.c_str());
|
||||
|
||||
setDefaultConfig();
|
||||
|
||||
if (!m_body.empty()) {
|
||||
curl_easy_setopt(m_curl, CURLOPT_POSTFIELDS, m_body.c_str());
|
||||
std::scoped_lock lock(m_transmissionMutex);
|
||||
|
||||
if (auto result = impl::executeCurl(m_curl, m_url, m_method, m_body, m_headers); result != 0) {
|
||||
log::error("Http request '{0} {1}' failed with error {2}: '{3}'", m_method, m_url, u32(result), impl::getStatusText(result));
|
||||
checkProxyErrors();
|
||||
}
|
||||
|
||||
curl_slist *headers = nullptr;
|
||||
headers = curl_slist_append(headers, "Cache-Control: no-cache");
|
||||
ON_SCOPE_EXIT { curl_slist_free_all(headers); };
|
||||
|
||||
for (auto &[key, value] : m_headers) {
|
||||
std::string header = hex::format("{}: {}", key, value);
|
||||
headers = curl_slist_append(headers, header.c_str());
|
||||
}
|
||||
curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, headers);
|
||||
|
||||
{
|
||||
std::scoped_lock lock(m_transmissionMutex);
|
||||
|
||||
auto result = curl_easy_perform(m_curl);
|
||||
if (result != CURLE_OK){
|
||||
char *url = nullptr;
|
||||
curl_easy_getinfo(m_curl, CURLINFO_EFFECTIVE_URL, &url);
|
||||
log::error("Http request '{0} {1}' failed with error {2}: '{3}'", m_method, url, u32(result), curl_easy_strerror(result));
|
||||
checkProxyErrors();
|
||||
|
||||
return { };
|
||||
}
|
||||
}
|
||||
|
||||
long statusCode = 0;
|
||||
curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &statusCode);
|
||||
|
||||
return Result<T>(statusCode, { data.begin(), data.end() });
|
||||
return Result<T>(impl::getStatusCode(m_curl), { data.begin(), data.end() });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
124
lib/libimhex/include/hex/helpers/keys.hpp
Normal file
124
lib/libimhex/include/hex/helpers/keys.hpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__cplusplus)
|
||||
enum class Keys {
|
||||
#else
|
||||
enum Keys {
|
||||
#endif
|
||||
Invalid,
|
||||
Space,
|
||||
Apostrophe,
|
||||
Comma,
|
||||
Minus,
|
||||
Period,
|
||||
Slash,
|
||||
Num0,
|
||||
Num1,
|
||||
Num2,
|
||||
Num3,
|
||||
Num4,
|
||||
Num5,
|
||||
Num6,
|
||||
Num7,
|
||||
Num8,
|
||||
Num9,
|
||||
Semicolon,
|
||||
Equals,
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
I,
|
||||
J,
|
||||
K,
|
||||
L,
|
||||
M,
|
||||
N,
|
||||
O,
|
||||
P,
|
||||
Q,
|
||||
R,
|
||||
S,
|
||||
T,
|
||||
U,
|
||||
V,
|
||||
W,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
LeftBracket,
|
||||
Backslash,
|
||||
RightBracket,
|
||||
GraveAccent,
|
||||
World1,
|
||||
World2,
|
||||
Escape,
|
||||
Enter,
|
||||
Tab,
|
||||
Backspace,
|
||||
Insert,
|
||||
Delete,
|
||||
Right,
|
||||
Left,
|
||||
Down,
|
||||
Up,
|
||||
PageUp,
|
||||
PageDown,
|
||||
Home,
|
||||
End,
|
||||
CapsLock,
|
||||
ScrollLock,
|
||||
NumLock,
|
||||
PrintScreen,
|
||||
Pause,
|
||||
F1,
|
||||
F2,
|
||||
F3,
|
||||
F4,
|
||||
F5,
|
||||
F6,
|
||||
F7,
|
||||
F8,
|
||||
F9,
|
||||
F10,
|
||||
F11,
|
||||
F12,
|
||||
F13,
|
||||
F14,
|
||||
F15,
|
||||
F16,
|
||||
F17,
|
||||
F18,
|
||||
F19,
|
||||
F20,
|
||||
F21,
|
||||
F22,
|
||||
F23,
|
||||
F24,
|
||||
F25,
|
||||
KeyPad0,
|
||||
KeyPad1,
|
||||
KeyPad2,
|
||||
KeyPad3,
|
||||
KeyPad4,
|
||||
KeyPad5,
|
||||
KeyPad6,
|
||||
KeyPad7,
|
||||
KeyPad8,
|
||||
KeyPad9,
|
||||
KeyPadDecimal,
|
||||
KeyPadDivide,
|
||||
KeyPadMultiply,
|
||||
KeyPadSubtract,
|
||||
KeyPadAdd,
|
||||
KeyPadEnter,
|
||||
KeyPadEqual,
|
||||
Menu
|
||||
};
|
||||
|
||||
enum Keys scanCodeToKey(int scanCode);
|
||||
int keyToScanCode(enum Keys key);
|
||||
25
lib/libimhex/include/hex/helpers/menu_items.hpp
Normal file
25
lib/libimhex/include/hex/helpers/menu_items.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include <hex/api/shortcut_manager.hpp>
|
||||
|
||||
namespace hex::menu {
|
||||
|
||||
void enableNativeMenuBar(bool enabled);
|
||||
bool isNativeMenuBarUsed();
|
||||
|
||||
bool beginMainMenuBar();
|
||||
void endMainMenuBar();
|
||||
|
||||
bool beginMenu(const char *label, bool enabled = true);
|
||||
void endMenu();
|
||||
|
||||
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);
|
||||
bool menuItem(const char *label, const Shortcut &shortcut, bool *selected, bool enabled = true);
|
||||
|
||||
bool menuItemEx(const char *label, const char *icon, const Shortcut &shortcut = Shortcut::None, bool selected = false, bool enabled = true);
|
||||
bool menuItemEx(const char *label, const char *icon, const Shortcut &shortcut, bool *selected, bool enabled = true);
|
||||
|
||||
void menuSeparator();
|
||||
|
||||
}
|
||||
@@ -9,9 +9,9 @@
|
||||
#include <map>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <numbers>
|
||||
|
||||
#include <opengl_support.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include "imgui.h"
|
||||
|
||||
namespace hex::gl {
|
||||
@@ -188,43 +188,43 @@ namespace hex::gl {
|
||||
|
||||
|
||||
T &getElement(int row,int col) {
|
||||
return this->mat[row*Columns+col];
|
||||
return this->mat[row * Columns+col];
|
||||
}
|
||||
|
||||
Vector<T,Rows> getColumn(int col) {
|
||||
Vector<T,Rows> result;
|
||||
for (size_t i = 0; i < Rows; i++)
|
||||
result[i] = this->mat[i*Columns+col];
|
||||
result[i] = this->mat[i * Columns + col];
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector<T,Columns> getRow(int row) {
|
||||
Vector<T,Columns> result;
|
||||
for (size_t i = 0; i < Columns; i++)
|
||||
result[i] = this->mat[row*Columns+i];
|
||||
result[i] = this->mat[row * Columns+i];
|
||||
return result;
|
||||
}
|
||||
|
||||
void updateRow(int row, Vector<T,Columns> values) {
|
||||
for (size_t i = 0; i < Columns; i++)
|
||||
this->mat[row*Columns+i] = values[i];
|
||||
this->mat[row * Columns + i] = values[i];
|
||||
}
|
||||
|
||||
void updateColumn(int col, Vector<T,Rows> values) {
|
||||
for (size_t i = 0; i < Rows; i++)
|
||||
this->mat[i*Columns+col] = values[i];
|
||||
this->mat[i * Columns + col] = values[i];
|
||||
}
|
||||
|
||||
void updateElement( int row,int col, T value) {
|
||||
this->mat[row*Columns + col] = value;
|
||||
void updateElement(int row, int col, T value) {
|
||||
this->mat[row * Columns + col] = value;
|
||||
}
|
||||
|
||||
T &operator()( const int &row,const int &col) {
|
||||
return this->mat[row*Columns + col];
|
||||
T &operator()(const unsigned &row, const unsigned &col) {
|
||||
return this->mat[row * Columns + col];
|
||||
}
|
||||
|
||||
const T &operator()(const unsigned& row,const unsigned& col ) const {
|
||||
return this->mat[row*Columns + col];
|
||||
const T &operator()(const unsigned &row, const unsigned &col) const {
|
||||
return this->mat[row * Columns + col];
|
||||
}
|
||||
|
||||
Matrix& operator=(const Matrix& A) {
|
||||
@@ -242,7 +242,7 @@ namespace hex::gl {
|
||||
|
||||
for (size_t i = 0; i < Rows; i++)
|
||||
for (size_t j = 0; j < Columns; j++)
|
||||
result(i, j) = this->mat[i*Columns+j] + A(i, j);
|
||||
result(i, j) = this->mat[i * Columns + j] + A(i, j);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -251,7 +251,7 @@ namespace hex::gl {
|
||||
|
||||
for (size_t i = 0; i < Rows; i++)
|
||||
for (size_t j = 0; j < Columns; j++)
|
||||
result(i, j) = this->mat[i*Columns+j] - A(i, j);
|
||||
result(i, j) = this->mat[i * Columns + j] - A(i, j);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ namespace hex::gl {
|
||||
Matrix t(0);
|
||||
for (size_t i = 0; i < Columns; i++)
|
||||
for (size_t j = 0; j < Rows; j++)
|
||||
t.updateElement(i, j, this->mat[j*Rows+i]);
|
||||
t.updateElement(i, j, this->mat[j * Rows + i]);
|
||||
|
||||
return t;
|
||||
}
|
||||
@@ -400,8 +400,8 @@ namespace hex::gl {
|
||||
|
||||
T Sx, Cx, Sy, Cy, Sz, Cz;
|
||||
Vector<T,3> angles = ypr;
|
||||
if(!radians)
|
||||
angles *= M_PI/180;
|
||||
if (!radians)
|
||||
angles *= std::numbers::pi_v<T> / 180;
|
||||
|
||||
Sx = -sin(angles[0]); Cx = cos(angles[0]);
|
||||
Sy = -sin(angles[1]); Cy = cos(angles[1]);
|
||||
@@ -524,7 +524,7 @@ namespace hex::gl {
|
||||
Vector<T,3> rotationVector3 = {{rotationVector[0], rotationVector[1], rotationVector[2]}};
|
||||
T theta = rotationVector3.magnitude();
|
||||
if (!radians)
|
||||
theta *= M_PI / 180;
|
||||
theta *= std::numbers::pi / 180;
|
||||
Vector<T,3> axis = rotationVector3;
|
||||
if (theta != 0)
|
||||
axis = axis.normalize();
|
||||
@@ -807,16 +807,18 @@ namespace hex::gl {
|
||||
void bind() const;
|
||||
void unbind() const;
|
||||
|
||||
bool isValid() const { return m_program != 0; }
|
||||
|
||||
void setUniform(std::string_view name, const int &value);
|
||||
void setUniform(std::string_view name, const float &value);
|
||||
|
||||
template<size_t N>
|
||||
void setUniform(std::string_view name, const Vector<float, N> &value) {
|
||||
if (N == 2)
|
||||
if constexpr (N == 2)
|
||||
glUniform2f(getUniformLocation(name), value[0], value[1]);
|
||||
else if (N == 3)
|
||||
else if constexpr (N == 3)
|
||||
glUniform3f(getUniformLocation(name), value[0], value[1], value[2]);
|
||||
else if (N == 4)
|
||||
else if constexpr (N == 4)
|
||||
glUniform4f(getUniformLocation(name), value[0], value[1], value[2],value[3]);
|
||||
}
|
||||
|
||||
|
||||
36
lib/libimhex/include/hex/helpers/semantic_version.hpp
Normal file
36
lib/libimhex/include/hex/helpers/semantic_version.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <compare>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace hex {
|
||||
|
||||
class SemanticVersion {
|
||||
public:
|
||||
SemanticVersion() = default;
|
||||
SemanticVersion(std::string version);
|
||||
SemanticVersion(std::string_view version);
|
||||
SemanticVersion(const char *version);
|
||||
|
||||
std::strong_ordering operator<=>(const SemanticVersion &) const;
|
||||
bool operator==(const SemanticVersion &other) const;
|
||||
|
||||
u32 major() const;
|
||||
u32 minor() const;
|
||||
u32 patch() const;
|
||||
bool nightly() const;
|
||||
const std::string& buildType() const;
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
std::string get(bool withBuildType = true) const;
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_parts;
|
||||
std::string m_buildType;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -6,17 +6,10 @@
|
||||
#include <concepts>
|
||||
#include <type_traits>
|
||||
|
||||
using u8 = std::uint8_t;
|
||||
using u16 = std::uint16_t;
|
||||
using u32 = std::uint32_t;
|
||||
using u64 = std::uint64_t;
|
||||
using u128 = __uint128_t;
|
||||
#include <wolv/types.hpp>
|
||||
|
||||
using i8 = std::int8_t;
|
||||
using i16 = std::int16_t;
|
||||
using i32 = std::int32_t;
|
||||
using i64 = std::int64_t;
|
||||
using i128 = __int128_t;
|
||||
using namespace wolv::unsigned_integers;
|
||||
using namespace wolv::signed_integers;
|
||||
|
||||
using color_t = u32;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <hex/helpers/utils_linux.hpp>
|
||||
#endif
|
||||
|
||||
struct ImVec2;
|
||||
#include <imgui.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace hex {
|
||||
template<typename T>
|
||||
[[nodiscard]] std::vector<std::vector<T>> sampleChannels(const std::vector<T> &data, size_t count, size_t channels) {
|
||||
if (channels == 0) return {};
|
||||
size_t signalLength = std::max(1.0, double(data.size()) / channels);
|
||||
size_t signalLength = std::max<double>(1.0, double(data.size()) / channels);
|
||||
|
||||
size_t stride = std::max(1.0, double(signalLength) / count);
|
||||
|
||||
@@ -109,13 +109,13 @@ namespace hex {
|
||||
[[nodiscard]] std::wstring utf8ToUtf16(const std::string& utf8);
|
||||
[[nodiscard]] std::string utf16ToUtf8(const std::wstring& utf16);
|
||||
|
||||
[[nodiscard]] constexpr u64 extract(u8 from, u8 to, const std::unsigned_integral auto &value) {
|
||||
[[nodiscard]] constexpr u64 extract(u8 from, u8 to, const auto &value) {
|
||||
if (from < to) std::swap(from, to);
|
||||
|
||||
using ValueType = std::remove_cvref_t<decltype(value)>;
|
||||
ValueType mask = (std::numeric_limits<ValueType>::max() >> (((sizeof(value) * 8) - 1) - (from - to))) << to;
|
||||
|
||||
return (value & mask) >> to;
|
||||
return u64((value & mask) >> to);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline u64 extract(u32 from, u32 to, const std::vector<u8> &bytes) {
|
||||
@@ -278,7 +278,7 @@ namespace hex {
|
||||
|
||||
std::string result;
|
||||
for (i16 bit = hex::bit_width(number) - 1; bit >= 0; bit -= 1)
|
||||
result += (number & (0b1 << bit)) == 0 ? '0' : '1';
|
||||
result += (number & (0b1LLU << bit)) == 0 ? '0' : '1';
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -340,4 +340,6 @@ namespace hex {
|
||||
*/
|
||||
[[nodiscard]] void* getContainingModule(void* symbol);
|
||||
|
||||
[[nodiscard]] std::optional<ImColor> blendColors(const std::optional<ImColor> &a, const std::optional<ImColor> &b);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/helpers/keys.hpp>
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
|
||||
struct GLFWwindow;
|
||||
@@ -17,8 +19,15 @@
|
||||
void enumerateFontsMacos();
|
||||
|
||||
void macosHandleTitlebarDoubleClickGesture(GLFWwindow *window);
|
||||
void macosSetWindowMovable(GLFWwindow *window, bool movable);
|
||||
bool macosIsWindowBeingResizedByUser(GLFWwindow *window);
|
||||
void macosMarkContentEdited(GLFWwindow *window, bool edited = true);
|
||||
|
||||
void macosGetKey(Keys key, int *output);
|
||||
|
||||
bool macosIsMainInstance();
|
||||
void macosSendMessageToMainInstance(const unsigned char *data, size_t size);
|
||||
void macosInstallEventListener();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,13 @@
|
||||
#include <wolv/utils/preproc.hpp>
|
||||
#include <wolv/utils/guards.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <windows.h>
|
||||
#define PLUGIN_ENTRY_POINT extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return TRUE; }
|
||||
#else
|
||||
#define PLUGIN_ENTRY_POINT
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
struct PluginFunctionHelperInstantiation {};
|
||||
}
|
||||
@@ -45,7 +52,11 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
|
||||
#if defined (IMHEX_STATIC_LINK_PLUGINS)
|
||||
#define IMHEX_PLUGIN_VISIBILITY_PREFIX static
|
||||
#else
|
||||
#define IMHEX_PLUGIN_VISIBILITY_PREFIX extern "C" [[gnu::visibility("default")]]
|
||||
#if defined(_MSC_VER)
|
||||
#define IMHEX_PLUGIN_VISIBILITY_PREFIX extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define IMHEX_PLUGIN_VISIBILITY_PREFIX extern "C" [[gnu::visibility("default")]]
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define IMHEX_FEATURE_ENABLED(feature) WOLV_TOKEN_CONCAT(WOLV_TOKEN_CONCAT(WOLV_TOKEN_CONCAT(IMHEX_PLUGIN_, IMHEX_PLUGIN_NAME), _FEATURE_), feature)
|
||||
@@ -70,14 +81,13 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
|
||||
#define IMHEX_LIBRARY_SETUP(name) IMHEX_LIBRARY_SETUP_IMPL(name)
|
||||
|
||||
#define IMHEX_LIBRARY_SETUP_IMPL(name) \
|
||||
namespace { static struct EXIT_HANDLER { ~EXIT_HANDLER() { hex::log::info("Unloaded library '{}'", name); } } HANDLER; } \
|
||||
IMHEX_PLUGIN_VISIBILITY_PREFIX void WOLV_TOKEN_CONCAT(initializeLibrary_, IMHEX_PLUGIN_NAME)(); \
|
||||
IMHEX_PLUGIN_VISIBILITY_PREFIX const char *WOLV_TOKEN_CONCAT(getLibraryName_, IMHEX_PLUGIN_NAME)() { return name; } \
|
||||
IMHEX_PLUGIN_VISIBILITY_PREFIX void WOLV_TOKEN_CONCAT(setImGuiContext_, IMHEX_PLUGIN_NAME)(ImGuiContext *ctx) { \
|
||||
ImGui::SetCurrentContext(ctx); \
|
||||
GImGui = ctx; \
|
||||
} \
|
||||
extern "C" [[gnu::visibility("default")]] void WOLV_TOKEN_CONCAT(forceLinkPlugin_, IMHEX_PLUGIN_NAME)() { \
|
||||
extern "C" void WOLV_TOKEN_CONCAT(forceLinkPlugin_, IMHEX_PLUGIN_NAME)() { \
|
||||
hex::PluginManager::addPlugin(name, hex::PluginFunctions { \
|
||||
nullptr, \
|
||||
WOLV_TOKEN_CONCAT(initializeLibrary_, IMHEX_PLUGIN_NAME), \
|
||||
@@ -92,10 +102,10 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
|
||||
nullptr \
|
||||
}); \
|
||||
} \
|
||||
PLUGIN_ENTRY_POINT \
|
||||
IMHEX_PLUGIN_VISIBILITY_PREFIX void WOLV_TOKEN_CONCAT(initializeLibrary_, IMHEX_PLUGIN_NAME)()
|
||||
|
||||
#define IMHEX_PLUGIN_SETUP_IMPL(name, author, description) \
|
||||
namespace { static struct EXIT_HANDLER { ~EXIT_HANDLER() { hex::log::debug("Unloaded plugin '{}'", name); } } HANDLER; } \
|
||||
IMHEX_PLUGIN_VISIBILITY_PREFIX const char *getPluginName() { return name; } \
|
||||
IMHEX_PLUGIN_VISIBILITY_PREFIX const char *getPluginAuthor() { return author; } \
|
||||
IMHEX_PLUGIN_VISIBILITY_PREFIX const char *getPluginDescription() { return description; } \
|
||||
@@ -112,7 +122,7 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
|
||||
return PluginSubCommandsFunctionHelper<PluginFunctionHelperInstantiation>::getSubCommands(); \
|
||||
} \
|
||||
IMHEX_PLUGIN_VISIBILITY_PREFIX void initializePlugin(); \
|
||||
extern "C" [[gnu::visibility("default")]] void WOLV_TOKEN_CONCAT(forceLinkPlugin_, IMHEX_PLUGIN_NAME)() { \
|
||||
extern "C" void WOLV_TOKEN_CONCAT(forceLinkPlugin_, IMHEX_PLUGIN_NAME)() { \
|
||||
hex::PluginManager::addPlugin(name, hex::PluginFunctions { \
|
||||
initializePlugin, \
|
||||
nullptr, \
|
||||
@@ -127,6 +137,7 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
|
||||
getFeatures \
|
||||
}); \
|
||||
} \
|
||||
PLUGIN_ENTRY_POINT \
|
||||
IMHEX_PLUGIN_VISIBILITY_PREFIX void initializePlugin()
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace hex::prv {
|
||||
|
||||
[[nodiscard]] std::string getName() const override { return m_name; }
|
||||
|
||||
[[nodiscard]] std::string getTypeName() const override { return "MemoryProvider"; }
|
||||
[[nodiscard]] UnlocalizedString getTypeName() const override { return "MemoryProvider"; }
|
||||
private:
|
||||
void renameFile();
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace hex::prv {
|
||||
|
||||
struct MenuEntry {
|
||||
std::string name;
|
||||
const char *icon;
|
||||
std::function<void()> callback;
|
||||
};
|
||||
|
||||
@@ -113,7 +114,7 @@ namespace hex::prv {
|
||||
* @param size number of bytes to read
|
||||
* @param overlays apply overlays and patches is true. Same as readRaw() if false
|
||||
*/
|
||||
void read(u64 offset, void *buffer, size_t size, bool overlays = true);
|
||||
virtual void read(u64 offset, void *buffer, size_t size, bool overlays = true);
|
||||
|
||||
/**
|
||||
* @brief Write data to the patches of this provider. Will not directly modify provider.
|
||||
@@ -121,7 +122,7 @@ namespace hex::prv {
|
||||
* @param buffer buffer to take data to write from
|
||||
* @param size number of bytes to write
|
||||
*/
|
||||
void write(u64 offset, const void *buffer, size_t size);
|
||||
virtual void write(u64 offset, const void *buffer, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Read data from this provider, without applying overlays and patches
|
||||
@@ -151,7 +152,7 @@ namespace hex::prv {
|
||||
* like "hex.builtin.provider.mem_file" or "hex.builtin.provider.file"
|
||||
* @return The provider's type name
|
||||
*/
|
||||
[[nodiscard]] virtual std::string getTypeName() const = 0;
|
||||
[[nodiscard]] virtual UnlocalizedString getTypeName() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Gets a human readable representation of the current provider
|
||||
@@ -193,11 +194,11 @@ namespace hex::prv {
|
||||
[[nodiscard]] virtual std::vector<Description> getDataDescription() const;
|
||||
[[nodiscard]] virtual std::variant<std::string, i128> queryInformation(const std::string &category, const std::string &argument);
|
||||
|
||||
void undo();
|
||||
void redo();
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
[[nodiscard]] bool canUndo() const;
|
||||
[[nodiscard]] bool canRedo() const;
|
||||
[[nodiscard]] virtual bool canUndo() const;
|
||||
[[nodiscard]] virtual bool canRedo() const;
|
||||
|
||||
[[nodiscard]] virtual bool hasFilePicker() const;
|
||||
virtual bool handleFilePicker();
|
||||
@@ -231,7 +232,7 @@ namespace hex::prv {
|
||||
return m_undoRedoStack.add<T>(std::forward<decltype(args)...>(args)...);
|
||||
}
|
||||
|
||||
[[nodiscard]] undo::Stack& getUndoStack() { return m_undoRedoStack; }
|
||||
[[nodiscard]] virtual undo::Stack& getUndoStack() { return m_undoRedoStack; }
|
||||
|
||||
protected:
|
||||
u32 m_currPage = 0;
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/events/events_provider.hpp>
|
||||
#include <hex/api/events/events_lifecycle.hpp>
|
||||
#include <hex/api/events/requests_provider.hpp>
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <ranges>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/events/events_interaction.hpp>
|
||||
|
||||
#include <hex/providers/undo_redo/operations/operation.hpp>
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace hex::test {
|
||||
return m_data->size();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string getTypeName() const override { return "hex.test.provider.test"; }
|
||||
[[nodiscard]] UnlocalizedString getTypeName() const override { return "hex.test.provider.test"; }
|
||||
|
||||
bool open() override { return true; }
|
||||
void close() override { }
|
||||
|
||||
57
lib/libimhex/include/hex/ui/banner.hpp
Normal file
57
lib/libimhex/include/hex/ui/banner.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include "hex/api/localization_manager.hpp"
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace impl {
|
||||
|
||||
class BannerBase {
|
||||
public:
|
||||
BannerBase(ImColor color) : m_color(color) {}
|
||||
virtual ~BannerBase() = default;
|
||||
|
||||
virtual void draw() { drawContent(); }
|
||||
virtual void drawContent() = 0;
|
||||
|
||||
[[nodiscard]] static std::list<std::unique_ptr<BannerBase>> &getOpenBanners();
|
||||
|
||||
[[nodiscard]] const ImColor& getColor() const {
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void close() { m_shouldClose = true; }
|
||||
[[nodiscard]] bool shouldClose() const { return m_shouldClose; }
|
||||
|
||||
protected:
|
||||
static std::mutex& getMutex();
|
||||
|
||||
bool m_shouldClose = false;
|
||||
ImColor m_color;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class Banner : public impl::BannerBase {
|
||||
public:
|
||||
using impl::BannerBase::BannerBase;
|
||||
|
||||
template<typename ...Args>
|
||||
static void open(Args && ... args) {
|
||||
std::lock_guard lock(getMutex());
|
||||
|
||||
auto toast = std::make_unique<T>(std::forward<Args>(args)...);
|
||||
getOpenBanners().emplace_back(std::move(toast));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -79,17 +79,16 @@ namespace ImGuiExt {
|
||||
Texture(const Texture&) = delete;
|
||||
Texture(Texture&& other) noexcept;
|
||||
|
||||
static Texture fromImage(const ImU8 *buffer, int size, Filter filter = Filter::Nearest);
|
||||
static Texture fromImage(std::span<const std::byte> buffer, Filter filter = Filter::Nearest);
|
||||
static Texture fromImage(const char *path, Filter filter = Filter::Nearest);
|
||||
static Texture fromImage(const std::fs::path &path, Filter filter = Filter::Nearest);
|
||||
static Texture fromGLTexture(unsigned int texture, int width, int height);
|
||||
static Texture fromBitmap(const ImU8 *buffer, int size, int width, int height, Filter filter = Filter::Nearest);
|
||||
static Texture fromBitmap(std::span<const std::byte> buffer, int width, int height, Filter filter = Filter::Nearest);
|
||||
static Texture fromSVG(const char *path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
static Texture fromSVG(const std::fs::path &path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
static Texture fromSVG(std::span<const std::byte> buffer, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
|
||||
[[nodiscard]] static Texture fromImage(const ImU8 *buffer, int size, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromImage(std::span<const std::byte> buffer, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromImage(const char *path, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromImage(const std::fs::path &path, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromGLTexture(unsigned int texture, int width, int height);
|
||||
[[nodiscard]] static Texture fromBitmap(const ImU8 *buffer, int size, int width, int height, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromBitmap(std::span<const std::byte> buffer, int width, int height, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromSVG(const char *path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromSVG(const std::fs::path &path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromSVG(std::span<const std::byte> buffer, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
|
||||
~Texture();
|
||||
|
||||
@@ -114,6 +113,8 @@ namespace ImGuiExt {
|
||||
return float(m_width) / float(m_height);
|
||||
}
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
ImTextureID m_textureId = 0;
|
||||
int m_width = 0, m_height = 0;
|
||||
@@ -144,13 +145,13 @@ namespace ImGuiExt {
|
||||
|
||||
bool TitleBarButton(const char *label, ImVec2 size_arg);
|
||||
bool ToolBarButton(const char *symbol, ImVec4 color);
|
||||
bool IconButton(const char *symbol, ImVec4 color, ImVec2 size_arg = ImVec2(0, 0));
|
||||
bool IconButton(const char *symbol, ImVec4 color, ImVec2 size_arg = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
|
||||
|
||||
bool InputIntegerPrefix(const char* label, const char *prefix, void *value, ImGuiDataType type, const char *format, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||
bool InputHexadecimal(const char* label, u32 *value, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||
bool InputHexadecimal(const char* label, u64 *value, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||
|
||||
bool SliderBytes(const char *label, u64 *value, u64 min, u64 max, ImGuiSliderFlags flags = ImGuiSliderFlags_None);
|
||||
bool SliderBytes(const char *label, u64 *value, u64 min, u64 max, u64 stepSize = 1, ImGuiSliderFlags flags = ImGuiSliderFlags_None);
|
||||
|
||||
inline bool HasSecondPassed() {
|
||||
return static_cast<ImU32>(ImGui::GetTime() * 100) % 100 <= static_cast<ImU32>(ImGui::GetIO().DeltaTime * 100);
|
||||
@@ -158,6 +159,8 @@ namespace ImGuiExt {
|
||||
|
||||
void OpenPopupInWindow(const char *window_name, const char *popup_name);
|
||||
|
||||
void DisableWindowResize(ImGuiDir dir);
|
||||
|
||||
struct ImHexCustomData {
|
||||
ImVec4 Colors[ImGuiCustomCol_COUNT];
|
||||
|
||||
@@ -183,7 +186,7 @@ namespace ImGuiExt {
|
||||
void StyleCustomColorsLight();
|
||||
void StyleCustomColorsClassic();
|
||||
|
||||
void SmallProgressBar(float fraction, float yOffset = 0.0F);
|
||||
void ProgressBar(float fraction, ImVec2 size_value = ImVec2(0, 0), float yOffset = 0.0F);
|
||||
|
||||
inline void TextFormatted(std::string_view fmt, auto &&...args) {
|
||||
if constexpr (sizeof...(args) == 0) {
|
||||
@@ -200,14 +203,15 @@ namespace ImGuiExt {
|
||||
ImGui::PushID(text.c_str());
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2());
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0F);
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4());
|
||||
|
||||
ImGui::PushItemWidth(ImGui::CalcTextSize(text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2);
|
||||
ImGui::InputText("##", const_cast<char *>(text.c_str()), text.size(), ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoHorizontalScroll);
|
||||
ImGui::InputText("##", const_cast<char *>(text.c_str()), text.size() + 1, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoHorizontalScroll);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
@@ -235,29 +239,32 @@ namespace ImGuiExt {
|
||||
|
||||
inline void TextFormattedWrappedSelectable(std::string_view fmt, auto &&...args) {
|
||||
// Manually wrap text, using the letter M (generally the widest character in non-monospaced fonts) to calculate the character width to use.
|
||||
auto text = wolv::util::wrapMonospacedString(
|
||||
auto text = wolv::util::trim(wolv::util::wrapMonospacedString(
|
||||
hex::format(fmt, std::forward<decltype(args)>(args)...),
|
||||
ImGui::CalcTextSize("M").x,
|
||||
ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize - ImGui::GetStyle().FrameBorderSize
|
||||
);
|
||||
));
|
||||
|
||||
auto textSize = ImGui::CalcTextSize(text.c_str());
|
||||
|
||||
ImGui::PushID(text.c_str());
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2());
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0F);
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4());
|
||||
|
||||
ImGui::PushItemWidth(ImGui::CalcTextSize(text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2);
|
||||
ImGui::InputTextMultiline(
|
||||
"##",
|
||||
const_cast<char *>(text.c_str()),
|
||||
text.size(),
|
||||
ImVec2(0, -FLT_MIN),
|
||||
text.size() + 1,
|
||||
ImVec2(0, textSize.y),
|
||||
ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoHorizontalScroll
|
||||
);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
@@ -291,8 +298,8 @@ namespace ImGuiExt {
|
||||
bool BitCheckbox(const char* label, bool* v);
|
||||
|
||||
bool DimmedButton(const char* label, ImVec2 size = ImVec2(0, 0));
|
||||
bool DimmedIconButton(const char *symbol, ImVec4 color, ImVec2 size = ImVec2(0, 0));
|
||||
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size);
|
||||
bool DimmedIconButton(const char *symbol, ImVec4 color, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
|
||||
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
|
||||
bool DimmedIconToggle(const char *icon, bool *v);
|
||||
bool DimmedIconToggle(const char *iconOn, const char *iconOff, bool *v);
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/shortcut_manager.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
@@ -99,6 +98,14 @@ namespace hex {
|
||||
|
||||
[[nodiscard]] static std::string toWindowName(const UnlocalizedString &unlocalizedName);
|
||||
|
||||
[[nodiscard]] bool isFocused() const { return m_focused; }
|
||||
|
||||
/**
|
||||
* @brief Used for focus handling. Don't use this directly
|
||||
* @param focused Whether this view is focused
|
||||
*/
|
||||
void setFocused(bool focused) { m_focused = focused; }
|
||||
|
||||
public:
|
||||
class Window;
|
||||
class Special;
|
||||
@@ -111,6 +118,7 @@ namespace hex {
|
||||
std::map<Shortcut, ShortcutManager::ShortcutEntry> m_shortcuts;
|
||||
bool m_windowJustOpened = false;
|
||||
const char *m_icon;
|
||||
bool m_focused = false;
|
||||
|
||||
friend class ShortcutManager;
|
||||
};
|
||||
@@ -175,7 +183,7 @@ namespace hex {
|
||||
|
||||
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
|
||||
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
||||
if (ImGui::BeginPopupModal(View::toWindowName(this->getUnlocalizedName()).c_str(), this->hasCloseButton() ? &this->getWindowOpenState() : nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize | this->getWindowFlags())) {
|
||||
if (ImGui::BeginPopupModal(View::toWindowName(this->getUnlocalizedName()).c_str(), this->hasCloseButton() ? &this->getWindowOpenState() : nullptr, ImGuiWindowFlags_NoCollapse | this->getWindowFlags())) {
|
||||
this->drawContent();
|
||||
|
||||
ImGui::EndPopup();
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
#include <hex/api/achievement_manager.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/events/events_interaction.hpp>
|
||||
|
||||
#include <hex/helpers/auto_reset.hpp>
|
||||
#include <hex/helpers/default_paths.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#if defined(OS_WEB)
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
namespace hex {
|
||||
|
||||
static AutoReset<std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>>> s_achievements;
|
||||
const std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>> &AchievementManager::getAchievements() {
|
||||
static AutoReset<std::unordered_map<UnlocalizedString, std::unordered_map<UnlocalizedString, std::unique_ptr<Achievement>>>> s_achievements;
|
||||
const std::unordered_map<UnlocalizedString, std::unordered_map<UnlocalizedString, std::unique_ptr<Achievement>>> &AchievementManager::getAchievements() {
|
||||
return *s_achievements;
|
||||
}
|
||||
|
||||
static AutoReset<std::unordered_map<std::string, std::list<AchievementManager::AchievementNode>>> s_nodeCategoryStorage;
|
||||
std::unordered_map<std::string, std::list<AchievementManager::AchievementNode>>& getAchievementNodesMutable(bool rebuild) {
|
||||
static AutoReset<std::unordered_map<UnlocalizedString, std::list<AchievementManager::AchievementNode>>> s_nodeCategoryStorage;
|
||||
std::unordered_map<UnlocalizedString, std::list<AchievementManager::AchievementNode>>& getAchievementNodesMutable(bool rebuild) {
|
||||
if (!s_nodeCategoryStorage->empty() || !rebuild)
|
||||
return s_nodeCategoryStorage;
|
||||
|
||||
@@ -32,12 +36,12 @@ namespace hex {
|
||||
return s_nodeCategoryStorage;
|
||||
}
|
||||
|
||||
const std::unordered_map<std::string, std::list<AchievementManager::AchievementNode>>& AchievementManager::getAchievementNodes(bool rebuild) {
|
||||
const std::unordered_map<UnlocalizedString, std::list<AchievementManager::AchievementNode>>& AchievementManager::getAchievementNodes(bool rebuild) {
|
||||
return getAchievementNodesMutable(rebuild);
|
||||
}
|
||||
|
||||
static AutoReset<std::unordered_map<std::string, std::vector<AchievementManager::AchievementNode*>>> s_startNodes;
|
||||
const std::unordered_map<std::string, std::vector<AchievementManager::AchievementNode*>>& AchievementManager::getAchievementStartNodes(bool rebuild) {
|
||||
static AutoReset<std::unordered_map<UnlocalizedString, std::vector<AchievementManager::AchievementNode*>>> s_startNodes;
|
||||
const std::unordered_map<UnlocalizedString, std::vector<AchievementManager::AchievementNode*>>& AchievementManager::getAchievementStartNodes(bool rebuild) {
|
||||
|
||||
if (!s_startNodes->empty() || !rebuild)
|
||||
return s_startNodes;
|
||||
@@ -183,10 +187,10 @@ namespace hex {
|
||||
const auto &category = newAchievement->getUnlocalizedCategory();
|
||||
const auto &name = newAchievement->getUnlocalizedName();
|
||||
|
||||
auto [categoryIter, categoryInserted] = s_achievements->insert({ category, std::unordered_map<std::string, std::unique_ptr<Achievement>>{} });
|
||||
auto [categoryIter, categoryInserted] = s_achievements->insert({ category, std::unordered_map<UnlocalizedString, std::unique_ptr<Achievement>>{} });
|
||||
auto &[categoryKey, achievements] = *categoryIter;
|
||||
|
||||
auto [achievementIter, achievementInserted] = achievements.insert({ name, std::move(newAchievement) });
|
||||
auto [achievementIter, achievementInserted] = achievements.emplace(name, std::move(newAchievement));
|
||||
auto &[achievementKey, achievement] = *achievementIter;
|
||||
|
||||
achievementAdded();
|
||||
@@ -215,7 +219,16 @@ namespace hex {
|
||||
}
|
||||
|
||||
try {
|
||||
auto json = nlohmann::json::parse(file.readString());
|
||||
#if defined(OS_WEB)
|
||||
auto data = (char *) MAIN_THREAD_EM_ASM_INT({
|
||||
let data = localStorage.getItem("achievements");
|
||||
return data ? stringToNewUTF8(data) : null;
|
||||
});
|
||||
#else
|
||||
auto data = file.readString();
|
||||
#endif
|
||||
|
||||
auto json = nlohmann::json::parse(data);
|
||||
|
||||
for (const auto &[categoryName, achievements] : getAchievements()) {
|
||||
for (const auto &[achievementName, achievement] : achievements) {
|
||||
@@ -226,7 +239,7 @@ namespace hex {
|
||||
|
||||
achievement->setProgress(progress);
|
||||
} catch (const std::exception &e) {
|
||||
log::warn("Failed to load achievement progress for '{}::{}': {}", categoryName, achievementName, e.what());
|
||||
log::warn("Failed to load achievement progress for '{}::{}': {}", categoryName.get(), achievementName.get(), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,16 +267,23 @@ namespace hex {
|
||||
if (json.empty())
|
||||
return;
|
||||
|
||||
for (const auto &directory : paths::Config.write()) {
|
||||
auto path = directory / AchievementsFile;
|
||||
#if defined(OS_WEB)
|
||||
auto data = json.dump();
|
||||
MAIN_THREAD_EM_ASM({
|
||||
localStorage.setItem("achievements", UTF8ToString($0));
|
||||
}, data.c_str());
|
||||
#else
|
||||
for (const auto &directory : paths::Config.write()) {
|
||||
auto path = directory / AchievementsFile;
|
||||
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||
if (!file.isValid())
|
||||
continue;
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||
if (!file.isValid())
|
||||
continue;
|
||||
|
||||
file.writeString(json.dump(4));
|
||||
break;
|
||||
}
|
||||
file.writeString(json.dump(4));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/shortcut_manager.hpp>
|
||||
#include <hex/api/events/requests_provider.hpp>
|
||||
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
@@ -32,12 +33,40 @@ namespace hex {
|
||||
namespace impl {
|
||||
|
||||
struct OnChange {
|
||||
u32 id;
|
||||
u64 id;
|
||||
OnChangeCallback callback;
|
||||
};
|
||||
|
||||
static AutoReset<std::map<std::string, std::map<std::string, std::vector<OnChange>>>> s_onChangeCallbacks;
|
||||
|
||||
static void runAllOnChangeCallbacks() {
|
||||
for (const auto &[category, rest] : *impl::s_onChangeCallbacks) {
|
||||
for (const auto &[name, callbacks] : rest) {
|
||||
for (const auto &[id, callback] : callbacks) {
|
||||
try {
|
||||
callback(getSetting(category, name, {}));
|
||||
} catch (const std::exception &e) {
|
||||
log::error("Failed to load setting [{}/{}]: {}", category, name, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void runOnChangeHandlers(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const nlohmann::json &value) {
|
||||
if (auto categoryIt = s_onChangeCallbacks->find(unlocalizedCategory); categoryIt != s_onChangeCallbacks->end()) {
|
||||
if (auto nameIt = categoryIt->second.find(unlocalizedName); nameIt != categoryIt->second.end()) {
|
||||
for (const auto &[id, callback] : nameIt->second) {
|
||||
try {
|
||||
callback(value);
|
||||
} catch (const nlohmann::json::exception &e) {
|
||||
log::error("Failed to run onChange handler for setting {}/{}: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static AutoReset<nlohmann::json> s_settings;
|
||||
const nlohmann::json& getSettingsData() {
|
||||
return s_settings;
|
||||
@@ -72,24 +101,28 @@ namespace hex {
|
||||
s_settings = nlohmann::json::parse(data);
|
||||
}
|
||||
|
||||
for (const auto &[category, rest] : *impl::s_onChangeCallbacks) {
|
||||
for (const auto &[name, callbacks] : rest) {
|
||||
for (const auto &[id, callback] : callbacks) {
|
||||
try {
|
||||
callback(getSetting(category, name, {}));
|
||||
} catch (const std::exception &e) {
|
||||
log::error("Failed to load setting [{}/{}]: {}", category, name, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
runAllOnChangeCallbacks();
|
||||
}
|
||||
|
||||
void store() {
|
||||
auto data = s_settings->dump();
|
||||
if (!s_settings.isValid())
|
||||
return;
|
||||
|
||||
const auto &settingsData = *s_settings;
|
||||
|
||||
// During a crash settings can be empty, causing them to be overwritten.
|
||||
if (settingsData.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto result = settingsData.dump(4);
|
||||
if (result.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MAIN_THREAD_EM_ASM({
|
||||
localStorage.setItem("config", UTF8ToString($0));
|
||||
}, data.c_str());
|
||||
}, result.c_str());
|
||||
}
|
||||
|
||||
void clear() {
|
||||
@@ -115,17 +148,7 @@ namespace hex {
|
||||
if (!loaded)
|
||||
store();
|
||||
|
||||
for (const auto &[category, rest] : *impl::s_onChangeCallbacks) {
|
||||
for (const auto &[name, callbacks] : rest) {
|
||||
for (const auto &[id, callback] : callbacks) {
|
||||
try {
|
||||
callback(getSetting(category, name, {}));
|
||||
} catch (const std::exception &e) {
|
||||
log::error("Failed to load setting [{}/{}]: {}", category, name, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
runAllOnChangeCallbacks();
|
||||
}
|
||||
|
||||
void store() {
|
||||
@@ -135,7 +158,7 @@ namespace hex {
|
||||
const auto &settingsData = *s_settings;
|
||||
|
||||
// During a crash settings can be empty, causing them to be overwritten.
|
||||
if (settingsData.empty()) {
|
||||
if (s_settings->empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -201,6 +224,8 @@ namespace hex {
|
||||
log::error("Failed to load setting [{} / {}]: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
|
||||
}
|
||||
});
|
||||
|
||||
runOnChangeHandlers(unlocalizedCategory, unlocalizedName, getSetting(unlocalizedCategory, unlocalizedName, entry->widget->store()));
|
||||
}
|
||||
|
||||
return entry->widget.get();
|
||||
@@ -210,20 +235,6 @@ namespace hex {
|
||||
hex::log::error("Failed to read setting {}/{}: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
|
||||
}
|
||||
|
||||
void runOnChangeHandlers(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const nlohmann::json &value) {
|
||||
if (auto categoryIt = s_onChangeCallbacks->find(unlocalizedCategory); categoryIt != s_onChangeCallbacks->end()) {
|
||||
if (auto nameIt = categoryIt->second.find(unlocalizedName); nameIt != categoryIt->second.end()) {
|
||||
for (const auto &[id, callback] : nameIt->second) {
|
||||
try {
|
||||
callback(value);
|
||||
} catch (const nlohmann::json::exception &e) {
|
||||
log::error("Failed to run onChange handler for setting {}/{}: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void setCategoryDescription(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedDescription) {
|
||||
@@ -325,7 +336,7 @@ namespace hex {
|
||||
|
||||
|
||||
bool SliderDataSize::draw(const std::string &name) {
|
||||
return ImGuiExt::SliderBytes(name.c_str(), &m_value, m_min, m_max);
|
||||
return ImGuiExt::SliderBytes(name.c_str(), &m_value, m_min, m_max, m_stepSize);
|
||||
}
|
||||
|
||||
void SliderDataSize::load(const nlohmann::json &data) {
|
||||
@@ -341,17 +352,34 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
ColorPicker::ColorPicker(ImColor defaultColor) {
|
||||
m_value = {
|
||||
defaultColor.Value.x,
|
||||
defaultColor.Value.y,
|
||||
defaultColor.Value.z,
|
||||
defaultColor.Value.w
|
||||
ColorPicker::ColorPicker(ImColor defaultColor, ImGuiColorEditFlags flags) {
|
||||
m_defaultValue = m_value = {
|
||||
defaultColor.Value.x,
|
||||
defaultColor.Value.y,
|
||||
defaultColor.Value.z,
|
||||
defaultColor.Value.w
|
||||
};
|
||||
m_flags = flags;
|
||||
}
|
||||
|
||||
bool ColorPicker::draw(const std::string &name) {
|
||||
return ImGui::ColorEdit4(name.c_str(), m_value.data(), ImGuiColorEditFlags_NoInputs);
|
||||
ImGui::PushID(name.c_str());
|
||||
auto result = ImGui::ColorEdit4("##color_picker", m_value.data(), ImGuiColorEditFlags_NoInputs | m_flags);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("X", ImGui::GetStyle().FramePadding * 2 + ImVec2(ImGui::GetTextLineHeight(), ImGui::GetTextLineHeight()))) {
|
||||
m_value = m_defaultValue;
|
||||
result = true;
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::TextUnformatted(name.c_str());
|
||||
|
||||
ImGui::PopID();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ColorPicker::load(const nlohmann::json &data) {
|
||||
@@ -377,7 +405,7 @@ namespace hex {
|
||||
bool DropDown::draw(const std::string &name) {
|
||||
auto preview = "";
|
||||
if (static_cast<size_t>(m_value) < m_items.size())
|
||||
preview = m_items[m_value].c_str();
|
||||
preview = m_items[m_value].get().c_str();
|
||||
|
||||
bool changed = false;
|
||||
if (ImGui::BeginCombo(name.c_str(), Lang(preview))) {
|
||||
@@ -630,7 +658,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
runtime.addDefine("__IMHEX__");
|
||||
runtime.addDefine("__IMHEX_VERSION__", ImHexApi::System::getImHexVersion());
|
||||
runtime.addDefine("__IMHEX_VERSION__", ImHexApi::System::getImHexVersion().get());
|
||||
}
|
||||
|
||||
void addPragma(const std::string &name, const pl::api::PragmaHandler &handler) {
|
||||
@@ -686,15 +714,15 @@ namespace hex {
|
||||
|
||||
namespace impl {
|
||||
|
||||
static AutoReset<std::map<std::string, std::unique_ptr<View>>> s_views;
|
||||
const std::map<std::string, std::unique_ptr<View>>& getEntries() {
|
||||
static AutoReset<std::map<UnlocalizedString, std::unique_ptr<View>>> s_views;
|
||||
const std::map<UnlocalizedString, std::unique_ptr<View>>& getEntries() {
|
||||
return *s_views;
|
||||
}
|
||||
|
||||
void add(std::unique_ptr<View> &&view) {
|
||||
log::debug("Registered new view: {}", view->getUnlocalizedName().get());
|
||||
|
||||
s_views->insert({ view->getUnlocalizedName(), std::move(view) });
|
||||
s_views->emplace(view->getUnlocalizedName(), std::move(view));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -708,6 +736,15 @@ namespace hex {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
View* getFocusedView() {
|
||||
for (const auto &[unlocalizedName, view] : *impl::s_views) {
|
||||
if (view->isFocused())
|
||||
return view.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::Tools {
|
||||
@@ -752,6 +789,14 @@ namespace hex {
|
||||
impl::s_entries->push_back({ unlocalizedName, requiredSize, maxSize, std::move(displayGeneratorFunction), std::move(editingFunction) });
|
||||
}
|
||||
|
||||
void drawMenuItems(const std::function<void()> &function) {
|
||||
if (ImGui::BeginPopup("##DataInspectorRowContextMenu")) {
|
||||
function();
|
||||
ImGui::Separator();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::DataProcessorNode {
|
||||
@@ -917,17 +962,10 @@ namespace hex {
|
||||
});
|
||||
|
||||
if (shortcut != Shortcut::None) {
|
||||
auto callbackIfEnabled = [enabledCallback, function]{ if (enabledCallback()) { function(); } };
|
||||
|
||||
const auto unlocalizedShortcutName =
|
||||
unlocalizedMainMenuNames.size() == 1 ?
|
||||
std::vector { unlocalizedMainMenuNames.back() } :
|
||||
std::vector(unlocalizedMainMenuNames.begin() + 1, unlocalizedMainMenuNames.end());
|
||||
|
||||
if (shortcut.isLocal() && view != nullptr)
|
||||
ShortcutManager::addShortcut(view, shortcut, unlocalizedShortcutName, callbackIfEnabled);
|
||||
ShortcutManager::addShortcut(view, shortcut, unlocalizedMainMenuNames, function, enabledCallback);
|
||||
else
|
||||
ShortcutManager::addGlobalShortcut(shortcut, unlocalizedShortcutName, callbackIfEnabled);
|
||||
ShortcutManager::addGlobalShortcut(shortcut, unlocalizedMainMenuNames, function, enabledCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1097,7 +1135,9 @@ namespace hex {
|
||||
|
||||
namespace ContentRegistry::HexEditor {
|
||||
|
||||
const int DataVisualizer::TextInputFlags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoHorizontalScroll | ImGuiInputTextFlags_AlwaysOverwrite;
|
||||
int DataVisualizer::DefaultTextInputFlags() {
|
||||
return ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoHorizontalScroll | ImGuiInputTextFlags_AlwaysOverwrite;
|
||||
}
|
||||
|
||||
bool DataVisualizer::drawDefaultScalarEditingTextBox(u64 address, const char *format, ImGuiDataType dataType, u8 *data, ImGuiInputTextFlags flags) const {
|
||||
struct UserData {
|
||||
@@ -1115,7 +1155,7 @@ namespace hex {
|
||||
};
|
||||
|
||||
ImGui::PushID(reinterpret_cast<void*>(address));
|
||||
ImGuiExt::InputScalarCallback("##editing_input", dataType, data, format, flags | TextInputFlags | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int {
|
||||
ImGuiExt::InputScalarCallback("##editing_input", dataType, data, format, flags | DefaultTextInputFlags() | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int {
|
||||
auto &userData = *static_cast<UserData*>(data->UserData);
|
||||
|
||||
if (data->CursorPos >= userData.maxChars)
|
||||
@@ -1146,7 +1186,7 @@ namespace hex {
|
||||
};
|
||||
|
||||
ImGui::PushID(reinterpret_cast<void*>(address));
|
||||
ImGui::InputText("##editing_input", data.data(), data.size() + 1, flags | TextInputFlags | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int {
|
||||
ImGui::InputText("##editing_input", data.data(), data.size() + 1, flags | DefaultTextInputFlags() | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int {
|
||||
auto &userData = *static_cast<UserData*>(data->UserData);
|
||||
|
||||
userData.data->resize(data->BufSize);
|
||||
@@ -1391,4 +1431,23 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::Disassembler {
|
||||
|
||||
namespace impl {
|
||||
|
||||
static AutoReset<std::map<std::string, impl::CreatorFunction>> s_architectures;
|
||||
|
||||
void addArchitectureCreator(impl::CreatorFunction function) {
|
||||
const auto arch = function();
|
||||
(*s_architectures)[arch->getName()] = std::move(function);
|
||||
}
|
||||
|
||||
const std::map<std::string, impl::CreatorFunction>& getArchitectures() {
|
||||
return *s_architectures;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/events/events_provider.hpp>
|
||||
#include <hex/api/events/events_lifecycle.hpp>
|
||||
#include <hex/api/events/events_gui.hpp>
|
||||
#include <hex/api/events/requests_interaction.hpp>
|
||||
#include <hex/api/events/requests_lifecycle.hpp>
|
||||
#include <hex/api/events/requests_provider.hpp>
|
||||
#include <hex/api/events/requests_gui.hpp>
|
||||
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
@@ -11,6 +18,7 @@
|
||||
#include <wolv/utils/string.hpp>
|
||||
|
||||
#include <utility>
|
||||
#include <numeric>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
@@ -18,13 +26,20 @@
|
||||
#include <algorithm>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <hex/helpers/utils_macos.hpp>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#include <windows.h>
|
||||
#include <DSRole.h>
|
||||
#else
|
||||
#include <sys/utsname.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(OS_WEB)
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
namespace hex {
|
||||
|
||||
|
||||
@@ -447,7 +462,7 @@ namespace hex {
|
||||
if (s_providers->empty())
|
||||
EventProviderChanged::post(provider, nullptr);
|
||||
|
||||
EventProviderClosed::post(it->get());
|
||||
EventProviderClosed::post(providerToRemove);
|
||||
RequestUpdateWindowTitle::post();
|
||||
|
||||
// Do the destruction of the provider in the background once all tasks have finished
|
||||
@@ -559,13 +574,22 @@ namespace hex {
|
||||
return s_windowResizable;
|
||||
}
|
||||
|
||||
static std::vector<hex::impl::AutoResetBase*> s_autoResetObjects;
|
||||
static auto& getAutoResetObjects() {
|
||||
static std::set<hex::impl::AutoResetBase*> autoResetObjects;
|
||||
|
||||
return autoResetObjects;
|
||||
}
|
||||
|
||||
void addAutoResetObject(hex::impl::AutoResetBase *object) {
|
||||
s_autoResetObjects.emplace_back(object);
|
||||
getAutoResetObjects().insert(object);
|
||||
}
|
||||
|
||||
void removeAutoResetObject(hex::impl::AutoResetBase *object) {
|
||||
getAutoResetObjects().erase(object);
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
for (const auto &object : s_autoResetObjects)
|
||||
for (const auto &object : getAutoResetObjects())
|
||||
object->reset();
|
||||
}
|
||||
|
||||
@@ -608,6 +632,28 @@ namespace hex {
|
||||
return impl::s_nativeScale;
|
||||
}
|
||||
|
||||
float getBackingScaleFactor() {
|
||||
#if defined(OS_WINDOWS)
|
||||
return 1.0F;
|
||||
#elif defined(OS_MACOS)
|
||||
return ::getBackingScaleFactor();
|
||||
#elif defined(OS_LINUX)
|
||||
const auto sessionType = hex::getEnvironmentVariable("XDG_SESSION_TYPE");
|
||||
if (!sessionType.has_value() || sessionType == "x11")
|
||||
return 1.0F;
|
||||
else {
|
||||
float xScale = 0, yScale = 0;
|
||||
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &xScale, &yScale);
|
||||
|
||||
return std::midpoint(xScale, yScale);
|
||||
}
|
||||
#elif defined(OS_WEB)
|
||||
return 1.0F;
|
||||
#else
|
||||
return 1.0F;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
ImVec2 getMainWindowPosition() {
|
||||
if ((ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) != ImGuiConfigFlags_None)
|
||||
@@ -645,6 +691,14 @@ namespace hex {
|
||||
return hex::getContainingModule(reinterpret_cast<void*>(&getLibImHexModuleHandle));
|
||||
}
|
||||
|
||||
void addMigrationRoutine(SemanticVersion migrationVersion, std::function<void()> function) {
|
||||
EventImHexUpdated::subscribe([migrationVersion, function](const SemanticVersion &oldVersion, const SemanticVersion &newVersion) {
|
||||
if (oldVersion < migrationVersion && newVersion >= migrationVersion) {
|
||||
function();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const std::map<std::string, std::string>& getInitArguments() {
|
||||
return *impl::s_initArguments;
|
||||
@@ -689,6 +743,28 @@ namespace hex {
|
||||
return impl::s_glRenderer;
|
||||
}
|
||||
|
||||
bool isCorporateEnvironment() {
|
||||
#if defined(OS_WINDOWS)
|
||||
{
|
||||
DSROLE_PRIMARY_DOMAIN_INFO_BASIC * info;
|
||||
if ((DsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic, (PBYTE *)&info) == ERROR_SUCCESS) && (info != nullptr))
|
||||
{
|
||||
bool result = std::wstring(info->DomainNameFlat) != L"WORKGROUP";
|
||||
DsRoleFreeMemory(info);
|
||||
|
||||
return result;
|
||||
} else {
|
||||
DWORD size = 128;
|
||||
char buffer[128];
|
||||
::GetComputerNameExA(ComputerNameDnsDomain, buffer, &size);
|
||||
return size > 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool isPortableVersion() {
|
||||
static std::optional<bool> portable;
|
||||
if (portable.has_value())
|
||||
@@ -794,16 +870,12 @@ namespace hex {
|
||||
return { { name, version } };
|
||||
}
|
||||
|
||||
std::string getImHexVersion(bool withBuildType) {
|
||||
SemanticVersion getImHexVersion() {
|
||||
#if defined IMHEX_VERSION
|
||||
if (withBuildType) {
|
||||
return IMHEX_VERSION;
|
||||
} else {
|
||||
auto version = std::string(IMHEX_VERSION);
|
||||
return version.substr(0, version.find('-'));
|
||||
}
|
||||
static auto version = SemanticVersion(IMHEX_VERSION);
|
||||
return version;
|
||||
#else
|
||||
return "Unknown";
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -837,7 +909,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
bool isNightlyBuild() {
|
||||
return getImHexVersion(false).ends_with("WIP");
|
||||
return getImHexVersion().nightly();
|
||||
}
|
||||
|
||||
bool updateImHex(UpdateType updateType) {
|
||||
@@ -865,7 +937,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
EventImHexClosing::subscribe([executablePath, updateTypeString] {
|
||||
hex::executeCommand(
|
||||
hex::startProgram(
|
||||
hex::format("\"{}\" \"{}\"",
|
||||
wolv::util::toUTF8String(executablePath),
|
||||
updateTypeString
|
||||
@@ -935,11 +1007,6 @@ namespace hex {
|
||||
return *s_fonts;
|
||||
}
|
||||
|
||||
static AutoReset<std::fs::path> s_customFontPath;
|
||||
void setCustomFontPath(const std::fs::path &path) {
|
||||
s_customFontPath = path;
|
||||
}
|
||||
|
||||
static float s_fontSize = DefaultFontSize;
|
||||
void setFontSize(float size) {
|
||||
s_fontSize = size;
|
||||
@@ -957,6 +1024,10 @@ namespace hex {
|
||||
s_italicFont = italic;
|
||||
}
|
||||
|
||||
static AutoReset<std::map<UnlocalizedString, ImFont*>> s_fontDefinitions;
|
||||
std::map<UnlocalizedString, ImFont*>& getFontDefinitions() {
|
||||
return *s_fontDefinitions;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1021,10 +1092,6 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
const std::fs::path& getCustomFontPath() {
|
||||
return impl::s_customFontPath;
|
||||
}
|
||||
|
||||
float getFontSize() {
|
||||
return impl::s_fontSize;
|
||||
}
|
||||
@@ -1033,6 +1100,14 @@ namespace hex {
|
||||
return impl::s_fontAtlas;
|
||||
}
|
||||
|
||||
void registerFont(const UnlocalizedString &fontName) {
|
||||
(*impl::s_fontDefinitions)[fontName] = nullptr;
|
||||
}
|
||||
|
||||
ImFont* getFont(const UnlocalizedString &fontName) {
|
||||
return (*impl::s_fontDefinitions)[fontName];
|
||||
}
|
||||
|
||||
ImFont* Bold() {
|
||||
return impl::s_boldFont;
|
||||
}
|
||||
|
||||
@@ -56,18 +56,19 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
void loadLanguage(const std::string &language) {
|
||||
void loadLanguage(std::string language) {
|
||||
auto &definitions = ContentRegistry::Language::impl::getLanguageDefinitions();
|
||||
|
||||
const auto& fallbackLanguage = getFallbackLanguage();
|
||||
if (!definitions.contains(language))
|
||||
return;
|
||||
language = fallbackLanguage;
|
||||
|
||||
s_currStrings->clear();
|
||||
|
||||
loadLanguageDefinitions(definitions.at(language));
|
||||
|
||||
const auto& fallbackLanguage = getFallbackLanguage();
|
||||
loadLanguageDefinitions(definitions.at(fallbackLanguage));
|
||||
if (language != fallbackLanguage)
|
||||
loadLanguageDefinitions(definitions.at(fallbackLanguage));
|
||||
|
||||
s_selectedLanguage = language;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,11 @@ namespace hex {
|
||||
|
||||
return handle;
|
||||
#else
|
||||
auto handle = uintptr_t(dlopen(wolv::util::toUTF8String(path).c_str(), RTLD_LAZY));
|
||||
const auto pathString = wolv::util::toUTF8String(path);
|
||||
|
||||
auto handle = uintptr_t(dlopen(pathString.c_str(), RTLD_NOLOAD));
|
||||
if (handle == 0)
|
||||
handle = uintptr_t(dlopen(pathString.c_str(), RTLD_NOW | RTLD_GLOBAL));
|
||||
|
||||
if (handle == 0) {
|
||||
log::error("Loading library '{}' failed: {}!", wolv::util::toUTF8String(path.filename()), dlerror());
|
||||
@@ -129,7 +133,7 @@ namespace hex {
|
||||
|
||||
|
||||
const auto requestedVersion = getCompatibleVersion();
|
||||
const auto imhexVersion = ImHexApi::System::getImHexVersion();
|
||||
const auto imhexVersion = ImHexApi::System::getImHexVersion().get();
|
||||
if (!imhexVersion.starts_with(requestedVersion)) {
|
||||
if (requestedVersion.empty()) {
|
||||
log::warn("Plugin '{}' did not specify a compatible version, assuming it is compatible with the current version of ImHex.", wolv::util::toUTF8String(m_path.filename()));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <hex/api/shortcut_manager.hpp>
|
||||
#include <imgui.h>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/helpers/auto_reset.hpp>
|
||||
|
||||
#include <hex/ui/view.hpp>
|
||||
@@ -12,6 +13,8 @@ namespace hex {
|
||||
AutoReset<std::map<Shortcut, ShortcutManager::ShortcutEntry>> s_globalShortcuts;
|
||||
std::atomic<bool> s_paused;
|
||||
std::optional<Shortcut> s_prevShortcut;
|
||||
bool s_macOSMode = false;
|
||||
AutoReset<std::optional<UnlocalizedString>> s_lastShortcutMainMenu;
|
||||
|
||||
}
|
||||
|
||||
@@ -78,22 +81,14 @@ namespace hex {
|
||||
std::string Shortcut::toString() const {
|
||||
std::string result;
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
constexpr static auto CTRL_NAME = "⌃";
|
||||
constexpr static auto ALT_NAME = "⌥";
|
||||
constexpr static auto SHIFT_NAME = "⇧";
|
||||
constexpr static auto SUPER_NAME = "⌘";
|
||||
constexpr static auto Concatination = " ";
|
||||
#else
|
||||
constexpr static auto CTRL_NAME = "CTRL";
|
||||
constexpr static auto ALT_NAME = "ALT";
|
||||
constexpr static auto SHIFT_NAME = "SHIFT";
|
||||
constexpr static auto SUPER_NAME = "SUPER";
|
||||
constexpr static auto Concatination = " + ";
|
||||
#endif
|
||||
const auto CTRL_NAME = s_macOSMode ? "⌃" : "CTRL";
|
||||
const auto ALT_NAME = s_macOSMode ? "⌥" : "ALT";
|
||||
const auto SHIFT_NAME = s_macOSMode ? "⇧" : "SHIFT";
|
||||
const auto SUPER_NAME = s_macOSMode ? "⌘" : "SUPER";
|
||||
const auto Concatination = s_macOSMode ? " " : " + ";
|
||||
|
||||
auto keys = m_keys;
|
||||
if (keys.erase(CTRL) > 0) {
|
||||
if (keys.erase(CTRL) > 0 || (!s_macOSMode && keys.erase(CTRLCMD) > 0)) {
|
||||
result += CTRL_NAME;
|
||||
result += Concatination;
|
||||
}
|
||||
@@ -105,7 +100,7 @@ namespace hex {
|
||||
result += SHIFT_NAME;
|
||||
result += Concatination;
|
||||
}
|
||||
if (keys.erase(SUPER) > 0) {
|
||||
if (keys.erase(SUPER) > 0 || (s_macOSMode && keys.erase(CTRLCMD) > 0)) {
|
||||
result += SUPER_NAME;
|
||||
result += Concatination;
|
||||
}
|
||||
@@ -238,28 +233,66 @@ namespace hex {
|
||||
return result;
|
||||
}
|
||||
|
||||
KeyEquivalent Shortcut::toKeyEquivalent() const {
|
||||
#if defined(OS_MACOS)
|
||||
if (*this == None)
|
||||
return { };
|
||||
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback) {
|
||||
KeyEquivalent result = {};
|
||||
result.valid = true;
|
||||
|
||||
for (const auto &key : m_keys) {
|
||||
switch (key.getKeyCode()) {
|
||||
case CTRL.getKeyCode():
|
||||
result.ctrl = true;
|
||||
break;
|
||||
case SHIFT.getKeyCode():
|
||||
result.shift = true;
|
||||
break;
|
||||
case ALT.getKeyCode():
|
||||
result.opt = true;
|
||||
break;
|
||||
case SUPER.getKeyCode():
|
||||
case CTRLCMD.getKeyCode():
|
||||
result.cmd = true;
|
||||
break;
|
||||
case CurrentView.getKeyCode(): break;
|
||||
case AllowWhileTyping.getKeyCode(): break;
|
||||
default:
|
||||
macosGetKey(Keys(key.getKeyCode()), &result.key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
#else
|
||||
return { };
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, unlocalizedName, callback } });
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, unlocalizedName, callback, enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback) {
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, { unlocalizedName }, callback } });
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, { unlocalizedName }, callback, enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback) {
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback } });
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback, enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback) {
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, { unlocalizedName }, callback } });
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, { unlocalizedName }, callback, enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
@@ -267,33 +300,58 @@ namespace hex {
|
||||
Shortcut pressedShortcut;
|
||||
|
||||
if (ctrl)
|
||||
pressedShortcut += CTRL;
|
||||
pressedShortcut += s_macOSMode ? CTRL : CTRLCMD;
|
||||
if (alt)
|
||||
pressedShortcut += ALT;
|
||||
if (shift)
|
||||
pressedShortcut += SHIFT;
|
||||
if (super)
|
||||
pressedShortcut += SUPER;
|
||||
pressedShortcut += s_macOSMode ? CTRLCMD : SUPER;
|
||||
if (focused)
|
||||
pressedShortcut += CurrentView;
|
||||
if (ImGui::GetIO().WantTextInput)
|
||||
pressedShortcut += AllowWhileTyping;
|
||||
|
||||
pressedShortcut += static_cast<Keys>(keyCode);
|
||||
pressedShortcut += scanCodeToKey(keyCode);
|
||||
|
||||
return pressedShortcut;
|
||||
}
|
||||
|
||||
static void processShortcut(const Shortcut &shortcut, const std::map<Shortcut, ShortcutManager::ShortcutEntry> &shortcuts) {
|
||||
if (s_paused) return;
|
||||
static bool processShortcut(Shortcut shortcut, const std::map<Shortcut, ShortcutManager::ShortcutEntry> &shortcuts) {
|
||||
if (s_paused)
|
||||
return true;
|
||||
|
||||
if (ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId))
|
||||
return;
|
||||
return true;
|
||||
|
||||
if (auto it = shortcuts.find(shortcut); it != shortcuts.end()) {
|
||||
const auto &[foundShortcut, entry] = *it;
|
||||
entry.callback();
|
||||
const bool currentlyTyping = ImGui::GetIO().WantTextInput;
|
||||
|
||||
auto it = shortcuts.find(shortcut + AllowWhileTyping);
|
||||
if (!currentlyTyping && it == shortcuts.end()) {
|
||||
if (it == shortcuts.end())
|
||||
it = shortcuts.find(shortcut);
|
||||
}
|
||||
|
||||
if (it != shortcuts.end()) {
|
||||
const auto &[foundShortcut, entry] = *it;
|
||||
|
||||
if (entry.enabledCallback()) {
|
||||
entry.callback();
|
||||
|
||||
if (!entry.unlocalizedName.empty()) {
|
||||
s_lastShortcutMainMenu = entry.unlocalizedName.front();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ShortcutManager::runShortcut(const Shortcut &shortcut, const View *view) {
|
||||
if (view == nullptr)
|
||||
return processShortcut(shortcut, s_globalShortcuts);
|
||||
else
|
||||
return processShortcut(shortcut, view->m_shortcuts);
|
||||
}
|
||||
|
||||
void ShortcutManager::process(const View *currentView, bool ctrl, bool alt, bool shift, bool super, bool focused, u32 keyCode) {
|
||||
@@ -301,7 +359,7 @@ namespace hex {
|
||||
if (keyCode != 0)
|
||||
s_prevShortcut = Shortcut(pressedShortcut.getKeys());
|
||||
|
||||
processShortcut(pressedShortcut, currentView->m_shortcuts);
|
||||
runShortcut(pressedShortcut, currentView);
|
||||
}
|
||||
|
||||
void ShortcutManager::processGlobals(bool ctrl, bool alt, bool shift, bool super, u32 keyCode) {
|
||||
@@ -309,9 +367,18 @@ namespace hex {
|
||||
if (keyCode != 0)
|
||||
s_prevShortcut = Shortcut(pressedShortcut.getKeys());
|
||||
|
||||
processShortcut(pressedShortcut, s_globalShortcuts);
|
||||
runShortcut(pressedShortcut);
|
||||
}
|
||||
|
||||
std::optional<UnlocalizedString> ShortcutManager::getLastActivatedMenu() {
|
||||
return *s_lastShortcutMainMenu;
|
||||
}
|
||||
|
||||
void ShortcutManager::resetLastActivatedMenu() {
|
||||
s_lastShortcutMainMenu->reset();
|
||||
}
|
||||
|
||||
|
||||
void ShortcutManager::clearShortcuts() {
|
||||
s_globalShortcuts->clear();
|
||||
}
|
||||
@@ -387,4 +454,9 @@ namespace hex {
|
||||
return result;
|
||||
}
|
||||
|
||||
void ShortcutManager::enableMacOSMode() {
|
||||
s_macOSMode = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -63,8 +63,11 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
Task::Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function)
|
||||
: m_unlocalizedName(std::move(unlocalizedName)), m_maxValue(maxValue), m_function(std::move(function)), m_background(background) { }
|
||||
Task::Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function)
|
||||
: m_unlocalizedName(std::move(unlocalizedName)),
|
||||
m_maxValue(maxValue),
|
||||
m_function(std::move(function)),
|
||||
m_background(background), m_blocking(blocking) { }
|
||||
|
||||
Task::Task(hex::Task &&other) noexcept {
|
||||
{
|
||||
@@ -133,6 +136,11 @@ namespace hex {
|
||||
return m_background;
|
||||
}
|
||||
|
||||
bool Task::isBlocking() const {
|
||||
return m_blocking;
|
||||
}
|
||||
|
||||
|
||||
bool Task::isFinished() const {
|
||||
return m_finished;
|
||||
}
|
||||
@@ -327,11 +335,11 @@ namespace hex {
|
||||
s_tasksFinishedCallbacks.clear();
|
||||
}
|
||||
|
||||
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, std::function<void(Task&)> function) {
|
||||
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task&)> function) {
|
||||
std::scoped_lock lock(s_queueMutex);
|
||||
|
||||
// Construct new task
|
||||
auto task = std::make_shared<Task>(std::move(unlocalizedName), maxValue, background, std::move(function));
|
||||
auto task = std::make_shared<Task>(std::move(unlocalizedName), maxValue, background, blocking, std::move(function));
|
||||
|
||||
s_tasks.emplace_back(task);
|
||||
|
||||
@@ -346,12 +354,12 @@ namespace hex {
|
||||
|
||||
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function) {
|
||||
log::debug("Creating task {}", unlocalizedName.get());
|
||||
return createTask(std::move(unlocalizedName), maxValue, false, std::move(function));
|
||||
return createTask(std::move(unlocalizedName), maxValue, false, false, std::move(function));
|
||||
}
|
||||
|
||||
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function) {
|
||||
log::debug("Creating task {}", unlocalizedName.get());
|
||||
return createTask(std::move(unlocalizedName), maxValue, false,
|
||||
return createTask(std::move(unlocalizedName), maxValue, false, false,
|
||||
[function = std::move(function)](Task&) {
|
||||
function();
|
||||
}
|
||||
@@ -360,12 +368,26 @@ namespace hex {
|
||||
|
||||
TaskHolder TaskManager::createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void(Task &)> function) {
|
||||
log::debug("Creating background task {}", unlocalizedName.get());
|
||||
return createTask(std::move(unlocalizedName), 0, true, std::move(function));
|
||||
return createTask(std::move(unlocalizedName), 0, true, false, std::move(function));
|
||||
}
|
||||
|
||||
TaskHolder TaskManager::createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void()> function) {
|
||||
log::debug("Creating background task {}", unlocalizedName.get());
|
||||
return createTask(std::move(unlocalizedName), 0, true,
|
||||
return createTask(std::move(unlocalizedName), 0, true, false,
|
||||
[function = std::move(function)](Task&) {
|
||||
function();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
TaskHolder TaskManager::createBlockingTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function) {
|
||||
log::debug("Creating blocking task {}", unlocalizedName.get());
|
||||
return createTask(std::move(unlocalizedName), maxValue, true, true, std::move(function));
|
||||
}
|
||||
|
||||
TaskHolder TaskManager::createBlockingTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function) {
|
||||
log::debug("Creating blocking task {}", unlocalizedName.get());
|
||||
return createTask(std::move(unlocalizedName), maxValue, true, true,
|
||||
[function = std::move(function)](Task&) {
|
||||
function();
|
||||
}
|
||||
@@ -414,6 +436,14 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
size_t TaskManager::getRunningBlockingTaskCount() {
|
||||
std::scoped_lock lock(s_queueMutex);
|
||||
|
||||
return std::ranges::count_if(s_tasks, [](const auto &task){
|
||||
return task->isBlocking();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void TaskManager::doLater(const std::function<void()> &function) {
|
||||
std::scoped_lock lock(s_deferredCallsMutex);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <hex/api/theme_manager.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/events/events_interaction.hpp>
|
||||
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
@@ -16,6 +16,7 @@ namespace hex {
|
||||
AutoReset<std::map<std::string, ThemeManager::StyleHandler>> s_styleHandlers;
|
||||
AutoReset<std::string> s_imageTheme;
|
||||
AutoReset<std::string> s_currTheme;
|
||||
AutoReset<std::optional<float>> s_accentColor;
|
||||
|
||||
std::recursive_mutex s_themeMutex;
|
||||
}
|
||||
@@ -155,12 +156,28 @@ namespace hex {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto color = parseColorString(value.get<std::string>());
|
||||
auto colorString = value.get<std::string>();
|
||||
bool accentableColor = false;
|
||||
if (colorString.starts_with("*")) {
|
||||
colorString = colorString.substr(1);
|
||||
accentableColor = true;
|
||||
}
|
||||
auto color = parseColorString(colorString);
|
||||
|
||||
if (!color.has_value()) {
|
||||
log::warn("Invalid color '{}' for '{}.{}'", value.get<std::string>(), type, key);
|
||||
log::warn("Invalid color '{}' for '{}.{}'", colorString, type, key);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (accentableColor && s_accentColor->has_value()) {
|
||||
float h, s, v;
|
||||
ImGui::ColorConvertRGBtoHSV(color->Value.x, color->Value.y, color->Value.z, h, s, v);
|
||||
|
||||
h = s_accentColor->value();
|
||||
|
||||
ImGui::ColorConvertHSVtoRGB(h, s, v, color->Value.x, color->Value.y, color->Value.z);
|
||||
}
|
||||
|
||||
(*s_themeHandlers)[type].setFunction((*s_themeHandlers)[type].colorMap.at(key), color.value());
|
||||
}
|
||||
}
|
||||
@@ -236,6 +253,14 @@ namespace hex {
|
||||
s_currTheme->clear();
|
||||
}
|
||||
|
||||
void ThemeManager::setAccentColor(const ImColor &color) {
|
||||
float h, s, v;
|
||||
ImGui::ColorConvertRGBtoHSV(color.Value.x, color.Value.y, color.Value.z, h, s, v);
|
||||
|
||||
s_accentColor = h;
|
||||
reapplyCurrentTheme();
|
||||
}
|
||||
|
||||
|
||||
const std::map<std::string, ThemeManager::ThemeHandler> &ThemeManager::getThemeHandlers() {
|
||||
return s_themeHandlers;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/api/events/events_gui.hpp>
|
||||
|
||||
#include <hex/helpers/auto_reset.hpp>
|
||||
|
||||
@@ -11,6 +12,8 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace {
|
||||
@@ -20,10 +23,12 @@ namespace hex {
|
||||
|
||||
AutoReset<std::map<ImGuiID, std::string>> s_highlights;
|
||||
AutoReset<std::vector<std::pair<ImRect, std::string>>> s_highlightDisplays;
|
||||
AutoReset<std::map<ImGuiID, ImRect>> s_interactiveHelpDisplays;
|
||||
|
||||
AutoReset<std::map<ImGuiID, std::function<void()>>> s_interactiveHelpItems;
|
||||
ImRect s_hoveredRect;
|
||||
ImGuiID s_hoveredId;
|
||||
ImGuiID s_activeHelpId;
|
||||
bool s_helpHoverActive = false;
|
||||
|
||||
|
||||
@@ -33,6 +38,13 @@ namespace hex {
|
||||
idStack.push_back(0);
|
||||
}
|
||||
|
||||
void add(const char *string) {
|
||||
const ImGuiID seed = idStack.back();
|
||||
const ImGuiID id = ImHashStr(string, 0, seed);
|
||||
|
||||
idStack.push_back(id);
|
||||
}
|
||||
|
||||
void add(const std::string &string) {
|
||||
const ImGuiID seed = idStack.back();
|
||||
const ImGuiID id = ImHashStr(string.c_str(), string.length(), seed);
|
||||
@@ -84,9 +96,23 @@ namespace hex {
|
||||
EventImGuiElementRendered::subscribe([](ImGuiID id, const std::array<float, 4> bb){
|
||||
const auto boundingBox = ImRect(bb[0], bb[1], bb[2], bb[3]);
|
||||
|
||||
const auto element = hex::s_highlights->find(id);
|
||||
if (element != hex::s_highlights->end()) {
|
||||
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
|
||||
{
|
||||
const auto element = hex::s_highlights->find(id);
|
||||
if (element != hex::s_highlights->end()) {
|
||||
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
|
||||
|
||||
const auto window = ImGui::GetCurrentWindow();
|
||||
if (window != nullptr && window->DockNode != nullptr && window->DockNode->TabBar != nullptr)
|
||||
window->DockNode->TabBar->NextSelectedTabId = window->TabId;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const auto element = s_interactiveHelpItems->find(id);
|
||||
if (element != s_interactiveHelpItems->end()) {
|
||||
(*s_interactiveHelpDisplays)[id] = boundingBox;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
|
||||
@@ -117,10 +143,10 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
void TutorialManager::addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString text) {
|
||||
void TutorialManager::addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString) {
|
||||
auto id = calculateId(ids);
|
||||
|
||||
s_interactiveHelpItems->emplace(id, [text = std::move(text)]{
|
||||
s_interactiveHelpItems->emplace(id, [text = std::move(unlocalizedString)]{
|
||||
log::info("{}", Lang(text).get());
|
||||
});
|
||||
}
|
||||
@@ -133,6 +159,39 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
void TutorialManager::setLastItemInteractiveHelpPopup(std::function<void()> callback) {
|
||||
auto id = ImGui::GetItemID();
|
||||
|
||||
if (!s_interactiveHelpItems->contains(id)) {
|
||||
s_interactiveHelpItems->emplace(id, [id]{
|
||||
s_activeHelpId = id;
|
||||
});
|
||||
}
|
||||
|
||||
if (id == s_activeHelpId) {
|
||||
ImGui::SetNextWindowSize(scaled({ 400, 0 }));
|
||||
if (ImGui::BeginTooltip()) {
|
||||
callback();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) || ImGui::IsKeyPressed(ImGuiKey_Escape))
|
||||
s_activeHelpId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TutorialManager::setLastItemInteractiveHelpLink(std::string link) {
|
||||
auto id = ImGui::GetItemID();
|
||||
|
||||
if (s_interactiveHelpItems->contains(id))
|
||||
return;
|
||||
|
||||
s_interactiveHelpItems->emplace(id, [link = std::move(link)]{
|
||||
hex::openWebpage(link);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void TutorialManager::startTutorial(const UnlocalizedString &unlocalizedName) {
|
||||
s_currentTutorial = s_tutorials->find(unlocalizedName);
|
||||
if (s_currentTutorial == s_tutorials->end())
|
||||
@@ -146,6 +205,19 @@ namespace hex {
|
||||
const auto &drawList = ImGui::GetForegroundDrawList();
|
||||
drawList->AddText(ImGui::GetMousePos() + scaled({ 10, -5, }), ImGui::GetColorU32(ImGuiCol_Text), "?");
|
||||
|
||||
for (const auto &[id, boundingBox] : *s_interactiveHelpDisplays) {
|
||||
drawList->AddRect(
|
||||
boundingBox.Min - ImVec2(5, 5),
|
||||
boundingBox.Max + ImVec2(5, 5),
|
||||
ImGui::GetColorU32(ImGuiCol_PlotHistogram),
|
||||
5.0F,
|
||||
ImDrawFlags_None,
|
||||
2.0F
|
||||
);
|
||||
}
|
||||
|
||||
s_interactiveHelpDisplays->clear();
|
||||
|
||||
const bool mouseClicked = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
|
||||
if (s_hoveredId != 0) {
|
||||
drawList->AddRectFilled(s_hoveredRect.Min, s_hoveredRect.Max, 0x30FFFFFF);
|
||||
@@ -164,6 +236,11 @@ namespace hex {
|
||||
if (mouseClicked || ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||
s_helpHoverActive = false;
|
||||
}
|
||||
|
||||
// Discard mouse click so it doesn't activate clicked item
|
||||
ImGui::GetIO().MouseDown[ImGuiMouseButton_Left] = false;
|
||||
ImGui::GetIO().MouseReleased[ImGuiMouseButton_Left] = false;
|
||||
ImGui::GetIO().MouseClicked[ImGuiMouseButton_Left] = false;
|
||||
}
|
||||
|
||||
for (const auto &[rect, unlocalizedText] : *s_highlightDisplays) {
|
||||
@@ -250,6 +327,7 @@ 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::BringWindowToDisplayFront(ImGui::GetCurrentWindowRead());
|
||||
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
AutoReset<std::map<std::string, WorkspaceManager::Workspace>> WorkspaceManager::s_workspaces;
|
||||
decltype(WorkspaceManager::s_workspaces)::Type::iterator WorkspaceManager::s_currentWorkspace = s_workspaces->end();
|
||||
decltype(WorkspaceManager::s_workspaces)::Type::iterator WorkspaceManager::s_previousWorkspace = s_workspaces->end();
|
||||
decltype(WorkspaceManager::s_workspaces)::Type::iterator WorkspaceManager::s_workspaceToRemove = s_workspaces->end();
|
||||
static AutoReset<std::map<std::string, WorkspaceManager::Workspace>> s_workspaces;
|
||||
static decltype(s_workspaces)::Type::iterator s_currentWorkspace = s_workspaces->end();
|
||||
static decltype(s_workspaces)::Type::iterator s_previousWorkspace = s_workspaces->end();
|
||||
static decltype(s_workspaces)::Type::iterator s_workspaceToRemove = s_workspaces->end();
|
||||
|
||||
void WorkspaceManager::createWorkspace(const std::string& name, const std::string &layout) {
|
||||
s_currentWorkspace = s_workspaces->insert_or_assign(name, Workspace {
|
||||
@@ -174,7 +174,13 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
const std::map<std::string, WorkspaceManager::Workspace>& WorkspaceManager::getWorkspaces() {
|
||||
return *s_workspaces;
|
||||
}
|
||||
|
||||
const std::map<std::string, WorkspaceManager::Workspace>::iterator& WorkspaceManager::getCurrentWorkspace() {
|
||||
return s_currentWorkspace;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace hex::dp {
|
||||
const i128& Node::getIntegerOnInput(u32 index) {
|
||||
auto attribute = this->getConnectedInputAttribute(index);
|
||||
|
||||
auto &outputData = [&] -> std::vector<u8>& {
|
||||
auto &outputData = [&]() -> std::vector<u8>&{
|
||||
if (attribute != nullptr) {
|
||||
if (attribute->getType() != Attribute::Type::Integer)
|
||||
throwNodeError("Tried to read integer from non-integer attribute");
|
||||
@@ -68,7 +68,7 @@ namespace hex::dp {
|
||||
const double& Node::getFloatOnInput(u32 index) {
|
||||
auto attribute = this->getConnectedInputAttribute(index);
|
||||
|
||||
auto &outputData = [&] -> std::vector<u8>& {
|
||||
auto &outputData = [&]() -> std::vector<u8>&{
|
||||
if (attribute != nullptr) {
|
||||
if (attribute->getType() != Attribute::Type::Float)
|
||||
throwNodeError("Tried to read integer from non-float attribute");
|
||||
|
||||
@@ -470,7 +470,7 @@ namespace hex::crypt {
|
||||
std::vector<u8> bytes;
|
||||
u8 byte;
|
||||
while (true) {
|
||||
byte = value & 0x7F;
|
||||
byte = u8(value & 0x7F);
|
||||
value >>= 7;
|
||||
if constexpr(std::signed_integral<T>) {
|
||||
if (value == 0 && (byte & 0x40) == 0) {
|
||||
|
||||
@@ -12,4 +12,13 @@ namespace hex::dbg {
|
||||
|
||||
}
|
||||
|
||||
static bool s_debugMode = false;
|
||||
bool debugModeEnabled() {
|
||||
return s_debugMode;
|
||||
}
|
||||
|
||||
void setDebugModeEnabled(bool enabled) {
|
||||
s_debugMode = enabled;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -44,7 +44,7 @@ namespace hex::paths {
|
||||
|
||||
if (includeSystemFolders) {
|
||||
if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value()) {
|
||||
paths.push_back(*executablePath);
|
||||
paths.push_back(executablePath->parent_path());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,13 @@ namespace hex::fs {
|
||||
// Call callback that will write the file
|
||||
Module._fileBrowserCallback(stringToNewUTF8("/savedFiles/" + filename));
|
||||
|
||||
let data = FS.readFile("/savedFiles/" + filename);
|
||||
let data;
|
||||
try {
|
||||
data = FS.readFile("/savedFiles/" + filename);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return;
|
||||
}
|
||||
|
||||
const reader = Object.assign(new FileReader(), {
|
||||
onload: () => {
|
||||
@@ -191,6 +197,7 @@ namespace hex::fs {
|
||||
else if (!validExtensions.empty())
|
||||
path = "file." + validExtensions[0].spec;
|
||||
|
||||
std::fs::create_directory("/savedFiles");
|
||||
callJs_saveFile(path.filename().string().c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -49,15 +49,6 @@ namespace hex {
|
||||
}
|
||||
|
||||
void HttpRequest::checkProxyErrors() { }
|
||||
|
||||
int HttpRequest::progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow) {
|
||||
std::ignore = contents;
|
||||
std::ignore = dlTotal;
|
||||
std::ignore = dlNow;
|
||||
std::ignore = ulTotal;
|
||||
std::ignore = ulNow;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,7 @@
|
||||
#if !defined(OS_WEB)
|
||||
|
||||
#include <hex/helpers/http_requests.hpp>
|
||||
#include <curl/curl.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -11,6 +12,19 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
int progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow) {
|
||||
auto &request = *static_cast<HttpRequest *>(contents);
|
||||
|
||||
if (dlTotal > 0)
|
||||
request.setProgress(float(dlNow) / dlTotal);
|
||||
else if (ulTotal > 0)
|
||||
request.setProgress(float(ulNow) / ulTotal);
|
||||
else
|
||||
request.setProgress(0.0F);
|
||||
|
||||
return request.isCanceled() ? CURLE_ABORTED_BY_CALLBACK : CURLE_OK;
|
||||
}
|
||||
|
||||
HttpRequest::HttpRequest(std::string method, std::string url) : m_method(std::move(method)), m_url(std::move(url)) {
|
||||
AT_FIRST_TIME {
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
@@ -95,19 +109,101 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
int HttpRequest::progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow) {
|
||||
auto &request = *static_cast<HttpRequest *>(contents);
|
||||
namespace impl {
|
||||
|
||||
if (dlTotal > 0)
|
||||
request.m_progress = float(dlNow) / dlTotal;
|
||||
else if (ulTotal > 0)
|
||||
request.m_progress = float(ulNow) / ulTotal;
|
||||
else
|
||||
request.m_progress = 0.0F;
|
||||
void setWriteFunctions(CURL *curl, wolv::io::File &file) {
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HttpRequest::writeToFile);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file);
|
||||
}
|
||||
|
||||
void setWriteFunctions(CURL *curl, std::vector<u8> &data) {
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HttpRequest::writeToVector);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
|
||||
}
|
||||
|
||||
void setupFileUpload(CURL *curl, wolv::io::File &file, const std::string &fileName, const std::string &mimeName) {
|
||||
curl_mime *mime = curl_mime_init(curl);
|
||||
curl_mimepart *part = curl_mime_addpart(mime);
|
||||
|
||||
|
||||
curl_mime_data_cb(part, file.getSize(),
|
||||
[](char *buffer, size_t size, size_t nitems, void *arg) -> size_t {
|
||||
auto handle = static_cast<FILE*>(arg);
|
||||
|
||||
return fread(buffer, size, nitems, handle);
|
||||
},
|
||||
[](void *arg, curl_off_t offset, int origin) -> int {
|
||||
auto handle = static_cast<FILE*>(arg);
|
||||
|
||||
if (fseek(handle, offset, origin) != 0)
|
||||
return CURL_SEEKFUNC_CANTSEEK;
|
||||
else
|
||||
return CURL_SEEKFUNC_OK;
|
||||
},
|
||||
[](void *arg) {
|
||||
auto handle = static_cast<FILE*>(arg);
|
||||
|
||||
fclose(handle);
|
||||
},
|
||||
file.getHandle());
|
||||
curl_mime_filename(part, fileName.c_str());
|
||||
curl_mime_name(part, mimeName.c_str());
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
|
||||
}
|
||||
|
||||
void setupFileUpload(CURL *curl, const std::vector<u8> &data, const std::fs::path &fileName, const std::string &mimeName) {
|
||||
curl_mime *mime = curl_mime_init(curl);
|
||||
curl_mimepart *part = curl_mime_addpart(mime);
|
||||
|
||||
curl_mime_data(part, reinterpret_cast<const char *>(data.data()), data.size());
|
||||
auto fileNameStr = wolv::util::toUTF8String(fileName.filename());
|
||||
curl_mime_filename(part, fileNameStr.c_str());
|
||||
curl_mime_name(part, mimeName.c_str());
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
|
||||
}
|
||||
|
||||
int executeCurl(CURL *curl, const std::string &url, const std::string &method, const std::string &body, std::map<std::string, std::string> &headers) {
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method.c_str());
|
||||
|
||||
if (!body.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
|
||||
}
|
||||
|
||||
curl_slist *headersList = nullptr;
|
||||
headersList = curl_slist_append(headersList, "Cache-Control: no-cache");
|
||||
ON_SCOPE_EXIT { curl_slist_free_all(headersList); };
|
||||
|
||||
for (auto &[key, value] : headers) {
|
||||
std::string header = hex::format("{}: {}", key, value);
|
||||
headersList = curl_slist_append(headersList, header.c_str());
|
||||
}
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headersList);
|
||||
|
||||
auto result = curl_easy_perform(curl);
|
||||
if (result != CURLE_OK){
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long getStatusCode(CURL *curl) {
|
||||
long statusCode = 0;
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &statusCode);
|
||||
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
std::string getStatusText(int result) {
|
||||
return curl_easy_strerror(CURLcode(result));
|
||||
}
|
||||
|
||||
return request.m_canceled ? CURLE_ABORTED_BY_CALLBACK : CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/events/events_gui.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
239
lib/libimhex/source/helpers/keys.cpp
Normal file
239
lib/libimhex/source/helpers/keys.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
#include <hex/helpers/keys.hpp>
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
enum Keys scanCodeToKey(int scanCode) {
|
||||
switch (scanCode) {
|
||||
case GLFW_KEY_SPACE: return Keys::Space;
|
||||
case GLFW_KEY_APOSTROPHE: return Keys::Apostrophe;
|
||||
case GLFW_KEY_COMMA: return Keys::Comma;
|
||||
case GLFW_KEY_MINUS: return Keys::Minus;
|
||||
case GLFW_KEY_PERIOD: return Keys::Period;
|
||||
case GLFW_KEY_SLASH: return Keys::Slash;
|
||||
case GLFW_KEY_0: return Keys::Num0;
|
||||
case GLFW_KEY_1: return Keys::Num1;
|
||||
case GLFW_KEY_2: return Keys::Num2;
|
||||
case GLFW_KEY_3: return Keys::Num3;
|
||||
case GLFW_KEY_4: return Keys::Num4;
|
||||
case GLFW_KEY_5: return Keys::Num5;
|
||||
case GLFW_KEY_6: return Keys::Num6;
|
||||
case GLFW_KEY_7: return Keys::Num7;
|
||||
case GLFW_KEY_8: return Keys::Num8;
|
||||
case GLFW_KEY_9: return Keys::Num9;
|
||||
case GLFW_KEY_SEMICOLON: return Keys::Semicolon;
|
||||
case GLFW_KEY_EQUAL: return Keys::Equals;
|
||||
case GLFW_KEY_A: return Keys::A;
|
||||
case GLFW_KEY_B: return Keys::B;
|
||||
case GLFW_KEY_C: return Keys::C;
|
||||
case GLFW_KEY_D: return Keys::D;
|
||||
case GLFW_KEY_E: return Keys::E;
|
||||
case GLFW_KEY_F: return Keys::F;
|
||||
case GLFW_KEY_G: return Keys::G;
|
||||
case GLFW_KEY_H: return Keys::H;
|
||||
case GLFW_KEY_I: return Keys::I;
|
||||
case GLFW_KEY_J: return Keys::J;
|
||||
case GLFW_KEY_K: return Keys::K;
|
||||
case GLFW_KEY_L: return Keys::L;
|
||||
case GLFW_KEY_M: return Keys::M;
|
||||
case GLFW_KEY_N: return Keys::N;
|
||||
case GLFW_KEY_O: return Keys::O;
|
||||
case GLFW_KEY_P: return Keys::P;
|
||||
case GLFW_KEY_Q: return Keys::Q;
|
||||
case GLFW_KEY_R: return Keys::R;
|
||||
case GLFW_KEY_S: return Keys::S;
|
||||
case GLFW_KEY_T: return Keys::T;
|
||||
case GLFW_KEY_U: return Keys::U;
|
||||
case GLFW_KEY_V: return Keys::V;
|
||||
case GLFW_KEY_W: return Keys::W;
|
||||
case GLFW_KEY_X: return Keys::X;
|
||||
case GLFW_KEY_Y: return Keys::Y;
|
||||
case GLFW_KEY_Z: return Keys::Z;
|
||||
case GLFW_KEY_LEFT_BRACKET: return Keys::LeftBracket;
|
||||
case GLFW_KEY_BACKSLASH: return Keys::Backslash;
|
||||
case GLFW_KEY_RIGHT_BRACKET: return Keys::RightBracket;
|
||||
case GLFW_KEY_GRAVE_ACCENT: return Keys::GraveAccent;
|
||||
case GLFW_KEY_WORLD_1: return Keys::World1;
|
||||
case GLFW_KEY_WORLD_2: return Keys::World2;
|
||||
case GLFW_KEY_ESCAPE: return Keys::Escape;
|
||||
case GLFW_KEY_ENTER: return Keys::Enter;
|
||||
case GLFW_KEY_TAB: return Keys::Tab;
|
||||
case GLFW_KEY_BACKSPACE: return Keys::Backspace;
|
||||
case GLFW_KEY_INSERT: return Keys::Insert;
|
||||
case GLFW_KEY_DELETE: return Keys::Delete;
|
||||
case GLFW_KEY_RIGHT: return Keys::Right;
|
||||
case GLFW_KEY_LEFT: return Keys::Left;
|
||||
case GLFW_KEY_DOWN: return Keys::Down;
|
||||
case GLFW_KEY_UP: return Keys::Up;
|
||||
case GLFW_KEY_PAGE_UP: return Keys::PageUp;
|
||||
case GLFW_KEY_PAGE_DOWN: return Keys::PageDown;
|
||||
case GLFW_KEY_HOME: return Keys::Home;
|
||||
case GLFW_KEY_END: return Keys::End;
|
||||
case GLFW_KEY_CAPS_LOCK: return Keys::CapsLock;
|
||||
case GLFW_KEY_SCROLL_LOCK: return Keys::ScrollLock;
|
||||
case GLFW_KEY_NUM_LOCK: return Keys::NumLock;
|
||||
case GLFW_KEY_PRINT_SCREEN: return Keys::PrintScreen;
|
||||
case GLFW_KEY_PAUSE: return Keys::Pause;
|
||||
case GLFW_KEY_F1: return Keys::F1;
|
||||
case GLFW_KEY_F2: return Keys::F2;
|
||||
case GLFW_KEY_F3: return Keys::F3;
|
||||
case GLFW_KEY_F4: return Keys::F4;
|
||||
case GLFW_KEY_F5: return Keys::F5;
|
||||
case GLFW_KEY_F6: return Keys::F6;
|
||||
case GLFW_KEY_F7: return Keys::F7;
|
||||
case GLFW_KEY_F8: return Keys::F8;
|
||||
case GLFW_KEY_F9: return Keys::F9;
|
||||
case GLFW_KEY_F10: return Keys::F10;
|
||||
case GLFW_KEY_F11: return Keys::F11;
|
||||
case GLFW_KEY_F12: return Keys::F12;
|
||||
case GLFW_KEY_F13: return Keys::F13;
|
||||
case GLFW_KEY_F14: return Keys::F14;
|
||||
case GLFW_KEY_F15: return Keys::F15;
|
||||
case GLFW_KEY_F16: return Keys::F16;
|
||||
case GLFW_KEY_F17: return Keys::F17;
|
||||
case GLFW_KEY_F18: return Keys::F18;
|
||||
case GLFW_KEY_F19: return Keys::F19;
|
||||
case GLFW_KEY_F20: return Keys::F20;
|
||||
case GLFW_KEY_F21: return Keys::F21;
|
||||
case GLFW_KEY_F22: return Keys::F22;
|
||||
case GLFW_KEY_F23: return Keys::F23;
|
||||
case GLFW_KEY_F24: return Keys::F24;
|
||||
case GLFW_KEY_F25: return Keys::F25;
|
||||
case GLFW_KEY_KP_0: return Keys::KeyPad0;
|
||||
case GLFW_KEY_KP_1: return Keys::KeyPad1;
|
||||
case GLFW_KEY_KP_2: return Keys::KeyPad2;
|
||||
case GLFW_KEY_KP_3: return Keys::KeyPad3;
|
||||
case GLFW_KEY_KP_4: return Keys::KeyPad4;
|
||||
case GLFW_KEY_KP_5: return Keys::KeyPad5;
|
||||
case GLFW_KEY_KP_6: return Keys::KeyPad6;
|
||||
case GLFW_KEY_KP_7: return Keys::KeyPad7;
|
||||
case GLFW_KEY_KP_8: return Keys::KeyPad8;
|
||||
case GLFW_KEY_KP_9: return Keys::KeyPad9;
|
||||
case GLFW_KEY_KP_DECIMAL: return Keys::KeyPadDecimal;
|
||||
case GLFW_KEY_KP_DIVIDE: return Keys::KeyPadDivide;
|
||||
case GLFW_KEY_KP_MULTIPLY: return Keys::KeyPadMultiply;
|
||||
case GLFW_KEY_KP_SUBTRACT: return Keys::KeyPadSubtract;
|
||||
case GLFW_KEY_KP_ADD: return Keys::KeyPadAdd;
|
||||
case GLFW_KEY_KP_ENTER: return Keys::KeyPadEnter;
|
||||
case GLFW_KEY_KP_EQUAL: return Keys::KeyPadEqual;
|
||||
case GLFW_KEY_MENU: return Keys::Menu;
|
||||
default: return Keys(scanCode);
|
||||
}
|
||||
}
|
||||
|
||||
int keyToScanCode(enum Keys key) {
|
||||
switch (key) {
|
||||
case Keys::Space: return GLFW_KEY_SPACE;
|
||||
case Keys::Apostrophe: return GLFW_KEY_APOSTROPHE;
|
||||
case Keys::Comma: return GLFW_KEY_COMMA;
|
||||
case Keys::Minus: return GLFW_KEY_MINUS;
|
||||
case Keys::Period: return GLFW_KEY_PERIOD;
|
||||
case Keys::Slash: return GLFW_KEY_SLASH;
|
||||
case Keys::Num0: return GLFW_KEY_0;
|
||||
case Keys::Num1: return GLFW_KEY_1;
|
||||
case Keys::Num2: return GLFW_KEY_2;
|
||||
case Keys::Num3: return GLFW_KEY_3;
|
||||
case Keys::Num4: return GLFW_KEY_4;
|
||||
case Keys::Num5: return GLFW_KEY_5;
|
||||
case Keys::Num6: return GLFW_KEY_6;
|
||||
case Keys::Num7: return GLFW_KEY_7;
|
||||
case Keys::Num8: return GLFW_KEY_8;
|
||||
case Keys::Num9: return GLFW_KEY_9;
|
||||
case Keys::Semicolon: return GLFW_KEY_SEMICOLON;
|
||||
case Keys::Equals: return GLFW_KEY_EQUAL;
|
||||
case Keys::A: return GLFW_KEY_A;
|
||||
case Keys::B: return GLFW_KEY_B;
|
||||
case Keys::C: return GLFW_KEY_C;
|
||||
case Keys::D: return GLFW_KEY_D;
|
||||
case Keys::E: return GLFW_KEY_E;
|
||||
case Keys::F: return GLFW_KEY_F;
|
||||
case Keys::G: return GLFW_KEY_G;
|
||||
case Keys::H: return GLFW_KEY_H;
|
||||
case Keys::I: return GLFW_KEY_I;
|
||||
case Keys::J: return GLFW_KEY_J;
|
||||
case Keys::K: return GLFW_KEY_K;
|
||||
case Keys::L: return GLFW_KEY_L;
|
||||
case Keys::M: return GLFW_KEY_M;
|
||||
case Keys::N: return GLFW_KEY_N;
|
||||
case Keys::O: return GLFW_KEY_O;
|
||||
case Keys::P: return GLFW_KEY_P;
|
||||
case Keys::Q: return GLFW_KEY_Q;
|
||||
case Keys::R: return GLFW_KEY_R;
|
||||
case Keys::S: return GLFW_KEY_S;
|
||||
case Keys::T: return GLFW_KEY_T;
|
||||
case Keys::U: return GLFW_KEY_U;
|
||||
case Keys::V: return GLFW_KEY_V;
|
||||
case Keys::W: return GLFW_KEY_W;
|
||||
case Keys::X: return GLFW_KEY_X;
|
||||
case Keys::Y: return GLFW_KEY_Y;
|
||||
case Keys::Z: return GLFW_KEY_Z;
|
||||
case Keys::LeftBracket: return GLFW_KEY_LEFT_BRACKET;
|
||||
case Keys::Backslash: return GLFW_KEY_BACKSLASH;
|
||||
case Keys::RightBracket: return GLFW_KEY_RIGHT_BRACKET;
|
||||
case Keys::GraveAccent: return GLFW_KEY_GRAVE_ACCENT;
|
||||
case Keys::World1: return GLFW_KEY_WORLD_1;
|
||||
case Keys::World2: return GLFW_KEY_WORLD_2;
|
||||
case Keys::Escape: return GLFW_KEY_ESCAPE;
|
||||
case Keys::Enter: return GLFW_KEY_ENTER;
|
||||
case Keys::Tab: return GLFW_KEY_TAB;
|
||||
case Keys::Backspace: return GLFW_KEY_BACKSPACE;
|
||||
case Keys::Insert: return GLFW_KEY_INSERT;
|
||||
case Keys::Delete: return GLFW_KEY_DELETE;
|
||||
case Keys::Right: return GLFW_KEY_RIGHT;
|
||||
case Keys::Left: return GLFW_KEY_LEFT;
|
||||
case Keys::Down: return GLFW_KEY_DOWN;
|
||||
case Keys::Up: return GLFW_KEY_UP;
|
||||
case Keys::PageUp: return GLFW_KEY_PAGE_UP;
|
||||
case Keys::PageDown: return GLFW_KEY_PAGE_DOWN;
|
||||
case Keys::Home: return GLFW_KEY_HOME;
|
||||
case Keys::End: return GLFW_KEY_END;
|
||||
case Keys::CapsLock: return GLFW_KEY_CAPS_LOCK;
|
||||
case Keys::ScrollLock: return GLFW_KEY_SCROLL_LOCK;
|
||||
case Keys::NumLock: return GLFW_KEY_NUM_LOCK;
|
||||
case Keys::PrintScreen: return GLFW_KEY_PRINT_SCREEN;
|
||||
case Keys::Pause: return GLFW_KEY_PAUSE;
|
||||
case Keys::F1: return GLFW_KEY_F1;
|
||||
case Keys::F2: return GLFW_KEY_F2;
|
||||
case Keys::F3: return GLFW_KEY_F3;
|
||||
case Keys::F4: return GLFW_KEY_F4;
|
||||
case Keys::F5: return GLFW_KEY_F5;
|
||||
case Keys::F6: return GLFW_KEY_F6;
|
||||
case Keys::F7: return GLFW_KEY_F7;
|
||||
case Keys::F8: return GLFW_KEY_F8;
|
||||
case Keys::F9: return GLFW_KEY_F9;
|
||||
case Keys::F10: return GLFW_KEY_F10;
|
||||
case Keys::F11: return GLFW_KEY_F11;
|
||||
case Keys::F12: return GLFW_KEY_F12;
|
||||
case Keys::F13: return GLFW_KEY_F13;
|
||||
case Keys::F14: return GLFW_KEY_F14;
|
||||
case Keys::F15: return GLFW_KEY_F15;
|
||||
case Keys::F16: return GLFW_KEY_F16;
|
||||
case Keys::F17: return GLFW_KEY_F17;
|
||||
case Keys::F18: return GLFW_KEY_F18;
|
||||
case Keys::F19: return GLFW_KEY_F19;
|
||||
case Keys::F20: return GLFW_KEY_F20;
|
||||
case Keys::F21: return GLFW_KEY_F21;
|
||||
case Keys::F22: return GLFW_KEY_F22;
|
||||
case Keys::F23: return GLFW_KEY_F23;
|
||||
case Keys::F24: return GLFW_KEY_F24;
|
||||
case Keys::F25: return GLFW_KEY_F25;
|
||||
case Keys::KeyPad0: return GLFW_KEY_KP_0;
|
||||
case Keys::KeyPad1: return GLFW_KEY_KP_1;
|
||||
case Keys::KeyPad2: return GLFW_KEY_KP_2;
|
||||
case Keys::KeyPad3: return GLFW_KEY_KP_3;
|
||||
case Keys::KeyPad4: return GLFW_KEY_KP_4;
|
||||
case Keys::KeyPad5: return GLFW_KEY_KP_5;
|
||||
case Keys::KeyPad6: return GLFW_KEY_KP_6;
|
||||
case Keys::KeyPad7: return GLFW_KEY_KP_7;
|
||||
case Keys::KeyPad8: return GLFW_KEY_KP_8;
|
||||
case Keys::KeyPad9: return GLFW_KEY_KP_9;
|
||||
case Keys::KeyPadDecimal: return GLFW_KEY_KP_DECIMAL;
|
||||
case Keys::KeyPadDivide: return GLFW_KEY_KP_DIVIDE;
|
||||
case Keys::KeyPadMultiply: return GLFW_KEY_KP_MULTIPLY;
|
||||
case Keys::KeyPadSubtract: return GLFW_KEY_KP_SUBTRACT;
|
||||
case Keys::KeyPadAdd: return GLFW_KEY_KP_ADD;
|
||||
case Keys::KeyPadEnter: return GLFW_KEY_KP_ENTER;
|
||||
case Keys::KeyPadEqual: return GLFW_KEY_KP_EQUAL;
|
||||
case Keys::Menu: return GLFW_KEY_MENU;
|
||||
default: return int(key);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user