summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-11-21 18:28:08 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-11-21 18:28:08 +0200
commit58955605b89a47f2a438ec1eca77bef91c4af032 (patch)
treea7fc31e31c134023843ebdf0e6ef465e9b639941
parent9908cc3ec9c6697070f23a9da52e25e95830fb01 (diff)
parent33fe87051f3c4e293f47618adced141b1183b324 (diff)
Merge branch 'dev' into work/v1.9
# Conflicts: # CMakeLists.txt # res/about/version.gmi
-rw-r--r--AUTHORS.md18
-rw-r--r--CMakeLists.txt15
-rw-r--r--Depends.cmake9
-rw-r--r--README.md4
-rw-r--r--po/de.po506
-rw-r--r--po/en.po59
-rw-r--r--res/about/help.gmi2
-rw-r--r--res/about/version.gmi5
-rw-r--r--res/fi.skyjake.Lagrange.appdata.xml19
-rw-r--r--src/gmcerts.c6
-rw-r--r--src/sitespec.c51
-rw-r--r--src/sitespec.h9
-rw-r--r--src/ui/banner.c18
-rw-r--r--src/ui/uploadwidget.c45
-rw-r--r--src/ui/util.c92
-rw-r--r--src/ui/util.h1
16 files changed, 630 insertions, 229 deletions
diff --git a/AUTHORS.md b/AUTHORS.md
index 81f3bb45..a809d9e3 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -5,25 +5,25 @@ Lagrange was created by Jaakko Keränen (<jaakko.keranen@iki.fi>) in July 2020.
5Legend: `C` code, `T` translation 5Legend: `C` code, `T` translation
6 6
7``` 7```
8C 2609 Jaakko Keränen <jaakko.keranen@iki.fi> 8C 2631 Jaakko Keränen <jaakko.keranen@iki.fi>
9CT 39 Nikolay Korotkiy <sikmir@gmail.com> 9CT 39 Nikolay Korotkiy <sikmir@gmail.com>
10 T 38 Olga Smirnova <mistresssilvara@hotmail.com> 10 T 39 Olga Smirnova <mistresssilvara@hotmail.com>
11 T 27 Alyssa Liddell <e-liss@tuta.io>
11 T 27 jan Anja <cyber@sysrq.in> 12 T 27 jan Anja <cyber@sysrq.in>
12 T 26 Alyssa Liddell <e-liss@tuta.io>
13 T 25 Shibo Lyu <github@of.sb> 13 T 25 Shibo Lyu <github@of.sb>
14 T 21 Страхиња Радић <contact@strahinja.org> 14 T 22 Страхиња Радић <contact@strahinja.org>
15 T 17 MCMic <come@chilliet.eu> 15 T 17 MCMic <come@chilliet.eu>
16 T 14 Wally Hackenslacker <mastor89@protonmail.com> 16 T 15 Wally Hackenslacker <mastor89@protonmail.com>
17 T 10 Tadeáš Erban <tadysekerbosek@gmail.com>
18 T 10 Xosé M <correoxm@disroot.org>
17 T 9 Aaron Fischer <mail@aaron-fischer.net> 19 T 9 Aaron Fischer <mail@aaron-fischer.net>
18 T 9 Xosé M <correoxm@disroot.org>
19 T 8 El Mau <public@correolibre.net> 20 T 8 El Mau <public@correolibre.net>
20 T 8 Tadeáš Erban <tadysekerbosek@gmail.com>
21 T 7 Waterrail <maksymiliankrol03@gmail.com> 21 T 7 Waterrail <maksymiliankrol03@gmail.com>
22 T 5 roy niang <roy@royniang.com> 22 T 5 roy niang <roy@royniang.com>
23 T 3 Botond Balázs <balazsbotond@gmail.com>
23 T 2 Alex Schroeder <alex@alexschroeder.ch> 24 T 2 Alex Schroeder <alex@alexschroeder.ch>
24C 2 Alyssa Rosenzweig <alyssa@rosenzweig.io> 25C 2 Alyssa Rosenzweig <alyssa@rosenzweig.io>
25 T 2 Arns Udovič <zordsdavini@arns.lt> 26 T 2 Arns Udovič <zordsdavini@arns.lt>
26 T 2 Botond Balázs <balazsbotond@gmail.com>
27C 2 Br0000k <77938600+Br0000k@users.noreply.github.com> 27C 2 Br0000k <77938600+Br0000k@users.noreply.github.com>
28 T 2 Gabriel de Oliveira Ferreira Machado <goliv04053@tutanota.com> 28 T 2 Gabriel de Oliveira Ferreira Machado <goliv04053@tutanota.com>
29C 2 Manos Pitsidianakis <el13635@mail.ntua.gr> 29C 2 Manos Pitsidianakis <el13635@mail.ntua.gr>
@@ -38,8 +38,8 @@ C 1 David Gillies <dave.gillies@gmail.com>
38C 1 Raph M <raph@raphm.com> 38C 1 Raph M <raph@raphm.com>
39C 1 SolidHal <hal@halemmerich.com> 39C 1 SolidHal <hal@halemmerich.com>
40C 1 Thomas Adam <thomas.adam@smoothwall.net> 40C 1 Thomas Adam <thomas.adam@smoothwall.net>
41C 1 Waweic <waweic@protonmail.com>
42C 1 Waweic <waweic@activ.ism.rocks> 41C 1 Waweic <waweic@activ.ism.rocks>
42C 1 Waweic <waweic@protonmail.com>
43C 1 Zach DeCook <zachdecook@librem.one> 43C 1 Zach DeCook <zachdecook@librem.one>
44C 1 zocker <zocker@10zen.eu> 44C 1 zocker <zocker@10zen.eu>
45``` 45```
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b0a8ba04..69b7c5c8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -285,6 +285,7 @@ endif ()
285 285
286# Target. 286# Target.
287add_executable (app ${SOURCES} ${RESOURCES}) 287add_executable (app ${SOURCES} ${RESOURCES})
288set_property (TARGET app PROPERTY C_STANDARD 11)
288if (TARGET ext-deps) 289if (TARGET ext-deps)
289 add_dependencies (app ext-deps) 290 add_dependencies (app ext-deps)
290endif () 291endif ()
@@ -444,6 +445,7 @@ elseif (HAIKU)
444 LAGRANGE_EMB_BIN="${CMAKE_INSTALL_PREFIX}/resources.lgr") 445 LAGRANGE_EMB_BIN="${CMAKE_INSTALL_PREFIX}/resources.lgr")
445 install (FILES ${EMB_BIN} DESTINATION .) 446 install (FILES ${EMB_BIN} DESTINATION .)
446elseif (UNIX AND NOT APPLE) 447elseif (UNIX AND NOT APPLE)
448 include (GNUInstallDirs)
447 set_target_properties (app PROPERTIES 449 set_target_properties (app PROPERTIES
448 INSTALL_RPATH_USE_LINK_PATH YES 450 INSTALL_RPATH_USE_LINK_PATH YES
449 ) 451 )
@@ -459,18 +461,19 @@ StartupWMClass=lagrange
459Icon=fi.skyjake.Lagrange 461Icon=fi.skyjake.Lagrange
460MimeType=x-scheme-handler/gemini;x-scheme-handler/gopher; 462MimeType=x-scheme-handler/gemini;x-scheme-handler/gopher;
461") 463")
462 install (TARGETS app DESTINATION bin) 464 install (TARGETS app DESTINATION ${CMAKE_INSTALL_BINDIR})
463 install (FILES ${desktop} DESTINATION share/applications) 465 install (FILES ${desktop} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
464 install (FILES res/lagrange-256.png 466 install (FILES res/lagrange-256.png
465 DESTINATION share/icons/hicolor/256x256/apps 467 DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps
466 RENAME fi.skyjake.Lagrange.png 468 RENAME fi.skyjake.Lagrange.png
467 ) 469 )
468 install (FILES res/fi.skyjake.Lagrange.appdata.xml 470 install (FILES res/fi.skyjake.Lagrange.appdata.xml
469 DESTINATION share/metainfo 471 DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo
470 ) 472 )
471 if (NOT ENABLE_RELATIVE_EMBED) 473 if (NOT ENABLE_RELATIVE_EMBED)
472 target_compile_definitions (app PUBLIC 474 target_compile_definitions (app PUBLIC
473 LAGRANGE_EMB_BIN="${CMAKE_INSTALL_PREFIX}/share/lagrange/resources.lgr") 475 LAGRANGE_EMB_BIN="${CMAKE_INSTALL_FULL_DATADIR}/lagrange/resources.lgr")
476 endif ()
474 endif () 477 endif ()
475 install (FILES ${EMB_BIN} DESTINATION share/lagrange) 478 install (FILES ${EMB_BIN} DESTINATION ${CMAKE_INSTALL_DATADIR}/lagrange)
476endif () 479endif ()
diff --git a/Depends.cmake b/Depends.cmake
index d7031035..0ea313f3 100644
--- a/Depends.cmake
+++ b/Depends.cmake
@@ -43,12 +43,13 @@ else ()
43 endif () 43 endif ()
44endif () 44endif ()
45 45
46if (ENABLE_HARFBUZZ AND EXISTS ${CMAKE_SOURCE_DIR}/lib/harfbuzz/CMakeLists.txt) 46if (ENABLE_HARFBUZZ)
47 # Find HarfBuzz with pkg-config. 47 # Find HarfBuzz with pkg-config.
48 if (NOT ENABLE_HARFBUZZ_MINIMAL AND PKG_CONFIG_FOUND) 48 if (NOT ENABLE_HARFBUZZ_MINIMAL AND PKG_CONFIG_FOUND)
49 pkg_check_modules (HARFBUZZ IMPORTED_TARGET harfbuzz) 49 pkg_check_modules (HARFBUZZ IMPORTED_TARGET harfbuzz)
50 endif () 50 endif ()
51 if (ENABLE_HARFBUZZ_MINIMAL OR NOT HARFBUZZ_FOUND) 51 if (EXISTS ${CMAKE_SOURCE_DIR}/lib/harfbuzz/CMakeLists.txt AND
52 (ENABLE_HARFBUZZ_MINIMAL OR NOT HARFBUZZ_FOUND))
52 # Build HarfBuzz with minimal dependencies. 53 # Build HarfBuzz with minimal dependencies.
53 if (MESON_EXECUTABLE AND NINJA_EXECUTABLE) 54 if (MESON_EXECUTABLE AND NINJA_EXECUTABLE)
54 set (_dst ${CMAKE_BINARY_DIR}/lib/harfbuzz) 55 set (_dst ${CMAKE_BINARY_DIR}/lib/harfbuzz)
@@ -107,12 +108,12 @@ if (ENABLE_HARFBUZZ AND EXISTS ${CMAKE_SOURCE_DIR}/lib/harfbuzz/CMakeLists.txt)
107 endif () 108 endif ()
108endif () 109endif ()
109 110
110if (ENABLE_FRIBIDI AND EXISTS ${CMAKE_SOURCE_DIR}/lib/fribidi) 111if (ENABLE_FRIBIDI)
111 # Find FriBidi with pkg-config. 112 # Find FriBidi with pkg-config.
112 if (NOT ENABLE_FRIBIDI_BUILD AND PKG_CONFIG_FOUND) 113 if (NOT ENABLE_FRIBIDI_BUILD AND PKG_CONFIG_FOUND)
113 pkg_check_modules (FRIBIDI IMPORTED_TARGET fribidi) 114 pkg_check_modules (FRIBIDI IMPORTED_TARGET fribidi)
114 endif () 115 endif ()
115 if (ENABLE_FRIBIDI_BUILD OR NOT FRIBIDI_FOUND) 116 if (EXISTS ${CMAKE_SOURCE_DIR}/lib/fribidi AND (ENABLE_FRIBIDI_BUILD OR NOT FRIBIDI_FOUND))
116 # Build FriBidi with Meson. 117 # Build FriBidi with Meson.
117 set (_dst ${CMAKE_BINARY_DIR}/lib/fribidi) 118 set (_dst ${CMAKE_BINARY_DIR}/lib/fribidi)
118 if (MESON_EXECUTABLE AND NINJA_EXECUTABLE) 119 if (MESON_EXECUTABLE AND NINJA_EXECUTABLE)
diff --git a/README.md b/README.md
index d32988af..9e68bf26 100644
--- a/README.md
+++ b/README.md
@@ -19,12 +19,14 @@ Like Gemini, Lagrange has been designed with minimalism in mind. It depends on a
19 19
20## Downloads 20## Downloads
21 21
22Prebuilt binaries for Windows, macOS and Linux can be found in [Releases][rel]. You can also find [Lagrange on Flathub for Linux](https://flathub.org/apps/details/fi.skyjake.Lagrange). 22Prebuilt binaries for Windows, macOS (10.13 or later) and Linux can be found in [Releases][rel]. You can also find [Lagrange on Flathub for Linux](https://flathub.org/apps/details/fi.skyjake.Lagrange).
23 23
24On macOS you can install and upgrade via Homebrew: 24On macOS you can install and upgrade via Homebrew:
25 25
26 brew install --cask lagrange 26 brew install --cask lagrange
27 27
28Please check [MacPorts](https://www.macports.org) if you are using macOS 10.12 or older.
29
28On openSUSE Tumbleweed: 30On openSUSE Tumbleweed:
29 31
30 sudo zypper install lagrange 32 sudo zypper install lagrange
diff --git a/po/de.po b/po/de.po
index 50f8a160..0f9b2fa5 100644
--- a/po/de.po
+++ b/po/de.po
@@ -1,7 +1,7 @@
1msgid "" 1msgid ""
2msgstr "" 2msgstr ""
3"Report-Msgid-Bugs-To: jaakko.keranen@iki.fi\n" 3"Report-Msgid-Bugs-To: jaakko.keranen@iki.fi\n"
4"PO-Revision-Date: 2021-09-20 20:49+0000\n" 4"PO-Revision-Date: 2021-11-14 20:50+0000\n"
5"Last-Translator: Alex Schroeder <alex@alexschroeder.ch>\n" 5"Last-Translator: Alex Schroeder <alex@alexschroeder.ch>\n"
6"Language-Team: German <http://weblate.skyjake.fi/projects/lagrange/ui/de/>\n" 6"Language-Team: German <http://weblate.skyjake.fi/projects/lagrange/ui/de/>\n"
7"Language: de\n" 7"Language: de\n"
@@ -12,13 +12,13 @@ msgstr ""
12"X-Generator: Weblate 4.5.1\n" 12"X-Generator: Weblate 4.5.1\n"
13 13
14msgid "menu.opentab" 14msgid "menu.opentab"
15msgstr "In neuem Tab öffnen" 15msgstr "In neuem Reiter öffnen"
16 16
17msgid "menu.feeds.entrylist" 17msgid "menu.feeds.entrylist"
18msgstr "Feed-Einträge anzeigen" 18msgstr "Feed-Einträge anzeigen"
19 19
20msgid "feeds.entry.newtab" 20msgid "feeds.entry.newtab"
21msgstr "Eintrag in neuem Tab öffnen" 21msgstr "Eintrag in neuem Reiter öffnen"
22 22
23msgid "cancel" 23msgid "cancel"
24msgstr "Abbrechen" 24msgstr "Abbrechen"
@@ -33,10 +33,10 @@ msgid "dlg.default"
33msgstr " Ok " 33msgstr " Ok "
34 34
35msgid "toggle.yes" 35msgid "toggle.yes"
36msgstr "JA" 36msgstr "Ja"
37 37
38msgid "toggle.no" 38msgid "toggle.no"
39msgstr "NEIN" 39msgstr "Nein"
40 40
41msgid "menu.title.file" 41msgid "menu.title.file"
42msgstr "Datei" 42msgstr "Datei"
@@ -57,22 +57,22 @@ msgid "menu.title.help"
57msgstr "Hilfe" 57msgstr "Hilfe"
58 58
59msgid "menu.newtab" 59msgid "menu.newtab"
60msgstr "Neuer Tab" 60msgstr "Neuer Reiter"
61 61
62msgid "menu.closetab" 62msgid "menu.closetab"
63msgstr "Tab schließen" 63msgstr "Reiter schließen"
64 64
65msgid "menu.closetab.other" 65msgid "menu.closetab.other"
66msgstr "Andere Tabs schließen" 66msgstr "Andere Reiter schließen"
67 67
68msgid "menu.closetab.left" 68msgid "menu.closetab.left"
69msgstr "Tabs links schließen" 69msgstr "Reiter links schließen"
70 70
71msgid "menu.closetab.right" 71msgid "menu.closetab.right"
72msgstr "Tabs rechts schließen" 72msgstr "Reiter rechts schließen"
73 73
74msgid "menu.duptab" 74msgid "menu.duptab"
75msgstr "Tab duplizieren" 75msgstr "Reiter duplizieren"
76 76
77msgid "feeds.entry.markread" 77msgid "feeds.entry.markread"
78msgstr "Als gelesen markieren" 78msgstr "Als gelesen markieren"
@@ -81,7 +81,7 @@ msgid "feeds.entry.markunread"
81msgstr "Als ungelesen markieren" 81msgstr "Als ungelesen markieren"
82 82
83msgid "menu.opentab.background" 83msgid "menu.opentab.background"
84msgstr "Tab im Hintergrund öffnen" 84msgstr "Reiter im Hintergrund öffnen"
85 85
86msgid "about.logo" 86msgid "about.logo"
87msgstr "ASCII-Kunst: Das Wort \"Lagrange\" in großer Schrift" 87msgstr "ASCII-Kunst: Das Wort \"Lagrange\" in großer Schrift"
@@ -135,7 +135,7 @@ msgid "menu.bookmarks.list"
135msgstr "Alle Lesezeichen auflisten" 135msgstr "Alle Lesezeichen auflisten"
136 136
137msgid "menu.bookmarks.bytag" 137msgid "menu.bookmarks.bytag"
138msgstr "Lesezeichen nach Tags auflisten" 138msgstr "Lesezeichen nach Schlagworten auflisten"
139 139
140msgid "menu.sidebar.right" 140msgid "menu.sidebar.right"
141msgstr "Rechte Seitenleiste ein-/ausblenden" 141msgstr "Rechte Seitenleiste ein-/ausblenden"
@@ -144,13 +144,13 @@ msgid "menu.zoom.in"
144msgstr "Vergrößern" 144msgstr "Vergrößern"
145 145
146msgid "macos.menu.bookmarks.bytag" 146msgid "macos.menu.bookmarks.bytag"
147msgstr "Nach Tags auflisten" 147msgstr "Nach Schlagworten auflisten"
148 148
149msgid "menu.bookmarks.bytime" 149msgid "menu.bookmarks.bytime"
150msgstr "Lesezeichen nach Erstellungszeitpunkt auflisten" 150msgstr "Lesezeichen nach Erstellungszeitpunkt auflisten"
151 151
152msgid "menu.preferences" 152msgid "menu.preferences"
153msgstr "Einstellungen…" 153msgstr "Präferenzen…"
154 154
155msgid "menu.help" 155msgid "menu.help"
156msgstr "Hilfe" 156msgstr "Hilfe"
@@ -195,7 +195,7 @@ msgid "menu.parent"
195msgstr "Nach oben" 195msgstr "Nach oben"
196 196
197msgid "keys.tab.next" 197msgid "keys.tab.next"
198msgstr "Nächster Tab" 198msgstr "Nächster Reiter"
199 199
200msgid "menu.sidebar.left" 200msgid "menu.sidebar.left"
201msgstr "Linke Seitenleiste ein-/ausblenden" 201msgstr "Linke Seitenleiste ein-/ausblenden"
@@ -204,7 +204,7 @@ msgid "menu.root"
204msgstr "Zum Hauptknoten" 204msgstr "Zum Hauptknoten"
205 205
206msgid "menu.reload" 206msgid "menu.reload"
207msgstr "Seite neu laden" 207msgstr "Seite aktualisieren"
208 208
209msgid "menu.autoreload" 209msgid "menu.autoreload"
210msgstr "Automatische Aktualisierung…" 210msgstr "Automatische Aktualisierung…"
@@ -298,10 +298,10 @@ msgid "feeds.entry.bookmark"
298msgstr "Lesezeichen hinzufügen…" 298msgstr "Lesezeichen hinzufügen…"
299 299
300msgid "dlg.confirm.history.clear" 300msgid "dlg.confirm.history.clear"
301msgstr "Wollen Sie wirklich die Chronik aller besuchten Seiten löschen?" 301msgstr "Wollen Sie wirklich den Verlauf aller besuchten Seiten löschen?"
302 302
303msgid "heading.bookmark.edit" 303msgid "heading.bookmark.edit"
304msgstr "LESEZEICHEN BEARBEITEN" 304msgstr "Lesezeichen bearbeiten"
305 305
306msgid "dlg.openlink" 306msgid "dlg.openlink"
307msgstr "Link öffnen" 307msgstr "Link öffnen"
@@ -319,10 +319,10 @@ msgid "dlg.save.incomplete"
319msgstr "Die Seiteninhalte werden noch heruntergeladen." 319msgstr "Die Seiteninhalte werden noch heruntergeladen."
320 320
321msgid "heading.save.incomplete" 321msgid "heading.save.incomplete"
322msgstr "SEITE UNVOLLSTNDIG" 322msgstr "Seite unvollstndig"
323 323
324msgid "heading.save" 324msgid "heading.save"
325msgstr "DATEI GESPEICHERT" 325msgstr "Datei gespeichert"
326 326
327msgid "dlg.input.send" 327msgid "dlg.input.send"
328msgstr "Senden" 328msgstr "Senden"
@@ -375,7 +375,7 @@ msgid "heading.prefs.colors"
375msgstr "Farben" 375msgstr "Farben"
376 376
377msgid "dlg.bookmark.tags" 377msgid "dlg.bookmark.tags"
378msgstr "Stichwörter:" 378msgstr "Schlagworte:"
379 379
380msgid "dlg.bookmark.url" 380msgid "dlg.bookmark.url"
381msgstr "URL:" 381msgstr "URL:"
@@ -384,7 +384,7 @@ msgid "dlg.feed.title"
384msgstr "Titel:" 384msgstr "Titel:"
385 385
386msgid "heading.feedcfg" 386msgid "heading.feedcfg"
387msgstr "FEED EINSTELLUNGEN" 387msgstr "Feed Einstellungen"
388 388
389msgid "dlg.newident.country" 389msgid "dlg.newident.country"
390msgstr "Land:" 390msgstr "Land:"
@@ -396,7 +396,7 @@ msgid "dlg.newident.email"
396msgstr "Email:" 396msgstr "Email:"
397 397
398msgid "heading.bookmark.add" 398msgid "heading.bookmark.add"
399msgstr "LESEZEICHEN HINZUFGEN" 399msgstr "Lesezeichen hinzufgen"
400 400
401msgid "dlg.feed.sub" 401msgid "dlg.feed.sub"
402msgstr "Abonnieren" 402msgstr "Abonnieren"
@@ -414,7 +414,7 @@ msgid "link.noproxy"
414msgstr "Ohne Proxy öffnen" 414msgstr "Ohne Proxy öffnen"
415 415
416msgid "link.newtab" 416msgid "link.newtab"
417msgstr "Link in neuem Tab öffnen" 417msgstr "Link in neuem Reiter öffnen"
418 418
419#, c-format 419#, c-format
420msgid "dlg.import.add" 420msgid "dlg.import.add"
@@ -423,7 +423,7 @@ msgstr[0] "%sLesezeichen hinzufügen"
423msgstr[1] "" 423msgstr[1] ""
424 424
425msgid "heading.import.bookmarks" 425msgid "heading.import.bookmarks"
426msgstr "LESEZEICHEN IMPORTIEREN" 426msgstr "Lesezeichen importieren"
427 427
428msgid "sidebar.entry.bookmark" 428msgid "sidebar.entry.bookmark"
429msgstr "Lesezeichen hinzufügen…" 429msgstr "Lesezeichen hinzufügen…"
@@ -447,10 +447,10 @@ msgid "menu.forgeturl"
447msgstr "URL vergessen" 447msgstr "URL vergessen"
448 448
449msgid "dlg.history.clear" 449msgid "dlg.history.clear"
450msgstr "Chronik löschen" 450msgstr "Verlauf löschen"
451 451
452msgid "history.clear" 452msgid "history.clear"
453msgstr "Chronik löschen…" 453msgstr "Verlauf löschen…"
454 454
455msgid "bookmark.tag.home" 455msgid "bookmark.tag.home"
456msgstr "Als Startseite verwenden" 456msgstr "Als Startseite verwenden"
@@ -494,7 +494,7 @@ msgid "dlg.translate.fail"
494msgstr "Anfrage fehlgeschlagen" 494msgstr "Anfrage fehlgeschlagen"
495 495
496msgid "heading.translate" 496msgid "heading.translate"
497msgstr "SEITE BERSETZEN" 497msgstr "Seite bersetzen"
498 498
499msgid "bookmark.title.blank" 499msgid "bookmark.title.blank"
500msgstr "Leere Seite" 500msgstr "Leere Seite"
@@ -549,7 +549,7 @@ msgid "heading.prefs.network"
549msgstr "Netzwerk" 549msgstr "Netzwerk"
550 550
551msgid "heading.prefs.paragraph" 551msgid "heading.prefs.paragraph"
552msgstr "ABSATZ" 552msgstr "Absatz"
553 553
554msgid "prefs.theme.dark" 554msgid "prefs.theme.dark"
555msgstr "Dunkel" 555msgstr "Dunkel"
@@ -583,16 +583,16 @@ msgid "prefs.proxy.gemini"
583msgstr "Gemini Proxy:" 583msgstr "Gemini Proxy:"
584 584
585msgid "keys.reload" 585msgid "keys.reload"
586msgstr "Seite neu laden" 586msgstr "Seite aktualisieren"
587 587
588msgid "keys.bookmark.add" 588msgid "keys.bookmark.add"
589msgstr "Lesezeichen hinzufügen" 589msgstr "Lesezeichen hinzufügen"
590 590
591msgid "keys.tab.new" 591msgid "keys.tab.new"
592msgstr "Neuer Tab" 592msgstr "Neuer Reiter"
593 593
594msgid "keys.tab.close" 594msgid "keys.tab.close"
595msgstr "Tab schließen" 595msgstr "Reiter schließen"
596 596
597msgid "error.cert.invalid" 597msgid "error.cert.invalid"
598msgstr "Ungültiges Zertifikat" 598msgstr "Ungültiges Zertifikat"
@@ -632,8 +632,8 @@ msgstr "Eine Seite zurück"
632 632
633msgid "num.bytes" 633msgid "num.bytes"
634msgid_plural "num.bytes.n" 634msgid_plural "num.bytes.n"
635msgstr[0] "%zu Byte" 635msgstr[0] "%u Byte"
636msgstr[1] "%zu Bytes" 636msgstr[1] "%u Bytes"
637 637
638# strftime() formatted, split on two lines 638# strftime() formatted, split on two lines
639#, c-format 639#, c-format
@@ -652,19 +652,19 @@ msgid "menu.bookmarks.refresh"
652msgstr "Remote-Lesezeichen aktualisieren" 652msgstr "Remote-Lesezeichen aktualisieren"
653 653
654msgid "feeds.unsubscribe" 654msgid "feeds.unsubscribe"
655msgstr "Deabonnieren…" 655msgstr "Abonnement abbestellen…"
656 656
657msgid "menu.dup" 657msgid "menu.dup"
658msgstr "Duplizieren …" 658msgstr "Duplizieren …"
659 659
660msgid "heading.history.clear" 660msgid "heading.history.clear"
661msgstr "VERLAUF LSCHEN" 661msgstr "Verlauf lschen"
662 662
663msgid "bookmark.tag.remote" 663msgid "bookmark.tag.remote"
664msgstr "Als Lesezeichen-Quelle verwenden" 664msgstr "Als Lesezeichen-Quelle verwenden"
665 665
666msgid "bookmark.untag.sub" 666msgid "bookmark.untag.sub"
667msgstr "Feed-Abonnement kündigen" 667msgstr "Feed-Abonnement abbestellen"
668 668
669msgid "bookmark.untag.remote" 669msgid "bookmark.untag.remote"
670msgstr "Lesezeichen-Quelle entfernen" 670msgstr "Lesezeichen-Quelle entfernen"
@@ -688,7 +688,7 @@ msgstr "Laden"
688 688
689# Inline download status message. 689# Inline download status message.
690msgid "media.download.warnclose" 690msgid "media.download.warnclose"
691msgstr "Der Download wird abgebrochen, wenn Sie diesen Tab schließen." 691msgstr "Der Download wird abgebrochen, wenn Sie diesen Reiter schließen."
692 692
693# Inline download status message. 693# Inline download status message.
694msgid "media.download.complete" 694msgid "media.download.complete"
@@ -728,8 +728,8 @@ msgstr "Feed-Einträge"
728#, c-format 728#, c-format
729msgid "feeds.list.entrycount" 729msgid "feeds.list.entrycount"
730msgid_plural "feeds.list.entrycount.n" 730msgid_plural "feeds.list.entrycount.n"
731msgstr[0] "insgesamt %zu Eintrag" 731msgstr[0] "insgesamt einen Eintrag"
732msgstr[1] "insgesamt %zu Einträge" 732msgstr[1] "insgesamt %u Einträge"
733 733
734#, c-format 734#, c-format
735msgid "feeds.list.refreshtime" 735msgid "feeds.list.refreshtime"
@@ -780,22 +780,22 @@ msgid "ident.delete"
780msgstr "Identität löschen …" 780msgstr "Identität löschen …"
781 781
782msgid "heading.ident.delete" 782msgid "heading.ident.delete"
783msgstr "IDENTITT LSCHEN" 783msgstr "Identitt lschen"
784 784
785#, c-format 785#, c-format
786msgid "ident.usedonurls" 786msgid "ident.usedonurls"
787msgid_plural "ident.usedonurls.n" 787msgid_plural "ident.usedonurls.n"
788msgstr[0] "Verwendet bei %zu URL" 788msgstr[0] "Verwendet für eine URL"
789msgstr[1] "Verwendet bei %zu URLs" 789msgstr[1] "Verwendet für %u URLs"
790 790
791msgid "ident.using" 791msgid "ident.using"
792msgstr "Verwenden für diese Seite" 792msgstr "Verwenden für diese Seite"
793 793
794msgid "heading.ident.use" 794msgid "heading.ident.use"
795msgstr "IDENTITTSVERWENDUNG" 795msgstr "Identittsverwendung"
796 796
797msgid "heading.ident.notes" 797msgid "heading.ident.notes"
798msgstr "IDENTITTSANMERKUNGEN" 798msgstr "Identittsanmerkungen"
799 799
800msgid "ident.showuse" 800msgid "ident.showuse"
801msgstr "Verwendung anzeigen" 801msgstr "Verwendung anzeigen"
@@ -807,20 +807,17 @@ msgid "sidebar.empty.idents"
807msgstr "keine Identitäten" 807msgstr "keine Identitäten"
808 808
809msgid "heading.unsub" 809msgid "heading.unsub"
810msgstr "ABONNEMENT KÜNDIGEN" 810msgstr "Abonnement abbestellen"
811 811
812#, c-format 812#, c-format
813msgid "dlg.confirm.unsub" 813msgid "dlg.confirm.unsub"
814msgstr "" 814msgstr "Feed wirklich abbestellen: \"%s\"?"
815"Feed wirklich abbestellen:\n"
816"\"%s\"?"
817 815
818#, c-format 816#, c-format
819msgid "dlg.confirm.ident.delete" 817msgid "dlg.confirm.ident.delete"
820msgstr "" 818msgstr ""
821"Wollen Sie wirklich die Identität\n" 819"Wollen Sie wirklich die Identität %s\"%s\"%s einschließlich ihrer "
822" %s%s%s\n" 820"Zertifikats- und privaten Schlüsseldateien löschen?"
823"einschließlich ihrer Zertifikats- und privaten Schlüsseldateien löschen?"
824 821
825# The %s format characters are used to highlight the word "Help" and must be used in the translation in same way as here. 822# The %s format characters are used to highlight the word "Help" and must be used in the translation in same way as here.
826#, c-format 823#, c-format
@@ -829,7 +826,7 @@ msgstr ""
829"Weitere Informationen zu TLS-Client-Zertifikaten finden Sie unter %sHelp%s." 826"Weitere Informationen zu TLS-Client-Zertifikaten finden Sie unter %sHelp%s."
830 827
831msgid "heading.openlink" 828msgid "heading.openlink"
832msgstr "LINK FFNEN" 829msgstr "Link ffnen"
833 830
834msgid "prefs.boldlink" 831msgid "prefs.boldlink"
835msgstr "Fettgedruckte Links:" 832msgstr "Fettgedruckte Links:"
@@ -846,7 +843,7 @@ msgid "lang.zh.hant"
846msgstr "Chinesisch (traditionell)" 843msgstr "Chinesisch (traditionell)"
847 844
848msgid "heading.newident" 845msgid "heading.newident"
849msgstr "NEUE IDENTITT" 846msgstr "Neue Identitt"
850 847
851msgid "dlg.newident.rsa.selfsign" 848msgid "dlg.newident.rsa.selfsign"
852msgstr "Erstellen eines selbstsignierten 2048-Bit-RSA-Zertifikats." 849msgstr "Erstellen eines selbstsignierten 2048-Bit-RSA-Zertifikats."
@@ -890,11 +887,11 @@ msgstr[1] ""
890 887
891# Interpret as "Results from bookmarks..." 888# Interpret as "Results from bookmarks..."
892msgid "heading.lookup.bookmarks" 889msgid "heading.lookup.bookmarks"
893msgstr "LESEZEICHEN" 890msgstr "Lesezeichen"
894 891
895# Interpret as "Results from feeds..." 892# Interpret as "Results from feeds..."
896msgid "heading.lookup.feeds" 893msgid "heading.lookup.feeds"
897msgstr "FEEDS" 894msgstr "Feeds"
898 895
899msgid "dlg.newident.until" 896msgid "dlg.newident.until"
900msgstr "Gültig bis:" 897msgstr "Gültig bis:"
@@ -931,7 +928,7 @@ msgid "dlg.unsub"
931msgstr "Abbestellen" 928msgstr "Abbestellen"
932 929
933msgid "heading.pageinfo" 930msgid "heading.pageinfo"
934msgstr "SEITENINFORMATION" 931msgstr "Seiteninformation"
935 932
936msgid "pageinfo.header.cached" 933msgid "pageinfo.header.cached"
937msgstr "(zwischengespeicherter Inhalt)" 934msgstr "(zwischengespeicherter Inhalt)"
@@ -952,13 +949,14 @@ msgid "pageinfo.domain.match"
952msgstr "Domänenname stimmt überein" 949msgstr "Domänenname stimmt überein"
953 950
954msgid "heading.save.error" 951msgid "heading.save.error"
955msgstr "FEHLER BEIM SPEICHERN DER DATEI" 952msgstr "Fehler beim Speichern der Datei"
956 953
957msgid "dlg.autoreload" 954msgid "dlg.autoreload"
958msgstr "Wählen Sie das Intervall für das automatische Neuladen für diese Tab." 955msgstr ""
956"Wählen Sie das Intervall für die automatische Aktualisierung des Reiters."
959 957
960msgid "link.newtab.background" 958msgid "link.newtab.background"
961msgstr "Link im Hintergrund-Tab öffnen" 959msgstr "Link in einem neuen Reiter im Hintergrund öffnen"
962 960
963msgid "link.browser" 961msgid "link.browser"
964msgstr "Link im Standardbrowser öffnen" 962msgstr "Link im Standardbrowser öffnen"
@@ -973,23 +971,23 @@ msgstr ""
973"Problem der Serverkonfiguration sein." 971"Problem der Serverkonfiguration sein."
974 972
975msgid "heading.certimport" 973msgid "heading.certimport"
976msgstr "IDENTITT IMPORTIEREN" 974msgstr "Identitt importieren"
977 975
978# Interpret as "Results from history..." 976# Interpret as "Results from history..."
979msgid "heading.lookup.history" 977msgid "heading.lookup.history"
980msgstr "Chronik" 978msgstr "Verlauf"
981 979
982# Interpret as "Results from page content..." 980# Interpret as "Results from page content..."
983msgid "heading.lookup.pagecontent" 981msgid "heading.lookup.pagecontent"
984msgstr "SEITENINHALT" 982msgstr "Seiteninhalt"
985 983
986# Interpret as "Results from identitites..." 984# Interpret as "Results from identitites..."
987msgid "heading.lookup.identities" 985msgid "heading.lookup.identities"
988msgstr "IDENTITTEN" 986msgstr "Identitten"
989 987
990# Interpret as "Other results..." 988# Interpret as "Other results..."
991msgid "heading.lookup.other" 989msgid "heading.lookup.other"
992msgstr "ANDERE" 990msgstr "Andere"
993 991
994msgid "dlg.translate.unavail" 992msgid "dlg.translate.unavail"
995msgstr "Dienst nicht verfügbar" 993msgstr "Dienst nicht verfügbar"
@@ -1010,7 +1008,7 @@ msgid "dlg.newident.userid"
1010msgstr "Benutzer-ID:" 1008msgstr "Benutzer-ID:"
1011 1009
1012msgid "heading.subscribe" 1010msgid "heading.subscribe"
1013msgstr "SEITE ABONNIEREN" 1011msgstr "Seite abonnieren"
1014 1012
1015msgid "dlg.feed.entrytype" 1013msgid "dlg.feed.entrytype"
1016msgstr "Eintragstyp:" 1014msgstr "Eintragstyp:"
@@ -1022,13 +1020,13 @@ msgid "dlg.bookmark.icon"
1022msgstr "Symbol:" 1020msgstr "Symbol:"
1023 1021
1024msgid "heading.prefs.scrolling" 1022msgid "heading.prefs.scrolling"
1025msgstr "BLTTERN" 1023msgstr "Blttern"
1026 1024
1027msgid "heading.prefs.sizing" 1025msgid "heading.prefs.sizing"
1028msgstr "GRßENEINTEILUNG" 1026msgstr "Grßeneinteilung"
1029 1027
1030msgid "heading.prefs.widelayout" 1028msgid "heading.prefs.widelayout"
1031msgstr "BREITES LAYOUT" 1029msgstr "Breites Layout"
1032 1030
1033msgid "prefs.hoverlink" 1031msgid "prefs.hoverlink"
1034msgstr "URL bei Mauszeiger anzeigen:" 1032msgstr "URL bei Mauszeiger anzeigen:"
@@ -1064,7 +1062,7 @@ msgid "prefs.accent.teal"
1064msgstr "Türkisblau" 1062msgstr "Türkisblau"
1065 1063
1066msgid "prefs.uiscale" 1064msgid "prefs.uiscale"
1067msgstr "UI-Skalierungsfaktor:" 1065msgstr "Skalierungsfaktor der Oberfläche :"
1068 1066
1069msgid "prefs.customframe" 1067msgid "prefs.customframe"
1070msgstr "Individueller Fensterrahmen:" 1068msgstr "Individueller Fensterrahmen:"
@@ -1154,10 +1152,10 @@ msgid "heading.certwarn"
1154msgstr "NICHT VERTRAUENSWÜRDIGES ZERTIFIKAT" 1152msgstr "NICHT VERTRAUENSWÜRDIGES ZERTIFIKAT"
1155 1153
1156msgid "heading.certimport.pasted" 1154msgid "heading.certimport.pasted"
1157msgstr "AUS DER ZWISCHENABLAGE EINGEFGT" 1155msgstr "Aus der Zwischenablage eingefgt"
1158 1156
1159msgid "heading.certimport.dropped" 1157msgid "heading.certimport.dropped"
1160msgstr "VERLORENE DATEI" 1158msgstr "Abgelegte Datei"
1161 1159
1162msgid "hint.certimport.description" 1160msgid "hint.certimport.description"
1163msgstr "Beschreibung" 1161msgstr "Beschreibung"
@@ -1191,23 +1189,23 @@ msgid "dlg.newident.create"
1191msgstr "Identität erstellen" 1189msgstr "Identität erstellen"
1192 1190
1193msgid "heading.prefs" 1191msgid "heading.prefs"
1194msgstr "PREFERENZEN" 1192msgstr "Präferenzen"
1195 1193
1196msgid "heading.prefs.certs" 1194msgid "heading.prefs.certs"
1197msgstr "ZERTIFIKATE" 1195msgstr "Zertifikate"
1198 1196
1199msgid "heading.prefs.fonts" 1197msgid "heading.prefs.fonts"
1200msgstr "Schriftarten" 1198msgstr "Schriftarten"
1201 1199
1202# tab button 1200# tab button
1203msgid "heading.prefs.keys" 1201msgid "heading.prefs.keys"
1204msgstr "TASTEN" 1202msgstr "Tasten"
1205 1203
1206msgid "heading.prefs.pagecontent" 1204msgid "heading.prefs.pagecontent"
1207msgstr "PAGE COLORS" 1205msgstr "Seitenfarben"
1208 1206
1209msgid "heading.prefs.proxies" 1207msgid "heading.prefs.proxies"
1210msgstr "PROXIES" 1208msgstr "Proxies"
1211 1209
1212msgid "gempub.meta.lang" 1210msgid "gempub.meta.lang"
1213msgstr "Sprache" 1211msgstr "Sprache"
@@ -1367,8 +1365,8 @@ msgstr "Server nicht erreichbar"
1367#, c-format 1365#, c-format
1368msgid "feeds.list.counts" 1366msgid "feeds.list.counts"
1369msgid_plural "feeds.list.counts.n" 1367msgid_plural "feeds.list.counts.n"
1370msgstr[0] "Sie haben %zu Feed mit %%s abonniert.\n" 1368msgstr[0] "Sie haben einen Feed mit %%s abonniert.\n"
1371msgstr[1] "Sie haben %zu Feeds mit %%s abonniert.\n" 1369msgstr[1] "Sie haben %u Feeds mit %%s abonniert.\n"
1372 1370
1373msgid "upload.port" 1371msgid "upload.port"
1374msgstr "Port…" 1372msgstr "Port…"
@@ -1393,7 +1391,7 @@ msgid "prefs.linespacing"
1393msgstr "Zeilenabstand:" 1391msgstr "Zeilenabstand:"
1394 1392
1395msgid "error.tls.msg" 1393msgid "error.tls.msg"
1396msgstr "Die Kommunikation mit dem Server ist fehlgeschlagen. Die Fehlermeldung:" 1394msgstr "Die Kommunikation mit dem Server ist fehlgeschlagen."
1397 1395
1398msgid "error.certexpired" 1396msgid "error.certexpired"
1399msgstr "Zertifikat abgelaufen" 1397msgstr "Zertifikat abgelaufen"
@@ -1452,7 +1450,7 @@ msgid "sidebar.action.ident.import"
1452msgstr "Importieren…" 1450msgstr "Importieren…"
1453 1451
1454msgid "keys.parent" 1452msgid "keys.parent"
1455msgstr "Zum darüber liegenden Verzeichnis" 1453msgstr "Zum darüber liegenden Ordner"
1456 1454
1457msgid "feeds.atom.translated" 1455msgid "feeds.atom.translated"
1458msgstr "" 1456msgstr ""
@@ -1478,13 +1476,13 @@ msgid "bookmark.export.format.tags"
1478msgstr "Schlagworte werden mit Überschriften der Stufe 2 definiert." 1476msgstr "Schlagworte werden mit Überschriften der Stufe 2 definiert."
1479 1477
1480msgid "menu.page.upload" 1478msgid "menu.page.upload"
1481msgstr "Seite mit Titan hochladen" 1479msgstr "Seite mit Titan hochladen"
1482 1480
1483msgid "heading.upload" 1481msgid "heading.upload"
1484msgstr "UPLOAD WITH TITAN" 1482msgstr "Hochladen mit Titan"
1485 1483
1486msgid "hint.upload.text" 1484msgid "hint.upload.text"
1487msgstr "Texteingabe für den Upload" 1485msgstr "Texteingabe für das Hochladen"
1488 1486
1489msgid "heading.upload.file" 1487msgid "heading.upload.file"
1490msgstr "Datei" 1488msgstr "Datei"
@@ -1502,10 +1500,10 @@ msgid "upload.token"
1502msgstr "Kennwort:" 1500msgstr "Kennwort:"
1503 1501
1504msgid "dlg.upload.send" 1502msgid "dlg.upload.send"
1505msgstr "Upload" 1503msgstr "Hochladen"
1506 1504
1507msgid "heading.uploadport" 1505msgid "heading.uploadport"
1508msgstr "TITAN UPLOAD PORT" 1506msgstr "Titan Port"
1509 1507
1510msgid "lang.ia" 1508msgid "lang.ia"
1511msgstr "Interlingua" 1509msgstr "Interlingua"
@@ -1526,13 +1524,13 @@ msgid "prefs.pinsplit.right"
1526msgstr "Rechter Reiter" 1524msgstr "Rechter Reiter"
1527 1525
1528msgid "heading.newident.missing" 1526msgid "heading.newident.missing"
1529msgstr "MISSING INFO" 1527msgstr "Fehlende Information"
1530 1528
1531msgid "heading.newident.date.bad" 1529msgid "heading.newident.date.bad"
1532msgstr "INVALID DATE" 1530msgstr "Ungültiges Datum"
1533 1531
1534msgid "heading.prefs.uitheme" 1532msgid "heading.prefs.uitheme"
1535msgstr "UI COLORS" 1533msgstr "Oberflächenfarben"
1536 1534
1537msgid "prefs.scrollspeed.keyboard" 1535msgid "prefs.scrollspeed.keyboard"
1538msgstr "Tastaturgeschwindigkeit:" 1536msgstr "Tastaturgeschwindigkeit:"
@@ -1626,13 +1624,13 @@ msgid "menu.split.horizontal"
1626msgstr "Horizontal" 1624msgstr "Horizontal"
1627 1625
1628msgid "menu.downloads" 1626msgid "menu.downloads"
1629msgstr "Download Verzeichnis anzeigen" 1627msgstr "Downloads anzeigen"
1630 1628
1631msgid "menu.unexpire" 1629msgid "menu.unexpire"
1632msgstr "Ablaufdatum ignorieren und weiter laden" 1630msgstr "Ablaufdatum ignorieren und weiter laden"
1633 1631
1634msgid "menu.save.downloads.open" 1632msgid "menu.save.downloads.open"
1635msgstr "Im Downloadverzeichnis speichern und Datei öffnen" 1633msgstr "In den Downloads speichern und Datei öffnen"
1636 1634
1637msgid "menu.select.clear" 1635msgid "menu.select.clear"
1638msgstr "Auswahl aufheben" 1636msgstr "Auswahl aufheben"
@@ -1656,7 +1654,7 @@ msgid "dlg.save.opendownload"
1656msgstr "Runtergeladene Datei öffnen" 1654msgstr "Runtergeladene Datei öffnen"
1657 1655
1658msgid "heading.autoreload" 1656msgid "heading.autoreload"
1659msgstr "AUTO-RELOAD" 1657msgstr "Automatische Aktualisierung"
1660 1658
1661msgid "link.side" 1659msgid "link.side"
1662msgstr "Link seitlich öffnen" 1660msgstr "Link seitlich öffnen"
@@ -1668,7 +1666,7 @@ msgid "link.file.delete"
1668msgstr "Datei löschen" 1666msgstr "Datei löschen"
1669 1667
1670msgid "heading.file.delete" 1668msgid "heading.file.delete"
1671msgstr "DELETE FILE" 1669msgstr "Datei löschen"
1672 1670
1673msgid "dlg.file.delete.confirm" 1671msgid "dlg.file.delete.confirm"
1674msgstr "Wollen Sie die Datei wirklich löschen?" 1672msgstr "Wollen Sie die Datei wirklich löschen?"
@@ -1680,7 +1678,7 @@ msgid "menu.pageinfo"
1680msgstr "Seiteninformation anzeigen" 1678msgstr "Seiteninformation anzeigen"
1681 1679
1682msgid "bookmark.export.title.tag" 1680msgid "bookmark.export.title.tag"
1683msgstr "Schlagworte für Lesenzeichen" 1681msgstr "Schlagworte für Lesezeichen"
1684 1682
1685msgid "bookmark.export.count" 1683msgid "bookmark.export.count"
1686msgid_plural "bookmark.export.count.n" 1684msgid_plural "bookmark.export.count.n"
@@ -1698,8 +1696,8 @@ msgstr "Links seitlich öffnen"
1698msgid "bookmark.export.taginfo" 1696msgid "bookmark.export.taginfo"
1699msgstr "" 1697msgstr ""
1700"In diese Liste steht jede Überschrift für ein Lesezeichenschlagwort. Nur " 1698"In diese Liste steht jede Überschrift für ein Lesezeichenschlagwort. Nur "
1701"verschlagwortete Lesezeichen werden aufgeführt. Lesezeichen mir mehreren " 1699"verschlagwortete Lesezeichen werden aufgeführt. Lesezeichen mit mehreren "
1702"Schlagworten werden jedem dieser Schlagworte aufgeführt." 1700"Schlagworten werden unter jedem dieser Schlagworte aufgeführt."
1703 1701
1704msgid "prefs.memorysize" 1702msgid "prefs.memorysize"
1705msgstr "Speichergrösse:" 1703msgstr "Speichergrösse:"
@@ -1710,17 +1708,17 @@ msgstr "Archiv verlassen"
1710#, c-format 1708#, c-format
1711msgid "archive.summary" 1709msgid "archive.summary"
1712msgid_plural "archive.summary.n" 1710msgid_plural "archive.summary.n"
1713msgstr[0] "Dieses Archiv enthält %zu Eintrag und wurde auf %.1f MB komprimiert." 1711msgstr[0] "Dieses Archiv enthält einen Eintrag und wurde auf %.1f MB komprimiert."
1714msgstr[1] "Dieses Archiv enthält %zu Einträge und wurde auf %.1f MB komprimiert." 1712msgstr[1] "Dieses Archiv enthält %u Einträge und wurde auf %.1f MB komprimiert."
1715 1713
1716msgid "dir.empty" 1714msgid "dir.empty"
1717msgstr "Dieses Verzeichnis ist leer." 1715msgstr "Dieser Ordner ist leer."
1718 1716
1719#, c-format 1717#, c-format
1720msgid "dir.summary" 1718msgid "dir.summary"
1721msgid_plural "dir.summary.n" 1719msgid_plural "dir.summary.n"
1722msgstr[0] "Dieses Verzeichnis enthält %zu Eintrag." 1720msgstr[0] "Dieser Ordner enthält einen Eintrag."
1723msgstr[1] "Dieses Verzeichnis enthält %zu Einträge." 1721msgstr[1] "Dieser Ordner enthält %u Einträge."
1724 1722
1725msgid "keys.zoom.out" 1723msgid "keys.zoom.out"
1726msgstr "Verkleinern" 1724msgstr "Verkleinern"
@@ -1745,8 +1743,8 @@ msgstr "siehe Instruktionen des Servers"
1745 1743
1746msgid "dlg.uploadport.msg" 1744msgid "dlg.uploadport.msg"
1747msgstr "" 1745msgstr ""
1748"Setzt den Port des Titanservers für diese URL.\n" 1746"Setzt den Port des Titanservers für diese URL. Der Port wird in der "
1749"Der Port wird für diesen Site gespeichert." 1747"Konfiguration für diesen Seiten gespeichert."
1750 1748
1751msgid "lang.tok" 1749msgid "lang.tok"
1752msgstr "Toki Pona" 1750msgstr "Toki Pona"
@@ -1814,3 +1812,303 @@ msgstr ""
1814 1812
1815msgid "error.unsupported.protocol.msg" 1813msgid "error.unsupported.protocol.msg"
1816msgstr "Das gewünschte Protokoll wird von dieser Applikation nicht unterstützt." 1814msgstr "Das gewünschte Protokoll wird von dieser Applikation nicht unterstützt."
1815
1816msgid "dlg.addfolder.defaulttitle"
1817msgstr "Neuer Ordner"
1818
1819# used on mobile
1820msgid "heading.settings"
1821msgstr "Einstellungen"
1822
1823msgid "prefs.imagestyle"
1824msgstr "Bilder einfärben:"
1825
1826msgid "prefs.imagestyle.original"
1827msgstr "Keine"
1828
1829msgid "prefs.imagestyle.grayscale"
1830msgstr "Graustufen"
1831
1832msgid "prefs.imagestyle.text"
1833msgstr "Textfarbe"
1834
1835msgid "prefs.imagestyle.preformat"
1836msgstr "Textfarbe für vorformatierten Text"
1837
1838msgid "prefs.font.heading"
1839msgstr "Titel:"
1840
1841msgid "prefs.font.body"
1842msgstr "Textkörper:"
1843
1844msgid "prefs.font.ui"
1845msgstr "Oberfläche :"
1846
1847# Font to use for headings and body when Monospace body is enabled.
1848msgid "prefs.font.monodoc"
1849msgstr "Nichtproportionale Schrift:"
1850
1851msgid "prefs.boldlink.visited"
1852msgstr "Besucht"
1853
1854msgid "prefs.gemtext.ansi"
1855msgstr "ANSI Code-Umschaltungen:"
1856
1857msgid "prefs.gemtext.ansi.fg"
1858msgstr "Vordergrundfarbe"
1859
1860msgid "prefs.gemtext.ansi.fontstyle"
1861msgstr "Schriftstil"
1862
1863msgid "prefs.font.warnmissing"
1864msgstr "Glyphenwarnungen:"
1865
1866msgid "prefs.font.smooth"
1867msgstr "Glättung:"
1868
1869msgid "keys.bookmark.addfolder"
1870msgstr "Lesezeichenordner hinzufügen"
1871
1872msgid "keys.split.item"
1873msgstr "Aufteilungsmenü:"
1874
1875msgid "keys.hoverurl"
1876msgstr "URL beim Darüberfahren anzeigen"
1877
1878msgid "error.ansi"
1879msgstr "Terminalemulation"
1880
1881msgid "error.glyphs"
1882msgstr "Fehlende Glyphen"
1883
1884msgid "error.glyphs.msg"
1885msgstr ""
1886"Diese Seite kann nicht vollständig angezeigt werden, weil gewisse Charaktere "
1887"fehlen. Mit der Installation zusätzlicher Schriftarten kann dies behoben "
1888"werden."
1889
1890#, c-format
1891msgid "dlg.fontpack.delete.confirm"
1892msgstr "Wollen Sie das Schriftartenpaket \"%s\" wirklich für immer löschen?"
1893
1894msgid "dlg.fontpack.delete"
1895msgstr "Schriftartenpaket löschen"
1896
1897msgid "fontpack.install.ttf"
1898msgstr "TrueType Schriftart installieren"
1899
1900msgid "fontpack.open.aboutfonts"
1901msgstr "Installierte Schriftarten anzeigen"
1902
1903msgid "fontpack.open.fontsdir"
1904msgstr "Benutzerschriftartenordner öffnen"
1905
1906#, c-format
1907msgid "dlg.dismiss.ansi"
1908msgstr "Die Warnung zur Terminalemulation für %s zukünftig ignorieren?"
1909
1910msgid "dlg.dismiss.warning"
1911msgstr "Warnung ignorieren"
1912
1913msgid "dlg.fontpack.classic.msg"
1914msgstr ""
1915"Die Schriftarten, welche bisher mit der Applikation verteilt wurden, gibt es "
1916"nun als separates Download. Wollen Sie das \"Klassik\" Set runterladen?"
1917
1918msgid "dlg.fontpack.classic"
1919msgstr "Schriftartenpaket runterladen (25 MB)"
1920
1921msgid "heading.dismiss.warning"
1922msgstr "Warnung ignorieren?"
1923
1924msgid "heading.fontpack.classic"
1925msgstr "Schriftartenpaket runterladen"
1926
1927msgid "truetype.help"
1928msgstr ""
1929"Lagrange probiert alle TrueType Schriftartendateien zu laden, welche im "
1930"Benutzerschriftartenordner liegen."
1931
1932msgid "truetype.help.installed"
1933msgstr "Diese Schriftart ist im Benutzerschriftartenordner installiert."
1934
1935msgid "lang.gl"
1936msgstr "Galizisch"
1937
1938msgid "dlg.feed.ignoreweb"
1939msgstr "HTTP(S) Links ignorieren:"
1940
1941msgid "heading.bookmark.tags"
1942msgstr "Spezielle Schlagworte"
1943
1944msgid "heading.addfolder"
1945msgstr "Ordner hinzufügen"
1946
1947msgid "keys.link.homerow.next"
1948msgstr "Nächster Satz von Mittelzeiletastenlinks"
1949
1950msgid "menu.newfolder"
1951msgstr "Neuer Ordner…"
1952
1953msgid "menu.sort.alpha"
1954msgstr "Alphabetisch sortieren"
1955
1956# used for Preferences on mobile
1957msgid "menu.settings"
1958msgstr "Einstellungen"
1959
1960# keep this short (3x1 horiz layout)
1961msgid "menu.selectall"
1962msgstr "Alles auswählen"
1963
1964# keep this short (3x1 horiz layout)
1965msgid "menu.delete"
1966msgstr "Löschen"
1967
1968# keep this short (3x1 horiz layout)
1969msgid "menu.undo"
1970msgstr "Rückgängig"
1971
1972msgid "heading.fontpack.meta.disabled"
1973msgstr "Deaktivierte Schriftartenpakete"
1974
1975# Action label
1976msgid "fontpack.meta.viewfile"
1977msgstr "Datei anzeigen"
1978
1979#, c-format
1980msgid "fontpack.meta.version"
1981msgstr "Version %d"
1982
1983msgid "fontpack.meta.installed"
1984msgstr "Installiert"
1985
1986msgid "fontpack.meta.notinstalled"
1987msgstr "Nicht installiert"
1988
1989msgid "fontpack.meta.disabled"
1990msgstr ", deaktiviert"
1991
1992msgid "dlg.addfolder.prompt"
1993msgstr "Name des neuen Ordners:"
1994
1995msgid "dlg.addfolder"
1996msgstr "Ordner hinzufügen"
1997
1998msgid "menu.website"
1999msgstr "Projektwebseite…"
2000
2001msgid "menu.fonts"
2002msgstr "Schriftarten verwalten…"
2003
2004msgid "heading.confirm.bookmarks.delete"
2005msgstr "Lesezeichen löschen"
2006
2007# button in the mobile New Identity dialog
2008msgid "dlg.certimport.pickfile"
2009msgstr "Zertifikats- und privaten Schlüsseldateien importieren"
2010
2011#, c-format
2012msgid "dlg.confirm.bookmarks.delete"
2013msgid_plural "dlg.confirm.bookmarks.delete.n"
2014msgstr[0] "Wollen Sie das Lesezeichen in diesem Ordner wirklich löschen?"
2015msgstr[1] "Wollen Sie die %u Lesezeichen in diesem Ordner wirklich löschen?"
2016
2017msgid "num.files"
2018msgid_plural "num.files.n"
2019msgstr[0] "eine Datei"
2020msgstr[1] "%u Dateien"
2021
2022msgid "num.fonts"
2023msgid_plural "num.fonts.n"
2024msgstr[0] "eine Schriftart"
2025msgstr[1] "%u Schriftarten"
2026
2027msgid "upload.id"
2028msgstr "Identität:"
2029
2030msgid "dlg.upload.id.none"
2031msgstr "Keine"
2032
2033msgid "dlg.upload.id.default"
2034msgstr "Default"
2035
2036# used on mobile
2037msgid "dlg.upload.text"
2038msgstr "Text hochladen"
2039
2040# used on mobile
2041msgid "dlg.upload.file"
2042msgstr "Datei hochladen"
2043
2044# used on mobile
2045msgid "dlg.upload.pickfile"
2046msgstr "Datei auswählen"
2047
2048msgid "prefs.font.mono"
2049msgstr "Vorformatiert:"
2050
2051#, c-format
2052msgid "fontpack.install"
2053msgstr "Installation von \"%s\""
2054
2055msgid "heading.fontpack.delete"
2056msgstr "Schriftartenpaket löschen"
2057
2058#, c-format
2059msgid "dlg.bookmarks.delete"
2060msgid_plural "dlg.bookmarks.delete.n"
2061msgstr[0] "Lesezeichen löschen"
2062msgstr[1] "%u Lesezeichen löschen"
2063
2064msgid "dlg.certwarn.title"
2065msgstr "Sicherheitsproblem"
2066
2067msgid "prefs.bookmarks.addbottom"
2068msgstr "Lesezeichen am Ende hinzufügen:"
2069
2070msgid "error.ansi.msg"
2071msgstr ""
2072"Diese Seite wird möglicherweise nicht richtig dargestellt. Es werden ANSI-"
2073"Code-Umschaltungen verwendet um die Darstellung zu kontrollieren, und das "
2074"wird nur teilweise unterstützt. Verwenden Sie einen Terminalemulator, um "
2075"diese Seite darzustellen."
2076
2077# Abbrevation: background-to-foreground
2078msgid "prefs.imagestyle.bgfg"
2079msgstr "Hintergrund zu Vordergrund"
2080
2081msgid "keys.split.next"
2082msgstr "Fokus zur nächsten Aufteilung"
2083
2084msgid "fontpack.help"
2085msgstr ""
2086"Lagrange Schriftartenpakete sind ZIP Dateien, welche Schriftarten und "
2087"dazugehörige Konfigurationen enthalten. Einmal installiert, können diese "
2088"Schriftarten für die Dokumenteninhalte und die Oberfläche verwendet werden. "
2089"Die aktive Schriftart wählen sie unter Präferenzen > Schriftarten."
2090
2091msgid "heading.fontpack.meta"
2092msgstr "Schriftarten"
2093
2094msgid "heading.fontpack.meta.enabled"
2095msgstr "Aktivierte Schriftartenpakete"
2096
2097#, c-format
2098msgid "fontpack.enable"
2099msgstr "Aktivierung von \"%s\""
2100
2101#, c-format
2102msgid "fontpack.disable"
2103msgstr "Deaktivierung von \"%s\""
2104
2105msgid "fontpack.export"
2106msgstr "Anzeige der fontpack.ini Vorlage"
2107
2108#, c-format
2109msgid "fontpack.upgrade"
2110msgstr "Aktualisieren von \"%s\" auf Version %d"
2111
2112#, c-format
2113msgid "fontpack.delete"
2114msgstr "\"%s\" für immer löschen"
diff --git a/po/en.po b/po/en.po
index 24fed59f..80fee8ae 100644
--- a/po/en.po
+++ b/po/en.po
@@ -1050,87 +1050,50 @@ msgstr "From:"
1050msgid "dlg.translate.to" 1050msgid "dlg.translate.to"
1051msgstr "To:" 1051msgstr "To:"
1052 1052
1053# A language choice in the Translation dialog.
1053msgid "lang.ar" 1054msgid "lang.ar"
1054msgstr "Arabic" 1055msgstr "Arabic"
1055 1056
1057# A language choice in the Translation dialog.
1056msgid "lang.zh" 1058msgid "lang.zh"
1057msgstr "Chinese" 1059msgstr "Chinese"
1058 1060
1059msgid "lang.zh.hans" 1061# A language choice in the Translation dialog.
1060msgstr "Chinese (Simplified)"
1061
1062msgid "lang.zh.hant"
1063msgstr "Chinese (Traditional)"
1064
1065msgid "lang.de" 1062msgid "lang.de"
1066msgstr "German" 1063msgstr "German"
1067 1064
1065# A language choice in the Translation dialog.
1068msgid "lang.en" 1066msgid "lang.en"
1069msgstr "English" 1067msgstr "English"
1070 1068
1071msgid "lang.ia" 1069# A language choice in the Translation dialog.
1072msgstr "Interlingua"
1073
1074msgid "lang.ie"
1075msgstr "Interlingue"
1076
1077msgid "lang.fi"
1078msgstr "Finnish"
1079
1080msgid "lang.fr" 1070msgid "lang.fr"
1081msgstr "French" 1071msgstr "French"
1082 1072
1083msgid "lang.gl" 1073# A language choice in the Translation dialog.
1084msgstr "Galician"
1085
1086msgid "lang.hi" 1074msgid "lang.hi"
1087msgstr "Hindi" 1075msgstr "Hindi"
1088 1076
1077# A language choice in the Translation dialog.
1089msgid "lang.it" 1078msgid "lang.it"
1090msgstr "Italian" 1079msgstr "Italian"
1091 1080
1081# A language choice in the Translation dialog.
1092msgid "lang.ja" 1082msgid "lang.ja"
1093msgstr "Japanese" 1083msgstr "Japanese"
1094 1084
1095msgid "lang.pl" 1085# A language choice in the Translation dialog.
1096msgstr "Polish"
1097
1098msgid "lang.pt" 1086msgid "lang.pt"
1099msgstr "Portuguese" 1087msgstr "Portuguese"
1100 1088
1089# A language choice in the Translation dialog.
1101msgid "lang.ru" 1090msgid "lang.ru"
1102msgstr "Russian" 1091msgstr "Russian"
1103 1092
1104msgid "lang.hu" 1093# A language choice in the Translation dialog.
1105msgstr "Hungarian"
1106
1107msgid "lang.uk"
1108msgstr "Ukrainian"
1109
1110msgid "lang.eo"
1111msgstr "Esperanto"
1112
1113msgid "lang.es" 1094msgid "lang.es"
1114msgstr "Spanish" 1095msgstr "Spanish"
1115 1096
1116msgid "lang.es.mx"
1117msgstr "Spanish (Mexico)"
1118
1119msgid "lang.cs"
1120msgstr "Czech"
1121
1122msgid "lang.sk"
1123msgstr "Slovak"
1124
1125msgid "lang.sr"
1126msgstr "Serbian"
1127
1128msgid "lang.isv"
1129msgstr "Interslavic"
1130
1131msgid "lang.tok"
1132msgstr "Toki Pona"
1133
1134msgid "heading.newident" 1097msgid "heading.newident"
1135msgstr "NEW IDENTITY" 1098msgstr "NEW IDENTITY"
1136 1099
diff --git a/res/about/help.gmi b/res/about/help.gmi
index 4af1581e..3c332f81 100644
--- a/res/about/help.gmi
+++ b/res/about/help.gmi
@@ -825,7 +825,7 @@ semibold = "FiraSans-SemiBold.ttf"
825bold = "FiraSans-Bold.ttf" 825bold = "FiraSans-Bold.ttf"
826``` 826```
827 827
828Fontpacks may use the Deflate compression method, but that can slow down launching the app because each font must then be decompressed before loading. 828Fontpacks may use the Deflate compression method, but that can slow down launching the app because each font must then be decompressed before loading. Therefore, it is recommended to use the -0 (--compression-method store) option when creating the archive. You may also find the -j (--junk-paths) option helpful if the current working directory is not the one where fontpack.ini is located.
829 829
830Each fontpack has an ID that comes from the file name: the ID of "firasans.fontpack" would be "firasans". Space characters are not allowed in the ID. 830Each fontpack has an ID that comes from the file name: the ID of "firasans.fontpack" would be "firasans". Space characters are not allowed in the ID.
831 831
diff --git a/res/about/version.gmi b/res/about/version.gmi
index 66b83cf5..a5e0d01f 100644
--- a/res/about/version.gmi
+++ b/res/about/version.gmi
@@ -17,6 +17,11 @@ Changes and enhancements:
17 17
18Fixes: 18Fixes:
19 19
20## 1.8.3
21* Fixed clicking on UI elements that are over the page top banner. The banner would always get clicked instead.
22* Titan upload identity is remembered as a site-specific setting. It is no longer affected by selections in the Identities sidebar.
23* macOS: Fixed updating items in native menus, e.g., upload identity selection.
24
20## 1.8.2 25## 1.8.2
21* Fixed encoding of `+` characters in URLs as per RFC 3986. 26* Fixed encoding of `+` characters in URLs as per RFC 3986.
22* Fixed crash when fontpack.ini specifies a file that cannot be found. 27* Fixed crash when fontpack.ini specifies a file that cannot be found.
diff --git a/res/fi.skyjake.Lagrange.appdata.xml b/res/fi.skyjake.Lagrange.appdata.xml
index 7cb12f2e..e69cbcf7 100644
--- a/res/fi.skyjake.Lagrange.appdata.xml
+++ b/res/fi.skyjake.Lagrange.appdata.xml
@@ -45,6 +45,25 @@
45 <update_contact>jaakko.keranen@iki.fi</update_contact> 45 <update_contact>jaakko.keranen@iki.fi</update_contact>
46 46
47 <releases> 47 <releases>
48 <release version="1.8.3" date="2021-11-21">
49 <description>
50 <p>Version 1.8 adds a customizable font library and improves warning
51 and errors messages. The bundled hardcoded fonts have been
52 removed, and font configuration is now more flexible. Tabs have
53 close buttons that appear on mouse hover.</p>
54 <p>Changes in v1.8.3:</p>
55 <ul>
56 <li>Fixed clicking on UI elements that are over the page top
57 banner. The banner would always get clicked instead.</li>
58 <li>Titan upload identity is remembered as a site-specific
59 setting. It is no longer affected by selections in the
60 Identities sidebar.</li>
61 </ul>
62 <p>The full release notes can be viewed inside the app by opening
63 the "about:version" page.</p>
64 </description>
65 <url>https://github.com/skyjake/lagrange/releases/tag/v1.8.3</url>
66 </release>
48 <release version="1.8.2" date="2021-11-13"> 67 <release version="1.8.2" date="2021-11-13">
49 <description> 68 <description>
50 <p>Version 1.8 adds a customizable font library and improves warning 69 <p>Version 1.8 adds a customizable font library and improves warning
diff --git a/src/gmcerts.c b/src/gmcerts.c
index 36fd7d55..f95fea7d 100644
--- a/src/gmcerts.c
+++ b/src/gmcerts.c
@@ -295,6 +295,9 @@ static void loadIdentities_GmCerts_(iGmCerts *d) {
295} 295}
296 296
297iGmIdentity *findIdentity_GmCerts(iGmCerts *d, const iBlock *fingerprint) { 297iGmIdentity *findIdentity_GmCerts(iGmCerts *d, const iBlock *fingerprint) {
298 if (isEmpty_Block(fingerprint)) {
299 return NULL;
300 }
298 iForEach(PtrArray, i, &d->idents) { 301 iForEach(PtrArray, i, &d->idents) {
299 iGmIdentity *ident = i.ptr; 302 iGmIdentity *ident = i.ptr;
300 if (cmp_Block(fingerprint, &ident->fingerprint) == 0) { /* TODO: could use a hash */ 303 if (cmp_Block(fingerprint, &ident->fingerprint) == 0) { /* TODO: could use a hash */
@@ -549,6 +552,9 @@ const iGmIdentity *constIdentity_GmCerts(const iGmCerts *d, unsigned int id) {
549} 552}
550 553
551const iGmIdentity *identityForUrl_GmCerts(const iGmCerts *d, const iString *url) { 554const iGmIdentity *identityForUrl_GmCerts(const iGmCerts *d, const iString *url) {
555 if (isEmpty_String(url)) {
556 return NULL;
557 }
552 lock_Mutex(d->mtx); 558 lock_Mutex(d->mtx);
553 const iGmIdentity *found = NULL; 559 const iGmIdentity *found = NULL;
554 iConstForEach(PtrArray, i, &d->idents) { 560 iConstForEach(PtrArray, i, &d->idents) {
diff --git a/src/sitespec.c b/src/sitespec.c
index 0332af2d..6f4546f0 100644
--- a/src/sitespec.c
+++ b/src/sitespec.c
@@ -33,17 +33,19 @@ iDeclareObjectConstruction(SiteParams)
33struct Impl_SiteParams { 33struct Impl_SiteParams {
34 iObject object; 34 iObject object;
35 uint16_t titanPort; 35 uint16_t titanPort;
36 iString titanIdentity; /* fingerprint */
36 int dismissWarnings; 37 int dismissWarnings;
37 /* TODO: theme seed, style settings */ 38 /* TODO: theme seed, style settings */
38}; 39};
39 40
40void init_SiteParams(iSiteParams *d) { 41void init_SiteParams(iSiteParams *d) {
41 d->titanPort = 0; /* undefined */ 42 d->titanPort = 0; /* undefined */
43 init_String(&d->titanIdentity);
42 d->dismissWarnings = 0; 44 d->dismissWarnings = 0;
43} 45}
44 46
45void deinit_SiteParams(iSiteParams *d) { 47void deinit_SiteParams(iSiteParams *d) {
46 iUnused(d); 48 deinit_String(&d->titanIdentity);
47} 49}
48 50
49iDefineClass(SiteParams) 51iDefineClass(SiteParams)
@@ -122,6 +124,9 @@ static void handleIniKeyValue_SiteSpec_(void *context, const iString *table, con
122 if (!cmp_String(key, "titanPort")) { 124 if (!cmp_String(key, "titanPort")) {
123 d->loadParams->titanPort = number_TomlValue(value); 125 d->loadParams->titanPort = number_TomlValue(value);
124 } 126 }
127 else if (!cmp_String(key, "titanIdentity") && value->type == string_TomlType) {
128 set_String(&d->loadParams->titanIdentity, value->value.string);
129 }
125 else if (!cmp_String(key, "dismissWarnings") && value->type == int64_TomlType) { 130 else if (!cmp_String(key, "dismissWarnings") && value->type == int64_TomlType) {
126 d->loadParams->dismissWarnings = value->value.int64; 131 d->loadParams->dismissWarnings = value->value.int64;
127 } 132 }
@@ -152,6 +157,10 @@ static void save_SiteSpec_(iSiteSpec *d) {
152 if (params->titanPort) { 157 if (params->titanPort) {
153 appendFormat_String(buf, "titanPort = %u\n", params->titanPort); 158 appendFormat_String(buf, "titanPort = %u\n", params->titanPort);
154 } 159 }
160 if (!isEmpty_String(&params->titanIdentity)) {
161 appendFormat_String(
162 buf, "titanIdentity = \"%s\"\n", cstr_String(&params->titanIdentity));
163 }
155 if (params->dismissWarnings) { 164 if (params->dismissWarnings) {
156 appendFormat_String(buf, "dismissWarnings = 0x%x\n", params->dismissWarnings); 165 appendFormat_String(buf, "dismissWarnings = 0x%x\n", params->dismissWarnings);
157 } 166 }
@@ -205,6 +214,30 @@ void setValue_SiteSpec(const iString *site, enum iSiteSpecKey key, int value) {
205 } 214 }
206} 215}
207 216
217void setValueString_SiteSpec(const iString *site, enum iSiteSpecKey key, const iString *value) {
218 iSiteSpec *d = &siteSpec_;
219 const iString *hashKey = collect_String(lower_String(site));
220 iSiteParams *params = value_StringHash(&d->sites, hashKey);
221 if (!params) {
222 params = new_SiteParams();
223 insert_StringHash(&d->sites, hashKey, params);
224 }
225 iBool needSave = iFalse;
226 switch (key) {
227 case titanIdentity_SiteSpecKey:
228 if (!equal_String(&params->titanIdentity, value)) {
229 needSave = iTrue;
230 set_String(&params->titanIdentity, value);
231 }
232 break;
233 default:
234 break;
235 }
236 if (needSave) {
237 save_SiteSpec_(d);
238 }
239}
240
208int value_SiteSpec(const iString *site, enum iSiteSpecKey key) { 241int value_SiteSpec(const iString *site, enum iSiteSpecKey key) {
209 iSiteSpec *d = &siteSpec_; 242 iSiteSpec *d = &siteSpec_;
210 const iSiteParams *params = constValue_StringHash(&d->sites, collect_String(lower_String(site))); 243 const iSiteParams *params = constValue_StringHash(&d->sites, collect_String(lower_String(site)));
@@ -220,3 +253,17 @@ int value_SiteSpec(const iString *site, enum iSiteSpecKey key) {
220 return 0; 253 return 0;
221 } 254 }
222} 255}
256
257const iString *valueString_SiteSpec(const iString *site, enum iSiteSpecKey key) {
258 iSiteSpec *d = &siteSpec_;
259 const iSiteParams *params = constValue_StringHash(&d->sites, collect_String(lower_String(site)));
260 if (!params) {
261 return 0;
262 }
263 switch (key) {
264 case titanIdentity_SiteSpecKey:
265 return &params->titanIdentity;
266 default:
267 return collectNew_String();
268 }
269}
diff --git a/src/sitespec.h b/src/sitespec.h
index 6b64f073..5adaeb8c 100644
--- a/src/sitespec.h
+++ b/src/sitespec.h
@@ -28,11 +28,16 @@ iDeclareType(SiteSpec)
28 28
29enum iSiteSpecKey { 29enum iSiteSpecKey {
30 titanPort_SiteSpecKey, 30 titanPort_SiteSpecKey,
31 titanIdentity_SiteSpecKey,
31 dismissWarnings_SiteSpecKey, 32 dismissWarnings_SiteSpecKey,
32}; 33};
33 34
34void init_SiteSpec (const char *saveDir); 35void init_SiteSpec (const char *saveDir);
35void deinit_SiteSpec (void); 36void deinit_SiteSpec (void);
36 37
37void setValue_SiteSpec (const iString *site, enum iSiteSpecKey key, int value); /* changes saved immediately */ 38/* changes saved immediately */
38int value_SiteSpec (const iString *site, enum iSiteSpecKey key); 39void setValue_SiteSpec (const iString *site, enum iSiteSpecKey key, int value);
40void setValueString_SiteSpec (const iString *site, enum iSiteSpecKey key, const iString *value);
41
42int value_SiteSpec (const iString *site, enum iSiteSpecKey key);
43const iString * valueString_SiteSpec (const iString *site, enum iSiteSpecKey key);
diff --git a/src/ui/banner.c b/src/ui/banner.c
index 0ffb1d9f..7ec189a4 100644
--- a/src/ui/banner.c
+++ b/src/ui/banner.c
@@ -257,8 +257,26 @@ static size_t itemAtCoord_Banner_(const iBanner *d, iInt2 coord) {
257 return iInvalidPos; 257 return iInvalidPos;
258} 258}
259 259
260static iBool isInside_Banner_(const iBanner *d, const SDL_Event *ev) {
261 if (ev->type == SDL_MOUSEMOTION || ev->type == SDL_MOUSEBUTTONDOWN ||
262 ev->type == SDL_MOUSEBUTTONDOWN) {
263 iInt2 coord;
264 if (ev->type == SDL_MOUSEMOTION) {
265 coord = init_I2(ev->motion.x, ev->motion.y);
266 }
267 else {
268 coord = init_I2(ev->button.x, ev->button.y);
269 }
270 return contains_Rect(bounds_Widget(constAs_Widget(d->doc)), coord);
271 }
272 return iTrue;
273}
274
260iBool processEvent_Banner(iBanner *d, const SDL_Event *ev) { 275iBool processEvent_Banner(iBanner *d, const SDL_Event *ev) {
261 iWidget *w = as_Widget(d->doc); 276 iWidget *w = as_Widget(d->doc);
277 if (!isInside_Banner_(d, ev)) {
278 return iFalse;
279 }
262 switch (ev->type) { 280 switch (ev->type) {
263 case SDL_MOUSEMOTION: { 281 case SDL_MOUSEMOTION: {
264 const iInt2 coord = init_I2(ev->motion.x, ev->motion.y); 282 const iInt2 coord = init_I2(ev->motion.x, ev->motion.y);
diff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c
index 90df1958..bad00071 100644
--- a/src/ui/uploadwidget.c
+++ b/src/ui/uploadwidget.c
@@ -45,7 +45,7 @@ iDefineObjectConstruction(UploadWidget)
45 45
46enum iUploadIdentity { 46enum iUploadIdentity {
47 none_UploadIdentity, 47 none_UploadIdentity,
48 defaultForUrl_UploadIdentity, 48 defaultForSite_UploadIdentity,
49 dropdown_UploadIdentity, 49 dropdown_UploadIdentity,
50}; 50};
51 51
@@ -104,9 +104,16 @@ static void updateInputMaxHeight_UploadWidget_(iUploadWidget *d) {
104 (avail - inputPos.y) / lineHeight_Text(font_InputWidget(d->input)))); 104 (avail - inputPos.y) / lineHeight_Text(font_InputWidget(d->input))));
105} 105}
106 106
107static const iGmIdentity *titanIdentityForUrl_(const iString *url) {
108 return findIdentity_GmCerts(
109 certs_App(),
110 collect_Block(hexDecode_Rangecc(range_String(valueString_SiteSpec(
111 collectNewRange_String(urlRoot_String(url)), titanIdentity_SiteSpecKey)))));
112}
113
107static const iArray *makeIdentityItems_UploadWidget_(const iUploadWidget *d) { 114static const iArray *makeIdentityItems_UploadWidget_(const iUploadWidget *d) {
108 iArray *items = collectNew_Array(sizeof(iMenuItem)); 115 iArray *items = collectNew_Array(sizeof(iMenuItem));
109 const iGmIdentity *urlId = identityForUrl_GmCerts(certs_App(), &d->url); 116 const iGmIdentity *urlId = titanIdentityForUrl_(&d->url);
110 pushBack_Array(items, 117 pushBack_Array(items,
111 &(iMenuItem){ format_CStr("${dlg.upload.id.default} (%s)", 118 &(iMenuItem){ format_CStr("${dlg.upload.id.default} (%s)",
112 urlId ? cstr_String(name_GmIdentity(urlId)) 119 urlId ? cstr_String(name_GmIdentity(urlId))
@@ -147,7 +154,7 @@ void init_UploadWidget(iUploadWidget *d) {
147 d->request = NULL; 154 d->request = NULL;
148 init_String(&d->filePath); 155 init_String(&d->filePath);
149 d->fileSize = 0; 156 d->fileSize = 0;
150 d->idMode = defaultForUrl_UploadIdentity; 157 d->idMode = defaultForSite_UploadIdentity;
151 init_Block(&d->idFingerprint, 0); 158 init_Block(&d->idFingerprint, 0);
152 const iMenuItem actions[] = { 159 const iMenuItem actions[] = {
153 { "${upload.port}", 0, 0, "upload.setport" }, 160 { "${upload.port}", 0, 0, "upload.setport" },
@@ -289,16 +296,22 @@ void deinit_UploadWidget(iUploadWidget *d) {
289 296
290static void remakeIdentityItems_UploadWidget_(iUploadWidget *d) { 297static void remakeIdentityItems_UploadWidget_(iUploadWidget *d) {
291 iWidget *dropMenu = findChild_Widget(findChild_Widget(as_Widget(d), "upload.id"), "menu"); 298 iWidget *dropMenu = findChild_Widget(findChild_Widget(as_Widget(d), "upload.id"), "menu");
292 releaseChildren_Widget(dropMenu);
293 const iArray *items = makeIdentityItems_UploadWidget_(d); 299 const iArray *items = makeIdentityItems_UploadWidget_(d);
294 makeMenuItems_Widget(dropMenu, constData_Array(items), size_Array(items)); 300 /* TODO: Make the following a utility method. */
301 if (flags_Widget(dropMenu) & nativeMenu_WidgetFlag) {
302 setNativeMenuItems_Widget(dropMenu, constData_Array(items), size_Array(items));
303 }
304 else {
305 releaseChildren_Widget(dropMenu);
306 makeMenuItems_Widget(dropMenu, constData_Array(items), size_Array(items));
307 }
295} 308}
296 309
297static void updateIdentityDropdown_UploadWidget_(iUploadWidget *d) { 310static void updateIdentityDropdown_UploadWidget_(iUploadWidget *d) {
298 updateDropdownSelection_LabelWidget( 311 updateDropdownSelection_LabelWidget(
299 findChild_Widget(as_Widget(d), "upload.id"), 312 findChild_Widget(as_Widget(d), "upload.id"),
300 d->idMode == none_UploadIdentity ? " arg:0" 313 d->idMode == none_UploadIdentity ? " arg:0"
301 : d->idMode == defaultForUrl_UploadIdentity 314 : d->idMode == defaultForSite_UploadIdentity
302 ? " arg:1" 315 ? " arg:1"
303 : format_CStr(" fp:%s", cstrCollect_String(hexEncode_Block(&d->idFingerprint)))); 316 : format_CStr(" fp:%s", cstrCollect_String(hexEncode_Block(&d->idFingerprint))));
304} 317}
@@ -422,7 +435,7 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) {
422 } 435 }
423 else if (arg_Command(cmd)) { 436 else if (arg_Command(cmd)) {
424 clear_Block(&d->idFingerprint); 437 clear_Block(&d->idFingerprint);
425 d->idMode = defaultForUrl_UploadIdentity; 438 d->idMode = defaultForSite_UploadIdentity;
426 } 439 }
427 else { 440 else {
428 clear_Block(&d->idFingerprint); 441 clear_Block(&d->idFingerprint);
@@ -452,19 +465,27 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) {
452 setSendProgressFunc_GmRequest(d->request, updateProgress_UploadWidget_); 465 setSendProgressFunc_GmRequest(d->request, updateProgress_UploadWidget_);
453 setUserData_Object(d->request, d); 466 setUserData_Object(d->request, d);
454 setUrl_GmRequest(d->request, &d->url); 467 setUrl_GmRequest(d->request, &d->url);
468 const iString *site = collectNewRange_String(urlRoot_String(&d->url));
455 switch (d->idMode) { 469 switch (d->idMode) {
456 case defaultForUrl_UploadIdentity:
457 break; /* GmRequest handles it */
458 case none_UploadIdentity: 470 case none_UploadIdentity:
459 setIdentity_GmRequest(d->request, NULL); 471 /* Ensure no identity will be used for this specific URL. */
460 signOut_GmCerts(certs_App(), url_GmRequest(d->request)); 472 signOut_GmCerts(certs_App(), url_GmRequest(d->request));
473 setValueString_SiteSpec(site, titanIdentity_SiteSpecKey, collectNew_String());
461 break; 474 break;
462 case dropdown_UploadIdentity: { 475 case dropdown_UploadIdentity: {
463 iGmIdentity *ident = findIdentity_GmCerts(certs_App(), &d->idFingerprint); 476 iGmIdentity *ident = findIdentity_GmCerts(certs_App(), &d->idFingerprint);
464 setIdentity_GmRequest(d->request, ident); 477 if (ident) {
465 signIn_GmCerts(certs_App(), ident, url_GmRequest(d->request)); 478 setValueString_SiteSpec(site,
479 titanIdentity_SiteSpecKey,
480 collect_String(hexEncode_Block(&ident->fingerprint)));
481 }
466 break; 482 break;
467 } 483 }
484 default:
485 break;
486 }
487 if (d->idMode != none_UploadIdentity) {
488 setIdentity_GmRequest(d->request, titanIdentityForUrl_(&d->url));
468 } 489 }
469 if (isText) { 490 if (isText) {
470 /* Uploading text. */ 491 /* Uploading text. */
diff --git a/src/ui/util.c b/src/ui/util.c
index 88348ff8..0a9dde0c 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -809,14 +809,27 @@ static void deleteMenuItems_(iArray *items) {
809 delete_Array(items); 809 delete_Array(items);
810} 810}
811 811
812iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) { 812void releaseNativeMenu_Widget(iWidget *d) {
813 iWidget *menu = new_Widget();
814#if defined (iHaveNativeContextMenus) 813#if defined (iHaveNativeContextMenus)
815 setFlags_Widget(menu, hidden_WidgetFlag | nativeMenu_WidgetFlag, iTrue); 814 iArray *items = userData_Object(d);
815 if (items) {
816 iAssert(flags_Widget(d) & nativeMenu_WidgetFlag);
817 iAssert(items);
818 deleteMenuItems_(items);
819 setUserData_Object(d, NULL);
820 }
821#else
822 iUnused(d);
823#endif
824}
825
826void setNativeMenuItems_Widget(iWidget *menu, const iMenuItem *items, size_t n) {
827#if defined (iHaveNativeContextMenus)
828 iAssert(flags_Widget(menu) & nativeMenu_WidgetFlag);
829 releaseNativeMenu_Widget(menu);
816 setUserData_Object(menu, deepCopyMenuItems_(menu, items, n)); 830 setUserData_Object(menu, deepCopyMenuItems_(menu, items, n));
817 addChild_Widget(parent, menu);
818 iRelease(menu); /* owned by parent now */
819 /* Keyboard shortcuts still need to triggerable via the menu, although the items don't exist. */ { 831 /* Keyboard shortcuts still need to triggerable via the menu, although the items don't exist. */ {
832 releaseChildren_Widget(menu);
820 for (size_t i = 0; i < n; i++) { 833 for (size_t i = 0; i < n; i++) {
821 const iMenuItem *item = &items[i]; 834 const iMenuItem *item = &items[i];
822 if (item->key) { 835 if (item->key) {
@@ -824,6 +837,17 @@ iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) {
824 } 837 }
825 } 838 }
826 } 839 }
840#endif
841}
842
843iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) {
844 iWidget *menu = new_Widget();
845#if defined (iHaveNativeContextMenus)
846 setFlags_Widget(menu, hidden_WidgetFlag | nativeMenu_WidgetFlag, iTrue);
847 addChild_Widget(parent, menu);
848 iRelease(menu); /* owned by parent now */
849 setUserData_Object(menu, NULL);
850 setNativeMenuItems_Widget(menu, items, n);
827#else 851#else
828 /* Non-native custom popup menu. This may still be displayed inside a separate window. */ 852 /* Non-native custom popup menu. This may still be displayed inside a separate window. */
829 setDrawBufferEnabled_Widget(menu, iTrue); 853 setDrawBufferEnabled_Widget(menu, iTrue);
@@ -990,18 +1014,6 @@ iLocalDef iBool isUsingMenuPopupWindows_(void) {
990#endif 1014#endif
991} 1015}
992 1016
993void releaseNativeMenu_Widget(iWidget *d) {
994#if defined (iHaveNativeContextMenus)
995 iArray *items = userData_Object(d);
996 iAssert(flags_Widget(d) & nativeMenu_WidgetFlag);
997 iAssert(items);
998 deleteMenuItems_(items);
999 setUserData_Object(d, NULL);
1000#else
1001 iUnused(d);
1002#endif
1003}
1004
1005void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, int menuOpenFlags) { 1017void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, int menuOpenFlags) {
1006 const iBool postCommands = (menuOpenFlags & postCommands_MenuOpenFlags) != 0; 1018 const iBool postCommands = (menuOpenFlags & postCommands_MenuOpenFlags) != 0;
1007#if defined (iHaveNativeContextMenus) 1019#if defined (iHaveNativeContextMenus)
@@ -1263,8 +1275,8 @@ void updateDropdownSelection_LabelWidget(iLabelWidget *dropButton, const char *s
1263 iMenuItem *item = findNativeMenuItem_Widget(menu, selectedCommand); 1275 iMenuItem *item = findNativeMenuItem_Widget(menu, selectedCommand);
1264 if (item) { 1276 if (item) {
1265 setSelected_NativeMenuItem(item, iTrue); 1277 setSelected_NativeMenuItem(item, iTrue);
1266 updateText_LabelWidget(dropButton, 1278 updateText_LabelWidget(
1267 removeMenuItemLabelPrefixes_String(collectNewCStr_String(item->label))); 1279 dropButton, removeMenuItemLabelPrefixes_String(collectNewCStr_String(item->label)));
1268 } 1280 }
1269 return; 1281 return;
1270 } 1282 }
@@ -2199,27 +2211,27 @@ iWidget *makeDialog_Widget(const char *id,
2199 2211
2200iWidget *makePreferences_Widget(void) { 2212iWidget *makePreferences_Widget(void) {
2201 /* Common items. */ 2213 /* Common items. */
2202 const iMenuItem langItems[] = { { "${lang.cs} - cs", 0, 0, "uilang id:cs" }, 2214 const iMenuItem langItems[] = { { u8"Čeština - cs", 0, 0, "uilang id:cs" },
2203 { "${lang.de} - de", 0, 0, "uilang id:de" }, 2215 { u8"Deutsch - de", 0, 0, "uilang id:de" },
2204 { "${lang.en} - en", 0, 0, "uilang id:en" }, 2216 { u8"English - en", 0, 0, "uilang id:en" },
2205 { "${lang.es} - es", 0, 0, "uilang id:es" }, 2217 { u8"Español - es", 0, 0, "uilang id:es" },
2206 { "${lang.es.mx} - es", 0, 0, "uilang id:es_MX" }, 2218 { u8"Español (México) - es", 0, 0, "uilang id:es_MX" },
2207 { "${lang.eo} - eo", 0, 0, "uilang id:eo" }, 2219 { u8"Esperanto - eo", 0, 0, "uilang id:eo" },
2208 { "${lang.fi} - fi", 0, 0, "uilang id:fi" }, 2220 { u8"Suomi - fi", 0, 0, "uilang id:fi" },
2209 { "${lang.fr} - fr", 0, 0, "uilang id:fr" }, 2221 { u8"Français - fr", 0, 0, "uilang id:fr" },
2210 { "${lang.gl} - gl", 0, 0, "uilang id:gl" }, 2222 { u8"Galego - gl", 0, 0, "uilang id:gl" },
2211 { "${lang.hu} - hu", 0, 0, "uilang id:hu" }, 2223 { u8"Magyar - hu", 0, 0, "uilang id:hu" },
2212 { "${lang.ia} - ia", 0, 0, "uilang id:ia" }, 2224 { u8"Interlingua - ia", 0, 0, "uilang id:ia" },
2213 { "${lang.ie} - ie", 0, 0, "uilang id:ie" }, 2225 { u8"Interlingue - ie", 0, 0, "uilang id:ie" },
2214 { "${lang.isv} - isv", 0, 0, "uilang id:isv" }, 2226 { u8"Interslavic - isv", 0, 0, "uilang id:isv" },
2215 { "${lang.pl} - pl", 0, 0, "uilang id:pl" }, 2227 { u8"Polski - pl", 0, 0, "uilang id:pl" },
2216 { "${lang.ru} - ru", 0, 0, "uilang id:ru" }, 2228 { u8"Русский - ru", 0, 0, "uilang id:ru" },
2217 { "${lang.sk} - sk", 0, 0, "uilang id:sk" }, 2229 { u8"Slovak - sk", 0, 0, "uilang id:sk" },
2218 { "${lang.sr} - sr", 0, 0, "uilang id:sr" }, 2230 { u8"Српски - sr", 0, 0, "uilang id:sr" },
2219 { "${lang.tok} - tok", 0, 0, "uilang id:tok" }, 2231 { u8"Toki pona - tok", 0, 0, "uilang id:tok" },
2220 { "${lang.uk} - uk", 0, 0, "uilang id:uk" }, 2232 { u8"Українська - uk", 0, 0, "uilang id:uk" },
2221 { "${lang.zh.hans} - zh", 0, 0, "uilang id:zh_Hans" }, 2233 { u8"简体中文 - zh", 0, 0, "uilang id:zh_Hans" },
2222 { "${lang.zh.hant} - zh", 0, 0, "uilang id:zh_Hant" }, 2234 { u8"繁體/正體中文 - zh", 0, 0, "uilang id:zh_Hant" },
2223 { NULL } }; 2235 { NULL } };
2224 const iMenuItem returnKeyBehaviors[] = { 2236 const iMenuItem returnKeyBehaviors[] = {
2225 { "${prefs.returnkey.linebreak} " uiTextAction_ColorEscape shift_Icon return_Icon 2237 { "${prefs.returnkey.linebreak} " uiTextAction_ColorEscape shift_Icon return_Icon
diff --git a/src/ui/util.h b/src/ui/util.h
index cf96dfe4..52b3a692 100644
--- a/src/ui/util.h
+++ b/src/ui/util.h
@@ -249,6 +249,7 @@ void setMenuItemDisabled_Widget (iWidget *menu, const char *comm
249void setMenuItemDisabledByIndex_Widget(iWidget *menu, size_t index, iBool disable); 249void setMenuItemDisabledByIndex_Widget(iWidget *menu, size_t index, iBool disable);
250void setMenuItemLabel_Widget (iWidget *menu, const char *command, const char *newLabel); 250void setMenuItemLabel_Widget (iWidget *menu, const char *command, const char *newLabel);
251void setMenuItemLabelByIndex_Widget (iWidget *menu, size_t index, const char *newLabel); 251void setMenuItemLabelByIndex_Widget (iWidget *menu, size_t index, const char *newLabel);
252void setNativeMenuItems_Widget (iWidget *, const iMenuItem *items, size_t n);
252 253
253int checkContextMenu_Widget (iWidget *, const SDL_Event *ev); /* see macro below */ 254int checkContextMenu_Widget (iWidget *, const SDL_Event *ev); /* see macro below */
254 255