summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--po/en.po12
-rw-r--r--res/lang/de.binbin19904 -> 20024 bytes
-rw-r--r--res/lang/en.binbin18392 -> 18512 bytes
-rw-r--r--res/lang/es.binbin20482 -> 20602 bytes
-rw-r--r--res/lang/fi.binbin20186 -> 20306 bytes
-rw-r--r--res/lang/fr.binbin20968 -> 21088 bytes
-rw-r--r--res/lang/ia.binbin20376 -> 20496 bytes
-rw-r--r--res/lang/ie.binbin19606 -> 19726 bytes
-rw-r--r--res/lang/ru.binbin30118 -> 30238 bytes
-rw-r--r--res/lang/sr.binbin28583 -> 28703 bytes
-rw-r--r--res/lang/tok.binbin18882 -> 19002 bytes
-rw-r--r--res/lang/zh_Hans.binbin17782 -> 17902 bytes
-rw-r--r--res/lang/zh_Hant.binbin17856 -> 17976 bytes
-rw-r--r--src/app.c21
-rw-r--r--src/bookmarks.c10
-rw-r--r--src/bookmarks.h8
-rw-r--r--src/feeds.c2
-rw-r--r--src/prefs.c1
-rw-r--r--src/prefs.h1
-rw-r--r--src/ui/documentwidget.c44
-rw-r--r--src/ui/sidebarwidget.c30
-rw-r--r--src/ui/util.c25
-rw-r--r--src/ui/window.c23
23 files changed, 132 insertions, 45 deletions
diff --git a/po/en.po b/po/en.po
index e51b434c..e01d303b 100644
--- a/po/en.po
+++ b/po/en.po
@@ -1066,6 +1066,18 @@ msgstr "Collapse preformatted:"
1066msgid "prefs.archive.openindex" 1066msgid "prefs.archive.openindex"
1067msgstr "Open archive indices:" 1067msgstr "Open archive indices:"
1068 1068
1069msgid "prefs.pinsplit"
1070msgstr "Split view pinning:"
1071
1072msgid "prefs.pinsplit.none"
1073msgstr "None"
1074
1075msgid "prefs.pinsplit.left"
1076msgstr "Left Tab"
1077
1078msgid "prefs.pinsplit.right"
1079msgstr "Right Tab"
1080
1069msgid "prefs.smoothscroll" 1081msgid "prefs.smoothscroll"
1070msgstr "Smooth scrolling:" 1082msgstr "Smooth scrolling:"
1071 1083
diff --git a/res/lang/de.bin b/res/lang/de.bin
index 9ca2be68..846dc8e1 100644
--- a/res/lang/de.bin
+++ b/res/lang/de.bin
Binary files differ
diff --git a/res/lang/en.bin b/res/lang/en.bin
index 1a18bc38..64e150d5 100644
--- a/res/lang/en.bin
+++ b/res/lang/en.bin
Binary files differ
diff --git a/res/lang/es.bin b/res/lang/es.bin
index b37813d1..8fdd3d8b 100644
--- a/res/lang/es.bin
+++ b/res/lang/es.bin
Binary files differ
diff --git a/res/lang/fi.bin b/res/lang/fi.bin
index 4e2bee52..7ab951b4 100644
--- a/res/lang/fi.bin
+++ b/res/lang/fi.bin
Binary files differ
diff --git a/res/lang/fr.bin b/res/lang/fr.bin
index 8cfb9331..01cc217d 100644
--- a/res/lang/fr.bin
+++ b/res/lang/fr.bin
Binary files differ
diff --git a/res/lang/ia.bin b/res/lang/ia.bin
index 5310ac72..eb3e44a8 100644
--- a/res/lang/ia.bin
+++ b/res/lang/ia.bin
Binary files differ
diff --git a/res/lang/ie.bin b/res/lang/ie.bin
index 151cdf7d..62d74fa7 100644
--- a/res/lang/ie.bin
+++ b/res/lang/ie.bin
Binary files differ
diff --git a/res/lang/ru.bin b/res/lang/ru.bin
index 95ebe75d..1e8a4a90 100644
--- a/res/lang/ru.bin
+++ b/res/lang/ru.bin
Binary files differ
diff --git a/res/lang/sr.bin b/res/lang/sr.bin
index 0f254c81..08682c88 100644
--- a/res/lang/sr.bin
+++ b/res/lang/sr.bin
Binary files differ
diff --git a/res/lang/tok.bin b/res/lang/tok.bin
index d6b0aba7..5061520c 100644
--- a/res/lang/tok.bin
+++ b/res/lang/tok.bin
Binary files differ
diff --git a/res/lang/zh_Hans.bin b/res/lang/zh_Hans.bin
index 249d88d5..cee2f096 100644
--- a/res/lang/zh_Hans.bin
+++ b/res/lang/zh_Hans.bin
Binary files differ
diff --git a/res/lang/zh_Hant.bin b/res/lang/zh_Hant.bin
index 99e29957..67240240 100644
--- a/res/lang/zh_Hant.bin
+++ b/res/lang/zh_Hant.bin
Binary files differ
diff --git a/src/app.c b/src/app.c
index 4872799b..39f0346e 100644
--- a/src/app.c
+++ b/src/app.c
@@ -1446,6 +1446,14 @@ static void updatePrefsThemeButtons_(iWidget *d) {
1446 } 1446 }
1447} 1447}
1448 1448
1449static void updatePrefsPinSplitButtons_(iWidget *d, int value) {
1450 for (size_t i = 0; i < 3; i++) {
1451 setFlags_Widget(findChild_Widget(d, format_CStr("prefs.pinsplit.%u", i)),
1452 selected_WidgetFlag,
1453 i == value);
1454 }
1455}
1456
1449static void updateDropdownSelection_(iLabelWidget *dropButton, const char *selectedCommand) { 1457static void updateDropdownSelection_(iLabelWidget *dropButton, const char *selectedCommand) {
1450 iWidget *menu = findChild_Widget(as_Widget(dropButton), "menu"); 1458 iWidget *menu = findChild_Widget(as_Widget(dropButton), "menu");
1451 iForEach(ObjectList, i, children_Widget(menu)) { 1459 iForEach(ObjectList, i, children_Widget(menu)) {
@@ -1526,6 +1534,10 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) {
1526 setFlags_Widget(findChild_Widget(d, "prefs.quoteicon.1"), selected_WidgetFlag, arg == 1); 1534 setFlags_Widget(findChild_Widget(d, "prefs.quoteicon.1"), selected_WidgetFlag, arg == 1);
1527 return iFalse; 1535 return iFalse;
1528 } 1536 }
1537 else if (equal_Command(cmd, "pinsplit.set")) {
1538 updatePrefsPinSplitButtons_(d, arg_Command(cmd));
1539 return iFalse;
1540 }
1529 else if (equal_Command(cmd, "doctheme.dark.set")) { 1541 else if (equal_Command(cmd, "doctheme.dark.set")) {
1530 updateColorThemeButton_(findChild_Widget(d, "prefs.doctheme.dark"), arg_Command(cmd)); 1542 updateColorThemeButton_(findChild_Widget(d, "prefs.doctheme.dark"), arg_Command(cmd));
1531 return iFalse; 1543 return iFalse;
@@ -1824,6 +1836,10 @@ iBool handleCommand_App(const char *cmd) {
1824 } 1836 }
1825 return iTrue; 1837 return iTrue;
1826 } 1838 }
1839 else if (equal_Command(cmd, "pinsplit.set")) {
1840 d->prefs.pinSplit = arg_Command(cmd);
1841 return iTrue;
1842 }
1827 else if (equal_Command(cmd, "theme.set")) { 1843 else if (equal_Command(cmd, "theme.set")) {
1828 const int isAuto = argLabel_Command(cmd, "auto"); 1844 const int isAuto = argLabel_Command(cmd, "auto");
1829 d->prefs.theme = arg_Command(cmd); 1845 d->prefs.theme = arg_Command(cmd);
@@ -2030,6 +2046,7 @@ iBool handleCommand_App(const char *cmd) {
2030 iRoot *oldRoot = root; 2046 iRoot *oldRoot = root;
2031 if (newTab & otherRoot_OpenTabFlag) { 2047 if (newTab & otherRoot_OpenTabFlag) {
2032 root = otherRoot_Window(d->window, root); 2048 root = otherRoot_Window(d->window, root);
2049 setKeyRoot_Window(d->window, root);
2033 setCurrent_Root(root); /* need to change for widget creation */ 2050 setCurrent_Root(root); /* need to change for widget creation */
2034 } 2051 }
2035 iDocumentWidget *doc = document_Command(cmd); 2052 iDocumentWidget *doc = document_Command(cmd);
@@ -2172,6 +2189,7 @@ iBool handleCommand_App(const char *cmd) {
2172 setToggle_Widget(findChild_Widget(dlg, "prefs.archive.openindex"), d->prefs.openArchiveIndexPages); 2189 setToggle_Widget(findChild_Widget(dlg, "prefs.archive.openindex"), d->prefs.openArchiveIndexPages);
2173 setToggle_Widget(findChild_Widget(dlg, "prefs.ostheme"), d->prefs.useSystemTheme); 2190 setToggle_Widget(findChild_Widget(dlg, "prefs.ostheme"), d->prefs.useSystemTheme);
2174 setToggle_Widget(findChild_Widget(dlg, "prefs.customframe"), d->prefs.customFrame); 2191 setToggle_Widget(findChild_Widget(dlg, "prefs.customframe"), d->prefs.customFrame);
2192 updatePrefsPinSplitButtons_(dlg, d->prefs.pinSplit);
2175 updateDropdownSelection_(findChild_Widget(dlg, "prefs.uilang"), cstr_String(&d->prefs.uiLanguage)); 2193 updateDropdownSelection_(findChild_Widget(dlg, "prefs.uilang"), cstr_String(&d->prefs.uiLanguage));
2176 setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->prefs.retainWindowSize); 2194 setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->prefs.retainWindowSize);
2177 setText_InputWidget(findChild_Widget(dlg, "prefs.uiscale"), 2195 setText_InputWidget(findChild_Widget(dlg, "prefs.uiscale"),
@@ -2234,7 +2252,8 @@ iBool handleCommand_App(const char *cmd) {
2234 } 2252 }
2235 else if (equal_Command(cmd, "navigate.home")) { 2253 else if (equal_Command(cmd, "navigate.home")) {
2236 /* Look for bookmarks tagged "homepage". */ 2254 /* Look for bookmarks tagged "homepage". */
2237 iRegExp *pattern = iClob(new_RegExp("\\bhomepage\\b", caseInsensitive_RegExpOption)); 2255 iRegExp *pattern = iClob(new_RegExp("\\b" homepage_BookmarkTag "\\b",
2256 caseInsensitive_RegExpOption));
2238 const iPtrArray *homepages = 2257 const iPtrArray *homepages =
2239 list_Bookmarks(d->bookmarks, NULL, filterTagsRegExp_Bookmarks, pattern); 2258 list_Bookmarks(d->bookmarks, NULL, filterTagsRegExp_Bookmarks, pattern);
2240 if (isEmpty_PtrArray(homepages)) { 2259 if (isEmpty_PtrArray(homepages)) {
diff --git a/src/bookmarks.c b/src/bookmarks.c
index 5fff9c75..1f887c98 100644
--- a/src/bookmarks.c
+++ b/src/bookmarks.c
@@ -219,7 +219,7 @@ iBool remove_Bookmarks(iBookmarks *d, uint32_t id) {
219 if (bm) { 219 if (bm) {
220 /* If this is a remote source, make sure all the remote bookmarks are 220 /* If this is a remote source, make sure all the remote bookmarks are
221 removed as well. */ 221 removed as well. */
222 if (hasTag_Bookmark(bm, "remotesource")) { 222 if (hasTag_Bookmark(bm, remoteSource_BookmarkTag)) {
223 iForEach(Hash, i, &d->bookmarks) { 223 iForEach(Hash, i, &d->bookmarks) {
224 iBookmark *j = (iBookmark *) i.value; 224 iBookmark *j = (iBookmark *) i.value;
225 if (j->sourceId == id_Bookmark(bm)) { 225 if (j->sourceId == id_Bookmark(bm)) {
@@ -240,7 +240,7 @@ iBool updateBookmarkIcon_Bookmarks(iBookmarks *d, const iString *url, iChar icon
240 const uint32_t id = findUrl_Bookmarks(d, url); 240 const uint32_t id = findUrl_Bookmarks(d, url);
241 if (id) { 241 if (id) {
242 iBookmark *bm = get_Bookmarks(d, id); 242 iBookmark *bm = get_Bookmarks(d, id);
243 if (!hasTag_Bookmark(bm, "remote") && !hasTag_Bookmark(bm, "usericon")) { 243 if (!hasTag_Bookmark(bm, remote_BookmarkTag) && !hasTag_Bookmark(bm, userIcon_BookmarkTag)) {
244 if (icon != bm->icon) { 244 if (icon != bm->icon) {
245 bm->icon = icon; 245 bm->icon = icon;
246 changed = iTrue; 246 changed = iTrue;
@@ -257,7 +257,7 @@ iChar siteIcon_Bookmarks(const iBookmarks *d, const iString *url) {
257 } 257 }
258 static iRegExp *tagPattern_; 258 static iRegExp *tagPattern_;
259 if (!tagPattern_) { 259 if (!tagPattern_) {
260 tagPattern_ = new_RegExp("\\busericon\\b", caseSensitive_RegExpOption); 260 tagPattern_ = new_RegExp("\\b" userIcon_BookmarkTag "\\b", caseSensitive_RegExpOption);
261 } 261 }
262 const iRangecc urlRoot = urlRoot_String(url); 262 const iRangecc urlRoot = urlRoot_String(url);
263 size_t matchingSize = iInvalidSize; /* we'll pick the shortest matching */ 263 size_t matchingSize = iInvalidSize; /* we'll pick the shortest matching */
@@ -412,7 +412,7 @@ const iString *bookmarkListPage_Bookmarks(const iBookmarks *d, enum iBookmarkLis
412 412
413static iBool isRemoteSource_Bookmark_(void *context, const iBookmark *d) { 413static iBool isRemoteSource_Bookmark_(void *context, const iBookmark *d) {
414 iUnused(context); 414 iUnused(context);
415 return hasTag_Bookmark(d, "remotesource"); 415 return hasTag_Bookmark(d, remoteSource_BookmarkTag);
416} 416}
417 417
418void remoteRequestFinished_Bookmarks_(iBookmarks *d, iGmRequest *req) { 418void remoteRequestFinished_Bookmarks_(iBookmarks *d, iGmRequest *req) {
@@ -484,7 +484,7 @@ void fetchRemote_Bookmarks(iBookmarks *d) {
484 size_t numRemoved = 0; 484 size_t numRemoved = 0;
485 iForEach(Hash, i, &d->bookmarks) { 485 iForEach(Hash, i, &d->bookmarks) {
486 iBookmark *bm = (iBookmark *) i.value; 486 iBookmark *bm = (iBookmark *) i.value;
487 if (hasTag_Bookmark(bm, "remote")) { 487 if (hasTag_Bookmark(bm, remote_BookmarkTag)) {
488 remove_HashIterator(&i); 488 remove_HashIterator(&i);
489 delete_Bookmark(bm); 489 delete_Bookmark(bm);
490 numRemoved++; 490 numRemoved++;
diff --git a/src/bookmarks.h b/src/bookmarks.h
index ab9c683b..635682d1 100644
--- a/src/bookmarks.h
+++ b/src/bookmarks.h
@@ -32,6 +32,14 @@ iDeclareType(GmRequest)
32iDeclareType(Bookmark) 32iDeclareType(Bookmark)
33iDeclareTypeConstruction(Bookmark) 33iDeclareTypeConstruction(Bookmark)
34 34
35#define headings_BookmarkTag "headings"
36#define homepage_BookmarkTag "homepage"
37#define linkSplit_BookmarkTag "linksplit"
38#define remote_BookmarkTag "remote"
39#define remoteSource_BookmarkTag "remotesource"
40#define subscribed_BookmarkTag "subscribed"
41#define userIcon_BookmarkTag "usericon"
42
35struct Impl_Bookmark { 43struct Impl_Bookmark {
36 iHashNode node; 44 iHashNode node;
37 iString url; 45 iString url;
diff --git a/src/feeds.c b/src/feeds.c
index 2f4714f3..dcd97b43 100644
--- a/src/feeds.c
+++ b/src/feeds.c
@@ -95,7 +95,7 @@ static void init_FeedJob(iFeedJob *d, const iBookmark *bookmark) {
95 init_PtrArray(&d->results); 95 init_PtrArray(&d->results);
96 iZap(d->startTime); 96 iZap(d->startTime);
97 d->isFirstUpdate = iFalse; 97 d->isFirstUpdate = iFalse;
98 d->checkHeadings = hasTag_Bookmark(bookmark, "headings"); 98 d->checkHeadings = hasTag_Bookmark(bookmark, headings_BookmarkTag);
99} 99}
100 100
101static void deinit_FeedJob(iFeedJob *d) { 101static void deinit_FeedJob(iFeedJob *d) {
diff --git a/src/prefs.c b/src/prefs.c
index e26efaba..e6eba2a6 100644
--- a/src/prefs.c
+++ b/src/prefs.c
@@ -37,6 +37,7 @@ void init_Prefs(iPrefs *d) {
37 d->zoomPercent = 100; 37 d->zoomPercent = 100;
38 d->sideIcon = iTrue; 38 d->sideIcon = iTrue;
39 d->hideToolbarOnScroll = iTrue; 39 d->hideToolbarOnScroll = iTrue;
40 d->pinSplit = 1;
40 d->hoverLink = iFalse; 41 d->hoverLink = iFalse;
41 d->smoothScrolling = iTrue; 42 d->smoothScrolling = iTrue;
42 d->loadImageInsteadOfScrolling = iFalse; 43 d->loadImageInsteadOfScrolling = iFalse;
diff --git a/src/prefs.h b/src/prefs.h
index 7f02a100..0f604ee2 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -51,6 +51,7 @@ struct Impl_Prefs {
51 int zoomPercent; 51 int zoomPercent;
52 iBool sideIcon; 52 iBool sideIcon;
53 iBool hideToolbarOnScroll; 53 iBool hideToolbarOnScroll;
54 int pinSplit; /* 0: no pinning, 1: left doc, 2: right doc */
54 /* Behavior */ 55 /* Behavior */
55 iString downloadDir; 56 iString downloadDir;
56 iBool hoverLink; 57 iBool hoverLink;
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 6a44fd5f..8d519865 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -221,6 +221,7 @@ enum iDocumentWidgetFlag {
221 pinchZoom_DocumentWidgetFlag = iBit(9), 221 pinchZoom_DocumentWidgetFlag = iBit(9),
222 movingSelectMarkStart_DocumentWidgetFlag = iBit(10), 222 movingSelectMarkStart_DocumentWidgetFlag = iBit(10),
223 movingSelectMarkEnd_DocumentWidgetFlag = iBit(11), 223 movingSelectMarkEnd_DocumentWidgetFlag = iBit(11),
224 otherRootByDefault_DocumentWidgetFlag = iBit(12), /* links open to other root by default */
224}; 225};
225 226
226enum iDocumentLinkOrdinalMode { 227enum iDocumentLinkOrdinalMode {
@@ -956,6 +957,20 @@ static void documentRunsInvalidated_DocumentWidget_(iDocumentWidget *d) {
956 iZap(d->renderRuns); 957 iZap(d->renderRuns);
957} 958}
958 959
960iBool isPinned_DocumentWidget_(const iDocumentWidget *d) {
961 if (d->flags & otherRootByDefault_DocumentWidgetFlag) {
962 return iTrue;
963 }
964 const iWidget *w = constAs_Widget(d);
965 const iWindow *win = get_Window();
966 if (numRoots_Window(win) == 1) {
967 return iFalse;
968 }
969 const iPrefs *prefs = prefs_App();
970 return (prefs->pinSplit == 1 && w->root == win->roots[0]) ||
971 (prefs->pinSplit == 2 && w->root == win->roots[1]);
972}
973
959void setSource_DocumentWidget(iDocumentWidget *d, const iString *source) { 974void setSource_DocumentWidget(iDocumentWidget *d, const iString *source) {
960 setUrl_GmDocument(d->doc, d->mod.url); 975 setUrl_GmDocument(d->doc, d->mod.url);
961 setSource_GmDocument(d->doc, source, documentWidth_DocumentWidget_(d)); 976 setSource_GmDocument(d->doc, source, documentWidth_DocumentWidget_(d));
@@ -965,6 +980,15 @@ void setSource_DocumentWidget(iDocumentWidget *d, const iString *source) {
965 d->drawBufs->flags |= updateSideBuf_DrawBufsFlag; 980 d->drawBufs->flags |= updateSideBuf_DrawBufsFlag;
966 invalidate_DocumentWidget_(d); 981 invalidate_DocumentWidget_(d);
967 refresh_Widget(as_Widget(d)); 982 refresh_Widget(as_Widget(d));
983 /* Check for special bookmark tags. */
984 d->flags &= ~otherRootByDefault_DocumentWidgetFlag;
985 const uint16_t bmid = findUrl_Bookmarks(bookmarks_App(), d->mod.url);
986 if (bmid) {
987 const iBookmark *bm = get_Bookmarks(bookmarks_App(), bmid);
988 if (hasTag_Bookmark(bm, linkSplit_BookmarkTag)) {
989 d->flags |= otherRootByDefault_DocumentWidgetFlag;
990 }
991 }
968} 992}
969 993
970static void updateTheme_DocumentWidget_(iDocumentWidget *d) { 994static void updateTheme_DocumentWidget_(iDocumentWidget *d) {
@@ -2455,7 +2479,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
2455 linkUrl_GmDocument(d->doc, run->linkId))) != 0) { 2479 linkUrl_GmDocument(d->doc, run->linkId))) != 0) {
2456 const iBookmark *bm = get_Bookmarks(bookmarks_App(), bmid); 2480 const iBookmark *bm = get_Bookmarks(bookmarks_App(), bmid);
2457 /* We can import local copies of remote bookmarks. */ 2481 /* We can import local copies of remote bookmarks. */
2458 if (!hasTag_Bookmark(bm, "remote")) { 2482 if (!hasTag_Bookmark(bm, remote_BookmarkTag)) {
2459 remove_PtrArrayIterator(&i); 2483 remove_PtrArrayIterator(&i);
2460 } 2484 }
2461 } 2485 }
@@ -2740,11 +2764,12 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
2740 else { 2764 else {
2741 postCommandf_Root(w->root, 2765 postCommandf_Root(w->root,
2742 "open newtab:%d url:%s", 2766 "open newtab:%d url:%s",
2743 d->ordinalMode == 2767 (isPinned_DocumentWidget_(d) ? otherRoot_OpenTabFlag : 0) ^
2768 (d->ordinalMode ==
2744 numbersAndAlphabet_DocumentLinkOrdinalMode 2769 numbersAndAlphabet_DocumentLinkOrdinalMode
2745 ? openTabMode_Sym(modState_Keys()) 2770 ? openTabMode_Sym(modState_Keys())
2746 : (d->flags & newTabViaHomeKeys_DocumentWidgetFlag ? 1 : 0), 2771 : (d->flags & newTabViaHomeKeys_DocumentWidgetFlag ? 1 : 0)),
2747 cstr_String(absoluteUrl_String( 2772 cstr_String(absoluteUrl_String(
2748 d->mod.url, linkUrl_GmDocument(d->doc, run->linkId)))); 2773 d->mod.url, linkUrl_GmDocument(d->doc, run->linkId))));
2749 } 2774 }
2750 setLinkNumberMode_DocumentWidget_(d, iFalse); 2775 setLinkNumberMode_DocumentWidget_(d, iFalse);
@@ -2862,8 +2887,9 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
2862 } 2887 }
2863 if (ev->button.button == SDL_BUTTON_MIDDLE && d->hoverLink) { 2888 if (ev->button.button == SDL_BUTTON_MIDDLE && d->hoverLink) {
2864 postCommandf_Root(w->root, "open newtab:%d url:%s", 2889 postCommandf_Root(w->root, "open newtab:%d url:%s",
2865 modState_Keys() & KMOD_SHIFT ? 1 : 2, 2890 (isPinned_DocumentWidget_(d) ? otherRoot_OpenTabFlag : 0) |
2866 cstr_String(linkUrl_GmDocument(d->doc, d->hoverLink->linkId))); 2891 (modState_Keys() & KMOD_SHIFT ? new_OpenTabFlag : newBackground_OpenTabFlag),
2892 cstr_String(linkUrl_GmDocument(d->doc, d->hoverLink->linkId)));
2867 return iTrue; 2893 return iTrue;
2868 } 2894 }
2869 if (ev->button.button == SDL_BUTTON_RIGHT && 2895 if (ev->button.button == SDL_BUTTON_RIGHT &&
@@ -3237,8 +3263,12 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
3237 refresh_Widget(w); 3263 refresh_Widget(w);
3238 } 3264 }
3239 else if (linkFlags & supportedProtocol_GmLinkFlag) { 3265 else if (linkFlags & supportedProtocol_GmLinkFlag) {
3266 int tabMode = openTabMode_Sym(modState_Keys());
3267 if (isPinned_DocumentWidget_(d)) {
3268 tabMode ^= otherRoot_OpenTabFlag;
3269 }
3240 postCommandf_Root(w->root, "open newtab:%d url:%s", 3270 postCommandf_Root(w->root, "open newtab:%d url:%s",
3241 openTabMode_Sym(modState_Keys()), 3271 tabMode,
3242 cstr_String(absoluteUrl_String( 3272 cstr_String(absoluteUrl_String(
3243 d->mod.url, linkUrl_GmDocument(d->doc, linkId)))); 3273 d->mod.url, linkUrl_GmDocument(d->doc, linkId))));
3244 } 3274 }
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c
index 7d08b83a..245b76a3 100644
--- a/src/ui/sidebarwidget.c
+++ b/src/ui/sidebarwidget.c
@@ -824,12 +824,12 @@ iBool handleBookmarkEditorCommands_SidebarWidget_(iWidget *editor, const char *c
824 set_String(&bm->url, url); 824 set_String(&bm->url, url);
825 set_String(&bm->tags, tags); 825 set_String(&bm->tags, tags);
826 if (isEmpty_String(icon)) { 826 if (isEmpty_String(icon)) {
827 removeTag_Bookmark(bm, "usericon"); 827 removeTag_Bookmark(bm, userIcon_BookmarkTag);
828 bm->icon = 0; 828 bm->icon = 0;
829 } 829 }
830 else { 830 else {
831 if (!hasTag_Bookmark(bm, "usericon")) { 831 if (!hasTag_Bookmark(bm, userIcon_BookmarkTag)) {
832 addTag_Bookmark(bm, "usericon"); 832 addTag_Bookmark(bm, userIcon_BookmarkTag);
833 } 833 }
834 bm->icon = first_String(icon); 834 bm->icon = first_String(icon);
835 } 835 }
@@ -1008,7 +1008,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1008 setText_InputWidget(findChild_Widget(dlg, "bmed.title"), &bm->title); 1008 setText_InputWidget(findChild_Widget(dlg, "bmed.title"), &bm->title);
1009 setText_InputWidget(findChild_Widget(dlg, "bmed.url"), &bm->url); 1009 setText_InputWidget(findChild_Widget(dlg, "bmed.url"), &bm->url);
1010 setText_InputWidget(findChild_Widget(dlg, "bmed.tags"), &bm->tags); 1010 setText_InputWidget(findChild_Widget(dlg, "bmed.tags"), &bm->tags);
1011 if (hasTag_Bookmark(bm, "usericon")) { 1011 if (hasTag_Bookmark(bm, userIcon_BookmarkTag)) {
1012 setText_InputWidget(findChild_Widget(dlg, "bmed.icon"), 1012 setText_InputWidget(findChild_Widget(dlg, "bmed.icon"),
1013 collect_String(newUnicodeN_String(&bm->icon, 1))); 1013 collect_String(newUnicodeN_String(&bm->icon, 1)));
1014 } 1014 }
@@ -1022,7 +1022,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1022 if (d->mode == bookmarks_SidebarMode && item) { 1022 if (d->mode == bookmarks_SidebarMode && item) {
1023 setFlags_Widget(w, disabled_WidgetFlag, iTrue); 1023 setFlags_Widget(w, disabled_WidgetFlag, iTrue);
1024 iBookmark *bm = get_Bookmarks(bookmarks_App(), item->id); 1024 iBookmark *bm = get_Bookmarks(bookmarks_App(), item->id);
1025 const iBool isRemote = hasTag_Bookmark(bm, "remote"); 1025 const iBool isRemote = hasTag_Bookmark(bm, remote_BookmarkTag);
1026 iChar icon = isRemote ? 0x1f588 : bm->icon; 1026 iChar icon = isRemote ? 0x1f588 : bm->icon;
1027 iWidget *dlg = makeBookmarkCreation_Widget(&bm->url, &bm->title, icon); 1027 iWidget *dlg = makeBookmarkCreation_Widget(&bm->url, &bm->title, icon);
1028 setId_Widget(dlg, format_CStr("bmed.%s", cstr_String(id_Widget(w)))); 1028 setId_Widget(dlg, format_CStr("bmed.%s", cstr_String(id_Widget(w))));
@@ -1040,7 +1040,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1040 iBookmark *bm = get_Bookmarks(bookmarks_App(), item->id); 1040 iBookmark *bm = get_Bookmarks(bookmarks_App(), item->id);
1041 if (hasTag_Bookmark(bm, tag)) { 1041 if (hasTag_Bookmark(bm, tag)) {
1042 removeTag_Bookmark(bm, tag); 1042 removeTag_Bookmark(bm, tag);
1043 if (!iCmpStr(tag, "subscribed")) { 1043 if (!iCmpStr(tag, subscribed_BookmarkTag)) {
1044 removeEntries_Feeds(item->id); 1044 removeEntries_Feeds(item->id);
1045 } 1045 }
1046 } 1046 }
@@ -1119,7 +1119,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1119 } 1119 }
1120 if (isCommand_Widget(w, ev, "feed.entry.unsubscribe")) { 1120 if (isCommand_Widget(w, ev, "feed.entry.unsubscribe")) {
1121 if (arg_Command(cmd)) { 1121 if (arg_Command(cmd)) {
1122 removeTag_Bookmark(feedBookmark, "subscribed"); 1122 removeTag_Bookmark(feedBookmark, subscribed_BookmarkTag);
1123 removeEntries_Feeds(id_Bookmark(feedBookmark)); 1123 removeEntries_Feeds(id_Bookmark(feedBookmark));
1124 updateItems_SidebarWidget_(d); 1124 updateItems_SidebarWidget_(d);
1125 } 1125 }
@@ -1308,7 +1308,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1308 "bookmark.tag tag:homepage"); 1308 "bookmark.tag tag:homepage");
1309 if (menuItem) { 1309 if (menuItem) {
1310 setTextCStr_LabelWidget(menuItem, 1310 setTextCStr_LabelWidget(menuItem,
1311 hasTag_Bookmark(bm, "homepage") 1311 hasTag_Bookmark(bm, homepage_BookmarkTag)
1312 ? home_Icon " ${bookmark.untag.home}" 1312 ? home_Icon " ${bookmark.untag.home}"
1313 : home_Icon " ${bookmark.tag.home}"); 1313 : home_Icon " ${bookmark.tag.home}");
1314 checkIcon_LabelWidget(menuItem); 1314 checkIcon_LabelWidget(menuItem);
@@ -1316,7 +1316,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1316 menuItem = findMenuItem_Widget(d->menu, "bookmark.tag tag:subscribed"); 1316 menuItem = findMenuItem_Widget(d->menu, "bookmark.tag tag:subscribed");
1317 if (menuItem) { 1317 if (menuItem) {
1318 setTextCStr_LabelWidget(menuItem, 1318 setTextCStr_LabelWidget(menuItem,
1319 hasTag_Bookmark(bm, "subscribed") 1319 hasTag_Bookmark(bm, subscribed_BookmarkTag)
1320 ? star_Icon " ${bookmark.untag.sub}" 1320 ? star_Icon " ${bookmark.untag.sub}"
1321 : star_Icon " ${bookmark.tag.sub}"); 1321 : star_Icon " ${bookmark.tag.sub}");
1322 checkIcon_LabelWidget(menuItem); 1322 checkIcon_LabelWidget(menuItem);
@@ -1324,7 +1324,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1324 menuItem = findMenuItem_Widget(d->menu, "bookmark.tag tag:remotesource"); 1324 menuItem = findMenuItem_Widget(d->menu, "bookmark.tag tag:remotesource");
1325 if (menuItem) { 1325 if (menuItem) {
1326 setTextCStr_LabelWidget(menuItem, 1326 setTextCStr_LabelWidget(menuItem,
1327 hasTag_Bookmark(bm, "remotesource") 1327 hasTag_Bookmark(bm, remoteSource_BookmarkTag)
1328 ? downArrowBar_Icon " ${bookmark.untag.remote}" 1328 ? downArrowBar_Icon " ${bookmark.untag.remote}"
1329 : downArrowBar_Icon " ${bookmark.tag.remote}"); 1329 : downArrowBar_Icon " ${bookmark.tag.remote}");
1330 checkIcon_LabelWidget(menuItem); 1330 checkIcon_LabelWidget(menuItem);
@@ -1386,13 +1386,13 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1386 const iSidebarItem *hoverItem = hoverItem_ListWidget(d->list); 1386 const iSidebarItem *hoverItem = hoverItem_ListWidget(d->list);
1387 iAssert(hoverItem); 1387 iAssert(hoverItem);
1388 const iBookmark * bm = get_Bookmarks(bookmarks_App(), hoverItem->id); 1388 const iBookmark * bm = get_Bookmarks(bookmarks_App(), hoverItem->id);
1389 const iBool isRemote = hasTag_Bookmark(bm, "remote"); 1389 const iBool isRemote = hasTag_Bookmark(bm, remote_BookmarkTag);
1390 static const char *localOnlyCmds[] = { "bookmark.edit", 1390 static const char *localOnlyCmds[] = { "bookmark.edit",
1391 "bookmark.delete", 1391 "bookmark.delete",
1392 "bookmark.tag tag:subscribed", 1392 "bookmark.tag tag:" subscribed_BookmarkTag,
1393 "bookmark.tag tag:homepage", 1393 "bookmark.tag tag:" homepage_BookmarkTag,
1394 "bookmark.tag tag:remotesource", 1394 "bookmark.tag tag:" remoteSource_BookmarkTag,
1395 "bookmark.tag tag:subscribed" }; 1395 "bookmark.tag tag:" subscribed_BookmarkTag };
1396 iForIndices(i, localOnlyCmds) { 1396 iForIndices(i, localOnlyCmds) {
1397 setFlags_Widget(as_Widget(findMenuItem_Widget(d->menu, localOnlyCmds[i])), 1397 setFlags_Widget(as_Widget(findMenuItem_Widget(d->menu, localOnlyCmds[i])),
1398 disabled_WidgetFlag, 1398 disabled_WidgetFlag,
diff --git a/src/ui/util.c b/src/ui/util.c
index 5995f6a0..8c058ac3 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -2218,6 +2218,14 @@ iWidget *makePreferences_Widget(void) {
2218 addChild_Widget(values, iClob(makeToggle_Widget("prefs.hoverlink"))); 2218 addChild_Widget(values, iClob(makeToggle_Widget("prefs.hoverlink")));
2219 addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.archive.openindex}"))); 2219 addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.archive.openindex}")));
2220 addChild_Widget(values, iClob(makeToggle_Widget("prefs.archive.openindex"))); 2220 addChild_Widget(values, iClob(makeToggle_Widget("prefs.archive.openindex")));
2221 addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.pinsplit}")));
2222 iWidget *pinSplit = new_Widget();
2223 /* Split mode document pinning. */ {
2224 addRadioButton_(pinSplit, "prefs.pinsplit.0", "${prefs.pinsplit.none}", "pinsplit.set arg:0");
2225 addRadioButton_(pinSplit, "prefs.pinsplit.1", "${prefs.pinsplit.left}", "pinsplit.set arg:1");
2226 addRadioButton_(pinSplit, "prefs.pinsplit.2", "${prefs.pinsplit.right}", "pinsplit.set arg:2");
2227 }
2228 addChildFlags_Widget(values, iClob(pinSplit), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag);
2221 addChild_Widget(headings, iClob(makePadding_Widget(bigGap))); 2229 addChild_Widget(headings, iClob(makePadding_Widget(bigGap)));
2222 addChild_Widget(values, iClob(makePadding_Widget(bigGap))); 2230 addChild_Widget(values, iClob(makePadding_Widget(bigGap)));
2223 /* UI languages. */ { 2231 /* UI languages. */ {
@@ -2457,10 +2465,21 @@ iWidget *makeBookmarkEditor_Widget(void) {
2457 setUrlContent_InputWidget(inputs[1], iTrue); 2465 setUrlContent_InputWidget(inputs[1], iTrue);
2458 addDialogInputWithHeading_(headings, values, "${dlg.bookmark.tags}", "bmed.tags", iClob(inputs[2] = new_InputWidget(0))); 2466 addDialogInputWithHeading_(headings, values, "${dlg.bookmark.tags}", "bmed.tags", iClob(inputs[2] = new_InputWidget(0)));
2459 addDialogInputWithHeading_(headings, values, "${dlg.bookmark.icon}", "bmed.icon", iClob(inputs[3] = new_InputWidget(1))); 2467 addDialogInputWithHeading_(headings, values, "${dlg.bookmark.icon}", "bmed.icon", iClob(inputs[3] = new_InputWidget(1)));
2468 /* Buttons for special tags. */
2469 addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI)));
2470 addChild_Widget(dlg, iClob(makeTwoColumnWidget_(&headings, &values)));
2471 makeTwoColumnHeading_("SPECIAL TAGS", headings, values);
2472 addChild_Widget(headings, iClob(makeHeading_Widget("${bookmark.tag.home}")));
2473 addChild_Widget(values, iClob(makeToggle_Widget("bmed.tag.home")));
2474 addChild_Widget(headings, iClob(makeHeading_Widget("${bookmark.tag.remote}")));
2475 addChild_Widget(values, iClob(makeToggle_Widget("bmed.tag.remote")));
2476 addChild_Widget(headings, iClob(makeHeading_Widget("${bookmark.tag.sub}")));
2477 addChild_Widget(values, iClob(makeToggle_Widget("bmed.tag.sub")));
2460 arrange_Widget(dlg); 2478 arrange_Widget(dlg);
2461 for (int i = 0; i < 3; ++i) { 2479 for (int i = 0; i < 3; ++i) {
2462 as_Widget(inputs[i])->rect.size.x = 100 * gap_UI - headings->rect.size.x; 2480 as_Widget(inputs[i])->rect.size.x = 100 * gap_UI - headings->rect.size.x;
2463 } 2481 }
2482 addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI)));
2464 addChild_Widget( 2483 addChild_Widget(
2465 dlg, 2484 dlg,
2466 iClob(makeDialogButtons_Widget((iMenuItem[]){ { "${cancel}", 0, 0, NULL }, 2485 iClob(makeDialogButtons_Widget((iMenuItem[]){ { "${cancel}", 0, 0, NULL },
@@ -2489,8 +2508,8 @@ static iBool handleBookmarkCreationCommands_SidebarWidget_(iWidget *editor, cons
2489 const uint32_t id = add_Bookmarks(bookmarks_App(), url, title, tags, first_String(icon)); 2508 const uint32_t id = add_Bookmarks(bookmarks_App(), url, title, tags, first_String(icon));
2490 if (!isEmpty_String(icon)) { 2509 if (!isEmpty_String(icon)) {
2491 iBookmark *bm = get_Bookmarks(bookmarks_App(), id); 2510 iBookmark *bm = get_Bookmarks(bookmarks_App(), id);
2492 if (!hasTag_Bookmark(bm, "usericon")) { 2511 if (!hasTag_Bookmark(bm, userIcon_BookmarkTag)) {
2493 addTag_Bookmark(bm, "usericon"); 2512 addTag_Bookmark(bm, userIcon_BookmarkTag);
2494 } 2513 }
2495 } 2514 }
2496 postCommand_App("bookmarks.changed"); 2515 postCommand_App("bookmarks.changed");
@@ -2609,7 +2628,7 @@ iWidget *makeFeedSettings_Widget(uint32_t bookmarkId) {
2609 setText_InputWidget(findChild_Widget(dlg, "feedcfg.title"), 2628 setText_InputWidget(findChild_Widget(dlg, "feedcfg.title"),
2610 bm ? &bm->title : feedTitle_DocumentWidget(document_App())); 2629 bm ? &bm->title : feedTitle_DocumentWidget(document_App()));
2611 setFlags_Widget(findChild_Widget(dlg, 2630 setFlags_Widget(findChild_Widget(dlg,
2612 hasTag_Bookmark(bm, "headings") ? "feedcfg.type.headings" 2631 hasTag_Bookmark(bm, headings_BookmarkTag) ? "feedcfg.type.headings"
2613 : "feedcfg.type.gemini"), 2632 : "feedcfg.type.gemini"),
2614 selected_WidgetFlag, 2633 selected_WidgetFlag,
2615 iTrue); 2634 iTrue);
diff --git a/src/ui/window.c b/src/ui/window.c
index 5a8a1e26..c4d06d75 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -1218,9 +1218,15 @@ void setSplitMode_Window(iWindow *d, int splitFlags) {
1218 setCurrent_Root(d->roots[1]); 1218 setCurrent_Root(d->roots[1]);
1219 d->keyRoot = d->roots[1]; 1219 d->keyRoot = d->roots[1];
1220 createUserInterface_Root(d->roots[1]); 1220 createUserInterface_Root(d->roots[1]);
1221 /* If the old root has multiple tabs, move the current one to the new split. */ { 1221 if (!isEmpty_String(d->pendingSplitUrl)) {
1222 postCommandf_Root(d->roots[1], "open url:%s",
1223 cstr_String(d->pendingSplitUrl));
1224 clear_String(d->pendingSplitUrl);
1225 }
1226 else if (~splitFlags & noEvents_WindowSplit) {
1222 iWidget *docTabs0 = findChild_Widget(d->roots[0]->widget, "doctabs"); 1227 iWidget *docTabs0 = findChild_Widget(d->roots[0]->widget, "doctabs");
1223 iWidget *docTabs1 = findChild_Widget(d->roots[1]->widget, "doctabs"); 1228 iWidget *docTabs1 = findChild_Widget(d->roots[1]->widget, "doctabs");
1229 /* If the old root has multiple tabs, move the current one to the new split. */
1224 if (tabCount_Widget(docTabs0) >= 2) { 1230 if (tabCount_Widget(docTabs0) >= 2) {
1225 int movedIndex = tabPageIndex_Widget(docTabs0, moved); 1231 int movedIndex = tabPageIndex_Widget(docTabs0, moved);
1226 removeTabPage_Widget(docTabs0, movedIndex); 1232 removeTabPage_Widget(docTabs0, movedIndex);
@@ -1228,19 +1234,10 @@ void setSplitMode_Window(iWindow *d, int splitFlags) {
1228 iRelease(removeTabPage_Widget(docTabs1, 0)); /* delete the default tab */ 1234 iRelease(removeTabPage_Widget(docTabs1, 0)); /* delete the default tab */
1229 setRoot_Widget(as_Widget(moved), d->roots[1]); 1235 setRoot_Widget(as_Widget(moved), d->roots[1]);
1230 prependTabPage_Widget(docTabs1, iClob(moved), "", 0, 0); 1236 prependTabPage_Widget(docTabs1, iClob(moved), "", 0, 0);
1231 if (~splitFlags & noEvents_WindowSplit) { 1237 postCommandf_App("tabs.switch page:%p", moved);
1232 postCommandf_App("tabs.switch page:%p", moved);
1233 }
1234 } 1238 }
1235 else if (~splitFlags & noEvents_WindowSplit) { 1239 else {
1236 if (isEmpty_String(d->pendingSplitUrl)) { 1240 postCommand_Root(d->roots[1], "navigate.home");
1237 postCommand_Root(d->roots[1], "navigate.home");
1238 }
1239 else {
1240 postCommandf_Root(d->roots[1], "open url:%s",
1241 cstr_String(d->pendingSplitUrl));
1242 clear_String(d->pendingSplitUrl);
1243 }
1244 } 1241 }
1245 } 1242 }
1246 setCurrent_Root(NULL); 1243 setCurrent_Root(NULL);