=> a5a59eb664cdfb5fe37fb7d8c82d11c7008cbac7
[1mdiff --git a/po/en.po b/po/en.po[m [1mindex 3fc5423d..481545cf 100644[m [1m--- a/po/en.po[m [1m+++ b/po/en.po[m [36m@@ -760,6 +760,10 @@[m [mmsgstr "Line break"[m msgid "dlg.input.send"[m msgstr "Send"[m [m [32m+[m[32m# Paste the line preceding the clicked link into the input prompt.[m [32m+[m[32mmsgid "menu.input.precedingline"[m [32m+[m[32mmsgstr "Paste Preceding Line"[m [32m+[m msgid "heading.save"[m msgstr "FILE SAVED"[m [m [1mdiff --git a/res/lang/cs.bin b/res/lang/cs.bin[m [1mindex 3a5b5820..97197051 100644[m Binary files a/res/lang/cs.bin and b/res/lang/cs.bin differ [1mdiff --git a/res/lang/de.bin b/res/lang/de.bin[m [1mindex 57a6c945..d2dceda6 100644[m Binary files a/res/lang/de.bin and b/res/lang/de.bin differ [1mdiff --git a/res/lang/en.bin b/res/lang/en.bin[m [1mindex 6c921d9b..28c11997 100644[m Binary files a/res/lang/en.bin and b/res/lang/en.bin differ [1mdiff --git a/res/lang/eo.bin b/res/lang/eo.bin[m [1mindex b0ad3a58..d148e2f0 100644[m Binary files a/res/lang/eo.bin and b/res/lang/eo.bin differ [1mdiff --git a/res/lang/es.bin b/res/lang/es.bin[m [1mindex 61a5b870..92037aea 100644[m Binary files a/res/lang/es.bin and b/res/lang/es.bin differ [1mdiff --git a/res/lang/es_MX.bin b/res/lang/es_MX.bin[m [1mindex 6658bbcb..7b7e1219 100644[m Binary files a/res/lang/es_MX.bin and b/res/lang/es_MX.bin differ [1mdiff --git a/res/lang/fi.bin b/res/lang/fi.bin[m [1mindex 287de822..243e9740 100644[m Binary files a/res/lang/fi.bin and b/res/lang/fi.bin differ [1mdiff --git a/res/lang/fr.bin b/res/lang/fr.bin[m [1mindex 495a1b30..507cbb4c 100644[m Binary files a/res/lang/fr.bin and b/res/lang/fr.bin differ [1mdiff --git a/res/lang/gl.bin b/res/lang/gl.bin[m [1mindex efafd3a1..447ed72d 100644[m Binary files a/res/lang/gl.bin and b/res/lang/gl.bin differ [1mdiff --git a/res/lang/hu.bin b/res/lang/hu.bin[m [1mindex e0095569..c2a085ec 100644[m Binary files a/res/lang/hu.bin and b/res/lang/hu.bin differ [1mdiff --git a/res/lang/ia.bin b/res/lang/ia.bin[m [1mindex fb4f482c..5305304c 100644[m Binary files a/res/lang/ia.bin and b/res/lang/ia.bin differ [1mdiff --git a/res/lang/ie.bin b/res/lang/ie.bin[m [1mindex d397cdea..69ac42d4 100644[m Binary files a/res/lang/ie.bin and b/res/lang/ie.bin differ [1mdiff --git a/res/lang/isv.bin b/res/lang/isv.bin[m [1mindex 012e624f..56ed525c 100644[m Binary files a/res/lang/isv.bin and b/res/lang/isv.bin differ [1mdiff --git a/res/lang/pl.bin b/res/lang/pl.bin[m [1mindex 60b5d77c..1ad99e5d 100644[m Binary files a/res/lang/pl.bin and b/res/lang/pl.bin differ [1mdiff --git a/res/lang/ru.bin b/res/lang/ru.bin[m [1mindex 8cda6497..03092acf 100644[m Binary files a/res/lang/ru.bin and b/res/lang/ru.bin differ [1mdiff --git a/res/lang/sk.bin b/res/lang/sk.bin[m [1mindex 9a5355d9..bf13f594 100644[m Binary files a/res/lang/sk.bin and b/res/lang/sk.bin differ [1mdiff --git a/res/lang/sr.bin b/res/lang/sr.bin[m [1mindex 7d5183e5..823818e2 100644[m Binary files a/res/lang/sr.bin and b/res/lang/sr.bin differ [1mdiff --git a/res/lang/tok.bin b/res/lang/tok.bin[m [1mindex e21e8201..50743783 100644[m Binary files a/res/lang/tok.bin and b/res/lang/tok.bin differ [1mdiff --git a/res/lang/tr.bin b/res/lang/tr.bin[m [1mindex 9dd4764e..543739cd 100644[m Binary files a/res/lang/tr.bin and b/res/lang/tr.bin differ [1mdiff --git a/res/lang/uk.bin b/res/lang/uk.bin[m [1mindex a48258b6..f866f86f 100644[m Binary files a/res/lang/uk.bin and b/res/lang/uk.bin differ [1mdiff --git a/res/lang/zh_Hans.bin b/res/lang/zh_Hans.bin[m [1mindex 1ad2db27..179d87db 100644[m Binary files a/res/lang/zh_Hans.bin and b/res/lang/zh_Hans.bin differ [1mdiff --git a/res/lang/zh_Hant.bin b/res/lang/zh_Hant.bin[m [1mindex f4263b3b..aad28410 100644[m Binary files a/res/lang/zh_Hant.bin and b/res/lang/zh_Hant.bin differ [1mdiff --git a/src/app.c b/src/app.c[m [1mindex e807f09d..accdd991 100644[m [1m--- a/src/app.c[m [1m+++ b/src/app.c[m [36m@@ -356,7 +356,7 @@[m [mstatic void loadPrefs_App_(iApp *d) {[m setUiScale_Window(get_Window(), argf_Command(cmd));[m }[m else if (equal_Command(cmd, "uilang")) {[m [31m- const char *id = cstr_Rangecc(range_Command(cmd, "id"));[m [32m+[m[32m const char *id = cstr_Command(cmd, "id");[m setCStr_String(&d->prefs.strings[uiLanguage_PrefsString], id);[m setCurrent_Lang(id);[m }[m [36m@@ -2190,6 +2190,7 @@[m [miBool handleCommand_App(const char *cmd) {[m return iTrue;[m }[m else if (equal_Command(cmd, "fontpack.suggest.classic")) {[m [32m+[m[32m /* TODO: Don't use this when system fonts are accessible. */[m if (!isInstalled_Fonts("classic-set") && !isInstalled_Fonts("cjk")) {[m makeQuestion_Widget([m uiHeading_ColorEscape "${heading.fontpack.classic}",[m [36m@@ -2243,6 +2244,9 @@[m [miBool handleCommand_App(const char *cmd) {[m (argLabel_Command(cmd, "axis") ? vertical_WindowSplit : 0) | (arg_Command(cmd) << 1);[m const char *url = suffixPtr_Command(cmd, "url");[m setCStr_String(d->window->pendingSplitUrl, url ? url : "");[m [32m+[m[32m if (hasLabel_Command(cmd, "origin")) {[m [32m+[m[32m set_String(d->window->pendingSplitOrigin, string_Command(cmd, "origin"));[m [32m+[m[32m }[m postRefresh_App();[m return iTrue;[m }[m [36m@@ -2732,12 +2736,21 @@[m [miBool handleCommand_App(const char *cmd) {[m openInDefaultBrowser_App(url);[m return iTrue;[m }[m [32m+[m[32m iDocumentWidget *doc = document_Command(cmd);[m [32m+[m[32m iDocumentWidget *origin = doc;[m [32m+[m[32m if (hasLabel_Command(cmd, "origin")) {[m [32m+[m[32m iDocumentWidget *cmdOrig = findWidget_App(cstr_Command(cmd, "origin"));[m [32m+[m[32m if (cmdOrig) {[m [32m+[m[32m origin = cmdOrig;[m [32m+[m[32m }[m [32m+[m[32m }[m const int newTab = argLabel_Command(cmd, "newtab");[m if (newTab & otherRoot_OpenTabFlag && numRoots_Window(get_Window()) == 1) {[m /* Need to split first. */[m const iInt2 winSize = get_Window()->size;[m [31m- postCommandf_App("ui.split arg:3 axis:%d newtab:%d url:%s",[m [32m+[m[32m postCommandf_App("ui.split arg:3 axis:%d origin:%s newtab:%d url:%s",[m (float) winSize.x / (float) winSize.y < 0.7f ? 1 : 0,[m [32m+[m[32m cstr_String(id_Widget(as_Widget(origin))),[m newTab & ~otherRoot_OpenTabFlag,[m cstr_String(url));[m return iTrue;[m [36m@@ -2749,7 +2762,6 @@[m [miBool handleCommand_App(const char *cmd) {[m setKeyRoot_Window(as_Window(d->window), root);[m setCurrent_Root(root); /* need to change for widget creation */[m }[m [31m- iDocumentWidget *doc = document_Command(cmd);[m if (newTab & (new_OpenTabFlag | newBackground_OpenTabFlag)) {[m doc = newTab_App(NULL, (newTab & new_OpenTabFlag) != 0); /* `newtab:2` to open in background */[m }[m [36m@@ -2766,13 +2778,14 @@[m [miBool handleCommand_App(const char *cmd) {[m }[m setInitialScroll_DocumentWidget(doc, argfLabel_Command(cmd, "scroll"));[m setRedirectCount_DocumentWidget(doc, redirectCount);[m [32m+[m[32m setOrigin_DocumentWidget(doc, origin);[m showCollapsed_Widget(findWidget_App("document.progress"), iFalse);[m if (prefs_App()->decodeUserVisibleURLs) {[m urlDecodePath_String(url);[m }[m else {[m urlEncodePath_String(url);[m [31m- }[m [32m+[m[32m }[m[41m [m setUrlFlags_DocumentWidget(doc, url,[m (isHistory ? useCachedContentIfAvailable_DocumentWidgetSetUrlFlag : 0) |[m (fromSidebar ? openedFromSidebar_DocumentWidgetSetUrlFlag : 0));[m [1mdiff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c[m [1mindex 384c51b5..50df05f5 100644[m [1m--- a/src/ui/documentwidget.c[m [1m+++ b/src/ui/documentwidget.c[m [36m@@ -264,6 +264,7 @@[m [mstruct Impl_DocumentWidget {[m int pinchZoomPosted;[m float swipeSpeed; /* points/sec */[m iString pendingGotoHeading;[m [32m+[m[32m iString linePrecedingLink;[m [m /* Network request: */[m enum iRequestState state;[m [36m@@ -391,6 +392,7 @@[m [mvoid init_DocumentWidget(iDocumentWidget *d) {[m d->grabbedPlayer = NULL;[m d->mediaTimer = 0;[m init_String(&d->pendingGotoHeading);[m [32m+[m[32m init_String(&d->linePrecedingLink);[m init_Click(&d->click, d, SDL_BUTTON_LEFT);[m addChild_Widget(w, iClob(d->scroll = new_ScrollWidget()));[m d->menu = NULL; /* created when clicking */[m [36m@@ -437,6 +439,7 @@[m [mvoid deinit_DocumentWidget(iDocumentWidget *d) {[m iRelease(d->media);[m iRelease(d->request);[m delete_Gempub(d->sourceGempub);[m [32m+[m[32m deinit_String(&d->linePrecedingLink);[m deinit_String(&d->pendingGotoHeading);[m deinit_Block(&d->sourceContent);[m deinit_String(&d->sourceMime);[m [36m@@ -1893,7 +1896,7 @@[m [mstatic void addBannerWarnings_DocumentWidget_(iDocumentWidget *d) {[m [m static void updateFromCachedResponse_DocumentWidget_(iDocumentWidget *d, float normScrollY,[m const iGmResponse *resp, iGmDocument *cachedDoc) {[m [31m- iAssert(width_Widget(d) > 0); /* must be laid out by now */[m [32m+[m[32m// iAssert(width_Widget(d) > 0); /* must be laid out by now */[m setLinkNumberMode_DocumentWidget_(d, iFalse);[m clear_ObjectList(d->media);[m delete_Gempub(d->sourceGempub);[m [36m@@ -1918,9 +1921,6 @@[m [mstatic void updateFromCachedResponse_DocumentWidget_(iDocumentWidget *d, float n[m setWidth_GmDocument(d->doc, documentWidth_DocumentWidget_(d), width_Widget(d));[m }[m updateDocument_DocumentWidget_(d, resp, cachedDoc, iTrue);[m [31m-// if (!cachedDoc) {[m [31m-// setCachedDocument_History(d->mod.history, d->doc, iFalse);[m [31m-// }[m clear_Banner(d->banner);[m updateBanner_DocumentWidget_(d);[m addBannerWarnings_DocumentWidget_(d);[m [36m@@ -2242,6 +2242,16 @@[m [mstatic void checkResponse_DocumentWidget_(iDocumentWidget *d) {[m if (lineBreak && deviceType_App() != desktop_AppDeviceType) {[m addChildPos_Widget(buttons, iClob(lineBreak), front_WidgetAddPos);[m }[m [32m+[m[32m /* Menu for additional actions, past entries. */ {[m [32m+[m[32m iMenuItem items[] = { { "${menu.input.precedingline}",[m [32m+[m[32m SDLK_v,[m [32m+[m[32m KMOD_PRIMARY | KMOD_SHIFT,[m [32m+[m[32m format_CStr("!valueinput.set ptr:%p text:%s",[m [32m+[m[32m buttons,[m [32m+[m[32m cstr_String(&d->linePrecedingLink)) } };[m [32m+[m[32m iLabelWidget *menu = makeMenuButton_LabelWidget(midEllipsis_Icon, items, 1);[m [32m+[m[32m addChildPos_Widget(buttons, iClob(menu), front_WidgetAddPos);[m [32m+[m[32m }[m[41m [m setValidator_InputWidget(findChild_Widget(dlg, "input"), inputQueryValidator_, d);[m setSensitiveContent_InputWidget(findChild_Widget(dlg, "input"),[m statusCode == sensitiveInput_GmStatusCode);[m [36m@@ -3836,6 +3846,30 @@[m [mstatic void beginMarkingSelection_DocumentWidget_(iDocumentWidget *d, iInt2 pos)[m refresh_Widget(as_Widget(d));[m }[m [m [32m+[m[32mstatic void linkWasTriggered_DocumentWidget_(iDocumentWidget *d, iGmLinkId id) {[m [32m+[m[32m iRangecc loc = linkUrlRange_GmDocument(d->doc, id);[m [32m+[m[32m if (!loc.start) {[m [32m+[m[32m clear_String(&d->linePrecedingLink);[m [32m+[m[32m return;[m [32m+[m[32m }[m [32m+[m[32m const char *start = range_String(source_GmDocument(d->doc)).start;[m [32m+[m[32m /* Find the preceding line. This is offered as a prefill option for a possible input query. */[m [32m+[m[32m while (loc.start > start && *loc.start != '\n') {[m [32m+[m[32m loc.start--;[m [32m+[m[32m }[m [32m+[m[32m loc.end = loc.start; /* End of the preceding line. */[m [32m+[m[32m if (loc.start > start) {[m [32m+[m[32m loc.start--;[m [32m+[m[32m }[m [32m+[m[32m while (loc.start > start && *loc.start != '\n') {[m [32m+[m[32m loc.start--;[m [32m+[m[32m }[m [32m+[m[32m if (*loc.start == '\n') {[m [32m+[m[32m loc.start++; /* Start of the preceding line. */[m [32m+[m[32m }[m [32m+[m[32m setRange_String(&d->linePrecedingLink, loc);[m [32m+[m[32m}[m [32m+[m static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *ev) {[m iWidget *w = as_Widget(d);[m if (isMetricsChange_UserEvent(ev)) {[m [36m@@ -3878,6 +3912,7 @@[m [mstatic iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e[m : (d->flags & newTabViaHomeKeys_DocumentWidgetFlag ? 1 : 0)),[m cstr_String(absoluteUrl_String([m d->mod.url, linkUrl_GmDocument(d->doc, run->linkId))));[m [32m+[m[32m linkWasTriggered_DocumentWidget_(d, run->linkId);[m }[m setLinkNumberMode_DocumentWidget_(d, iFalse);[m invalidateVisibleLinks_DocumentWidget_(d);[m [36m@@ -3995,6 +4030,7 @@[m [mstatic iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e[m return iTrue;[m }[m if (ev->button.button == SDL_BUTTON_MIDDLE && d->hoverLink) {[m [32m+[m[32m linkWasTriggered_DocumentWidget_(d, d->hoverLink->linkId);[m postCommandf_Root(w->root, "open newtab:%d url:%s",[m (isPinned_DocumentWidget_(d) ? otherRoot_OpenTabFlag : 0) |[m (modState_Keys() & KMOD_SHIFT ? new_OpenTabFlag : newBackground_OpenTabFlag),[m [36m@@ -4015,6 +4051,7 @@[m [mstatic iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e[m init_Array(&items, sizeof(iMenuItem));[m if (d->contextLink) {[m /* Context menu for a link. */[m [32m+[m[32m linkWasTriggered_DocumentWidget_(d, d->contextLink->linkId); /* perhaps will be triggered */[m const iString *linkUrl = linkUrl_GmDocument(d->doc, d->contextLink->linkId);[m // const int linkFlags = linkFlags_GmDocument(d->doc, d->contextLink->linkId);[m const iRangecc scheme = urlScheme_String(linkUrl);[m [36m@@ -4034,23 +4071,30 @@[m [mstatic iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e[m /* Regular links that we can open. */[m pushBackN_Array([m &items,[m [31m- (iMenuItem[]){[m [31m- { openTab_Icon " ${link.newtab}",[m [31m- 0,[m [31m- 0,[m [31m- format_CStr("!open newtab:1 url:%s", cstr_String(linkUrl)) },[m [31m- { openTabBg_Icon " ${link.newtab.background}",[m [31m- 0,[m [31m- 0,[m [31m- format_CStr("!open newtab:2 url:%s", cstr_String(linkUrl)) },[m [31m- { "${link.side}",[m [31m- 0,[m [31m- 0,[m [31m- format_CStr("!open newtab:4 url:%s", cstr_String(linkUrl)) },[m [31m- { "${link.side.newtab}",[m [31m- 0,[m [31m- 0,[m [31m- format_CStr("!open newtab:5 url:%s", cstr_String(linkUrl)) } },[m [32m+[m[32m (iMenuItem[]){ { openTab_Icon " ${link.newtab}",[m [32m+[m[32m 0,[m [32m+[m[32m 0,[m [32m+[m[32m format_CStr("!open newtab:1 origin:%s url:%s",[m [32m+[m[32m cstr_String(id_Widget(w)),[m [32m+[m[32m cstr_String(linkUrl)) },[m [32m+[m[32m { openTabBg_Icon " ${link.newtab.background}",[m [32m+[m[32m 0,[m [32m+[m[32m 0,[m [32m+[m[32m format_CStr("!open newtab:2 origin:%s url:%s",[m [32m+[m[32m cstr_String(id_Widget(w)),[m [32m+[m[32m cstr_String(linkUrl)) },[m [32m+[m[32m { "${link.side}",[m [32m+[m[32m 0,[m [32m+[m[32m 0,[m [32m+[m[32m format_CStr("!open newtab:4 origin:%s url:%s",[m [32m+[m[32m cstr_String(id_Widget(w)),[m [32m+[m[32m cstr_String(linkUrl)) },[m [32m+[m[32m { "${link.side.newtab}",[m [32m+[m[32m 0,[m [32m+[m[32m 0,[m [32m+[m[32m format_CStr("!open newtab:5 origin:%s url:%s",[m [32m+[m[32m cstr_String(id_Widget(w)),[m [32m+[m[32m cstr_String(linkUrl)) } },[m 4);[m if (deviceType_App() == phone_AppDeviceType) {[m removeN_Array(&items, size_Array(&items) - 2, iInvalidSize);[m [36m@@ -4072,7 +4116,9 @@[m [mstatic iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e[m { isGemini ? "${link.noproxy}" : openExt_Icon " ${link.browser}",[m 0,[m 0,[m [31m- format_CStr("!open noproxy:1 url:%s", cstr_String(linkUrl)) } },[m [32m+[m[32m format_CStr("!open origin:%s noproxy:1 url:%s",[m [32m+[m[32m cstr_String(id_Widget(w)),[m [32m+[m[32m cstr_String(linkUrl)) } },[m 2);[m }[m iString *linkLabel = collectNewRange_String([m [36m@@ -4414,6 +4460,7 @@[m [mstatic iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e[m if (isPinned_DocumentWidget_(d)) {[m tabMode ^= otherRoot_OpenTabFlag;[m }[m [32m+[m[32m linkWasTriggered_DocumentWidget_(d, linkId);[m postCommandf_Root(w->root, "open newtab:%d url:%s",[m tabMode,[m cstr_String(absoluteUrl_String([m [36m@@ -5495,6 +5542,13 @@[m [miDocumentWidget *duplicate_DocumentWidget(const iDocumentWidget *orig) {[m return d;[m }[m [m [32m+[m[32mvoid setOrigin_DocumentWidget(iDocumentWidget *d, const iDocumentWidget *other) {[m [32m+[m[32m if (d != other) {[m [32m+[m[32m /* TODO: Could remember the other's ID? */[m [32m+[m[32m set_String(&d->linePrecedingLink, &other->linePrecedingLink);[m [32m+[m[32m }[m [32m+[m[32m}[m [32m+[m void setUrl_DocumentWidget(iDocumentWidget *d, const iString *url) {[m setUrlFlags_DocumentWidget(d, url, 0);[m }[m [1mdiff --git a/src/ui/documentwidget.h b/src/ui/documentwidget.h[m [1mindex c97fa0ba..1405f19d 100644[m [1m--- a/src/ui/documentwidget.h[m [1m+++ b/src/ui/documentwidget.h[m [36m@@ -53,6 +53,7 @@[m [menum iDocumentWidgetSetUrlFlags {[m openedFromSidebar_DocumentWidgetSetUrlFlag = iBit(2),[m };[m [m [32m+[m[32mvoid setOrigin_DocumentWidget (iDocumentWidget *, const iDocumentWidget *other);[m void setUrl_DocumentWidget (iDocumentWidget *, const iString *url);[m void setUrlFlags_DocumentWidget (iDocumentWidget *, const iString *url, int setUrlFlags);[m void setUrlAndSource_DocumentWidget (iDocumentWidget *, const iString *url, const iString *mime, const iBlock *source);[m [1mdiff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c[m [1mindex b910f905..b94e0c27 100644[m [1m--- a/src/ui/inputwidget.c[m [1m+++ b/src/ui/inputwidget.c[m [36m@@ -1163,6 +1163,12 @@[m [mvoid selectAll_InputWidget(iInputWidget *d) {[m #endif[m }[m [m [32m+[m[32mvoid validate_InputWidget(iInputWidget *d) {[m [32m+[m[32m if (d->validator) {[m [32m+[m[32m d->validator(d, d->validatorContext); /* this may change the contents */[m [32m+[m[32m }[m[41m [m [32m+[m[32m}[m [32m+[m iLocalDef iBool isEditing_InputWidget_(const iInputWidget *d) {[m return (flags_Widget(constAs_Widget(d)) & selected_WidgetFlag) != 0;[m }[m [36m@@ -1653,9 +1659,7 @@[m [mvoid setEatEscape_InputWidget(iInputWidget *d, iBool eatEscape) {[m }[m [m static void contentsWereChanged_InputWidget_(iInputWidget *d) {[m [31m- if (d->validator) {[m [31m- d->validator(d, d->validatorContext); /* this may change the contents */[m [31m- }[m [32m+[m[32m validate_InputWidget(d);[m if (d->inFlags & notifyEdits_InputWidgetFlag) {[m postCommand_Widget(d, "input.edited id:%s", cstr_String(id_Widget(constAs_Widget(d))));[m }[m [1mdiff --git a/src/ui/inputwidget.h b/src/ui/inputwidget.h[m [1mindex f70c81af..5a61ec22 100644[m [1m--- a/src/ui/inputwidget.h[m [1m+++ b/src/ui/inputwidget.h[m [36m@@ -57,6 +57,7 @@[m [mvoid setBackupFileName_InputWidget (iInputWidget *, const char *fileName);[m void begin_InputWidget (iInputWidget *);[m void end_InputWidget (iInputWidget *, iBool accept);[m void selectAll_InputWidget (iInputWidget *);[m [32m+[m[32mvoid validate_InputWidget (iInputWidget *);[m [m void setSelectAllOnFocus_InputWidget (iInputWidget *, iBool selectAllOnFocus);[m void setSensitiveContent_InputWidget (iInputWidget *, iBool isSensitive);[m [1mdiff --git a/src/ui/mobile.c b/src/ui/mobile.c[m [1mindex bf3eb425..df2a661a 100644[m [1m--- a/src/ui/mobile.c[m [1m+++ b/src/ui/mobile.c[m [36m@@ -499,7 +499,7 @@[m [mvoid makePanelItem_Mobile(iWidget *panel, const iMenuItem *item) {[m iLabelWidget *heading = NULL;[m iWidget * value = NULL;[m const char * spec = item->label;[m [31m- const char * id = cstr_Rangecc(range_Command(spec, "id"));[m [32m+[m[32m const char * id = cstr_Command(spec, "id");[m const char * label = hasLabel_Command(spec, "text")[m ? suffixPtr_Command(spec, "text")[m : format_CStr("${%s}", id);[m [36m@@ -580,7 +580,7 @@[m [mvoid makePanelItem_Mobile(iWidget *panel, const iMenuItem *item) {[m addChildFlags_Widget(widget, iClob(sep), 0);[m }[m isFirst = iFalse;[m [31m- const char * radId = cstr_Rangecc(range_Command(radioItem->label, "id"));[m [32m+[m[32m const char * radId = cstr_Command(radioItem->label, "id");[m int64_t flags = noBackground_WidgetFlag | frameless_WidgetFlag;[m if (!isHorizontal) {[m flags |= alignLeft_WidgetFlag;[m [36m@@ -590,7 +590,7 @@[m [mvoid makePanelItem_Mobile(iWidget *panel, const iMenuItem *item) {[m const char *radLabel =[m hasLabel_Command(radioItem->label, "label")[m ? format_CStr("${%s}",[m [31m- cstr_Rangecc(range_Command(radioItem->label, "label")))[m [32m+[m[32m cstr_Command(radioItem->label, "label"))[m : suffixPtr_Command(radioItem->label, "text");[m button = new_LabelWidget(radLabel, radioItem->command);[m flags |= radio_WidgetFlag;[m [36m@@ -613,7 +613,7 @@[m [mvoid makePanelItem_Mobile(iWidget *panel, const iMenuItem *item) {[m else if (equal_Command(spec, "input")) {[m iInputWidget *input = new_InputWidget(argU32Label_Command(spec, "maxlen"));[m if (hasLabel_Command(spec, "hint")) {[m [31m- setHint_InputWidget(input, cstr_Lang(cstr_Rangecc(range_Command(spec, "hint"))));[m [32m+[m[32m setHint_InputWidget(input, cstr_Lang(cstr_Command(spec, "hint")));[m }[m setId_Widget(as_Widget(input), id);[m setUrlContent_InputWidget(input, argLabel_Command(spec, "url"));[m [36m@@ -630,7 +630,7 @@[m [mvoid makePanelItem_Mobile(iWidget *panel, const iMenuItem *item) {[m iWidget *unit = addChildFlags_Widget([m as_Widget(input),[m iClob(new_LabelWidget([m [31m- format_CStr("${%s}", cstr_Rangecc(range_Command(spec, "unit"))), NULL)),[m [32m+[m[32m format_CStr("${%s}", cstr_Command(spec, "unit")), NULL)),[m frameless_WidgetFlag | moveToParentRightEdge_WidgetFlag |[m resizeToParentHeight_WidgetFlag);[m setContentPadding_InputWidget(input, -1, width_Widget(unit) - 4 * gap_UI);[m [36m@@ -800,7 +800,7 @@[m [mvoid initPanels_Mobile(iWidget *panels, iWidget *parentWidget,[m const iMenuItem *item = &itemsNullTerminated[i];[m if (equal_Command(item->label, "panel")) {[m haveDetailPanels = iTrue;[m [31m- const char *id = cstr_Rangecc(range_Command(item->label, "id"));[m [32m+[m[32m const char *id = cstr_Command(item->label, "id");[m const iString *label = hasLabel_Command(item->label, "text")[m ? collect_String(suffix_Command(item->label, "text"))[m : collectNewFormat_String("${%s}", id);[m [1mdiff --git a/src/ui/root.c b/src/ui/root.c[m [1mindex 04586bac..780dc6e7 100644[m [1m--- a/src/ui/root.c[m [1m+++ b/src/ui/root.c[m [36m@@ -441,7 +441,7 @@[m [mstatic iBool handleRootCommands_(iWidget *root, const char *cmd) {[m return iFalse;[m }[m else if (equal_Command(cmd, "focus.set")) {[m [31m- setFocus_Widget(findWidget_App(cstr_Rangecc(range_Command(cmd, "id"))));[m [32m+[m[32m setFocus_Widget(findWidget_App(cstr_Command(cmd, "id")));[m return iTrue;[m }[m else if (equal_Command(cmd, "input.resized")) {[m [1mdiff --git a/src/ui/util.c b/src/ui/util.c[m [1mindex a46c7f80..58e49230 100644[m [1m--- a/src/ui/util.c[m [1m+++ b/src/ui/util.c[m [36m@@ -1392,7 +1392,7 @@[m [mstatic iBool tabSwitcher_(iWidget *tabs, const char *cmd) {[m if (equal_Command(cmd, "tabs.switch")) {[m iWidget *target = pointerLabel_Command(cmd, "page");[m if (!target) {[m [31m- target = findChild_Widget(tabs, cstr_Rangecc(range_Command(cmd, "id")));[m [32m+[m[32m target = findChild_Widget(tabs, cstr_Command(cmd, "id"));[m }[m if (!target) return iFalse;[m unfocusFocusInsideTabPage_(currentTabPage_Widget(tabs));[m [36m@@ -1720,6 +1720,12 @@[m [miBool valueInputHandler_(iWidget *dlg, const char *cmd) {[m }[m return iFalse;[m }[m [32m+[m[32m else if (equal_Command(cmd, "valueinput.set")) {[m [32m+[m[32m iInputWidget *input = findChild_Widget(dlg, "input");[m [32m+[m[32m setTextCStr_InputWidget(input, suffixPtr_Command(cmd, "text"));[m [32m+[m[32m validate_InputWidget(input);[m [32m+[m[32m return iTrue;[m [32m+[m[32m }[m else if (equal_Command(cmd, "valueinput.cancel")) {[m postCommandf_App("valueinput.cancelled id:%s", cstr_String(id_Widget(dlg)));[m setId_Widget(dlg, ""); /* no further commands to emit */[m [36m@@ -3317,7 +3323,7 @@[m [mstatic const iMenuItem languages[] = {[m static iBool translationHandler_(iWidget *dlg, const char *cmd) {[m iUnused(dlg);[m if (equal_Command(cmd, "xlt.lang")) {[m [31m- const iMenuItem *langItem = &languages[languageIndex_CStr(cstr_Rangecc(range_Command(cmd, "id")))];[m [32m+[m[32m const iMenuItem *langItem = &languages[languageIndex_CStr(cstr_Command(cmd, "id"))];[m iWidget *widget = pointer_Command(cmd);[m iLabelWidget *drop;[m if (flags_Widget(widget) & nativeMenu_WidgetFlag) {[m [36m@@ -3337,7 +3343,7 @@[m [mconst char *languageId_String(const iString *menuItemLabel) {[m iForIndices(i, languages) {[m if (!languages[i].label) break;[m if (!cmp_String(menuItemLabel, translateCStr_Lang(languages[i].label))) {[m [31m- return cstr_Rangecc(range_Command(languages[i].command, "id"));[m [32m+[m[32m return cstr_Command(languages[i].command, "id");[m }[m }[m return "";[m [1mdiff --git a/src/ui/window.c b/src/ui/window.c[m [1mindex a4929f51..0e13a57f 100644[m [1m--- a/src/ui/window.c[m [1m+++ b/src/ui/window.c[m [36m@@ -552,6 +552,7 @@[m [mvoid init_MainWindow(iMainWindow *d, iRect rect) {[m d->splitMode = 0;[m d->pendingSplitMode = 0;[m d->pendingSplitUrl = new_String();[m [32m+[m[32m d->pendingSplitOrigin = new_String();[m d->place.initialPos = rect.pos;[m d->place.normalRect = rect;[m d->place.lastNotifiedSize = zero_I2();[m [36m@@ -634,6 +635,7 @@[m [mvoid deinit_MainWindow(iMainWindow *d) {[m if (theMainWindow_ == d) {[m theMainWindow_ = NULL;[m }[m [32m+[m[32m delete_String(d->pendingSplitOrigin);[m delete_String(d->pendingSplitUrl);[m deinit_Window(&d->base);[m }[m [36m@@ -1528,9 +1530,11 @@[m [mvoid setSplitMode_MainWindow(iMainWindow *d, int splitFlags) {[m }[m }[m if (!isEmpty_String(d->pendingSplitUrl)) {[m [31m- postCommandf_Root(w->roots[newRootIndex], "open url:%s",[m [32m+[m[32m postCommandf_Root(w->roots[newRootIndex], "open origin:%s url:%s",[m [32m+[m[32m cstr_String(d->pendingSplitOrigin),[m cstr_String(d->pendingSplitUrl));[m clear_String(d->pendingSplitUrl);[m [32m+[m[32m clear_String(d->pendingSplitOrigin);[m }[m else if (~splitFlags & noEvents_WindowSplit) {[m iWidget *docTabs0 = findChild_Widget(w->roots[newRootIndex ^ 1]->widget, "doctabs");[m [1mdiff --git a/src/ui/window.h b/src/ui/window.h[m [1mindex 6c921f09..ae111f4c 100644[m [1m--- a/src/ui/window.h[m [1m+++ b/src/ui/window.h[m [36m@@ -114,6 +114,7 @@[m [mstruct Impl_MainWindow {[m int splitMode;[m int pendingSplitMode;[m iString * pendingSplitUrl; /* URL to open in a newly opened split */[m [32m+[m[32m iString * pendingSplitOrigin; /* tab from where split was initiated, if any */[m SDL_Texture * appIcon;[m int keyboardHeight; /* mobile software keyboards */ [m };[m
text/gemini; charset=utf-8
This content has been proxied by September (3851b).