diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/app.c | 3 | ||||
-rw-r--r-- | src/gmdocument.c | 2 | ||||
-rw-r--r-- | src/gmrequest.c | 80 | ||||
-rw-r--r-- | src/ui/window.c | 12 |
4 files changed, 63 insertions, 34 deletions
@@ -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 | ||
83 | struct Impl_GmRequest { | 85 | struct 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 | ||
97 | iDefineObjectConstructionArgs(GmRequest, (iGmCerts *certs), certs) | 99 | iDefineObjectConstructionArgs(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 | ||
266 | static 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 | |||
280 | static 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 | |||
264 | void submit_GmRequest(iGmRequest *d) { | 300 | void 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 | |||
117 | static 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 | ||
118 | static const char *reloadCStr_ = "\U0001f503"; | 123 | static 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. */ { |