summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/documentwidget.c47
-rw-r--r--src/ui/sidebarwidget.c30
-rw-r--r--src/ui/util.c15
-rw-r--r--src/ui/widget.c6
-rw-r--r--src/ui/widget.h1
-rw-r--r--src/ui/window.c24
6 files changed, 96 insertions, 27 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index ed38ad0b..5a5a4f84 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -298,10 +298,12 @@ struct Impl_DocumentWidget {
298 298
299iDefineObjectConstruction(DocumentWidget) 299iDefineObjectConstruction(DocumentWidget)
300 300
301static int docEnum_ = 0;
302
301void init_DocumentWidget(iDocumentWidget *d) { 303void init_DocumentWidget(iDocumentWidget *d) {
302 iWidget *w = as_Widget(d); 304 iWidget *w = as_Widget(d);
303 init_Widget(w); 305 init_Widget(w);
304 setId_Widget(w, "document000"); 306 setId_Widget(w, format_CStr("document%03d", ++docEnum_));
305 setFlags_Widget(w, hover_WidgetFlag, iTrue); 307 setFlags_Widget(w, hover_WidgetFlag, iTrue);
306 init_PersistentDocumentState(&d->mod); 308 init_PersistentDocumentState(&d->mod);
307 d->flags = 0; 309 d->flags = 0;
@@ -880,7 +882,7 @@ static void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) {
880 } 882 }
881 /* Take away parts if it doesn't fit. */ 883 /* Take away parts if it doesn't fit. */
882 const int avail = bounds_Widget(as_Widget(tabButton)).size.x - 3 * gap_UI; 884 const int avail = bounds_Widget(as_Widget(tabButton)).size.x - 3 * gap_UI;
883 iBool setWindow = (document_App() == d); 885 iBool setWindow = (document_App() == d && isUnderKeyRoot_Widget(d));
884 for (;;) { 886 for (;;) {
885 iString *text = collect_String(joinCStr_StringArray(title, " \u2014 ")); 887 iString *text = collect_String(joinCStr_StringArray(title, " \u2014 "));
886 if (setWindow) { 888 if (setWindow) {
@@ -1094,6 +1096,7 @@ static const char *zipPageHeading_(const iRangecc mime) {
1094} 1096}
1095 1097
1096static void postProcessRequestContent_DocumentWidget_(iDocumentWidget *d) { 1098static void postProcessRequestContent_DocumentWidget_(iDocumentWidget *d) {
1099 iWidget *w = as_Widget(d);
1097 delete_Gempub(d->sourceGempub); 1100 delete_Gempub(d->sourceGempub);
1098 d->sourceGempub = NULL; 1101 d->sourceGempub = NULL;
1099 if (!cmpCase_String(&d->sourceMime, "application/octet-stream") || 1102 if (!cmpCase_String(&d->sourceMime, "application/octet-stream") ||
@@ -1111,20 +1114,27 @@ static void postProcessRequestContent_DocumentWidget_(iDocumentWidget *d) {
1111 } 1114 }
1112 } 1115 }
1113 if (!d->sourceGempub) { 1116 if (!d->sourceGempub) {
1114 iString *localPath = localFilePathFromUrl_String(d->mod.url); 1117 const iString *localPath = collect_String(localFilePathFromUrl_String(d->mod.url));
1118 iBool isInside = iFalse;
1119 if (localPath && !fileExists_FileInfo(localPath)) {
1120 /* This URL may refer to a file inside the archive. */
1121 localPath = findContainerArchive_Path(localPath);
1122 isInside = iTrue;
1123 }
1115 if (localPath && equal_CStr(mediaType_Path(localPath), "application/gpub+zip")) { 1124 if (localPath && equal_CStr(mediaType_Path(localPath), "application/gpub+zip")) {
1116 iGempub *gempub = new_Gempub(); 1125 iGempub *gempub = new_Gempub();
1117 if (openFile_Gempub(gempub, localPath)) { 1126 if (openFile_Gempub(gempub, localPath)) {
1118 setBaseUrl_Gempub(gempub, d->mod.url); 1127 setBaseUrl_Gempub(gempub, collect_String(makeFileUrl_String(localPath)));
1119 setSource_DocumentWidget(d, collect_String(coverPageSource_Gempub(gempub))); 1128 if (!isInside) {
1120 setCStr_String(&d->sourceMime, mimeType_Gempub); 1129 setSource_DocumentWidget(d, collect_String(coverPageSource_Gempub(gempub)));
1130 setCStr_String(&d->sourceMime, mimeType_Gempub);
1131 }
1121 d->sourceGempub = gempub; 1132 d->sourceGempub = gempub;
1122 } 1133 }
1123 else { 1134 else {
1124 delete_Gempub(gempub); 1135 delete_Gempub(gempub);
1125 } 1136 }
1126 } 1137 }
1127 delete_String(localPath);
1128 } 1138 }
1129 if (d->sourceGempub) { 1139 if (d->sourceGempub) {
1130 if (preloadCoverImage_Gempub(d->sourceGempub, d->doc)) { 1140 if (preloadCoverImage_Gempub(d->sourceGempub, d->doc)) {
@@ -1132,6 +1142,26 @@ static void postProcessRequestContent_DocumentWidget_(iDocumentWidget *d) {
1132 updateVisible_DocumentWidget_(d); 1142 updateVisible_DocumentWidget_(d);
1133 invalidate_DocumentWidget_(d); 1143 invalidate_DocumentWidget_(d);
1134 } 1144 }
1145 if (prefs_App()->pinSplit && equal_String(d->mod.url, indexPageUrl_Gempub(d->sourceGempub))) {
1146 const iString *navStart = navStartLinkUrl_Gempub(d->sourceGempub);
1147 if (navStart) {
1148 iWindow *win = get_Window();
1149 /* Auto-split to show index and the first navigation link. */
1150 if (numRoots_Window(win) == 2) {
1151 /* This document is showing the index page. */
1152 iRoot *other = otherRoot_Window(win, w->root);
1153 postCommandf_Root(other, "open url:%s", cstr_String(navStart));
1154 if (prefs_App()->pinSplit == 1 && w->root == win->roots[1]) {
1155 /* On the wrong side. */
1156 postCommand_App("ui.split swap:1");
1157 }
1158 }
1159 else {
1160 postCommandf_App(
1161 "open newtab:%d url:%s", otherRoot_OpenTabFlag, cstr_String(navStart));
1162 }
1163 }
1164 }
1135 } 1165 }
1136} 1166}
1137 1167
@@ -1925,7 +1955,8 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
1925 } 1955 }
1926 return iTrue; 1956 return iTrue;
1927 } 1957 }
1928 else if (equal_Command(cmd, "window.resized") || equal_Command(cmd, "font.changed")) { 1958 else if (equal_Command(cmd, "window.resized") || equal_Command(cmd, "font.changed") ||
1959 equal_Command(cmd, "keyroot.changed")) {
1929 /* Alt/Option key may be involved in window size changes. */ 1960 /* Alt/Option key may be involved in window size changes. */
1930 setLinkNumberMode_DocumentWidget_(d, iFalse); 1961 setLinkNumberMode_DocumentWidget_(d, iFalse);
1931 d->phoneToolbar = findWidget_App("toolbar"); 1962 d->phoneToolbar = findWidget_App("toolbar");
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c
index 245b76a3..eae0432f 100644
--- a/src/ui/sidebarwidget.c
+++ b/src/ui/sidebarwidget.c
@@ -265,9 +265,10 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
265 break; 265 break;
266 } 266 }
267 case bookmarks_SidebarMode: { 267 case bookmarks_SidebarMode: {
268 iRegExp *homeTag = iClob(new_RegExp("\\bhomepage\\b", caseSensitive_RegExpOption)); 268 iRegExp *homeTag = iClob(new_RegExp("\\b" homepage_BookmarkTag "\\b", caseSensitive_RegExpOption));
269 iRegExp *subTag = iClob(new_RegExp("\\bsubscribed\\b", caseSensitive_RegExpOption)); 269 iRegExp *subTag = iClob(new_RegExp("\\b" subscribed_BookmarkTag "\\b", caseSensitive_RegExpOption));
270 iRegExp *remoteSourceTag = iClob(new_RegExp("\\bremotesource\\b", caseSensitive_RegExpOption)); 270 iRegExp *remoteSourceTag = iClob(new_RegExp("\\b" remoteSource_BookmarkTag "\\b", caseSensitive_RegExpOption));
271 iRegExp *linkSplitTag = iClob(new_RegExp("\\b" linkSplit_BookmarkTag "\\b", caseSensitive_RegExpOption));
271 iConstForEach(PtrArray, i, list_Bookmarks(bookmarks_App(), cmpTitle_Bookmark_, NULL, NULL)) { 272 iConstForEach(PtrArray, i, list_Bookmarks(bookmarks_App(), cmpTitle_Bookmark_, NULL, NULL)) {
272 const iBookmark *bm = i.ptr; 273 const iBookmark *bm = i.ptr;
273 iSidebarItem *item = new_SidebarItem(); 274 iSidebarItem *item = new_SidebarItem();
@@ -290,6 +291,10 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
290 appendChar_String(&item->meta, 0x2913); 291 appendChar_String(&item->meta, 0x2913);
291 item->isBold = iTrue; 292 item->isBold = iTrue;
292 } 293 }
294 init_RegExpMatch(&m);
295 if (matchString_RegExp(linkSplitTag, &bm->tags, &m)) {
296 appendChar_String(&item->meta, 0x25e7);
297 }
293 } 298 }
294 addItem_ListWidget(d->list, item); 299 addItem_ListWidget(d->list, item);
295 iRelease(item); 300 iRelease(item);
@@ -828,11 +833,15 @@ iBool handleBookmarkEditorCommands_SidebarWidget_(iWidget *editor, const char *c
828 bm->icon = 0; 833 bm->icon = 0;
829 } 834 }
830 else { 835 else {
831 if (!hasTag_Bookmark(bm, userIcon_BookmarkTag)) { 836 addTagIfMissing_Bookmark(bm, userIcon_BookmarkTag);
832 addTag_Bookmark(bm, userIcon_BookmarkTag);
833 }
834 bm->icon = first_String(icon); 837 bm->icon = first_String(icon);
835 } 838 }
839 addOrRemoveTag_Bookmark(bm, homepage_BookmarkTag,
840 isSelected_Widget(findChild_Widget(editor, "bmed.tag.home")));
841 addOrRemoveTag_Bookmark(bm, remoteSource_BookmarkTag,
842 isSelected_Widget(findChild_Widget(editor, "bmed.tag.remote")));
843 addOrRemoveTag_Bookmark(bm, linkSplit_BookmarkTag,
844 isSelected_Widget(findChild_Widget(editor, "bmed.tag.linksplit")));
836 postCommand_App("bookmarks.changed"); 845 postCommand_App("bookmarks.changed");
837 } 846 }
838 setFlags_Widget(as_Widget(d), disabled_WidgetFlag, iFalse); 847 setFlags_Widget(as_Widget(d), disabled_WidgetFlag, iFalse);
@@ -1012,6 +1021,15 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1012 setText_InputWidget(findChild_Widget(dlg, "bmed.icon"), 1021 setText_InputWidget(findChild_Widget(dlg, "bmed.icon"),
1013 collect_String(newUnicodeN_String(&bm->icon, 1))); 1022 collect_String(newUnicodeN_String(&bm->icon, 1)));
1014 } 1023 }
1024 setFlags_Widget(findChild_Widget(dlg, "bmed.tag.home"),
1025 selected_WidgetFlag,
1026 hasTag_Bookmark(bm, homepage_BookmarkTag));
1027 setFlags_Widget(findChild_Widget(dlg, "bmed.tag.remote"),
1028 selected_WidgetFlag,
1029 hasTag_Bookmark(bm, remoteSource_BookmarkTag));
1030 setFlags_Widget(findChild_Widget(dlg, "bmed.tag.linksplit"),
1031 selected_WidgetFlag,
1032 hasTag_Bookmark(bm, linkSplit_BookmarkTag));
1015 setCommandHandler_Widget(dlg, handleBookmarkEditorCommands_SidebarWidget_); 1033 setCommandHandler_Widget(dlg, handleBookmarkEditorCommands_SidebarWidget_);
1016 setFocus_Widget(findChild_Widget(dlg, "bmed.title")); 1034 setFocus_Widget(findChild_Widget(dlg, "bmed.title"));
1017 } 1035 }
diff --git a/src/ui/util.c b/src/ui/util.c
index d2f27a8b..92cf85b7 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -2506,11 +2506,18 @@ static iBool handleBookmarkCreationCommands_SidebarWidget_(iWidget *editor, cons
2506 const iString *tags = text_InputWidget(findChild_Widget(editor, "bmed.tags")); 2506 const iString *tags = text_InputWidget(findChild_Widget(editor, "bmed.tags"));
2507 const iString *icon = collect_String(trimmed_String(text_InputWidget(findChild_Widget(editor, "bmed.icon")))); 2507 const iString *icon = collect_String(trimmed_String(text_InputWidget(findChild_Widget(editor, "bmed.icon"))));
2508 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));
2509 iBookmark * bm = get_Bookmarks(bookmarks_App(), id);
2509 if (!isEmpty_String(icon)) { 2510 if (!isEmpty_String(icon)) {
2510 iBookmark *bm = get_Bookmarks(bookmarks_App(), id); 2511 addTagIfMissing_Bookmark(bm, userIcon_BookmarkTag);
2511 if (!hasTag_Bookmark(bm, userIcon_BookmarkTag)) { 2512 }
2512 addTag_Bookmark(bm, userIcon_BookmarkTag); 2513 if (isSelected_Widget(findChild_Widget(editor, "bmed.tag.home"))) {
2513 } 2514 addTag_Bookmark(bm, homepage_BookmarkTag);
2515 }
2516 if (isSelected_Widget(findChild_Widget(editor, "bmed.tag.remote"))) {
2517 addTag_Bookmark(bm, remoteSource_BookmarkTag);
2518 }
2519 if (isSelected_Widget(findChild_Widget(editor, "bmed.tag.linksplit"))) {
2520 addTag_Bookmark(bm, linkSplit_BookmarkTag);
2514 } 2521 }
2515 postCommand_App("bookmarks.changed"); 2522 postCommand_App("bookmarks.changed");
2516 } 2523 }
diff --git a/src/ui/widget.c b/src/ui/widget.c
index 00fe0f5f..67ce1345 100644
--- a/src/ui/widget.c
+++ b/src/ui/widget.c
@@ -1346,6 +1346,12 @@ iBool isHover_Widget(const iAnyObject *d) {
1346 return get_Window()->hover == d; 1346 return get_Window()->hover == d;
1347} 1347}
1348 1348
1349iBool isUnderKeyRoot_Widget(const iAnyObject *d) {
1350 iAssert(isInstance_Object(d, &Class_Widget));
1351 const iWidget *w = d;
1352 return w && get_Window() && w->root == get_Window()->keyRoot;
1353}
1354
1349iBool isSelected_Widget(const iAnyObject *d) { 1355iBool isSelected_Widget(const iAnyObject *d) {
1350 if (d) { 1356 if (d) {
1351 iAssert(isInstance_Object(d, &Class_Widget)); 1357 iAssert(isInstance_Object(d, &Class_Widget));
diff --git a/src/ui/widget.h b/src/ui/widget.h
index 36797210..5b6b18e1 100644
--- a/src/ui/widget.h
+++ b/src/ui/widget.h
@@ -232,6 +232,7 @@ iBool isDisabled_Widget (const iAnyObject *);
232iBool isFocused_Widget (const iAnyObject *); 232iBool isFocused_Widget (const iAnyObject *);
233iBool isHover_Widget (const iAnyObject *); 233iBool isHover_Widget (const iAnyObject *);
234iBool isSelected_Widget (const iAnyObject *); 234iBool isSelected_Widget (const iAnyObject *);
235iBool isUnderKeyRoot_Widget (const iAnyObject *);
235iBool isCommand_Widget (const iWidget *d, const SDL_Event *ev, const char *cmd); 236iBool isCommand_Widget (const iWidget *d, const SDL_Event *ev, const char *cmd);
236iBool hasParent_Widget (const iWidget *d, const iWidget *someParent); 237iBool hasParent_Widget (const iWidget *d, const iWidget *someParent);
237iBool isAffectedByVisualOffset_Widget 238iBool isAffectedByVisualOffset_Widget
diff --git a/src/ui/window.c b/src/ui/window.c
index c4d06d75..a1df2609 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -1214,30 +1214,36 @@ void setSplitMode_Window(iWindow *d, int splitFlags) {
1214 /* Add a second root. */ 1214 /* Add a second root. */
1215 iDocumentWidget *moved = document_Root(d->roots[0]); 1215 iDocumentWidget *moved = document_Root(d->roots[0]);
1216 iAssert(d->roots[1] == NULL); 1216 iAssert(d->roots[1] == NULL);
1217 d->roots[1] = new_Root(); 1217 const iBool addToLeft = (prefs_App()->pinSplit == 2);
1218 setCurrent_Root(d->roots[1]); 1218 size_t newRootIndex = 1;
1219 d->keyRoot = d->roots[1]; 1219 if (addToLeft) {
1220 createUserInterface_Root(d->roots[1]); 1220 iSwap(iRoot *, d->roots[0], d->roots[1]);
1221 newRootIndex = 0;
1222 }
1223 d->roots[newRootIndex] = new_Root();
1224 d->keyRoot = d->roots[newRootIndex];
1225 setCurrent_Root(d->roots[newRootIndex]);
1226 createUserInterface_Root(d->roots[newRootIndex]);
1221 if (!isEmpty_String(d->pendingSplitUrl)) { 1227 if (!isEmpty_String(d->pendingSplitUrl)) {
1222 postCommandf_Root(d->roots[1], "open url:%s", 1228 postCommandf_Root(d->roots[newRootIndex], "open url:%s",
1223 cstr_String(d->pendingSplitUrl)); 1229 cstr_String(d->pendingSplitUrl));
1224 clear_String(d->pendingSplitUrl); 1230 clear_String(d->pendingSplitUrl);
1225 } 1231 }
1226 else if (~splitFlags & noEvents_WindowSplit) { 1232 else if (~splitFlags & noEvents_WindowSplit) {
1227 iWidget *docTabs0 = findChild_Widget(d->roots[0]->widget, "doctabs"); 1233 iWidget *docTabs0 = findChild_Widget(d->roots[newRootIndex ^ 1]->widget, "doctabs");
1228 iWidget *docTabs1 = findChild_Widget(d->roots[1]->widget, "doctabs"); 1234 iWidget *docTabs1 = findChild_Widget(d->roots[newRootIndex]->widget, "doctabs");
1229 /* If the old root has multiple tabs, move the current one to the new split. */ 1235 /* If the old root has multiple tabs, move the current one to the new split. */
1230 if (tabCount_Widget(docTabs0) >= 2) { 1236 if (tabCount_Widget(docTabs0) >= 2) {
1231 int movedIndex = tabPageIndex_Widget(docTabs0, moved); 1237 int movedIndex = tabPageIndex_Widget(docTabs0, moved);
1232 removeTabPage_Widget(docTabs0, movedIndex); 1238 removeTabPage_Widget(docTabs0, movedIndex);
1233 showTabPage_Widget(docTabs0, tabPage_Widget(docTabs0, iMax(movedIndex - 1, 0))); 1239 showTabPage_Widget(docTabs0, tabPage_Widget(docTabs0, iMax(movedIndex - 1, 0)));
1234 iRelease(removeTabPage_Widget(docTabs1, 0)); /* delete the default tab */ 1240 iRelease(removeTabPage_Widget(docTabs1, 0)); /* delete the default tab */
1235 setRoot_Widget(as_Widget(moved), d->roots[1]); 1241 setRoot_Widget(as_Widget(moved), d->roots[newRootIndex]);
1236 prependTabPage_Widget(docTabs1, iClob(moved), "", 0, 0); 1242 prependTabPage_Widget(docTabs1, iClob(moved), "", 0, 0);
1237 postCommandf_App("tabs.switch page:%p", moved); 1243 postCommandf_App("tabs.switch page:%p", moved);
1238 } 1244 }
1239 else { 1245 else {
1240 postCommand_Root(d->roots[1], "navigate.home"); 1246 postCommand_Root(d->roots[newRootIndex], "navigate.home");
1241 } 1247 }
1242 } 1248 }
1243 setCurrent_Root(NULL); 1249 setCurrent_Root(NULL);