=> 07804493ac17ff430302c7940f44b7525c0620e8
[1mdiff --git a/res/about/version.gmi b/res/about/version.gmi[m [1mindex a0cbe637..df532ab3 100644[m [1m--- a/res/about/version.gmi[m [1m+++ b/res/about/version.gmi[m [36m@@ -9,6 +9,8 @@[m ## 1.10.3[m * Added a man page.[m * "/index.gmi" is considered equal to "/" when navigating to parent directory.[m [32m+[m[32m* Gopher: Fixed navigating to root, e.g., when clicking on the page top banner. Set item type to 1 to show a gophermap and not the plain source.[m [32m+[m[32m* Titan: When navigating to parent/root, switch URL scheme to "gemini". This action occurs on a Titan response page, so initiating a new upload with the parent/root URL is probably not appropriate.[m * Fixed crash when a media player is active and a new download is started.[m * Fixed crash when a line contains nothing but an ANSI escape sequence.[m * Fixed a possible crash when saving state of subscribed feeds.[m [1mdiff --git a/src/gmutil.c b/src/gmutil.c[m [1mindex 98e4d4d6..b984950e 100644[m [1m--- a/src/gmutil.c[m [1m+++ b/src/gmutil.c[m [36m@@ -131,6 +131,16 @@[m [mstatic iRangecc prevPathSeg_(const char *end, const char *start) {[m return seg;[m }[m [m [32m+[m[32mvoid stripUrlPort_String(iString *d) {[m [32m+[m[32m iUrl parts;[m [32m+[m[32m init_Url(&parts, d);[m [32m+[m[32m if (!isEmpty_Range(&parts.port)) {[m [32m+[m[32m /* Always preceded by a colon. */[m [32m+[m[32m remove_Block(&d->chars, parts.port.start - 1 - constBegin_String(d),[m [32m+[m[32m size_Range(&parts.port) + 1);[m [32m+[m[32m }[m [32m+[m[32m}[m [32m+[m void stripDefaultUrlPort_String(iString *d) {[m iUrl parts;[m init_Url(&parts, d);[m [36m@@ -681,6 +691,17 @@[m [mconst iString *withSpacesEncoded_String(const iString *d) {[m return d;[m }[m [m [32m+[m[32mconst iString *withScheme_String(const iString *d, const char *scheme) {[m [32m+[m[32m iUrl parts;[m [32m+[m[32m init_Url(&parts, d);[m [32m+[m[32m if (!equalCase_Rangecc(parts.scheme, scheme)) {[m [32m+[m[32m iString *repl = collectNewCStr_String(scheme);[m [32m+[m[32m appendRange_String(repl, (iRangecc){ parts.scheme.end, constEnd_String(d) });[m [32m+[m[32m return repl;[m [32m+[m[32m }[m [32m+[m[32m return d;[m [32m+[m[32m}[m [32m+[m const iString *canonicalUrl_String(const iString *d) {[m /* The "canonical" form, used for internal storage and comparisons, is:[m - all non-reserved characters decoded (i.e., it's an IRI)[m [1mdiff --git a/src/gmutil.h b/src/gmutil.h[m [1mindex 15bb7b2e..1594afc4 100644[m [1m--- a/src/gmutil.h[m [1m+++ b/src/gmutil.h[m [36m@@ -127,6 +127,7 @@[m [miBool isKnownScheme_Rangecc (iRangecc scheme); /* any URI scheme */[m iBool isKnownUrlScheme_Rangecc(iRangecc scheme); /* URL schemes only */[m void punyEncodeDomain_Rangecc(iRangecc domain, iString *encoded_out);[m void punyEncodeUrlHost_String(iString *absoluteUrl);[m [32m+[m[32mvoid stripUrlPort_String (iString *);[m void stripDefaultUrlPort_String(iString *);[m const iString * urlFragmentStripped_String(const iString *);[m const iString * urlQueryStripped_String (const iString *);[m [36m@@ -138,6 +139,7 @@[m [mconst char * makeFileUrl_CStr (const char *localFilePath);[m iString * localFilePathFromUrl_String(const iString *);[m void urlEncodeSpaces_String (iString *);[m const iString * withSpacesEncoded_String(const iString *);[m [32m+[m[32mconst iString * withScheme_String (const iString *, const char *scheme); /* replace URI scheme */[m const iString * canonicalUrl_String (const iString *);[m [m const char * mediaType_Path (const iString *path);[m [1mdiff --git a/src/gopher.c b/src/gopher.c[m [1mindex 008a7743..0e34fe6a 100644[m [1m--- a/src/gopher.c[m [1m+++ b/src/gopher.c[m [36m@@ -299,3 +299,13 @@[m [miBool processResponse_Gopher(iGopher *d, const iBlock *data) {[m }[m return changed;[m }[m [32m+[m [32m+[m[32mvoid setUrlItemType_Gopher(iString *url, char itemType) {[m [32m+[m[32m iUrl parts;[m [32m+[m[32m init_Url(&parts, url);[m [32m+[m[32m if (equalCase_Rangecc(parts.scheme, "gopher")) {[m [32m+[m[32m if (parts.path.start && size_Range(&parts.path) >= 2) {[m [32m+[m[32m ((char *) parts.path.start)[1] = itemType;[m [32m+[m[32m }[m [32m+[m[32m }[m[41m [m [32m+[m[32m}[m [1mdiff --git a/src/gopher.h b/src/gopher.h[m [1mindex 3ad7e374..3cad0c21 100644[m [1m--- a/src/gopher.h[m [1m+++ b/src/gopher.h[m [36m@@ -44,3 +44,5 @@[m [miDeclareTypeConstruction(Gopher)[m void open_Gopher (iGopher *, const iString *url);[m iBool processResponse_Gopher (iGopher *, const iBlock *data);[m void cancel_Gopher (iGopher *);[m [32m+[m [32m+[m[32mvoid setUrlItemType_Gopher (iString *url, char itemType);[m [1mdiff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c[m [1mindex 2e15cdce..86513368 100644[m [1m--- a/src/ui/documentwidget.c[m [1m+++ b/src/ui/documentwidget.c[m [36m@@ -36,6 +36,7 @@[m [mSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */[m #include "gmdocument.h"[m #include "gmrequest.h"[m #include "gmutil.h"[m [32m+[m[32m#include "gopher.h"[m #include "history.h"[m #include "indicatorwidget.h"[m #include "inputwidget.h"[m [36m@@ -4315,20 +4316,31 @@[m [mstatic iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)[m }[m iString *parentUrl = collectNewRange_String((iRangecc){ constBegin_String(d->mod.url),[m parts.path.end });[m [31m- if (equalCase_Rangecc(parts.scheme, "gopher")) {[m [31m- /* Always go to a gophermap. */[m [31m- iZap(parts);[m [31m- init_Url(&parts, parentUrl);[m [31m- if (parts.path.start && size_Range(&parts.path) >= 2) {[m [31m- ((char *) parts.path.start)[1] = '1';[m [31m- }[m [32m+[m[32m /* Always go to a gophermap. */[m [32m+[m[32m setUrlItemType_Gopher(parentUrl, '1');[m [32m+[m[32m /* Hierarchical navigation doesn't make sense with Titan. */[m [32m+[m[32m if (startsWith_String(parentUrl, "titan://")) {[m [32m+[m[32m /* We have no way of knowing if the corresponding URL is valid for Gemini,[m [32m+[m[32m but let's try anyway. */[m[41m [m [32m+[m[32m set_String(parentUrl, withScheme_String(parentUrl, "gemini"));[m [32m+[m[32m stripUrlPort_String(parentUrl);[m }[m postCommandf_Root(w->root, "open url:%s", cstr_String(parentUrl));[m }[m return iTrue;[m }[m else if (equal_Command(cmd, "navigate.root") && document_App() == d) {[m [31m- postCommandf_Root(w->root, "open url:%s/", cstr_Rangecc(urlRoot_String(d->mod.url)));[m [32m+[m[32m iString *rootUrl = collectNewRange_String(urlRoot_String(d->mod.url));[m [32m+[m[32m /* Always go to a gophermap. */[m [32m+[m[32m setUrlItemType_Gopher(rootUrl, '1');[m [32m+[m[32m /* Hierarchical navigation doesn't make sense with Titan. */[m [32m+[m[32m if (startsWith_String(rootUrl, "titan://")) {[m [32m+[m[32m /* We have no way of knowing if the corresponding URL is valid for Gemini,[m [32m+[m[32m but let's try anyway. */[m[41m [m [32m+[m[32m set_String(rootUrl, withScheme_String(rootUrl, "gemini"));[m [32m+[m[32m stripUrlPort_String(rootUrl);[m [32m+[m[32m }[m[41m [m [32m+[m[32m postCommandf_Root(w->root, "open url:%s/", cstr_String(rootUrl));[m return iTrue;[m }[m else if (equalWidget_Command(cmd, w, "scroll.moved")) {[m
text/gemini; charset=utf-8
This content has been proxied by September (ba2dc).