From a6146ac91c90a4003efd489ee3ada175203995cc Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Wed, 19 Jan 2022 15:51:07 +0200 Subject: Fontpack lookup via missing glyphs IssueID #435 --- res/lang/cs.bin | Bin 32069 -> 32702 bytes res/lang/de.bin | Bin 30896 -> 31529 bytes res/lang/en.bin | Bin 26965 -> 27598 bytes res/lang/eo.bin | Bin 26163 -> 26796 bytes res/lang/es.bin | Bin 30784 -> 31417 bytes res/lang/es_MX.bin | Bin 28035 -> 28668 bytes res/lang/fi.bin | Bin 30606 -> 31239 bytes res/lang/fr.bin | Bin 31693 -> 32326 bytes res/lang/gl.bin | Bin 29952 -> 30585 bytes res/lang/hu.bin | Bin 31718 -> 32351 bytes res/lang/ia.bin | Bin 29748 -> 30381 bytes res/lang/ie.bin | Bin 29655 -> 30288 bytes res/lang/isv.bin | Bin 25686 -> 26319 bytes res/lang/nl.bin | Bin 29075 -> 29708 bytes res/lang/pl.bin | Bin 30321 -> 30954 bytes res/lang/ru.bin | Bin 45641 -> 46274 bytes res/lang/sk.bin | Bin 26022 -> 26655 bytes res/lang/sr.bin | Bin 44947 -> 45580 bytes res/lang/tok.bin | Bin 27801 -> 28434 bytes res/lang/tr.bin | Bin 29902 -> 30535 bytes res/lang/uk.bin | Bin 45028 -> 45661 bytes res/lang/zh_Hans.bin | Bin 25930 -> 26563 bytes res/lang/zh_Hant.bin | Bin 26328 -> 26961 bytes 23 files changed, 0 insertions(+), 0 deletions(-) (limited to 'res') diff --git a/res/lang/cs.bin b/res/lang/cs.bin index eb59f65d..6f1afa85 100644 Binary files a/res/lang/cs.bin and b/res/lang/cs.bin differ diff --git a/res/lang/de.bin b/res/lang/de.bin index 9c3d4541..ecb601aa 100644 Binary files a/res/lang/de.bin and b/res/lang/de.bin differ diff --git a/res/lang/en.bin b/res/lang/en.bin index 5f649846..758adbba 100644 Binary files a/res/lang/en.bin and b/res/lang/en.bin differ diff --git a/res/lang/eo.bin b/res/lang/eo.bin index ace592df..1de8a7db 100644 Binary files a/res/lang/eo.bin and b/res/lang/eo.bin differ diff --git a/res/lang/es.bin b/res/lang/es.bin index 14c1b843..a11c6f78 100644 Binary files a/res/lang/es.bin and b/res/lang/es.bin differ diff --git a/res/lang/es_MX.bin b/res/lang/es_MX.bin index dfcd6306..40379ee0 100644 Binary files a/res/lang/es_MX.bin and b/res/lang/es_MX.bin differ diff --git a/res/lang/fi.bin b/res/lang/fi.bin index 44d2741d..18a4c11d 100644 Binary files a/res/lang/fi.bin and b/res/lang/fi.bin differ diff --git a/res/lang/fr.bin b/res/lang/fr.bin index ad16b2e7..ba098242 100644 Binary files a/res/lang/fr.bin and b/res/lang/fr.bin differ diff --git a/res/lang/gl.bin b/res/lang/gl.bin index f1501b4a..7727f587 100644 Binary files a/res/lang/gl.bin and b/res/lang/gl.bin differ diff --git a/res/lang/hu.bin b/res/lang/hu.bin index c070dd49..94af8aa8 100644 Binary files a/res/lang/hu.bin and b/res/lang/hu.bin differ diff --git a/res/lang/ia.bin b/res/lang/ia.bin index 34633dd1..1aac22fe 100644 Binary files a/res/lang/ia.bin and b/res/lang/ia.bin differ diff --git a/res/lang/ie.bin b/res/lang/ie.bin index 722ee20d..4d5ac8d9 100644 Binary files a/res/lang/ie.bin and b/res/lang/ie.bin differ diff --git a/res/lang/isv.bin b/res/lang/isv.bin index 3be01643..c3931a80 100644 Binary files a/res/lang/isv.bin and b/res/lang/isv.bin differ diff --git a/res/lang/nl.bin b/res/lang/nl.bin index dcc9fe97..579f0df8 100644 Binary files a/res/lang/nl.bin and b/res/lang/nl.bin differ diff --git a/res/lang/pl.bin b/res/lang/pl.bin index a32e9d10..448be098 100644 Binary files a/res/lang/pl.bin and b/res/lang/pl.bin differ diff --git a/res/lang/ru.bin b/res/lang/ru.bin index e434971b..04114010 100644 Binary files a/res/lang/ru.bin and b/res/lang/ru.bin differ diff --git a/res/lang/sk.bin b/res/lang/sk.bin index 833872c9..fc984d97 100644 Binary files a/res/lang/sk.bin and b/res/lang/sk.bin differ diff --git a/res/lang/sr.bin b/res/lang/sr.bin index 43a6deda..ef949942 100644 Binary files a/res/lang/sr.bin and b/res/lang/sr.bin differ diff --git a/res/lang/tok.bin b/res/lang/tok.bin index d17f075e..cfbee57e 100644 Binary files a/res/lang/tok.bin and b/res/lang/tok.bin differ diff --git a/res/lang/tr.bin b/res/lang/tr.bin index 06fc22e5..8552574c 100644 Binary files a/res/lang/tr.bin and b/res/lang/tr.bin differ diff --git a/res/lang/uk.bin b/res/lang/uk.bin index 23329907..8f39c7fd 100644 Binary files a/res/lang/uk.bin and b/res/lang/uk.bin differ diff --git a/res/lang/zh_Hans.bin b/res/lang/zh_Hans.bin index 246b7c42..2f0c03fa 100644 Binary files a/res/lang/zh_Hans.bin and b/res/lang/zh_Hans.bin differ diff --git a/res/lang/zh_Hant.bin b/res/lang/zh_Hant.bin index 0e94f66a..f978013c 100644 Binary files a/res/lang/zh_Hant.bin and b/res/lang/zh_Hant.bin differ -- cgit v1.2.3 From df37aaff1278b8f283af421a0c47cffcf0cbeb06 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Thu, 20 Jan 2022 06:07:15 +0200 Subject: Updated language strings --- res/lang/cs.bin | Bin 32702 -> 32719 bytes res/lang/es.bin | Bin 31417 -> 31441 bytes res/lang/ru.bin | Bin 46274 -> 46301 bytes res/lang/sr.bin | Bin 45580 -> 45597 bytes res/lang/tr.bin | Bin 30535 -> 30545 bytes res/lang/uk.bin | Bin 45661 -> 45678 bytes 6 files changed, 0 insertions(+), 0 deletions(-) (limited to 'res') diff --git a/res/lang/cs.bin b/res/lang/cs.bin index 6f1afa85..98cd5d32 100644 Binary files a/res/lang/cs.bin and b/res/lang/cs.bin differ diff --git a/res/lang/es.bin b/res/lang/es.bin index a11c6f78..d50a2cae 100644 Binary files a/res/lang/es.bin and b/res/lang/es.bin differ diff --git a/res/lang/ru.bin b/res/lang/ru.bin index 04114010..098c2b11 100644 Binary files a/res/lang/ru.bin and b/res/lang/ru.bin differ diff --git a/res/lang/sr.bin b/res/lang/sr.bin index ef949942..49ec2b90 100644 Binary files a/res/lang/sr.bin and b/res/lang/sr.bin differ diff --git a/res/lang/tr.bin b/res/lang/tr.bin index 8552574c..8e9a09c4 100644 Binary files a/res/lang/tr.bin and b/res/lang/tr.bin differ diff --git a/res/lang/uk.bin b/res/lang/uk.bin index 8f39c7fd..ae80d456 100644 Binary files a/res/lang/uk.bin and b/res/lang/uk.bin differ -- cgit v1.2.3 From edb260848a42de2e1af44cab93dbf267d20e1f6f Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Sat, 22 Jan 2022 13:01:46 +0200 Subject: Updated Smol Emoji --- res/fonts/SmolEmoji-Regular.ttf | Bin 58544 -> 67168 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'res') diff --git a/res/fonts/SmolEmoji-Regular.ttf b/res/fonts/SmolEmoji-Regular.ttf index 3ab9484b..a9694f3a 100644 Binary files a/res/fonts/SmolEmoji-Regular.ttf and b/res/fonts/SmolEmoji-Regular.ttf differ -- cgit v1.2.3 From 672a534a044d811aa57e927288de50360882ac54 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Sun, 13 Feb 2022 20:57:09 +0200 Subject: Added a preference for maximum URL size The setting defaults to 8 KB. Link lines with longer URLs are not recognized as links. --- po/en.po | 3 +++ res/about/help.gmi | 7 ++++++- res/lang/cs.bin | Bin 32779 -> 32811 bytes res/lang/de.bin | Bin 31589 -> 31621 bytes res/lang/en.bin | Bin 27658 -> 27690 bytes res/lang/eo.bin | Bin 26848 -> 26880 bytes res/lang/es.bin | Bin 31501 -> 31533 bytes res/lang/es_MX.bin | Bin 28728 -> 28760 bytes res/lang/fi.bin | Bin 31299 -> 31331 bytes res/lang/fr.bin | Bin 32386 -> 32418 bytes res/lang/gl.bin | Bin 30662 -> 30694 bytes res/lang/hu.bin | Bin 32411 -> 32443 bytes res/lang/ia.bin | Bin 30441 -> 30473 bytes res/lang/ie.bin | Bin 30398 -> 30430 bytes res/lang/isv.bin | Bin 26379 -> 26411 bytes res/lang/nl.bin | Bin 29768 -> 29800 bytes res/lang/pl.bin | Bin 31014 -> 31046 bytes res/lang/ru.bin | Bin 46361 -> 46393 bytes res/lang/sk.bin | Bin 26715 -> 26747 bytes res/lang/sr.bin | Bin 45657 -> 45689 bytes res/lang/tok.bin | Bin 28504 -> 28536 bytes res/lang/tr.bin | Bin 30605 -> 30637 bytes res/lang/uk.bin | Bin 45738 -> 45770 bytes res/lang/zh_Hans.bin | Bin 26623 -> 26655 bytes res/lang/zh_Hant.bin | Bin 27021 -> 27053 bytes src/app.c | 12 ++++++++++++ src/gmdocument.c | 17 +++++++++-------- src/prefs.c | 1 + src/prefs.h | 1 + src/ui/util.c | 1 + 30 files changed, 33 insertions(+), 9 deletions(-) (limited to 'res') diff --git a/po/en.po b/po/en.po index 100cfb9f..aae67ff0 100644 --- a/po/en.po +++ b/po/en.po @@ -1670,6 +1670,9 @@ msgstr "Wrap plain text:" msgid "prefs.decodeurls" msgstr "Decode URLs:" +msgid "prefs.urlsize" +msgstr "Maximum URL size:" + msgid "prefs.cachesize" msgstr "Cache size:" diff --git a/res/about/help.gmi b/res/about/help.gmi index 93bc6a05..5bf77a76 100644 --- a/res/about/help.gmi +++ b/res/about/help.gmi @@ -106,10 +106,15 @@ The type and destination of a link are indicated by the link's icon and color: Link colors remain the same regardless of which color theme is being used for page content. (Color themes are discussed in the Customization section.) -When you move the mouse cursor over a link, additional information will appear: the destination domain, with the URL scheme shown for non-Gemini links, and the date of the last visit to the URL. +The "Show URL on hover" option can be enabled in Preferences to show additional information when you move the mouse cursor over a link: the destination domain, URL scheme for non-Gemini links, date of the last visit to the URL, and the identity that will be used when opening the link. If a link would normally use the default ➤ icon but there is an Emoji at the beginning of the link label, that Emoji is used as the link icon instead. In these cases, you can always assume that the link is a Gemini link whose destination is the same domain that you're currently on. +The "Network" tab of Preferences has a few settings that affect the presentation of links and URLs in general: + +* "Decode URLs" causes percent-coding to be decoded for the user interface, so one can see international characters in URLs. +* "Maximum URL size" sets a limit for how long URLs can be. While Gemini servers are required to enforce a limit of 1024 bytes for URLs, this setting affects all URLs regardless of scheme. Link lines with URLs longer than this will be presented as plain text. + ### 1.1.3 Page caching When navigating to a new page, the old page is cached in memory. If you navigate back, the cached copy of the page is restored. Think of it as rewinding time — you return to a past time as if nothing had happened. The same applies to forward navigation; cached pages are loaded if available. This allows back and forward navigation to happen instantly, without any network requests. diff --git a/res/lang/cs.bin b/res/lang/cs.bin index a45f34ca..a14c5cf4 100644 Binary files a/res/lang/cs.bin and b/res/lang/cs.bin differ diff --git a/res/lang/de.bin b/res/lang/de.bin index 9b99e7ed..8dd9d478 100644 Binary files a/res/lang/de.bin and b/res/lang/de.bin differ diff --git a/res/lang/en.bin b/res/lang/en.bin index 7b06807d..dd3389ef 100644 Binary files a/res/lang/en.bin and b/res/lang/en.bin differ diff --git a/res/lang/eo.bin b/res/lang/eo.bin index 6c3bab91..c65c893c 100644 Binary files a/res/lang/eo.bin and b/res/lang/eo.bin differ diff --git a/res/lang/es.bin b/res/lang/es.bin index f82aca48..a0f2a07f 100644 Binary files a/res/lang/es.bin and b/res/lang/es.bin differ diff --git a/res/lang/es_MX.bin b/res/lang/es_MX.bin index e1956da3..e83f92e2 100644 Binary files a/res/lang/es_MX.bin and b/res/lang/es_MX.bin differ diff --git a/res/lang/fi.bin b/res/lang/fi.bin index fc7ccab8..f390cdca 100644 Binary files a/res/lang/fi.bin and b/res/lang/fi.bin differ diff --git a/res/lang/fr.bin b/res/lang/fr.bin index 44b391b4..c268b356 100644 Binary files a/res/lang/fr.bin and b/res/lang/fr.bin differ diff --git a/res/lang/gl.bin b/res/lang/gl.bin index 583f7909..04311f53 100644 Binary files a/res/lang/gl.bin and b/res/lang/gl.bin differ diff --git a/res/lang/hu.bin b/res/lang/hu.bin index 6776ea40..28ba0e48 100644 Binary files a/res/lang/hu.bin and b/res/lang/hu.bin differ diff --git a/res/lang/ia.bin b/res/lang/ia.bin index 2659c595..27e3ba71 100644 Binary files a/res/lang/ia.bin and b/res/lang/ia.bin differ diff --git a/res/lang/ie.bin b/res/lang/ie.bin index 33bc6419..244ade42 100644 Binary files a/res/lang/ie.bin and b/res/lang/ie.bin differ diff --git a/res/lang/isv.bin b/res/lang/isv.bin index 23726e20..8c177e99 100644 Binary files a/res/lang/isv.bin and b/res/lang/isv.bin differ diff --git a/res/lang/nl.bin b/res/lang/nl.bin index 32ec0205..2bdf4a71 100644 Binary files a/res/lang/nl.bin and b/res/lang/nl.bin differ diff --git a/res/lang/pl.bin b/res/lang/pl.bin index 52e02876..129d34da 100644 Binary files a/res/lang/pl.bin and b/res/lang/pl.bin differ diff --git a/res/lang/ru.bin b/res/lang/ru.bin index 7445fe10..ac407168 100644 Binary files a/res/lang/ru.bin and b/res/lang/ru.bin differ diff --git a/res/lang/sk.bin b/res/lang/sk.bin index 76d4dd6f..099f0ccf 100644 Binary files a/res/lang/sk.bin and b/res/lang/sk.bin differ diff --git a/res/lang/sr.bin b/res/lang/sr.bin index 11ab7e1d..e550a05a 100644 Binary files a/res/lang/sr.bin and b/res/lang/sr.bin differ diff --git a/res/lang/tok.bin b/res/lang/tok.bin index 7e9b02d9..2bf27e86 100644 Binary files a/res/lang/tok.bin and b/res/lang/tok.bin differ diff --git a/res/lang/tr.bin b/res/lang/tr.bin index c13d575f..6bd0c26c 100644 Binary files a/res/lang/tr.bin and b/res/lang/tr.bin differ diff --git a/res/lang/uk.bin b/res/lang/uk.bin index 609b1c53..520f6c97 100644 Binary files a/res/lang/uk.bin and b/res/lang/uk.bin differ diff --git a/res/lang/zh_Hans.bin b/res/lang/zh_Hans.bin index 904fe90d..81ea7de6 100644 Binary files a/res/lang/zh_Hans.bin and b/res/lang/zh_Hans.bin differ diff --git a/res/lang/zh_Hant.bin b/res/lang/zh_Hant.bin index 9161c061..029551c7 100644 Binary files a/res/lang/zh_Hant.bin and b/res/lang/zh_Hant.bin differ diff --git a/src/app.c b/src/app.c index 0f9249cc..a2ada36e 100644 --- a/src/app.c +++ b/src/app.c @@ -244,6 +244,7 @@ static iString *serializePrefs_App_(const iApp *d) { appendFormat_String(str, "imageloadscroll arg:%d\n", d->prefs.loadImageInsteadOfScrolling); appendFormat_String(str, "cachesize.set arg:%d\n", d->prefs.maxCacheSize); appendFormat_String(str, "memorysize.set arg:%d\n", d->prefs.maxMemorySize); + appendFormat_String(str, "urlsize.set arg:%d\n", d->prefs.maxUrlSize); appendFormat_String(str, "decodeurls arg:%d\n", d->prefs.decodeUserVisibleURLs); appendFormat_String(str, "linewidth.set arg:%d\n", d->prefs.lineWidth); appendFormat_String(str, "linespacing.set arg:%f\n", d->prefs.lineSpacing); @@ -1974,6 +1975,8 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) { toInt_String(text_InputWidget(findChild_Widget(d, "prefs.cachesize")))); postCommandf_App("memorysize.set arg:%d", toInt_String(text_InputWidget(findChild_Widget(d, "prefs.memorysize")))); + postCommandf_App("urlsize.set arg:%d", + toInt_String(text_InputWidget(findChild_Widget(d, "prefs.urlsize")))); postCommandf_App("ca.file path:%s", cstrText_InputWidget(findChild_Widget(d, "prefs.ca.file"))); postCommandf_App("ca.path path:%s", @@ -2771,6 +2774,13 @@ iBool handleCommand_App(const char *cmd) { } return iTrue; } + else if (equal_Command(cmd, "urlsize.set")) { + d->prefs.maxUrlSize = arg_Command(cmd); + if (d->prefs.maxUrlSize < 1024) { + d->prefs.maxUrlSize = 1024; /* Gemini protocol requirement */ + } + return iTrue; + } else if (equal_Command(cmd, "searchurl")) { iString *url = &d->prefs.strings[searchUrl_PrefsString]; setCStr_String(url, suffixPtr_Command(cmd, "address")); @@ -3158,6 +3168,8 @@ iBool handleCommand_App(const char *cmd) { collectNewFormat_String("%d", d->prefs.maxCacheSize)); setText_InputWidget(findChild_Widget(dlg, "prefs.memorysize"), collectNewFormat_String("%d", d->prefs.maxMemorySize)); + setText_InputWidget(findChild_Widget(dlg, "prefs.urlsize"), + collectNewFormat_String("%d", d->prefs.maxUrlSize)); setToggle_Widget(findChild_Widget(dlg, "prefs.decodeurls"), d->prefs.decodeUserVisibleURLs); setText_InputWidget(findChild_Widget(dlg, "prefs.searchurl"), &d->prefs.strings[searchUrl_PrefsString]); setText_InputWidget(findChild_Widget(dlg, "prefs.ca.file"), &d->prefs.strings[caFile_PrefsString]); diff --git a/src/gmdocument.c b/src/gmdocument.c index 63d100e2..5cae4138 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c @@ -333,13 +333,14 @@ static iRangecc addLink_GmDocument_(iGmDocument *d, iRangecc line, iGmLinkId *li link->urlRange = capturedRange_RegExpMatch(&m, 1); setRange_String(&link->url, link->urlRange); set_String(&link->url, canonicalUrl_String(absoluteUrl_String(&d->url, &link->url))); - if (startsWithCase_String(&link->url, "about:command")) { - /* This is a special internal page that allows submitting UI events. */ - if (!d->enableCommandLinks) { - delete_GmLink(link); - *linkId = 0; - return line; - } + /* If invalid, disregard the link. */ + if (size_String(&link->url) > prefs_App()->maxUrlSize || + (startsWithCase_String(&link->url, "about:command") + /* this is a special internal page that allows submitting UI events */ + && !d->enableCommandLinks)) { + delete_GmLink(link); + *linkId = 0; + return line; } /* Check the URL. */ { iUrl parts; @@ -385,7 +386,7 @@ static iRangecc addLink_GmDocument_(iGmDocument *d, iRangecc line, iGmLinkId *li iString *path = newRange_String(parts.path); if (endsWithCase_String(path, ".gif") || endsWithCase_String(path, ".jpg") || endsWithCase_String(path, ".jpeg") || endsWithCase_String(path, ".png") || - endsWithCase_String(path, ".tga") || endsWithCase_String(path, ".psd") || + endsWithCase_String(path, ".tga") || endsWithCase_String(path, ".psd") || #if defined (LAGRANGE_ENABLE_WEBP) endsWithCase_String(path, ".webp") || #endif diff --git a/src/prefs.c b/src/prefs.c index 13a1dab7..cd86bf60 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -73,6 +73,7 @@ void init_Prefs(iPrefs *d) { d->decodeUserVisibleURLs = iTrue; d->maxCacheSize = 10; d->maxMemorySize = 200; + d->maxUrlSize = 8192; setCStr_String(&d->strings[uiFont_PrefsString], "default"); setCStr_String(&d->strings[headingFont_PrefsString], "default"); setCStr_String(&d->strings[bodyFont_PrefsString], "default"); diff --git a/src/prefs.h b/src/prefs.h index ea864f51..25bf56c4 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -172,6 +172,7 @@ struct Impl_Prefs { /* Network */ int maxCacheSize; /* MB */ int maxMemorySize; /* MB */ + int maxUrlSize; /* bytes; longer ones will be disregarded */ /* Style */ iStringSet * disabledFontPacks; int gemtextAnsiEscapes; diff --git a/src/ui/util.c b/src/ui/util.c index 41f8eaa9..53ee8fda 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -2902,6 +2902,7 @@ iWidget *makePreferences_Widget(void) { appendTwoColumnTabPage_Widget(tabs, "${heading.prefs.network}", '6', &headings, &values); addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.decodeurls}"))); addChild_Widget(values, iClob(makeToggle_Widget("prefs.decodeurls"))); + addPrefsInputWithHeading_(headings, values, "prefs.urlsize", iClob(new_InputWidget(10))); /* Cache size. */ { iInputWidget *cache = new_InputWidget(4); setSelectAllOnFocus_InputWidget(cache, iTrue); -- cgit v1.2.3 From cb7a3cf7a47bdcf2366efb06e7e4c056394fcfd3 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Mon, 14 Feb 2022 09:22:31 +0200 Subject: Added option for autoshowing images in data URLs Disabled by default to be consistent with behavior of other links. --- po/en.po | 4 ++++ res/lang/cs.bin | Bin 32811 -> 32862 bytes res/lang/de.bin | Bin 31621 -> 31672 bytes res/lang/en.bin | Bin 27690 -> 27741 bytes res/lang/eo.bin | Bin 26880 -> 26931 bytes res/lang/es.bin | Bin 31533 -> 31584 bytes res/lang/es_MX.bin | Bin 28760 -> 28811 bytes res/lang/fi.bin | Bin 31331 -> 31382 bytes res/lang/fr.bin | Bin 32418 -> 32469 bytes res/lang/gl.bin | Bin 30694 -> 30745 bytes res/lang/hu.bin | Bin 32443 -> 32494 bytes res/lang/ia.bin | Bin 30473 -> 30524 bytes res/lang/ie.bin | Bin 30430 -> 30481 bytes res/lang/isv.bin | Bin 26411 -> 26462 bytes res/lang/nl.bin | Bin 29800 -> 29851 bytes res/lang/pl.bin | Bin 31046 -> 31097 bytes res/lang/ru.bin | Bin 46393 -> 46444 bytes res/lang/sk.bin | Bin 26747 -> 26798 bytes res/lang/sr.bin | Bin 45689 -> 45740 bytes res/lang/tok.bin | Bin 28536 -> 28587 bytes res/lang/tr.bin | Bin 30637 -> 30688 bytes res/lang/uk.bin | Bin 45770 -> 45821 bytes res/lang/zh_Hans.bin | Bin 26655 -> 26706 bytes res/lang/zh_Hant.bin | Bin 27053 -> 27104 bytes src/app.c | 6 ++++++ src/gmdocument.c | 8 ++++++-- src/prefs.c | 11 ++++++----- src/prefs.h | 2 ++ src/ui/documentwidget.c | 5 +++-- src/ui/util.c | 3 +++ 30 files changed, 30 insertions(+), 9 deletions(-) (limited to 'res') diff --git a/po/en.po b/po/en.po index aae67ff0..aa557043 100644 --- a/po/en.po +++ b/po/en.po @@ -1429,6 +1429,10 @@ msgstr "Collapse preformatted:" msgid "prefs.bookmarks.addbottom" msgstr "Add bookmarks to bottom:" +# User preference that controls whether image data embedded in Data URLs gets automatically displayed when a page is loaded. +msgid "prefs.dataurl.openimages" +msgstr "Open images in Data URLs:" + # User preference that controls whether index.gmi pages get automatically opened when browsing the contents of a directory inside a compressed archive. msgid "prefs.archive.openindex" msgstr "Open archive indices:" diff --git a/res/lang/cs.bin b/res/lang/cs.bin index a14c5cf4..f3f2a060 100644 Binary files a/res/lang/cs.bin and b/res/lang/cs.bin differ diff --git a/res/lang/de.bin b/res/lang/de.bin index 8dd9d478..0f918bfb 100644 Binary files a/res/lang/de.bin and b/res/lang/de.bin differ diff --git a/res/lang/en.bin b/res/lang/en.bin index dd3389ef..727258d1 100644 Binary files a/res/lang/en.bin and b/res/lang/en.bin differ diff --git a/res/lang/eo.bin b/res/lang/eo.bin index c65c893c..f68ac15d 100644 Binary files a/res/lang/eo.bin and b/res/lang/eo.bin differ diff --git a/res/lang/es.bin b/res/lang/es.bin index a0f2a07f..1d09138c 100644 Binary files a/res/lang/es.bin and b/res/lang/es.bin differ diff --git a/res/lang/es_MX.bin b/res/lang/es_MX.bin index e83f92e2..d3efe8fe 100644 Binary files a/res/lang/es_MX.bin and b/res/lang/es_MX.bin differ diff --git a/res/lang/fi.bin b/res/lang/fi.bin index f390cdca..24e2a905 100644 Binary files a/res/lang/fi.bin and b/res/lang/fi.bin differ diff --git a/res/lang/fr.bin b/res/lang/fr.bin index c268b356..c644fab8 100644 Binary files a/res/lang/fr.bin and b/res/lang/fr.bin differ diff --git a/res/lang/gl.bin b/res/lang/gl.bin index 04311f53..e93d1eb7 100644 Binary files a/res/lang/gl.bin and b/res/lang/gl.bin differ diff --git a/res/lang/hu.bin b/res/lang/hu.bin index 28ba0e48..5bfe37eb 100644 Binary files a/res/lang/hu.bin and b/res/lang/hu.bin differ diff --git a/res/lang/ia.bin b/res/lang/ia.bin index 27e3ba71..4b0b9bc3 100644 Binary files a/res/lang/ia.bin and b/res/lang/ia.bin differ diff --git a/res/lang/ie.bin b/res/lang/ie.bin index 244ade42..b69fd2a4 100644 Binary files a/res/lang/ie.bin and b/res/lang/ie.bin differ diff --git a/res/lang/isv.bin b/res/lang/isv.bin index 8c177e99..0cbd0f67 100644 Binary files a/res/lang/isv.bin and b/res/lang/isv.bin differ diff --git a/res/lang/nl.bin b/res/lang/nl.bin index 2bdf4a71..82d13774 100644 Binary files a/res/lang/nl.bin and b/res/lang/nl.bin differ diff --git a/res/lang/pl.bin b/res/lang/pl.bin index 129d34da..9d13a9e2 100644 Binary files a/res/lang/pl.bin and b/res/lang/pl.bin differ diff --git a/res/lang/ru.bin b/res/lang/ru.bin index ac407168..6a09521d 100644 Binary files a/res/lang/ru.bin and b/res/lang/ru.bin differ diff --git a/res/lang/sk.bin b/res/lang/sk.bin index 099f0ccf..9532ca17 100644 Binary files a/res/lang/sk.bin and b/res/lang/sk.bin differ diff --git a/res/lang/sr.bin b/res/lang/sr.bin index e550a05a..58828fea 100644 Binary files a/res/lang/sr.bin and b/res/lang/sr.bin differ diff --git a/res/lang/tok.bin b/res/lang/tok.bin index 2bf27e86..0c4f6123 100644 Binary files a/res/lang/tok.bin and b/res/lang/tok.bin differ diff --git a/res/lang/tr.bin b/res/lang/tr.bin index 6bd0c26c..f62d0968 100644 Binary files a/res/lang/tr.bin and b/res/lang/tr.bin differ diff --git a/res/lang/uk.bin b/res/lang/uk.bin index 520f6c97..bbc10575 100644 Binary files a/res/lang/uk.bin and b/res/lang/uk.bin differ diff --git a/res/lang/zh_Hans.bin b/res/lang/zh_Hans.bin index 81ea7de6..3a34d15d 100644 Binary files a/res/lang/zh_Hans.bin and b/res/lang/zh_Hans.bin differ diff --git a/res/lang/zh_Hant.bin b/res/lang/zh_Hant.bin index 029551c7..f0ac2727 100644 Binary files a/res/lang/zh_Hant.bin and b/res/lang/zh_Hant.bin differ diff --git a/src/app.c b/src/app.c index a2ada36e..d1e3870a 100644 --- a/src/app.c +++ b/src/app.c @@ -280,6 +280,7 @@ static iString *serializePrefs_App_(const iApp *d) { { "prefs.collapsepreonload", &d->prefs.collapsePreOnLoad }, { "prefs.hoverlink", &d->prefs.hoverLink }, { "prefs.bookmarks.addbottom", &d->prefs.addBookmarksToBottom }, + { "prefs.dataurl.openimages", &d->prefs.openDataUrlImagesOnLoad }, { "prefs.archive.openindex", &d->prefs.openArchiveIndexPages }, { "prefs.font.warnmissing", &d->prefs.warnAboutMissingGlyphs }, { "prefs.blink", &d->prefs.blinkingCursor }, @@ -2729,6 +2730,10 @@ iBool handleCommand_App(const char *cmd) { postRefresh_App(); return iTrue; } + else if (equal_Command(cmd, "prefs.dataurl.openimages.changed")) { + d->prefs.openDataUrlImagesOnLoad = arg_Command(cmd) != 0; + return iTrue; + } else if (equal_Command(cmd, "prefs.archive.openindex.changed")) { d->prefs.openArchiveIndexPages = arg_Command(cmd) != 0; return iTrue; @@ -3096,6 +3101,7 @@ iBool handleCommand_App(const char *cmd) { setToggle_Widget(findChild_Widget(dlg, "prefs.hidetoolbarscroll"), d->prefs.hideToolbarOnScroll); setToggle_Widget(findChild_Widget(dlg, "prefs.bookmarks.addbottom"), d->prefs.addBookmarksToBottom); setToggle_Widget(findChild_Widget(dlg, "prefs.font.warnmissing"), d->prefs.warnAboutMissingGlyphs); + setToggle_Widget(findChild_Widget(dlg, "prefs.dataurl.openimages"), d->prefs.openDataUrlImagesOnLoad); setToggle_Widget(findChild_Widget(dlg, "prefs.archive.openindex"), d->prefs.openArchiveIndexPages); setToggle_Widget(findChild_Widget(dlg, "prefs.ostheme"), d->prefs.useSystemTheme); setToggle_Widget(findChild_Widget(dlg, "prefs.customframe"), d->prefs.customFrame); diff --git a/src/gmdocument.c b/src/gmdocument.c index 5cae4138..a3e233f3 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c @@ -334,7 +334,7 @@ static iRangecc addLink_GmDocument_(iGmDocument *d, iRangecc line, iGmLinkId *li setRange_String(&link->url, link->urlRange); set_String(&link->url, canonicalUrl_String(absoluteUrl_String(&d->url, &link->url))); /* If invalid, disregard the link. */ - if (size_String(&link->url) > prefs_App()->maxUrlSize || + if ((d->format == gemini_SourceFormat && size_String(&link->url) > prefs_App()->maxUrlSize) || (startsWithCase_String(&link->url, "about:command") /* this is a special internal page that allows submitting UI events */ && !d->enableCommandLinks)) { @@ -371,7 +371,11 @@ static iRangecc addLink_GmDocument_(iGmDocument *d, iRangecc line, iGmLinkId *li } else if (equalCase_Rangecc(parts.scheme, "data")) { setScheme_GmLink_(link, data_GmLinkScheme); - if (startsWith_Rangecc(parts.path, "image/")) { + if (startsWith_Rangecc(parts.path, "image/png") || + startsWith_Rangecc(parts.path, "image/jpg") || + startsWith_Rangecc(parts.path, "image/jpeg") || + startsWith_Rangecc(parts.path, "image/webp") || + startsWith_Rangecc(parts.path, "image/gif")) { link->flags |= imageFileExtension_GmLinkFlag; } } diff --git a/src/prefs.c b/src/prefs.c index cd86bf60..08355a6a 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -66,11 +66,12 @@ void init_Prefs(iPrefs *d) { d->smoothScrollSpeed[keyboard_ScrollType] = 13; d->smoothScrollSpeed[mouse_ScrollType] = 13; d->loadImageInsteadOfScrolling = iFalse; - d->collapsePreOnLoad = iFalse; - d->openArchiveIndexPages = iTrue; - d->addBookmarksToBottom = iTrue; - d->warnAboutMissingGlyphs = iTrue; - d->decodeUserVisibleURLs = iTrue; + d->openDataUrlImagesOnLoad = iFalse; + d->collapsePreOnLoad = iFalse; + d->openArchiveIndexPages = iTrue; + d->addBookmarksToBottom = iTrue; + d->warnAboutMissingGlyphs = iTrue; + d->decodeUserVisibleURLs = iTrue; d->maxCacheSize = 10; d->maxMemorySize = 200; d->maxUrlSize = 8192; diff --git a/src/prefs.h b/src/prefs.h index 25bf56c4..59c36a16 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -75,6 +75,7 @@ enum iPrefsBool { hoverLink_PrefsBool, smoothScrolling_PrefsBool, loadImageInsteadOfScrolling_PrefsBool, + openDataUrlImagesOnLoad_PrefsBool, collapsePreOnLoad_PrefsBool, openArchiveIndexPages_PrefsBool, @@ -128,6 +129,7 @@ struct Impl_Prefs { iBool hoverLink; iBool smoothScrolling; iBool loadImageInsteadOfScrolling; + iBool openDataUrlImagesOnLoad; iBool collapsePreOnLoad; iBool openArchiveIndexPages; diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 6513fc33..293e4507 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c @@ -2411,8 +2411,9 @@ static const char *zipPageHeading_(const iRangecc mime) { static void postProcessRequestContent_DocumentWidget_(iDocumentWidget *d, iBool isCached) { iWidget *w = as_Widget(d); - /* Embedded images in data links should be shown immediately as they are already fetched - data that is part of the document. */ { + /* Embedded images in data links can be shown immediately as they are already fetched + data that is part of the document. */ + if (prefs_App()->openDataUrlImagesOnLoad) { iGmDocument *doc = d->view.doc; for (size_t linkId = 1; ; linkId++) { const int linkFlags = linkFlags_GmDocument(doc, linkId); diff --git a/src/ui/util.c b/src/ui/util.c index 53ee8fda..b9f37476 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -2497,6 +2497,7 @@ iWidget *makePreferences_Widget(void) { { "input id:prefs.searchurl url:1 noheading:1" }, { "padding" }, { "toggle id:prefs.bookmarks.addbottom" }, + { "toggle id:prefs.dataurl.openimages" }, { "toggle id:prefs.archive.openindex" }, { "radio device:1 id:prefs.pinsplit", 0, 0, (const void *) pinSplitItems }, { "padding" }, @@ -2569,6 +2570,7 @@ iWidget *makePreferences_Widget(void) { const iMenuItem networkPanelItems[] = { { "title id:heading.prefs.network" }, { "toggle id:prefs.decodeurls" }, + { "input id:prefs.urlsize maxlen:10 selectall:1" }, { "padding" }, { "input id:prefs.cachesize maxlen:4 selectall:1 unit:mb" }, { "input id:prefs.memorysize maxlen:4 selectall:1 unit:mb" }, @@ -2643,6 +2645,7 @@ iWidget *makePreferences_Widget(void) { addDialogPadding_(headings, values); addDialogToggle_(headings, values, "${prefs.hoverlink}", "prefs.hoverlink"); addDialogToggle_(headings, values, "${prefs.bookmarks.addbottom}", "prefs.bookmarks.addbottom"); + addDialogToggle_(headings, values, "${prefs.dataurl.openimages}", "prefs.dataurl.openimages"); addDialogToggle_(headings, values, "${prefs.archive.openindex}", "prefs.archive.openindex"); if (deviceType_App() != phone_AppDeviceType) { addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.pinsplit}"))); -- cgit v1.2.3 From e455699fca461e7e73d920a9ebfe557c20a67f98 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Tue, 15 Feb 2022 23:18:06 +0200 Subject: Site-specific settings The theme palette seed phrase and ANSI warnings can be configured in the new site-specific settings dialog. Added bindings for Page Information and for opening the site-specific settings dialog. IssueID #381 --- po/en.po | 21 +++++++++++ res/lang/cs.bin | Bin 32862 -> 33216 bytes res/lang/de.bin | Bin 31672 -> 32026 bytes res/lang/en.bin | Bin 27741 -> 28095 bytes res/lang/eo.bin | Bin 26931 -> 27285 bytes res/lang/es.bin | Bin 31584 -> 31938 bytes res/lang/es_MX.bin | Bin 28811 -> 29165 bytes res/lang/fi.bin | Bin 31382 -> 31736 bytes res/lang/fr.bin | Bin 32469 -> 32823 bytes res/lang/gl.bin | Bin 30745 -> 31099 bytes res/lang/hu.bin | Bin 32494 -> 32848 bytes res/lang/ia.bin | Bin 30524 -> 30878 bytes res/lang/ie.bin | Bin 30481 -> 30835 bytes res/lang/isv.bin | Bin 26462 -> 26816 bytes res/lang/nl.bin | Bin 29851 -> 30205 bytes res/lang/pl.bin | Bin 31097 -> 31451 bytes res/lang/ru.bin | Bin 46444 -> 46798 bytes res/lang/sk.bin | Bin 26798 -> 27152 bytes res/lang/sr.bin | Bin 45740 -> 46094 bytes res/lang/tok.bin | Bin 28587 -> 28941 bytes res/lang/tr.bin | Bin 30688 -> 31042 bytes res/lang/uk.bin | Bin 45821 -> 46175 bytes res/lang/zh_Hans.bin | Bin 26706 -> 27060 bytes res/lang/zh_Hant.bin | Bin 27104 -> 27458 bytes src/sitespec.c | 8 ++++ src/ui/documentwidget.c | 6 +++ src/ui/keys.c | 2 + src/ui/util.c | 95 +++++++++++++++++++++++++++++++++++++++++++----- 28 files changed, 123 insertions(+), 9 deletions(-) (limited to 'res') diff --git a/po/en.po b/po/en.po index 6db26259..22c10e44 100644 --- a/po/en.po +++ b/po/en.po @@ -760,6 +760,27 @@ msgstr "Trust" msgid "dlg.cert.fingerprint" msgstr "Copy Fingerprint" +msgid "pageinfo.settings" +msgstr "Settings" + +msgid "heading.sitespec" +msgstr "Site-Specific Settings" + +msgid "sitespec.ansi" +msgstr "ANSI escape warnings:" + +msgid "sitespec.palette" +msgstr "Theme palette seed:" + +msgid "sitespec.accept" +msgstr "Save Settings" + +msgid "keys.pageinfo" +msgstr "Show page information" + +msgid "keys.sitespec" +msgstr "Show site-specific settings" + #, c-format msgid "dlg.input.prompt" msgstr "Please enter input for %s:" diff --git a/res/lang/cs.bin b/res/lang/cs.bin index f3f2a060..0cf36a2b 100644 Binary files a/res/lang/cs.bin and b/res/lang/cs.bin differ diff --git a/res/lang/de.bin b/res/lang/de.bin index 0f918bfb..ea6e1841 100644 Binary files a/res/lang/de.bin and b/res/lang/de.bin differ diff --git a/res/lang/en.bin b/res/lang/en.bin index 727258d1..372cef24 100644 Binary files a/res/lang/en.bin and b/res/lang/en.bin differ diff --git a/res/lang/eo.bin b/res/lang/eo.bin index f68ac15d..8a9519b6 100644 Binary files a/res/lang/eo.bin and b/res/lang/eo.bin differ diff --git a/res/lang/es.bin b/res/lang/es.bin index 1d09138c..3435a8d8 100644 Binary files a/res/lang/es.bin and b/res/lang/es.bin differ diff --git a/res/lang/es_MX.bin b/res/lang/es_MX.bin index d3efe8fe..5c527322 100644 Binary files a/res/lang/es_MX.bin and b/res/lang/es_MX.bin differ diff --git a/res/lang/fi.bin b/res/lang/fi.bin index 24e2a905..cdbda504 100644 Binary files a/res/lang/fi.bin and b/res/lang/fi.bin differ diff --git a/res/lang/fr.bin b/res/lang/fr.bin index c644fab8..3ab07f12 100644 Binary files a/res/lang/fr.bin and b/res/lang/fr.bin differ diff --git a/res/lang/gl.bin b/res/lang/gl.bin index e93d1eb7..5f5d467b 100644 Binary files a/res/lang/gl.bin and b/res/lang/gl.bin differ diff --git a/res/lang/hu.bin b/res/lang/hu.bin index 5bfe37eb..17486efa 100644 Binary files a/res/lang/hu.bin and b/res/lang/hu.bin differ diff --git a/res/lang/ia.bin b/res/lang/ia.bin index 4b0b9bc3..8cae5947 100644 Binary files a/res/lang/ia.bin and b/res/lang/ia.bin differ diff --git a/res/lang/ie.bin b/res/lang/ie.bin index b69fd2a4..bd647d76 100644 Binary files a/res/lang/ie.bin and b/res/lang/ie.bin differ diff --git a/res/lang/isv.bin b/res/lang/isv.bin index 0cbd0f67..81d30963 100644 Binary files a/res/lang/isv.bin and b/res/lang/isv.bin differ diff --git a/res/lang/nl.bin b/res/lang/nl.bin index 82d13774..e860c109 100644 Binary files a/res/lang/nl.bin and b/res/lang/nl.bin differ diff --git a/res/lang/pl.bin b/res/lang/pl.bin index 9d13a9e2..b759b1b7 100644 Binary files a/res/lang/pl.bin and b/res/lang/pl.bin differ diff --git a/res/lang/ru.bin b/res/lang/ru.bin index 6a09521d..8463fbfe 100644 Binary files a/res/lang/ru.bin and b/res/lang/ru.bin differ diff --git a/res/lang/sk.bin b/res/lang/sk.bin index 9532ca17..a0197c5b 100644 Binary files a/res/lang/sk.bin and b/res/lang/sk.bin differ diff --git a/res/lang/sr.bin b/res/lang/sr.bin index 58828fea..dc10b8a0 100644 Binary files a/res/lang/sr.bin and b/res/lang/sr.bin differ diff --git a/res/lang/tok.bin b/res/lang/tok.bin index 0c4f6123..977454a8 100644 Binary files a/res/lang/tok.bin and b/res/lang/tok.bin differ diff --git a/res/lang/tr.bin b/res/lang/tr.bin index f62d0968..c131d0ea 100644 Binary files a/res/lang/tr.bin and b/res/lang/tr.bin differ diff --git a/res/lang/uk.bin b/res/lang/uk.bin index bbc10575..8377c0ba 100644 Binary files a/res/lang/uk.bin and b/res/lang/uk.bin differ diff --git a/res/lang/zh_Hans.bin b/res/lang/zh_Hans.bin index 3a34d15d..acaaaa77 100644 Binary files a/res/lang/zh_Hans.bin and b/res/lang/zh_Hans.bin differ diff --git a/res/lang/zh_Hant.bin b/res/lang/zh_Hant.bin index f0ac2727..cf674d55 100644 Binary files a/res/lang/zh_Hant.bin and b/res/lang/zh_Hant.bin differ diff --git a/src/sitespec.c b/src/sitespec.c index 31094981..21edc0a2 100644 --- a/src/sitespec.c +++ b/src/sitespec.c @@ -268,6 +268,12 @@ void setValueString_SiteSpec(const iString *site, enum iSiteSpecKey key, const i set_String(¶ms->titanIdentity, value); } break; + case paletteSeed_SiteSpecKey: + if (!equal_String(¶ms->paletteSeed, value)) { + needSave = iTrue; + set_String(¶ms->paletteSeed, value); + } + break; default: break; } @@ -339,6 +345,8 @@ const iString *valueString_SiteSpec(const iString *site, enum iSiteSpecKey key) switch (key) { case titanIdentity_SiteSpecKey: return ¶ms->titanIdentity; + case paletteSeed_SiteSpecKey: + return ¶ms->paletteSeed; default: return collectNew_String(); } diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 7d9ac154..1f3e0e37 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c @@ -4033,6 +4033,12 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) addAction_Widget(dlg, SDLK_SPACE, 0, "message.ok"); return iTrue; } + else if (equal_Command(cmd, "document.sitespec") && d == document_App()) { + if (!findWidget_App("sitespec.palette")) { + makeSiteSpecificSettings_Widget(d->mod.url); + } + return iTrue; + } else if (equal_Command(cmd, "server.unexpire") && document_App() == d) { const iRangecc host = urlHost_String(d->mod.url); const uint16_t port = urlPort_String(d->mod.url); diff --git a/src/ui/keys.c b/src/ui/keys.c index 26a286bc..88efa98b 100644 --- a/src/ui/keys.c +++ b/src/ui/keys.c @@ -243,6 +243,8 @@ static const struct { int id; iMenuItem bind; int flags; } defaultBindings_[] = { 110,{ "${menu.save.downloads}", SDLK_s, KMOD_PRIMARY, "document.save" }, 0 }, { 120,{ "${keys.upload}", SDLK_u, KMOD_PRIMARY, "document.upload" }, 0 }, { 121,{ "${keys.upload.edit}", SDLK_e, KMOD_PRIMARY, "document.upload copy:1" }, 0 }, + { 125,{ "${keys.pageinfo}", SDLK_i, KMOD_PRIMARY, "document.info" }, 0 }, + { 126,{ "${keys.sitespec}", ',', KMOD_PRIMARY | KMOD_SHIFT, "document.sitespec" }, 0 }, { 130,{ "${keys.input.precedingline}", SDLK_v, KMOD_PRIMARY | KMOD_SHIFT, "input.precedingline" }, 0 }, /* The following cannot currently be changed (built-in duplicates). */ #if defined (iPlatformApple) diff --git a/src/ui/util.c b/src/ui/util.c index 54715121..5cd8a582 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "keys.h" #include "labelwidget.h" #include "root.h" +#include "sitespec.h" #include "text.h" #include "touch.h" #include "widget.h" @@ -3126,7 +3127,7 @@ iWidget *makeBookmarkCreation_Widget(const iString *url, const iString *title, i static iBool handleFeedSettingCommands_(iWidget *dlg, const char *cmd) { if (equal_Command(cmd, "cancel")) { - setupSheetTransition_Mobile(dlg, iFalse); + setupSheetTransition_Mobile(dlg, 0); destroy_Widget(dlg); return iTrue; } @@ -3233,32 +3234,108 @@ iWidget *makeFeedSettings_Widget(uint32_t bookmarkId) { return dlg; } +/*----------------------------------------------------------------------------------------------*/ + +static void siteSpecificThemeChanged_(const iWidget *dlg) { + iDocumentWidget *doc = document_App(); + setThemeSeed_GmDocument((iGmDocument *) document_DocumentWidget(doc), + urlPaletteSeed_String(url_DocumentWidget(doc)), + urlThemeSeed_String(url_DocumentWidget(doc))); + postCommand_App("theme.changed"); +} + +static const iString *siteSpecificRoot_(const iWidget *dlg) { + return collect_String(suffix_Command(cstr_String(id_Widget(dlg)), "site")); +} + +static void updateSiteSpecificTheme_(iInputWidget *palSeed, void *context) { + iWidget *dlg = context; + const iString *siteRoot = siteSpecificRoot_(dlg); + setValueString_SiteSpec(siteRoot, paletteSeed_SiteSpecKey, text_InputWidget(palSeed)); + siteSpecificThemeChanged_(dlg); + /* Allow seeing the new theme. */ + setFlags_Widget(dlg, noFadeBackground_WidgetFlag, iTrue); +} + +static void closeSiteSpecific_(iWidget *dlg) { + setupSheetTransition_Mobile(dlg, 0); + delete_String(userData_Object(dlg)); /* saved original palette seed */ + destroy_Widget(dlg); +} + +static iBool siteSpecificSettingsHandler_(iWidget *dlg, const char *cmd) { + if (equal_Command(cmd, "cancel")) { + iInputWidget *palSeed = findChild_Widget(dlg, "sitespec.palette"); + setText_InputWidget(palSeed, userData_Object(dlg)); + updateSiteSpecificTheme_(palSeed, dlg); + closeSiteSpecific_(dlg); + return iTrue; + } + if (startsWith_CStr(cmd, "input.ended id:sitespec.palette")) { + setFlags_Widget(dlg, noFadeBackground_WidgetFlag, iFalse); + refresh_Widget(dlg); + siteSpecificThemeChanged_(dlg); + return iTrue; + } + if (equal_Command(cmd, "sitespec.accept")) { + const iInputWidget *palSeed = findChild_Widget(dlg, "sitespec.palette"); + const iBool warnAnsi = isSelected_Widget(findChild_Widget(dlg, "sitespec.ansi")); + const iString *siteRoot = siteSpecificRoot_(dlg); + int dismissed = value_SiteSpec(siteRoot, dismissWarnings_SiteSpecKey); + iChangeFlags(dismissed, ansiEscapes_GmDocumentWarning, !warnAnsi); + setValue_SiteSpec(siteRoot, dismissWarnings_SiteSpecKey, dismissed); + setValueString_SiteSpec(siteRoot, paletteSeed_SiteSpecKey, text_InputWidget(palSeed)); + siteSpecificThemeChanged_(dlg); + /* Note: The active DocumentWidget may actually be different than when opening the dialog. */ + closeSiteSpecific_(dlg); + return iTrue; + } + return iFalse; +} + iWidget *makeSiteSpecificSettings_Widget(const iString *url) { iWidget *dlg; const iMenuItem actions[] = { - { "${cancel}" }, { "${sitespec.accept}", SDLK_RETURN, KMOD_PRIMARY, "sitespec.accept" } + { "${cancel}" }, + { "${sitespec.accept}", SDLK_RETURN, KMOD_PRIMARY, "sitespec.accept" } }; if (isUsingPanelLayout_Mobile()) { iAssert(iFalse); } else { iWidget *headings, *values; - dlg = makeSheet_Widget("sitespec"); + dlg = makeSheet_Widget(format_CStr("sitespec site:%s", cstr_Rangecc(urlRoot_String(url)))); addDialogTitle_(dlg, "${heading.sitespec}", "heading.sitespec"); addChild_Widget(dlg, iClob(makeTwoColumns_Widget(&headings, &values))); + iInputWidget *palSeed = new_InputWidget(0); + setHint_InputWidget(palSeed, cstr_Block(urlThemeSeed_String(url))); + addPrefsInputWithHeading_(headings, values, "sitespec.palette", iClob(palSeed)); addDialogToggle_(headings, values, "${sitespec.ansi}", "sitespec.ansi"); - iInputWidget *palInput = new_InputWidget(0); - addPrefsInputWithHeading_(headings, values, "sitespec.palette", iClob(palInput)); - as_Widget(palInput)->rect.size.x = 80 * gap_UI; - addChild_Widget(dlg, iClob(makeDialogButtons_Widget(actions, iElemCount(actions)))); + addChild_Widget(dlg, iClob(makeDialogButtons_Widget(actions, iElemCount(actions)))); + addChild_Widget(get_Root()->widget, iClob(dlg)); + as_Widget(palSeed)->rect.size.x = 60 * gap_UI; + arrange_Widget(dlg); } /* Initialize. */ { - const iRangecc root = urlRoot_String(url); - + const iString *site = collectNewRange_String(urlRoot_String(url)); + setToggle_Widget(findChild_Widget(dlg, "sitespec.ansi"), + ~value_SiteSpec(site, dismissWarnings_SiteSpecKey) & ansiEscapes_GmDocumentWarning); + setText_InputWidget(findChild_Widget(dlg, "sitespec.palette"), + valueString_SiteSpec(site, paletteSeed_SiteSpecKey)); + /* Keep a copy of the original palette seed for restoring on cancel. */ + setUserData_Object(dlg, copy_String(valueString_SiteSpec(site, paletteSeed_SiteSpecKey))); + if (!isUsingPanelLayout_Mobile()) { + setValidator_InputWidget(findChild_Widget(dlg, "sitespec.palette"), + updateSiteSpecificTheme_, dlg); + } } + setCommandHandler_Widget(dlg, siteSpecificSettingsHandler_); + setupSheetTransition_Mobile(dlg, incoming_TransitionFlag); return dlg; } +/*----------------------------------------------------------------------------------------------*/ + iWidget *makeIdentityCreation_Widget(void) { const iMenuItem actions[] = { { "${dlg.newident.more}", 0, 0, "ident.showmore" }, { "---" }, -- cgit v1.2.3 From d743f11dd80264c2ac871981fd79ef9288bde219 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Wed, 16 Feb 2022 10:14:57 +0200 Subject: Help: Site-specific theme; max URL size; data URL images --- res/about/help.gmi | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'res') diff --git a/res/about/help.gmi b/res/about/help.gmi index 5bf77a76..cd1a332e 100644 --- a/res/about/help.gmi +++ b/res/about/help.gmi @@ -360,6 +360,8 @@ You can find a number of settings in Preferences to customize the user interface One important characteristic of Gemini is that you remain in control of what gets loaded and when. The browser will not suddenly fetch a ton of images, autoplay videos, or make surreptitious connections to any tracking servers — each network request is purposeful and manually triggered. With this in mind, the "Load image on scroll" option is provided to assist keyboard-only browsing and to facilitate a focused reading experience. When enabled, if there is an image link visible on the page and you press Space or ↓, it will be loaded and shown inline _instead_ of the view scrolling down. This allows you to read and see all the content of the page while only tapping on a single key on the keyboard. +The "Show images in Data URLs" option determines if image data embedded into links using data URLs is automatically shown after the page has finished loading. This only applies to a handful of common image media types: JPEG, PNG, GIF, and WebP. Note that the maximum size of an URL has a limit, so these embedded images have to fit under the configured limit to be recognized as valid links. Image from data URLs are displayed as links' inline content, just like with any other URL scheme. + The "Open archive indices" option controls whether index.gmi pages are automatically opened while browsing the contents of a ZIP archive. The purpose is to simulate the behavior of a Gemini server where opening a directory will by default show its index page. Enabling this option makes navigating an archived copy of a capsule a more streamlined experience. "Split view pinning" controls which tab links will be opened on when browsing in split view mode. The default mode is "Left Tab", which means that the page in the left tab is pinned (remains unchanged) when clicking on a link. For more information, see section 1.9. @@ -393,6 +395,17 @@ Page content color themes are selected on the "Colors" tab of Preferences. The " * Sepia: Light sepia background with black text. Does not change depending on domain; use this for readability if you prefer a sepia reading experience. * High Contrast: White background with black text. Does not change depending on domain; use this for readability if you prefer maximum contrast between text and the background. +### 2.3.1 Site-specific theme + +You can manually customize the color theme of a site. Open "Page Information" and click on "Settings" to open the Site-Specific Settings dialog. The default keyboard shortcut for this is ${SHIFT+}${CTRL+}Comma. + +The "Theme palette seed" is the input data given to the theme generator that determines a site's color palette. The theme generator is designed to algorithmically choose a palette whose colors go together. It is not possible to individually pick the colors of a theme. + +You can enter any text as the palette seed. By default, the seed is the site's hostname, or a user name found in the URL path (e.g., "gemini://example.com/~User/" → seed "User"). Examples of how to use this: + +* Enter a word or phrase, or just random characters, to find a theme that you like. +* To copy the theme of another site, enter the hostname of that site as the seed. + ## 2.4 Fonts This version of Lagrange supports TrueType fonts. To use a new font, simply view a .ttf file in the app and a page footer action is available for performing the installation. For example, try drag-and-dropping a .ttf file on the window. Alternatively, you can manually copy the font to the "fonts" subdirectory of the user-specific configuration directory (see section 3.5). @@ -498,7 +511,19 @@ Gemini allows relaying requests via a proxy server. On the "Network" tab, you ca When an HTTP proxy server is configured, HTTP/HTTPS links will no longer open in the system's default web browser but will be loaded via the proxy, expecting it to serve a 'text/gemini' version of the link contents. -## 2.7 Keybindings +## 2.7 URL handling + +The "Network" tab of Preferences has a few options related to handling URLs. + +Enabling the "Decode URLs" option causes all percent-encoded URLs to be shown in decoded form in the UI. Enabling this option is useful when encountering URLs that contain characters outside the basic Latin (A-Z) alphabet. This does not affect what gets sent to a server when loading pages: Gemini requests are always required to be sent in encoded form. + +The "Maximum URL size" setting defines what is considered a valid link in Gemtext. Link lines with URLs longer than this are not considered to be links and are displayed like regular text lines. This only affects links that don't use the "gemini" scheme. The maximum size of a Gemini URL is 1024 bytes. + +Having a length limit is necessary due the special case of Data URLs: +=> https://datatracker.ietf.org/doc/html/rfc2397 RFC 2397: The "data" URL scheme +With Data URLs, one is able to embed arbitrary data into a Gemtext file using link lines. This makes it possible to circumvent the intentional limitations of Gemini and override the clients' ability to choose which linked resources should be loaded and when. Without a limit, a server could for example send an arbitrarily large image attachment as part of the page, with no regard to the user's or client's preferences or abilities to view images. Also note that like any non-Gemini scheme, "data" is not expected to be supported by Gemini clients. + +## 2.8 Keybindings The "Keys" tab lets you change which keys are bound to UI commands. Click on an item with the mouse and then press the new key combination that you want bound to it. Right-click on a binding to erase it or reset it to the default. -- cgit v1.2.3 From dd9add718c4a9a2b29cd38b05886f22877b89b35 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Fri, 18 Feb 2022 19:51:38 +0200 Subject: Serializing multiple windows Not quite fully functional yet. The window positioning still needs to be written to prefs.cfg. --- res/about/version.gmi | 3 + src/app.c | 202 ++++++++++++++++++++++++++++++++---------------- src/app.h | 3 +- src/defs.h | 5 +- src/ui/documentwidget.c | 5 ++ src/ui/text.c | 20 +++-- src/ui/window.c | 36 ++++++++- 7 files changed, 193 insertions(+), 81 deletions(-) (limited to 'res') diff --git a/res/about/version.gmi b/res/about/version.gmi index aee62e82..73b88a52 100644 --- a/res/about/version.gmi +++ b/res/about/version.gmi @@ -6,6 +6,9 @@ ``` # Release notes +## 1.11 +⚠️ Downgrading back to v1.10 causes all site-specific themes to be forgotten. Back up your sitespec.ini beforehand. + ## 1.10.6 * Added bindings for switching Feeds list to Unread/All mode. * Fixed normalization of empty Gemini URL paths to `/` as per the November 2021 spec update. diff --git a/src/app.c b/src/app.c index 686d8b82..850a9706 100644 --- a/src/app.c +++ b/src/app.c @@ -476,7 +476,11 @@ static const char *magicSidebar_App_ = "side"; enum iDocumentStateFlag { current_DocumentStateFlag = iBit(1), - rootIndex1_DocumentStateFlag = iBit(2) + rootIndex1_DocumentStateFlag = iBit(2), +}; + +enum iWindowStateFlag { + current_WindowStateFlag = iBit(9), }; static iBool loadState_App_(iApp *d) { @@ -499,19 +503,48 @@ static iBool loadState_App_(iApp *d) { } setVersion_Stream(stream_File(f), version); /* Window state. */ - iDocumentWidget *doc = NULL; - iDocumentWidget *current[2] = { NULL, NULL }; - iBool isFirstTab[2] = { iTrue, iTrue }; + iDeclareType(CurrentTabs); + struct Impl_CurrentTabs { + iDocumentWidget *currentTab[2]; /* for each root */ + }; + int numWins = 0; + iMainWindow * win = NULL; + iMainWindow * currentWin = d->window; + iArray * currentTabs; /* two per window (per root per window) */ + iBool isFirstTab[2]; + currentTabs = collectNew_Array(sizeof(iCurrentTabs)); while (!atEnd_File(f)) { readData_File(f, 4, magic); if (!memcmp(magic, magicWindow_App_, 4)) { - const int splitMode = read32_File(f); - const int keyRoot = read32_File(f); - d->window->pendingSplitMode = splitMode; - setSplitMode_MainWindow(d->window, splitMode | noEvents_WindowSplit); - d->window->base.keyRoot = d->window->base.roots[keyRoot]; + numWins++; + const int splitMode = read32_File(f); + const int winState = read32_File(f); + const int keyRoot = (winState & 1); + const iBool isCurrent = (winState & current_WindowStateFlag) != 0; + if (numWins == 1) { + win = d->window; + } + else { + win = new_MainWindow(d->initialWindowRect); + addWindow_App(win); + } + pushBack_Array(currentTabs, &(iCurrentTabs){ { NULL, NULL } }); + isFirstTab[0] = isFirstTab[1] = iTrue; + if (isCurrent) { + currentWin = win; + } + setCurrent_Window(win); + setCurrent_Root(NULL); + win->pendingSplitMode = splitMode; + setSplitMode_MainWindow(win, splitMode | noEvents_WindowSplit); + win->base.keyRoot = d->window->base.roots[keyRoot]; } else if (!memcmp(magic, magicSidebar_App_, 4)) { + if (!win) { + printf("%s: missing window\n", cstr_String(path_File(f))); + setCurrent_Root(NULL); + return iFalse; + } const uint16_t bits = readU16_File(f); const uint8_t modes = readU8_File(f); const float widths[2] = { @@ -528,7 +561,7 @@ static iBool loadState_App_(iApp *d) { } const uint8_t rootIndex = bits & 0xff; const uint8_t flags = bits >> 8; - iRoot *root = d->window->base.roots[rootIndex]; + iRoot *root = win->base.roots[rootIndex]; if (root) { iSidebarWidget *sidebar = findChild_Widget(root->widget, "sidebar"); iSidebarWidget *sidebar2 = findChild_Widget(root->widget, "sidebar2"); @@ -551,12 +584,18 @@ static iBool loadState_App_(iApp *d) { } } else if (!memcmp(magic, magicTabDocument_App_, 4)) { + if (!win) { + printf("%s: missing window\n", cstr_String(path_File(f))); + setCurrent_Root(NULL); + return iFalse; + } const int8_t flags = read8_File(f); int rootIndex = flags & rootIndex1_DocumentStateFlag ? 1 : 0; - if (rootIndex > numRoots_Window(as_Window(d->window)) - 1) { + if (rootIndex > numRoots_Window(as_Window(win)) - 1) { rootIndex = 0; } - setCurrent_Root(d->window->base.roots[rootIndex]); + setCurrent_Root(win->base.roots[rootIndex]); + iDocumentWidget *doc; if (isFirstTab[rootIndex]) { isFirstTab[rootIndex] = iFalse; /* There is one pre-created tab in each root. */ @@ -566,7 +605,7 @@ static iBool loadState_App_(iApp *d) { doc = newTab_App(NULL, iFalse /* no switching */); } if (flags & current_DocumentStateFlag) { - current[rootIndex] = doc; + value_Array(currentTabs, numWins - 1, iCurrentTabs).currentTab[rootIndex] = doc; } deserializeState_DocumentWidget(doc, stream_File(f)); doc = NULL; @@ -577,12 +616,23 @@ static iBool loadState_App_(iApp *d) { return iFalse; } } - if (d->window->splitMode) { - /* Update root placement. */ - resize_MainWindow(d->window, -1, -1); + iForEach(Array, i, currentTabs) { + const iCurrentTabs *cur = i.value; + win = at_PtrArray(&d->mainWindows, index_ArrayIterator(&i)); + for (size_t j = 0; j < 2; ++j) { + postCommandf_Root(win->base.roots[j], "tabs.switch page:%p", cur->currentTab[j]); + } + if (win->splitMode) { + /* Update root placement. */ + resize_MainWindow(win, -1, -1); + } +// postCommand_Root(win->base.roots[0], "window.unfreeze"); + win->isDrawFrozen = iFalse; + SDL_ShowWindow(win->base.win); } - iForIndices(i, current) { - postCommandf_Root(NULL, "tabs.switch page:%p", current[i]); + if (numWindows_App() > 1) { + SDL_RaiseWindow(currentWin->base.win); + setActiveWindow_App(currentWin); } setCurrent_Root(NULL); return iTrue; @@ -593,7 +643,6 @@ static iBool loadState_App_(iApp *d) { static void saveState_App_(const iApp *d) { iUnused(d); trimCache_App(); - iMainWindow *win = d->window; /* UI state is saved in binary because it is quite complex (e.g., navigation history, cached content) and depends closely on the widget tree. The data is largely not reorderable and should not be modified @@ -602,43 +651,48 @@ static void saveState_App_(const iApp *d) { if (open_File(f, writeOnly_FileMode)) { writeData_File(f, magicState_App_, 4); writeU32_File(f, latest_FileVersion); /* version */ - /* Begin with window state. */ { - writeData_File(f, magicWindow_App_, 4); - writeU32_File(f, win->splitMode); - writeU32_File(f, win->base.keyRoot == win->base.roots[0] ? 0 : 1); - } - /* State of UI elements. */ { - iForIndices(i, win->base.roots) { - const iRoot *root = win->base.roots[i]; - if (root) { - writeData_File(f, magicSidebar_App_, 4); - const iSidebarWidget *sidebar = findChild_Widget(root->widget, "sidebar"); - const iSidebarWidget *sidebar2 = findChild_Widget(root->widget, "sidebar2"); - writeU16_File(f, i | - (isVisible_Widget(sidebar) ? 0x100 : 0) | - (isVisible_Widget(sidebar2) ? 0x200 : 0) | - (feedsMode_SidebarWidget(sidebar) == unread_FeedsMode ? 0x400 : 0) | - (feedsMode_SidebarWidget(sidebar2) == unread_FeedsMode ? 0x800 : 0)); - writeU8_File(f, - mode_SidebarWidget(sidebar) | - (mode_SidebarWidget(sidebar2) << 4)); - writef_Stream(stream_File(f), width_SidebarWidget(sidebar)); - writef_Stream(stream_File(f), width_SidebarWidget(sidebar2)); - serialize_IntSet(closedFolders_SidebarWidget(sidebar), stream_File(f)); - serialize_IntSet(closedFolders_SidebarWidget(sidebar2), stream_File(f)); + iConstForEach(PtrArray, winIter, &d->mainWindows) { + const iMainWindow *win = winIter.ptr; + setCurrent_Window(winIter.ptr); + /* Window state. */ { + writeData_File(f, magicWindow_App_, 4); + writeU32_File(f, win->splitMode); + writeU32_File(f, (win->base.keyRoot == win->base.roots[0] ? 0 : 1) | + (win == d->window ? current_WindowStateFlag : 0)); + } + /* State of UI elements. */ { + iForIndices(i, win->base.roots) { + const iRoot *root = win->base.roots[i]; + if (root) { + writeData_File(f, magicSidebar_App_, 4); + const iSidebarWidget *sidebar = findChild_Widget(root->widget, "sidebar"); + const iSidebarWidget *sidebar2 = findChild_Widget(root->widget, "sidebar2"); + writeU16_File(f, i | + (isVisible_Widget(sidebar) ? 0x100 : 0) | + (isVisible_Widget(sidebar2) ? 0x200 : 0) | + (feedsMode_SidebarWidget(sidebar) == unread_FeedsMode ? 0x400 : 0) | + (feedsMode_SidebarWidget(sidebar2) == unread_FeedsMode ? 0x800 : 0)); + writeU8_File(f, + mode_SidebarWidget(sidebar) | + (mode_SidebarWidget(sidebar2) << 4)); + writef_Stream(stream_File(f), width_SidebarWidget(sidebar)); + writef_Stream(stream_File(f), width_SidebarWidget(sidebar2)); + serialize_IntSet(closedFolders_SidebarWidget(sidebar), stream_File(f)); + serialize_IntSet(closedFolders_SidebarWidget(sidebar2), stream_File(f)); + } } } - } - iConstForEach(ObjectList, i, iClob(listDocuments_App(NULL))) { - iAssert(isInstance_Object(i.object, &Class_DocumentWidget)); - const iWidget *widget = constAs_Widget(i.object); - writeData_File(f, magicTabDocument_App_, 4); - int8_t flags = (document_Root(widget->root) == i.object ? current_DocumentStateFlag : 0); - if (widget->root == win->base.roots[1]) { - flags |= rootIndex1_DocumentStateFlag; + iConstForEach(ObjectList, i, iClob(listDocuments_App(NULL))) { + iAssert(isInstance_Object(i.object, &Class_DocumentWidget)); + const iWidget *widget = constAs_Widget(i.object); + writeData_File(f, magicTabDocument_App_, 4); + int8_t flags = (document_Root(widget->root) == i.object ? current_DocumentStateFlag : 0); + if (widget->root == win->base.roots[1]) { + flags |= rootIndex1_DocumentStateFlag; + } + write8_File(f, flags); + serializeState_DocumentWidget(i.object, stream_File(f)); } - write8_File(f, flags); - serializeState_DocumentWidget(i.object, stream_File(f)); } iRelease(f); } @@ -1491,6 +1545,7 @@ void processEvents_App(enum iAppEventMode eventMode) { window->lastHover = window->hover; wasUsed = processEvent_Window(window, &ev); if (ev.type == SDL_MOUSEMOTION || ev.type == SDL_MOUSEBUTTONDOWN) { + /* Only offered to the frontmost window. */ break; } if (wasUsed) break; @@ -1776,7 +1831,7 @@ void postCommand_Root(iRoot *d, const char *command) { } SDL_Event ev = { .type = SDL_USEREVENT }; ev.user.code = command_UserEventCode; - /*ev.user.windowID = id_Window(get_Window());*/ +// ev.user.windowID = id_Window(get_Window()); ev.user.data1 = strdup(command); ev.user.data2 = d; /* all events are root-specific */ SDL_PushEvent(&ev); @@ -1788,10 +1843,17 @@ void postCommand_Root(iRoot *d, const char *command) { command); #else if (app_.commandEcho) { - printf("%s[command] {%d} %s\n", - app_.isLoadingPrefs ? "[Prefs] " : "", - (d == NULL || win == NULL ? 0 : d == win->roots[0] ? 1 : 2), - command); fflush(stdout); + const int windowIndex = + win && type_Window(win) == main_WindowType ? windowIndex_App(as_MainWindow(win)) + 1 : 0; + printf("%s%s[command] {%d:%d} %s\n", + !app_.isFinishedLaunching ? " " : "", + app_.isLoadingPrefs ? " " : "", + windowIndex, + (d == NULL || win == NULL ? 0 + : d == win->roots[0] ? 1 + : 2), + command); + fflush(stdout); } #endif } @@ -1870,6 +1932,10 @@ size_t numWindows_App(void) { return size_PtrArray(&app_.mainWindows); } +size_t windowIndex_App(const iMainWindow *win) { + return indexOf_PtrArray(&app_.mainWindows, win); +} + void setActiveWindow_App(iMainWindow *win) { iApp *d = &app_; d->window = win; @@ -3066,12 +3132,12 @@ iBool handleCommand_App(const char *cmd) { return iFalse; } else if (equal_Command(cmd, "window.new")) { - iMainWindow *newWin = new_MainWindow(moved_Rect(d->initialWindowRect, init_I2(20, 20))); - addWindow_App(newWin); + iMainWindow *newWin = new_MainWindow(moved_Rect(d->initialWindowRect, init_I2(30, 30))); + addWindow_App(newWin); /* takes ownership */ SDL_ShowWindow(newWin->base.win); setCurrent_Window(newWin); - postCommand_Root(newWin->base.roots[0], "navigate.home"); - postCommand_Root(newWin->base.roots[0], "window.unfreeze"); + postCommand_Root(newWin->base.roots[0], "~navigate.home"); + postCommand_Root(newWin->base.roots[0], "~window.unfreeze"); return iTrue; } else if (equal_Command(cmd, "tabs.new")) { @@ -3659,12 +3725,16 @@ iMainWindow *mainWindow_App(void) { return app_.window; } -void closePopups_App(void) { +void closePopups_App(iBool doForce) { iApp *d = &app_; const uint32_t now = SDL_GetTicks(); - iConstForEach(PtrArray, i, &d->popupWindows) { - const iWindow *win = i.ptr; - if (now - win->focusGainedAt > 200) { + iForEach(PtrArray, i, &d->popupWindows) { + iWindow *win = i.ptr; +// if (doForce) { +// collect_Garbage(win, (iDeleteFunc) delete_Window); +// } +// else + if (now - win->focusGainedAt > 200) { postCommand_Root(((const iWindow *) i.ptr)->roots[0], "cancel"); } } diff --git a/src/app.h b/src/app.h index 74a5429b..dd24ec8e 100644 --- a/src/app.h +++ b/src/app.h @@ -127,6 +127,7 @@ void removeWindow_App (iMainWindow *win); void setActiveWindow_App (iMainWindow *win); void closeWindow_App (iMainWindow *win); size_t numWindows_App (void); +size_t windowIndex_App (const iMainWindow *win); void addPopup_App (iWindow *popup); void removePopup_App (iWindow *popup); void postRefresh_App (void); @@ -151,4 +152,4 @@ void resetFonts_App (void); void availableFontsChanged_App(void); iMainWindow * mainWindow_App (void); -void closePopups_App (void); +void closePopups_App (iBool doForce); diff --git a/src/defs.h b/src/defs.h index cd502f70..be5280fa 100644 --- a/src/defs.h +++ b/src/defs.h @@ -38,9 +38,10 @@ enum iFileVersion { serializedSidebarState_FileVersion = 3, addedRecentUrlFlags_FileVersion = 4, bookmarkFolderState_FileVersion = 5, + multipleWindows_FileVersion = 6, /* meta */ - idents_FileVersion = 1, /* version used by GmCerts/idents.lgr */ - latest_FileVersion = 5, + latest_FileVersion = 6, /* used by state.lgr */ + idents_FileVersion = 1, /* used by GmCerts/idents.lgr */ }; enum iImageStyle { diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 7c071f47..f8cc10b9 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c @@ -5275,6 +5275,11 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e "document.upload", !equalCase_Rangecc(urlScheme_String(d->mod.url), "gemini") && !equalCase_Rangecc(urlScheme_String(d->mod.url), "titan")); + setMenuItemDisabled_Widget( + d->menu, + "document.upload copy:1", + !equalCase_Rangecc(urlScheme_String(d->mod.url), "gemini") && + !equalCase_Rangecc(urlScheme_String(d->mod.url), "titan")); } processContextMenuEvent_Widget(d->menu, ev, {}); } diff --git a/src/ui/text.c b/src/ui/text.c index 51531057..83e87d0c 100644 --- a/src/ui/text.c +++ b/src/ui/text.c @@ -295,6 +295,7 @@ static void setupFontVariants_Text_(iText *d, const iFontSpec *spec, int baseId) /* This is the highest priority override font. */ d->overrideFontId = baseId; } + iAssert(activeText_ == d); pushBack_Array(&d->fontPriorityOrder, &(iPrioMapItem){ spec->priority, baseId }); for (enum iFontStyle style = 0; style < max_FontStyle; style++) { for (enum iFontSize sizeId = 0; sizeId < max_FontSize; sizeId++) { @@ -499,10 +500,13 @@ static void resetCache_Text_(iText *d) { } void resetFonts_Text(iText *d) { + iText *oldActive = activeText_; + setCurrent_Text(d); /* some routines rely on the global `activeText_` pointer */ deinitFonts_Text_(d); deinitCache_Text_(d); initCache_Text_(d); initFonts_Text_(d); + setCurrent_Text(oldActive); } static SDL_Palette *glyphPalette_(void) { @@ -1476,14 +1480,14 @@ static void evenMonospaceAdvances_GlyphBuffer_(iGlyphBuffer *d, iFont *baseFont) } static iRect run_Font_(iFont *d, const iRunArgs *args) { - const int mode = args->mode; - const iInt2 orig = args->pos; - iRect bounds = { orig, init_I2(0, d->height) }; - float xCursor = 0.0f; - float yCursor = 0.0f; - float xCursorMax = 0.0f; - const iBool isMonospaced = isMonospaced_Font(d); - iWrapText *wrap = args->wrap; + const int mode = args->mode; + const iInt2 orig = args->pos; + iRect bounds = { orig, init_I2(0, d->height) }; + float xCursor = 0.0f; + float yCursor = 0.0f; + float xCursorMax = 0.0f; + const iBool isMonospaced = isMonospaced_Font(d); + iWrapText *wrap = args->wrap; iAssert(args->text.end >= args->text.start); /* Split the text into a number of attributed runs that specify exactly which font is used and other attributes such as color. (HarfBuzz shaping is done diff --git a/src/ui/window.c b/src/ui/window.c index bc32e479..0a97b97c 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -865,7 +865,7 @@ static iBool handleWindowEvent_MainWindow_(iMainWindow *d, const SDL_WindowEvent if (d->base.isMinimized) { return iFalse; } - closePopups_App(); + closePopups_App(iFalse); checkPixelRatioChange_Window_(as_Window(d)); const iInt2 newPos = init_I2(ev->data1, ev->data2); if (isEqual_I2(newPos, init1_I2(-32000))) { /* magic! */ @@ -915,7 +915,7 @@ static iBool handleWindowEvent_MainWindow_(iMainWindow *d, const SDL_WindowEvent // updateSize_Window_(d, iTrue); return iTrue; } - closePopups_App(); + closePopups_App(iFalse); if (unsnap_MainWindow_(d, NULL)) { return iTrue; } @@ -937,7 +937,7 @@ static iBool handleWindowEvent_MainWindow_(iMainWindow *d, const SDL_WindowEvent return iTrue; case SDL_WINDOWEVENT_MINIMIZED: d->base.isMinimized = iTrue; - closePopups_App(); + closePopups_App(iTrue); return iTrue; #else /* if defined (!iPlatformDesktop) */ case SDL_WINDOWEVENT_RESIZED: @@ -973,7 +973,7 @@ static iBool handleWindowEvent_MainWindow_(iMainWindow *d, const SDL_WindowEvent #if !defined (iPlatformDesktop) setFreezeDraw_MainWindow(d, iTrue); #endif - closePopups_App(); + closePopups_App(iTrue); return iFalse; case SDL_WINDOWEVENT_TAKE_FOCUS: SDL_SetWindowInputFocus(d->base.win); @@ -1178,7 +1178,35 @@ iLocalDef iBool isEscapeKeypress_(const SDL_Event *ev) { return (ev->type == SDL_KEYDOWN || ev->type == SDL_KEYUP) && ev->key.keysym.sym == SDLK_ESCAPE; } +static uint32_t windowId_SDLEvent_(const SDL_Event *ev) { + switch (ev->type) { + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + return ev->button.windowID; + case SDL_MOUSEMOTION: + return ev->motion.windowID; + case SDL_MOUSEWHEEL: + return ev->wheel.windowID; + case SDL_KEYDOWN: + case SDL_KEYUP: + return ev->key.windowID; + case SDL_TEXTINPUT: + return ev->text.windowID; + case SDL_USEREVENT: + return ev->user.windowID; + default: + return 0; + } +} + iBool dispatchEvent_Window(iWindow *d, const SDL_Event *ev) { +#if 0 + /* For the right window? */ + const uint32_t evWin = windowId_SDLEvent_(ev); + if (evWin && evWin != id_Window(d)) { + return iFalse; /* Meant for a different window. */ + } +#endif if (ev->type == SDL_MOUSEMOTION) { /* Hover widget may change. */ setHover_Widget(NULL); -- cgit v1.2.3