diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2022-01-29 18:00:01 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2022-01-29 18:00:01 +0200 |
commit | 07804493ac17ff430302c7940f44b7525c0620e8 (patch) | |
tree | 885db4fd4576ef65df77d4d47a3ae354efdba01e | |
parent | 8d46b523f2948992343a9491a12dcec73f109c87 (diff) |
Hierarchical navigation with Gopher and Titan
With Gopher, ensure that the item type changes to 1, and with Titan, change to normal Gemini.
-rw-r--r-- | res/about/version.gmi | 2 | ||||
-rw-r--r-- | src/gmutil.c | 21 | ||||
-rw-r--r-- | src/gmutil.h | 2 | ||||
-rw-r--r-- | src/gopher.c | 10 | ||||
-rw-r--r-- | src/gopher.h | 2 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 28 |
6 files changed, 57 insertions, 8 deletions
diff --git a/res/about/version.gmi b/res/about/version.gmi index a0cbe637..df532ab3 100644 --- a/res/about/version.gmi +++ b/res/about/version.gmi | |||
@@ -9,6 +9,8 @@ | |||
9 | ## 1.10.3 | 9 | ## 1.10.3 |
10 | * Added a man page. | 10 | * Added a man page. |
11 | * "/index.gmi" is considered equal to "/" when navigating to parent directory. | 11 | * "/index.gmi" is considered equal to "/" when navigating to parent directory. |
12 | * 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. | ||
13 | * 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. | ||
12 | * Fixed crash when a media player is active and a new download is started. | 14 | * Fixed crash when a media player is active and a new download is started. |
13 | * Fixed crash when a line contains nothing but an ANSI escape sequence. | 15 | * Fixed crash when a line contains nothing but an ANSI escape sequence. |
14 | * Fixed a possible crash when saving state of subscribed feeds. | 16 | * Fixed a possible crash when saving state of subscribed feeds. |
diff --git a/src/gmutil.c b/src/gmutil.c index 98e4d4d6..b984950e 100644 --- a/src/gmutil.c +++ b/src/gmutil.c | |||
@@ -131,6 +131,16 @@ static iRangecc prevPathSeg_(const char *end, const char *start) { | |||
131 | return seg; | 131 | return seg; |
132 | } | 132 | } |
133 | 133 | ||
134 | void stripUrlPort_String(iString *d) { | ||
135 | iUrl parts; | ||
136 | init_Url(&parts, d); | ||
137 | if (!isEmpty_Range(&parts.port)) { | ||
138 | /* Always preceded by a colon. */ | ||
139 | remove_Block(&d->chars, parts.port.start - 1 - constBegin_String(d), | ||
140 | size_Range(&parts.port) + 1); | ||
141 | } | ||
142 | } | ||
143 | |||
134 | void stripDefaultUrlPort_String(iString *d) { | 144 | void stripDefaultUrlPort_String(iString *d) { |
135 | iUrl parts; | 145 | iUrl parts; |
136 | init_Url(&parts, d); | 146 | init_Url(&parts, d); |
@@ -681,6 +691,17 @@ const iString *withSpacesEncoded_String(const iString *d) { | |||
681 | return d; | 691 | return d; |
682 | } | 692 | } |
683 | 693 | ||
694 | const iString *withScheme_String(const iString *d, const char *scheme) { | ||
695 | iUrl parts; | ||
696 | init_Url(&parts, d); | ||
697 | if (!equalCase_Rangecc(parts.scheme, scheme)) { | ||
698 | iString *repl = collectNewCStr_String(scheme); | ||
699 | appendRange_String(repl, (iRangecc){ parts.scheme.end, constEnd_String(d) }); | ||
700 | return repl; | ||
701 | } | ||
702 | return d; | ||
703 | } | ||
704 | |||
684 | const iString *canonicalUrl_String(const iString *d) { | 705 | const iString *canonicalUrl_String(const iString *d) { |
685 | /* The "canonical" form, used for internal storage and comparisons, is: | 706 | /* The "canonical" form, used for internal storage and comparisons, is: |
686 | - all non-reserved characters decoded (i.e., it's an IRI) | 707 | - all non-reserved characters decoded (i.e., it's an IRI) |
diff --git a/src/gmutil.h b/src/gmutil.h index 15bb7b2e..1594afc4 100644 --- a/src/gmutil.h +++ b/src/gmutil.h | |||
@@ -127,6 +127,7 @@ iBool isKnownScheme_Rangecc (iRangecc scheme); /* any URI scheme */ | |||
127 | iBool isKnownUrlScheme_Rangecc(iRangecc scheme); /* URL schemes only */ | 127 | iBool isKnownUrlScheme_Rangecc(iRangecc scheme); /* URL schemes only */ |
128 | void punyEncodeDomain_Rangecc(iRangecc domain, iString *encoded_out); | 128 | void punyEncodeDomain_Rangecc(iRangecc domain, iString *encoded_out); |
129 | void punyEncodeUrlHost_String(iString *absoluteUrl); | 129 | void punyEncodeUrlHost_String(iString *absoluteUrl); |
130 | void stripUrlPort_String (iString *); | ||
130 | void stripDefaultUrlPort_String(iString *); | 131 | void stripDefaultUrlPort_String(iString *); |
131 | const iString * urlFragmentStripped_String(const iString *); | 132 | const iString * urlFragmentStripped_String(const iString *); |
132 | const iString * urlQueryStripped_String (const iString *); | 133 | const iString * urlQueryStripped_String (const iString *); |
@@ -138,6 +139,7 @@ const char * makeFileUrl_CStr (const char *localFilePath); | |||
138 | iString * localFilePathFromUrl_String(const iString *); | 139 | iString * localFilePathFromUrl_String(const iString *); |
139 | void urlEncodeSpaces_String (iString *); | 140 | void urlEncodeSpaces_String (iString *); |
140 | const iString * withSpacesEncoded_String(const iString *); | 141 | const iString * withSpacesEncoded_String(const iString *); |
142 | const iString * withScheme_String (const iString *, const char *scheme); /* replace URI scheme */ | ||
141 | const iString * canonicalUrl_String (const iString *); | 143 | const iString * canonicalUrl_String (const iString *); |
142 | 144 | ||
143 | const char * mediaType_Path (const iString *path); | 145 | const char * mediaType_Path (const iString *path); |
diff --git a/src/gopher.c b/src/gopher.c index 008a7743..0e34fe6a 100644 --- a/src/gopher.c +++ b/src/gopher.c | |||
@@ -299,3 +299,13 @@ iBool processResponse_Gopher(iGopher *d, const iBlock *data) { | |||
299 | } | 299 | } |
300 | return changed; | 300 | return changed; |
301 | } | 301 | } |
302 | |||
303 | void setUrlItemType_Gopher(iString *url, char itemType) { | ||
304 | iUrl parts; | ||
305 | init_Url(&parts, url); | ||
306 | if (equalCase_Rangecc(parts.scheme, "gopher")) { | ||
307 | if (parts.path.start && size_Range(&parts.path) >= 2) { | ||
308 | ((char *) parts.path.start)[1] = itemType; | ||
309 | } | ||
310 | } | ||
311 | } | ||
diff --git a/src/gopher.h b/src/gopher.h index 3ad7e374..3cad0c21 100644 --- a/src/gopher.h +++ b/src/gopher.h | |||
@@ -44,3 +44,5 @@ iDeclareTypeConstruction(Gopher) | |||
44 | void open_Gopher (iGopher *, const iString *url); | 44 | void open_Gopher (iGopher *, const iString *url); |
45 | iBool processResponse_Gopher (iGopher *, const iBlock *data); | 45 | iBool processResponse_Gopher (iGopher *, const iBlock *data); |
46 | void cancel_Gopher (iGopher *); | 46 | void cancel_Gopher (iGopher *); |
47 | |||
48 | void setUrlItemType_Gopher (iString *url, char itemType); | ||
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 2e15cdce..86513368 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
36 | #include "gmdocument.h" | 36 | #include "gmdocument.h" |
37 | #include "gmrequest.h" | 37 | #include "gmrequest.h" |
38 | #include "gmutil.h" | 38 | #include "gmutil.h" |
39 | #include "gopher.h" | ||
39 | #include "history.h" | 40 | #include "history.h" |
40 | #include "indicatorwidget.h" | 41 | #include "indicatorwidget.h" |
41 | #include "inputwidget.h" | 42 | #include "inputwidget.h" |
@@ -4315,20 +4316,31 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
4315 | } | 4316 | } |
4316 | iString *parentUrl = collectNewRange_String((iRangecc){ constBegin_String(d->mod.url), | 4317 | iString *parentUrl = collectNewRange_String((iRangecc){ constBegin_String(d->mod.url), |
4317 | parts.path.end }); | 4318 | parts.path.end }); |
4318 | if (equalCase_Rangecc(parts.scheme, "gopher")) { | 4319 | /* Always go to a gophermap. */ |
4319 | /* Always go to a gophermap. */ | 4320 | setUrlItemType_Gopher(parentUrl, '1'); |
4320 | iZap(parts); | 4321 | /* Hierarchical navigation doesn't make sense with Titan. */ |
4321 | init_Url(&parts, parentUrl); | 4322 | if (startsWith_String(parentUrl, "titan://")) { |
4322 | if (parts.path.start && size_Range(&parts.path) >= 2) { | 4323 | /* We have no way of knowing if the corresponding URL is valid for Gemini, |
4323 | ((char *) parts.path.start)[1] = '1'; | 4324 | but let's try anyway. */ |
4324 | } | 4325 | set_String(parentUrl, withScheme_String(parentUrl, "gemini")); |
4326 | stripUrlPort_String(parentUrl); | ||
4325 | } | 4327 | } |
4326 | postCommandf_Root(w->root, "open url:%s", cstr_String(parentUrl)); | 4328 | postCommandf_Root(w->root, "open url:%s", cstr_String(parentUrl)); |
4327 | } | 4329 | } |
4328 | return iTrue; | 4330 | return iTrue; |
4329 | } | 4331 | } |
4330 | else if (equal_Command(cmd, "navigate.root") && document_App() == d) { | 4332 | else if (equal_Command(cmd, "navigate.root") && document_App() == d) { |
4331 | postCommandf_Root(w->root, "open url:%s/", cstr_Rangecc(urlRoot_String(d->mod.url))); | 4333 | iString *rootUrl = collectNewRange_String(urlRoot_String(d->mod.url)); |
4334 | /* Always go to a gophermap. */ | ||
4335 | setUrlItemType_Gopher(rootUrl, '1'); | ||
4336 | /* Hierarchical navigation doesn't make sense with Titan. */ | ||
4337 | if (startsWith_String(rootUrl, "titan://")) { | ||
4338 | /* We have no way of knowing if the corresponding URL is valid for Gemini, | ||
4339 | but let's try anyway. */ | ||
4340 | set_String(rootUrl, withScheme_String(rootUrl, "gemini")); | ||
4341 | stripUrlPort_String(rootUrl); | ||
4342 | } | ||
4343 | postCommandf_Root(w->root, "open url:%s/", cstr_String(rootUrl)); | ||
4332 | return iTrue; | 4344 | return iTrue; |
4333 | } | 4345 | } |
4334 | else if (equalWidget_Command(cmd, w, "scroll.moved")) { | 4346 | else if (equalWidget_Command(cmd, w, "scroll.moved")) { |