Compare commits
444 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
5c148d19dd | ||
|
acb03642c2 | ||
|
ba2aea86f9 | ||
|
c704703b14 | ||
|
33a329f16a | ||
|
f0df06a795 | ||
|
9ae41b7335 | ||
|
b9fee0f6c9 | ||
|
92273829bb | ||
|
86f6f81d9b | ||
|
573a619191 | ||
|
c5807a3463 | ||
|
2a9f49a148 | ||
|
64245bf745 | ||
|
772598996c | ||
|
ccb82c1676 | ||
|
cd900cdfee | ||
|
1767575728 | ||
|
0a34c04b44 | ||
|
7e85168576 | ||
|
3027e00905 | ||
|
2ecbacc924 | ||
|
84eb56d6b1 | ||
|
f3e5dcbe65 | ||
|
a78fdd386f | ||
|
348c1cb965 | ||
|
32fc7def7c | ||
|
14602a7384 | ||
|
c683ef9ad9 | ||
|
039cc7458d | ||
|
d99f16f82d | ||
|
243e48e609 | ||
|
fac9f1ba58 | ||
|
6a5ecb4d95 | ||
|
dc28eae95a | ||
|
baf96da80c | ||
|
31ca6d9fd2 | ||
|
04befeb180 | ||
|
a4c8a2290d | ||
|
96ec5bb665 | ||
|
f60cea2216 | ||
|
77dd9fabfa | ||
|
ee67037a3f | ||
|
b46cf53be5 | ||
|
02741f2c1b | ||
|
955b9239b9 | ||
|
53ac853367 | ||
|
1c38671356 | ||
|
91527fbd0d | ||
|
537d4163c2 | ||
|
c0e4a3a988 | ||
|
860049fad5 | ||
|
344f269414 | ||
|
3487353fc7 | ||
|
86fc8f4186 | ||
|
acb80da387 | ||
|
d99d8443ee | ||
|
319f9c392c | ||
|
a61a630ee6 | ||
|
e8260c164f | ||
|
4e4986f670 | ||
|
3610a2508b | ||
|
8396d07d9e | ||
|
59acd0f82f | ||
|
544ae6f915 | ||
|
111399cf4a | ||
|
fba5cee519 | ||
|
f95d79129e | ||
|
02ce353c6d | ||
|
241d9a2140 | ||
|
849ebf17f1 | ||
|
41776fbd02 | ||
|
5c7631e713 | ||
|
41e2478a6f | ||
|
a9d35dcccd | ||
|
e87766f106 | ||
|
a038f47a25 | ||
|
d841a2c862 | ||
|
4ee7025ab0 | ||
|
d0fa308f6e | ||
|
4456c8771d | ||
|
caa551a469 | ||
|
ccf5afbba9 | ||
|
2474ffc2ba | ||
|
5cf4d8e160 | ||
|
49ff9a249e | ||
|
abc448eca0 | ||
|
d7177cac97 | ||
|
c6182e8923 | ||
|
270730d9b3 | ||
|
4ec5c1dfcc | ||
|
da27c67e6b | ||
|
de3b53c676 | ||
|
3ac993bae4 | ||
|
756de57919 | ||
|
d9cf989813 | ||
|
ffc69576f2 | ||
|
2bed7f161b | ||
|
607607ef0a | ||
|
b2ba7709df | ||
|
8b488a5ca9 | ||
|
1d8ef79da6 | ||
|
bbf32730cd | ||
|
f58ca39e8c | ||
|
3b5f4ded31 | ||
|
f6fdfeb95f | ||
|
2c25319fb8 | ||
|
7daa0a250c | ||
|
121c2585c8 | ||
|
b18b94818a | ||
|
63db16a711 | ||
|
c30ab91738 | ||
|
e8f16292d1 | ||
|
db28abaa44 | ||
|
bfb2490938 | ||
|
b4ab88f708 | ||
|
2dab595476 | ||
|
a98967fccc | ||
|
32e4540464 | ||
|
02dc28e89c | ||
|
47545d9d32 | ||
|
5670dfc1d5 | ||
|
34f8af599d | ||
|
d36fe4d0e9 | ||
|
44317e2d34 | ||
|
5b806a2589 | ||
|
5a13c7fef7 | ||
|
c22a49f64e | ||
|
436024b4a0 | ||
|
61cde0f7e1 | ||
|
a9399873fd | ||
|
c2be1d3668 | ||
|
1d981d2c5a | ||
|
c2b7ca780e | ||
|
57e95c8969 | ||
|
56a74fb5dd | ||
|
49685c3989 | ||
|
9767e1e7fd | ||
|
a83e9c01a6 | ||
|
7b1ceeedf4 | ||
|
a0b3c9f8a4 | ||
|
a2a45757e9 | ||
|
271d21c7bd | ||
|
46b88566f1 | ||
|
af60bceada | ||
|
3583a5d251 | ||
|
4503aeabc4 | ||
|
7f1d3df4a5 | ||
|
17f1289c84 | ||
|
fc3d0fddd2 | ||
|
4bd5c89266 | ||
|
a0599ab812 | ||
|
6c54296ba3 | ||
|
7ed415040a | ||
|
011cb159cf | ||
|
25fd2c3840 | ||
|
7e3976785f | ||
|
75213fcede | ||
|
179ff980e9 | ||
|
f784550964 | ||
|
ce238d08e9 | ||
|
f9864a24ed | ||
|
738d50dd43 | ||
|
7d49f934bc | ||
|
fbb5522861 | ||
|
0ce509f80e | ||
|
b6b215ee6f | ||
|
d7f3ee9f98 | ||
|
2328c8bafe | ||
|
dfd642bb82 | ||
|
6c9bf4ff81 | ||
|
481685b3bb | ||
|
f31d431517 | ||
|
604f2ffe3d | ||
|
4e0b22375f | ||
|
9d0c7691d8 | ||
|
cef28e94ea | ||
|
40106ddeb1 | ||
|
8695562cb4 | ||
|
5338eab3a5 | ||
|
d7bb6049e1 | ||
|
ea7464722b | ||
|
d6da646d87 | ||
|
17c1f913df | ||
|
6c94e75513 | ||
|
801894abc6 | ||
|
207c004228 | ||
|
36f73a6106 | ||
|
41d80af128 | ||
|
145504bdd6 | ||
|
9fd0d404a1 | ||
|
b75599e55d | ||
|
67062d6ed8 | ||
|
c43d49ed54 | ||
|
e9867173c9 | ||
|
f580535d35 | ||
|
1d7529e609 | ||
|
1fb7ca0007 | ||
|
b576bd0fcc | ||
|
f19dcc0114 | ||
|
38a49d172c | ||
|
72935b0558 | ||
|
a5332efcfb | ||
|
15954830e2 | ||
|
46ab760a56 | ||
|
0b0135268e | ||
|
511fb445d1 | ||
|
bcfb2146cd | ||
|
a1b662a325 | ||
|
14b5bf7d0d | ||
|
d288989386 | ||
|
d63941797f | ||
|
1ea2811713 | ||
|
af56784797 | ||
|
2461406887 | ||
|
8e11dd97e9 | ||
|
2690febf20 | ||
|
af3d278825 | ||
|
c9647f9b33 | ||
|
e1703aea3f | ||
|
e02107feea | ||
|
192b043e7a | ||
|
8c72d4c18d | ||
|
0da913cd4a | ||
|
fb3d69c5e7 | ||
|
c40208ac66 | ||
|
069c22e9cd | ||
|
8f30bb33a3 | ||
|
4326c5e29b | ||
|
a51a54bc59 | ||
|
d88079000a | ||
|
574cbc35d8 | ||
|
fc76a15c46 | ||
|
fd53a76bf6 | ||
|
b5c1394662 | ||
|
66d7cb581c | ||
|
8f823420b6 | ||
|
36d5e011e8 | ||
|
5a4bcbf377 | ||
|
0fe007569e | ||
|
c49e454ec0 | ||
|
8afc8c62ef | ||
|
4644adff94 | ||
|
5e08083b5a | ||
|
95a8da803a | ||
|
43a41b34bc | ||
|
9c285a09e5 | ||
|
9d21df8e1b | ||
|
1da2c57376 | ||
|
409af292af | ||
|
108002248c | ||
|
43795f4c87 | ||
|
1f68da6b77 | ||
|
98e0e84d57 | ||
|
6ddba4363a | ||
|
b5b5c40ecd | ||
|
d84fe2b800 | ||
|
da561ba4d5 | ||
|
2257ff9798 | ||
|
c40b8a4122 | ||
|
1f445742b4 | ||
|
d629846220 | ||
|
b26b2d4be0 | ||
|
b65c09411a | ||
|
a51b813f70 | ||
|
1078d94b73 | ||
|
12c105623c | ||
|
d950460e14 | ||
|
2c2686946d | ||
|
9175da2cf0 | ||
|
14d025a342 | ||
|
c98b62caca | ||
|
d425997c26 | ||
|
84b1b62e0e | ||
|
b248e0ae9a | ||
|
f1a39c006f | ||
|
3e34f785c6 | ||
|
9694813724 | ||
|
3393526876 | ||
|
b6424c9d37 | ||
|
bf560ae9d2 | ||
|
fa1a007dc1 | ||
|
abc0a7931e | ||
|
ad523f37c5 | ||
|
cf33d53809 | ||
|
e8b1bcd216 | ||
|
dead7f2f6a | ||
|
df6b01a632 | ||
|
9755090c8c | ||
|
3815d97f5f | ||
|
7cb4a75ca7 | ||
|
af85d5c895 | ||
|
b012340830 | ||
|
002004cb5f | ||
|
f3769ca301 | ||
|
07e30b9acd | ||
|
66747ec753 | ||
|
8ed2cd65b6 | ||
|
3977159415 | ||
|
3333e2ce8c | ||
|
ab948c29b7 | ||
|
af0cbcf2c1 | ||
|
95b93a0698 | ||
|
04ebd069b4 | ||
|
fcb094463b | ||
|
b0d609d386 | ||
|
69e03bbfb7 | ||
|
962cda957d | ||
|
5c63fe9487 | ||
|
8059e524f1 | ||
|
2a45d7173a | ||
|
1fa3e5beac | ||
|
2a2f96f9b6 | ||
|
d2f6bd08fc | ||
|
66c7ecf2ab | ||
|
e0db238cf0 | ||
|
613bb2b7c6 | ||
|
7ffded5b13 | ||
|
e01110c739 | ||
|
856674506c | ||
|
41a63df1b1 | ||
|
40897ece3c | ||
|
a19d214272 | ||
|
06f85c3a2d | ||
|
6c77e89bbe | ||
|
22376ba54a | ||
|
355ef009c8 | ||
|
b659e3bc91 | ||
|
014e176e0a | ||
|
9d2d13a389 | ||
|
1936f9ab8a | ||
|
ede2f53ba5 | ||
|
df243a40b5 | ||
|
30391836d0 | ||
|
ea9dd29721 | ||
|
5bf48fa6c0 | ||
|
96b8b19dd3 | ||
|
fdee6c22cf | ||
|
4988db95bc | ||
|
a5e5954ae7 | ||
|
a4d0cd9612 | ||
|
d20a822fdb | ||
|
0250229e81 | ||
|
8a4283edd1 | ||
|
e74e6f2342 | ||
|
a30f7346f7 | ||
|
8c3752ef9f | ||
|
f60e2cd6bd | ||
|
ccf7c414be | ||
|
f5e78c899a | ||
|
41bd2334fa | ||
|
b2b55eb06e | ||
|
ca3eacbd79 | ||
|
fa87adb4a3 | ||
|
8321cd29d6 | ||
|
ecf8fb6a5f | ||
|
9ec52e3473 | ||
|
3565ec885e | ||
|
ab2c7bed88 | ||
|
7b127439ea | ||
|
9f66990af2 | ||
|
b01a4406fa | ||
|
09872cf426 | ||
|
87d5faf30b | ||
|
c154a63967 | ||
|
4102db1eb9 | ||
|
d0d5c655fc | ||
|
716627f47d | ||
|
f1504eca15 | ||
|
67c944f219 | ||
|
66e2311bf0 | ||
|
90076cf689 | ||
|
0fcd14c089 | ||
|
cbc65bf766 | ||
|
4b089606ea | ||
|
f7ac0f2a1e | ||
|
698ec52d5c | ||
|
220aa6d13a | ||
|
9388c8926c | ||
|
4d0eb756d2 | ||
|
eab0e100c4 | ||
|
989ec06838 | ||
|
6e75c4a95d | ||
|
41d60e5e90 | ||
|
7db2675087 | ||
|
78f3164063 | ||
|
51fdcddaea | ||
|
d527669d39 | ||
|
e166c83d33 | ||
|
efc97aa2b0 | ||
|
c73b08e341 | ||
|
5de40a4e61 | ||
|
8e58da2daf | ||
|
43ea62d444 | ||
|
28b33d1b22 | ||
|
be44508316 | ||
|
a4aab9bc16 | ||
|
6dca3d9d17 | ||
|
7768401a03 | ||
|
5866836d5d | ||
|
c3b2bbd647 | ||
|
c0c402797f | ||
|
14d0968c92 | ||
|
fe9642f1f1 | ||
|
79c00c68e5 | ||
|
c43b39fe70 | ||
|
a4868e16e9 | ||
|
91ed1359fc | ||
|
484e21e693 | ||
|
193c2b7912 | ||
|
249d47c5f7 | ||
|
5d8209cf10 | ||
|
c75a91d15f | ||
|
b2655260fa | ||
|
a1c7d14efa | ||
|
acbe03157c | ||
|
72053457a0 | ||
|
6a15f91a14 | ||
|
a283ab14a2 | ||
|
1c5f912019 | ||
|
223a185124 | ||
|
f53b9742cb | ||
|
cd97c55465 | ||
|
95eb664641 | ||
|
858fd8ce62 | ||
|
09cb0b07bb | ||
|
06ba3acc93 | ||
|
81ae2b3a83 | ||
|
e6a20e5984 | ||
|
ae3b256746 | ||
|
bf26e49f2c | ||
|
925405826a | ||
|
a781cc76a0 | ||
|
abd2b9c71e | ||
|
469053a144 | ||
|
dd7852014f | ||
|
78d3c5b679 | ||
|
e44484cc26 | ||
|
19a2aed020 | ||
|
712e78b0c8 | ||
|
d679b1af76 | ||
|
e2736e5806 | ||
|
762f501f2c | ||
|
86ab14e5ec |
136
.github/workflows/ci.yml
vendored
@ -3,56 +3,103 @@ name: Abaddon CI
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
windows:
|
||||
name: windows-${{ matrix.buildtype }}
|
||||
msys2:
|
||||
name: msys2-mingw64
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
matrix:
|
||||
buildtype: [Debug, RelWithDebInfo]
|
||||
buildtype: [Debug, RelWithDebInfo, MinSizeRel]
|
||||
mindeps: [false]
|
||||
include:
|
||||
- buildtype: RelWithDebInfo
|
||||
mindeps: true
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Fetch CMake
|
||||
uses: lukka/get-cmake@latest
|
||||
|
||||
- name: Fetch dependencies
|
||||
uses: lukka/run-vcpkg@main
|
||||
- name: Setup MSYS2 (1)
|
||||
uses: haya14busa/action-cond@v1
|
||||
id: setupmsys
|
||||
with:
|
||||
vcpkgArguments: gtkmm nlohmann-json zlib sqlite3 glibmm openssl ixwebsocket curl
|
||||
vcpkgDirectory: ${{ github.workspace }}/ci/vcpkg/
|
||||
vcpkgTriplet: x64-windows
|
||||
cond: ${{ matrix.mindeps == true }}
|
||||
if_true: >-
|
||||
git
|
||||
make
|
||||
mingw-w64-x86_64-toolchain
|
||||
mingw-w64-x86_64-cmake
|
||||
mingw-w64-x86_64-ninja
|
||||
mingw-w64-x86_64-sqlite3
|
||||
mingw-w64-x86_64-nlohmann-json
|
||||
mingw-w64-x86_64-curl
|
||||
mingw-w64-x86_64-zlib
|
||||
mingw-w64-x86_64-gtkmm3
|
||||
if_false: >-
|
||||
git
|
||||
make
|
||||
mingw-w64-x86_64-toolchain
|
||||
mingw-w64-x86_64-cmake
|
||||
mingw-w64-x86_64-ninja
|
||||
mingw-w64-x86_64-sqlite3
|
||||
mingw-w64-x86_64-nlohmann-json
|
||||
mingw-w64-x86_64-curl
|
||||
mingw-w64-x86_64-zlib
|
||||
mingw-w64-x86_64-gtkmm3
|
||||
mingw-w64-x86_64-libhandy
|
||||
|
||||
- name: Setup MSYS2 (2)
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: mingw64
|
||||
update: true
|
||||
install: ${{ steps.setupmsys.outputs.value }}
|
||||
|
||||
- name: Build
|
||||
uses: lukka/run-cmake@main
|
||||
with:
|
||||
useVcpkgToolchainFile: true
|
||||
vcpkgTriplet: x64-windows
|
||||
buildDirectory: ${{ runner.workspace }}/build
|
||||
cmakeBuildType: ${{ matrix.buildtype }}
|
||||
|
||||
- name: Setup artifact files
|
||||
shell: cmd
|
||||
run: |
|
||||
del /f /s /q "${{ runner.workspace }}\build\CMakeFiles"
|
||||
rmdir /s /q "${{ runner.workspace }}\build\CMakeFiles"
|
||||
del /f /s /q "${{ runner.workspace }}\build\.ninja_deps"
|
||||
del /f /s /q "${{ runner.workspace }}\build\.ninja_log"
|
||||
del /f /s /q "${{ runner.workspace }}\build\abaddon.ilk"
|
||||
del /f /s /q "${{ runner.workspace }}\build\CMakeCache.txt"
|
||||
xcopy /E /I "${{ github.workspace }}\css" "${{ runner.workspace }}\build\css"
|
||||
xcopy /E /I "${{ github.workspace }}\res" "${{ runner.workspace }}\build\res"
|
||||
mkdir "${{ runner.workspace }}\build\share"
|
||||
xcopy /E /I "${{ github.workspace }}\ci\gtk-for-windows\gtk-nsis-pack\share\glib-2.0" "${{ runner.workspace }}\build\share\glib-2.0"
|
||||
copy "${{ github.workspace }}\ci\vcpkg\installed\x64-windows\tools\glib\gspawn-win64-helper.exe" "${{ runner.workspace }}\build\gspawn-win64-helper.exe"
|
||||
copy "${{ github.workspace }}\ci\vcpkg\installed\x64-windows\tools\glib\gspawn-win64-helper-console.exe" "${{ runner.workspace }}\build\gspawn-win64-helper-console.exe"
|
||||
cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=${{ matrix.buildtype }}
|
||||
cmake --build build
|
||||
|
||||
- name: Upload build
|
||||
- name: Setup Artifact
|
||||
run: |
|
||||
mkdir -p build/artifactdir/bin build/artifactdir/ssl/certs build/artifactdir/lib build/artifactdir/share/glib-2.0/schemas
|
||||
cd build
|
||||
cp *.exe artifactdir/bin
|
||||
cd ..
|
||||
cp /mingw64/ssl/certs/ca-bundle.crt build/artifactdir/ssl/certs
|
||||
cp -r /mingw64/lib/gdk-pixbuf-2.0 build/artifactdir/lib
|
||||
cp -r res/css res/res res/fonts build/artifactdir/bin
|
||||
cp /mingw64/share/glib-2.0/schemas/gschemas.compiled build/artifactdir/share/glib-2.0/schemas
|
||||
cat "ci/msys-deps.txt" | sed 's/\r$//' | xargs -I % cp /mingw64% build/artifactdir/bin || :
|
||||
cp /usr/bin/msys-ffi-8.dll build/artifactdir/bin/libffi-8.dll
|
||||
mkdir -p build/artifactdir/share/icons/Adwaita
|
||||
cd build/artifactdir/share/icons/Adwaita
|
||||
mkdir -p 16x16/actions 24x24/actions 32x32/actions 48x48/actions 64x64/actions 96x96/actions scalable/actions
|
||||
cd ../../../../../
|
||||
cat "ci/used-icons.txt" | sed 's/\r$//' | xargs -I % cp ci/gtk-for-windows/gtk-nsis-pack/share/icons/Adwaita/16x16/actions/%.symbolic.png build/artifactdir/share/icons/Adwaita/16x16/actions || :
|
||||
cat "ci/used-icons.txt" | sed 's/\r$//' | xargs -I % cp ci/gtk-for-windows/gtk-nsis-pack/share/icons/Adwaita/24x24/actions/%.symbolic.png build/artifactdir/share/icons/Adwaita/24x24/actions || :
|
||||
cat "ci/used-icons.txt" | sed 's/\r$//' | xargs -I % cp ci/gtk-for-windows/gtk-nsis-pack/share/icons/Adwaita/32x32/actions/%.symbolic.png build/artifactdir/share/icons/Adwaita/32x32/actions || :
|
||||
cat "ci/used-icons.txt" | sed 's/\r$//' | xargs -I % cp ci/gtk-for-windows/gtk-nsis-pack/share/icons/Adwaita/48x48/actions/%.symbolic.png build/artifactdir/share/icons/Adwaita/48x48/actions || :
|
||||
cat "ci/used-icons.txt" | sed 's/\r$//' | xargs -I % cp ci/gtk-for-windows/gtk-nsis-pack/share/icons/Adwaita/64x64/actions/%.symbolic.png build/artifactdir/share/icons/Adwaita/64x64/actions || :
|
||||
cat "ci/used-icons.txt" | sed 's/\r$//' | xargs -I % cp ci/gtk-for-windows/gtk-nsis-pack/share/icons/Adwaita/96x96/actions/%.symbolic.png build/artifactdir/share/icons/Adwaita/96x96/actions || :
|
||||
cat "ci/used-icons.txt" | sed 's/\r$//' | xargs -I % cp ci/gtk-for-windows/gtk-nsis-pack/share/icons/Adwaita/scalable/actions/%.svg build/artifactdir/share/icons/Adwaita/scalable/actions || :
|
||||
|
||||
- name: Upload build (1)
|
||||
uses: haya14busa/action-cond@v1
|
||||
id: buildname
|
||||
with:
|
||||
cond: ${{ matrix.mindeps == true }}
|
||||
if_true: "${{ matrix.buildtype }}-mindeps"
|
||||
if_false: "${{ matrix.buildtype }}"
|
||||
|
||||
- name: Upload build (2)
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: build-windows-${{ matrix.buildtype }}
|
||||
path: ${{ runner.workspace }}/build
|
||||
name: build-windows-msys2-${{ steps.buildname.outputs.value }}
|
||||
path: build/artifactdir
|
||||
|
||||
mac:
|
||||
name: macos-${{ matrix.buildtype }}
|
||||
runs-on: macos-latest
|
||||
@ -65,15 +112,16 @@ jobs:
|
||||
submodules: true
|
||||
|
||||
- name: Fetch CMake
|
||||
uses: lukka/get-cmake@latest
|
||||
uses: lukka/get-cmake@v3.21.2
|
||||
|
||||
- name: Fetch dependencies
|
||||
run: |
|
||||
brew install gtkmm3
|
||||
brew install nlohmann-json
|
||||
brew install jpeg
|
||||
|
||||
- name: Build
|
||||
uses: lukka/run-cmake@main
|
||||
uses: lukka/run-cmake@v3
|
||||
with:
|
||||
buildDirectory: ${{ runner.workspace }}/build
|
||||
cmakeBuildType: ${{ matrix.buildtype }}
|
||||
@ -82,8 +130,8 @@ jobs:
|
||||
run: |
|
||||
mkdir "${{ runner.workspace }}/artifactdir"
|
||||
cp "${{runner.workspace}}/build/abaddon" "${{ runner.workspace }}/artifactdir/abaddon"
|
||||
cp -r "${{ github.workspace }}/css" "${{ runner.workspace }}/artifactdir/css"
|
||||
cp -r "${{ github.workspace }}/res" "${{ runner.workspace }}/artifactdir/res"
|
||||
cp -r "${{ github.workspace }}/res/css" "${{ runner.workspace }}/artifactdir/css"
|
||||
cp -r "${{ github.workspace }}/res/res" "${{ runner.workspace }}/artifactdir/res"
|
||||
|
||||
- name: Upload build
|
||||
uses: actions/upload-artifact@v2
|
||||
@ -103,7 +151,7 @@ jobs:
|
||||
submodules: true
|
||||
|
||||
- name: Fetch CMake
|
||||
uses: lukka/get-cmake@latest
|
||||
uses: lukka/get-cmake@v3.21.2
|
||||
|
||||
- name: Fetch dependencies
|
||||
run: |
|
||||
@ -112,7 +160,7 @@ jobs:
|
||||
cd deps
|
||||
git clone https://github.com/nlohmann/json
|
||||
cd json
|
||||
git checkout db78ac1d7716f56fc9f1b030b715f872f93964e4
|
||||
git checkout bc889afb4c5bf1c0d8ee29ef35eaaf4c8bef8a5d
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
@ -122,7 +170,7 @@ jobs:
|
||||
sudo apt-get install libcurl4-gnutls-dev
|
||||
|
||||
- name: Build
|
||||
uses: lukka/run-cmake@main
|
||||
uses: lukka/run-cmake@v3
|
||||
env:
|
||||
CC: gcc-9
|
||||
CXX: g++-9
|
||||
@ -135,8 +183,8 @@ jobs:
|
||||
run: |
|
||||
mkdir "${{ runner.workspace }}/artifactdir"
|
||||
cp "${{runner.workspace}}/build/abaddon" "${{ runner.workspace }}/artifactdir/abaddon"
|
||||
cp -r "${{ github.workspace }}/css" "${{ runner.workspace }}/artifactdir/css"
|
||||
cp -r "${{ github.workspace }}/res" "${{ runner.workspace }}/artifactdir/res"
|
||||
cp -r "${{ github.workspace }}/res/css" "${{ runner.workspace }}/artifactdir/css"
|
||||
cp -r "${{ github.workspace }}/res/res" "${{ runner.workspace }}/artifactdir/res"
|
||||
|
||||
- name: Upload build
|
||||
uses: actions/upload-artifact@v2
|
||||
|
8
.gitignore
vendored
@ -354,3 +354,11 @@ testdata/
|
||||
|
||||
build/
|
||||
out/
|
||||
|
||||
fonts/fonts.conf
|
||||
|
||||
# To make sure no zipped resources are added to the repo
|
||||
*.7z
|
||||
*.zip
|
||||
*.tar.*
|
||||
*.rar
|
||||
|
18
.gitmodules
vendored
@ -1,15 +1,9 @@
|
||||
[submodule "vcpkg"]
|
||||
path = ci/vcpkg
|
||||
url = https://github.com/microsoft/vcpkg/
|
||||
[submodule "thirdparty/simpleini"]
|
||||
path = thirdparty/simpleini
|
||||
url = https://github.com/brofield/simpleini
|
||||
[submodule "thirdparty/IXWebSocket"]
|
||||
path = thirdparty/IXWebSocket
|
||||
url = https://github.com/machinezone/ixwebsocket
|
||||
[submodule "ci/vcpkg"]
|
||||
path = ci/vcpkg
|
||||
url = https://github.com/microsoft/vcpkg
|
||||
[submodule "ci/gtk-for-windows"]
|
||||
path = ci/gtk-for-windows
|
||||
url = https://github.com/tschoonj/GTK-for-Windows-Runtime-Environment-Installer
|
||||
[submodule "subprojects/ixwebsocket"]
|
||||
path = subprojects/ixwebsocket
|
||||
url = https://github.com/machinezone/ixwebsocket
|
||||
[submodule "subprojects/keychain"]
|
||||
path = subprojects/keychain
|
||||
url = https://github.com/hrantzsch/keychain
|
||||
|
139
CMakeLists.txt
@ -2,11 +2,13 @@ cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(abaddon)
|
||||
|
||||
set(ABADDON_RESOURCE_DIR "/usr/share/abaddon" CACHE PATH "Fallback directory for resources on Linux")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
|
||||
|
||||
set(USE_TLS TRUE)
|
||||
set(USE_OPEN_SSL TRUE)
|
||||
option(USE_LIBHANDY "Enable features that require libhandy (default)" ON)
|
||||
option(USE_KEYCHAIN "Store the token in the keychain (default)" ON)
|
||||
|
||||
find_package(nlohmann_json REQUIRED)
|
||||
find_package(CURL)
|
||||
@ -14,79 +16,104 @@ find_package(ZLIB REQUIRED)
|
||||
find_package(SQLite3 REQUIRED)
|
||||
find_package(gtkmm REQUIRED)
|
||||
|
||||
find_path(IXWEBSOCKET_INCLUDE_DIRS ixwebsocket/IXWebSocket.h)
|
||||
find_library(IXWEBSOCKET_LIBRARY ixwebsocket)
|
||||
if (NOT IXWEBSOCKET_LIBRARY)
|
||||
add_subdirectory(thirdparty/IXWebSocket)
|
||||
include_directories(IXWEBSOCKET_INCLUDE_DIRS)
|
||||
endif()
|
||||
set(USE_TLS TRUE)
|
||||
set(USE_OPEN_SSL TRUE)
|
||||
find_package(IXWebSocket QUIET)
|
||||
if (NOT IXWebSocket_FOUND)
|
||||
message("ixwebsocket was not found and will be included as a submodule")
|
||||
add_subdirectory(subprojects/ixwebsocket)
|
||||
include_directories(IXWEBSOCKET_INCLUDE_DIRS)
|
||||
endif ()
|
||||
|
||||
include_directories(thirdparty/simpleini)
|
||||
if (MINGW OR WIN32)
|
||||
link_libraries(ws2_32)
|
||||
endif ()
|
||||
|
||||
if(MINGW OR WIN32)
|
||||
link_libraries(ws2_32)
|
||||
endif()
|
||||
if (WIN32)
|
||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||||
add_compile_definitions(NOMINMAX)
|
||||
endif ()
|
||||
|
||||
if(WIN32)
|
||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||||
add_compile_definitions(NOMINMAX)
|
||||
endif()
|
||||
include(TestBigEndian)
|
||||
test_big_endian(IS_BIG_ENDIAN)
|
||||
if (IS_BIG_ENDIAN)
|
||||
add_compile_definitions(ABADDON_IS_BIG_ENDIAN)
|
||||
endif ()
|
||||
|
||||
file(GLOB ABADDON_SOURCES
|
||||
"*.h"
|
||||
"*.hpp"
|
||||
"*.cpp"
|
||||
"discord/*.hpp"
|
||||
"discord/*.cpp"
|
||||
"components/*.hpp"
|
||||
"components/*.cpp"
|
||||
"windows/*.hpp"
|
||||
"windows/*.cpp"
|
||||
"windows/guildsettings/*.hpp"
|
||||
"windows/guildsettings/*.cpp"
|
||||
"windows/profile/*.hpp"
|
||||
"windows/profile/*.cpp"
|
||||
"dialogs/*.hpp"
|
||||
"dialogs/*.cpp"
|
||||
)
|
||||
configure_file(${PROJECT_SOURCE_DIR}/src/config.h.in ${PROJECT_BINARY_DIR}/config.h)
|
||||
|
||||
file(GLOB_RECURSE ABADDON_SOURCES
|
||||
"src/*.h"
|
||||
"src/*.hpp"
|
||||
"src/*.cpp"
|
||||
)
|
||||
|
||||
add_executable(abaddon ${ABADDON_SOURCES})
|
||||
target_include_directories(abaddon PUBLIC ${PROJECT_SOURCE_DIR}/src)
|
||||
target_include_directories(abaddon PUBLIC ${PROJECT_BINARY_DIR})
|
||||
target_include_directories(abaddon PUBLIC ${GTKMM_INCLUDE_DIRS})
|
||||
target_include_directories(abaddon PUBLIC ${ZLIB_INCLUDE_DIRS})
|
||||
target_include_directories(abaddon PUBLIC ${SQLite3_INCLUDE_DIRS})
|
||||
target_include_directories(abaddon PUBLIC ${NLOHMANN_JSON_INCLUDE_DIRS})
|
||||
|
||||
if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR
|
||||
(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND
|
||||
((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_CXX_COMPILER_VERSION LESS 9))))
|
||||
target_link_libraries(abaddon stdc++fs)
|
||||
endif()
|
||||
(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND
|
||||
((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_CXX_COMPILER_VERSION LESS 9))))
|
||||
target_link_libraries(abaddon stdc++fs)
|
||||
endif ()
|
||||
|
||||
if (IXWEBSOCKET_LIBRARY)
|
||||
target_link_libraries(abaddon ${IXWEBSOCKET_LIBRARY})
|
||||
find_library(MBEDTLS_X509_LIBRARY mbedx509)
|
||||
find_library(MBEDTLS_TLS_LIBRARY mbedtls)
|
||||
find_library(MBEDTLS_CRYPTO_LIBRARY mbedcrypto)
|
||||
if (MBEDTLS_TLS_LIBRARY)
|
||||
target_link_libraries(abaddon ${MBEDTLS_TLS_LIBRARY})
|
||||
endif()
|
||||
if (MBEDTLS_X509_LIBRARY)
|
||||
target_link_libraries(abaddon ${MBEDTLS_X509_LIBRARY})
|
||||
endif()
|
||||
if (MBEDTLS_CRYPTO_LIBRARY)
|
||||
target_link_libraries(abaddon ${MBEDTLS_CRYPTO_LIBRARY})
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(abaddon $<BUILD_INTERFACE:ixwebsocket>)
|
||||
endif()
|
||||
if (IXWebSocket_LIBRARIES)
|
||||
target_link_libraries(abaddon ${IXWebSocket_LIBRARIES})
|
||||
find_library(MBEDTLS_X509_LIBRARY mbedx509)
|
||||
find_library(MBEDTLS_TLS_LIBRARY mbedtls)
|
||||
find_library(MBEDTLS_CRYPTO_LIBRARY mbedcrypto)
|
||||
if (MBEDTLS_TLS_LIBRARY)
|
||||
target_link_libraries(abaddon ${MBEDTLS_TLS_LIBRARY})
|
||||
endif ()
|
||||
if (MBEDTLS_X509_LIBRARY)
|
||||
target_link_libraries(abaddon ${MBEDTLS_X509_LIBRARY})
|
||||
endif ()
|
||||
if (MBEDTLS_CRYPTO_LIBRARY)
|
||||
target_link_libraries(abaddon ${MBEDTLS_CRYPTO_LIBRARY})
|
||||
endif ()
|
||||
else ()
|
||||
target_link_libraries(abaddon $<BUILD_INTERFACE:ixwebsocket>)
|
||||
endif ()
|
||||
|
||||
find_package(Threads)
|
||||
if (Threads_FOUND)
|
||||
target_link_libraries(abaddon Threads::Threads)
|
||||
endif()
|
||||
target_link_libraries(abaddon Threads::Threads)
|
||||
endif ()
|
||||
|
||||
find_package(Fontconfig QUIET)
|
||||
if (Fontconfig_FOUND)
|
||||
target_link_libraries(abaddon Fontconfig::Fontconfig)
|
||||
endif ()
|
||||
|
||||
target_link_libraries(abaddon ${SQLite3_LIBRARIES})
|
||||
target_link_libraries(abaddon ${GTKMM_LIBRARIES})
|
||||
target_link_libraries(abaddon ${CURL_LIBRARIES})
|
||||
target_link_libraries(abaddon ${ZLIB_LIBRARY})
|
||||
target_link_libraries(abaddon ${NLOHMANN_JSON_LIBRARIES})
|
||||
|
||||
if (USE_LIBHANDY)
|
||||
find_package(libhandy)
|
||||
if (NOT libhandy_FOUND)
|
||||
message("libhandy could not be found. features requiring it have been disabled")
|
||||
set(USE_LIBHANDY OFF)
|
||||
else ()
|
||||
target_include_directories(abaddon PUBLIC ${libhandy_INCLUDE_DIRS})
|
||||
target_link_libraries(abaddon ${libhandy_LIBRARIES})
|
||||
target_compile_definitions(abaddon PRIVATE WITH_LIBHANDY)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (USE_KEYCHAIN)
|
||||
find_package(keychain QUIET)
|
||||
if (NOT keychain_FOUND)
|
||||
message("keychain was not found and will be included as a submodule")
|
||||
add_subdirectory(subprojects/keychain)
|
||||
target_link_libraries(abaddon keychain)
|
||||
target_compile_definitions(abaddon PRIVATE WITH_KEYCHAIN)
|
||||
endif ()
|
||||
endif ()
|
||||
|
375
README.md
@ -4,12 +4,16 @@ Alternative Discord client made in C++ with GTK
|
||||
|
||||
<img src="/.readme/s3.png">
|
||||
|
||||
<a href="https://discord.gg/wkCU3vuzG5"><img src="https://discord.com/api/guilds/858156817711890443/widget.png?style=shield"></a>
|
||||
|
||||
Current features:
|
||||
|
||||
* Not Electron
|
||||
* Handles most types of chat messages including embeds, images, and replies
|
||||
* Completely styleable/customizable with CSS (if you have a system GTK theme it won't really use it though)
|
||||
* Identifies to gateway as the web client unlike other clients so less likely to be falsely flagged as spam<sup>1</sup>
|
||||
* Identifies to Discord as the web client unlike other clients so less likely to be falsely flagged as spam<sup>1</sup>
|
||||
* Set status
|
||||
* Unread and mention indicators
|
||||
* Start new DMs and group DMs
|
||||
* View user profiles (notes, mutual servers, mutual friends)
|
||||
* Kick, ban, and unban members
|
||||
@ -18,176 +22,279 @@ Current features:
|
||||
* Manage emojis
|
||||
* View audit log
|
||||
* Emojis<sup>2</sup>
|
||||
* Thread support<sup>3</sup>
|
||||
* Animated avatars, server icons, emojis (can be turned off)
|
||||
|
||||
1 - Other third-party clients send the IDENTIFY message that bots use which makes Discord more likely to think you are selfbotting or spamming. However, Discord still loves to ban people's accounts for no good reason, even users of the official clients. If you want to be really careful avoid joining servers really fast or cold DMing people.
|
||||
2 - Getting emojis to function properly on GTK is still something I've yet to figure out ([#5](../../issues/5)). Unicode emojis are manually searched for and replaced in several places as opposed to allowing GTK to figure it out since GTK's way of doing it doesn't work very well.
|
||||
|
||||
|
||||
1 - Abaddon tries its best (though is not perfect) to make Discord think it's a legitimate web client. Some of the
|
||||
things done to do this
|
||||
include: using a browser user agent, sending the same IDENTIFY message that the official web client does, using API v9
|
||||
endpoints in all cases, and not using endpoints the web client does not normally use. There are still a few smaller
|
||||
inconsistencies, however. For example the web client sends lots of telemetry via the `/science` endpoint (uBlock origin
|
||||
stops this) as well as in the headers of all requests.<br>
|
||||
|
||||
**See [here](#the-spam-filter)** for things you might want to avoid if you are worried about being caught in the spam
|
||||
filter.
|
||||
|
||||
2 - Unicode emojis are substituted manually as opposed to rendered by GTK on non-Windows platforms. This can be changed
|
||||
with the `stock_emojis` setting as shown at the bottom of this README. A CBDT-based font using Twemoji is provided to
|
||||
allow GTK to render emojis natively on Windows.
|
||||
|
||||
3 - There are some inconsistencies with thread state that might be encountered in some more uncommon cases, but they are
|
||||
the result of fundamental issues with Discord's thread implementation.
|
||||
|
||||
### Building manually (recommended if not on Windows):
|
||||
#### Windows:
|
||||
1. `git clone https://github.com/uowuo/abaddon && cd abaddon`
|
||||
2. `vcpkg install gtkmm:x64-windows nlohmann-json:x64-windows ixwebsocket:x64-windows zlib:x64-windows simpleini:x64-windows sqlite3:x64-windows openssl:x64-windows curl:x64-windows`
|
||||
|
||||
#### Windows (with MSYS2):
|
||||
|
||||
1. Install following packages:
|
||||
* mingw-w64-x86_64-cmake
|
||||
* mingw-w64-x86_64-ninja
|
||||
* mingw-w64-x86_64-sqlite3
|
||||
* mingw-w64-x86_64-nlohmann-json
|
||||
* mingw-w64-x86_64-curl
|
||||
* mingw-w64-x86_64-zlib
|
||||
* mingw-w64-x86_64-gtkmm3
|
||||
* mingw-w64-x86_64-libhandy
|
||||
2. `git clone --recurse-submodules="subprojects" https://github.com/uowuo/abaddon && cd abaddon`
|
||||
3. `mkdir build && cd build`
|
||||
4. `cmake -G"Visual Studio 16 2019" -A x64 -DCMAKE_TOOLCHAIN_FILE=c:\path\to\vcpkg\scripts\buildsystems\vcpkg.cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVCPKG_TARGET_TRIPLET=x64-windows ..`
|
||||
5. Build with Visual Studio
|
||||
|
||||
Or, do steps 1 and 2, and open CMakeLists.txt in Visual Studio if `vcpkg integrate install` was run
|
||||
4. `cmake -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo ..`
|
||||
5. `ninja`
|
||||
|
||||
#### Mac:
|
||||
1. `git clone https://github.com/uowuo/abaddon && cd abaddon`
|
||||
2. `brew install gtkmm3 nlohmann-json`
|
||||
|
||||
1. `git clone https://github.com/uowuo/abaddon --recurse-submodules="subprojects" && cd abaddon`
|
||||
2. `brew install gtkmm3 nlohmann-json libhandy`
|
||||
3. `mkdir build && cd build`
|
||||
4. `cmake ..`
|
||||
5. `make`
|
||||
|
||||
#### Linux:
|
||||
1. Install dependencies: `libgtkmm-3.0-dev`, `libcurl4-gnutls-dev`, and [nlohmann-json](https://github.com/nlohmann/json)
|
||||
2. `git clone https://github.com/uowuo/abaddon && cd abaddon`
|
||||
|
||||
1. Install dependencies
|
||||
* On Ubuntu 20.04 (Focal) and newer:
|
||||
```Shell
|
||||
$ sudo apt install g++ cmake libgtkmm-3.0-dev libcurl4-gnutls-dev libsqlite3-dev libssl-dev nlohmann-json3-dev
|
||||
```
|
||||
* On Arch Linux
|
||||
```Shell
|
||||
$ sudo pacman -S gcc cmake gtkmm3 libcurl-gnutls lib32-sqlite lib32-openssl nlohmann-json libhandy
|
||||
```
|
||||
* On Fedora Linux:
|
||||
```Shell
|
||||
$ sudo dnf install g++ cmake gtkmm3.0-devel libcurl-devel sqlite-devel openssl-devel json-devel libsecret-devel libhandy-devel
|
||||
```
|
||||
2. `git clone https://github.com/uowuo/abaddon --recurse-submodules="subprojects" && cd abaddon`
|
||||
3. `mkdir build && cd build`
|
||||
4. `cmake ..`
|
||||
5. `make`
|
||||
|
||||
### Downloads (from CI):
|
||||
- Windows: [here](https://nightly.link/uowuo/abaddon/workflows/ci/master/build-windows-RelWithDebInfo.zip)
|
||||
- MacOS: [here](https://nightly.link/uowuo/abaddon/workflows/ci/master/build-macos-RelWithDebInfo.zip) unsigned, unpackaged, requires gtkmm3 (e.g. from homebrew)
|
||||
- Linux: [here](https://nightly.link/uowuo/abaddon/workflows/ci/master/build-linux-MinSizeRel.zip) unpackaged (for now), requires gtkmm3. built on Ubuntu 18.04 + gcc9
|
||||
### Downloads:
|
||||
|
||||
⚠️ Make sure you start from the directory where `css` and `res` are or else stuff will be broken
|
||||
Latest release version: https://github.com/uowuo/abaddon/releases/latest
|
||||
|
||||
**CI:**
|
||||
|
||||
- Windows: [here](https://nightly.link/uowuo/abaddon/workflows/ci/master/build-windows-msys2-MinSizeRel.zip)
|
||||
- MacOS: [here](https://nightly.link/uowuo/abaddon/workflows/ci/master/build-macos-RelWithDebInfo.zip) unsigned,
|
||||
unpackaged, requires gtkmm3 (e.g. from homebrew)
|
||||
- Linux: [here](https://nightly.link/uowuo/abaddon/workflows/ci/master/build-linux-MinSizeRel.zip) unpackaged (for now),
|
||||
requires gtkmm3. built on Ubuntu 18.04 + gcc9
|
||||
|
||||
> **Warning**: If you use Windows, make sure to start from the `bin` directory
|
||||
|
||||
On Linux, `css` and `res` can also be loaded from `~/.local/share/abaddon` or `/usr/share/abaddon`
|
||||
|
||||
`abaddon.ini` will also be automatically used if located at `~/.config/abaddon/abaddon.ini` and there is
|
||||
no `abaddon.ini` in the working directory
|
||||
|
||||
#### The Spam Filter
|
||||
|
||||
Discord likes disabling accounts/forcing them to reset their passwords if they think the user is a spam bot or
|
||||
potentially had their account compromised. While the official client still often gets users caught in the spam filter,
|
||||
third party clients tend to upset the spam filter more often. If you get caught by it, you can
|
||||
usually [appeal](https://support.discord.com/hc/en-us/requests/new?ticket_form_id=360000029731) it and get it restored.
|
||||
Here are some things you might want to do with the official client instead if you are particularly afraid of evoking the
|
||||
spam filter's wrath:
|
||||
|
||||
* Joining or leaving servers (usually main cause of getting caught)
|
||||
* Frequently disconnecting and reconnecting
|
||||
* Starting new DMs with people
|
||||
* Managing your friends list
|
||||
* Managing your user profile while connected to a third party client
|
||||
|
||||
#### Dependencies:
|
||||
|
||||
#### Dependencies:
|
||||
* [gtkmm](https://www.gtkmm.org/en/)
|
||||
* [JSON for Modern C++](https://github.com/nlohmann/json)
|
||||
* [IXWebSocket](https://github.com/machinezone/IXWebSocket)
|
||||
* [libcurl](https://curl.se/)
|
||||
* [zlib](https://zlib.net/)
|
||||
* [simpleini](https://github.com/brofield/simpleini)
|
||||
* [SQLite3](https://www.sqlite.org/index.html)
|
||||
* [libhandy](https://gnome.pages.gitlab.gnome.org/libhandy/) (optional)
|
||||
|
||||
### TODO:
|
||||
|
||||
* Voice support
|
||||
* Unread indicators
|
||||
* User activities
|
||||
* Nicknames
|
||||
* More server management stuff
|
||||
* Manage friends
|
||||
* A bunch of other stuff
|
||||
|
||||
### Styling
|
||||
#### CSS selectors
|
||||
.app-window - Applied to all windows. This means the main window and all popups
|
||||
.app-popup - Additional class for `.app-window`s when the window is not the main window
|
||||
|
||||
.channel-list - Container of the channel list
|
||||
.channel-row - All rows within the channel container
|
||||
.channel-row-channel - Only rows containing a channel
|
||||
.channel-row-category - Only rows containing a category
|
||||
.channel-row-guild - Only rows containing a guild
|
||||
.channel-row-label - All labels within the channel container
|
||||
.nsfw - Applied to channel row labels and their container for NSFW channels
|
||||
|
||||
.messages - Container of user messages
|
||||
.message-container - The container which holds a user's messages
|
||||
.message-container-author - The author label for a message container
|
||||
.message-container-timestamp - The timestamp label for a message container
|
||||
.message-container-avatar - Avatar for a user in a message
|
||||
.message-container-extra - Label containing BOT/Webhook
|
||||
.message-text - The text of a user message
|
||||
.pending - Extra class of .message-text for messages pending to be sent
|
||||
.failed - Extra class of .message-text for messages that failed to be sent
|
||||
.message-attachment-box - Contains attachment info
|
||||
.message-reply - Container for the replied-to message in a reply (these elements will also have .message-text set)
|
||||
.message-input - Applied to the chat input container
|
||||
.replying - Extra class for chat input container when a reply is currently being created
|
||||
.reaction-box - Contains a reaction image and the count
|
||||
.reacted - Additional class for reaction-box when the user has reacted with a particular reaction
|
||||
.reaction-count - Contains the count for reaction
|
||||
|
||||
.completer - Container for the message completer
|
||||
.completer-entry - Container for a single entry in the completer
|
||||
.completer-entry-label - Contains the label for an entry in the completer
|
||||
.completer-entry-image - Contains the image for an entry in the completer
|
||||
|
||||
.embed - Container for a message embed
|
||||
.embed-author - The author of an embed
|
||||
.embed-title - The title of an embed
|
||||
.embed-description - The description of an embed
|
||||
.embed-field-title - The title of an embed field
|
||||
.embed-field-value - The value of an embed field
|
||||
.embed-footer - The footer of an embed
|
||||
|
||||
.members - Container of the member list
|
||||
.members-row - All rows within the members container
|
||||
.members-row-label - All labels in the members container
|
||||
.members-row-member - Rows containing a member
|
||||
.members-row-role - Rows containing a role
|
||||
.members-row-avatar - Contains the avatar for a row in the member list
|
||||
|
||||
.status-indicator - The status indicator
|
||||
.online - Applied to status indicators when the associated user is online
|
||||
.idle - Applied to status indicators when the associated user is away
|
||||
.dnd - Applied to status indicators when the associated user is on do not disturb
|
||||
.offline - Applied to status indicators when the associated user is offline
|
||||
|
||||
.typing-indicator - The typing indicator (also used for replies)
|
||||
|
||||
Used in reorderable list implementation:
|
||||
.drag-icon
|
||||
.drag-hover-top
|
||||
.drag-hover-bottom
|
||||
|
||||
Used in guild settings popup:
|
||||
.guild-settings-window
|
||||
.guild-members-pane-list - Container for list of members in the members pane
|
||||
.guild-members-pane-info - Container for member info
|
||||
.guild-roles-pane-list - Container for list of roles in the roles pane
|
||||
|
||||
Used in profile popup:
|
||||
.mutual-friend-item - Applied to every item in the mutual friends list
|
||||
.mutual-friend-item-name - Name in mutual friend item
|
||||
.mutual-friend-item-avatar - Avatar in mutual friend item
|
||||
.mutual-guild-item - Applied to every item in the mutual guilds list
|
||||
.mutual-guild-item-name - Name in mutual guild item
|
||||
.mutual-guild-item-icon - Icon in mutual guild item
|
||||
.mutual-guild-item-nick - User nickname in mutual guild item
|
||||
.profile-connection - Applied to every item in the user connections list
|
||||
.profile-connection-label - Label in profile connection item
|
||||
.profile-connection-check - Checkmark in verified profile connection items
|
||||
.profile-connections - Container for profile connections
|
||||
.profile-notes - Container for notes in profile window
|
||||
.profile-notes-label - Label that says "NOTE"
|
||||
.profile-notes-text - Actual note text
|
||||
.profile-info-pane - Applied to container for info section of profile popup
|
||||
.profile-info-created - Label for creation date of profile
|
||||
.user-profile-window
|
||||
.profile-main-container - Inner container for profile
|
||||
.profile-avatar
|
||||
.profile-username
|
||||
.profile-switcher - Buttons used to switch viewed section of profile
|
||||
.profile-stack - Container for profile info that can be switched between
|
||||
.profile-badges - Container for badges
|
||||
.profile-badge
|
||||
|
||||
#### CSS selectors
|
||||
|
||||
| Selector | Description |
|
||||
|--------------------------------|---------------------------------------------------------------------------------------------------|
|
||||
| `.app-window` | Applied to all windows. This means the main window and all popups |
|
||||
| `.app-popup` | Additional class for `.app-window`s when the window is not the main window |
|
||||
| `.channel-list` | Container of the channel list |
|
||||
| `.messages` | Container of user messages |
|
||||
| `.message-container` | The container which holds a user's messages |
|
||||
| `.message-container-author` | The author label for a message container |
|
||||
| `.message-container-timestamp` | The timestamp label for a message container |
|
||||
| `.message-container-avatar` | Avatar for a user in a message |
|
||||
| `.message-container-extra` | Label containing BOT/Webhook |
|
||||
| `.message-text` | The text of a user message |
|
||||
| `.pending` | Extra class of .message-text for messages pending to be sent |
|
||||
| `.failed` | Extra class of .message-text for messages that failed to be sent |
|
||||
| `.message-attachment-box` | Contains attachment info |
|
||||
| `.message-reply` | Container for the replied-to message in a reply (these elements will also have .message-text set) |
|
||||
| `.message-input` | Applied to the chat input container |
|
||||
| `.replying` | Extra class for chat input container when a reply is currently being created |
|
||||
| `.reaction-box` | Contains a reaction image and the count |
|
||||
| `.reacted` | Additional class for reaction-box when the user has reacted with a particular reaction |
|
||||
| `.reaction-count` | Contains the count for reaction |
|
||||
| `.completer` | Container for the message completer |
|
||||
| `.completer-entry` | Container for a single entry in the completer |
|
||||
| `.completer-entry-label` | Contains the label for an entry in the completer |
|
||||
| `.completer-entry-image` | Contains the image for an entry in the completer |
|
||||
| `.embed` | Container for a message embed |
|
||||
| `.embed-author` | The author of an embed |
|
||||
| `.embed-title` | The title of an embed |
|
||||
| `.embed-description` | The description of an embed |
|
||||
| `.embed-field-title` | The title of an embed field |
|
||||
| `.embed-field-value` | The value of an embed field |
|
||||
| `.embed-footer` | The footer of an embed |
|
||||
| `.members` | Container of the member list |
|
||||
| `.members-row` | All rows within the members container |
|
||||
| `.members-row-label` | All labels in the members container |
|
||||
| `.members-row-member` | Rows containing a member |
|
||||
| `.members-row-role` | Rows containing a role |
|
||||
| `.members-row-avatar` | Contains the avatar for a row in the member list |
|
||||
| `.status-indicator` | The status indicator |
|
||||
| `.online` | Applied to status indicators when the associated user is online |
|
||||
| `.idle` | Applied to status indicators when the associated user is away |
|
||||
| `.dnd` | Applied to status indicators when the associated user is on do not disturb |
|
||||
| `.offline` | Applied to status indicators when the associated user is offline |
|
||||
| `.typing-indicator` | The typing indicator (also used for replies) |
|
||||
|
||||
Used in reorderable list implementation:
|
||||
| Selector |
|
||||
|----------------------|
|
||||
| `.drag-icon` |
|
||||
| `.drag-hover-top` |
|
||||
| `.drag-hover-bottom` |
|
||||
|
||||
Used in guild settings popup:
|
||||
|
||||
| Selector | Description |
|
||||
|----------------------------|---------------------------------------------------|
|
||||
| `.guild-settings-window` | Container for list of members in the members pane |
|
||||
| `.guild-members-pane-list` | |
|
||||
| `.guild-members-pane-info` | Container for member info |
|
||||
| `.guild-roles-pane-list` | Container for list of roles in the roles pane |
|
||||
|
||||
Used in profile popup:
|
||||
|
||||
| Selector | Description |
|
||||
|------------------------------|---------------------------------------------------------|
|
||||
| `.mutual-friend-item` | Applied to every item in the mutual friends list |
|
||||
| `.mutual-friend-item-name` | Name in mutual friend item |
|
||||
| `.mutual-friend-item-avatar` | Avatar in mutual friend item |
|
||||
| `.mutual-guild-item` | Applied to every item in the mutual guilds list |
|
||||
| `.mutual-guild-item-name` | Name in mutual guild item |
|
||||
| `.mutual-guild-item-icon` | Icon in mutual guild item |
|
||||
| `.mutual-guild-item-nick` | User nickname in mutual guild item |
|
||||
| `.profile-connection` | Applied to every item in the user connections list |
|
||||
| `.profile-connection-label` | Label in profile connection item |
|
||||
| `.profile-connection-check` | Checkmark in verified profile connection items |
|
||||
| `.profile-connections` | Container for profile connections |
|
||||
| `.profile-notes` | Container for notes in profile window |
|
||||
| `.profile-notes-label` | Label that says "NOTE" |
|
||||
| `.profile-notes-text` | Actual note text |
|
||||
| `.profile-info-pane` | Applied to container for info section of profile popup |
|
||||
| `.profile-info-created` | Label for creation date of profile |
|
||||
| `.user-profile-window` | |
|
||||
| `.profile-main-container` | Inner container for profile |
|
||||
| `.profile-avatar` | |
|
||||
| `.profile-username` | |
|
||||
| `.profile-switcher` | Buttons used to switch viewed section of profile |
|
||||
| `.profile-stack` | Container for profile info that can be switched between |
|
||||
| `.profile-badges` | Container for badges |
|
||||
| `.profile-badge` | |
|
||||
|
||||
### Settings
|
||||
Settings are configured (for now) by editing abaddon.ini
|
||||
You should edit these while the client is closed even though there's an option to reload while running
|
||||
This listing is organized by section.
|
||||
|
||||
Settings are configured (for now) by editing `abaddon.ini`.
|
||||
The format is similar to the standard Windows ini format **except**:
|
||||
|
||||
* `#` is used to begin comments as opposed to `;`
|
||||
* Section and key names are case-sensitive
|
||||
|
||||
> **Warning**: You should edit these while the client is closed, even though there's an option to reload while running.
|
||||
|
||||
This listing is organized by section.
|
||||
For example, memory_db would be set by adding `memory_db = true` under the line `[discord]`
|
||||
|
||||
#### discord
|
||||
* memory_db (true or false, default false) - if true, Discord data will be kept in memory as opposed to on disk
|
||||
* token (string) - Discord token used to login, this can be set from the menu
|
||||
* prefetch (true or false, default false) - if true, new messages will cause the avatar and image attachments to be automatically downloaded
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
|---------------|---------|---------|--------------------------------------------------------------------------------------------------|
|
||||
| `gateway` | string | | override url for Discord gateway. must be json format and use zlib stream compression |
|
||||
| `api_base` | string | | override base url for Discord API |
|
||||
| `memory_db` | boolean | false | if true, Discord data will be kept in memory as opposed to on disk |
|
||||
| `token` | string | | Discord token used to login, this can be set from the menu |
|
||||
| `prefetch` | boolean | false | if true, new messages will cause the avatar and image attachments to be automatically downloaded |
|
||||
| `autoconnect` | boolean | false | autoconnect to discord |
|
||||
|
||||
#### http
|
||||
* user_agent (string) - sets the user-agent to use in HTTP requests to the Discord API (not including media/images)
|
||||
* concurrent (int, default 10) - how many images can be concurrently retrieved
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
|--------------|--------|---------|---------------------------------------------------------------------------------------------|
|
||||
| `user_agent` | string | | sets the user-agent to use in HTTP requests to the Discord API (not including media/images) |
|
||||
| `concurrent` | int | 20 | how many images can be concurrently retrieved |
|
||||
|
||||
#### gui
|
||||
* member_list_discriminator (true or false, default true) - show user discriminators in the member list
|
||||
* emojis (true or false, default true) - resolve unicode and custom emojis to images. this needs to be false to allow GTK to render emojis by itself
|
||||
* css (string) - path to the main CSS file
|
||||
* animations (true or false, default true) - use animated images where available (e.g. server icons, emojis, avatars). false means static images will be used
|
||||
* owner_crown (true or false, default true) - show a crown next to the owner
|
||||
|
||||
#### misc
|
||||
* linkcolor (string) - color to use for links in messages
|
||||
| Setting | Type | Default | Description |
|
||||
|-----------------------------|---------|---------|----------------------------------------------------------------------------------------------------------------------------|
|
||||
| `member_list_discriminator` | boolean | true | show user discriminators in the member list |
|
||||
| `stock_emojis` | boolean | true | allow abaddon to substitute unicode emojis with images from emojis.bin, must be false to allow GTK to render emojis itself |
|
||||
| `custom_emojis` | boolean | true | download and use custom Discord emojis |
|
||||
| `css` | string | | path to the main CSS file |
|
||||
| `animations` | boolean | true | use animated images where available (e.g. server icons, emojis, avatars). false means static images will be used |
|
||||
| `animated_guild_hover_only` | boolean | true | only animate guild icons when the guild is being hovered over |
|
||||
| `owner_crown` | boolean | true | show a crown next to the owner |
|
||||
| `unreads` | boolean | true | show unread indicators and mention badges |
|
||||
| `save_state` | boolean | true | save the state of the gui (active channels, tabs, expanded channels) |
|
||||
| `alt_menu` | boolean | false | keep the menu hidden unless revealed with alt key |
|
||||
| `hide_to_tray` | boolean | false | hide abaddon to the system tray on window close |
|
||||
|
||||
#### style
|
||||
|
||||
| Setting | Type | Description |
|
||||
|-------------------------|--------|-----------------------------------------------------|
|
||||
| `linkcolor` | string | color to use for links in messages |
|
||||
| `expandercolor` | string | color to use for the expander in the channel list |
|
||||
| `nsfwchannelcolor` | string | color to use for NSFW channels in the channel list |
|
||||
| `channelcolor` | string | color to use for SFW channels in the channel list |
|
||||
| `mentionbadgecolor` | string | background color for mention badges |
|
||||
| `mentionbadgetextcolor` | string | color to use for number displayed on mention badges |
|
||||
| `unreadcolor` | string | color to use for the unread indicator |
|
||||
|
||||
### Environment variables
|
||||
|
||||
| variable | Description |
|
||||
|------------------|------------------------------------------------------------------------------|
|
||||
| `ABADDON_NO_FC` | (Windows only) don't use custom font config |
|
||||
| `ABADDON_CONFIG` | change path of configuration file to use. relative to cwd or can be absolute |
|
||||
|
59
ci/msys-deps.txt
Normal file
@ -0,0 +1,59 @@
|
||||
/bin/gdbus.exe
|
||||
/bin/gspawn-win64-helper-console.exe
|
||||
/bin/libatk-1.0-0.dll
|
||||
/bin/libatkmm-1.6-1.dll
|
||||
/bin/libbrotlicommon.dll
|
||||
/bin/libbrotlidec.dll
|
||||
/bin/libbz2-1.dll
|
||||
/bin/libcairo-2.dll
|
||||
/bin/libcairo-gobject-2.dll
|
||||
/bin/libcairomm-1.0-1.dll
|
||||
/bin/libcrypto-1_1-x64.dll
|
||||
/bin/libcurl-4.dll
|
||||
/bin/libdatrie-1.dll
|
||||
/bin/libdeflate.dll
|
||||
/bin/libepoxy-0.dll
|
||||
/bin/libexpat-1.dll
|
||||
/bin/libffi-8.dll
|
||||
/bin/libfontconfig-1.dll
|
||||
/bin/libfreetype-6.dll
|
||||
/bin/libfribidi-0.dll
|
||||
/bin/libgcc_s_seh-1.dll
|
||||
/bin/libgdk-3-0.dll
|
||||
/bin/libgdk_pixbuf-2.0-0.dll
|
||||
/bin/libgdkmm-3.0-1.dll
|
||||
/bin/libgio-2.0-0.dll
|
||||
/bin/libgiomm-2.4-1.dll
|
||||
/bin/libglib-2.0-0.dll
|
||||
/bin/libglibmm-2.4-1.dll
|
||||
/bin/libgmodule-2.0-0.dll
|
||||
/bin/libgobject-2.0-0.dll
|
||||
/bin/libgraphite2.dll
|
||||
/bin/libgtk-3-0.dll
|
||||
/bin/libgtkmm-3.0-1.dll
|
||||
/bin/libhandy-1-0.dll
|
||||
/bin/libharfbuzz-0.dll
|
||||
/bin/libiconv-2.dll
|
||||
/bin/libidn2-0.dll
|
||||
/bin/libintl-8.dll
|
||||
/bin/libnghttp2-14.dll
|
||||
/bin/libpango-1.0-0.dll
|
||||
/bin/libpangocairo-1.0-0.dll
|
||||
/bin/libpangoft2-1.0-0.dll
|
||||
/bin/libpangomm-1.4-1.dll
|
||||
/bin/libpangowin32-1.0-0.dll
|
||||
/bin/libpcre2-8-0.dll
|
||||
/bin/libpixman-1-0.dll
|
||||
/bin/libpng16-16.dll
|
||||
/bin/libpsl-5.dll
|
||||
/bin/libsigc-2.0-0.dll
|
||||
/bin/libsqlite3-0.dll
|
||||
/bin/libssh2-1.dll
|
||||
/bin/libssl-1_1-x64.dll
|
||||
/bin/libstdc++-6.dll
|
||||
/bin/libthai-0.dll
|
||||
/bin/libunistring-2.dll
|
||||
/bin/libwinpthread-1.dll
|
||||
/bin/libzstd.dll
|
||||
/bin/zlib1.dll
|
||||
/../usr/bin/msys-2.0.dll
|
1
ci/used-icons.txt
Normal file
@ -0,0 +1 @@
|
||||
document-send-symbolic
|
1
ci/vcpkg
@ -1 +0,0 @@
|
||||
Subproject commit 50ea8c0ab7aca3bb9245bba7fc877ad2f2a4464c
|
@ -31,7 +31,6 @@ set(HARFBUZZ_INCLUDE_DIRS ${HARFBUZZ_INCLUDE_DIR};${HARFBUZZ_CONFIG_INCLUDE_DIRS
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(HarfBuzz
|
||||
FOUND_VAR HARFBUZZ_FOUND
|
||||
REQUIRED_VARS
|
||||
HARFBUZZ_LIBRARY
|
||||
HARFBUZZ_INCLUDE_DIR
|
||||
|
30
cmake/FindIXWebSocket.cmake
Normal file
@ -0,0 +1,30 @@
|
||||
set(IXWebSocket_LIBRARY_NAME ixwebsocket)
|
||||
|
||||
find_path(IXWebSocket_INCLUDE_DIR
|
||||
NAMES ixwebsocket/IXWebSocket.h
|
||||
HINTS /usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
PATH_SUFFIXES ${IXWebSocket_LIBRARY_NAME})
|
||||
|
||||
|
||||
find_library(IXWebSocket_LIBRARY
|
||||
NAMES ${IXWebSocket_LIBRARY_NAME}
|
||||
PATH_SUFFIXES ${IXWebSocket_LIBRARY_NAME}
|
||||
${IXWebSocket_LIBRARY_NAME}/include)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_package_handle_standard_args(IXWebSocket
|
||||
REQUIRED_VARS
|
||||
IXWebSocket_LIBRARY
|
||||
IXWebSocket_INCLUDE_DIR)
|
||||
|
||||
|
||||
mark_as_advanced(IXWebSocket_LIBRARY IXWebSocket_INCLUDE_DIR)
|
||||
|
||||
if (IXWebSocket_FOUND)
|
||||
find_package(OpenSSL QUIET)
|
||||
set(IXWebSocket_INCLUDE_DIRS "${IXWebSocket_INCLUDE_DIR};${OPENSSL_INCLUDE_DIR}")
|
||||
set(IXWebSocket_LIBRARIES "${IXWebSocket_LIBRARY};${OPENSSL_LIBRARIES}")
|
||||
endif()
|
@ -31,7 +31,6 @@ set(ATK_INCLUDE_DIRS ${ATK_INCLUDE_DIR};${ATK_CONFIG_INCLUDE_DIRS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(atk
|
||||
FOUND_VAR ATK_FOUND
|
||||
REQUIRED_VARS
|
||||
ATK_LIBRARY
|
||||
ATK_INCLUDE_DIR
|
||||
|
@ -42,7 +42,6 @@ set(ATKMM_INCLUDE_DIRS ${ATKMM_INCLUDE_DIR};${ATKMM_CONFIG_INCLUDE_DIR};${ATK_IN
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(atkmm
|
||||
FOUND_VAR ATKMM_FOUND
|
||||
REQUIRED_VARS
|
||||
ATKMM_LIBRARY
|
||||
ATKMM_INCLUDE_DIRS
|
||||
|
@ -31,7 +31,6 @@ set(CAIRO_INCLUDE_DIRS ${CAIRO_INCLUDE_DIR};${CAIRO_CONFIG_INCLUDE_DIRS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(cairo
|
||||
FOUND_VAR CAIRO_FOUND
|
||||
REQUIRED_VARS
|
||||
CAIRO_LIBRARY
|
||||
CAIRO_INCLUDE_DIR
|
||||
|
@ -45,7 +45,6 @@ set(CAIROMM_INCLUDE_DIRS ${CAIROMM_INCLUDE_DIR};${CAIROMM_CONFIG_INCLUDE_DIRS};$
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(cairomm
|
||||
FOUND_VAR CAIROMM_FOUND
|
||||
REQUIRED_VARS
|
||||
CAIROMM_LIBRARY
|
||||
CAIROMM_INCLUDE_DIR
|
||||
|
37
cmake/Findgdk.cmake
Normal file
@ -0,0 +1,37 @@
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(PC_gdk QUIET gdk-3.0)
|
||||
set(gdk_DEFINITIONS ${PC_gdk_CFLAGS_OTHER})
|
||||
endif ()
|
||||
|
||||
set(gdk_INCLUDE_HINTS ${PC_gdk_INCLUDEDIR} ${PC_gdk_INCLUDE_DIRS})
|
||||
set(gdk_LIBRARY_HINTS ${PC_gdk_LIBDIR} ${PC_gdk_LIBRARY_DIRS})
|
||||
|
||||
find_path(gdk_INCLUDE_DIR
|
||||
NAMES gdk/gdk.h
|
||||
HINTS ${gdk_INCLUDE_HINTS}
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
PATH_SUFFIXES gdk-3.0)
|
||||
|
||||
find_library(gdk_LIBRARY
|
||||
NAMES gdk-3.0
|
||||
gdk-3
|
||||
gdk
|
||||
HINTS ${gdk_LIBRARY_HINTS}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib)
|
||||
|
||||
set(gdk_LIBRARIES ${gdk_LIBRARY})
|
||||
set(gdk_INCLUDE_DIRS ${gdk_INCLUDE_DIR})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(gdk
|
||||
REQUIRED_VARS
|
||||
gdk_LIBRARY
|
||||
gdk_INCLUDE_DIR
|
||||
VERSION_VAR gdk_VERSION)
|
||||
|
||||
mark_as_advanced(gdk_INCLUDE_DIR gdk_LIBRARY)
|
@ -1,49 +1,50 @@
|
||||
set(GDKMM_LIBRARY_NAME gdkmm-3.0)
|
||||
set(gdkmm_LIBRARY_NAME gdkmm-3.0)
|
||||
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(PKGCONFIG_GDKMM QUIET ${GDKMM_LIBRARY_NAME})
|
||||
set(GDKMM_DEFINITIONS ${PKGCONFIG_GDKMM_CFLAGS_OTHER})
|
||||
pkg_check_modules(PKGCONFIG_gdkmm QUIET ${gdkmm_LIBRARY_NAME})
|
||||
set(gdkmm_DEFINITIONS ${PKGCONFIG_gdkmm_CFLAGS_OTHER})
|
||||
endif (PKG_CONFIG_FOUND)
|
||||
|
||||
set(GDKMM_INCLUDE_HINTS ${PKGCONFIG_GDKMM_INCLUDEDIR} ${PKGCONFIG_GDKMM_INCLUDE_DIRS})
|
||||
set(GDKMM_LIBRARY_HINTS ${PKGCONFIG_GDKMM_LIBDIR} ${PKGCONFIG_GDKMM_LIBRARY_DIRS})
|
||||
set(gdkmm_INCLUDE_HINTS ${PKGCONFIG_gdkmm_INCLUDEDIR} ${PKGCONFIG_gdkmm_INCLUDE_DIRS})
|
||||
set(gdkmm_LIBRARY_HINTS ${PKGCONFIG_gdkmm_LIBDIR} ${PKGCONFIG_gdkmm_LIBRARY_DIRS})
|
||||
|
||||
find_path(GDKMM_INCLUDE_DIR
|
||||
find_path(gdkmm_INCLUDE_DIR
|
||||
NAMES gdkmm.h
|
||||
HINTS ${GDKMM_INCLUDE_HINTS}
|
||||
HINTS ${gdkmm_INCLUDE_HINTS}
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
PATH_SUFFIXES ${GDKMM_LIBRARY_NAME})
|
||||
PATH_SUFFIXES ${gdkmm_LIBRARY_NAME})
|
||||
|
||||
find_path(GDKMM_CONFIG_INCLUDE_DIR
|
||||
find_path(gdkmm_CONFIG_INCLUDE_DIR
|
||||
NAMES gdkmmconfig.h
|
||||
HINTS ${GDKMM_LIBRARY_HINTS}
|
||||
HINTS ${gdkmm_LIBRARY_HINTS}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
PATH_SUFFIXES ${GDKMM_LIBRARY_NAME}/include)
|
||||
PATH_SUFFIXES ${gdkmm_LIBRARY_NAME}/include)
|
||||
|
||||
find_library(GDKMM_LIBRARY
|
||||
NAMES ${GDKMM_LIBRARY_NAME}
|
||||
gdkmm
|
||||
HINTS ${GDKMM_LIBRARY_HINTS}
|
||||
find_library(gdkmm_LIBRARY
|
||||
NAMES ${gdkmm_LIBRARY_NAME}
|
||||
gdkmm
|
||||
HINTS ${gdkmm_LIBRARY_HINTS}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
PATH_SUFFIXES ${GDKMM_LIBRARY_NAME}
|
||||
${GDKMM_LIBRARY_NAME}/include)
|
||||
PATH_SUFFIXES ${gdkmm_LIBRARY_NAME}
|
||||
${gdkmm_LIBRARY_NAME}/include)
|
||||
|
||||
set(GDKMM_LIBRARIES ${GDKMM_LIBRARY})
|
||||
set(GDKMM_INCLUDE_DIRS ${GDKMM_INCLUDE_DIR};${GDKMM_CONFIG_INCLUDE_DIRS};${GDKMM_CONFIG_INCLUDE_DIR})
|
||||
find_package(gdk)
|
||||
|
||||
set(gdkmm_LIBRARIES ${gdkmm_LIBRARY};${gdk_LIBRARIES})
|
||||
set(gdkmm_INCLUDE_DIRS ${gdkmm_INCLUDE_DIR};${gdkmm_CONFIG_INCLUDE_DIRS};${gdkmm_CONFIG_INCLUDE_DIR};${gdk_INCLUDE_DIRS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(gdkmm
|
||||
FOUND_VAR GDKMM_FOUND
|
||||
REQUIRED_VARS
|
||||
GDKMM_LIBRARY
|
||||
GDKMM_INCLUDE_DIRS
|
||||
VERSION_VAR GDKMM_VERSION)
|
||||
gdkmm_LIBRARY
|
||||
gdkmm_INCLUDE_DIRS
|
||||
VERSION_VAR gdkmm_VERSION)
|
||||
|
||||
mark_as_advanced(GDKMM_INCLUDE_DIR GDKMM_LIBRARY)
|
||||
mark_as_advanced(gdkmm_INCLUDE_DIR gdkmm_LIBRARY)
|
||||
|
@ -33,7 +33,6 @@ set(GDKPIXBUF_INCLUDE_DIRS ${GDKPIXBUF_INCLUDE_DIR};${GDKPIXBUF_CONFIG_INCLUDE_D
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(gdkpixbuf
|
||||
FOUND_VAR GDKPIXBUF_FOUND
|
||||
REQUIRED_VARS
|
||||
GDKPIXBUF_LIBRARY
|
||||
GDKPIXBUF_INCLUDE_DIR
|
||||
|
@ -2,57 +2,70 @@ find_package(PkgConfig)
|
||||
pkg_check_modules(PC_GLIB2 QUIET glib-2.0)
|
||||
|
||||
find_path(GLIB_INCLUDE_DIR
|
||||
NAMES glib.h
|
||||
HINTS ${PC_GLIB2_INCLUDEDIR}
|
||||
${PC_GLIB2_INCLUDE_DIRS}
|
||||
$ENV{GLIB2_HOME}/include
|
||||
$ENV{GLIB2_ROOT}/include
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
/glib2/include
|
||||
/glib-2.0/include
|
||||
PATH_SUFFIXES glib2 glib-2.0 glib-2.0/include
|
||||
)
|
||||
NAMES glib.h
|
||||
HINTS ${PC_GLIB2_INCLUDEDIR}
|
||||
${PC_GLIB2_INCLUDE_DIRS}
|
||||
$ENV{GLIB2_HOME}/include
|
||||
$ENV{GLIB2_ROOT}/include
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
/glib2/include
|
||||
/glib-2.0/include
|
||||
PATH_SUFFIXES glib2 glib-2.0 glib-2.0/include
|
||||
)
|
||||
set(GLIB_INCLUDE_DIRS ${GLIB_INCLUDE_DIR})
|
||||
|
||||
find_library(GLIB_LIBRARIES
|
||||
NAMES glib2
|
||||
glib-2.0
|
||||
HINTS ${PC_GLIB2_LIBDIR}
|
||||
${PC_GLIB2_LIBRARY_DIRS}
|
||||
$ENV{GLIB2_HOME}/lib
|
||||
$ENV{GLIB2_ROOT}/lib
|
||||
/usr/local/lib
|
||||
/usr/lib
|
||||
/lib
|
||||
/glib-2.0/lib
|
||||
PATH_SUFFIXES glib2 glib-2.0
|
||||
)
|
||||
NAMES glib2
|
||||
glib-2.0
|
||||
HINTS ${PC_GLIB2_LIBDIR}
|
||||
${PC_GLIB2_LIBRARY_DIRS}
|
||||
$ENV{GLIB2_HOME}/lib
|
||||
$ENV{GLIB2_ROOT}/lib
|
||||
/usr/local/lib
|
||||
/usr/lib
|
||||
/lib
|
||||
/glib-2.0/lib
|
||||
PATH_SUFFIXES glib2 glib-2.0
|
||||
)
|
||||
|
||||
find_library(glib_GOBJECT_LIBRARIES
|
||||
NAMES gobject-2.0
|
||||
HINTS ${PC_GLIB2_LIBDIR}
|
||||
${PC_GLIB2_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
find_library(glib_GIO_LIBRARIES
|
||||
NAMES gio-2.0
|
||||
HINTS ${PC_GLIB2_LIBDIR}
|
||||
${PC_GLIB2_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
get_filename_component(_GLIB2_LIB_DIR "${GLIB_LIBRARIES}" PATH)
|
||||
find_path(GLIB_CONFIG_INCLUDE_DIR
|
||||
NAMES glibconfig.h
|
||||
HINTS ${PC_GLIB2_INCLUDEDIR}
|
||||
${PC_GLIB2_INCLUDE_DIRS}
|
||||
$ENV{GLIB2_HOME}/include
|
||||
$ENV{GLIB2_ROOT}/include
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
/glib2/include
|
||||
/glib-2.0/include
|
||||
${_GLIB2_LIB_DIR}
|
||||
${CMAKE_SYSTEM_LIBRARY_PATH}
|
||||
PATH_SUFFIXES glib2 glib-2.0 glib-2.0/include
|
||||
)
|
||||
NAMES glibconfig.h
|
||||
HINTS ${PC_GLIB2_INCLUDEDIR}
|
||||
${PC_GLIB2_INCLUDE_DIRS}
|
||||
$ENV{GLIB2_HOME}/include
|
||||
$ENV{GLIB2_ROOT}/include
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
/glib2/include
|
||||
/glib-2.0/include
|
||||
${_GLIB2_LIB_DIR}
|
||||
${CMAKE_SYSTEM_LIBRARY_PATH}
|
||||
PATH_SUFFIXES glib2 glib-2.0 glib-2.0/include
|
||||
)
|
||||
if (GLIB_CONFIG_INCLUDE_DIR)
|
||||
set(GLIB_INCLUDE_DIRS ${GLIB_INCLUDE_DIRS} ${GLIB_CONFIG_INCLUDE_DIR})
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
set(GLIB_LIBRARIES ${GLIB_LIBRARIES} ${glib_GOBJECT_LIBRARIES} ${glib_GIO_LIBRARIES})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(glib
|
||||
FOUND_VAR GLIB_FOUND
|
||||
REQUIRED_VARS
|
||||
GLIB_LIBRARIES
|
||||
GLIB_INCLUDE_DIRS
|
||||
VERSION_VAR GLIB_VERSION)
|
||||
mark_as_advanced(GLIB_INCLUDE_DIR GLIB_CONFIG_INCLUDE_DIR)
|
||||
REQUIRED_VARS
|
||||
GLIB_LIBRARIES
|
||||
GLIB_INCLUDE_DIRS
|
||||
VERSION_VAR GLIB_VERSION)
|
||||
mark_as_advanced(GLIB_INCLUDE_DIR GLIB_CONFIG_INCLUDE_DIR glib_GOBJECT_LIBRARIES)
|
||||
|
@ -60,7 +60,6 @@ set(GLIBMM_INCLUDE_DIRS ${GLIBMM_INCLUDE_DIR};${GLIBMM_CONFIG_INCLUDE_DIR};${GIO
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(glibmm
|
||||
FOUND_VAR GLIBMM_FOUND
|
||||
REQUIRED_VARS
|
||||
GLIBMM_LIBRARY
|
||||
GLIBMM_INCLUDE_DIR
|
||||
|
@ -47,7 +47,6 @@ set(GTK_INCLUDE_DIRS ${GTK_INCLUDE_DIR};${GDK_CONFIG_INCLUDE_DIR};${GDKPIXBUF_IN
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(gtk
|
||||
FOUND_VAR GTK_FOUND
|
||||
REQUIRED_VARS
|
||||
GTK_LIBRARY
|
||||
GTK_INCLUDE_DIR
|
||||
|
@ -1,13 +1,13 @@
|
||||
set(GTKMM_LIBRARY_NAME gtkmm-3.0)
|
||||
set(GDKMM_LIBRARY_NAME gdkmm-3.0)
|
||||
set(GTKMM_LIBRARY_NAME gtkmm-3.0)
|
||||
set(GDKMM_LIBRARY_NAME gdkmm-3.0)
|
||||
|
||||
find_package(PkgConfig)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(PC_GTKMM QUIET ${GTKMM_LIBRARY_NAME})
|
||||
pkg_check_modules(PC_GDKMM QUIET ${GDKMM_LIBRARY_NAME})
|
||||
pkg_check_modules(PC_PANGOMM QUIET ${PANGOMM_LIBRARY_NAME})
|
||||
set(GTKMM_DEFINITIONS ${PC_GTKMM_CFLAGS_OTHER})
|
||||
endif()
|
||||
set(GTKMM_DEFINITIONS ${PC_GTKMM_CFLAGS_OTHER})
|
||||
endif ()
|
||||
|
||||
find_package(gtk)
|
||||
find_package(glibmm)
|
||||
@ -46,15 +46,14 @@ find_path(GDKMM_CONFIG_INCLUDE_DIR
|
||||
HINTS ${GDKMM_INCLUDE_HINTS}
|
||||
PATH_SUFFIXES ${GDKMM_LIBRARY_NAME}/include)
|
||||
|
||||
set(GTKMM_LIBRARIES ${GTKMM_LIB};${GDKMM_LIBRARY};${GTK_LIBRARIES};${GLIBMM_LIBRARIES};${PANGOMM_LIBRARIES};${CAIROMM_LIBRARIES};${ATKMM_LIBRARIES};${SIGC++_LIBRARIES})
|
||||
set(GTKMM_INCLUDE_DIRS ${GTKMM_INCLUDE_DIR};${GTKMM_CONFIG_INCLUDE_DIR};${GDKMM_INCLUDE_DIR};${GDKMM_CONFIG_INCLUDE_DIR};${GTK_INCLUDE_DIRS};${GLIBMM_INCLUDE_DIRS};${PANGOMM_INCLUDE_DIRS};${CAIROMM_INCLUDE_DIRS};${ATKMM_INCLUDE_DIRS};${SIGC++_INCLUDE_DIRS})
|
||||
set(GTKMM_LIBRARIES ${GTKMM_LIB};${gdkmm_LIBRARIES};${GTK_LIBRARIES};${GLIBMM_LIBRARIES};${PANGOMM_LIBRARIES};${CAIROMM_LIBRARIES};${ATKMM_LIBRARIES};${SIGC++_LIBRARIES})
|
||||
set(GTKMM_INCLUDE_DIRS ${GTKMM_INCLUDE_DIR};${GTKMM_CONFIG_INCLUDE_DIR};${gdkmm_INCLUDE_DIRS};${gdkmm_CONFIG_INCLUDE_DIR};${GTK_INCLUDE_DIRS};${GLIBMM_INCLUDE_DIRS};${PANGOMM_INCLUDE_DIRS};${CAIROMM_INCLUDE_DIRS};${ATKMM_INCLUDE_DIRS};${SIGC++_INCLUDE_DIRS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(gtkmm
|
||||
FOUND_VAR GTKMM_FOUND
|
||||
REQUIRED_VARS
|
||||
GTKMM_LIB
|
||||
GTKMM_INCLUDE_DIRS
|
||||
GTKMM_LIB
|
||||
GTKMM_INCLUDE_DIRS
|
||||
VERSION_VAR GTKMM_VERSION)
|
||||
|
||||
mark_as_advanced(GTKMM_INCLUDE_DIR GTKMM_LIBRARY)
|
||||
|
@ -1,17 +0,0 @@
|
||||
find_path(IXWEBSOCKET_INCLUDE_DIR
|
||||
NAMES ixwebsocket/IXWebSocket.h)
|
||||
|
||||
find_library(IXWEBSOCKET_LIBRARY
|
||||
NAMES ixwebsocket
|
||||
HINTS ${IXWEBSOCKET_LIBRARY_ROOT})
|
||||
|
||||
set(IXWEBSOCKET_LIBRARIES ${IXWEBSOCKET_LIBRARY})
|
||||
set(IXWEBSOCKET_INCLUDE_DIRS ${IXWEBSOCKET_INCLUDE_DIR})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(ixwebsocket
|
||||
FOUND_VAR IXWEBSOCKET_FOUND
|
||||
REQUIRED_VARS
|
||||
IXWEBSOCKET_LIBRARY
|
||||
IXWEBSOCKET_INCLUDE_DIR
|
||||
VERSION_VAR IXWEBSOCKET_VERSION)
|
39
cmake/Findlibhandy.cmake
Normal file
@ -0,0 +1,39 @@
|
||||
set(libhandy_LIBRARY_NAME libhandy-1)
|
||||
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(PC_libhandy QUIET ${libhandy_LIBRARY_NAME})
|
||||
set(libhandy_DEfINITIONS ${PC_libhandy_CFLAGS_OTHER})
|
||||
endif (PKG_CONFIG_FOUND)
|
||||
|
||||
set(libhandy_INCLUDE_HINTS ${PC_libhandy_INCLUDEDIR} ${PC_libhandy_INCLUDE_DIRS})
|
||||
set(libhandy_LIBRARY_HINTS ${PC_libhandy_LIBDIR} ${PC_libhandy_LIBRARY_DIRS})
|
||||
|
||||
find_path(libhandy_INCLUDE_DIR
|
||||
NAMES handy.h
|
||||
HINTS ${libhandy_INCLUDE_HINTS}
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
PATH_SUFFIXES ${libhandy_LIBRARY_NAME})
|
||||
|
||||
find_library(libhandy_LIBRARY
|
||||
NAMES ${libhandy_LIBRARY_NAME} handy-1
|
||||
HINTS ${libhandy_LIBRARY_HINTS}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
PATH_SUFFIXES ${libhandy_LIBRARY_NAME}
|
||||
${libhandy_LIBRARY_NAME}/include)
|
||||
|
||||
set(libhandy_LIBRARIES ${libhandy_LIBRARY})
|
||||
set(libhandy_INCLUDE_DIRS ${libhandy_INCLUDE_DIR};${libhandy_CONFIG_INCLUDE_DIRS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(libhandy
|
||||
REQUIRED_VARS
|
||||
libhandy_LIBRARY
|
||||
libhandy_INCLUDE_DIR
|
||||
VERSION_VAR libhandy_VERSION)
|
||||
|
||||
mark_as_advanced(libhandy_INCLUDE_DIR libhandy_LIBRARY)
|
@ -22,7 +22,6 @@ set(NLOHMANN_JSON_LIBRARIES "")
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(nlohmann_json
|
||||
FOUND_VAR NLOHMANN_JSON_FOUND
|
||||
REQUIRED_VARS
|
||||
NLOHMANN_JSON_INCLUDE_DIR
|
||||
VERSION_VAR NLOHMANN_JSON_VERSION)
|
||||
|
@ -1,4 +1,6 @@
|
||||
set(PANGO_LIBRARY_NAME pango-1.0)
|
||||
set(PANGOCAIRO_LIBRARY_NAME pangocairo-1.0)
|
||||
set(PANGOFT2_LIBRARY_NAME pangoft2-1.0)
|
||||
|
||||
find_package(HarfBuzz)
|
||||
find_package(cairo)
|
||||
@ -42,12 +44,31 @@ find_library(PANGO_LIBRARY
|
||||
PATH_SUFFIXES ${PANGO_LIBRARY_NAME}
|
||||
${PANGO_LIBRARY_NAME}/include)
|
||||
|
||||
set(PANGO_LIBRARIES ${PANGO_LIBRARY};${HARFBUZZ_LIBRARIES};${CAIRO_LIBRARIES};${FREETYPE_LIBRARIES})
|
||||
find_library(PANGOCAIRO_LIBRARY
|
||||
NAMES ${PANGOCAIRO_LIBRARY_NAME}
|
||||
pangocairo
|
||||
HINTS ${PANGO_LIBRARY_HINTS}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
PATH_SUFFIXES ${PANGO_LIBRARY_NAME}
|
||||
${PANGO_LIBRARY_NAME}/include)
|
||||
|
||||
find_library(PANGOFT2_LIBRARY
|
||||
NAMES ${PANGOFT2_LIBRARY_NAME}
|
||||
pangoft2
|
||||
HINTS ${PANGO_LIBRARY_HINTS}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
PATH_SUFFIXES ${PANGO_LIBRARY_NAME}
|
||||
${PANGO_LIBRARY_NAME}/include)
|
||||
|
||||
set(PANGO_LIBRARIES ${PANGO_LIBRARY};${HARFBUZZ_LIBRARIES};${CAIRO_LIBRARIES};${FREETYPE_LIBRARIES};${PANGOCAIRO_LIBRARY};${PANGOFT2_LIBRARY})
|
||||
set(PANGO_INCLUDE_DIRS ${PANGO_INCLUDE_DIR};${PANGO_CONFIG_INCLUDE_DIRS};${HARFBUZZ_INCLUDE_DIR};${CAIRO_INCLUDE_DIRS};${FREETYPE_INCLUDE_DIRS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(pango
|
||||
FOUND_VAR PANGO_FOUND
|
||||
REQUIRED_VARS
|
||||
PANGO_LIBRARY
|
||||
PANGO_INCLUDE_DIR
|
||||
|
@ -56,7 +56,6 @@ set(PANGOMM_INCLUDE_DIRS ${PANGOMM_INCLUDE_DIR};${PANGOMM_CONFIG_INCLUDE_DIR};${
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(pangomm
|
||||
FOUND_VAR PANGOMM_FOUND
|
||||
REQUIRED_VARS
|
||||
PANGOMM_LIBRARY
|
||||
PANGOMM_INCLUDE_DIRS
|
||||
|
@ -32,7 +32,6 @@ set(SIGC++_INCLUDE_DIRS ${SIGC++_INCLUDE_DIR};${SIGC++_CONFIG_INCLUDE_DIR})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(sigc++
|
||||
FOUND_VAR SIGC++_FOUND
|
||||
REQUIRED_VARS
|
||||
SIGC++_INCLUDE_DIR
|
||||
SIGC++_LIBRARY
|
||||
|
@ -1,813 +0,0 @@
|
||||
#include "channels.hpp"
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include "../abaddon.hpp"
|
||||
#include "../imgmanager.hpp"
|
||||
#include "../util.hpp"
|
||||
#include "statusindicator.hpp"
|
||||
|
||||
void ChannelListRow::Collapse() {}
|
||||
|
||||
void ChannelListRow::Expand() {}
|
||||
|
||||
void ChannelListRow::MakeReadOnly(Gtk::TextView *tv) {
|
||||
tv->set_can_focus(false);
|
||||
tv->set_editable(false);
|
||||
tv->signal_realize().connect([tv]() {
|
||||
auto window = tv->get_window(Gtk::TEXT_WINDOW_TEXT);
|
||||
auto display = window->get_display();
|
||||
auto cursor = Gdk::Cursor::create(display, "default"); // textview uses "text" which looks out of place
|
||||
window->set_cursor(cursor);
|
||||
});
|
||||
// stupid hack to prevent selection
|
||||
auto buf = tv->get_buffer();
|
||||
buf->property_has_selection().signal_changed().connect([tv, buf]() {
|
||||
Gtk::TextBuffer::iterator a, b;
|
||||
buf->get_bounds(a, b);
|
||||
buf->select_range(a, a);
|
||||
});
|
||||
}
|
||||
|
||||
ChannelListRowDMHeader::ChannelListRowDMHeader() {
|
||||
m_ev = Gtk::manage(new Gtk::EventBox);
|
||||
m_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
|
||||
m_lbl = Gtk::manage(new Gtk::Label);
|
||||
|
||||
get_style_context()->add_class("channel-row");
|
||||
m_lbl->get_style_context()->add_class("channel-row-label");
|
||||
|
||||
m_lbl->set_use_markup(true);
|
||||
m_lbl->set_markup("<b>Direct Messages</b>");
|
||||
m_box->set_halign(Gtk::ALIGN_START);
|
||||
m_box->pack_start(*m_lbl);
|
||||
|
||||
m_ev->add(*m_box);
|
||||
add(*m_ev);
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
ChannelListRowDMChannel::ChannelListRowDMChannel(const ChannelData *data) {
|
||||
ID = data->ID;
|
||||
m_ev = Gtk::manage(new Gtk::EventBox);
|
||||
m_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
|
||||
|
||||
std::optional<UserData> top_recipient; // potentially nullopt in group dm
|
||||
const auto recipients = data->GetDMRecipients();
|
||||
if (recipients.size() > 0)
|
||||
top_recipient = recipients[0];
|
||||
|
||||
const static bool alt = Abaddon::Get().GetSettings().GetUseMobileLayout();
|
||||
if (alt) {
|
||||
auto *tmp = Gtk::manage(new Gtk::Label);
|
||||
m_lbl = tmp;
|
||||
if (data->Type == ChannelType::DM)
|
||||
tmp->set_text(top_recipient->Username);
|
||||
else if (data->Type == ChannelType::GROUP_DM)
|
||||
tmp->set_text(std::to_string(recipients.size()) + " users");
|
||||
} else {
|
||||
auto *tmp = Gtk::manage(new Gtk::TextView);
|
||||
m_lbl = tmp;
|
||||
MakeReadOnly(tmp);
|
||||
|
||||
auto buf = tmp->get_buffer();
|
||||
if (data->Type == ChannelType::DM)
|
||||
buf->set_text(top_recipient->Username);
|
||||
else if (data->Type == ChannelType::GROUP_DM)
|
||||
buf->set_text(std::to_string(recipients.size()) + " users");
|
||||
|
||||
static bool show_emojis = Abaddon::Get().GetSettings().GetShowEmojis();
|
||||
if (show_emojis)
|
||||
Abaddon::Get().GetEmojis().ReplaceEmojis(buf, ChannelEmojiSize);
|
||||
}
|
||||
|
||||
AddWidgetMenuHandler(m_ev, m_menu);
|
||||
AddWidgetMenuHandler(m_lbl, m_menu);
|
||||
|
||||
m_menu_copy_id = Gtk::manage(new Gtk::MenuItem("_Copy ID", true));
|
||||
m_menu_copy_id->signal_activate().connect([this] {
|
||||
Gtk::Clipboard::get()->set_text(std::to_string(ID));
|
||||
});
|
||||
|
||||
if (data->Type == ChannelType::GROUP_DM)
|
||||
m_menu_close = Gtk::manage(new Gtk::MenuItem("_Leave DM", true));
|
||||
else
|
||||
m_menu_close = Gtk::manage(new Gtk::MenuItem("_Close DM", true));
|
||||
m_menu_close->signal_activate().connect([this] {
|
||||
Abaddon::Get().GetDiscordClient().CloseDM(ID);
|
||||
});
|
||||
|
||||
m_menu.append(*m_menu_copy_id);
|
||||
m_menu.append(*m_menu_close);
|
||||
m_menu.show_all();
|
||||
|
||||
get_style_context()->add_class("channel-row");
|
||||
m_lbl->get_style_context()->add_class("channel-row-label");
|
||||
|
||||
if (data->Type == ChannelType::DM) {
|
||||
m_status = Gtk::manage(new StatusIndicator(top_recipient->ID));
|
||||
m_status->set_margin_start(5);
|
||||
|
||||
m_icon = Gtk::manage(new Gtk::Image(Abaddon::Get().GetImageManager().GetPlaceholder(24)));
|
||||
auto cb = [this](const Glib::RefPtr<Gdk::Pixbuf> &pb) {
|
||||
m_icon->property_pixbuf() = pb->scale_simple(24, 24, Gdk::INTERP_BILINEAR);
|
||||
};
|
||||
Abaddon::Get().GetImageManager().LoadFromURL(top_recipient->GetAvatarURL("png", "16"), sigc::track_obj(cb, *this));
|
||||
}
|
||||
|
||||
m_box->set_halign(Gtk::ALIGN_START);
|
||||
if (m_icon != nullptr)
|
||||
m_box->pack_start(*m_icon);
|
||||
if (m_status != nullptr)
|
||||
m_box->pack_start(*m_status);
|
||||
m_box->pack_start(*m_lbl);
|
||||
m_ev->add(*m_box);
|
||||
add(*m_ev);
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
ChannelListRowGuild::ChannelListRowGuild(const GuildData *data) {
|
||||
ID = data->ID;
|
||||
m_ev = Gtk::manage(new Gtk::EventBox);
|
||||
m_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
|
||||
|
||||
const static bool alt = Abaddon::Get().GetSettings().GetUseMobileLayout();
|
||||
if (alt) {
|
||||
m_lbl = Gtk::manage(new Gtk::Label(data->Name));
|
||||
} else {
|
||||
auto *tmp = Gtk::manage(new Gtk::TextView);
|
||||
m_lbl = tmp;
|
||||
MakeReadOnly(tmp);
|
||||
auto buf = tmp->get_buffer();
|
||||
Gtk::TextBuffer::iterator start, end;
|
||||
buf->get_bounds(start, end);
|
||||
buf->insert_markup(start, "<b>" + Glib::Markup::escape_text(data->Name) + "</b>");
|
||||
static bool show_emojis = Abaddon::Get().GetSettings().GetShowEmojis();
|
||||
if (show_emojis)
|
||||
Abaddon::Get().GetEmojis().ReplaceEmojis(buf, ChannelEmojiSize);
|
||||
}
|
||||
|
||||
AddWidgetMenuHandler(m_ev, m_menu);
|
||||
AddWidgetMenuHandler(m_lbl, m_menu);
|
||||
|
||||
m_menu_copyid = Gtk::manage(new Gtk::MenuItem("_Copy ID", true));
|
||||
m_menu_copyid->signal_activate().connect([this]() {
|
||||
m_signal_copy_id.emit();
|
||||
});
|
||||
m_menu.append(*m_menu_copyid);
|
||||
|
||||
m_menu_leave = Gtk::manage(new Gtk::MenuItem("_Leave Guild", true));
|
||||
m_menu_leave->signal_activate().connect([this]() {
|
||||
m_signal_leave.emit();
|
||||
});
|
||||
m_menu.append(*m_menu_leave);
|
||||
|
||||
m_menu_settings = Gtk::manage(new Gtk::MenuItem("Guild _Settings", true));
|
||||
m_menu_settings->signal_activate().connect([this]() {
|
||||
m_signal_settings.emit();
|
||||
});
|
||||
m_menu.append(*m_menu_settings);
|
||||
|
||||
m_menu.show_all();
|
||||
|
||||
const auto show_animations = Abaddon::Get().GetSettings().GetShowAnimations();
|
||||
auto &img = Abaddon::Get().GetImageManager();
|
||||
if (data->HasIcon()) {
|
||||
if (data->HasAnimatedIcon() && show_animations) {
|
||||
m_icon = Gtk::manage(new Gtk::Image(img.GetPlaceholder(24)));
|
||||
auto cb = [this](const Glib::RefPtr<Gdk::PixbufAnimation> &pb) {
|
||||
m_icon->property_pixbuf_animation() = pb;
|
||||
};
|
||||
img.LoadAnimationFromURL(data->GetIconURL("gif", "32"), 24, 24, sigc::track_obj(cb, *this));
|
||||
} else {
|
||||
m_icon = Gtk::manage(new Gtk::Image(img.GetPlaceholder(24)));
|
||||
auto cb = [this](const Glib::RefPtr<Gdk::Pixbuf> &pb) {
|
||||
m_icon->property_pixbuf() = pb->scale_simple(24, 24, Gdk::INTERP_BILINEAR);
|
||||
};
|
||||
img.LoadFromURL(data->GetIconURL("png", "32"), sigc::track_obj(cb, *this));
|
||||
}
|
||||
} else {
|
||||
m_icon = Gtk::manage(new Gtk::Image(Abaddon::Get().GetImageManager().GetPlaceholder(24)));
|
||||
}
|
||||
|
||||
get_style_context()->add_class("channel-row");
|
||||
get_style_context()->add_class("channel-row-guild");
|
||||
m_lbl->get_style_context()->add_class("channel-row-label");
|
||||
|
||||
m_box->set_halign(Gtk::ALIGN_START);
|
||||
m_box->pack_start(*m_icon);
|
||||
m_box->pack_start(*m_lbl);
|
||||
m_ev->add(*m_box);
|
||||
add(*m_ev);
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
ChannelListRowGuild::type_signal_copy_id ChannelListRowGuild::signal_copy_id() {
|
||||
return m_signal_copy_id;
|
||||
}
|
||||
|
||||
ChannelListRowGuild::type_signal_leave ChannelListRowGuild::signal_leave() {
|
||||
return m_signal_leave;
|
||||
}
|
||||
|
||||
ChannelListRowGuild::type_signal_settings ChannelListRowGuild::signal_settings() {
|
||||
return m_signal_settings;
|
||||
}
|
||||
|
||||
ChannelListRowCategory::ChannelListRowCategory(const ChannelData *data) {
|
||||
ID = data->ID;
|
||||
m_ev = Gtk::manage(new Gtk::EventBox);
|
||||
m_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
|
||||
|
||||
const static bool alt = Abaddon::Get().GetSettings().GetUseMobileLayout();
|
||||
if (alt) {
|
||||
m_lbl = Gtk::manage(new Gtk::Label(*data->Name));
|
||||
} else {
|
||||
auto *tmp = Gtk::manage(new Gtk::TextView);
|
||||
m_lbl = tmp;
|
||||
MakeReadOnly(tmp);
|
||||
auto buf = tmp->get_buffer();
|
||||
buf->set_text(*data->Name);
|
||||
static bool show_emojis = Abaddon::Get().GetSettings().GetShowEmojis();
|
||||
if (show_emojis)
|
||||
Abaddon::Get().GetEmojis().ReplaceEmojis(buf, ChannelEmojiSize);
|
||||
}
|
||||
m_arrow = Gtk::manage(new Gtk::Arrow(Gtk::ARROW_DOWN, Gtk::SHADOW_NONE));
|
||||
|
||||
m_menu_copyid = Gtk::manage(new Gtk::MenuItem("_Copy ID", true));
|
||||
m_menu_copyid->signal_activate().connect([this]() {
|
||||
m_signal_copy_id.emit();
|
||||
});
|
||||
m_menu.append(*m_menu_copyid);
|
||||
|
||||
m_menu.show_all();
|
||||
|
||||
AddWidgetMenuHandler(m_ev, m_menu);
|
||||
AddWidgetMenuHandler(m_lbl, m_menu);
|
||||
|
||||
get_style_context()->add_class("channel-row");
|
||||
get_style_context()->add_class("channel-row-category");
|
||||
m_lbl->get_style_context()->add_class("channel-row-label");
|
||||
|
||||
m_box->set_halign(Gtk::ALIGN_START);
|
||||
m_box->pack_start(*m_arrow);
|
||||
m_box->pack_start(*m_lbl);
|
||||
m_ev->add(*m_box);
|
||||
add(*m_ev);
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
void ChannelListRowCategory::Collapse() {
|
||||
m_arrow->set(Gtk::ARROW_RIGHT, Gtk::SHADOW_NONE);
|
||||
}
|
||||
|
||||
void ChannelListRowCategory::Expand() {
|
||||
m_arrow->set(IsUserCollapsed ? Gtk::ARROW_RIGHT : Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
|
||||
}
|
||||
|
||||
ChannelListRowCategory::type_signal_copy_id ChannelListRowCategory::signal_copy_id() {
|
||||
return m_signal_copy_id;
|
||||
}
|
||||
|
||||
ChannelListRowChannel::ChannelListRowChannel(const ChannelData *data) {
|
||||
ID = data->ID;
|
||||
m_ev = Gtk::manage(new Gtk::EventBox);
|
||||
m_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
|
||||
|
||||
const static bool alt = Abaddon::Get().GetSettings().GetUseMobileLayout();
|
||||
if (alt) {
|
||||
m_lbl = Gtk::manage(new Gtk::Label("#" + *data->Name));
|
||||
} else {
|
||||
auto *tmp = Gtk::manage(new Gtk::TextView);
|
||||
m_lbl = tmp;
|
||||
MakeReadOnly(tmp);
|
||||
auto buf = tmp->get_buffer();
|
||||
buf->set_text("#" + *data->Name);
|
||||
static bool show_emojis = Abaddon::Get().GetSettings().GetShowEmojis();
|
||||
if (show_emojis)
|
||||
Abaddon::Get().GetEmojis().ReplaceEmojis(buf, ChannelEmojiSize);
|
||||
}
|
||||
|
||||
m_menu_copyid = Gtk::manage(new Gtk::MenuItem("_Copy ID", true));
|
||||
m_menu_copyid->signal_activate().connect([this]() {
|
||||
m_signal_copy_id.emit();
|
||||
});
|
||||
m_menu.append(*m_menu_copyid);
|
||||
|
||||
m_menu.show_all();
|
||||
|
||||
AddWidgetMenuHandler(m_ev, m_menu);
|
||||
AddWidgetMenuHandler(m_lbl, m_menu);
|
||||
|
||||
get_style_context()->add_class("channel-row");
|
||||
get_style_context()->add_class("channel-row-channel");
|
||||
m_lbl->get_style_context()->add_class("channel-row-label");
|
||||
|
||||
if (data->IsNSFW.has_value() && *data->IsNSFW) {
|
||||
get_style_context()->add_class("nsfw");
|
||||
m_lbl->get_style_context()->add_class("nsfw");
|
||||
}
|
||||
|
||||
m_box->set_halign(Gtk::ALIGN_START);
|
||||
m_box->pack_start(*m_lbl);
|
||||
m_ev->add(*m_box);
|
||||
add(*m_ev);
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
ChannelListRowChannel::type_signal_copy_id ChannelListRowChannel::signal_copy_id() {
|
||||
return m_signal_copy_id;
|
||||
}
|
||||
|
||||
ChannelList::ChannelList() {
|
||||
m_main = Gtk::manage(new Gtk::ScrolledWindow);
|
||||
m_list = Gtk::manage(new Gtk::ListBox);
|
||||
|
||||
m_list->get_style_context()->add_class("channel-list");
|
||||
|
||||
m_list->set_activate_on_single_click(true);
|
||||
m_list->signal_row_activated().connect(sigc::mem_fun(*this, &ChannelList::on_row_activated));
|
||||
|
||||
m_main->add(*m_list);
|
||||
m_main->show_all();
|
||||
|
||||
// maybe will regret doing it this way
|
||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
auto cb = [this, &discord](const Message &message) {
|
||||
const auto channel = discord.GetChannel(message.ChannelID);
|
||||
if (!channel.has_value()) return;
|
||||
if (channel->Type == ChannelType::DM || channel->Type == ChannelType::GROUP_DM)
|
||||
CheckBumpDM(message.ChannelID);
|
||||
};
|
||||
discord.signal_message_create().connect(sigc::track_obj(cb, *this));
|
||||
}
|
||||
|
||||
Gtk::Widget *ChannelList::GetRoot() const {
|
||||
return m_main;
|
||||
}
|
||||
|
||||
void ChannelList::UpdateNewGuild(Snowflake id) {
|
||||
auto sort = Abaddon::Get().GetDiscordClient().GetUserSortedGuilds();
|
||||
if (sort.size() == 1) {
|
||||
UpdateListing();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto insert_at = [this, id](int listpos) {
|
||||
InsertGuildAt(id, listpos);
|
||||
};
|
||||
|
||||
auto it = std::find(sort.begin(), sort.end(), id);
|
||||
if (it == sort.end()) return;
|
||||
// if the new guild pos is at the end use -1
|
||||
if (it + 1 == sort.end()) {
|
||||
insert_at(-1);
|
||||
return;
|
||||
}
|
||||
// find the position of the guild below it into the listbox
|
||||
auto below_id = *(it + 1);
|
||||
auto below_it = m_id_to_row.find(below_id);
|
||||
if (below_it == m_id_to_row.end()) {
|
||||
UpdateListing();
|
||||
return;
|
||||
}
|
||||
auto below_pos = below_it->second->get_index();
|
||||
// stick it just above
|
||||
insert_at(below_pos - 1);
|
||||
}
|
||||
|
||||
void ChannelList::UpdateRemoveGuild(Snowflake id) {
|
||||
auto it = m_guild_id_to_row.find(id);
|
||||
if (it == m_guild_id_to_row.end()) return;
|
||||
auto row = dynamic_cast<ChannelListRow *>(it->second);
|
||||
if (row == nullptr) return;
|
||||
DeleteRow(row);
|
||||
}
|
||||
|
||||
void ChannelList::UpdateRemoveChannel(Snowflake id) {
|
||||
auto it = m_id_to_row.find(id);
|
||||
if (it == m_id_to_row.end()) return;
|
||||
auto row = dynamic_cast<ChannelListRow *>(it->second);
|
||||
if (row == nullptr) return;
|
||||
DeleteRow(row);
|
||||
}
|
||||
|
||||
// this is total shit
|
||||
void ChannelList::UpdateChannelCategory(Snowflake id) {
|
||||
const auto data = Abaddon::Get().GetDiscordClient().GetChannel(id);
|
||||
const auto guild = Abaddon::Get().GetDiscordClient().GetGuild(*data->GuildID);
|
||||
auto git = m_guild_id_to_row.find(*data->GuildID);
|
||||
if (git == m_guild_id_to_row.end()) return;
|
||||
auto *guild_row = git->second;
|
||||
if (!data.has_value() || !guild.has_value()) return;
|
||||
auto it = m_id_to_row.find(id);
|
||||
if (it == m_id_to_row.end()) return;
|
||||
auto row = dynamic_cast<ChannelListRowCategory *>(it->second);
|
||||
if (row == nullptr) return;
|
||||
const bool old_collapsed = row->IsUserCollapsed;
|
||||
const bool visible = row->is_visible();
|
||||
std::map<int, Snowflake> child_rows;
|
||||
for (auto child : row->Children) {
|
||||
child_rows[child->get_index()] = child->ID;
|
||||
}
|
||||
guild_row->Children.erase(row);
|
||||
DeleteRow(row);
|
||||
|
||||
int pos = guild_row->get_index();
|
||||
const auto sorted = guild->GetSortedChannels(id);
|
||||
const auto sorted_it = std::find(sorted.begin(), sorted.end(), id);
|
||||
if (sorted_it == sorted.end()) return;
|
||||
if (std::next(sorted_it) == sorted.end()) {
|
||||
const auto x = m_id_to_row.find(*std::prev(sorted_it));
|
||||
if (x != m_id_to_row.end())
|
||||
pos = x->second->get_index() + 1;
|
||||
} else {
|
||||
const auto x = m_id_to_row.find(*std::next(sorted_it));
|
||||
if (x != m_id_to_row.end())
|
||||
pos = x->second->get_index();
|
||||
}
|
||||
|
||||
auto *new_row = Gtk::manage(new ChannelListRowCategory(&*data));
|
||||
new_row->IsUserCollapsed = old_collapsed;
|
||||
if (visible)
|
||||
new_row->show();
|
||||
m_id_to_row[id] = new_row;
|
||||
new_row->signal_copy_id().connect(sigc::bind(sigc::mem_fun(*this, &ChannelList::OnMenuCopyID), new_row->ID));
|
||||
new_row->Parent = guild_row;
|
||||
guild_row->Children.insert(new_row);
|
||||
m_list->insert(*new_row, pos);
|
||||
int i = 1;
|
||||
for (const auto &[idx, child_id] : child_rows) {
|
||||
const auto channel = Abaddon::Get().GetDiscordClient().GetChannel(child_id);
|
||||
if (channel.has_value()) {
|
||||
auto *new_child = Gtk::manage(new ChannelListRowChannel(&*channel));
|
||||
new_row->Children.insert(new_child);
|
||||
new_child->Parent = new_row;
|
||||
new_child->signal_copy_id().connect(sigc::bind(sigc::mem_fun(*this, &ChannelList::OnMenuCopyID), new_child->ID));
|
||||
m_id_to_row[child_id] = new_child;
|
||||
if (visible && !new_row->IsUserCollapsed)
|
||||
new_child->show();
|
||||
m_list->insert(*new_child, pos + i++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// so is this
|
||||
void ChannelList::UpdateChannel(Snowflake id) {
|
||||
const auto data = Abaddon::Get().GetDiscordClient().GetChannel(id);
|
||||
const auto guild = Abaddon::Get().GetDiscordClient().GetGuild(*data->GuildID);
|
||||
const auto *guild_row = m_guild_id_to_row.at(*data->GuildID);
|
||||
if (data->Type == ChannelType::GUILD_CATEGORY) {
|
||||
UpdateChannelCategory(id);
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = m_id_to_row.find(id);
|
||||
if (it == m_id_to_row.end()) return; // stuff like voice doesnt have a row yet
|
||||
auto row = dynamic_cast<ChannelListRowChannel *>(it->second);
|
||||
const bool old_collapsed = row->IsUserCollapsed;
|
||||
const bool old_visible = row->is_visible();
|
||||
DeleteRow(row);
|
||||
|
||||
int pos = guild_row->get_index() + 1; // fallback
|
||||
const auto sorted = guild->GetSortedChannels();
|
||||
const auto sorted_it = std::find(sorted.begin(), sorted.end(), id);
|
||||
if (sorted_it + 1 == sorted.end()) {
|
||||
const auto x = m_id_to_row.find(*std::prev(sorted_it));
|
||||
if (x != m_id_to_row.end())
|
||||
pos = x->second->get_index() + 1;
|
||||
} else {
|
||||
const auto x = m_id_to_row.find(*std::next(sorted_it));
|
||||
if (x != m_id_to_row.end())
|
||||
pos = x->second->get_index();
|
||||
}
|
||||
|
||||
auto *new_row = Gtk::manage(new ChannelListRowChannel(&*data));
|
||||
new_row->IsUserCollapsed = old_collapsed;
|
||||
m_id_to_row[id] = new_row;
|
||||
if (data->ParentID.has_value()) {
|
||||
new_row->Parent = m_id_to_row.at(*data->ParentID);
|
||||
} else {
|
||||
new_row->Parent = m_guild_id_to_row.at(*data->GuildID);
|
||||
}
|
||||
new_row->Parent->Children.insert(new_row);
|
||||
if (new_row->Parent->is_visible() && !new_row->Parent->IsUserCollapsed)
|
||||
new_row->show();
|
||||
new_row->signal_copy_id().connect(sigc::bind(sigc::mem_fun(*this, &ChannelList::OnMenuCopyID), new_row->ID));
|
||||
m_list->insert(*new_row, pos);
|
||||
}
|
||||
|
||||
void ChannelList::UpdateCreateDMChannel(Snowflake id) {
|
||||
const auto chan = Abaddon::Get().GetDiscordClient().GetChannel(id);
|
||||
auto *dm_row = Gtk::manage(new ChannelListRowDMChannel(&*chan));
|
||||
dm_row->IsUserCollapsed = false;
|
||||
m_list->insert(*dm_row, m_dm_header_row->get_index() + 1);
|
||||
m_dm_header_row->Children.insert(dm_row);
|
||||
m_id_to_row[id] = dm_row;
|
||||
if (!m_dm_header_row->IsUserCollapsed)
|
||||
dm_row->show();
|
||||
}
|
||||
|
||||
void ChannelList::UpdateCreateChannel(Snowflake id) {
|
||||
const auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
const auto data = discord.GetChannel(id);
|
||||
if (data->Type == ChannelType::DM || data->Type == ChannelType::GROUP_DM) {
|
||||
UpdateCreateDMChannel(id);
|
||||
return;
|
||||
}
|
||||
const auto guild = discord.GetGuild(*data->GuildID);
|
||||
auto *guild_row = m_guild_id_to_row.at(*data->GuildID);
|
||||
|
||||
int pos = guild_row->get_index() + 1;
|
||||
const auto sorted = guild->GetSortedChannels();
|
||||
const auto sorted_it = std::find(sorted.begin(), sorted.end(), id);
|
||||
if (sorted_it + 1 == sorted.end()) {
|
||||
const auto x = m_id_to_row.find(*std::prev(sorted_it));
|
||||
if (x != m_id_to_row.end())
|
||||
pos = x->second->get_index() + 1;
|
||||
} else {
|
||||
const auto x = m_id_to_row.find(*std::next(sorted_it));
|
||||
if (x != m_id_to_row.end())
|
||||
pos = x->second->get_index();
|
||||
}
|
||||
|
||||
ChannelListRow *row;
|
||||
if (data->Type == ChannelType::GUILD_TEXT || data->Type == ChannelType::GUILD_NEWS) {
|
||||
auto *tmp = Gtk::manage(new ChannelListRowChannel(&*data));
|
||||
tmp->signal_copy_id().connect(sigc::bind(sigc::mem_fun(*this, &ChannelList::OnMenuCopyID), tmp->ID));
|
||||
row = tmp;
|
||||
} else if (data->Type == ChannelType::GUILD_CATEGORY) {
|
||||
auto *tmp = Gtk::manage(new ChannelListRowCategory(&*data));
|
||||
tmp->signal_copy_id().connect(sigc::bind(sigc::mem_fun(*this, &ChannelList::OnMenuCopyID), tmp->ID));
|
||||
row = tmp;
|
||||
} else
|
||||
return;
|
||||
row->IsUserCollapsed = false;
|
||||
if (!guild_row->IsUserCollapsed)
|
||||
row->show();
|
||||
row->Parent = guild_row;
|
||||
guild_row->Children.insert(row);
|
||||
m_id_to_row[id] = row;
|
||||
m_list->insert(*row, pos);
|
||||
}
|
||||
|
||||
void ChannelList::UpdateGuild(Snowflake id) {
|
||||
// the only thing changed is the row containing the guild item so just recreate it
|
||||
const auto data = Abaddon::Get().GetDiscordClient().GetGuild(id);
|
||||
if (!data.has_value()) return;
|
||||
auto it = m_guild_id_to_row.find(id);
|
||||
if (it == m_guild_id_to_row.end()) return;
|
||||
auto *row = dynamic_cast<ChannelListRowGuild *>(it->second);
|
||||
const auto children = row->Children;
|
||||
const auto index = row->get_index();
|
||||
const bool old_collapsed = row->IsUserCollapsed;
|
||||
const bool old_gindex = row->GuildIndex;
|
||||
delete row;
|
||||
auto *new_row = Gtk::manage(new ChannelListRowGuild(&*data));
|
||||
new_row->IsUserCollapsed = old_collapsed;
|
||||
new_row->GuildIndex = old_gindex;
|
||||
m_guild_id_to_row[new_row->ID] = new_row;
|
||||
new_row->signal_leave().connect(sigc::bind(sigc::mem_fun(*this, &ChannelList::OnGuildMenuLeave), new_row->ID));
|
||||
new_row->signal_copy_id().connect(sigc::bind(sigc::mem_fun(*this, &ChannelList::OnMenuCopyID), new_row->ID));
|
||||
new_row->signal_settings().connect(sigc::bind(sigc::mem_fun(*this, &ChannelList::OnGuildMenuSettings), new_row->ID));
|
||||
new_row->Children = children;
|
||||
for (auto child : children)
|
||||
child->Parent = new_row;
|
||||
new_row->show_all();
|
||||
m_list->insert(*new_row, index);
|
||||
}
|
||||
|
||||
void ChannelList::SetActiveChannel(Snowflake id) {
|
||||
auto it = m_id_to_row.find(id);
|
||||
if (it == m_id_to_row.end()) return;
|
||||
m_list->select_row(*it->second);
|
||||
}
|
||||
|
||||
void ChannelList::CollapseRow(ChannelListRow *row) {
|
||||
row->Collapse();
|
||||
for (auto child : row->Children) {
|
||||
child->hide();
|
||||
CollapseRow(child);
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelList::ExpandRow(ChannelListRow *row) {
|
||||
row->Expand();
|
||||
row->show();
|
||||
if (!row->IsUserCollapsed)
|
||||
for (auto child : row->Children)
|
||||
ExpandRow(child);
|
||||
}
|
||||
|
||||
void ChannelList::DeleteRow(ChannelListRow *row) {
|
||||
for (auto child : row->Children)
|
||||
DeleteRow(child);
|
||||
if (row->Parent != nullptr)
|
||||
row->Parent->Children.erase(row);
|
||||
else
|
||||
printf("row has no parent!\n");
|
||||
if (dynamic_cast<ChannelListRowGuild *>(row) != nullptr)
|
||||
m_guild_id_to_row.erase(row->ID);
|
||||
else
|
||||
m_id_to_row.erase(row->ID);
|
||||
delete row;
|
||||
}
|
||||
|
||||
void ChannelList::on_row_activated(Gtk::ListBoxRow *tmprow) {
|
||||
auto row = dynamic_cast<ChannelListRow *>(tmprow);
|
||||
if (row == nullptr) return;
|
||||
bool new_collapsed = !row->IsUserCollapsed;
|
||||
row->IsUserCollapsed = new_collapsed;
|
||||
|
||||
// kinda ugly
|
||||
if (dynamic_cast<ChannelListRowChannel *>(row) != nullptr || dynamic_cast<ChannelListRowDMChannel *>(row) != nullptr)
|
||||
m_signal_action_channel_item_select.emit(row->ID);
|
||||
|
||||
if (new_collapsed)
|
||||
CollapseRow(row);
|
||||
else
|
||||
ExpandRow(row);
|
||||
}
|
||||
|
||||
void ChannelList::InsertGuildAt(Snowflake id, int pos) {
|
||||
const auto insert_and_adjust = [&](Gtk::Widget &widget) {
|
||||
m_list->insert(widget, pos);
|
||||
if (pos != -1) pos++;
|
||||
};
|
||||
|
||||
const auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
const auto guild_data = discord.GetGuild(id);
|
||||
if (!guild_data.has_value()) return;
|
||||
|
||||
std::map<int, ChannelData> orphan_channels;
|
||||
std::unordered_map<Snowflake, std::vector<ChannelData>> cat_to_channels;
|
||||
if (guild_data->Channels.has_value())
|
||||
for (const auto &dc : *guild_data->Channels) {
|
||||
const auto channel = discord.GetChannel(dc.ID);
|
||||
if (!channel.has_value()) continue;
|
||||
if (channel->Type != ChannelType::GUILD_TEXT && channel->Type != ChannelType::GUILD_NEWS) continue;
|
||||
|
||||
if (channel->ParentID.has_value())
|
||||
cat_to_channels[*channel->ParentID].push_back(*channel);
|
||||
else
|
||||
orphan_channels[*channel->Position] = *channel;
|
||||
}
|
||||
|
||||
auto *guild_row = Gtk::manage(new ChannelListRowGuild(&*guild_data));
|
||||
guild_row->show_all();
|
||||
guild_row->IsUserCollapsed = true;
|
||||
guild_row->GuildIndex = m_guild_count++;
|
||||
insert_and_adjust(*guild_row);
|
||||
m_guild_id_to_row[guild_row->ID] = guild_row;
|
||||
guild_row->signal_leave().connect(sigc::bind(sigc::mem_fun(*this, &ChannelList::OnGuildMenuLeave), guild_row->ID));
|
||||
guild_row->signal_copy_id().connect(sigc::bind(sigc::mem_fun(*this, &ChannelList::OnMenuCopyID), guild_row->ID));
|
||||
guild_row->signal_settings().connect(sigc::bind(sigc::mem_fun(*this, &ChannelList::OnGuildMenuSettings), guild_row->ID));
|
||||
|
||||
// add channels with no parent category
|
||||
for (const auto &[pos, channel] : orphan_channels) {
|
||||
auto *chan_row = Gtk::manage(new ChannelListRowChannel(&channel));
|
||||
chan_row->IsUserCollapsed = false;
|
||||
chan_row->signal_copy_id().connect(sigc::bind(sigc::mem_fun(*this, &ChannelList::OnMenuCopyID), chan_row->ID));
|
||||
insert_and_adjust(*chan_row);
|
||||
guild_row->Children.insert(chan_row);
|
||||
chan_row->Parent = guild_row;
|
||||
m_id_to_row[chan_row->ID] = chan_row;
|
||||
}
|
||||
|
||||
// categories
|
||||
std::map<int, std::vector<ChannelData>> sorted_categories;
|
||||
if (guild_data->Channels.has_value())
|
||||
for (const auto &dc : *guild_data->Channels) {
|
||||
const auto channel = discord.GetChannel(dc.ID);
|
||||
if (!channel.has_value()) continue;
|
||||
if (channel->Type == ChannelType::GUILD_CATEGORY)
|
||||
sorted_categories[*channel->Position].push_back(*channel);
|
||||
}
|
||||
|
||||
for (auto &[pos, catvec] : sorted_categories) {
|
||||
std::sort(catvec.begin(), catvec.end(), [](const ChannelData &a, const ChannelData &b) { return a.ID < b.ID; });
|
||||
for (const auto cat : catvec) {
|
||||
auto *cat_row = Gtk::manage(new ChannelListRowCategory(&cat));
|
||||
cat_row->IsUserCollapsed = false;
|
||||
cat_row->signal_copy_id().connect(sigc::bind(sigc::mem_fun(*this, &ChannelList::OnMenuCopyID), cat_row->ID));
|
||||
insert_and_adjust(*cat_row);
|
||||
guild_row->Children.insert(cat_row);
|
||||
cat_row->Parent = guild_row;
|
||||
m_id_to_row[cat_row->ID] = cat_row;
|
||||
|
||||
// child channels
|
||||
if (cat_to_channels.find(cat.ID) == cat_to_channels.end()) continue;
|
||||
std::map<int, ChannelData> sorted_channels;
|
||||
|
||||
for (const auto channel : cat_to_channels.at(cat.ID))
|
||||
sorted_channels[*channel.Position] = channel;
|
||||
|
||||
for (const auto &[pos, channel] : sorted_channels) {
|
||||
auto *chan_row = Gtk::manage(new ChannelListRowChannel(&channel));
|
||||
chan_row->IsUserCollapsed = false;
|
||||
chan_row->signal_copy_id().connect(sigc::bind(sigc::mem_fun(*this, &ChannelList::OnMenuCopyID), chan_row->ID));
|
||||
insert_and_adjust(*chan_row);
|
||||
cat_row->Children.insert(chan_row);
|
||||
chan_row->Parent = cat_row;
|
||||
m_id_to_row[chan_row->ID] = chan_row;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelList::AddPrivateChannels() {
|
||||
const auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
auto dms_ = discord.GetPrivateChannels();
|
||||
std::vector<ChannelData> dms;
|
||||
for (const auto &x : dms_) {
|
||||
const auto chan = discord.GetChannel(x);
|
||||
dms.push_back(*chan);
|
||||
}
|
||||
std::sort(dms.begin(), dms.end(), [&](const ChannelData &a, const ChannelData &b) -> bool {
|
||||
return a.LastMessageID > b.LastMessageID;
|
||||
});
|
||||
|
||||
m_dm_header_row = Gtk::manage(new ChannelListRowDMHeader);
|
||||
m_dm_header_row->show_all();
|
||||
m_dm_header_row->IsUserCollapsed = true;
|
||||
m_list->add(*m_dm_header_row);
|
||||
|
||||
for (const auto &dm : dms) {
|
||||
auto *dm_row = Gtk::manage(new ChannelListRowDMChannel(&dm));
|
||||
dm_row->Parent = m_dm_header_row;
|
||||
m_id_to_row[dm.ID] = dm_row;
|
||||
dm_row->IsUserCollapsed = false;
|
||||
m_list->add(*dm_row);
|
||||
m_dm_header_row->Children.insert(dm_row);
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelList::UpdateListing() {
|
||||
std::unordered_set<Snowflake> guilds = Abaddon::Get().GetDiscordClient().GetGuilds();
|
||||
|
||||
auto children = m_list->get_children();
|
||||
auto it = children.begin();
|
||||
|
||||
while (it != children.end()) {
|
||||
delete *it;
|
||||
it++;
|
||||
}
|
||||
|
||||
m_id_to_row.clear();
|
||||
|
||||
m_guild_count = 0;
|
||||
|
||||
AddPrivateChannels();
|
||||
|
||||
auto sorted_guilds = Abaddon::Get().GetDiscordClient().GetUserSortedGuilds();
|
||||
for (auto gid : sorted_guilds) {
|
||||
InsertGuildAt(gid, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelList::OnMenuCopyID(Snowflake id) {
|
||||
Gtk::Clipboard::get()->set_text(std::to_string(id));
|
||||
}
|
||||
|
||||
void ChannelList::OnGuildMenuLeave(Snowflake id) {
|
||||
m_signal_action_guild_leave.emit(id);
|
||||
}
|
||||
|
||||
void ChannelList::OnGuildMenuSettings(Snowflake id) {
|
||||
m_signal_action_guild_settings.emit(id);
|
||||
}
|
||||
|
||||
void ChannelList::CheckBumpDM(Snowflake channel_id) {
|
||||
auto it = m_id_to_row.find(channel_id);
|
||||
if (it == m_id_to_row.end()) return;
|
||||
auto *row = it->second;
|
||||
const auto index = row->get_index();
|
||||
if (index == 1) return; // 1 is top of dm list
|
||||
const bool selected = row->is_selected();
|
||||
row->Parent->Children.erase(row);
|
||||
delete row;
|
||||
const auto chan = Abaddon::Get().GetDiscordClient().GetChannel(channel_id);
|
||||
auto *dm_row = Gtk::manage(new ChannelListRowDMChannel(&*chan));
|
||||
dm_row->Parent = m_dm_header_row;
|
||||
m_dm_header_row->Children.insert(dm_row);
|
||||
m_id_to_row[channel_id] = dm_row;
|
||||
dm_row->IsUserCollapsed = false;
|
||||
m_list->insert(*dm_row, 1);
|
||||
m_dm_header_row->Children.insert(dm_row);
|
||||
if (selected)
|
||||
m_list->select_row(*dm_row);
|
||||
if (m_dm_header_row->is_visible() && !m_dm_header_row->IsUserCollapsed)
|
||||
dm_row->show();
|
||||
}
|
||||
|
||||
ChannelList::type_signal_action_channel_item_select ChannelList::signal_action_channel_item_select() {
|
||||
return m_signal_action_channel_item_select;
|
||||
}
|
||||
|
||||
ChannelList::type_signal_action_guild_leave ChannelList::signal_action_guild_leave() {
|
||||
return m_signal_action_guild_leave;
|
||||
}
|
||||
|
||||
ChannelList::type_signal_action_guild_settings ChannelList::signal_action_guild_settings() {
|
||||
return m_signal_action_guild_settings;
|
||||
}
|
@ -1,191 +0,0 @@
|
||||
#pragma once
|
||||
#include <gtkmm.h>
|
||||
#include <string>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <sigc++/sigc++.h>
|
||||
#include "../discord/discord.hpp"
|
||||
|
||||
static const constexpr int ChannelEmojiSize = 16;
|
||||
|
||||
class ChannelListRow : public Gtk::ListBoxRow {
|
||||
public:
|
||||
bool IsUserCollapsed;
|
||||
Snowflake ID;
|
||||
std::unordered_set<ChannelListRow *> Children;
|
||||
ChannelListRow *Parent = nullptr;
|
||||
|
||||
virtual void Collapse();
|
||||
virtual void Expand();
|
||||
|
||||
static void MakeReadOnly(Gtk::TextView *tv);
|
||||
};
|
||||
|
||||
class ChannelListRowDMHeader : public ChannelListRow {
|
||||
public:
|
||||
ChannelListRowDMHeader();
|
||||
|
||||
protected:
|
||||
Gtk::EventBox *m_ev;
|
||||
Gtk::Box *m_box;
|
||||
Gtk::Label *m_lbl;
|
||||
};
|
||||
|
||||
class StatusIndicator;
|
||||
class ChannelListRowDMChannel : public ChannelListRow {
|
||||
public:
|
||||
ChannelListRowDMChannel(const ChannelData *data);
|
||||
|
||||
protected:
|
||||
Gtk::EventBox *m_ev;
|
||||
Gtk::Box *m_box;
|
||||
StatusIndicator *m_status = nullptr;
|
||||
Gtk::Widget *m_lbl;
|
||||
Gtk::Image *m_icon = nullptr;
|
||||
|
||||
Gtk::Menu m_menu;
|
||||
Gtk::MenuItem *m_menu_close; // leave if group
|
||||
Gtk::MenuItem *m_menu_copy_id;
|
||||
};
|
||||
|
||||
class ChannelListRowGuild : public ChannelListRow {
|
||||
public:
|
||||
ChannelListRowGuild(const GuildData *data);
|
||||
|
||||
int GuildIndex;
|
||||
|
||||
protected:
|
||||
Gtk::EventBox *m_ev;
|
||||
Gtk::Box *m_box;
|
||||
Gtk::Widget *m_lbl;
|
||||
Gtk::Image *m_icon;
|
||||
|
||||
Gtk::Menu m_menu;
|
||||
Gtk::MenuItem *m_menu_copyid;
|
||||
Gtk::MenuItem *m_menu_leave;
|
||||
Gtk::MenuItem *m_menu_settings;
|
||||
|
||||
private:
|
||||
typedef sigc::signal<void> type_signal_copy_id;
|
||||
typedef sigc::signal<void> type_signal_leave;
|
||||
typedef sigc::signal<void> type_signal_settings;
|
||||
|
||||
type_signal_copy_id m_signal_copy_id;
|
||||
type_signal_leave m_signal_leave;
|
||||
type_signal_settings m_signal_settings;
|
||||
|
||||
public:
|
||||
type_signal_copy_id signal_copy_id();
|
||||
type_signal_leave signal_leave();
|
||||
type_signal_settings signal_settings();
|
||||
};
|
||||
|
||||
class ChannelListRowCategory : public ChannelListRow {
|
||||
public:
|
||||
ChannelListRowCategory(const ChannelData *data);
|
||||
|
||||
virtual void Collapse();
|
||||
virtual void Expand();
|
||||
|
||||
protected:
|
||||
Gtk::EventBox *m_ev;
|
||||
Gtk::Box *m_box;
|
||||
Gtk::Widget *m_lbl;
|
||||
Gtk::Arrow *m_arrow;
|
||||
|
||||
Gtk::Menu m_menu;
|
||||
Gtk::MenuItem *m_menu_copyid;
|
||||
|
||||
private:
|
||||
typedef sigc::signal<void> type_signal_copy_id;
|
||||
|
||||
type_signal_copy_id m_signal_copy_id;
|
||||
|
||||
public:
|
||||
type_signal_copy_id signal_copy_id();
|
||||
};
|
||||
|
||||
class ChannelListRowChannel : public ChannelListRow {
|
||||
public:
|
||||
ChannelListRowChannel(const ChannelData *data);
|
||||
|
||||
protected:
|
||||
Gtk::EventBox *m_ev;
|
||||
Gtk::Box *m_box;
|
||||
Gtk::Widget *m_lbl;
|
||||
|
||||
Gtk::Menu m_menu;
|
||||
Gtk::MenuItem *m_menu_copyid;
|
||||
|
||||
private:
|
||||
typedef sigc::signal<void> type_signal_copy_id;
|
||||
|
||||
type_signal_copy_id m_signal_copy_id;
|
||||
|
||||
public:
|
||||
type_signal_copy_id signal_copy_id();
|
||||
};
|
||||
|
||||
class ChannelList {
|
||||
public:
|
||||
ChannelList();
|
||||
Gtk::Widget *GetRoot() const;
|
||||
void UpdateListing();
|
||||
void UpdateNewGuild(Snowflake id);
|
||||
void UpdateRemoveGuild(Snowflake id);
|
||||
void UpdateRemoveChannel(Snowflake id);
|
||||
void UpdateChannel(Snowflake id);
|
||||
void UpdateCreateDMChannel(Snowflake id);
|
||||
void UpdateCreateChannel(Snowflake id);
|
||||
void UpdateGuild(Snowflake id);
|
||||
|
||||
void SetActiveChannel(Snowflake id);
|
||||
|
||||
protected:
|
||||
Gtk::ListBox *m_list;
|
||||
Gtk::ScrolledWindow *m_main;
|
||||
|
||||
ChannelListRowDMHeader *m_dm_header_row = nullptr;
|
||||
|
||||
void CollapseRow(ChannelListRow *row);
|
||||
void ExpandRow(ChannelListRow *row);
|
||||
void DeleteRow(ChannelListRow *row);
|
||||
|
||||
void UpdateChannelCategory(Snowflake id);
|
||||
|
||||
void on_row_activated(Gtk::ListBoxRow *row);
|
||||
|
||||
int m_guild_count;
|
||||
void OnMenuCopyID(Snowflake id);
|
||||
void OnGuildMenuLeave(Snowflake id);
|
||||
void OnGuildMenuSettings(Snowflake id);
|
||||
|
||||
Gtk::Menu m_channel_menu;
|
||||
Gtk::MenuItem *m_channel_menu_copyid;
|
||||
|
||||
// i would use one map but in really old guilds there can be a channel w/ same id as the guild so this hacky shit has to do
|
||||
std::unordered_map<Snowflake, ChannelListRow *> m_guild_id_to_row;
|
||||
std::unordered_map<Snowflake, ChannelListRow *> m_id_to_row;
|
||||
|
||||
void InsertGuildAt(Snowflake id, int pos);
|
||||
|
||||
void AddPrivateChannels();
|
||||
|
||||
void CheckBumpDM(Snowflake channel_id);
|
||||
|
||||
public:
|
||||
typedef sigc::signal<void, Snowflake> type_signal_action_channel_item_select;
|
||||
typedef sigc::signal<void, Snowflake> type_signal_action_guild_leave;
|
||||
typedef sigc::signal<void, Snowflake> type_signal_action_guild_settings;
|
||||
|
||||
type_signal_action_channel_item_select signal_action_channel_item_select();
|
||||
type_signal_action_guild_leave signal_action_guild_leave();
|
||||
type_signal_action_guild_settings signal_action_guild_settings();
|
||||
|
||||
protected:
|
||||
type_signal_action_channel_item_select m_signal_action_channel_item_select;
|
||||
type_signal_action_guild_leave m_signal_action_guild_leave;
|
||||
type_signal_action_guild_settings m_signal_action_guild_settings;
|
||||
};
|
@ -1,66 +0,0 @@
|
||||
#include "chatinput.hpp"
|
||||
|
||||
ChatInput::ChatInput() {
|
||||
get_style_context()->add_class("message-input");
|
||||
set_propagate_natural_height(true);
|
||||
set_min_content_height(20);
|
||||
set_max_content_height(250);
|
||||
set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
|
||||
|
||||
// hack
|
||||
auto cb = [this](GdkEventKey *e) -> bool {
|
||||
return event(reinterpret_cast<GdkEvent *>(e));
|
||||
};
|
||||
m_textview.signal_key_press_event().connect(cb, false);
|
||||
m_textview.set_hexpand(false);
|
||||
m_textview.set_halign(Gtk::ALIGN_FILL);
|
||||
m_textview.set_valign(Gtk::ALIGN_CENTER);
|
||||
m_textview.set_wrap_mode(Gtk::WRAP_WORD_CHAR);
|
||||
m_textview.show();
|
||||
add(m_textview);
|
||||
}
|
||||
|
||||
void ChatInput::InsertText(const Glib::ustring &text) {
|
||||
GetBuffer()->insert_at_cursor(text);
|
||||
m_textview.grab_focus();
|
||||
}
|
||||
|
||||
Glib::RefPtr<Gtk::TextBuffer> ChatInput::GetBuffer() {
|
||||
return m_textview.get_buffer();
|
||||
}
|
||||
|
||||
// this isnt connected directly so that the chat window can handle stuff like the completer first
|
||||
bool ChatInput::ProcessKeyPress(GdkEventKey *event) {
|
||||
if (event->keyval == GDK_KEY_Escape) {
|
||||
m_signal_escape.emit();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event->keyval == GDK_KEY_Return) {
|
||||
if (event->state & GDK_SHIFT_MASK)
|
||||
return false;
|
||||
|
||||
auto buf = GetBuffer();
|
||||
auto text = buf->get_text();
|
||||
|
||||
const bool accepted = m_signal_submit.emit(text);
|
||||
if (accepted)
|
||||
buf->set_text("");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ChatInput::on_grab_focus() {
|
||||
m_textview.grab_focus();
|
||||
}
|
||||
|
||||
ChatInput::type_signal_submit ChatInput::signal_submit() {
|
||||
return m_signal_submit;
|
||||
}
|
||||
|
||||
ChatInput::type_signal_escape ChatInput::signal_escape() {
|
||||
return m_signal_escape;
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
#include <gtkmm.h>
|
||||
|
||||
class ChatInput : public Gtk::ScrolledWindow {
|
||||
public:
|
||||
ChatInput();
|
||||
|
||||
void InsertText(const Glib::ustring &text);
|
||||
Glib::RefPtr<Gtk::TextBuffer> GetBuffer();
|
||||
bool ProcessKeyPress(GdkEventKey *event);
|
||||
|
||||
protected:
|
||||
void on_grab_focus() override;
|
||||
|
||||
private:
|
||||
Gtk::TextView m_textview;
|
||||
|
||||
public:
|
||||
typedef sigc::signal<bool, Glib::ustring> type_signal_submit;
|
||||
typedef sigc::signal<void> type_signal_escape;
|
||||
|
||||
type_signal_submit signal_submit();
|
||||
type_signal_escape signal_escape();
|
||||
|
||||
private:
|
||||
type_signal_submit m_signal_submit;
|
||||
type_signal_escape m_signal_escape;
|
||||
};
|
@ -1,411 +0,0 @@
|
||||
#include "chatwindow.hpp"
|
||||
#include "chatmessage.hpp"
|
||||
#include "../abaddon.hpp"
|
||||
#include "chatinputindicator.hpp"
|
||||
#include "ratelimitindicator.hpp"
|
||||
#include "chatinput.hpp"
|
||||
|
||||
constexpr static uint64_t SnowflakeSplitDifference = 600;
|
||||
|
||||
ChatWindow::ChatWindow() {
|
||||
Abaddon::Get().GetDiscordClient().signal_message_send_fail().connect(sigc::mem_fun(*this, &ChatWindow::OnMessageSendFail));
|
||||
|
||||
m_main = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
|
||||
m_list = Gtk::manage(new Gtk::ListBox);
|
||||
m_scroll = Gtk::manage(new Gtk::ScrolledWindow);
|
||||
m_input = Gtk::manage(new ChatInput);
|
||||
m_input_indicator = Gtk::manage(new ChatInputIndicator);
|
||||
m_rate_limit_indicator = Gtk::manage(new RateLimitIndicator);
|
||||
m_meta = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
|
||||
|
||||
m_rate_limit_indicator->set_margin_end(5);
|
||||
m_rate_limit_indicator->set_hexpand(true);
|
||||
m_rate_limit_indicator->set_halign(Gtk::ALIGN_END);
|
||||
m_rate_limit_indicator->set_valign(Gtk::ALIGN_END);
|
||||
m_rate_limit_indicator->show();
|
||||
|
||||
m_input_indicator->set_halign(Gtk::ALIGN_START);
|
||||
m_input_indicator->set_valign(Gtk::ALIGN_END);
|
||||
m_input_indicator->show();
|
||||
|
||||
m_main->get_style_context()->add_class("messages");
|
||||
m_list->get_style_context()->add_class("messages");
|
||||
|
||||
m_main->set_hexpand(true);
|
||||
m_main->set_vexpand(true);
|
||||
|
||||
m_scroll->signal_edge_reached().connect(sigc::mem_fun(*this, &ChatWindow::OnScrollEdgeOvershot));
|
||||
|
||||
auto v = m_scroll->get_vadjustment();
|
||||
v->signal_value_changed().connect([this, v] {
|
||||
m_should_scroll_to_bottom = v->get_upper() - v->get_page_size() <= v->get_value();
|
||||
});
|
||||
|
||||
m_scroll->set_can_focus(false);
|
||||
m_scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
|
||||
m_scroll->show();
|
||||
|
||||
m_list->signal_size_allocate().connect([this](Gtk::Allocation &) {
|
||||
if (m_should_scroll_to_bottom)
|
||||
ScrollToBottom();
|
||||
});
|
||||
|
||||
m_list->set_selection_mode(Gtk::SELECTION_NONE);
|
||||
m_list->set_hexpand(true);
|
||||
m_list->set_vexpand(true);
|
||||
m_list->set_focus_hadjustment(m_scroll->get_hadjustment());
|
||||
m_list->set_focus_vadjustment(m_scroll->get_vadjustment());
|
||||
m_list->show();
|
||||
|
||||
m_input->signal_submit().connect(sigc::mem_fun(*this, &ChatWindow::OnInputSubmit));
|
||||
m_input->signal_escape().connect([this]() {
|
||||
if (m_is_replying)
|
||||
StopReplying();
|
||||
});
|
||||
m_input->signal_key_press_event().connect(sigc::mem_fun(*this, &ChatWindow::OnKeyPressEvent), false);
|
||||
m_input->show();
|
||||
|
||||
m_completer.SetBuffer(m_input->GetBuffer());
|
||||
m_completer.SetGetChannelID([this]() -> auto {
|
||||
return m_active_channel;
|
||||
});
|
||||
|
||||
m_completer.SetGetRecentAuthors([this]() -> auto {
|
||||
const auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
std::vector<Snowflake> ret;
|
||||
|
||||
std::map<Snowflake, Gtk::Widget *> ordered(m_id_to_widget.begin(), m_id_to_widget.end());
|
||||
|
||||
for (auto it = ordered.crbegin(); it != ordered.crend(); it++) {
|
||||
const auto *widget = dynamic_cast<ChatMessageItemContainer *>(it->second);
|
||||
if (widget == nullptr) continue;
|
||||
const auto msg = discord.GetMessage(widget->ID);
|
||||
if (!msg.has_value()) continue;
|
||||
if (std::find(ret.begin(), ret.end(), msg->Author.ID) == ret.end())
|
||||
ret.push_back(msg->Author.ID);
|
||||
}
|
||||
|
||||
const auto chan = discord.GetChannel(m_active_channel);
|
||||
if (chan->GuildID.has_value()) {
|
||||
const auto others = discord.GetUsersInGuild(*chan->GuildID);
|
||||
for (const auto id : others)
|
||||
if (std::find(ret.begin(), ret.end(), id) == ret.end())
|
||||
ret.push_back(id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
});
|
||||
|
||||
m_completer.show();
|
||||
|
||||
m_meta->set_hexpand(true);
|
||||
m_meta->set_halign(Gtk::ALIGN_FILL);
|
||||
m_meta->show();
|
||||
|
||||
m_meta->add(*m_input_indicator);
|
||||
m_meta->add(*m_rate_limit_indicator);
|
||||
m_scroll->add(*m_list);
|
||||
m_main->add(*m_scroll);
|
||||
m_main->add(m_completer);
|
||||
m_main->add(*m_input);
|
||||
m_main->add(*m_meta);
|
||||
m_main->show();
|
||||
}
|
||||
|
||||
Gtk::Widget *ChatWindow::GetRoot() const {
|
||||
return m_main;
|
||||
}
|
||||
|
||||
void ChatWindow::Clear() {
|
||||
SetMessages(std::set<Snowflake>());
|
||||
}
|
||||
|
||||
void ChatWindow::SetMessages(const std::set<Snowflake> &msgs) {
|
||||
// empty the listbox
|
||||
auto children = m_list->get_children();
|
||||
auto it = children.begin();
|
||||
while (it != children.end()) {
|
||||
delete *it;
|
||||
it++;
|
||||
}
|
||||
|
||||
m_num_rows = 0;
|
||||
m_num_messages = 0;
|
||||
m_id_to_widget.clear();
|
||||
|
||||
for (const auto &id : msgs) {
|
||||
ProcessNewMessage(id, false);
|
||||
}
|
||||
}
|
||||
|
||||
void ChatWindow::SetActiveChannel(Snowflake id) {
|
||||
m_active_channel = id;
|
||||
m_input_indicator->SetActiveChannel(id);
|
||||
m_rate_limit_indicator->SetActiveChannel(id);
|
||||
if (m_is_replying)
|
||||
StopReplying();
|
||||
}
|
||||
|
||||
void ChatWindow::AddNewMessage(Snowflake id) {
|
||||
ProcessNewMessage(id, false);
|
||||
}
|
||||
|
||||
void ChatWindow::DeleteMessage(Snowflake id) {
|
||||
auto widget = m_id_to_widget.find(id);
|
||||
if (widget == m_id_to_widget.end()) return;
|
||||
|
||||
auto *x = dynamic_cast<ChatMessageItemContainer *>(widget->second);
|
||||
if (x != nullptr)
|
||||
x->UpdateAttributes();
|
||||
}
|
||||
|
||||
void ChatWindow::UpdateMessage(Snowflake id) {
|
||||
auto widget = m_id_to_widget.find(id);
|
||||
if (widget == m_id_to_widget.end()) return;
|
||||
|
||||
auto *x = dynamic_cast<ChatMessageItemContainer *>(widget->second);
|
||||
if (x != nullptr) {
|
||||
x->UpdateContent();
|
||||
x->UpdateAttributes();
|
||||
}
|
||||
}
|
||||
|
||||
void ChatWindow::AddNewHistory(const std::vector<Snowflake> &id) {
|
||||
std::set<Snowflake> ids(id.begin(), id.end());
|
||||
for (auto it = ids.rbegin(); it != ids.rend(); it++)
|
||||
ProcessNewMessage(*it, true);
|
||||
}
|
||||
|
||||
void ChatWindow::InsertChatInput(std::string text) {
|
||||
m_input->InsertText(text);
|
||||
}
|
||||
|
||||
Snowflake ChatWindow::GetOldestListedMessage() {
|
||||
return m_id_to_widget.begin()->first;
|
||||
}
|
||||
|
||||
void ChatWindow::UpdateReactions(Snowflake id) {
|
||||
auto it = m_id_to_widget.find(id);
|
||||
if (it == m_id_to_widget.end()) return;
|
||||
auto *widget = dynamic_cast<ChatMessageItemContainer *>(it->second);
|
||||
if (widget == nullptr) return;
|
||||
widget->UpdateReactions();
|
||||
}
|
||||
|
||||
Snowflake ChatWindow::GetActiveChannel() const {
|
||||
return m_active_channel;
|
||||
}
|
||||
|
||||
bool ChatWindow::OnInputSubmit(const Glib::ustring &text) {
|
||||
if (!m_rate_limit_indicator->CanSpeak())
|
||||
return false;
|
||||
|
||||
if (m_active_channel.IsValid())
|
||||
m_signal_action_chat_submit.emit(text, m_active_channel, m_replying_to); // m_replying_to is checked for invalid in the handler
|
||||
if (m_is_replying)
|
||||
StopReplying();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatWindow::OnKeyPressEvent(GdkEventKey *e) {
|
||||
if (m_completer.ProcessKeyPress(e))
|
||||
return true;
|
||||
|
||||
if (m_input->ProcessKeyPress(e))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ChatMessageItemContainer *ChatWindow::CreateMessageComponent(Snowflake id) {
|
||||
auto *container = ChatMessageItemContainer::FromMessage(id);
|
||||
return container;
|
||||
}
|
||||
|
||||
void ChatWindow::RemoveMessageAndHeader(Gtk::Widget *widget) {
|
||||
ChatMessageHeader *header = dynamic_cast<ChatMessageHeader *>(widget->get_ancestor(Gtk::ListBoxRow::get_type()));
|
||||
if (header != nullptr) {
|
||||
if (header->GetChildContent().size() == 1) {
|
||||
m_num_rows--;
|
||||
delete header;
|
||||
} else
|
||||
delete widget;
|
||||
} else
|
||||
delete widget;
|
||||
m_num_messages--;
|
||||
}
|
||||
|
||||
constexpr static int MaxMessagesForCull = 50; // this has to be 50 cuz that magic number is used in a couple other places and i dont feel like replacing them
|
||||
void ChatWindow::ProcessNewMessage(Snowflake id, bool prepend) {
|
||||
const auto &client = Abaddon::Get().GetDiscordClient();
|
||||
if (!client.IsStarted()) return; // e.g. load channel and then dc
|
||||
const auto data = client.GetMessage(id);
|
||||
if (!data.has_value()) return;
|
||||
|
||||
if (!data->IsPending && data->Nonce.has_value() && data->Author.ID == client.GetUserData().ID) {
|
||||
for (auto [id, widget] : m_id_to_widget) {
|
||||
if (dynamic_cast<ChatMessageItemContainer *>(widget)->Nonce == *data->Nonce) {
|
||||
RemoveMessageAndHeader(widget);
|
||||
m_id_to_widget.erase(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChatMessageHeader *last_row = nullptr;
|
||||
bool should_attach = false;
|
||||
if (m_num_rows > 0) {
|
||||
if (prepend)
|
||||
last_row = dynamic_cast<ChatMessageHeader *>(m_list->get_row_at_index(0));
|
||||
else
|
||||
last_row = dynamic_cast<ChatMessageHeader *>(m_list->get_row_at_index(m_num_rows - 1));
|
||||
|
||||
if (last_row != nullptr) {
|
||||
const uint64_t diff = std::max(id, last_row->NewestID) - std::min(id, last_row->NewestID);
|
||||
if (last_row->UserID == data->Author.ID && (prepend || (diff < SnowflakeSplitDifference * Snowflake::SecondsInterval)))
|
||||
should_attach = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_num_messages++;
|
||||
|
||||
if (m_should_scroll_to_bottom && !prepend)
|
||||
while (m_num_messages > MaxMessagesForCull) {
|
||||
auto first_it = m_id_to_widget.begin();
|
||||
RemoveMessageAndHeader(first_it->second);
|
||||
m_id_to_widget.erase(first_it);
|
||||
}
|
||||
|
||||
ChatMessageHeader *header;
|
||||
if (should_attach) {
|
||||
header = last_row;
|
||||
} else {
|
||||
const auto guild_id = *client.GetChannel(m_active_channel)->GuildID;
|
||||
const auto user_id = data->Author.ID;
|
||||
const auto user = client.GetUser(user_id);
|
||||
if (!user.has_value()) return;
|
||||
|
||||
header = Gtk::manage(new ChatMessageHeader(&*data));
|
||||
header->signal_action_insert_mention().connect([this, user_id]() {
|
||||
m_signal_action_insert_mention.emit(user_id);
|
||||
});
|
||||
|
||||
header->signal_action_open_user_menu().connect([this, user_id, guild_id](const GdkEvent *event) {
|
||||
m_signal_action_open_user_menu.emit(event, user_id, guild_id);
|
||||
});
|
||||
|
||||
m_num_rows++;
|
||||
}
|
||||
|
||||
auto *content = CreateMessageComponent(id);
|
||||
if (content != nullptr) {
|
||||
header->AddContent(content, prepend);
|
||||
m_id_to_widget[id] = content;
|
||||
|
||||
if (!data->IsPending) {
|
||||
content->signal_action_delete().connect([this, id] {
|
||||
m_signal_action_message_delete.emit(m_active_channel, id);
|
||||
});
|
||||
content->signal_action_edit().connect([this, id] {
|
||||
m_signal_action_message_edit.emit(m_active_channel, id);
|
||||
});
|
||||
content->signal_action_reaction_add().connect([this, id](const Glib::ustring ¶m) {
|
||||
m_signal_action_reaction_add.emit(id, param);
|
||||
});
|
||||
content->signal_action_reaction_remove().connect([this, id](const Glib::ustring ¶m) {
|
||||
m_signal_action_reaction_remove.emit(id, param);
|
||||
});
|
||||
content->signal_action_channel_click().connect([this](const Snowflake &id) {
|
||||
m_signal_action_channel_click.emit(id);
|
||||
});
|
||||
content->signal_action_reply_to().connect(sigc::mem_fun(*this, &ChatWindow::StartReplying));
|
||||
}
|
||||
}
|
||||
|
||||
header->set_margin_left(5);
|
||||
header->show_all();
|
||||
|
||||
if (!should_attach) {
|
||||
if (prepend)
|
||||
m_list->prepend(*header);
|
||||
else
|
||||
m_list->add(*header);
|
||||
}
|
||||
}
|
||||
|
||||
void ChatWindow::StartReplying(Snowflake message_id) {
|
||||
const auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
const auto message = *discord.GetMessage(message_id);
|
||||
const auto author = discord.GetUser(message.Author.ID);
|
||||
m_replying_to = message_id;
|
||||
m_is_replying = true;
|
||||
m_input->grab_focus();
|
||||
m_input->get_style_context()->add_class("replying");
|
||||
if (author.has_value())
|
||||
m_input_indicator->SetCustomMarkup("Replying to " + author->GetEscapedBoldString<false>());
|
||||
else
|
||||
m_input_indicator->SetCustomMarkup("Replying...");
|
||||
}
|
||||
|
||||
void ChatWindow::StopReplying() {
|
||||
m_is_replying = false;
|
||||
m_replying_to = Snowflake::Invalid;
|
||||
m_input->get_style_context()->remove_class("replying");
|
||||
m_input_indicator->ClearCustom();
|
||||
}
|
||||
|
||||
void ChatWindow::OnScrollEdgeOvershot(Gtk::PositionType pos) {
|
||||
if (pos == Gtk::POS_TOP)
|
||||
m_signal_action_chat_load_history.emit(m_active_channel);
|
||||
}
|
||||
|
||||
void ChatWindow::ScrollToBottom() {
|
||||
auto x = m_scroll->get_vadjustment();
|
||||
x->set_value(x->get_upper());
|
||||
}
|
||||
|
||||
void ChatWindow::OnMessageSendFail(const std::string &nonce, float retry_after) {
|
||||
for (auto [id, widget] : m_id_to_widget) {
|
||||
if (auto *container = dynamic_cast<ChatMessageItemContainer *>(widget); container->Nonce == nonce) {
|
||||
container->SetFailed();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChatWindow::type_signal_action_message_delete ChatWindow::signal_action_message_delete() {
|
||||
return m_signal_action_message_delete;
|
||||
}
|
||||
|
||||
ChatWindow::type_signal_action_message_edit ChatWindow::signal_action_message_edit() {
|
||||
return m_signal_action_message_edit;
|
||||
}
|
||||
|
||||
ChatWindow::type_signal_action_chat_submit ChatWindow::signal_action_chat_submit() {
|
||||
return m_signal_action_chat_submit;
|
||||
}
|
||||
|
||||
ChatWindow::type_signal_action_chat_load_history ChatWindow::signal_action_chat_load_history() {
|
||||
return m_signal_action_chat_load_history;
|
||||
}
|
||||
|
||||
ChatWindow::type_signal_action_channel_click ChatWindow::signal_action_channel_click() {
|
||||
return m_signal_action_channel_click;
|
||||
}
|
||||
|
||||
ChatWindow::type_signal_action_insert_mention ChatWindow::signal_action_insert_mention() {
|
||||
return m_signal_action_insert_mention;
|
||||
}
|
||||
|
||||
ChatWindow::type_signal_action_open_user_menu ChatWindow::signal_action_open_user_menu() {
|
||||
return m_signal_action_open_user_menu;
|
||||
}
|
||||
|
||||
ChatWindow::type_signal_action_reaction_add ChatWindow::signal_action_reaction_add() {
|
||||
return m_signal_action_reaction_add;
|
||||
}
|
||||
|
||||
ChatWindow::type_signal_action_reaction_remove ChatWindow::signal_action_reaction_remove() {
|
||||
return m_signal_action_reaction_remove;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// for things that are used in stackswitchers to be able to be told when they're switched to
|
||||
|
||||
class INotifySwitched {
|
||||
public:
|
||||
virtual void on_switched_to() {};
|
||||
};
|
@ -1,97 +0,0 @@
|
||||
#include "joinguild.hpp"
|
||||
#include "../abaddon.hpp"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <regex>
|
||||
|
||||
JoinGuildDialog::JoinGuildDialog(Gtk::Window &parent)
|
||||
: Gtk::Dialog("Join Server", parent, true)
|
||||
, m_layout(Gtk::ORIENTATION_VERTICAL)
|
||||
, m_ok("OK")
|
||||
, m_cancel("Cancel")
|
||||
, m_info("Enter code") {
|
||||
set_default_size(300, 50);
|
||||
get_style_context()->add_class("app-window");
|
||||
get_style_context()->add_class("app-popup");
|
||||
|
||||
Glib::signal_idle().connect(sigc::mem_fun(*this, &JoinGuildDialog::on_idle_slot));
|
||||
|
||||
m_entry.signal_changed().connect(sigc::mem_fun(*this, &JoinGuildDialog::on_entry_changed));
|
||||
|
||||
m_ok.set_sensitive(false);
|
||||
|
||||
m_ok.signal_clicked().connect([&]() {
|
||||
response(Gtk::RESPONSE_OK);
|
||||
});
|
||||
|
||||
m_cancel.signal_clicked().connect([&]() {
|
||||
response(Gtk::RESPONSE_CANCEL);
|
||||
});
|
||||
|
||||
m_entry.set_hexpand(true);
|
||||
m_layout.add(m_entry);
|
||||
m_lower.set_hexpand(true);
|
||||
m_lower.pack_start(m_info);
|
||||
m_info.set_halign(Gtk::ALIGN_START);
|
||||
m_lower.pack_start(m_ok, Gtk::PACK_SHRINK);
|
||||
m_lower.pack_start(m_cancel, Gtk::PACK_SHRINK);
|
||||
m_ok.set_halign(Gtk::ALIGN_END);
|
||||
m_cancel.set_halign(Gtk::ALIGN_END);
|
||||
m_layout.add(m_lower);
|
||||
get_content_area()->add(m_layout);
|
||||
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
void JoinGuildDialog::on_entry_changed() {
|
||||
std::string s = m_entry.get_text();
|
||||
std::regex invite_regex(R"((https?:\/\/)?discord\.(gg(\/invite)?\/|com\/invite\/)([A-Za-z0-9\-]+))", std::regex_constants::ECMAScript);
|
||||
std::smatch match;
|
||||
bool full_url = std::regex_search(s, match, invite_regex);
|
||||
if (full_url || IsCode(s)) {
|
||||
m_code = full_url ? match[4].str() : s;
|
||||
m_needs_request = true;
|
||||
m_ok.set_sensitive(false);
|
||||
} else {
|
||||
m_ok.set_sensitive(false);
|
||||
}
|
||||
}
|
||||
|
||||
void JoinGuildDialog::CheckCode() {
|
||||
auto cb = [this](const std::optional<InviteData> &invite) {
|
||||
if (invite.has_value()) {
|
||||
m_ok.set_sensitive(true);
|
||||
if (invite->Guild.has_value()) {
|
||||
if (invite->MemberCount.has_value())
|
||||
m_info.set_text(invite->Guild->Name + " (" + std::to_string(*invite->MemberCount) + " members)");
|
||||
else
|
||||
m_info.set_text(invite->Guild->Name);
|
||||
} else {
|
||||
m_info.set_text("Group DM (" + std::to_string(*invite->MemberCount) + " members)");
|
||||
}
|
||||
} else {
|
||||
m_ok.set_sensitive(false);
|
||||
m_info.set_text("Invalid invite");
|
||||
}
|
||||
};
|
||||
Abaddon::Get().GetDiscordClient().FetchInvite(m_code, sigc::track_obj(cb, *this));
|
||||
}
|
||||
|
||||
bool JoinGuildDialog::IsCode(std::string str) {
|
||||
return str.length() >= 2 && std::all_of(str.begin(), str.end(), [](char c) -> bool { return std::isalnum(c) || c == '-'; });
|
||||
}
|
||||
|
||||
std::string JoinGuildDialog::GetCode() {
|
||||
return m_code;
|
||||
}
|
||||
|
||||
static const constexpr int RateLimitMS = 1500;
|
||||
bool JoinGuildDialog::on_idle_slot() {
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
if (m_needs_request && ((now - m_last_req_time) > std::chrono::milliseconds(RateLimitMS))) {
|
||||
m_needs_request = false;
|
||||
m_last_req_time = now;
|
||||
CheckCode();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
#pragma once
|
||||
#include <gtkmm.h>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
|
||||
class JoinGuildDialog : public Gtk::Dialog {
|
||||
public:
|
||||
JoinGuildDialog(Gtk::Window &parent);
|
||||
std::string GetCode();
|
||||
|
||||
protected:
|
||||
void on_entry_changed();
|
||||
bool IsCode(std::string str);
|
||||
|
||||
Gtk::Box m_layout;
|
||||
Gtk::Button m_ok;
|
||||
Gtk::Button m_cancel;
|
||||
Gtk::Box m_lower;
|
||||
Gtk::Label m_info;
|
||||
Gtk::Entry m_entry;
|
||||
|
||||
void CheckCode();
|
||||
|
||||
// needs a rate limit cuz if u hit it u get ip banned from /invites for a long time :(
|
||||
bool m_needs_request = false;
|
||||
std::chrono::time_point<std::chrono::steady_clock> m_last_req_time;
|
||||
bool on_idle_slot();
|
||||
|
||||
private:
|
||||
std::string m_code;
|
||||
};
|
@ -1,67 +0,0 @@
|
||||
#include "../abaddon.hpp"
|
||||
#include "channel.hpp"
|
||||
|
||||
void from_json(const nlohmann::json &j, ChannelData &m) {
|
||||
JS_D("id", m.ID);
|
||||
JS_D("type", m.Type);
|
||||
JS_O("guild_id", m.GuildID);
|
||||
JS_O("position", m.Position);
|
||||
JS_O("permission_overwrites", m.PermissionOverwrites);
|
||||
JS_ON("name", m.Name);
|
||||
JS_ON("topic", m.Topic);
|
||||
JS_O("nsfw", m.IsNSFW);
|
||||
JS_ON("last_message_id", m.LastMessageID);
|
||||
JS_O("bitrate", m.Bitrate);
|
||||
JS_O("user_limit", m.UserLimit);
|
||||
JS_O("rate_limit_per_user", m.RateLimitPerUser);
|
||||
JS_O("recipients", m.Recipients);
|
||||
JS_O("recipient_ids", m.RecipientIDs);
|
||||
JS_ON("icon", m.Icon);
|
||||
JS_O("owner_id", m.OwnerID);
|
||||
JS_O("application_id", m.ApplicationID);
|
||||
JS_ON("parent_id", m.ParentID);
|
||||
JS_ON("last_pin_timestamp", m.LastPinTimestamp);
|
||||
}
|
||||
|
||||
void ChannelData::update_from_json(const nlohmann::json &j) {
|
||||
JS_RD("type", Type);
|
||||
JS_RD("guild_id", GuildID);
|
||||
JS_RV("position", Position, -1);
|
||||
JS_RD("permission_overwrites", PermissionOverwrites);
|
||||
JS_RD("name", Name);
|
||||
JS_RD("topic", Topic);
|
||||
JS_RD("nsfw", IsNSFW);
|
||||
JS_RD("last_message_id", LastMessageID);
|
||||
JS_RD("bitrate", Bitrate);
|
||||
JS_RD("user_limit", UserLimit);
|
||||
JS_RD("rate_limit_per_user", RateLimitPerUser);
|
||||
JS_RD("recipients", Recipients);
|
||||
JS_RD("icon", Icon);
|
||||
JS_RD("owner_id", OwnerID);
|
||||
JS_RD("application_id", ApplicationID);
|
||||
JS_RD("parent_id", ParentID);
|
||||
JS_RD("last_pin_timestamp", LastPinTimestamp);
|
||||
}
|
||||
|
||||
std::optional<PermissionOverwrite> ChannelData::GetOverwrite(Snowflake id) const {
|
||||
return Abaddon::Get().GetDiscordClient().GetPermissionOverwrite(ID, id);
|
||||
}
|
||||
|
||||
std::vector<UserData> ChannelData::GetDMRecipients() const {
|
||||
const auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
if (Recipients.has_value())
|
||||
return *Recipients;
|
||||
|
||||
if (RecipientIDs.has_value()) {
|
||||
std::vector<UserData> ret;
|
||||
for (const auto &id : *RecipientIDs) {
|
||||
auto user = discord.GetUser(id);
|
||||
if (user.has_value())
|
||||
ret.push_back(std::move(*user));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return std::vector<UserData>();
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
#pragma once
|
||||
#include "snowflake.hpp"
|
||||
#include "json.hpp"
|
||||
#include "user.hpp"
|
||||
#include "permissions.hpp"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
enum class ChannelType : int {
|
||||
GUILD_TEXT = 0,
|
||||
DM = 1,
|
||||
GUILD_VOICE = 2,
|
||||
GROUP_DM = 3,
|
||||
GUILD_CATEGORY = 4,
|
||||
GUILD_NEWS = 5,
|
||||
GUILD_STORE = 6,
|
||||
/* 7 and 8 were used for LFG */
|
||||
/* 9 and 10 were used for threads */
|
||||
PUBLIC_THREAD = 11,
|
||||
PRIVATE_THREAD = 12,
|
||||
GUILD_STAGE_VOICE = 13,
|
||||
};
|
||||
|
||||
struct ChannelData {
|
||||
Snowflake ID;
|
||||
ChannelType Type;
|
||||
std::optional<Snowflake> GuildID;
|
||||
std::optional<int> Position;
|
||||
std::optional<std::vector<PermissionOverwrite>> PermissionOverwrites; // shouldnt be accessed
|
||||
std::optional<std::string> Name; // null for dm's
|
||||
std::optional<std::string> Topic; // null
|
||||
std::optional<bool> IsNSFW;
|
||||
std::optional<Snowflake> LastMessageID; // null
|
||||
std::optional<int> Bitrate;
|
||||
std::optional<int> UserLimit;
|
||||
std::optional<int> RateLimitPerUser;
|
||||
std::optional<std::vector<UserData>> Recipients; // only access id
|
||||
std::optional<std::vector<Snowflake>> RecipientIDs;
|
||||
std::optional<std::string> Icon; // null
|
||||
std::optional<Snowflake> OwnerID;
|
||||
std::optional<Snowflake> ApplicationID;
|
||||
std::optional<Snowflake> ParentID; // null
|
||||
std::optional<std::string> LastPinTimestamp; // null
|
||||
|
||||
friend void from_json(const nlohmann::json &j, ChannelData &m);
|
||||
void update_from_json(const nlohmann::json &j);
|
||||
|
||||
std::optional<PermissionOverwrite> GetOverwrite(Snowflake id) const;
|
||||
std::vector<UserData> GetDMRecipients() const;
|
||||
};
|
@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <glibmm.h>
|
||||
#include "../http.hpp"
|
||||
|
||||
class HTTPClient {
|
||||
public:
|
||||
HTTPClient(std::string api_base);
|
||||
|
||||
void SetUserAgent(std::string agent);
|
||||
void SetAuth(std::string auth);
|
||||
void MakeDELETE(const std::string &path, std::function<void(http::response_type r)> cb);
|
||||
void MakeGET(const std::string &path, std::function<void(http::response_type r)> cb);
|
||||
void MakePATCH(const std::string &path, const std::string &payload, std::function<void(http::response_type r)> cb);
|
||||
void MakePOST(const std::string &path, const std::string &payload, std::function<void(http::response_type r)> cb);
|
||||
void MakePUT(const std::string &path, const std::string &payload, std::function<void(http::response_type r)> cb);
|
||||
|
||||
private:
|
||||
void OnResponse(const http::response_type &r, std::function<void(http::response_type r)> cb);
|
||||
void CleanupFutures();
|
||||
|
||||
mutable std::mutex m_mutex;
|
||||
Glib::Dispatcher m_dispatcher;
|
||||
std::queue<std::function<void()>> m_queue;
|
||||
void RunCallbacks();
|
||||
|
||||
std::vector<std::future<void>> m_futures;
|
||||
std::string m_api_base;
|
||||
std::string m_authorization;
|
||||
std::string m_agent;
|
||||
};
|
1325
discord/store.cpp
@ -1,160 +0,0 @@
|
||||
#pragma once
|
||||
#include "../util.hpp"
|
||||
#include "objects.hpp"
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <mutex>
|
||||
#include <filesystem>
|
||||
#include <sqlite3.h>
|
||||
|
||||
#ifdef GetMessage // fuck you windows.h
|
||||
#undef GetMessage
|
||||
#endif
|
||||
|
||||
class Store {
|
||||
public:
|
||||
Store(bool mem_store = false);
|
||||
~Store();
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
void SetUser(Snowflake id, const UserData &user);
|
||||
void SetChannel(Snowflake id, const ChannelData &chan);
|
||||
void SetGuild(Snowflake id, const GuildData &guild);
|
||||
void SetRole(Snowflake id, const RoleData &role);
|
||||
void SetMessage(Snowflake id, const Message &message);
|
||||
void SetGuildMember(Snowflake guild_id, Snowflake user_id, const GuildMember &data);
|
||||
void SetPermissionOverwrite(Snowflake channel_id, Snowflake id, const PermissionOverwrite &perm);
|
||||
void SetEmoji(Snowflake id, const EmojiData &emoji);
|
||||
void SetBan(Snowflake guild_id, Snowflake user_id, const BanData &ban);
|
||||
|
||||
// slap const on everything even tho its not *really* const
|
||||
|
||||
std::optional<ChannelData> GetChannel(Snowflake id) const;
|
||||
std::optional<EmojiData> GetEmoji(Snowflake id) const;
|
||||
std::optional<GuildData> GetGuild(Snowflake id) const;
|
||||
std::optional<GuildMember> GetGuildMember(Snowflake guild_id, Snowflake user_id) const;
|
||||
std::optional<Message> GetMessage(Snowflake id) const;
|
||||
std::optional<PermissionOverwrite> GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const;
|
||||
std::optional<RoleData> GetRole(Snowflake id) const;
|
||||
std::optional<UserData> GetUser(Snowflake id) const;
|
||||
std::optional<BanData> GetBan(Snowflake guild_id, Snowflake user_id) const;
|
||||
std::vector<BanData> GetBans(Snowflake guild_id) const;
|
||||
|
||||
void ClearGuild(Snowflake id);
|
||||
void ClearChannel(Snowflake id);
|
||||
void ClearBan(Snowflake guild_id, Snowflake user_id);
|
||||
|
||||
using users_type = std::unordered_map<Snowflake, UserData>;
|
||||
using channels_type = std::unordered_map<Snowflake, ChannelData>;
|
||||
using guilds_type = std::unordered_map<Snowflake, GuildData>;
|
||||
using roles_type = std::unordered_map<Snowflake, RoleData>;
|
||||
using messages_type = std::unordered_map<Snowflake, Message>;
|
||||
using members_type = std::unordered_map<Snowflake, std::unordered_map<Snowflake, GuildMember>>; // [guild][user]
|
||||
using permission_overwrites_type = std::unordered_map<Snowflake, std::unordered_map<Snowflake, PermissionOverwrite>>; // [channel][user/role]
|
||||
using emojis_type = std::unordered_map<Snowflake, EmojiData>;
|
||||
|
||||
const std::unordered_set<Snowflake> &GetChannels() const;
|
||||
const std::unordered_set<Snowflake> &GetGuilds() const;
|
||||
|
||||
void ClearAll();
|
||||
|
||||
void BeginTransaction();
|
||||
void EndTransaction();
|
||||
|
||||
private:
|
||||
void SetMessageInteractionPair(Snowflake message_id, const MessageInteractionData &interaction);
|
||||
|
||||
std::unordered_set<Snowflake> m_channels;
|
||||
std::unordered_set<Snowflake> m_guilds;
|
||||
|
||||
bool CreateTables();
|
||||
bool CreateStatements();
|
||||
void Cleanup();
|
||||
|
||||
template<typename T>
|
||||
void Bind(sqlite3_stmt *stmt, int index, const std::optional<T> &opt) const;
|
||||
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_enum<T>::value, void>::type
|
||||
Bind(sqlite3_stmt *stmt, int index, T val) const;
|
||||
|
||||
void Bind(sqlite3_stmt *stmt, int index, int num) const;
|
||||
void Bind(sqlite3_stmt *stmt, int index, uint64_t num) const;
|
||||
void Bind(sqlite3_stmt *stmt, int index, const std::string &str) const;
|
||||
void Bind(sqlite3_stmt *stmt, int index, bool val) const;
|
||||
void Bind(sqlite3_stmt *stmt, int index, std::nullptr_t) const;
|
||||
bool RunInsert(sqlite3_stmt *stmt);
|
||||
bool FetchOne(sqlite3_stmt *stmt) const;
|
||||
|
||||
template<typename T>
|
||||
void Get(sqlite3_stmt *stmt, int index, std::optional<T> &out) const;
|
||||
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_enum<T>::value, void>::type
|
||||
Get(sqlite3_stmt *stmt, int index, T &out) const;
|
||||
|
||||
void Get(sqlite3_stmt *stmt, int index, int &out) const;
|
||||
void Get(sqlite3_stmt *stmt, int index, uint64_t &out) const;
|
||||
void Get(sqlite3_stmt *stmt, int index, std::string &out) const;
|
||||
void Get(sqlite3_stmt *stmt, int index, bool &out) const;
|
||||
void Get(sqlite3_stmt *stmt, int index, Snowflake &out) const;
|
||||
bool IsNull(sqlite3_stmt *stmt, int index) const;
|
||||
void Reset(sqlite3_stmt *stmt) const;
|
||||
|
||||
std::filesystem::path m_db_path;
|
||||
mutable sqlite3 *m_db;
|
||||
mutable int m_db_err;
|
||||
mutable sqlite3_stmt *m_set_user_stmt;
|
||||
mutable sqlite3_stmt *m_get_user_stmt;
|
||||
mutable sqlite3_stmt *m_set_perm_stmt;
|
||||
mutable sqlite3_stmt *m_get_perm_stmt;
|
||||
mutable sqlite3_stmt *m_set_msg_stmt;
|
||||
mutable sqlite3_stmt *m_get_msg_stmt;
|
||||
mutable sqlite3_stmt *m_set_role_stmt;
|
||||
mutable sqlite3_stmt *m_get_role_stmt;
|
||||
mutable sqlite3_stmt *m_set_emote_stmt;
|
||||
mutable sqlite3_stmt *m_get_emote_stmt;
|
||||
mutable sqlite3_stmt *m_set_member_stmt;
|
||||
mutable sqlite3_stmt *m_get_member_stmt;
|
||||
mutable sqlite3_stmt *m_set_guild_stmt;
|
||||
mutable sqlite3_stmt *m_get_guild_stmt;
|
||||
mutable sqlite3_stmt *m_set_chan_stmt;
|
||||
mutable sqlite3_stmt *m_get_chan_stmt;
|
||||
mutable sqlite3_stmt *m_set_ban_stmt;
|
||||
mutable sqlite3_stmt *m_get_ban_stmt;
|
||||
mutable sqlite3_stmt *m_clear_ban_stmt;
|
||||
mutable sqlite3_stmt *m_get_bans_stmt;
|
||||
mutable sqlite3_stmt *m_set_msg_interaction_stmt;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline void Store::Bind(sqlite3_stmt *stmt, int index, const std::optional<T> &opt) const {
|
||||
if (opt.has_value())
|
||||
Bind(stmt, index, *opt);
|
||||
else
|
||||
sqlite3_bind_null(stmt, index);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline typename std::enable_if<std::is_enum<T>::value, void>::type
|
||||
Store::Bind(sqlite3_stmt *stmt, int index, T val) const {
|
||||
Bind(stmt, index, static_cast<typename std::underlying_type<T>::type>(val));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void Store::Get(sqlite3_stmt *stmt, int index, std::optional<T> &out) const {
|
||||
if (sqlite3_column_type(stmt, index) == SQLITE_NULL)
|
||||
out = std::nullopt;
|
||||
else {
|
||||
T v;
|
||||
Get(stmt, index, v);
|
||||
out = std::optional<T>(v);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline typename std::enable_if<std::is_enum<T>::value, void>::type
|
||||
Store::Get(sqlite3_stmt *stmt, int index, T &out) const {
|
||||
out = static_cast<T>(sqlite3_column_int(stmt, index));
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
#include "usersettings.hpp"
|
||||
|
||||
void from_json(const nlohmann::json &j, UserSettingsGuildFoldersEntry &m) {
|
||||
JS_N("color", m.Color);
|
||||
JS_D("guild_ids", m.GuildIDs);
|
||||
JS_N("id", m.ID);
|
||||
JS_N("name", m.Name);
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, UserSettings &m) {
|
||||
JS_D("timezone_offset", m.TimezoneOffset);
|
||||
JS_D("theme", m.Theme);
|
||||
JS_D("stream_notifications_enabled", m.AreStreamNotificationsEnabled);
|
||||
JS_D("status", m.Status);
|
||||
JS_D("show_current_game", m.ShouldShowCurrentGame);
|
||||
// JS_D("restricted_guilds", m.RestrictedGuilds);
|
||||
JS_D("render_reactions", m.ShouldRenderReactions);
|
||||
JS_D("render_embeds", m.ShouldRenderEmbeds);
|
||||
JS_D("native_phone_integration_enabled", m.IsNativePhoneIntegrationEnabled);
|
||||
JS_D("message_display_compact", m.ShouldMessageDisplayCompact);
|
||||
JS_D("locale", m.Locale);
|
||||
JS_D("inline_embed_media", m.ShouldInlineEmbedMedia);
|
||||
JS_D("inline_attachment_media", m.ShouldInlineAttachmentMedia);
|
||||
JS_D("guild_positions", m.GuildPositions);
|
||||
JS_D("guild_folders", m.GuildFolders);
|
||||
JS_D("gif_auto_play", m.ShouldGIFAutoplay);
|
||||
// JS_D("friend_source_flags", m.FriendSourceFlags);
|
||||
JS_D("explicit_content_filter", m.ExplicitContentFilter);
|
||||
JS_D("enable_tts_command", m.IsTTSCommandEnabled);
|
||||
JS_D("disable_games_tab", m.ShouldDisableGamesTab);
|
||||
JS_D("developer_mode", m.DeveloperMode);
|
||||
JS_D("detect_platform_accounts", m.ShouldDetectPlatformAccounts);
|
||||
JS_D("default_guilds_restricted", m.AreDefaultGuildsRestricted);
|
||||
// JS_N("custom_status", m.CustomStatus);
|
||||
JS_D("convert_emoticons", m.ShouldConvertEmoticons);
|
||||
JS_D("contact_sync_enabled", m.IsContactSyncEnabled);
|
||||
JS_D("animate_emoji", m.ShouldAnimateEmojis);
|
||||
JS_D("allow_accessibility_detection", m.IsAccessibilityDetectionAllowed);
|
||||
JS_D("afk_timeout", m.AFKTimeout);
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
#pragma once
|
||||
#include "json.hpp"
|
||||
#include "snowflake.hpp"
|
||||
#include <string>
|
||||
|
||||
struct UserSettingsGuildFoldersEntry {
|
||||
int Color = -1; // null
|
||||
std::vector<Snowflake> GuildIDs;
|
||||
Snowflake ID; // null (this can be a snowflake as a string or an int that isnt a snowflake lol)
|
||||
std::string Name; // null
|
||||
|
||||
friend void from_json(const nlohmann::json &j, UserSettingsGuildFoldersEntry &m);
|
||||
};
|
||||
|
||||
struct UserSettings {
|
||||
int TimezoneOffset; //
|
||||
std::string Theme; //
|
||||
bool AreStreamNotificationsEnabled; //
|
||||
std::string Status; //
|
||||
bool ShouldShowCurrentGame; //
|
||||
// std::vector<Unknown> RestrictedGuilds; //
|
||||
bool ShouldRenderReactions; //
|
||||
bool ShouldRenderEmbeds; //
|
||||
bool IsNativePhoneIntegrationEnabled; //
|
||||
bool ShouldMessageDisplayCompact; //
|
||||
std::string Locale; //
|
||||
bool ShouldInlineEmbedMedia; //
|
||||
bool ShouldInlineAttachmentMedia; //
|
||||
std::vector<Snowflake> GuildPositions; // deprecated?
|
||||
std::vector<UserSettingsGuildFoldersEntry> GuildFolders; //
|
||||
bool ShouldGIFAutoplay; //
|
||||
// Unknown FriendSourceFlags; //
|
||||
int ExplicitContentFilter; //
|
||||
bool IsTTSCommandEnabled; //
|
||||
bool ShouldDisableGamesTab; //
|
||||
bool DeveloperMode; //
|
||||
bool ShouldDetectPlatformAccounts; //
|
||||
bool AreDefaultGuildsRestricted; //
|
||||
// Unknown CustomStatus; // null
|
||||
bool ShouldConvertEmoticons; //
|
||||
bool IsContactSyncEnabled; //
|
||||
bool ShouldAnimateEmojis; //
|
||||
bool IsAccessibilityDetectionAllowed; //
|
||||
int AFKTimeout;
|
||||
|
||||
friend void from_json(const nlohmann::json &j, UserSettings &m);
|
||||
};
|
121
http.cpp
@ -1,121 +0,0 @@
|
||||
#include "http.hpp"
|
||||
|
||||
namespace http {
|
||||
request::request(EMethod method, const std::string &url)
|
||||
: m_url(url) {
|
||||
switch (method) {
|
||||
case REQUEST_GET:
|
||||
m_method = "GET";
|
||||
break;
|
||||
case REQUEST_POST:
|
||||
m_method = "POST";
|
||||
break;
|
||||
case REQUEST_PATCH:
|
||||
m_method = "PATCH";
|
||||
break;
|
||||
case REQUEST_PUT:
|
||||
m_method = "PUT";
|
||||
break;
|
||||
case REQUEST_DELETE:
|
||||
m_method = "DELETE";
|
||||
break;
|
||||
default:
|
||||
m_method = "GET";
|
||||
break;
|
||||
}
|
||||
|
||||
prepare();
|
||||
}
|
||||
|
||||
request::~request() {
|
||||
if (m_curl != nullptr)
|
||||
curl_easy_cleanup(m_curl);
|
||||
|
||||
if (m_header_list != nullptr)
|
||||
curl_slist_free_all(m_header_list);
|
||||
}
|
||||
|
||||
void request::set_verify_ssl(bool verify) {
|
||||
curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYPEER, verify ? 1L : 0L);
|
||||
}
|
||||
|
||||
void request::set_proxy(const std::string &proxy) {
|
||||
curl_easy_setopt(m_curl, CURLOPT_PROXY, proxy.c_str());
|
||||
}
|
||||
|
||||
void request::set_header(const std::string &name, const std::string &value) {
|
||||
m_header_list = curl_slist_append(m_header_list, (name + ": " + value).c_str());
|
||||
}
|
||||
|
||||
void request::set_body(const std::string &data) {
|
||||
curl_easy_setopt(m_curl, CURLOPT_COPYPOSTFIELDS, data.c_str());
|
||||
}
|
||||
|
||||
void request::set_user_agent(const std::string &data) {
|
||||
curl_easy_setopt(m_curl, CURLOPT_USERAGENT, data.c_str());
|
||||
}
|
||||
|
||||
response request::execute() {
|
||||
if (m_curl == nullptr) {
|
||||
auto response = detail::make_response(m_url, EStatusCode::ClientErrorCURLInit);
|
||||
response.error_string = "curl pointer is null";
|
||||
}
|
||||
|
||||
detail::check_init();
|
||||
|
||||
std::string str;
|
||||
curl_easy_setopt(m_curl, CURLOPT_CUSTOMREQUEST, m_method);
|
||||
curl_easy_setopt(m_curl, CURLOPT_URL, m_url.c_str());
|
||||
curl_easy_setopt(m_curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, detail::curl_write_data_callback);
|
||||
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &str);
|
||||
curl_easy_setopt(m_curl, CURLOPT_ERRORBUFFER, m_error_buf);
|
||||
if (m_header_list != nullptr)
|
||||
curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, m_header_list);
|
||||
|
||||
CURLcode result = curl_easy_perform(m_curl);
|
||||
if (result != CURLE_OK) {
|
||||
auto response = detail::make_response(m_url, EStatusCode::ClientErrorCURLPerform);
|
||||
response.error_string = curl_easy_strerror(result);
|
||||
response.error_string += " " + std::string(m_error_buf);
|
||||
return response;
|
||||
}
|
||||
|
||||
int response_code = 0;
|
||||
curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &response_code);
|
||||
|
||||
auto response = detail::make_response(m_url, response_code);
|
||||
response.text = str;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
void request::prepare() {
|
||||
m_curl = curl_easy_init();
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
size_t curl_write_data_callback(void *ptr, size_t size, size_t nmemb, std::string *outstr) {
|
||||
auto new_length = size * nmemb;
|
||||
outstr->append(reinterpret_cast<char *>(ptr), new_length);
|
||||
return new_length;
|
||||
}
|
||||
|
||||
response make_response(const std::string &url, int code) {
|
||||
response r;
|
||||
r.url = url;
|
||||
r.status_code = static_cast<EStatusCode>(code);
|
||||
if (code < http::EStatusCode::ClientErrorMax)
|
||||
r.error = true;
|
||||
return r;
|
||||
}
|
||||
|
||||
void check_init() {
|
||||
static bool initialized = false;
|
||||
if (!initialized) {
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace http
|
89
res/css/application-low-priority.css
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
application wide stuff
|
||||
has to be separate to allow main.css to override certain things
|
||||
*/
|
||||
|
||||
.app-window label:not(:disabled) {
|
||||
color: @text_color;
|
||||
}
|
||||
|
||||
.app-window entry {
|
||||
background: @secondary_color;
|
||||
color: @text_color;
|
||||
border: 1px solid #1c2e40;
|
||||
}
|
||||
|
||||
.app-window button {
|
||||
background: @secondary_color;
|
||||
color: @text_color;
|
||||
text-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.app-window button:checked {
|
||||
border-top: 0px;
|
||||
border-left: 0px;
|
||||
border-right: 0px;
|
||||
border-bottom: 3px solid #39a2ed;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.app-window button:not(:checked) {
|
||||
border: 3px #0000ff;
|
||||
}
|
||||
|
||||
.app-window.background {
|
||||
background: @background_color;
|
||||
}
|
||||
|
||||
.app-window treeview {
|
||||
color: @text_color;
|
||||
}
|
||||
|
||||
.app-window treeview:not(:selected) {
|
||||
background: @secondary_color;
|
||||
}
|
||||
|
||||
.app-popup list {
|
||||
background: @secondary_color;
|
||||
}
|
||||
|
||||
.app-window paned separator {
|
||||
background: @background_color;
|
||||
}
|
||||
|
||||
.app-window scrollbar {
|
||||
background: @background_color;
|
||||
border-left: 1px solid transparent;
|
||||
}
|
||||
|
||||
.app-window menubar, menu {
|
||||
background: @background_color;
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
.app-window textview text {
|
||||
caret-color: #ababab;
|
||||
}
|
||||
|
||||
.app-window check,
|
||||
.app-window radio {
|
||||
background-clip: padding-box;
|
||||
background: @secondary_color;
|
||||
border-color: #070707;
|
||||
box-shadow: 0 1px rgba(0, 0, 0, 0);
|
||||
color: #dddddd;
|
||||
}
|
||||
|
||||
.app-window check:checked,
|
||||
.app-window radio:checked {
|
||||
background-clip: border-box;
|
||||
background: #0b4285;
|
||||
border-color: #092444;
|
||||
box-shadow: 0 1px rgba(0, 0, 0, 0);
|
||||
color: #dddddd;
|
||||
}
|
||||
|
||||
.app-window colorswatch {
|
||||
box-shadow: 0 1px rgba(0, 0, 0, 0);
|
||||
}
|
@ -57,14 +57,8 @@
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.message-container + .message-container {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.message-container-extra {
|
||||
color: #78909c;
|
||||
margin-left: -5px;
|
||||
margin-right: -5px;
|
||||
}
|
||||
|
||||
.message-container-timestamp {
|
||||
@ -72,7 +66,8 @@
|
||||
}
|
||||
|
||||
.message-text {
|
||||
padding-top: 5px;
|
||||
/* this isnt stricly necessary but it fixes emoji clipping */
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.message-text:not(.failed) text, .message-reply {
|
||||
@ -106,17 +101,38 @@
|
||||
.message-input, .message-input textview, .message-input textview text {
|
||||
background-color: #242424;
|
||||
color: #adadad;
|
||||
border-radius: 15px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.message-input {
|
||||
border: 1px solid #444444;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.message-input.replying {
|
||||
border: 1px solid #026FB9;
|
||||
}
|
||||
|
||||
.message-input {
|
||||
.message-input.bad-input {
|
||||
border: 1px solid #dd3300;
|
||||
}
|
||||
|
||||
.message-input-browse-icon {
|
||||
color: #b9bbbe;
|
||||
margin-left: 5px;
|
||||
margin-top: 11px;
|
||||
}
|
||||
|
||||
/* i dont think theres a way to circumvent having to do this to adjust around the browse icon */
|
||||
.message-input:not(.with-browser-icon) {
|
||||
padding: 0px 0px 0px 5px;
|
||||
}
|
||||
|
||||
.message-input.with-browse-icon {
|
||||
padding: 0px 0px 0px 30px;
|
||||
}
|
||||
|
||||
.members {
|
||||
background-color: @background_color;
|
||||
}
|
||||
@ -141,6 +157,26 @@
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.message-component {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.message-component.primary {
|
||||
background: #5865F2;
|
||||
}
|
||||
|
||||
.message-component.secondary, .message-component.link {
|
||||
background: #4F545C;
|
||||
}
|
||||
|
||||
.message-component.success {
|
||||
background: #43B581;
|
||||
}
|
||||
|
||||
.message-component.danger {
|
||||
background: #F04747;
|
||||
}
|
||||
|
||||
.reaction-box {
|
||||
padding: 2px 5px 2px 5px;
|
||||
margin: 0px 0px 0px 0px;
|
||||
@ -176,62 +212,6 @@
|
||||
color: @text_color;
|
||||
}
|
||||
|
||||
.app-window label:not(:disabled) {
|
||||
color: @text_color;
|
||||
}
|
||||
|
||||
.app-window entry {
|
||||
background: @secondary_color;
|
||||
color: @text_color;
|
||||
border: 1px solid #1c2e40;
|
||||
}
|
||||
|
||||
.app-window button {
|
||||
background: @secondary_color;
|
||||
color: @text_color;
|
||||
text-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.app-window button:checked {
|
||||
border-top: 0px;
|
||||
border-left: 0px;
|
||||
border-right: 0px;
|
||||
border-bottom: 3px solid #39a2ed;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.app-window button:not(:checked) {
|
||||
border: 3px #0000ff;
|
||||
}
|
||||
|
||||
.app-window.background {
|
||||
background: @background_color;
|
||||
}
|
||||
|
||||
.app-window treeview {
|
||||
color: @text_color;
|
||||
background: @secondary_color;
|
||||
}
|
||||
|
||||
.app-popup list {
|
||||
background: @secondary_color;
|
||||
}
|
||||
|
||||
.app-window paned separator {
|
||||
background: @background_color;
|
||||
}
|
||||
|
||||
.app-window scrollbar {
|
||||
background: @background_color;
|
||||
border-left: 1px solid transparent;
|
||||
}
|
||||
|
||||
.app-window menubar, menu {
|
||||
background: @background_color;
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
.status-indicator.dnd {
|
||||
color: #982929;
|
||||
}
|
||||
@ -303,37 +283,10 @@
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.app-window textview text {
|
||||
caret-color: #ababab;
|
||||
}
|
||||
|
||||
.guild-members-pane-info {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
|
||||
.app-window check,
|
||||
.app-window radio {
|
||||
background-clip: padding-box;
|
||||
background: @secondary_color;
|
||||
border-color: #070707;
|
||||
box-shadow: 0 1px rgba(0, 0, 0, 0);
|
||||
color: #dddddd;
|
||||
}
|
||||
|
||||
.app-window check:checked,
|
||||
.app-window radio:checked {
|
||||
background-clip: border-box;
|
||||
background: #0b4285;
|
||||
border-color: #092444;
|
||||
box-shadow: 0 1px rgba(0, 0, 0, 0);
|
||||
color: #dddddd;
|
||||
}
|
||||
|
||||
.app-window colorswatch {
|
||||
box-shadow: 0 1px rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.drag-hover-top {
|
||||
background: linear-gradient(to bottom, rgba(255, 66, 66, 0.65) 0%, rgba(0, 0, 0, 0) 35%);
|
||||
}
|
||||
@ -341,3 +294,69 @@
|
||||
.drag-hover-bottom {
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 65%, rgba(255, 66, 66, 0.65) 100%);
|
||||
}
|
||||
|
||||
.friends-list list {
|
||||
background: @background_color;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.friends-list-row-bot {
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
.channel-tab-switcher .box {
|
||||
margin: -7px -1px -7px -1px;
|
||||
background: #2a2a2a;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.channel-tab-switcher tab:hover {
|
||||
box-shadow: inset 0 -6px #17633e;
|
||||
}
|
||||
|
||||
.channel-tab-switcher tab:checked {
|
||||
box-shadow: inset 0 -6px #2feb90;
|
||||
}
|
||||
|
||||
.channel-tab-switcher tab {
|
||||
background: #1A1A1A;
|
||||
border: 1px solid #808080;
|
||||
min-height: 35px;
|
||||
}
|
||||
|
||||
.channel-tab-switcher tab.needs-attention:not(:checked) {
|
||||
font-weight: bold;
|
||||
animation: 150ms ease-in;
|
||||
/* background-image: radial-gradient(ellipse at bottom, #FF5370, #1A1A1A 30%); */
|
||||
box-shadow: inset 0 -6px red;
|
||||
}
|
||||
|
||||
.channel-tab-switcher tab > button {
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 5px;
|
||||
min-width: 16px;
|
||||
min-height: 16px;
|
||||
color: #FF5370;
|
||||
background-color: rgba(0.21, 0.21, 0.21, 0.5);
|
||||
}
|
||||
|
||||
.channel-tab-switcher tab > button:hover {
|
||||
background-color: alpha(#ff0000, 0.5);
|
||||
}
|
||||
|
||||
.message-progress {
|
||||
border: none;
|
||||
margin-bottom: -8px;
|
||||
}
|
||||
|
||||
.message-progress trough {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.message-progress progress {
|
||||
border: none;
|
||||
background-color: #dd3300;
|
||||
margin-left: 1px;
|
||||
}
|
BIN
res/fonts/TwitterColorEmoji.ttf
Normal file
14
res/fonts/conf.d/10-autohint.conf
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!-- Use the Autohinter -->
|
||||
<match target="pattern">
|
||||
<!--
|
||||
This configuration is available on the major desktop environments.
|
||||
We shouldn't overwrite it with "assign" unconditionally.
|
||||
Most clients may picks up the first value only. so using "append"
|
||||
may simply works to avoid it.
|
||||
-->
|
||||
<edit name="autohint" mode="append"><bool>true</bool></edit>
|
||||
</match>
|
||||
</fontconfig>
|
13
res/fonts/conf.d/10-hinting-full.conf
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<match target="pattern">
|
||||
<!--
|
||||
This configuration is available on the major desktop environments.
|
||||
We shouldn't overwrite it with "assign" unconditionally.
|
||||
Most clients may picks up the first value only. so using "append"
|
||||
may simply works to avoid it.
|
||||
-->
|
||||
<edit name="hintstyle" mode="append"><const>hintfull</const></edit>
|
||||
</match>
|
||||
</fontconfig>
|
13
res/fonts/conf.d/10-hinting-medium.conf
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<match target="pattern">
|
||||
<!--
|
||||
This configuration is available on the major desktop environments.
|
||||
We shouldn't overwrite it with "assign" unconditionally.
|
||||
Most clients may picks up the first value only. so using "append"
|
||||
may simply works to avoid it.
|
||||
-->
|
||||
<edit name="hintstyle" mode="append"><const>hintmedium</const></edit>
|
||||
</match>
|
||||
</fontconfig>
|
13
res/fonts/conf.d/10-hinting-none.conf
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<match target="pattern">
|
||||
<!--
|
||||
This configuration is available on the major desktop environments.
|
||||
We shouldn't overwrite it with "assign" unconditionally.
|
||||
Most clients may picks up the first value only. so using "append"
|
||||
may simply works to avoid it.
|
||||
-->
|
||||
<edit name="hintstyle" mode="append"><const>hintnone</const></edit>
|
||||
</match>
|
||||
</fontconfig>
|
13
res/fonts/conf.d/10-hinting-slight.conf
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<match target="pattern">
|
||||
<!--
|
||||
This configuration is available on the major desktop environments.
|
||||
We shouldn't overwrite it with "assign" unconditionally.
|
||||
Most clients may picks up the first value only. so using "append"
|
||||
may simply works to avoid it.
|
||||
-->
|
||||
<edit name="hintstyle" mode="append"><const>hintslight</const></edit>
|
||||
</match>
|
||||
</fontconfig>
|
14
res/fonts/conf.d/10-no-sub-pixel.conf
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!-- Disable sub-pixel rendering -->
|
||||
<match target="pattern">
|
||||
<!--
|
||||
This configuration is available on the major desktop environments.
|
||||
We shouldn't overwrite it with "assign" unconditionally.
|
||||
Most clients may picks up the first value only. so using "append"
|
||||
may simply works to avoid it.
|
||||
-->
|
||||
<edit name="rgba" mode="append"><const>none</const></edit>
|
||||
</match>
|
||||
</fontconfig>
|
80
res/fonts/conf.d/10-scale-bitmap-fonts.conf
Normal file
@ -0,0 +1,80 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
|
||||
<!--
|
||||
If font is bitmap, calculate scale factor.
|
||||
Note that color bitmap fonts have scalable=true, while
|
||||
non-color ones have scalable=false. Both groups have outline=false.
|
||||
-->
|
||||
<match target="font">
|
||||
<test name="outline" compare="eq">
|
||||
<bool>false</bool>
|
||||
</test>
|
||||
<edit name="pixelsizefixupfactor" mode="assign">
|
||||
<double>0.15</double>
|
||||
</edit>
|
||||
</match>
|
||||
<!--
|
||||
For non-scalable bitmap fonts (ie. non-color), skip
|
||||
minor scaling if hinting is enabled.
|
||||
-->
|
||||
<match target="font">
|
||||
<test name="outline" compare="eq">
|
||||
<bool>false</bool>
|
||||
</test>
|
||||
<test name="scalable" compare="eq">
|
||||
<bool>false</bool>
|
||||
</test>
|
||||
<test name="hinting" compare="eq">
|
||||
<bool>true</bool>
|
||||
</test>
|
||||
<edit name="scalingnotneeded" mode="assign">
|
||||
<and>
|
||||
<less>
|
||||
<name>pixelsizefixupfactor</name>
|
||||
<double>1.2</double>
|
||||
</less>
|
||||
<more>
|
||||
<name>pixelsizefixupfactor</name>
|
||||
<double>0.8</double>
|
||||
</more>
|
||||
</and>
|
||||
</edit>
|
||||
</match>
|
||||
<match target="font">
|
||||
<test name="scalingnotneeded" compare="eq">
|
||||
<bool>true</bool>
|
||||
</test>
|
||||
<edit name="pixelsizefixupfactor" mode="assign">
|
||||
<double>1.0</double>
|
||||
</edit>
|
||||
</match>
|
||||
<!--
|
||||
If we *are* going to scale, go ahead and do it.
|
||||
-->
|
||||
<match target="font">
|
||||
<test name="outline" compare="eq">
|
||||
<bool>false</bool>
|
||||
</test>
|
||||
<test name="pixelsizefixupfactor" compare="not_eq">
|
||||
<double>1.0</double>
|
||||
</test>
|
||||
<edit name="matrix" mode="assign">
|
||||
<times>
|
||||
<name>matrix</name>
|
||||
<matrix>
|
||||
<name>pixelsizefixupfactor</name> <double>0</double>
|
||||
<double>0</double> <name>pixelsizefixupfactor</name>
|
||||
</matrix>
|
||||
</times>
|
||||
</edit>
|
||||
<edit name="size" mode="assign">
|
||||
<divide>
|
||||
<name>size</name>
|
||||
<name>pixelsizefixupfactor</name>
|
||||
</divide>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
</fontconfig>
|
14
res/fonts/conf.d/10-sub-pixel-bgr.conf
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!-- Enable sub-pixel rendering -->
|
||||
<match target="pattern">
|
||||
<!--
|
||||
This configuration is available on the major desktop environments.
|
||||
We shouldn't overwrite it with "assign" unconditionally.
|
||||
Most clients may picks up the first value only. so using "append"
|
||||
may simply works to avoid it.
|
||||
-->
|
||||
<edit name="rgba" mode="append"><const>bgr</const></edit>
|
||||
</match>
|
||||
</fontconfig>
|
14
res/fonts/conf.d/10-sub-pixel-rgb.conf
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!-- Enable sub-pixel rendering -->
|
||||
<match target="pattern">
|
||||
<!--
|
||||
This configuration is available on the major desktop environments.
|
||||
We shouldn't overwrite it with "assign" unconditionally.
|
||||
Most clients may picks up the first value only. so using "append"
|
||||
may simply works to avoid it.
|
||||
-->
|
||||
<edit name="rgba" mode="append"><const>rgb</const></edit>
|
||||
</match>
|
||||
</fontconfig>
|
14
res/fonts/conf.d/10-sub-pixel-vbgr.conf
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!-- Enable sub-pixel rendering -->
|
||||
<match target="pattern">
|
||||
<!--
|
||||
This configuration is available on the major desktop environments.
|
||||
We shouldn't overwrite it with "assign" unconditionally.
|
||||
Most clients may picks up the first value only. so using "append"
|
||||
may simply works to avoid it.
|
||||
-->
|
||||
<edit name="rgba" mode="append"><const>vbgr</const></edit>
|
||||
</match>
|
||||
</fontconfig>
|
14
res/fonts/conf.d/10-sub-pixel-vrgb.conf
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!-- Enable sub-pixel rendering -->
|
||||
<match target="pattern">
|
||||
<!--
|
||||
This configuration is available on the major desktop environments.
|
||||
We shouldn't overwrite it with "assign" unconditionally.
|
||||
Most clients may picks up the first value only. so using "append"
|
||||
may simply works to avoid it.
|
||||
-->
|
||||
<edit name="rgba" mode="append"><const>vrgb</const></edit>
|
||||
</match>
|
||||
</fontconfig>
|
14
res/fonts/conf.d/10-unhinted.conf
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!-- Disable hinting -->
|
||||
<match target="pattern">
|
||||
<!--
|
||||
This configuration is available on the major desktop environments.
|
||||
We shouldn't overwrite it with "assign" unconditionally.
|
||||
Most clients may picks up the first value only. so using "append"
|
||||
may simply works to avoid it.
|
||||
-->
|
||||
<edit name="hinting" mode="append"><bool>false</bool></edit>
|
||||
</match>
|
||||
</fontconfig>
|
16
res/fonts/conf.d/11-lcdfilter-default.conf
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!-- Use lcddefault as default for LCD filter -->
|
||||
<match target="pattern">
|
||||
<!--
|
||||
This configuration is available on the major desktop environments.
|
||||
We shouldn't overwrite it with "assign" unconditionally.
|
||||
Most clients may picks up the first value only. so using "append"
|
||||
may simply works to avoid it.
|
||||
-->
|
||||
<edit mode="append" name="lcdfilter">
|
||||
<const>lcddefault</const>
|
||||
</edit>
|
||||
</match>
|
||||
</fontconfig>
|
16
res/fonts/conf.d/11-lcdfilter-legacy.conf
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!-- Use lcdlegacy as default for LCD filter -->
|
||||
<match target="pattern">
|
||||
<!--
|
||||
This configuration is available on the major desktop environments.
|
||||
We shouldn't overwrite it with "assign" unconditionally.
|
||||
Most clients may picks up the first value only. so using "append"
|
||||
may simply works to avoid it.
|
||||
-->
|
||||
<edit mode="append" name="lcdfilter">
|
||||
<const>lcdlegacy</const>
|
||||
</edit>
|
||||
</match>
|
||||
</fontconfig>
|
16
res/fonts/conf.d/11-lcdfilter-light.conf
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!-- Use lcdlight as default for LCD filter -->
|
||||
<match target="pattern">
|
||||
<!--
|
||||
This configuration is available on the major desktop environments.
|
||||
We shouldn't overwrite it with "assign" unconditionally.
|
||||
Most clients may picks up the first value only. so using "append"
|
||||
may simply works to avoid it.
|
||||
-->
|
||||
<edit mode="append" name="lcdfilter">
|
||||
<const>lcdlight</const>
|
||||
</edit>
|
||||
</match>
|
||||
</fontconfig>
|
48
res/fonts/conf.d/20-unhint-small-vera.conf
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!--
|
||||
The Bitstream Vera fonts have GASP entries suggesting that hinting be
|
||||
disabled below 8 ppem, but FreeType ignores those, preferring to use
|
||||
the data found in the instructed hints. The initial Vera release
|
||||
didn't include the right instructions in the 'prep' table. Fix this
|
||||
by disabling hinting manually at smaller sizes (< 8ppem)
|
||||
-->
|
||||
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Bitstream Vera Sans</string>
|
||||
</test>
|
||||
<test name="pixelsize" compare="less">
|
||||
<double>7.5</double>
|
||||
</test>
|
||||
<edit name="hinting">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Bitstream Vera Serif</string>
|
||||
</test>
|
||||
<test name="pixelsize" compare="less">
|
||||
<double>7.5</double>
|
||||
</test>
|
||||
<edit name="hinting">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Bitstream Vera Sans Mono</string>
|
||||
</test>
|
||||
<test name="pixelsize" compare="less">
|
||||
<double>7.5</double>
|
||||
</test>
|
||||
<edit name="hinting">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
</fontconfig>
|
128
res/fonts/conf.d/25-unhint-nonlatin.conf
Normal file
@ -0,0 +1,128 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
|
||||
<!-- We can't hint CJK fonts well, so turn off hinting for CJK fonts. -->
|
||||
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Kochi Mincho</string>
|
||||
</test>
|
||||
<edit name="hinting" mode="assign">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Kochi Gothic</string>
|
||||
</test>
|
||||
<edit name="hinting" mode="assign">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Sazanami Mincho</string>
|
||||
</test>
|
||||
<edit name="hinting" mode="assign">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Sazanami Gothic</string>
|
||||
</test>
|
||||
<edit name="hinting" mode="assign">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Baekmuk Batang</string>
|
||||
</test>
|
||||
<edit name="hinting" mode="assign">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Baekmuk Dotum</string>
|
||||
</test>
|
||||
<edit name="hinting" mode="assign">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Baekmuk Gulim</string>
|
||||
</test>
|
||||
<edit name="hinting" mode="assign">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Baekmuk Headline</string>
|
||||
</test>
|
||||
<edit name="hinting" mode="assign">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>AR PL Mingti2L Big5</string>
|
||||
</test>
|
||||
<edit name="hinting" mode="assign">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>AR PL ShanHeiSun Uni</string>
|
||||
</test>
|
||||
<edit name="hinting" mode="assign">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>AR PL KaitiM Big5</string>
|
||||
</test>
|
||||
<edit name="hinting" mode="assign">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>AR PL ZenKai Uni</string>
|
||||
</test>
|
||||
<edit name="hinting" mode="assign">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>AR PL SungtiL GB</string>
|
||||
</test>
|
||||
<edit name="hinting" mode="assign">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>AR PL KaitiM GB</string>
|
||||
</test>
|
||||
<edit name="hinting" mode="assign">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
<match target="font">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>ZYSong18030</string>
|
||||
</test>
|
||||
<edit name="hinting" mode="assign">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
</fontconfig>
|
652
res/fonts/conf.d/30-metric-aliases.conf
Normal file
@ -0,0 +1,652 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
|
||||
<!--
|
||||
|
||||
Alias similar/metric-compatible families from various sources:
|
||||
|
||||
PostScript fonts: URW fonts: GUST fonts: Windows fonts:
|
||||
====================== ================== ================= ==================
|
||||
Helvetica Nimbus Sans TeX Gyre Heros
|
||||
Helvetica Narrow Nimbus Sans Narrow TeX Gyre Heros Cn
|
||||
Times Nimbus Roman TeX Gyre Termes
|
||||
Courier Nimbus Mono PS TeX Gyre Cursor
|
||||
ITC Avant Garde Gothic URW Gothic TeX Gyre Adventor
|
||||
ITC Bookman URW Bookman TeX Gyre Bonum Bookman Old Style
|
||||
ITC Zapf Chancery Z003 TeX Gyre Chorus
|
||||
Palatino P052 TeX Gyre Pagella Palatino Linotype
|
||||
New Century Schoolbook C059 TeX Gyre Schola Century Schoolbook
|
||||
|
||||
Microsoft fonts: Liberation fonts: Google CrOS core fonts: StarOffice fonts: AMT fonts:
|
||||
================ ====================== ======================= ================= ==============
|
||||
Arial Liberation Sans Arimo Albany Albany AMT
|
||||
Arial Narrow Liberation Sans Narrow
|
||||
Times New Roman Liberation Serif Tinos Thorndale Thorndale AMT
|
||||
Courier New Liberation Mono Cousine Cumberland Cumberland AMT
|
||||
Cambria Caladea
|
||||
Calibri Carlito
|
||||
Symbol SymbolNeu
|
||||
|
||||
Microsoft fonts: Other fonts:
|
||||
================ ============
|
||||
Georgia Gelasio
|
||||
|
||||
We want for each of them to fallback to any of these available,
|
||||
but in an order preferring similar designs first. We do this in three steps:
|
||||
|
||||
1) Alias each specific to its generic family.
|
||||
e.g. Liberation Sans to Arial
|
||||
|
||||
2) Weak alias each generic to the other generic of its family.
|
||||
e.g. Arial to Helvetica
|
||||
|
||||
3) Alias each generic to its specifics.
|
||||
e.g. Arial to Liberation Sans, Arimo, Albany, and Albany AMT
|
||||
|
||||
-->
|
||||
|
||||
<!-- Map specifics to generics -->
|
||||
|
||||
<!-- PostScript -->
|
||||
<alias binding="same">
|
||||
<family>Nimbus Sans L</family>
|
||||
<default>
|
||||
<family>Helvetica</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Nimbus Sans</family>
|
||||
<default>
|
||||
<family>Helvetica</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>TeX Gyre Heros</family>
|
||||
<default>
|
||||
<family>Helvetica</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Nimbus Sans Narrow</family>
|
||||
<default>
|
||||
<family>Helvetica Narrow</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>TeX Gyre Heros Cn</family>
|
||||
<default>
|
||||
<family>Helvetica Narrow</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Nimbus Roman No9 L</family>
|
||||
<default>
|
||||
<family>Times</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Nimbus Roman</family>
|
||||
<default>
|
||||
<family>Times</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>TeX Gyre Termes</family>
|
||||
<default>
|
||||
<family>Times</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Nimbus Mono L</family>
|
||||
<default>
|
||||
<family>Courier</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Nimbus Mono</family>
|
||||
<default>
|
||||
<family>Courier</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Nimbus Mono PS</family>
|
||||
<default>
|
||||
<family>Courier</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>TeX Gyre Cursor</family>
|
||||
<default>
|
||||
<family>Courier</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Avant Garde</family>
|
||||
<default>
|
||||
<family>ITC Avant Garde Gothic</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>URW Gothic L</family>
|
||||
<default>
|
||||
<family>ITC Avant Garde Gothic</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>URW Gothic</family>
|
||||
<default>
|
||||
<family>ITC Avant Garde Gothic</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>TeX Gyre Adventor</family>
|
||||
<default>
|
||||
<family>ITC Avant Garde Gothic</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Bookman</family>
|
||||
<default>
|
||||
<family>ITC Bookman</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>URW Bookman L</family>
|
||||
<default>
|
||||
<family>ITC Bookman</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Bookman URW</family>
|
||||
<default>
|
||||
<family>ITC Bookman</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>URW Bookman</family>
|
||||
<default>
|
||||
<family>ITC Bookman</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>TeX Gyre Bonum</family>
|
||||
<default>
|
||||
<family>ITC Bookman</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Bookman Old Style</family>
|
||||
<default>
|
||||
<family>ITC Bookman</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Zapf Chancery</family>
|
||||
<default>
|
||||
<family>ITC Zapf Chancery</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>URW Chancery L</family>
|
||||
<default>
|
||||
<family>ITC Zapf Chancery</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Chancery URW</family>
|
||||
<default>
|
||||
<family>ITC Zapf Chancery</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Z003</family>
|
||||
<default>
|
||||
<family>ITC Zapf Chancery</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>TeX Gyre Chorus</family>
|
||||
<default>
|
||||
<family>ITC Zapf Chancery</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>URW Palladio L</family>
|
||||
<default>
|
||||
<family>Palatino</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Palladio URW</family>
|
||||
<default>
|
||||
<family>Palatino</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>P052</family>
|
||||
<default>
|
||||
<family>Palatino</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>TeX Gyre Pagella</family>
|
||||
<default>
|
||||
<family>Palatino</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Palatino Linotype</family>
|
||||
<default>
|
||||
<family>Palatino</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Century Schoolbook L</family>
|
||||
<default>
|
||||
<family>New Century Schoolbook</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Century SchoolBook URW</family>
|
||||
<default>
|
||||
<family>New Century Schoolbook</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>C059</family>
|
||||
<default>
|
||||
<family>New Century Schoolbook</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>TeX Gyre Schola</family>
|
||||
<default>
|
||||
<family>New Century Schoolbook</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Century Schoolbook</family>
|
||||
<default>
|
||||
<family>New Century Schoolbook</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
|
||||
<!-- Microsoft -->
|
||||
<alias binding="same">
|
||||
<family>Arimo</family>
|
||||
<default>
|
||||
<family>Arial</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Liberation Sans</family>
|
||||
<default>
|
||||
<family>Arial</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Liberation Sans Narrow</family>
|
||||
<default>
|
||||
<family>Arial Narrow</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Albany</family>
|
||||
<default>
|
||||
<family>Arial</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Albany AMT</family>
|
||||
<default>
|
||||
<family>Arial</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Tinos</family>
|
||||
<default>
|
||||
<family>Times New Roman</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Liberation Serif</family>
|
||||
<default>
|
||||
<family>Times New Roman</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Thorndale</family>
|
||||
<default>
|
||||
<family>Times New Roman</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Thorndale AMT</family>
|
||||
<default>
|
||||
<family>Times New Roman</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Cousine</family>
|
||||
<default>
|
||||
<family>Courier New</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Liberation Mono</family>
|
||||
<default>
|
||||
<family>Courier New</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Cumberland</family>
|
||||
<default>
|
||||
<family>Courier New</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Cumberland AMT</family>
|
||||
<default>
|
||||
<family>Courier New</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Gelasio</family>
|
||||
<default>
|
||||
<family>Georgia</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Caladea</family>
|
||||
<default>
|
||||
<family>Cambria</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Carlito</family>
|
||||
<default>
|
||||
<family>Calibri</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>SymbolNeu</family>
|
||||
<default>
|
||||
<family>Symbol</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<!-- Accept the other group as fallback -->
|
||||
|
||||
<!-- PostScript -->
|
||||
<alias>
|
||||
<family>Helvetica</family>
|
||||
<default>
|
||||
<family>Arial</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias>
|
||||
<family>Helvetica Narrow</family>
|
||||
<default>
|
||||
<family>Arial Narrow</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias>
|
||||
<family>Times</family>
|
||||
<default>
|
||||
<family>Times New Roman</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias>
|
||||
<family>Courier</family>
|
||||
<default>
|
||||
<family>Courier New</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
|
||||
<!-- Microsoft -->
|
||||
<alias>
|
||||
<family>Arial</family>
|
||||
<default>
|
||||
<family>Helvetica</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias>
|
||||
<family>Arial Narrow</family>
|
||||
<default>
|
||||
<family>Helvetica Narrow</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias>
|
||||
<family>Times New Roman</family>
|
||||
<default>
|
||||
<family>Times</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
<alias>
|
||||
<family>Courier New</family>
|
||||
<default>
|
||||
<family>Courier</family>
|
||||
</default>
|
||||
</alias>
|
||||
|
||||
|
||||
|
||||
<!-- Map generics to specifics -->
|
||||
|
||||
<!-- PostScript -->
|
||||
<alias binding="same">
|
||||
<family>Helvetica</family>
|
||||
<accept>
|
||||
<family>TeX Gyre Heros</family>
|
||||
<family>Nimbus Sans</family>
|
||||
<family>Nimbus Sans L</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Helvetica Narrow</family>
|
||||
<accept>
|
||||
<family>TeX Gyre Heros Cn</family>
|
||||
<family>Nimbus Sans Narrow</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Times</family>
|
||||
<accept>
|
||||
<family>TeX Gyre Termes</family>
|
||||
<family>Nimbus Roman</family>
|
||||
<family>Nimbus Roman No9 L</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Courier</family>
|
||||
<accept>
|
||||
<family>TeX Gyre Cursor</family>
|
||||
<family>Nimbus Mono PS</family>
|
||||
<family>Nimbus Mono</family>
|
||||
<family>Nimbus Mono L</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>ITC Avant Garde Gothic</family>
|
||||
<accept>
|
||||
<family>TeX Gyre Adventor</family>
|
||||
<family>URW Gothic</family>
|
||||
<family>URW Gothic L</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>ITC Bookman</family>
|
||||
<accept>
|
||||
<family>Bookman Old Style</family>
|
||||
<family>TeX Gyre Bonum</family>
|
||||
<family>URW Bookman</family>
|
||||
<family>Bookman URW</family>
|
||||
<family>URW Bookman L</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>ITC Zapf Chancery</family>
|
||||
<accept>
|
||||
<family>TeX Gyre Chorus</family>
|
||||
<family>Z003</family>
|
||||
<family>Chancery URW</family>
|
||||
<family>URW Chancery L</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Palatino</family>
|
||||
<accept>
|
||||
<family>Palatino Linotype</family>
|
||||
<family>TeX Gyre Pagella</family>
|
||||
<family>P052</family>
|
||||
<family>Palladio URW</family>
|
||||
<family>URW Palladio L</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>New Century Schoolbook</family>
|
||||
<accept>
|
||||
<family>Century Schoolbook</family>
|
||||
<family>TeX Gyre Schola</family>
|
||||
<family>C059</family>
|
||||
<family>Century SchoolBook URW</family>
|
||||
<family>Century Schoolbook L</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<!-- Microsoft -->
|
||||
<alias binding="same">
|
||||
<family>Arial</family>
|
||||
<accept>
|
||||
<family>Arimo</family>
|
||||
<family>Liberation Sans</family>
|
||||
<family>Albany</family>
|
||||
<family>Albany AMT</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Arial Narrow</family>
|
||||
<accept>
|
||||
<family>Liberation Sans Narrow</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Times New Roman</family>
|
||||
<accept>
|
||||
<family>Tinos</family>
|
||||
<family>Liberation Serif</family>
|
||||
<family>Thorndale</family>
|
||||
<family>Thorndale AMT</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Courier New</family>
|
||||
<accept>
|
||||
<family>Cousine</family>
|
||||
<family>Liberation Mono</family>
|
||||
<family>Cumberland</family>
|
||||
<family>Cumberland AMT</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Georgia</family>
|
||||
<accept>
|
||||
<family>Gelasio</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Cambria</family>
|
||||
<accept>
|
||||
<family>Caladea</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Calibri</family>
|
||||
<accept>
|
||||
<family>Carlito</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>Symbol</family>
|
||||
<accept>
|
||||
<family>SymbolNeu</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
</fontconfig>
|
33
res/fonts/conf.d/30-urw-aliases.conf
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!--
|
||||
URW provides metric and shape compatible fonts for some Adobe families.
|
||||
Most of these are handled in 30-metric-aliases.conf.
|
||||
-->
|
||||
<alias binding="same">
|
||||
<family>Zapf Dingbats</family>
|
||||
<accept>
|
||||
<family>D050000L</family>
|
||||
<family>Dingbats</family>
|
||||
</accept>
|
||||
</alias>
|
||||
<alias binding="same">
|
||||
<family>ITC Zapf Dingbats</family>
|
||||
<accept>
|
||||
<family>D050000L</family>
|
||||
<family>Dingbats</family>
|
||||
</accept>
|
||||
</alias>
|
||||
<match target="pattern">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Symbol</string>
|
||||
</test>
|
||||
<edit name="family" mode="append" binding="same">
|
||||
<string>Standard Symbols PS</string>
|
||||
</edit>
|
||||
<edit name="family" mode="append" binding="same">
|
||||
<string>Standard Symbols L</string>
|
||||
</edit>
|
||||
</match>
|
||||
</fontconfig>
|
231
res/fonts/conf.d/40-nonlatin.conf
Normal file
@ -0,0 +1,231 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!--
|
||||
Mark common families with their generics so we'll get
|
||||
something reasonable
|
||||
-->
|
||||
|
||||
<!--
|
||||
Serif faces
|
||||
-->
|
||||
<alias>
|
||||
<family>Nazli</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Lotoos</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Mitra</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Ferdosi</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Badr</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Zar</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Titr</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Jadid</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Kochi Mincho</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>AR PL SungtiL GB</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>AR PL Mingti2L Big5</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>MS 明朝</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>NanumMyeongjo</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>UnBatang</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Baekmuk Batang</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>MgOpen Canonica</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Sazanami Mincho</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>AR PL ZenKai Uni</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>ZYSong18030</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>FreeSerif</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>SimSun</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<!--
|
||||
Sans-serif faces
|
||||
-->
|
||||
<alias>
|
||||
<family>Arshia</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Elham</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Farnaz</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Nasim</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Sina</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Roya</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Koodak</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Terafik</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Kochi Gothic</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>AR PL KaitiM GB</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>AR PL KaitiM Big5</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>MS ゴシック</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>NanumGothic</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>UnDotum</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Baekmuk Dotum</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>MgOpen Modata</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Sazanami Gothic</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>AR PL ShanHeiSun Uni</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>ZYSong18030</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>FreeSans</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<!--
|
||||
Monospace faces
|
||||
-->
|
||||
<alias>
|
||||
<family>NSimSun</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>ZYSong18030</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>NanumGothicCoding</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>FreeMono</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
|
||||
<!--
|
||||
Fantasy faces
|
||||
-->
|
||||
<alias>
|
||||
<family>Homa</family>
|
||||
<default><family>fantasy</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Kamran</family>
|
||||
<default><family>fantasy</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Fantezi</family>
|
||||
<default><family>fantasy</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Tabassom</family>
|
||||
<default><family>fantasy</family></default>
|
||||
</alias>
|
||||
|
||||
<!--
|
||||
Cursive faces
|
||||
-->
|
||||
<alias>
|
||||
<family>IranNastaliq</family>
|
||||
<default><family>cursive</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Nafees Nastaleeq</family>
|
||||
<default><family>cursive</family></default>
|
||||
</alias>
|
||||
|
||||
</fontconfig>
|
273
res/fonts/conf.d/45-latin.conf
Normal file
@ -0,0 +1,273 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!--
|
||||
Mark common families with their generics so we'll get
|
||||
something reasonable
|
||||
-->
|
||||
|
||||
<!--
|
||||
Serif faces
|
||||
-->
|
||||
<alias>
|
||||
<family>Bitstream Vera Serif</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Cambria</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Constantia</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>DejaVu Serif</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Elephant</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Garamond</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Georgia</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Liberation Serif</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Luxi Serif</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>MS Serif</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Nimbus Roman No9 L</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Nimbus Roman</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Palatino Linotype</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Thorndale AMT</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Thorndale</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Times New Roman</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Times</family>
|
||||
<default><family>serif</family></default>
|
||||
</alias>
|
||||
<!--
|
||||
Sans-serif faces
|
||||
-->
|
||||
<alias>
|
||||
<family>Albany AMT</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Albany</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Arial Unicode MS</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Arial</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Bitstream Vera Sans</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Britannic</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Calibri</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Candara</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Century Gothic</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Corbel</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>DejaVu Sans</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Helvetica</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Haettenschweiler</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Liberation Sans</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>MS Sans Serif</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Nimbus Sans L</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Nimbus Sans</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Luxi Sans</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Tahoma</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Trebuchet MS</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Twentieth Century</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Verdana</family>
|
||||
<default><family>sans-serif</family></default>
|
||||
</alias>
|
||||
<!--
|
||||
Monospace faces
|
||||
-->
|
||||
<alias>
|
||||
<family>Andale Mono</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Bitstream Vera Sans Mono</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Consolas</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Courier New</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Courier</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Cumberland AMT</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Cumberland</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>DejaVu Sans Mono</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Fixedsys</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Inconsolata</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Liberation Mono</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Luxi Mono</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Nimbus Mono L</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Nimbus Mono</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Nimbus Mono PS</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Terminal</family>
|
||||
<default><family>monospace</family></default>
|
||||
</alias>
|
||||
<!--
|
||||
Fantasy faces
|
||||
-->
|
||||
<alias>
|
||||
<family>Bauhaus Std</family>
|
||||
<default><family>fantasy</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Cooper Std</family>
|
||||
<default><family>fantasy</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Copperplate Gothic Std</family>
|
||||
<default><family>fantasy</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Impact</family>
|
||||
<default><family>fantasy</family></default>
|
||||
</alias>
|
||||
<!--
|
||||
Cursive faces
|
||||
-->
|
||||
<alias>
|
||||
<family>Comic Sans MS</family>
|
||||
<default><family>cursive</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>ITC Zapf Chancery Std</family>
|
||||
<default><family>cursive</family></default>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>Zapfino</family>
|
||||
<default><family>cursive</family></default>
|
||||
</alias>
|
||||
|
||||
</fontconfig>
|
21
res/fonts/conf.d/49-sansserif.conf
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!--
|
||||
If the font still has no generic name, add sans-serif
|
||||
-->
|
||||
<match target="pattern">
|
||||
<test qual="all" name="family" compare="not_eq">
|
||||
<string>sans-serif</string>
|
||||
</test>
|
||||
<test qual="all" name="family" compare="not_eq">
|
||||
<string>serif</string>
|
||||
</test>
|
||||
<test qual="all" name="family" compare="not_eq">
|
||||
<string>monospace</string>
|
||||
</test>
|
||||
<edit name="family" mode="append_last">
|
||||
<string>sans-serif</string>
|
||||
</edit>
|
||||
</match>
|
||||
</fontconfig>
|
15
res/fonts/conf.d/50-user.conf
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!--
|
||||
Load per-user customization files where stored on XDG Base Directory
|
||||
specification compliant places. it should be usually:
|
||||
$HOME/.config/fontconfig/conf.d
|
||||
$HOME/.config/fontconfig/fonts.conf
|
||||
-->
|
||||
<include ignore_missing="yes" prefix="xdg">fontconfig/conf.d</include>
|
||||
<include ignore_missing="yes" prefix="xdg">fontconfig/fonts.conf</include>
|
||||
<!-- the following elements will be removed in the future -->
|
||||
<include ignore_missing="yes" deprecated="yes">~/.fonts.conf.d</include>
|
||||
<include ignore_missing="yes" deprecated="yes">~/.fonts.conf</include>
|
||||
</fontconfig>
|
6
res/fonts/conf.d/51-local.conf
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!-- Load local system customization file -->
|
||||
<include ignore_missing="yes">local.conf</include>
|
||||
</fontconfig>
|
9
res/fonts/conf.d/55-emoji-prepend.conf
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<match>
|
||||
<edit name="family" mode="prepend" binding="weak">
|
||||
<string>Twitter Color Emoji</string>
|
||||
</edit>
|
||||
</match>
|
||||
</fontconfig>
|
74
res/fonts/conf.d/60-latin.conf
Normal file
@ -0,0 +1,74 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<alias>
|
||||
<family>serif</family>
|
||||
<prefer>
|
||||
<family>Bitstream Vera Serif</family>
|
||||
<family>DejaVu Serif</family>
|
||||
<family>Times New Roman</family>
|
||||
<family>Thorndale AMT</family>
|
||||
<family>Luxi Serif</family>
|
||||
<family>Nimbus Roman No9 L</family>
|
||||
<family>Nimbus Roman</family>
|
||||
<family>Times</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>sans-serif</family>
|
||||
<prefer>
|
||||
<family>Bitstream Vera Sans</family>
|
||||
<family>DejaVu Sans</family>
|
||||
<family>Verdana</family>
|
||||
<family>Arial</family>
|
||||
<family>Albany AMT</family>
|
||||
<family>Luxi Sans</family>
|
||||
<family>Nimbus Sans L</family>
|
||||
<family>Nimbus Sans</family>
|
||||
<family>Helvetica</family>
|
||||
<family>Lucida Sans Unicode</family>
|
||||
<family>BPG Glaho International</family> <!-- lat,cyr,arab,geor -->
|
||||
<family>Tahoma</family> <!-- lat,cyr,greek,heb,arab,thai -->
|
||||
</prefer>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>monospace</family>
|
||||
<prefer>
|
||||
<family>Bitstream Vera Sans Mono</family>
|
||||
<family>DejaVu Sans Mono</family>
|
||||
<family>Inconsolata</family>
|
||||
<family>Andale Mono</family>
|
||||
<family>Courier New</family>
|
||||
<family>Cumberland AMT</family>
|
||||
<family>Luxi Mono</family>
|
||||
<family>Nimbus Mono L</family>
|
||||
<family>Nimbus Mono</family>
|
||||
<family>Nimbus Mono PS</family>
|
||||
<family>Courier</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
<!--
|
||||
Fantasy faces
|
||||
-->
|
||||
<alias>
|
||||
<family>fantasy</family>
|
||||
<prefer>
|
||||
<family>Impact</family>
|
||||
<family>Copperplate Gothic Std</family>
|
||||
<family>Cooper Std</family>
|
||||
<family>Bauhaus Std</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
<!--
|
||||
Cursive faces
|
||||
-->
|
||||
<alias>
|
||||
<family>cursive</family>
|
||||
<prefer>
|
||||
<family>ITC Zapf Chancery Std</family>
|
||||
<family>Zapfino</family>
|
||||
<family>Comic Sans MS</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
|
||||
</fontconfig>
|
419
res/fonts/conf.d/65-fonts-persian.conf
Normal file
@ -0,0 +1,419 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<!--
|
||||
fonts-persian.conf
|
||||
To configure Persian fonts from The FarsiWeb Project.
|
||||
|
||||
Copyright (C) 2005 Sharif FarsiWeb, Inc. <license@farsiweb.info>
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided that
|
||||
the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation, and that the name of Sharif FarsiWeb, Inc. not be used in
|
||||
advertising or publicity pertaining to distribution of the software without
|
||||
specific, written prior permission. Sharif FarsiWeb, Inc. makes no
|
||||
representations about the suitability of this software for any purpose. It
|
||||
is provided "as is" without express or implied warranty.
|
||||
|
||||
SHARIF FARSIWEB, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
ChangeLog:
|
||||
2005-04-03 Behdad Esfahbod: Initial revision.
|
||||
2005-10-09 Behdad Esfahbod: Turned off back-slant and Tahoma sections.
|
||||
2005-11-30 Behdad Esfahbod: Set Titr susbtitution size to 24 points.
|
||||
2008 Behdad Esfahbod: Cleanup. Add fantasy and cursive.
|
||||
-->
|
||||
<fontconfig>
|
||||
|
||||
|
||||
<!-- Deprecated fonts are discouraged -->
|
||||
|
||||
<!-- Nesf[2] is officially deprecated and has problematic tables -->
|
||||
<alias binding="same">
|
||||
<family>Nesf</family>
|
||||
<accept><family>Nesf2</family></accept>
|
||||
</alias>
|
||||
<alias binding="same">
|
||||
<family>Nesf2</family>
|
||||
<accept><family>Persian_sansserif_default</family></accept>
|
||||
</alias>
|
||||
|
||||
<!-- Name changes and spelling variant aliases -->
|
||||
|
||||
<alias binding="same">
|
||||
<family>Nazanin</family>
|
||||
<accept><family>Nazli</family></accept>
|
||||
</alias>
|
||||
<alias binding="same">
|
||||
<family>Lotus</family>
|
||||
<accept><family>Lotoos</family></accept>
|
||||
</alias>
|
||||
<alias binding="same">
|
||||
<family>Yaqut</family>
|
||||
<accept><family>Yaghoot</family></accept>
|
||||
</alias>
|
||||
<alias binding="same">
|
||||
<family>Yaghut</family>
|
||||
<accept><family>Yaghoot</family></accept>
|
||||
</alias>
|
||||
<alias binding="same">
|
||||
<family>Traffic</family>
|
||||
<accept><family>Terafik</family></accept>
|
||||
</alias>
|
||||
<alias binding="same">
|
||||
<family>Ferdowsi</family>
|
||||
<accept><family>Ferdosi</family></accept>
|
||||
</alias>
|
||||
<alias binding="same">
|
||||
<family>Fantezy</family>
|
||||
<accept><family>Fantezi</family></accept>
|
||||
</alias>
|
||||
|
||||
|
||||
<!-- Classify fonts. -->
|
||||
|
||||
<!-- Persian_title class -->
|
||||
<alias binding="same">
|
||||
<family>Jadid</family>
|
||||
<accept><family>Persian_title</family></accept>
|
||||
</alias>
|
||||
<alias binding="same">
|
||||
<family>Titr</family>
|
||||
<accept><family>Persian_title</family></accept>
|
||||
</alias>
|
||||
|
||||
<!-- Persian_fantasy class -->
|
||||
<alias binding="same">
|
||||
<family>Kamran</family>
|
||||
<accept>
|
||||
<family>Persian_fantasy</family>
|
||||
<family>Homa</family>
|
||||
</accept>
|
||||
</alias>
|
||||
<alias binding="same">
|
||||
<family>Homa</family>
|
||||
<accept>
|
||||
<family>Persian_fantasy</family>
|
||||
<family>Kamran</family>
|
||||
</accept>
|
||||
</alias>
|
||||
<alias binding="same">
|
||||
<family>Fantezi</family>
|
||||
<accept><family>Persian_fantasy</family></accept>
|
||||
</alias>
|
||||
<alias binding="same">
|
||||
<family>Tabassom</family>
|
||||
<accept><family>Persian_fantasy</family></accept>
|
||||
</alias>
|
||||
|
||||
<!-- Persian_square class -->
|
||||
<alias binding="same">
|
||||
<family>Arshia</family>
|
||||
<accept><family>Persian_square</family></accept>
|
||||
</alias>
|
||||
<alias binding="same">
|
||||
<family>Nasim</family>
|
||||
<accept><family>Persian_square</family></accept>
|
||||
</alias>
|
||||
<alias binding="same">
|
||||
<family>Elham</family>
|
||||
<accept>
|
||||
<family>Persian_square</family>
|
||||
<family>Farnaz</family>
|
||||
</accept>
|
||||
</alias>
|
||||
<alias binding="same">
|
||||
<family>Farnaz</family>
|
||||
<accept>
|
||||
<family>Persian_square</family>
|
||||
<family>Elham</family>
|
||||
</accept>
|
||||
</alias>
|
||||
<alias binding="same">
|
||||
<family>Sina</family>
|
||||
<accept><family>Persian_square</family></accept>
|
||||
</alias>
|
||||
|
||||
<!-- Font ordering per class -->
|
||||
|
||||
<!-- Persian_title class -->
|
||||
<alias binding="same">
|
||||
<family>Persian_title</family>
|
||||
<accept>
|
||||
<family>Titr</family>
|
||||
<family>Jadid</family>
|
||||
<family>Persian_serif</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<!-- Persian_fantasy class -->
|
||||
<alias binding="same">
|
||||
<family>Persian_fantasy</family>
|
||||
<accept>
|
||||
<family>Homa</family>
|
||||
<family>Kamran</family>
|
||||
<family>Fantezi</family>
|
||||
<family>Tabassom</family>
|
||||
<family>Persian_square</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<!-- Persian_square class -->
|
||||
<alias binding="same">
|
||||
<family>Persian_square</family>
|
||||
<accept>
|
||||
<family>Arshia</family>
|
||||
<family>Elham</family>
|
||||
<family>Farnaz</family>
|
||||
<family>Nasim</family>
|
||||
<family>Sina</family>
|
||||
<family>Persian_serif</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<!-- Register the fonts that we actually do have -->
|
||||
|
||||
<match target="scan">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Elham</string>
|
||||
</test>
|
||||
<edit name="foundry">
|
||||
<string>farsiweb</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<match target="scan">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Homa</string>
|
||||
</test>
|
||||
<edit name="foundry">
|
||||
<string>farsiweb</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<match target="scan">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Koodak</string>
|
||||
</test>
|
||||
<edit name="foundry">
|
||||
<string>farsiweb</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<match target="scan">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Nazli</string>
|
||||
</test>
|
||||
<edit name="foundry">
|
||||
<string>farsiweb</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<match target="scan">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Roya</string>
|
||||
</test>
|
||||
<edit name="foundry">
|
||||
<string>farsiweb</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<match target="scan">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Terafik</string>
|
||||
</test>
|
||||
<edit name="foundry">
|
||||
<string>farsiweb</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<match target="scan">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Titr</string>
|
||||
</test>
|
||||
<edit name="foundry">
|
||||
<string>farsiweb</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
|
||||
<!-- Our fonts should oblique to the other side (TURNED-OFF) -->
|
||||
|
||||
<match target="font">
|
||||
<test name="foundry">
|
||||
<!--string>farsiweb</string-->
|
||||
<string>TURNED-OFF</string>
|
||||
</test>
|
||||
<test name="foundry">
|
||||
<string>farsiweb</string>
|
||||
</test>
|
||||
<!-- check to see if the font is roman -->
|
||||
<test name="slant">
|
||||
<const>roman</const>
|
||||
</test>
|
||||
<!-- check to see if the pattern requested non-roman -->
|
||||
<test target="pattern" name="slant" compare="not_eq">
|
||||
<const>roman</const>
|
||||
</test>
|
||||
<!-- multiply the matrix to slant the font -->
|
||||
<edit name="matrix" mode="assign">
|
||||
<times>
|
||||
<name>matrix</name>
|
||||
<matrix><double>1</double><double>-0.2</double>
|
||||
<double>0</double><double>1</double>
|
||||
</matrix>
|
||||
</times>
|
||||
</edit>
|
||||
<!-- pretend the font is oblique now -->
|
||||
<edit name="slant" mode="assign">
|
||||
<const>oblique</const>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
|
||||
<!--
|
||||
We can't hint our fonts well, so turn off hinting.
|
||||
Moreover, the bitmaps we have designed (well, they
|
||||
have designed), suck, so disable them too.
|
||||
-->
|
||||
|
||||
<match target="font">
|
||||
<test name="foundry">
|
||||
<string>farsiweb</string>
|
||||
</test>
|
||||
<edit name="autohint">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
<edit name="hinting">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
<edit name="embeddedbitmap">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
|
||||
<!-- Alias our fonts to common families -->
|
||||
|
||||
<!-- Persian serif fonts -->
|
||||
<alias>
|
||||
<family>serif</family>
|
||||
<accept>
|
||||
<family>Nazli</family>
|
||||
<family>Lotoos</family>
|
||||
<family>Mitra</family>
|
||||
<family>Ferdosi</family>
|
||||
<family>Badr</family>
|
||||
<family>Zar</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<!-- Persian sans-serif fonts -->
|
||||
<alias>
|
||||
<family>sans-serif</family>
|
||||
<accept>
|
||||
<family>Roya</family>
|
||||
<family>Koodak</family>
|
||||
<family>Terafik</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<!-- Persian monospace fonts -->
|
||||
<alias>
|
||||
<family>monospace</family>
|
||||
<accept>
|
||||
<!-- Not really monospace -->
|
||||
<family>Terafik</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<!-- Persian fantasy fonts -->
|
||||
<alias>
|
||||
<family>fantasy</family>
|
||||
<accept>
|
||||
<family>Homa</family>
|
||||
<family>Kamran</family>
|
||||
<family>Fantezi</family>
|
||||
<family>Tabassom</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<!-- Persian (and Urdu) Nastaliq/cursive fonts -->
|
||||
<alias>
|
||||
<family>cursive</family>
|
||||
<accept>
|
||||
<family>IranNastaliq</family>
|
||||
<family>Nafees Nastaleeq</family>
|
||||
</accept>
|
||||
</alias>
|
||||
|
||||
<!-- Use Titr in titles -->
|
||||
|
||||
<!-- Both serif... -->
|
||||
<match>
|
||||
<test name="family">
|
||||
<string>serif</string>
|
||||
</test>
|
||||
<test name="weight" compare="more_eq">
|
||||
<int>200</int>
|
||||
</test>
|
||||
<test name="size" compare="more_eq">
|
||||
<double>24</double>
|
||||
</test>
|
||||
<edit name="family" mode="prepend">
|
||||
<string>Titr</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<!-- and sans-serif. -->
|
||||
<match>
|
||||
<test name="family">
|
||||
<string>sans-serif</string>
|
||||
</test>
|
||||
<test name="weight" compare="more_eq">
|
||||
<int>200</int>
|
||||
</test>
|
||||
<test name="size" compare="more_eq">
|
||||
<double>24</double>
|
||||
</test>
|
||||
<edit name="family" mode="prepend">
|
||||
<string>Titr</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<!-- and more. -->
|
||||
<match>
|
||||
<test name="family">
|
||||
<string>Persian_sansserif_default</string>
|
||||
</test>
|
||||
<test name="weight" compare="more_eq">
|
||||
<int>200</int>
|
||||
</test>
|
||||
<test name="size" compare="more_eq">
|
||||
<double>24</double>
|
||||
</test>
|
||||
<edit name="family" mode="prepend" binding="same">
|
||||
<string>Titr</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
|
||||
<!-- Default substituted for deprecated sans-serif fonts -->
|
||||
|
||||
<match>
|
||||
<test name="family">
|
||||
<string>Persian_sansserif_default</string>
|
||||
</test>
|
||||
<edit name="family" mode="assign" binding="same">
|
||||
<string>Roya</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
</fontconfig>
|
16
res/fonts/conf.d/65-khmer.conf
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<alias>
|
||||
<family>serif</family>
|
||||
<prefer>
|
||||
<family>Khmer OS"</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>sans-serif</family>
|
||||
<prefer>
|
||||
<family>Khmer OS"</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
</fontconfig>
|
196
res/fonts/conf.d/65-nonlatin.conf
Normal file
@ -0,0 +1,196 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<alias>
|
||||
<family>serif</family>
|
||||
<prefer>
|
||||
<family>Artsounk</family> <!-- armenian -->
|
||||
<family>BPG UTF8 M</family> <!-- georgian -->
|
||||
<family>Kinnari</family> <!-- thai -->
|
||||
<family>Norasi</family> <!-- thai -->
|
||||
<family>Frank Ruehl</family> <!-- hebrew -->
|
||||
<family>Dror</family> <!-- hebrew -->
|
||||
<family>JG LaoTimes</family> <!-- lao -->
|
||||
<family>Saysettha Unicode</family> <!-- lao -->
|
||||
<family>Pigiarniq</family> <!-- canadian syllabics -->
|
||||
<family>B Davat</family> <!-- arabic (fa) -->
|
||||
<family>B Compset</family> <!-- arabic (fa) -->
|
||||
<family>Kacst-Qr</family> <!-- arabic (ar) -->
|
||||
<family>Urdu Nastaliq Unicode</family> <!-- arabic (ur) -->
|
||||
<family>Raghindi</family> <!-- devanagari -->
|
||||
<family>Mukti Narrow</family> <!-- bengali -->
|
||||
<family>malayalam</family> <!-- malayalam -->
|
||||
<family>Sampige</family> <!-- kannada -->
|
||||
<family>padmaa</family> <!-- gujarati -->
|
||||
<family>Hapax Berbère</family> <!-- tifinagh -->
|
||||
<family>MS Mincho</family> <!-- han (ja) -->
|
||||
<family>SimSun</family> <!-- han (zh-cn,zh-tw) -->
|
||||
<family>PMingLiu</family> <!-- han (zh-tw) -->
|
||||
<family>WenQuanYi Zen Hei</family> <!-- han (zh-cn,zh-tw) -->
|
||||
<family>WenQuanYi Bitmap Song</family> <!-- han (zh-cn,zh-tw) -->
|
||||
<family>AR PL ShanHeiSun Uni</family> <!-- han (ja,zh-cn,zh-tw) -->
|
||||
<family>AR PL New Sung</family> <!-- han (zh-cn,zh-tw) -->
|
||||
<family>ZYSong18030</family> <!-- han (zh-cn,zh-tw) -->
|
||||
<family>HanyiSong</family> <!-- han (zh-cn,zh-tw) -->
|
||||
<family>MgOpen Canonica</family>
|
||||
<family>Sazanami Mincho</family>
|
||||
<family>IPAMonaMincho</family>
|
||||
<family>IPAMincho</family>
|
||||
<family>Kochi Mincho</family>
|
||||
<family>AR PL SungtiL GB</family>
|
||||
<family>AR PL Mingti2L Big5</family>
|
||||
<family>AR PL Zenkai Uni</family>
|
||||
<family>MS 明朝</family>
|
||||
<family>ZYSong18030</family>
|
||||
<family>NanumMyeongjo</family> <!-- hangul (ko) -->
|
||||
<family>UnBatang</family> <!-- hangul (ko) -->
|
||||
<family>Baekmuk Batang</family> <!-- hangul (ko) -->
|
||||
<family>KacstQura</family>
|
||||
<family>Frank Ruehl CLM</family>
|
||||
<family>Lohit Bengali</family>
|
||||
<family>Lohit Gujarati</family>
|
||||
<family>Lohit Hindi</family>
|
||||
<family>Lohit Marathi</family>
|
||||
<family>Lohit Maithili</family>
|
||||
<family>Lohit Kashmiri</family>
|
||||
<family>Lohit Konkani</family>
|
||||
<family>Lohit Nepali</family>
|
||||
<family>Lohit Sindhi</family>
|
||||
<family>Lohit Punjabi</family>
|
||||
<family>Lohit Tamil</family>
|
||||
<family>Meera</family>
|
||||
<family>Lohit Malayalam</family>
|
||||
<family>Lohit Kannada</family>
|
||||
<family>Lohit Telugu</family>
|
||||
<family>Lohit Oriya</family>
|
||||
<family>LKLUG</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>sans-serif</family>
|
||||
<prefer>
|
||||
<family>Nachlieli</family> <!-- hebrew -->
|
||||
<family>Lucida Sans Unicode</family>
|
||||
<family>Yudit Unicode</family>
|
||||
<family>Kerkis</family> <!-- greek -->
|
||||
<family>ArmNet Helvetica</family> <!-- armenian -->
|
||||
<family>Artsounk</family> <!-- armenian -->
|
||||
<family>BPG UTF8 M</family> <!-- georgian -->
|
||||
<family>Waree</family> <!-- thai -->
|
||||
<family>Loma</family> <!-- thai -->
|
||||
<family>Garuda</family> <!-- thai -->
|
||||
<family>Umpush</family> <!-- thai -->
|
||||
<family>Saysettha Unicode</family> <!-- lao? -->
|
||||
<family>JG Lao Old Arial</family> <!-- lao -->
|
||||
<family>GF Zemen Unicode</family> <!-- ethiopic -->
|
||||
<family>Pigiarniq</family> <!-- canadian syllabics -->
|
||||
<family>B Davat</family> <!-- arabic (fa) -->
|
||||
<family>B Compset</family> <!-- arabic (fa) -->
|
||||
<family>Kacst-Qr</family> <!-- arabic (ar) -->
|
||||
<family>Urdu Nastaliq Unicode</family> <!-- arabic (ur) -->
|
||||
<family>Raghindi</family> <!-- devanagari -->
|
||||
<family>Mukti Narrow</family> <!-- bengali -->
|
||||
<family>malayalam</family> <!-- malayalam -->
|
||||
<family>Sampige</family> <!-- kannada -->
|
||||
<family>padmaa</family> <!-- gujarati -->
|
||||
<family>Hapax Berbère</family> <!-- tifinagh -->
|
||||
<family>MS Gothic</family> <!-- han (ja) -->
|
||||
<family>UmePlus P Gothic</family> <!-- han (ja) -->
|
||||
<!-- chinese fonts are actually serifed -->
|
||||
<family>SimSun</family> <!-- han (zh-cn,zh-tw) -->
|
||||
<family>PMingLiu</family> <!-- han (zh-tw) -->
|
||||
<family>WenQuanYi Zen Hei</family> <!-- han (zh-cn,zh-tw) -->
|
||||
<family>WenQuanYi Bitmap Song</family> <!-- han (zh-cn,zh-tw) -->
|
||||
<family>AR PL ShanHeiSun Uni</family> <!--han (ja,zh-cn,zh-tw) -->
|
||||
<family>AR PL New Sung</family> <!-- han (zh-cn,zh-tw) -->
|
||||
<family>MgOpen Modata</family>
|
||||
<family>VL Gothic</family>
|
||||
<family>IPAMonaGothic</family>
|
||||
<family>IPAGothic</family>
|
||||
<family>Sazanami Gothic</family>
|
||||
<family>Kochi Gothic</family>
|
||||
<family>AR PL KaitiM GB</family>
|
||||
<family>AR PL KaitiM Big5</family>
|
||||
<family>AR PL ShanHeiSun Uni</family>
|
||||
<family>AR PL SungtiL GB</family>
|
||||
<family>AR PL Mingti2L Big5</family>
|
||||
<family>MS ゴシック</family>
|
||||
<family>ZYSong18030</family> <!-- han (zh-cn,zh-tw) -->
|
||||
<family>TSCu_Paranar</family> <!-- tamil -->
|
||||
<family>NanumGothic</family> <!-- hangul (ko) -->
|
||||
<family>UnDotum</family> <!-- hangul (ko) -->
|
||||
<family>Baekmuk Dotum</family> <!-- hangul (ko) -->
|
||||
<family>Baekmuk Gulim</family> <!-- hangul (ko) -->
|
||||
<family>KacstQura</family>
|
||||
<family>Lohit Bengali</family>
|
||||
<family>Lohit Gujarati</family>
|
||||
<family>Lohit Hindi</family>
|
||||
<family>Lohit Marathi</family>
|
||||
<family>Lohit Maithili</family>
|
||||
<family>Lohit Kashmiri</family>
|
||||
<family>Lohit Konkani</family>
|
||||
<family>Lohit Nepali</family>
|
||||
<family>Lohit Sindhi</family>
|
||||
<family>Lohit Punjabi</family>
|
||||
<family>Lohit Tamil</family>
|
||||
<family>Meera</family>
|
||||
<family>Lohit Malayalam</family>
|
||||
<family>Lohit Kannada</family>
|
||||
<family>Lohit Telugu</family>
|
||||
<family>Lohit Oriya</family>
|
||||
<family>LKLUG</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>monospace</family>
|
||||
<prefer>
|
||||
<family>Miriam Mono</family> <!-- hebrew -->
|
||||
<family>VL Gothic</family>
|
||||
<family>IPAMonaGothic</family>
|
||||
<family>IPAGothic</family>
|
||||
<family>Sazanami Gothic</family>
|
||||
<family>Kochi Gothic</family>
|
||||
<family>AR PL KaitiM GB</family>
|
||||
<family>MS Gothic</family> <!-- han (ja) -->
|
||||
<family>UmePlus Gothic</family> <!-- han (ja) -->
|
||||
<family>NSimSun</family> <!-- han (zh-cn,zh-tw) -->
|
||||
<family>MingLiu</family> <!-- han (zh-tw) -->
|
||||
<family>AR PL ShanHeiSun Uni</family> <!-- han (ja,zh-cn,zh-tw) -->
|
||||
<family>AR PL New Sung Mono</family> <!-- han (zh-cn,zh-tw) -->
|
||||
<family>HanyiSong</family> <!-- han (zh-cn) -->
|
||||
<family>AR PL SungtiL GB</family>
|
||||
<family>AR PL Mingti2L Big5</family>
|
||||
<family>ZYSong18030</family> <!-- han (zh-cn,zh-tw) -->
|
||||
<family>NanumGothicCoding</family> <!-- hangul (ko) -->
|
||||
<family>NanumGothic</family> <!-- hangul (ko) -->
|
||||
<family>UnDotum</family> <!-- hangul (ko) -->
|
||||
<family>Baekmuk Dotum</family> <!-- hangul (ko) -->
|
||||
<family>Baekmuk Gulim</family> <!-- hangul (ko) -->
|
||||
<family>TlwgTypo</family> <!-- thai -->
|
||||
<family>TlwgTypist</family> <!-- thai -->
|
||||
<family>TlwgTypewriter</family> <!-- thai -->
|
||||
<family>TlwgMono</family> <!-- thai -->
|
||||
<family>Hasida</family> <!-- hebrew -->
|
||||
<family>Mitra Mono</family> <!-- bengali -->
|
||||
<family>GF Zemen Unicode</family> <!-- ethiopic -->
|
||||
<family>Hapax Berbère</family> <!-- tifinagh -->
|
||||
<family>Lohit Bengali</family>
|
||||
<family>Lohit Gujarati</family>
|
||||
<family>Lohit Hindi</family>
|
||||
<family>Lohit Marathi</family>
|
||||
<family>Lohit Maithili</family>
|
||||
<family>Lohit Kashmiri</family>
|
||||
<family>Lohit Konkani</family>
|
||||
<family>Lohit Nepali</family>
|
||||
<family>Lohit Sindhi</family>
|
||||
<family>Lohit Punjabi</family>
|
||||
<family>Lohit Tamil</family>
|
||||
<family>Meera</family>
|
||||
<family>Lohit Malayalam</family>
|
||||
<family>Lohit Kannada</family>
|
||||
<family>Lohit Telugu</family>
|
||||
<family>Lohit Oriya</family>
|
||||
<family>LKLUG</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
</fontconfig>
|
28
res/fonts/conf.d/69-unifont.conf
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<alias>
|
||||
<family>serif</family>
|
||||
<prefer>
|
||||
<family>FreeSerif</family>
|
||||
<family>Code2000</family>
|
||||
<family>Code2001</family> <!-- plane1 and beyond -->
|
||||
</prefer>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>sans-serif</family>
|
||||
<prefer>
|
||||
<family>FreeSans</family>
|
||||
<family>Arial Unicode MS</family>
|
||||
<family>Arial Unicode</family>
|
||||
<family>Code2000</family> <!-- almost everything; serif actually -->
|
||||
<family>Code2001</family> <!-- plane1 and beyond -->
|
||||
</prefer>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>monospace</family>
|
||||
<prefer>
|
||||
<family>FreeMono</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
</fontconfig>
|
12
res/fonts/conf.d/70-yes-bitmaps.conf
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!-- Accept bitmap fonts -->
|
||||
<selectfont>
|
||||
<acceptfont>
|
||||
<pattern>
|
||||
<patelt name="scalable"><bool>false</bool></patelt>
|
||||
</pattern>
|
||||
</acceptfont>
|
||||
</selectfont>
|
||||
</fontconfig>
|
19
res/fonts/conf.d/80-delicious.conf
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!-- Fix-ups for Delicious family -->
|
||||
|
||||
<!-- Delicious 'heavy' variant says its Medium weight -->
|
||||
<match target="scan">
|
||||
<test name="family" compare="eq" ignore-blanks="true">
|
||||
<string>Delicious</string>
|
||||
</test>
|
||||
<test name="style">
|
||||
<string>Heavy</string>
|
||||
</test>
|
||||
<edit name="weight">
|
||||
<const>heavy</const>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
</fontconfig>
|
64
res/fonts/conf.d/90-synthetic.conf
Normal file
@ -0,0 +1,64 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<!--
|
||||
Artificial oblique for fonts without an italic or oblique version
|
||||
-->
|
||||
|
||||
<match target="font">
|
||||
<!-- check to see if the font is roman -->
|
||||
<test name="slant">
|
||||
<const>roman</const>
|
||||
</test>
|
||||
<!-- check to see if the pattern requested non-roman -->
|
||||
<test target="pattern" name="slant" compare="not_eq">
|
||||
<const>roman</const>
|
||||
</test>
|
||||
<!-- multiply the matrix to slant the font -->
|
||||
<edit name="matrix" mode="assign">
|
||||
<times>
|
||||
<name>matrix</name>
|
||||
<matrix><double>1</double><double>0.2</double>
|
||||
<double>0</double><double>1</double>
|
||||
</matrix>
|
||||
</times>
|
||||
</edit>
|
||||
<!-- pretend the font is oblique now -->
|
||||
<edit name="slant" mode="assign">
|
||||
<const>oblique</const>
|
||||
</edit>
|
||||
<!-- and disable embedded bitmaps for artificial oblique -->
|
||||
<edit name="embeddedbitmap" mode="assign">
|
||||
<bool>false</bool>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<!--
|
||||
Synthetic emboldening for fonts that do not have bold face available
|
||||
-->
|
||||
|
||||
<match target="font">
|
||||
<!-- check to see if the font is just regular -->
|
||||
<test name="weight" compare="less_eq">
|
||||
<const>medium</const>
|
||||
</test>
|
||||
<!-- check to see if the pattern requests bold -->
|
||||
<test target="pattern" name="weight" compare="more">
|
||||
<const>medium</const>
|
||||
</test>
|
||||
<!--
|
||||
set the embolden flag
|
||||
needed for applications using cairo, e.g. gucharmap, gedit, ...
|
||||
-->
|
||||
<edit name="embolden" mode="assign">
|
||||
<bool>true</bool>
|
||||
</edit>
|
||||
<!--
|
||||
set weight to bold
|
||||
needed for applications using Xft directly, e.g. Firefox, ...
|
||||
-->
|
||||
<edit name="weight" mode="assign">
|
||||
<const>bold</const>
|
||||
</edit>
|
||||
</match>
|
||||
</fontconfig>
|
89
res/fonts/fonts.template.conf
Normal file
@ -0,0 +1,89 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<!-- /etc/fonts/fonts.conf file to configure system font access -->
|
||||
<fontconfig>
|
||||
|
||||
<!--
|
||||
DO NOT EDIT THIS FILE.
|
||||
IT WILL BE REPLACED WHEN FONTCONFIG IS UPDATED.
|
||||
LOCAL CHANGES BELONG IN 'local.conf'.
|
||||
|
||||
The intent of this standard configuration file is to be adequate for
|
||||
most environments. If you have a reasonably normal environment and
|
||||
have found problems with this configuration, they are probably
|
||||
things that others will also want fixed. Please submit any
|
||||
problems to the fontconfig bugzilla system located at fontconfig.org
|
||||
|
||||
Note that the normal 'make install' procedure for fontconfig is to
|
||||
replace any existing fonts.conf file with the new version. Place
|
||||
any local customizations in local.conf which this file references.
|
||||
|
||||
Keith Packard
|
||||
-->
|
||||
|
||||
<!-- Font directory list -->
|
||||
|
||||
<dir>WINDOWSFONTDIR</dir>
|
||||
|
||||
<dir prefix="xdg">fonts</dir>
|
||||
<!-- the following element will be removed in the future -->
|
||||
<dir>~/.fonts</dir>
|
||||
|
||||
<!--
|
||||
Accept deprecated 'mono' alias, replacing it with 'monospace'
|
||||
-->
|
||||
<match target="pattern">
|
||||
<test qual="any" name="family">
|
||||
<string>mono</string>
|
||||
</test>
|
||||
<edit name="family" mode="assign" binding="same">
|
||||
<string>monospace</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<!--
|
||||
Accept alternate 'sans serif' spelling, replacing it with 'sans-serif'
|
||||
-->
|
||||
<match target="pattern">
|
||||
<test qual="any" name="family">
|
||||
<string>sans serif</string>
|
||||
</test>
|
||||
<edit name="family" mode="assign" binding="same">
|
||||
<string>sans-serif</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<!--
|
||||
Accept deprecated 'sans' alias, replacing it with 'sans-serif'
|
||||
-->
|
||||
<match target="pattern">
|
||||
<test qual="any" name="family">
|
||||
<string>sans</string>
|
||||
</test>
|
||||
<edit name="family" mode="assign" binding="same">
|
||||
<string>sans-serif</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<!--
|
||||
Load local system customization file
|
||||
-->
|
||||
<!--(CONFD)-->
|
||||
|
||||
<!-- Font cache directory list -->
|
||||
|
||||
<cachedir>LOCAL_APPDATA_FONTCONFIG_CACHE</cachedir>
|
||||
<cachedir prefix="xdg">fontconfig</cachedir>
|
||||
<!-- the following element will be removed in the future -->
|
||||
<cachedir>~/.fontconfig</cachedir>
|
||||
|
||||
<config>
|
||||
<!--
|
||||
Rescan configuration every 30 seconds when FcFontSetList is called
|
||||
-->
|
||||
<rescan>
|
||||
<int>30</int>
|
||||
</rescan>
|
||||
</config>
|
||||
|
||||
</fontconfig>
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.9 KiB |
BIN
res/res/certifiedmoderator.png
Normal file
After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |