summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app.c3
-rw-r--r--src/gmdocument.c2
-rw-r--r--src/gmrequest.c80
-rw-r--r--src/ui/window.c12
4 files changed, 63 insertions, 34 deletions
diff --git a/src/app.c b/src/app.c
index ee30d644..5543db11 100644
--- a/src/app.c
+++ b/src/app.c
@@ -587,7 +587,8 @@ iBool handleCommand_App(const char *cmd) {
587 setCommandHandler_Widget(dlg, handlePrefsCommands_); 587 setCommandHandler_Widget(dlg, handlePrefsCommands_);
588 } 588 }
589 else if (equal_Command(cmd, "navigate.home")) { 589 else if (equal_Command(cmd, "navigate.home")) {
590 postCommand_App("open url:about:home"); 590 /* TODO: Look for bookmarks tagged homepage, or use the URL set in Preferences. */
591 postCommand_App("open url:about:lagrange");
591 return iTrue; 592 return iTrue;
592 } 593 }
593 else if (equal_Command(cmd, "zoom.set")) { 594 else if (equal_Command(cmd, "zoom.set")) {
diff --git a/src/gmdocument.c b/src/gmdocument.c
index d140b065..52ff1654 100644
--- a/src/gmdocument.c
+++ b/src/gmdocument.c
@@ -289,7 +289,7 @@ static void doLayout_GmDocument_(iGmDocument *d) {
289 static const char *bullet = "\u2022"; 289 static const char *bullet = "\u2022";
290 static const char *folder = "\U0001f4c1"; 290 static const char *folder = "\U0001f4c1";
291 static const char *globe = "\U0001f310"; 291 static const char *globe = "\U0001f310";
292 const float midRunSkip = 0.1f; /* extra space between wrapped text/quote lines */ 292 const float midRunSkip = 0.120f; /* extra space between wrapped text/quote lines */
293 clear_Array(&d->layout); 293 clear_Array(&d->layout);
294 clearLinks_GmDocument_(d); 294 clearLinks_GmDocument_(d);
295 clear_Array(&d->headings); 295 clear_Array(&d->headings);
diff --git a/src/gmrequest.c b/src/gmrequest.c
index 996c77ea..2b6ee9f9 100644
--- a/src/gmrequest.c
+++ b/src/gmrequest.c
@@ -2,11 +2,13 @@
2#include "gmutil.h" 2#include "gmutil.h"
3#include "gmcerts.h" 3#include "gmcerts.h"
4#include "app.h" /* dataDir_App() */ 4#include "app.h" /* dataDir_App() */
5#include "embedded.h"
5 6
6#include <the_Foundation/file.h> 7#include <the_Foundation/file.h>
7#include <the_Foundation/tlsrequest.h>
8#include <the_Foundation/mutex.h> 8#include <the_Foundation/mutex.h>
9#include <the_Foundation/path.h> 9#include <the_Foundation/path.h>
10#include <the_Foundation/regexp.h>
11#include <the_Foundation/tlsrequest.h>
10 12
11#include <SDL_timer.h> 13#include <SDL_timer.h>
12 14
@@ -81,17 +83,17 @@ enum iGmRequestState {
81}; 83};
82 84
83struct Impl_GmRequest { 85struct Impl_GmRequest {
84 iObject object; 86 iObject object;
85 iMutex mutex; 87 iMutex mutex;
86 iGmCerts * certs; /* not owned */ 88 iGmCerts * certs; /* not owned */
87 enum iGmRequestState state; 89 enum iGmRequestState state;
88 iString url; 90 iString url;
89 iTlsRequest * req; 91 iTlsRequest * req;
90 iGmResponse resp; 92 iGmResponse resp;
91 uint32_t timeoutId; /* in case server doesn't close the connection */ 93 uint32_t timeoutId; /* in case server doesn't close the connection */
92 iAudience * updated; 94 iAudience * updated;
93 iAudience * timeout; 95 iAudience * timeout;
94 iAudience * finished; 96 iAudience * finished;
95}; 97};
96 98
97iDefineObjectConstructionArgs(GmRequest, (iGmCerts *certs), certs) 99iDefineObjectConstructionArgs(GmRequest, (iGmCerts *certs), certs)
@@ -261,6 +263,40 @@ static void requestFinished_GmRequest_(iAnyObject *obj) {
261 iNotifyAudience(d, finished, GmRequestFinished); 263 iNotifyAudience(d, finished, GmRequestFinished);
262} 264}
263 265
266static const iBlock *aboutPageSource_(iRangecc path) {
267 const iBlock *src = NULL;
268 if (equalCase_Rangecc(&path, "lagrange")) {
269 return &blobAbout_Embedded;
270 }
271 if (equalCase_Rangecc(&path, "help")) {
272 return &blobHelp_Embedded;
273 }
274 if (equalCase_Rangecc(&path, "version")) {
275 return &blobVersion_Embedded;
276 }
277 return src;
278}
279
280static const iBlock *replaceVariables_(const iBlock *block) {
281 iRegExp *var = new_RegExp("\\$\\{([A-Z_]+)\\}", 0);
282 iRegExpMatch m;
283 if (matchRange_RegExp(var, range_Block(block), &m)) {
284 iBlock *replaced = collect_Block(copy_Block(block));
285 do {
286 const iRangei span = m.range;
287 remove_Block(replaced, span.start, size_Range(&span));
288 const iRangecc name = capturedRange_RegExpMatch(&m, 1);
289 if (equal_Rangecc(&name, "APP_VERSION")) {
290 insertData_Block(replaced, span.start,
291 LAGRANGE_APP_VERSION, strlen(LAGRANGE_APP_VERSION));
292 }
293 } while (matchRange_RegExp(var, range_Block(replaced), &m));
294 block = replaced;
295 }
296 iRelease(var);
297 return block;
298}
299
264void submit_GmRequest(iGmRequest *d) { 300void submit_GmRequest(iGmRequest *d) {
265 iAssert(d->state == initialized_GmRequestState); 301 iAssert(d->state == initialized_GmRequestState);
266 if (d->state != initialized_GmRequestState) { 302 if (d->state != initialized_GmRequestState) {
@@ -272,25 +308,11 @@ void submit_GmRequest(iGmRequest *d) {
272 /* Check for special protocols. */ 308 /* Check for special protocols. */
273 /* TODO: If this were a library, these could be handled via callbacks. */ 309 /* TODO: If this were a library, these could be handled via callbacks. */
274 if (equalCase_Rangecc(&url.protocol, "about")) { 310 if (equalCase_Rangecc(&url.protocol, "about")) {
275 if (equalCase_Rangecc(&url.path, "home")) { 311 const iBlock *src = aboutPageSource_(url.path);
312 if (src) {
276 d->resp.statusCode = success_GmStatusCode; 313 d->resp.statusCode = success_GmStatusCode;
277 setCStr_String(&d->resp.meta, "text/gemini; charset=utf-8"); 314 setCStr_String(&d->resp.meta, "text/gemini; charset=utf-8");
278 setCStr_Block(&d->resp.body, 315 set_Block(&d->resp.body, replaceVariables_(src));
279"```\n"
280"ooooo\n"
281"`888'\n"
282" 888 .oooo. .oooooooo oooo d8b .oooo. ooo. .oo. .oooooooo .ooooo. \n"
283" 888 `P )88b 888' `88b `888\"\"8P `P )88b `888P\"Y88b 888' `88b d88' `88b \n"
284" 888 .oP\"888 888 888 888 .oP\"888 888 888 888 888 888ooo888 \n"
285" 888 o d8( 888 `88bod8P' 888 d8( 888 888 888 `88bod8P' 888 .o \n"
286"o888ooooood8 `Y888\"\"8o `8oooooo. d888b `Y888\"\"8o o888o o888o `8oooooo. `Y8bod8P' \n"
287" d\" YD d\" YD\n"
288" \"Y88888P' \"Y88888P'\n"
289"```\n"
290"# A Beautiful Gemini Client\n"
291"## Version " LAGRANGE_APP_VERSION "\n\n"
292"=> https://skyjake.fi/@jk by Jaakko Keränen <code@iki.fi>\n"
293"Crafted with \u2615 in Finland\n");
294 d->state = receivingBody_GmRequestState; 316 d->state = receivingBody_GmRequestState;
295 iNotifyAudience(d, updated, GmRequestUpdated); 317 iNotifyAudience(d, updated, GmRequestUpdated);
296 } 318 }
diff --git a/src/ui/window.c b/src/ui/window.c
index 2f5c428d..5e1ad9c6 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -113,6 +113,11 @@ static const iMenuItem viewMenuItems[] = {
113 { "Zoom Out", SDLK_MINUS, KMOD_PRIMARY, "zoom.delta arg:-10" }, 113 { "Zoom Out", SDLK_MINUS, KMOD_PRIMARY, "zoom.delta arg:-10" },
114 { "Reset Zoom", SDLK_0, KMOD_PRIMARY, "zoom.set arg:100" }, 114 { "Reset Zoom", SDLK_0, KMOD_PRIMARY, "zoom.set arg:100" },
115}; 115};
116
117static const iMenuItem helpMenuItems[] = {
118 { "Help", 0, 0, "open url:about:help" },
119 { "Release Notes", 0, 0, "open url:about:version" },
120};
116#endif 121#endif
117 122
118static const char *reloadCStr_ = "\U0001f503"; 123static const char *reloadCStr_ = "\U0001f503";
@@ -288,9 +293,10 @@ static void setupUserInterface_Window(iWindow *d) {
288 setAlignVisually_LabelWidget(navMenu, iTrue); 293 setAlignVisually_LabelWidget(navMenu, iTrue);
289 addChild_Widget(navBar, iClob(navMenu)); 294 addChild_Widget(navBar, iClob(navMenu));
290#else 295#else
291 insertMenuItems_MacOS("File", fileMenuItems, iElemCount(fileMenuItems)); 296 insertMenuItems_MacOS("File", 1, fileMenuItems, iElemCount(fileMenuItems));
292 insertMenuItems_MacOS("Edit", editMenuItems, iElemCount(editMenuItems)); 297 insertMenuItems_MacOS("Edit", 2, editMenuItems, iElemCount(editMenuItems));
293 insertMenuItems_MacOS("View", viewMenuItems, iElemCount(viewMenuItems)); 298 insertMenuItems_MacOS("View", 3, viewMenuItems, iElemCount(viewMenuItems));
299 insertMenuItems_MacOS("Help", 5, helpMenuItems, iElemCount(helpMenuItems));
294#endif 300#endif
295 } 301 }
296 /* Tab bar. */ { 302 /* Tab bar. */ {