diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/app.c | 21 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 98 | ||||
-rw-r--r-- | src/ui/documentwidget.h | 1 | ||||
-rw-r--r-- | src/ui/inputwidget.c | 10 | ||||
-rw-r--r-- | src/ui/inputwidget.h | 1 | ||||
-rw-r--r-- | src/ui/mobile.c | 12 | ||||
-rw-r--r-- | src/ui/root.c | 2 | ||||
-rw-r--r-- | src/ui/util.c | 12 | ||||
-rw-r--r-- | src/ui/window.c | 6 | ||||
-rw-r--r-- | src/ui/window.h | 1 |
10 files changed, 124 insertions, 40 deletions
@@ -356,7 +356,7 @@ static void loadPrefs_App_(iApp *d) { | |||
356 | setUiScale_Window(get_Window(), argf_Command(cmd)); | 356 | setUiScale_Window(get_Window(), argf_Command(cmd)); |
357 | } | 357 | } |
358 | else if (equal_Command(cmd, "uilang")) { | 358 | else if (equal_Command(cmd, "uilang")) { |
359 | const char *id = cstr_Rangecc(range_Command(cmd, "id")); | 359 | const char *id = cstr_Command(cmd, "id"); |
360 | setCStr_String(&d->prefs.strings[uiLanguage_PrefsString], id); | 360 | setCStr_String(&d->prefs.strings[uiLanguage_PrefsString], id); |
361 | setCurrent_Lang(id); | 361 | setCurrent_Lang(id); |
362 | } | 362 | } |
@@ -2190,6 +2190,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2190 | return iTrue; | 2190 | return iTrue; |
2191 | } | 2191 | } |
2192 | else if (equal_Command(cmd, "fontpack.suggest.classic")) { | 2192 | else if (equal_Command(cmd, "fontpack.suggest.classic")) { |
2193 | /* TODO: Don't use this when system fonts are accessible. */ | ||
2193 | if (!isInstalled_Fonts("classic-set") && !isInstalled_Fonts("cjk")) { | 2194 | if (!isInstalled_Fonts("classic-set") && !isInstalled_Fonts("cjk")) { |
2194 | makeQuestion_Widget( | 2195 | makeQuestion_Widget( |
2195 | uiHeading_ColorEscape "${heading.fontpack.classic}", | 2196 | uiHeading_ColorEscape "${heading.fontpack.classic}", |
@@ -2243,6 +2244,9 @@ iBool handleCommand_App(const char *cmd) { | |||
2243 | (argLabel_Command(cmd, "axis") ? vertical_WindowSplit : 0) | (arg_Command(cmd) << 1); | 2244 | (argLabel_Command(cmd, "axis") ? vertical_WindowSplit : 0) | (arg_Command(cmd) << 1); |
2244 | const char *url = suffixPtr_Command(cmd, "url"); | 2245 | const char *url = suffixPtr_Command(cmd, "url"); |
2245 | setCStr_String(d->window->pendingSplitUrl, url ? url : ""); | 2246 | setCStr_String(d->window->pendingSplitUrl, url ? url : ""); |
2247 | if (hasLabel_Command(cmd, "origin")) { | ||
2248 | set_String(d->window->pendingSplitOrigin, string_Command(cmd, "origin")); | ||
2249 | } | ||
2246 | postRefresh_App(); | 2250 | postRefresh_App(); |
2247 | return iTrue; | 2251 | return iTrue; |
2248 | } | 2252 | } |
@@ -2732,12 +2736,21 @@ iBool handleCommand_App(const char *cmd) { | |||
2732 | openInDefaultBrowser_App(url); | 2736 | openInDefaultBrowser_App(url); |
2733 | return iTrue; | 2737 | return iTrue; |
2734 | } | 2738 | } |
2739 | iDocumentWidget *doc = document_Command(cmd); | ||
2740 | iDocumentWidget *origin = doc; | ||
2741 | if (hasLabel_Command(cmd, "origin")) { | ||
2742 | iDocumentWidget *cmdOrig = findWidget_App(cstr_Command(cmd, "origin")); | ||
2743 | if (cmdOrig) { | ||
2744 | origin = cmdOrig; | ||
2745 | } | ||
2746 | } | ||
2735 | const int newTab = argLabel_Command(cmd, "newtab"); | 2747 | const int newTab = argLabel_Command(cmd, "newtab"); |
2736 | if (newTab & otherRoot_OpenTabFlag && numRoots_Window(get_Window()) == 1) { | 2748 | if (newTab & otherRoot_OpenTabFlag && numRoots_Window(get_Window()) == 1) { |
2737 | /* Need to split first. */ | 2749 | /* Need to split first. */ |
2738 | const iInt2 winSize = get_Window()->size; | 2750 | const iInt2 winSize = get_Window()->size; |
2739 | postCommandf_App("ui.split arg:3 axis:%d newtab:%d url:%s", | 2751 | postCommandf_App("ui.split arg:3 axis:%d origin:%s newtab:%d url:%s", |
2740 | (float) winSize.x / (float) winSize.y < 0.7f ? 1 : 0, | 2752 | (float) winSize.x / (float) winSize.y < 0.7f ? 1 : 0, |
2753 | cstr_String(id_Widget(as_Widget(origin))), | ||
2741 | newTab & ~otherRoot_OpenTabFlag, | 2754 | newTab & ~otherRoot_OpenTabFlag, |
2742 | cstr_String(url)); | 2755 | cstr_String(url)); |
2743 | return iTrue; | 2756 | return iTrue; |
@@ -2749,7 +2762,6 @@ iBool handleCommand_App(const char *cmd) { | |||
2749 | setKeyRoot_Window(as_Window(d->window), root); | 2762 | setKeyRoot_Window(as_Window(d->window), root); |
2750 | setCurrent_Root(root); /* need to change for widget creation */ | 2763 | setCurrent_Root(root); /* need to change for widget creation */ |
2751 | } | 2764 | } |
2752 | iDocumentWidget *doc = document_Command(cmd); | ||
2753 | if (newTab & (new_OpenTabFlag | newBackground_OpenTabFlag)) { | 2765 | if (newTab & (new_OpenTabFlag | newBackground_OpenTabFlag)) { |
2754 | doc = newTab_App(NULL, (newTab & new_OpenTabFlag) != 0); /* `newtab:2` to open in background */ | 2766 | doc = newTab_App(NULL, (newTab & new_OpenTabFlag) != 0); /* `newtab:2` to open in background */ |
2755 | } | 2767 | } |
@@ -2766,13 +2778,14 @@ iBool handleCommand_App(const char *cmd) { | |||
2766 | } | 2778 | } |
2767 | setInitialScroll_DocumentWidget(doc, argfLabel_Command(cmd, "scroll")); | 2779 | setInitialScroll_DocumentWidget(doc, argfLabel_Command(cmd, "scroll")); |
2768 | setRedirectCount_DocumentWidget(doc, redirectCount); | 2780 | setRedirectCount_DocumentWidget(doc, redirectCount); |
2781 | setOrigin_DocumentWidget(doc, origin); | ||
2769 | showCollapsed_Widget(findWidget_App("document.progress"), iFalse); | 2782 | showCollapsed_Widget(findWidget_App("document.progress"), iFalse); |
2770 | if (prefs_App()->decodeUserVisibleURLs) { | 2783 | if (prefs_App()->decodeUserVisibleURLs) { |
2771 | urlDecodePath_String(url); | 2784 | urlDecodePath_String(url); |
2772 | } | 2785 | } |
2773 | else { | 2786 | else { |
2774 | urlEncodePath_String(url); | 2787 | urlEncodePath_String(url); |
2775 | } | 2788 | } |
2776 | setUrlFlags_DocumentWidget(doc, url, | 2789 | setUrlFlags_DocumentWidget(doc, url, |
2777 | (isHistory ? useCachedContentIfAvailable_DocumentWidgetSetUrlFlag : 0) | | 2790 | (isHistory ? useCachedContentIfAvailable_DocumentWidgetSetUrlFlag : 0) | |
2778 | (fromSidebar ? openedFromSidebar_DocumentWidgetSetUrlFlag : 0)); | 2791 | (fromSidebar ? openedFromSidebar_DocumentWidgetSetUrlFlag : 0)); |
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 | ||
1894 | static void updateFromCachedResponse_DocumentWidget_(iDocumentWidget *d, float normScrollY, | 1897 | static 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 | ||
3849 | static 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 | |||
3839 | static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *ev) { | 3873 | static 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 | ||
5545 | void 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 | |||
5498 | void setUrl_DocumentWidget(iDocumentWidget *d, const iString *url) { | 5552 | void setUrl_DocumentWidget(iDocumentWidget *d, const iString *url) { |
5499 | setUrlFlags_DocumentWidget(d, url, 0); | 5553 | setUrlFlags_DocumentWidget(d, url, 0); |
5500 | } | 5554 | } |
diff --git a/src/ui/documentwidget.h b/src/ui/documentwidget.h index c97fa0ba..1405f19d 100644 --- a/src/ui/documentwidget.h +++ b/src/ui/documentwidget.h | |||
@@ -53,6 +53,7 @@ enum iDocumentWidgetSetUrlFlags { | |||
53 | openedFromSidebar_DocumentWidgetSetUrlFlag = iBit(2), | 53 | openedFromSidebar_DocumentWidgetSetUrlFlag = iBit(2), |
54 | }; | 54 | }; |
55 | 55 | ||
56 | void setOrigin_DocumentWidget (iDocumentWidget *, const iDocumentWidget *other); | ||
56 | void setUrl_DocumentWidget (iDocumentWidget *, const iString *url); | 57 | void setUrl_DocumentWidget (iDocumentWidget *, const iString *url); |
57 | void setUrlFlags_DocumentWidget (iDocumentWidget *, const iString *url, int setUrlFlags); | 58 | void setUrlFlags_DocumentWidget (iDocumentWidget *, const iString *url, int setUrlFlags); |
58 | void setUrlAndSource_DocumentWidget (iDocumentWidget *, const iString *url, const iString *mime, const iBlock *source); | 59 | void setUrlAndSource_DocumentWidget (iDocumentWidget *, const iString *url, const iString *mime, const iBlock *source); |
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index b910f905..b94e0c27 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c | |||
@@ -1163,6 +1163,12 @@ void selectAll_InputWidget(iInputWidget *d) { | |||
1163 | #endif | 1163 | #endif |
1164 | } | 1164 | } |
1165 | 1165 | ||
1166 | void validate_InputWidget(iInputWidget *d) { | ||
1167 | if (d->validator) { | ||
1168 | d->validator(d, d->validatorContext); /* this may change the contents */ | ||
1169 | } | ||
1170 | } | ||
1171 | |||
1166 | iLocalDef iBool isEditing_InputWidget_(const iInputWidget *d) { | 1172 | iLocalDef iBool isEditing_InputWidget_(const iInputWidget *d) { |
1167 | return (flags_Widget(constAs_Widget(d)) & selected_WidgetFlag) != 0; | 1173 | return (flags_Widget(constAs_Widget(d)) & selected_WidgetFlag) != 0; |
1168 | } | 1174 | } |
@@ -1653,9 +1659,7 @@ void setEatEscape_InputWidget(iInputWidget *d, iBool eatEscape) { | |||
1653 | } | 1659 | } |
1654 | 1660 | ||
1655 | static void contentsWereChanged_InputWidget_(iInputWidget *d) { | 1661 | static void contentsWereChanged_InputWidget_(iInputWidget *d) { |
1656 | if (d->validator) { | 1662 | validate_InputWidget(d); |
1657 | d->validator(d, d->validatorContext); /* this may change the contents */ | ||
1658 | } | ||
1659 | if (d->inFlags & notifyEdits_InputWidgetFlag) { | 1663 | if (d->inFlags & notifyEdits_InputWidgetFlag) { |
1660 | postCommand_Widget(d, "input.edited id:%s", cstr_String(id_Widget(constAs_Widget(d)))); | 1664 | postCommand_Widget(d, "input.edited id:%s", cstr_String(id_Widget(constAs_Widget(d)))); |
1661 | } | 1665 | } |
diff --git a/src/ui/inputwidget.h b/src/ui/inputwidget.h index f70c81af..5a61ec22 100644 --- a/src/ui/inputwidget.h +++ b/src/ui/inputwidget.h | |||
@@ -57,6 +57,7 @@ void setBackupFileName_InputWidget (iInputWidget *, const char *fileName); | |||
57 | void begin_InputWidget (iInputWidget *); | 57 | void begin_InputWidget (iInputWidget *); |
58 | void end_InputWidget (iInputWidget *, iBool accept); | 58 | void end_InputWidget (iInputWidget *, iBool accept); |
59 | void selectAll_InputWidget (iInputWidget *); | 59 | void selectAll_InputWidget (iInputWidget *); |
60 | void validate_InputWidget (iInputWidget *); | ||
60 | 61 | ||
61 | void setSelectAllOnFocus_InputWidget (iInputWidget *, iBool selectAllOnFocus); | 62 | void setSelectAllOnFocus_InputWidget (iInputWidget *, iBool selectAllOnFocus); |
62 | void setSensitiveContent_InputWidget (iInputWidget *, iBool isSensitive); | 63 | void setSensitiveContent_InputWidget (iInputWidget *, iBool isSensitive); |
diff --git a/src/ui/mobile.c b/src/ui/mobile.c index bf3eb425..df2a661a 100644 --- a/src/ui/mobile.c +++ b/src/ui/mobile.c | |||
@@ -499,7 +499,7 @@ void makePanelItem_Mobile(iWidget *panel, const iMenuItem *item) { | |||
499 | iLabelWidget *heading = NULL; | 499 | iLabelWidget *heading = NULL; |
500 | iWidget * value = NULL; | 500 | iWidget * value = NULL; |
501 | const char * spec = item->label; | 501 | const char * spec = item->label; |
502 | const char * id = cstr_Rangecc(range_Command(spec, "id")); | 502 | const char * id = cstr_Command(spec, "id"); |
503 | const char * label = hasLabel_Command(spec, "text") | 503 | const char * label = hasLabel_Command(spec, "text") |
504 | ? suffixPtr_Command(spec, "text") | 504 | ? suffixPtr_Command(spec, "text") |
505 | : format_CStr("${%s}", id); | 505 | : format_CStr("${%s}", id); |
@@ -580,7 +580,7 @@ void makePanelItem_Mobile(iWidget *panel, const iMenuItem *item) { | |||
580 | addChildFlags_Widget(widget, iClob(sep), 0); | 580 | addChildFlags_Widget(widget, iClob(sep), 0); |
581 | } | 581 | } |
582 | isFirst = iFalse; | 582 | isFirst = iFalse; |
583 | const char * radId = cstr_Rangecc(range_Command(radioItem->label, "id")); | 583 | const char * radId = cstr_Command(radioItem->label, "id"); |
584 | int64_t flags = noBackground_WidgetFlag | frameless_WidgetFlag; | 584 | int64_t flags = noBackground_WidgetFlag | frameless_WidgetFlag; |
585 | if (!isHorizontal) { | 585 | if (!isHorizontal) { |
586 | flags |= alignLeft_WidgetFlag; | 586 | flags |= alignLeft_WidgetFlag; |
@@ -590,7 +590,7 @@ void makePanelItem_Mobile(iWidget *panel, const iMenuItem *item) { | |||
590 | const char *radLabel = | 590 | const char *radLabel = |
591 | hasLabel_Command(radioItem->label, "label") | 591 | hasLabel_Command(radioItem->label, "label") |
592 | ? format_CStr("${%s}", | 592 | ? format_CStr("${%s}", |
593 | cstr_Rangecc(range_Command(radioItem->label, "label"))) | 593 | cstr_Command(radioItem->label, "label")) |
594 | : suffixPtr_Command(radioItem->label, "text"); | 594 | : suffixPtr_Command(radioItem->label, "text"); |
595 | button = new_LabelWidget(radLabel, radioItem->command); | 595 | button = new_LabelWidget(radLabel, radioItem->command); |
596 | flags |= radio_WidgetFlag; | 596 | flags |= radio_WidgetFlag; |
@@ -613,7 +613,7 @@ void makePanelItem_Mobile(iWidget *panel, const iMenuItem *item) { | |||
613 | else if (equal_Command(spec, "input")) { | 613 | else if (equal_Command(spec, "input")) { |
614 | iInputWidget *input = new_InputWidget(argU32Label_Command(spec, "maxlen")); | 614 | iInputWidget *input = new_InputWidget(argU32Label_Command(spec, "maxlen")); |
615 | if (hasLabel_Command(spec, "hint")) { | 615 | if (hasLabel_Command(spec, "hint")) { |
616 | setHint_InputWidget(input, cstr_Lang(cstr_Rangecc(range_Command(spec, "hint")))); | 616 | setHint_InputWidget(input, cstr_Lang(cstr_Command(spec, "hint"))); |
617 | } | 617 | } |
618 | setId_Widget(as_Widget(input), id); | 618 | setId_Widget(as_Widget(input), id); |
619 | setUrlContent_InputWidget(input, argLabel_Command(spec, "url")); | 619 | setUrlContent_InputWidget(input, argLabel_Command(spec, "url")); |
@@ -630,7 +630,7 @@ void makePanelItem_Mobile(iWidget *panel, const iMenuItem *item) { | |||
630 | iWidget *unit = addChildFlags_Widget( | 630 | iWidget *unit = addChildFlags_Widget( |
631 | as_Widget(input), | 631 | as_Widget(input), |
632 | iClob(new_LabelWidget( | 632 | iClob(new_LabelWidget( |
633 | format_CStr("${%s}", cstr_Rangecc(range_Command(spec, "unit"))), NULL)), | 633 | format_CStr("${%s}", cstr_Command(spec, "unit")), NULL)), |
634 | frameless_WidgetFlag | moveToParentRightEdge_WidgetFlag | | 634 | frameless_WidgetFlag | moveToParentRightEdge_WidgetFlag | |
635 | resizeToParentHeight_WidgetFlag); | 635 | resizeToParentHeight_WidgetFlag); |
636 | setContentPadding_InputWidget(input, -1, width_Widget(unit) - 4 * gap_UI); | 636 | setContentPadding_InputWidget(input, -1, width_Widget(unit) - 4 * gap_UI); |
@@ -800,7 +800,7 @@ void initPanels_Mobile(iWidget *panels, iWidget *parentWidget, | |||
800 | const iMenuItem *item = &itemsNullTerminated[i]; | 800 | const iMenuItem *item = &itemsNullTerminated[i]; |
801 | if (equal_Command(item->label, "panel")) { | 801 | if (equal_Command(item->label, "panel")) { |
802 | haveDetailPanels = iTrue; | 802 | haveDetailPanels = iTrue; |
803 | const char *id = cstr_Rangecc(range_Command(item->label, "id")); | 803 | const char *id = cstr_Command(item->label, "id"); |
804 | const iString *label = hasLabel_Command(item->label, "text") | 804 | const iString *label = hasLabel_Command(item->label, "text") |
805 | ? collect_String(suffix_Command(item->label, "text")) | 805 | ? collect_String(suffix_Command(item->label, "text")) |
806 | : collectNewFormat_String("${%s}", id); | 806 | : collectNewFormat_String("${%s}", id); |
diff --git a/src/ui/root.c b/src/ui/root.c index 04586bac..780dc6e7 100644 --- a/src/ui/root.c +++ b/src/ui/root.c | |||
@@ -441,7 +441,7 @@ static iBool handleRootCommands_(iWidget *root, const char *cmd) { | |||
441 | return iFalse; | 441 | return iFalse; |
442 | } | 442 | } |
443 | else if (equal_Command(cmd, "focus.set")) { | 443 | else if (equal_Command(cmd, "focus.set")) { |
444 | setFocus_Widget(findWidget_App(cstr_Rangecc(range_Command(cmd, "id")))); | 444 | setFocus_Widget(findWidget_App(cstr_Command(cmd, "id"))); |
445 | return iTrue; | 445 | return iTrue; |
446 | } | 446 | } |
447 | else if (equal_Command(cmd, "input.resized")) { | 447 | else if (equal_Command(cmd, "input.resized")) { |
diff --git a/src/ui/util.c b/src/ui/util.c index a46c7f80..58e49230 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -1392,7 +1392,7 @@ static iBool tabSwitcher_(iWidget *tabs, const char *cmd) { | |||
1392 | if (equal_Command(cmd, "tabs.switch")) { | 1392 | if (equal_Command(cmd, "tabs.switch")) { |
1393 | iWidget *target = pointerLabel_Command(cmd, "page"); | 1393 | iWidget *target = pointerLabel_Command(cmd, "page"); |
1394 | if (!target) { | 1394 | if (!target) { |
1395 | target = findChild_Widget(tabs, cstr_Rangecc(range_Command(cmd, "id"))); | 1395 | target = findChild_Widget(tabs, cstr_Command(cmd, "id")); |
1396 | } | 1396 | } |
1397 | if (!target) return iFalse; | 1397 | if (!target) return iFalse; |
1398 | unfocusFocusInsideTabPage_(currentTabPage_Widget(tabs)); | 1398 | unfocusFocusInsideTabPage_(currentTabPage_Widget(tabs)); |
@@ -1720,6 +1720,12 @@ iBool valueInputHandler_(iWidget *dlg, const char *cmd) { | |||
1720 | } | 1720 | } |
1721 | return iFalse; | 1721 | return iFalse; |
1722 | } | 1722 | } |
1723 | else if (equal_Command(cmd, "valueinput.set")) { | ||
1724 | iInputWidget *input = findChild_Widget(dlg, "input"); | ||
1725 | setTextCStr_InputWidget(input, suffixPtr_Command(cmd, "text")); | ||
1726 | validate_InputWidget(input); | ||
1727 | return iTrue; | ||
1728 | } | ||
1723 | else if (equal_Command(cmd, "valueinput.cancel")) { | 1729 | else if (equal_Command(cmd, "valueinput.cancel")) { |
1724 | postCommandf_App("valueinput.cancelled id:%s", cstr_String(id_Widget(dlg))); | 1730 | postCommandf_App("valueinput.cancelled id:%s", cstr_String(id_Widget(dlg))); |
1725 | setId_Widget(dlg, ""); /* no further commands to emit */ | 1731 | setId_Widget(dlg, ""); /* no further commands to emit */ |
@@ -3317,7 +3323,7 @@ static const iMenuItem languages[] = { | |||
3317 | static iBool translationHandler_(iWidget *dlg, const char *cmd) { | 3323 | static iBool translationHandler_(iWidget *dlg, const char *cmd) { |
3318 | iUnused(dlg); | 3324 | iUnused(dlg); |
3319 | if (equal_Command(cmd, "xlt.lang")) { | 3325 | if (equal_Command(cmd, "xlt.lang")) { |
3320 | const iMenuItem *langItem = &languages[languageIndex_CStr(cstr_Rangecc(range_Command(cmd, "id")))]; | 3326 | const iMenuItem *langItem = &languages[languageIndex_CStr(cstr_Command(cmd, "id"))]; |
3321 | iWidget *widget = pointer_Command(cmd); | 3327 | iWidget *widget = pointer_Command(cmd); |
3322 | iLabelWidget *drop; | 3328 | iLabelWidget *drop; |
3323 | if (flags_Widget(widget) & nativeMenu_WidgetFlag) { | 3329 | if (flags_Widget(widget) & nativeMenu_WidgetFlag) { |
@@ -3337,7 +3343,7 @@ const char *languageId_String(const iString *menuItemLabel) { | |||
3337 | iForIndices(i, languages) { | 3343 | iForIndices(i, languages) { |
3338 | if (!languages[i].label) break; | 3344 | if (!languages[i].label) break; |
3339 | if (!cmp_String(menuItemLabel, translateCStr_Lang(languages[i].label))) { | 3345 | if (!cmp_String(menuItemLabel, translateCStr_Lang(languages[i].label))) { |
3340 | return cstr_Rangecc(range_Command(languages[i].command, "id")); | 3346 | return cstr_Command(languages[i].command, "id"); |
3341 | } | 3347 | } |
3342 | } | 3348 | } |
3343 | return ""; | 3349 | return ""; |
diff --git a/src/ui/window.c b/src/ui/window.c index a4929f51..0e13a57f 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -552,6 +552,7 @@ void init_MainWindow(iMainWindow *d, iRect rect) { | |||
552 | d->splitMode = 0; | 552 | d->splitMode = 0; |
553 | d->pendingSplitMode = 0; | 553 | d->pendingSplitMode = 0; |
554 | d->pendingSplitUrl = new_String(); | 554 | d->pendingSplitUrl = new_String(); |
555 | d->pendingSplitOrigin = new_String(); | ||
555 | d->place.initialPos = rect.pos; | 556 | d->place.initialPos = rect.pos; |
556 | d->place.normalRect = rect; | 557 | d->place.normalRect = rect; |
557 | d->place.lastNotifiedSize = zero_I2(); | 558 | d->place.lastNotifiedSize = zero_I2(); |
@@ -634,6 +635,7 @@ void deinit_MainWindow(iMainWindow *d) { | |||
634 | if (theMainWindow_ == d) { | 635 | if (theMainWindow_ == d) { |
635 | theMainWindow_ = NULL; | 636 | theMainWindow_ = NULL; |
636 | } | 637 | } |
638 | delete_String(d->pendingSplitOrigin); | ||
637 | delete_String(d->pendingSplitUrl); | 639 | delete_String(d->pendingSplitUrl); |
638 | deinit_Window(&d->base); | 640 | deinit_Window(&d->base); |
639 | } | 641 | } |
@@ -1528,9 +1530,11 @@ void setSplitMode_MainWindow(iMainWindow *d, int splitFlags) { | |||
1528 | } | 1530 | } |
1529 | } | 1531 | } |
1530 | if (!isEmpty_String(d->pendingSplitUrl)) { | 1532 | if (!isEmpty_String(d->pendingSplitUrl)) { |
1531 | postCommandf_Root(w->roots[newRootIndex], "open url:%s", | 1533 | postCommandf_Root(w->roots[newRootIndex], "open origin:%s url:%s", |
1534 | cstr_String(d->pendingSplitOrigin), | ||
1532 | cstr_String(d->pendingSplitUrl)); | 1535 | cstr_String(d->pendingSplitUrl)); |
1533 | clear_String(d->pendingSplitUrl); | 1536 | clear_String(d->pendingSplitUrl); |
1537 | clear_String(d->pendingSplitOrigin); | ||
1534 | } | 1538 | } |
1535 | else if (~splitFlags & noEvents_WindowSplit) { | 1539 | else if (~splitFlags & noEvents_WindowSplit) { |
1536 | iWidget *docTabs0 = findChild_Widget(w->roots[newRootIndex ^ 1]->widget, "doctabs"); | 1540 | iWidget *docTabs0 = findChild_Widget(w->roots[newRootIndex ^ 1]->widget, "doctabs"); |
diff --git a/src/ui/window.h b/src/ui/window.h index 6c921f09..ae111f4c 100644 --- a/src/ui/window.h +++ b/src/ui/window.h | |||
@@ -114,6 +114,7 @@ struct Impl_MainWindow { | |||
114 | int splitMode; | 114 | int splitMode; |
115 | int pendingSplitMode; | 115 | int pendingSplitMode; |
116 | iString * pendingSplitUrl; /* URL to open in a newly opened split */ | 116 | iString * pendingSplitUrl; /* URL to open in a newly opened split */ |
117 | iString * pendingSplitOrigin; /* tab from where split was initiated, if any */ | ||
117 | SDL_Texture * appIcon; | 118 | SDL_Texture * appIcon; |
118 | int keyboardHeight; /* mobile software keyboards */ | 119 | int keyboardHeight; /* mobile software keyboards */ |
119 | }; | 120 | }; |