summaryrefslogtreecommitdiff
path: root/src/ui/documentwidget.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r--src/ui/documentwidget.c98
1 files changed, 76 insertions, 22 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 384c51b5..50df05f5 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -264,6 +264,7 @@ struct Impl_DocumentWidget {
264 int pinchZoomPosted; 264 int pinchZoomPosted;
265 float swipeSpeed; /* points/sec */ 265 float swipeSpeed; /* points/sec */
266 iString pendingGotoHeading; 266 iString pendingGotoHeading;
267 iString linePrecedingLink;
267 268
268 /* Network request: */ 269 /* Network request: */
269 enum iRequestState state; 270 enum iRequestState state;
@@ -391,6 +392,7 @@ void init_DocumentWidget(iDocumentWidget *d) {
391 d->grabbedPlayer = NULL; 392 d->grabbedPlayer = NULL;
392 d->mediaTimer = 0; 393 d->mediaTimer = 0;
393 init_String(&d->pendingGotoHeading); 394 init_String(&d->pendingGotoHeading);
395 init_String(&d->linePrecedingLink);
394 init_Click(&d->click, d, SDL_BUTTON_LEFT); 396 init_Click(&d->click, d, SDL_BUTTON_LEFT);
395 addChild_Widget(w, iClob(d->scroll = new_ScrollWidget())); 397 addChild_Widget(w, iClob(d->scroll = new_ScrollWidget()));
396 d->menu = NULL; /* created when clicking */ 398 d->menu = NULL; /* created when clicking */
@@ -437,6 +439,7 @@ void deinit_DocumentWidget(iDocumentWidget *d) {
437 iRelease(d->media); 439 iRelease(d->media);
438 iRelease(d->request); 440 iRelease(d->request);
439 delete_Gempub(d->sourceGempub); 441 delete_Gempub(d->sourceGempub);
442 deinit_String(&d->linePrecedingLink);
440 deinit_String(&d->pendingGotoHeading); 443 deinit_String(&d->pendingGotoHeading);
441 deinit_Block(&d->sourceContent); 444 deinit_Block(&d->sourceContent);
442 deinit_String(&d->sourceMime); 445 deinit_String(&d->sourceMime);
@@ -1893,7 +1896,7 @@ static void addBannerWarnings_DocumentWidget_(iDocumentWidget *d) {
1893 1896
1894static void updateFromCachedResponse_DocumentWidget_(iDocumentWidget *d, float normScrollY, 1897static void updateFromCachedResponse_DocumentWidget_(iDocumentWidget *d, float normScrollY,
1895 const iGmResponse *resp, iGmDocument *cachedDoc) { 1898 const iGmResponse *resp, iGmDocument *cachedDoc) {
1896 iAssert(width_Widget(d) > 0); /* must be laid out by now */ 1899// iAssert(width_Widget(d) > 0); /* must be laid out by now */
1897 setLinkNumberMode_DocumentWidget_(d, iFalse); 1900 setLinkNumberMode_DocumentWidget_(d, iFalse);
1898 clear_ObjectList(d->media); 1901 clear_ObjectList(d->media);
1899 delete_Gempub(d->sourceGempub); 1902 delete_Gempub(d->sourceGempub);
@@ -1918,9 +1921,6 @@ static void updateFromCachedResponse_DocumentWidget_(iDocumentWidget *d, float n
1918 setWidth_GmDocument(d->doc, documentWidth_DocumentWidget_(d), width_Widget(d)); 1921 setWidth_GmDocument(d->doc, documentWidth_DocumentWidget_(d), width_Widget(d));
1919 } 1922 }
1920 updateDocument_DocumentWidget_(d, resp, cachedDoc, iTrue); 1923 updateDocument_DocumentWidget_(d, resp, cachedDoc, iTrue);
1921// if (!cachedDoc) {
1922// setCachedDocument_History(d->mod.history, d->doc, iFalse);
1923// }
1924 clear_Banner(d->banner); 1924 clear_Banner(d->banner);
1925 updateBanner_DocumentWidget_(d); 1925 updateBanner_DocumentWidget_(d);
1926 addBannerWarnings_DocumentWidget_(d); 1926 addBannerWarnings_DocumentWidget_(d);
@@ -2242,6 +2242,16 @@ static void checkResponse_DocumentWidget_(iDocumentWidget *d) {
2242 if (lineBreak && deviceType_App() != desktop_AppDeviceType) { 2242 if (lineBreak && deviceType_App() != desktop_AppDeviceType) {
2243 addChildPos_Widget(buttons, iClob(lineBreak), front_WidgetAddPos); 2243 addChildPos_Widget(buttons, iClob(lineBreak), front_WidgetAddPos);
2244 } 2244 }
2245 /* Menu for additional actions, past entries. */ {
2246 iMenuItem items[] = { { "${menu.input.precedingline}",
2247 SDLK_v,
2248 KMOD_PRIMARY | KMOD_SHIFT,
2249 format_CStr("!valueinput.set ptr:%p text:%s",
2250 buttons,
2251 cstr_String(&d->linePrecedingLink)) } };
2252 iLabelWidget *menu = makeMenuButton_LabelWidget(midEllipsis_Icon, items, 1);
2253 addChildPos_Widget(buttons, iClob(menu), front_WidgetAddPos);
2254 }
2245 setValidator_InputWidget(findChild_Widget(dlg, "input"), inputQueryValidator_, d); 2255 setValidator_InputWidget(findChild_Widget(dlg, "input"), inputQueryValidator_, d);
2246 setSensitiveContent_InputWidget(findChild_Widget(dlg, "input"), 2256 setSensitiveContent_InputWidget(findChild_Widget(dlg, "input"),
2247 statusCode == sensitiveInput_GmStatusCode); 2257 statusCode == sensitiveInput_GmStatusCode);
@@ -3836,6 +3846,30 @@ static void beginMarkingSelection_DocumentWidget_(iDocumentWidget *d, iInt2 pos)
3836 refresh_Widget(as_Widget(d)); 3846 refresh_Widget(as_Widget(d));
3837} 3847}
3838 3848
3849static void linkWasTriggered_DocumentWidget_(iDocumentWidget *d, iGmLinkId id) {
3850 iRangecc loc = linkUrlRange_GmDocument(d->doc, id);
3851 if (!loc.start) {
3852 clear_String(&d->linePrecedingLink);
3853 return;
3854 }
3855 const char *start = range_String(source_GmDocument(d->doc)).start;
3856 /* Find the preceding line. This is offered as a prefill option for a possible input query. */
3857 while (loc.start > start && *loc.start != '\n') {
3858 loc.start--;
3859 }
3860 loc.end = loc.start; /* End of the preceding line. */
3861 if (loc.start > start) {
3862 loc.start--;
3863 }
3864 while (loc.start > start && *loc.start != '\n') {
3865 loc.start--;
3866 }
3867 if (*loc.start == '\n') {
3868 loc.start++; /* Start of the preceding line. */
3869 }
3870 setRange_String(&d->linePrecedingLink, loc);
3871}
3872
3839static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *ev) { 3873static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *ev) {
3840 iWidget *w = as_Widget(d); 3874 iWidget *w = as_Widget(d);
3841 if (isMetricsChange_UserEvent(ev)) { 3875 if (isMetricsChange_UserEvent(ev)) {
@@ -3878,6 +3912,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
3878 : (d->flags & newTabViaHomeKeys_DocumentWidgetFlag ? 1 : 0)), 3912 : (d->flags & newTabViaHomeKeys_DocumentWidgetFlag ? 1 : 0)),
3879 cstr_String(absoluteUrl_String( 3913 cstr_String(absoluteUrl_String(
3880 d->mod.url, linkUrl_GmDocument(d->doc, run->linkId)))); 3914 d->mod.url, linkUrl_GmDocument(d->doc, run->linkId))));
3915 linkWasTriggered_DocumentWidget_(d, run->linkId);
3881 } 3916 }
3882 setLinkNumberMode_DocumentWidget_(d, iFalse); 3917 setLinkNumberMode_DocumentWidget_(d, iFalse);
3883 invalidateVisibleLinks_DocumentWidget_(d); 3918 invalidateVisibleLinks_DocumentWidget_(d);
@@ -3995,6 +4030,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
3995 return iTrue; 4030 return iTrue;
3996 } 4031 }
3997 if (ev->button.button == SDL_BUTTON_MIDDLE && d->hoverLink) { 4032 if (ev->button.button == SDL_BUTTON_MIDDLE && d->hoverLink) {
4033 linkWasTriggered_DocumentWidget_(d, d->hoverLink->linkId);
3998 postCommandf_Root(w->root, "open newtab:%d url:%s", 4034 postCommandf_Root(w->root, "open newtab:%d url:%s",
3999 (isPinned_DocumentWidget_(d) ? otherRoot_OpenTabFlag : 0) | 4035 (isPinned_DocumentWidget_(d) ? otherRoot_OpenTabFlag : 0) |
4000 (modState_Keys() & KMOD_SHIFT ? new_OpenTabFlag : newBackground_OpenTabFlag), 4036 (modState_Keys() & KMOD_SHIFT ? new_OpenTabFlag : newBackground_OpenTabFlag),
@@ -4015,6 +4051,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
4015 init_Array(&items, sizeof(iMenuItem)); 4051 init_Array(&items, sizeof(iMenuItem));
4016 if (d->contextLink) { 4052 if (d->contextLink) {
4017 /* Context menu for a link. */ 4053 /* Context menu for a link. */
4054 linkWasTriggered_DocumentWidget_(d, d->contextLink->linkId); /* perhaps will be triggered */
4018 const iString *linkUrl = linkUrl_GmDocument(d->doc, d->contextLink->linkId); 4055 const iString *linkUrl = linkUrl_GmDocument(d->doc, d->contextLink->linkId);
4019// const int linkFlags = linkFlags_GmDocument(d->doc, d->contextLink->linkId); 4056// const int linkFlags = linkFlags_GmDocument(d->doc, d->contextLink->linkId);
4020 const iRangecc scheme = urlScheme_String(linkUrl); 4057 const iRangecc scheme = urlScheme_String(linkUrl);
@@ -4034,23 +4071,30 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
4034 /* Regular links that we can open. */ 4071 /* Regular links that we can open. */
4035 pushBackN_Array( 4072 pushBackN_Array(
4036 &items, 4073 &items,
4037 (iMenuItem[]){ 4074 (iMenuItem[]){ { openTab_Icon " ${link.newtab}",
4038 { openTab_Icon " ${link.newtab}", 4075 0,
4039 0, 4076 0,
4040 0, 4077 format_CStr("!open newtab:1 origin:%s url:%s",
4041 format_CStr("!open newtab:1 url:%s", cstr_String(linkUrl)) }, 4078 cstr_String(id_Widget(w)),
4042 { openTabBg_Icon " ${link.newtab.background}", 4079 cstr_String(linkUrl)) },
4043 0, 4080 { openTabBg_Icon " ${link.newtab.background}",
4044 0, 4081 0,
4045 format_CStr("!open newtab:2 url:%s", cstr_String(linkUrl)) }, 4082 0,
4046 { "${link.side}", 4083 format_CStr("!open newtab:2 origin:%s url:%s",
4047 0, 4084 cstr_String(id_Widget(w)),
4048 0, 4085 cstr_String(linkUrl)) },
4049 format_CStr("!open newtab:4 url:%s", cstr_String(linkUrl)) }, 4086 { "${link.side}",
4050 { "${link.side.newtab}", 4087 0,
4051 0, 4088 0,
4052 0, 4089 format_CStr("!open newtab:4 origin:%s url:%s",
4053 format_CStr("!open newtab:5 url:%s", cstr_String(linkUrl)) } }, 4090 cstr_String(id_Widget(w)),
4091 cstr_String(linkUrl)) },
4092 { "${link.side.newtab}",
4093 0,
4094 0,
4095 format_CStr("!open newtab:5 origin:%s url:%s",
4096 cstr_String(id_Widget(w)),
4097 cstr_String(linkUrl)) } },
4054 4); 4098 4);
4055 if (deviceType_App() == phone_AppDeviceType) { 4099 if (deviceType_App() == phone_AppDeviceType) {
4056 removeN_Array(&items, size_Array(&items) - 2, iInvalidSize); 4100 removeN_Array(&items, size_Array(&items) - 2, iInvalidSize);
@@ -4072,7 +4116,9 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
4072 { isGemini ? "${link.noproxy}" : openExt_Icon " ${link.browser}", 4116 { isGemini ? "${link.noproxy}" : openExt_Icon " ${link.browser}",
4073 0, 4117 0,
4074 0, 4118 0,
4075 format_CStr("!open noproxy:1 url:%s", cstr_String(linkUrl)) } }, 4119 format_CStr("!open origin:%s noproxy:1 url:%s",
4120 cstr_String(id_Widget(w)),
4121 cstr_String(linkUrl)) } },
4076 2); 4122 2);
4077 } 4123 }
4078 iString *linkLabel = collectNewRange_String( 4124 iString *linkLabel = collectNewRange_String(
@@ -4414,6 +4460,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
4414 if (isPinned_DocumentWidget_(d)) { 4460 if (isPinned_DocumentWidget_(d)) {
4415 tabMode ^= otherRoot_OpenTabFlag; 4461 tabMode ^= otherRoot_OpenTabFlag;
4416 } 4462 }
4463 linkWasTriggered_DocumentWidget_(d, linkId);
4417 postCommandf_Root(w->root, "open newtab:%d url:%s", 4464 postCommandf_Root(w->root, "open newtab:%d url:%s",
4418 tabMode, 4465 tabMode,
4419 cstr_String(absoluteUrl_String( 4466 cstr_String(absoluteUrl_String(
@@ -5495,6 +5542,13 @@ iDocumentWidget *duplicate_DocumentWidget(const iDocumentWidget *orig) {
5495 return d; 5542 return d;
5496} 5543}
5497 5544
5545void setOrigin_DocumentWidget(iDocumentWidget *d, const iDocumentWidget *other) {
5546 if (d != other) {
5547 /* TODO: Could remember the other's ID? */
5548 set_String(&d->linePrecedingLink, &other->linePrecedingLink);
5549 }
5550}
5551
5498void setUrl_DocumentWidget(iDocumentWidget *d, const iString *url) { 5552void setUrl_DocumentWidget(iDocumentWidget *d, const iString *url) {
5499 setUrlFlags_DocumentWidget(d, url, 0); 5553 setUrlFlags_DocumentWidget(d, url, 0);
5500} 5554}