summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-11-28 14:03:33 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-11-28 14:03:33 +0200
commit1efe2aab4fdc811c1dd37c76d1f5d37063745649 (patch)
tree410df70002df7256343a993fc91a9b1dcbb3dbca
parentab44b19cf747c348099c5aa86fcaf8bf0be628c9 (diff)
Bookmarks: Internal tags have a dot prefix
Internal behavior tags are now written in bookmarks.ini with a dot prefix (like hidden files on Unix), and at runtime they are removed from the tags string. This makes things more efficient as it isn't necessary to compile regular expressions all the time. TODO: Add "Edit Feed..." into the Bookmarks context menu, and a new menu item for listing all subscriptions. IssueID #331
-rw-r--r--src/app.c4
-rw-r--r--src/bookmarks.c135
-rw-r--r--src/bookmarks.h77
-rw-r--r--src/feeds.c12
-rw-r--r--src/ui/documentwidget.c4
-rw-r--r--src/ui/sidebarwidget.c85
-rw-r--r--src/ui/util.c18
7 files changed, 204 insertions, 131 deletions
diff --git a/src/app.c b/src/app.c
index a2de03ca..0c6e38f1 100644
--- a/src/app.c
+++ b/src/app.c
@@ -2980,10 +2980,8 @@ iBool handleCommand_App(const char *cmd) {
2980 } 2980 }
2981 else if (equal_Command(cmd, "navigate.home")) { 2981 else if (equal_Command(cmd, "navigate.home")) {
2982 /* Look for bookmarks tagged "homepage". */ 2982 /* Look for bookmarks tagged "homepage". */
2983 iRegExp *pattern = iClob(new_RegExp("\\b" homepage_BookmarkTag "\\b",
2984 caseInsensitive_RegExpOption));
2985 const iPtrArray *homepages = 2983 const iPtrArray *homepages =
2986 list_Bookmarks(d->bookmarks, NULL, filterTagsRegExp_Bookmarks, pattern); 2984 list_Bookmarks(d->bookmarks, NULL, filterHomepage_Bookmark, NULL);
2987 if (isEmpty_PtrArray(homepages)) { 2985 if (isEmpty_PtrArray(homepages)) {
2988 postCommand_Root(get_Root(), "open url:about:lagrange"); 2986 postCommand_Root(get_Root(), "open url:about:lagrange");
2989 } 2987 }
diff --git a/src/bookmarks.c b/src/bookmarks.c
index d4b20162..2606d975 100644
--- a/src/bookmarks.c
+++ b/src/bookmarks.c
@@ -37,6 +37,7 @@ void init_Bookmark(iBookmark *d) {
37 init_String(&d->url); 37 init_String(&d->url);
38 init_String(&d->title); 38 init_String(&d->title);
39 init_String(&d->tags); 39 init_String(&d->tags);
40 iZap(d->flags);
40 iZap(d->when); 41 iZap(d->when);
41 d->parentId = 0; 42 d->parentId = 0;
42 d->order = 0; 43 d->order = 0;
@@ -48,6 +49,7 @@ void deinit_Bookmark(iBookmark *d) {
48 deinit_String(&d->url); 49 deinit_String(&d->url);
49} 50}
50 51
52#if 0
51iBool hasTag_Bookmark(const iBookmark *d, const char *tag) { 53iBool hasTag_Bookmark(const iBookmark *d, const char *tag) {
52 if (!d) return iFalse; 54 if (!d) return iFalse;
53 iRegExp *pattern = new_RegExp(format_CStr("\\b%s\\b", tag), caseSensitive_RegExpOption); 55 iRegExp *pattern = new_RegExp(format_CStr("\\b%s\\b", tag), caseSensitive_RegExpOption);
@@ -60,7 +62,7 @@ iBool hasTag_Bookmark(const iBookmark *d, const char *tag) {
60 62
61void addTag_Bookmark(iBookmark *d, const char *tag) { 63void addTag_Bookmark(iBookmark *d, const char *tag) {
62 if (!isEmpty_String(&d->tags)) { 64 if (!isEmpty_String(&d->tags)) {
63 appendChar_String(&d->tags, ' '); 65 appendCStr_String(&d->tags, " ");
64 } 66 }
65 appendCStr_String(&d->tags, tag); 67 appendCStr_String(&d->tags, tag);
66} 68}
@@ -72,6 +74,93 @@ void removeTag_Bookmark(iBookmark *d, const char *tag) {
72 trim_String(&d->tags); 74 trim_String(&d->tags);
73 } 75 }
74} 76}
77#endif
78
79static struct {
80 uint32_t bit;
81 const char *tag;
82 iRegExp * pattern;
83 iRegExp * oldPattern;
84}
85specialTags_[] = {
86 { homepage_BookmarkFlag, ".homepage" },
87 { remoteSource_BookmarkFlag, ".remotesource" },
88 { linkSplit_BookmarkFlag, ".linksplit" },
89 { userIcon_BookmarkFlag, ".usericon" },
90 { subscribed_BookmarkFlag, ".subscribed" },
91 { headings_BookmarkFlag, ".headings" },
92 { ignoreWeb_BookmarkFlag, ".ignoreweb" },
93 /* `remote_BookmarkFlag` not included because it's runtime only */
94};
95
96static void updatePatterns_(size_t index) {
97 if (!specialTags_[index].pattern) {
98 specialTags_[index].pattern = new_RegExp(format_CStr("(?<!\\w)\\%s\\b(?!\\w)",
99 specialTags_[index].tag),
100 caseSensitive_RegExpOption); /* never released */
101 }
102 if (!specialTags_[index].oldPattern) {
103 /* TODO: Get rid of these when compatibility with v1.9 or older is not important. */
104 specialTags_[index].oldPattern =
105 new_RegExp(format_CStr("\\b%s\\b", specialTags_[index].tag + 1), /* dotless */
106 caseSensitive_RegExpOption); /* never released */
107 }
108}
109
110static void normalizeSpacesInTags_(iString *tags) {
111 iBool wasSpace = iFalse;
112 iString out;
113 init_String(&out);
114 for (const char *ch = constBegin_String(tags); ch != constEnd_String(tags); ch++) {
115 if (*ch == ' ') {
116 if (!wasSpace) {
117 wasSpace = iTrue;
118 }
119 else {
120 continue;
121 }
122 }
123 else {
124 wasSpace = iFalse;
125 }
126 appendData_Block(&out.chars, ch, 1);
127 }
128 trim_String(&out);
129 set_String(tags, &out);
130 deinit_String(&out);
131}
132
133static void unpackDotTags_Bookmark_(iBookmark *d) {
134 iZap(d->flags);
135 iForIndices(i, specialTags_) {
136 updatePatterns_(i);
137 iRegExpMatch m;
138 init_RegExpMatch(&m);
139 iBool isSet = matchString_RegExp(specialTags_[i].pattern, &d->tags, &m);
140 if (!isSet) {
141 init_RegExpMatch(&m);
142 isSet = matchString_RegExp(specialTags_[i].oldPattern, &d->tags, &m);
143 }
144 iChangeFlags(d->flags, specialTags_[i].bit, isSet);
145 if (isSet) {
146 remove_Block(&d->tags.chars, m.range.start, size_Range(&m.range));
147 }
148 }
149 normalizeSpacesInTags_(&d->tags);
150}
151
152static iString *packedDotTags_Bookmark_(const iBookmark *d) {
153 iString *withDot = copy_String(&d->tags);
154 iForIndices(i, specialTags_) {
155 if (d->flags & specialTags_[i].bit) {
156 if (!isEmpty_String(withDot)) {
157 appendCStr_String(withDot, " ");
158 }
159 appendCStr_String(withDot, specialTags_[i].tag);
160 }
161 }
162 return withDot;
163}
75 164
76iDefineTypeConstruction(Bookmark) 165iDefineTypeConstruction(Bookmark)
77 166
@@ -176,6 +265,7 @@ static void loadOldFormat_Bookmarks(iBookmarks *d, const char *dirPath) {
176 setRange_String(&bm->title, line); 265 setRange_String(&bm->title, line);
177 nextSplit_Rangecc(src, "\n", &line); 266 nextSplit_Rangecc(src, "\n", &line);
178 setRange_String(&bm->tags, line); 267 setRange_String(&bm->tags, line);
268 unpackDotTags_Bookmark_(bm);
179 insert_Bookmarks_(d, bm); 269 insert_Bookmarks_(d, bm);
180 } 270 }
181 } 271 }
@@ -220,6 +310,10 @@ static void handleKeyValue_BookmarkLoader_(void *context, const iString *table,
220 } 310 }
221 else if (!cmp_String(key, "tags") && tv->type == string_TomlType) { 311 else if (!cmp_String(key, "tags") && tv->type == string_TomlType) {
222 set_String(&bm->tags, tv->value.string); 312 set_String(&bm->tags, tv->value.string);
313 if (strstr(cstr_String(&bm->tags), "subscribed")) {
314 printf("a\n");
315 }
316 unpackDotTags_Bookmark_(bm);
223 } 317 }
224 else if (!cmp_String(key, "icon") && tv->type == int64_TomlType) { 318 else if (!cmp_String(key, "icon") && tv->type == int64_TomlType) {
225 bm->icon = (iChar) tv->value.int64; 319 bm->icon = (iChar) tv->value.int64;
@@ -292,7 +386,6 @@ void load_Bookmarks(iBookmarks *d, const char *dirPath) {
292 386
293void save_Bookmarks(const iBookmarks *d, const char *dirPath) { 387void save_Bookmarks(const iBookmarks *d, const char *dirPath) {
294 lock_Mutex(d->mtx); 388 lock_Mutex(d->mtx);
295 iRegExp *remotePattern = iClob(new_RegExp("\\bremote\\b", caseSensitive_RegExpOption));
296 iFile *f = newCStr_File(concatPath_CStr(dirPath, fileName_Bookmarks_)); 389 iFile *f = newCStr_File(concatPath_CStr(dirPath, fileName_Bookmarks_));
297 if (open_File(f, writeOnly_FileMode | text_FileMode)) { 390 if (open_File(f, writeOnly_FileMode | text_FileMode)) {
298 iString *str = collectNew_String(); 391 iString *str = collectNew_String();
@@ -300,13 +393,12 @@ void save_Bookmarks(const iBookmarks *d, const char *dirPath) {
300 writeData_File(f, cstr_String(str), size_String(str)); 393 writeData_File(f, cstr_String(str), size_String(str));
301 iConstForEach(Hash, i, &d->bookmarks) { 394 iConstForEach(Hash, i, &d->bookmarks) {
302 const iBookmark *bm = (const iBookmark *) i.value; 395 const iBookmark *bm = (const iBookmark *) i.value;
303 iRegExpMatch m; 396 if (bm->flags & remote_BookmarkFlag) {
304 init_RegExpMatch(&m);
305 if (matchString_RegExp(remotePattern, &bm->tags, &m)) {
306 /* Remote bookmarks are not saved. */ 397 /* Remote bookmarks are not saved. */
307 continue; 398 continue;
308 } 399 }
309 iBeginCollect(); 400 iBeginCollect();
401 const iString *packedTags = collect_String(packedDotTags_Bookmark_(bm));
310 format_String(str, 402 format_String(str,
311 "[%d]\n" 403 "[%d]\n"
312 "url = \"%s\"\n" 404 "url = \"%s\"\n"
@@ -317,7 +409,7 @@ void save_Bookmarks(const iBookmarks *d, const char *dirPath) {
317 id_Bookmark(bm), 409 id_Bookmark(bm),
318 cstrCollect_String(quote_String(&bm->url, iFalse)), 410 cstrCollect_String(quote_String(&bm->url, iFalse)),
319 cstrCollect_String(quote_String(&bm->title, iFalse)), 411 cstrCollect_String(quote_String(&bm->title, iFalse)),
320 cstrCollect_String(quote_String(&bm->tags, iFalse)), 412 cstrCollect_String(quote_String(packedTags, iFalse)),
321 bm->icon, 413 bm->icon,
322 seconds_Time(&bm->when), 414 seconds_Time(&bm->when),
323 cstrCollect_String(format_Time(&bm->when, "%Y-%m-%d"))); 415 cstrCollect_String(format_Time(&bm->when, "%Y-%m-%d")));
@@ -397,7 +489,7 @@ iBool updateBookmarkIcon_Bookmarks(iBookmarks *d, const iString *url, iChar icon
397 const uint32_t id = findUrl_Bookmarks(d, url); 489 const uint32_t id = findUrl_Bookmarks(d, url);
398 if (id) { 490 if (id) {
399 iBookmark *bm = get_Bookmarks(d, id); 491 iBookmark *bm = get_Bookmarks(d, id);
400 if (!hasTag_Bookmark(bm, remote_BookmarkTag) && !hasTag_Bookmark(bm, userIcon_BookmarkTag)) { 492 if (~bm->flags & remote_BookmarkFlag && ~bm->flags & userIcon_BookmarkFlag) {
401 if (icon != bm->icon) { 493 if (icon != bm->icon) {
402 bm->icon = icon; 494 bm->icon = icon;
403 changed = iTrue; 495 changed = iTrue;
@@ -422,19 +514,13 @@ iChar siteIcon_Bookmarks(const iBookmarks *d, const iString *url) {
422 if (isEmpty_String(url)) { 514 if (isEmpty_String(url)) {
423 return 0; 515 return 0;
424 } 516 }
425 static iRegExp *tagPattern_;
426 if (!tagPattern_) {
427 tagPattern_ = new_RegExp("\\b" userIcon_BookmarkTag "\\b", caseSensitive_RegExpOption);
428 }
429 const iRangecc urlRoot = urlRoot_String(url); 517 const iRangecc urlRoot = urlRoot_String(url);
430 size_t matchingSize = iInvalidSize; /* we'll pick the shortest matching */ 518 size_t matchingSize = iInvalidSize; /* we'll pick the shortest matching */
431 iChar icon = 0; 519 iChar icon = 0;
432 lock_Mutex(d->mtx); 520 lock_Mutex(d->mtx);
433 iConstForEach(Hash, i, &d->bookmarks) { 521 iConstForEach(Hash, i, &d->bookmarks) {
434 const iBookmark *bm = (const iBookmark *) i.value; 522 const iBookmark *bm = (const iBookmark *) i.value;
435 iRegExpMatch m; 523 if (bm->icon && bm->flags & userIcon_BookmarkFlag) {
436 init_RegExpMatch(&m);
437 if (bm->icon && matchString_RegExp(tagPattern_, &bm->tags, &m)) {
438 const iRangecc bmRoot = urlRoot_String(&bm->url); 524 const iRangecc bmRoot = urlRoot_String(&bm->url);
439 if (equalRangeCase_Rangecc(urlRoot, bmRoot)) { 525 if (equalRangeCase_Rangecc(urlRoot, bmRoot)) {
440 const size_t n = size_String(&bm->url); 526 const size_t n = size_String(&bm->url);
@@ -467,10 +553,15 @@ void reorder_Bookmarks(iBookmarks *d, uint32_t id, int newOrder) {
467 unlock_Mutex(d->mtx); 553 unlock_Mutex(d->mtx);
468} 554}
469 555
470iBool filterTagsRegExp_Bookmarks(void *regExp, const iBookmark *bm) { 556//iBool filterTagsRegExp_Bookmarks(void *regExp, const iBookmark *bm) {
471 iRegExpMatch m; 557// iRegExpMatch m;
472 init_RegExpMatch(&m); 558// init_RegExpMatch(&m);
473 return matchString_RegExp(regExp, &bm->tags, &m); 559// return matchString_RegExp(regExp, &bm->tags, &m);
560//}
561
562iBool filterHomepage_Bookmark(void *d, const iBookmark *bm) {
563 iUnused(d);
564 return (bm->flags & homepage_BookmarkFlag) != 0;
474} 565}
475 566
476static iBool matchUrl_(void *url, const iBookmark *bm) { 567static iBool matchUrl_(void *url, const iBookmark *bm) {
@@ -618,7 +709,7 @@ const iString *bookmarkListPage_Bookmarks(const iBookmarks *d, enum iBookmarkLis
618 709
619static iBool isRemoteSource_Bookmark_(void *context, const iBookmark *d) { 710static iBool isRemoteSource_Bookmark_(void *context, const iBookmark *d) {
620 iUnused(context); 711 iUnused(context);
621 return hasTag_Bookmark(d, remoteSource_BookmarkTag); 712 return (d->flags & remoteSource_BookmarkFlag) != 0;
622} 713}
623 714
624void remoteRequestFinished_Bookmarks_(iBookmarks *d, iGmRequest *req) { 715void remoteRequestFinished_Bookmarks_(iBookmarks *d, iGmRequest *req) {
@@ -642,7 +733,6 @@ void requestFinished_Bookmarks(iBookmarks *d, iGmRequest *req) {
642 initCurrent_Time(&now); 733 initCurrent_Time(&now);
643 iRegExp *linkPattern = new_RegExp("^=>\\s*([^\\s]+)(\\s+(.*))?", 0); 734 iRegExp *linkPattern = new_RegExp("^=>\\s*([^\\s]+)(\\s+(.*))?", 0);
644 iString src; 735 iString src;
645 const iString *remoteTag = collectNewCStr_String("remote");
646 initBlock_String(&src, body_GmRequest(req)); 736 initBlock_String(&src, body_GmRequest(req));
647 iRangecc srcLine = iNullRange; 737 iRangecc srcLine = iNullRange;
648 while (nextSplit_Rangecc(range_String(&src), "\n", &srcLine)) { 738 while (nextSplit_Rangecc(range_String(&src), "\n", &srcLine)) {
@@ -660,8 +750,9 @@ void requestFinished_Bookmarks(iBookmarks *d, iGmRequest *req) {
660 if (isEmpty_String(titleStr)) { 750 if (isEmpty_String(titleStr)) {
661 setRange_String(titleStr, urlHost_String(urlStr)); 751 setRange_String(titleStr, urlHost_String(urlStr));
662 } 752 }
663 const uint32_t bmId = add_Bookmarks(d, absUrl, titleStr, remoteTag, 0x2913); 753 const uint32_t bmId = add_Bookmarks(d, absUrl, titleStr, NULL, 0x2913);
664 iBookmark *bm = get_Bookmarks(d, bmId); 754 iBookmark *bm = get_Bookmarks(d, bmId);
755 bm->flags |= remote_BookmarkFlag;
665 bm->parentId = *(uint32_t *) userData_Object(req); 756 bm->parentId = *(uint32_t *) userData_Object(req);
666 delete_String(titleStr); 757 delete_String(titleStr);
667 } 758 }
@@ -690,7 +781,7 @@ void fetchRemote_Bookmarks(iBookmarks *d) {
690 size_t numRemoved = 0; 781 size_t numRemoved = 0;
691 iForEach(Hash, i, &d->bookmarks) { 782 iForEach(Hash, i, &d->bookmarks) {
692 iBookmark *bm = (iBookmark *) i.value; 783 iBookmark *bm = (iBookmark *) i.value;
693 if (hasTag_Bookmark(bm, remote_BookmarkTag)) { 784 if (bm->flags & remote_BookmarkFlag) {
694 remove_HashIterator(&i); 785 remove_HashIterator(&i);
695 delete_Bookmark(bm); 786 delete_Bookmark(bm);
696 numRemoved++; 787 numRemoved++;
diff --git a/src/bookmarks.h b/src/bookmarks.h
index 6cb5c8a9..08afdd8b 100644
--- a/src/bookmarks.h
+++ b/src/bookmarks.h
@@ -31,27 +31,30 @@ iDeclareType(GmRequest)
31 31
32iDeclareType(Bookmark) 32iDeclareType(Bookmark)
33iDeclareTypeConstruction(Bookmark) 33iDeclareTypeConstruction(Bookmark)
34 34
35/* TODO: Make the special internal tags a bitfield, separate from user's tags. */ 35/* These values are not serialized as-is in bookmarks.ini. Instead, they are included in `tags`
36 36 with a dot prefix. This helps retain backwards and forwards compatibility. */
37#define headings_BookmarkTag "headings" 37enum iBookmarkFlags {
38#define ignoreWeb_BookmarkTag "ignoreweb" 38 homepage_BookmarkFlag = iBit(1),
39#define homepage_BookmarkTag "homepage" 39 remoteSource_BookmarkFlag = iBit(2),
40#define linkSplit_BookmarkTag "linksplit" 40 linkSplit_BookmarkFlag = iBit(3),
41#define remote_BookmarkTag "remote" 41 userIcon_BookmarkFlag = iBit(4),
42#define remoteSource_BookmarkTag "remotesource" 42 subscribed_BookmarkFlag = iBit(17),
43#define subscribed_BookmarkTag "subscribed" 43 headings_BookmarkFlag = iBit(18),
44#define userIcon_BookmarkTag "usericon" 44 ignoreWeb_BookmarkFlag = iBit(19),
45 remote_BookmarkFlag = iBit(31),
46};
45 47
46struct Impl_Bookmark { 48struct Impl_Bookmark {
47 iHashNode node; 49 iHashNode node;
48 iString url; 50 iString url;
49 iString title; 51 iString title;
50 iString tags; 52 iString tags;
51 iChar icon; 53 uint32_t flags;
52 iTime when; 54 iChar icon;
53 uint32_t parentId; /* remote source or folder */ 55 iTime when;
54 int order; /* sort order */ 56 uint32_t parentId; /* remote source or folder */
57 int order; /* sort order */
55}; 58};
56 59
57iLocalDef uint32_t id_Bookmark (const iBookmark *d) { return d->node.key; } 60iLocalDef uint32_t id_Bookmark (const iBookmark *d) { return d->node.key; }
@@ -59,23 +62,24 @@ iLocalDef iBool isFolder_Bookmark (const iBookmark *d) { return isEmpty_St
59 62
60iBool hasParent_Bookmark (const iBookmark *, uint32_t parentId); 63iBool hasParent_Bookmark (const iBookmark *, uint32_t parentId);
61int depth_Bookmark (const iBookmark *); 64int depth_Bookmark (const iBookmark *);
62iBool hasTag_Bookmark (const iBookmark *, const char *tag); 65
63void addTag_Bookmark (iBookmark *, const char *tag); 66//iBool hasTag_Bookmark (const iBookmark *, const char *tag);
64void removeTag_Bookmark (iBookmark *, const char *tag); 67//void addTag_Bookmark (iBookmark *, const char *tag);
65 68//void removeTag_Bookmark (iBookmark *, const char *tag);
66iLocalDef void addTagIfMissing_Bookmark(iBookmark *d, const char *tag) { 69
67 if (!hasTag_Bookmark(d, tag)) { 70//iLocalDef void addTagIfMissing_Bookmark(iBookmark *d, const char *tag) {
68 addTag_Bookmark(d, tag); 71// if (!hasTag_Bookmark(d, tag)) {
69 } 72// addTag_Bookmark(d, tag);
70} 73// }
71iLocalDef void addOrRemoveTag_Bookmark(iBookmark *d, const char *tag, iBool add) { 74//}
72 if (add) { 75//iLocalDef void addOrRemoveTag_Bookmark(iBookmark *d, const char *tag, iBool add) {
73 addTagIfMissing_Bookmark(d, tag); 76// if (add) {
74 } 77// addTagIfMissing_Bookmark(d, tag);
75 else { 78// }
76 removeTag_Bookmark(d, tag); 79// else {
77 } 80// removeTag_Bookmark(d, tag);
78} 81// }
82//}
79 83
80int cmpTitleAscending_Bookmark (const iBookmark **, const iBookmark **); 84int cmpTitleAscending_Bookmark (const iBookmark **, const iBookmark **);
81int cmpTree_Bookmark (const iBookmark **, const iBookmark **); 85int cmpTree_Bookmark (const iBookmark **, const iBookmark **);
@@ -109,7 +113,8 @@ iChar siteIcon_Bookmarks (const iBookmarks *, const iString *url)
109uint32_t findUrl_Bookmarks (const iBookmarks *, const iString *url); /* O(n) */ 113uint32_t findUrl_Bookmarks (const iBookmarks *, const iString *url); /* O(n) */
110uint32_t recentFolder_Bookmarks (const iBookmarks *); 114uint32_t recentFolder_Bookmarks (const iBookmarks *);
111 115
112iBool filterTagsRegExp_Bookmarks (void *regExp, const iBookmark *); 116//iBool filterTagsRegExp_Bookmarks (void *regExp, const iBookmark *);
117iBool filterHomepage_Bookmark (void *, const iBookmark *);
113 118
114/** 119/**
115 * Lists all or a subset of the bookmarks in a sorted array of Bookmark pointers. 120 * Lists all or a subset of the bookmarks in a sorted array of Bookmark pointers.
diff --git a/src/feeds.c b/src/feeds.c
index 26b3d6db..b7ce739b 100644
--- a/src/feeds.c
+++ b/src/feeds.c
@@ -97,8 +97,8 @@ static void init_FeedJob(iFeedJob *d, const iBookmark *bookmark) {
97 init_PtrArray(&d->results); 97 init_PtrArray(&d->results);
98 iZap(d->startTime); 98 iZap(d->startTime);
99 d->isFirstUpdate = iFalse; 99 d->isFirstUpdate = iFalse;
100 d->checkHeadings = hasTag_Bookmark(bookmark, headings_BookmarkTag); 100 d->checkHeadings = (bookmark->flags & headings_BookmarkFlag) != 0;
101 d->ignoreWeb = hasTag_Bookmark(bookmark, ignoreWeb_BookmarkTag); 101 d->ignoreWeb = (bookmark->flags & ignoreWeb_BookmarkFlag) != 0;
102} 102}
103 103
104static void deinit_FeedJob(iFeedJob *d) { 104static void deinit_FeedJob(iFeedJob *d) {
@@ -146,13 +146,7 @@ static void submit_FeedJob_(iFeedJob *d) {
146 146
147static iBool isSubscribed_(void *context, const iBookmark *bm) { 147static iBool isSubscribed_(void *context, const iBookmark *bm) {
148 iUnused(context); 148 iUnused(context);
149 static iRegExp *pattern_ = NULL; 149 return (bm->flags & subscribed_BookmarkFlag) != 0;
150 if (!pattern_) {
151 pattern_ = new_RegExp("\\bsubscribed\\b", caseSensitive_RegExpOption);
152 }
153 iRegExpMatch m;
154 init_RegExpMatch(&m);
155 return matchString_RegExp(pattern_, &bm->tags, &m);
156} 150}
157 151
158static const iPtrArray *listSubscriptions_(void) { 152static const iPtrArray *listSubscriptions_(void) {
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index aac77572..39dd3aab 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -1108,7 +1108,7 @@ static void documentWasChanged_DocumentWidget_(iDocumentWidget *d) {
1108 const uint16_t bmid = findUrl_Bookmarks(bookmarks_App(), d->mod.url); 1108 const uint16_t bmid = findUrl_Bookmarks(bookmarks_App(), d->mod.url);
1109 if (bmid) { 1109 if (bmid) {
1110 const iBookmark *bm = get_Bookmarks(bookmarks_App(), bmid); 1110 const iBookmark *bm = get_Bookmarks(bookmarks_App(), bmid);
1111 if (hasTag_Bookmark(bm, linkSplit_BookmarkTag)) { 1111 if (bm->flags & linkSplit_BookmarkFlag) {
1112 d->flags |= otherRootByDefault_DocumentWidgetFlag; 1112 d->flags |= otherRootByDefault_DocumentWidgetFlag;
1113 } 1113 }
1114 } 1114 }
@@ -3383,7 +3383,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
3383 linkUrl_GmDocument(d->doc, run->linkId))) != 0) { 3383 linkUrl_GmDocument(d->doc, run->linkId))) != 0) {
3384 const iBookmark *bm = get_Bookmarks(bookmarks_App(), bmid); 3384 const iBookmark *bm = get_Bookmarks(bookmarks_App(), bmid);
3385 /* We can import local copies of remote bookmarks. */ 3385 /* We can import local copies of remote bookmarks. */
3386 if (!hasTag_Bookmark(bm, remote_BookmarkTag)) { 3386 if (~bm->flags & remote_BookmarkFlag) {
3387 remove_PtrArrayIterator(&i); 3387 remove_PtrArrayIterator(&i);
3388 } 3388 }
3389 } 3389 }
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c
index 550fccde..b6aa06b1 100644
--- a/src/ui/sidebarwidget.c
+++ b/src/ui/sidebarwidget.c
@@ -407,11 +407,6 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
407 break; 407 break;
408 } 408 }
409 case bookmarks_SidebarMode: { 409 case bookmarks_SidebarMode: {
410 iRegExp *homeTag = iClob(new_RegExp("\\b" homepage_BookmarkTag "\\b", caseSensitive_RegExpOption));
411 iRegExp *subTag = iClob(new_RegExp("\\b" subscribed_BookmarkTag "\\b", caseSensitive_RegExpOption));
412 iRegExp *remoteSourceTag = iClob(new_RegExp("\\b" remoteSource_BookmarkTag "\\b", caseSensitive_RegExpOption));
413 iRegExp *remoteTag = iClob(new_RegExp("\\b" remote_BookmarkTag "\\b", caseSensitive_RegExpOption));
414 iRegExp *linkSplitTag = iClob(new_RegExp("\\b" linkSplit_BookmarkTag "\\b", caseSensitive_RegExpOption));
415 iConstForEach(PtrArray, i, list_Bookmarks(bookmarks_App(), cmpTree_Bookmark, NULL, NULL)) { 410 iConstForEach(PtrArray, i, list_Bookmarks(bookmarks_App(), cmpTree_Bookmark, NULL, NULL)) {
416 const iBookmark *bm = i.ptr; 411 const iBookmark *bm = i.ptr;
417 if (isBookmarkFolded_SidebarWidget_(d, bm)) { 412 if (isBookmarkFolded_SidebarWidget_(d, bm)) {
@@ -430,27 +425,21 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
430 } 425 }
431 set_String(&item->url, &bm->url); 426 set_String(&item->url, &bm->url);
432 set_String(&item->label, &bm->title); 427 set_String(&item->label, &bm->title);
433 /* Icons for special tags. */ { 428 /* Icons for special behaviors. */ {
434 iRegExpMatch m; 429 if (bm->flags & subscribed_BookmarkFlag) {
435 init_RegExpMatch(&m);
436 if (matchString_RegExp(subTag, &bm->tags, &m)) {
437 appendChar_String(&item->meta, 0x2605); 430 appendChar_String(&item->meta, 0x2605);
438 } 431 }
439 init_RegExpMatch(&m); 432 if (bm->flags & homepage_BookmarkFlag) {
440 if (matchString_RegExp(homeTag, &bm->tags, &m)) {
441 appendChar_String(&item->meta, 0x1f3e0); 433 appendChar_String(&item->meta, 0x1f3e0);
442 } 434 }
443 init_RegExpMatch(&m); 435 if (bm->flags & remote_BookmarkFlag) {
444 if (matchString_RegExp(remoteTag, &bm->tags, &m)) {
445 item->listItem.isDraggable = iFalse; 436 item->listItem.isDraggable = iFalse;
446 } 437 }
447 init_RegExpMatch(&m); 438 if (bm->flags & remoteSource_BookmarkFlag) {
448 if (matchString_RegExp(remoteSourceTag, &bm->tags, &m)) {
449 appendChar_String(&item->meta, 0x2913); 439 appendChar_String(&item->meta, 0x2913);
450 item->isBold = iTrue; 440 item->isBold = iTrue;
451 } 441 }
452 init_RegExpMatch(&m); 442 if (bm->flags & linkSplit_BookmarkFlag) {
453 if (matchString_RegExp(linkSplitTag, &bm->tags, &m)) {
454 appendChar_String(&item->meta, 0x25e7); 443 appendChar_String(&item->meta, 0x25e7);
455 } 444 }
456 } 445 }
@@ -1042,19 +1031,16 @@ iBool handleBookmarkEditorCommands_SidebarWidget_(iWidget *editor, const char *c
1042 set_String(&bm->url, url); 1031 set_String(&bm->url, url);
1043 set_String(&bm->tags, tags); 1032 set_String(&bm->tags, tags);
1044 if (isEmpty_String(icon)) { 1033 if (isEmpty_String(icon)) {
1045 removeTag_Bookmark(bm, userIcon_BookmarkTag); 1034 bm->flags &= ~userIcon_BookmarkFlag;
1046 bm->icon = 0; 1035 bm->icon = 0;
1047 } 1036 }
1048 else { 1037 else {
1049 addTagIfMissing_Bookmark(bm, userIcon_BookmarkTag); 1038 bm->flags |= userIcon_BookmarkFlag;
1050 bm->icon = first_String(icon); 1039 bm->icon = first_String(icon);
1051 } 1040 }
1052 addOrRemoveTag_Bookmark(bm, homepage_BookmarkTag, 1041 iChangeFlags(bm->flags, homepage_BookmarkFlag, isSelected_Widget(findChild_Widget(editor, "bmed.tag.home")));
1053 isSelected_Widget(findChild_Widget(editor, "bmed.tag.home"))); 1042 iChangeFlags(bm->flags, remoteSource_BookmarkFlag, isSelected_Widget(findChild_Widget(editor, "bmed.tag.remote")));
1054 addOrRemoveTag_Bookmark(bm, remoteSource_BookmarkTag, 1043 iChangeFlags(bm->flags, linkSplit_BookmarkFlag, isSelected_Widget(findChild_Widget(editor, "bmed.tag.linksplit")));
1055 isSelected_Widget(findChild_Widget(editor, "bmed.tag.remote")));
1056 addOrRemoveTag_Bookmark(bm, linkSplit_BookmarkTag,
1057 isSelected_Widget(findChild_Widget(editor, "bmed.tag.linksplit")));
1058 } 1044 }
1059 const iBookmark *folder = userData_Object(findChild_Widget(editor, "bmed.folder")); 1045 const iBookmark *folder = userData_Object(findChild_Widget(editor, "bmed.folder"));
1060 if (!folder || !hasParent_Bookmark(folder, id_Bookmark(bm))) { 1046 if (!folder || !hasParent_Bookmark(folder, id_Bookmark(bm))) {
@@ -1152,7 +1138,7 @@ static void bookmarkMoved_SidebarWidget_(iSidebarWidget *d, size_t index, size_t
1152 : dstIndex); 1138 : dstIndex);
1153 if (isLast && isBefore) isBefore = iFalse; 1139 if (isLast && isBefore) isBefore = iFalse;
1154 const iBookmark *dst = get_Bookmarks(bookmarks_App(), dstItem->id); 1140 const iBookmark *dst = get_Bookmarks(bookmarks_App(), dstItem->id);
1155 if (hasParent_Bookmark(dst, movingItem->id) || hasTag_Bookmark(dst, remote_BookmarkTag)) { 1141 if (hasParent_Bookmark(dst, movingItem->id) || dst->flags & remote_BookmarkFlag) {
1156 /* Can't move a folder inside itself, and remote bookmarks cannot be reordered. */ 1142 /* Can't move a folder inside itself, and remote bookmarks cannot be reordered. */
1157 return; 1143 return;
1158 } 1144 }
@@ -1176,7 +1162,8 @@ static void bookmarkMovedOntoFolder_SidebarWidget_(iSidebarWidget *d, size_t ind
1176static size_t numBookmarks_(const iPtrArray *bmList) { 1162static size_t numBookmarks_(const iPtrArray *bmList) {
1177 size_t num = 0; 1163 size_t num = 0;
1178 iConstForEach(PtrArray, i, bmList) { 1164 iConstForEach(PtrArray, i, bmList) {
1179 if (!isFolder_Bookmark(i.ptr) && !hasTag_Bookmark(i.ptr, remote_BookmarkTag)) { 1165 const iBookmark *bm = i.ptr;
1166 if (!isFolder_Bookmark(bm) && ~bm->flags & remote_BookmarkFlag) {
1180 num++; 1167 num++;
1181 } 1168 }
1182 } 1169 }
@@ -1349,13 +1336,13 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1349 if (!isFolder_Bookmark(bm)) { 1336 if (!isFolder_Bookmark(bm)) {
1350 setText_InputWidget(urlInput, &bm->url); 1337 setText_InputWidget(urlInput, &bm->url);
1351 setText_InputWidget(tagsInput, &bm->tags); 1338 setText_InputWidget(tagsInput, &bm->tags);
1352 if (hasTag_Bookmark(bm, userIcon_BookmarkTag)) { 1339 if (bm->flags & userIcon_BookmarkFlag) {
1353 setText_InputWidget(iconInput, 1340 setText_InputWidget(iconInput,
1354 collect_String(newUnicodeN_String(&bm->icon, 1))); 1341 collect_String(newUnicodeN_String(&bm->icon, 1)));
1355 } 1342 }
1356 setToggle_Widget(homeTag, hasTag_Bookmark(bm, homepage_BookmarkTag)); 1343 setToggle_Widget(homeTag, bm->flags & homepage_BookmarkFlag);
1357 setToggle_Widget(remoteSourceTag, hasTag_Bookmark(bm, remoteSource_BookmarkTag)); 1344 setToggle_Widget(remoteSourceTag, bm->flags & remoteSource_BookmarkFlag);
1358 setToggle_Widget(linkSplitTag, hasTag_Bookmark(bm, linkSplit_BookmarkTag)); 1345 setToggle_Widget(linkSplitTag, bm->flags & linkSplit_BookmarkFlag);
1359 } 1346 }
1360 else { 1347 else {
1361 setFlags_Widget(findChild_Widget(dlg, "bmed.special"), 1348 setFlags_Widget(findChild_Widget(dlg, "bmed.special"),
@@ -1376,7 +1363,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1376 const iSidebarItem *item = d->contextItem; 1363 const iSidebarItem *item = d->contextItem;
1377 if (d->mode == bookmarks_SidebarMode && item) { 1364 if (d->mode == bookmarks_SidebarMode && item) {
1378 iBookmark *bm = get_Bookmarks(bookmarks_App(), item->id); 1365 iBookmark *bm = get_Bookmarks(bookmarks_App(), item->id);
1379 const iBool isRemote = hasTag_Bookmark(bm, remote_BookmarkTag); 1366 const iBool isRemote = (bm->flags & remote_BookmarkFlag) != 0;
1380 iChar icon = isRemote ? 0x1f588 : bm->icon; 1367 iChar icon = isRemote ? 0x1f588 : bm->icon;
1381 iWidget *dlg = makeBookmarkCreation_Widget(&bm->url, &bm->title, icon); 1368 iWidget *dlg = makeBookmarkCreation_Widget(&bm->url, &bm->title, icon);
1382 setId_Widget(dlg, format_CStr("bmed.%s", cstr_String(id_Widget(w)))); 1369 setId_Widget(dlg, format_CStr("bmed.%s", cstr_String(id_Widget(w))));
@@ -1390,17 +1377,16 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1390 else if (isCommand_Widget(w, ev, "bookmark.tag")) { 1377 else if (isCommand_Widget(w, ev, "bookmark.tag")) {
1391 const iSidebarItem *item = d->contextItem; 1378 const iSidebarItem *item = d->contextItem;
1392 if (d->mode == bookmarks_SidebarMode && item) { 1379 if (d->mode == bookmarks_SidebarMode && item) {
1393 const char *tag = cstr_String(string_Command(cmd, "tag")); 1380 const iRangecc tag = range_Command(cmd, "tag");
1381 const int flag =
1382 (equal_Rangecc(tag, "homepage") ? homepage_BookmarkFlag : 0) |
1383 (equal_Rangecc(tag, "subscribed") ? subscribed_BookmarkFlag : 0) |
1384 (equal_Rangecc(tag, "remotesource") ? remoteSource_BookmarkFlag : 0);
1394 iBookmark *bm = get_Bookmarks(bookmarks_App(), item->id); 1385 iBookmark *bm = get_Bookmarks(bookmarks_App(), item->id);
1395 if (hasTag_Bookmark(bm, tag)) { 1386 if (flag == subscribed_BookmarkFlag && (bm->flags & flag)) {
1396 removeTag_Bookmark(bm, tag); 1387 removeEntries_Feeds(item->id); /* get rid of unsubscribed entries */
1397 if (!iCmpStr(tag, subscribed_BookmarkTag)) {
1398 removeEntries_Feeds(item->id);
1399 }
1400 }
1401 else {
1402 addTag_Bookmark(bm, tag);
1403 } 1388 }
1389 bm->flags ^= flag;
1404 postCommand_App("bookmarks.changed"); 1390 postCommand_App("bookmarks.changed");
1405 } 1391 }
1406 return iTrue; 1392 return iTrue;
@@ -1525,7 +1511,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1525 } 1511 }
1526 if (isCommand_Widget(w, ev, "feed.entry.unsubscribe")) { 1512 if (isCommand_Widget(w, ev, "feed.entry.unsubscribe")) {
1527 if (arg_Command(cmd)) { 1513 if (arg_Command(cmd)) {
1528 removeTag_Bookmark(feedBookmark, subscribed_BookmarkTag); 1514 feedBookmark->flags &= ~subscribed_BookmarkFlag;
1529 removeEntries_Feeds(id_Bookmark(feedBookmark)); 1515 removeEntries_Feeds(id_Bookmark(feedBookmark));
1530 updateItems_SidebarWidget_(d); 1516 updateItems_SidebarWidget_(d);
1531 } 1517 }
@@ -1733,17 +1719,17 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1733 if (bm) { 1719 if (bm) {
1734 setMenuItemLabel_Widget(d->menu, 1720 setMenuItemLabel_Widget(d->menu,
1735 "bookmark.tag tag:homepage", 1721 "bookmark.tag tag:homepage",
1736 hasTag_Bookmark(bm, homepage_BookmarkTag) 1722 bm->flags & homepage_BookmarkFlag
1737 ? home_Icon " ${bookmark.untag.home}" 1723 ? home_Icon " ${bookmark.untag.home}"
1738 : home_Icon " ${bookmark.tag.home}"); 1724 : home_Icon " ${bookmark.tag.home}");
1739 setMenuItemLabel_Widget(d->menu, 1725 setMenuItemLabel_Widget(d->menu,
1740 "bookmark.tag tag:subscribed", 1726 "bookmark.tag tag:subscribed",
1741 hasTag_Bookmark(bm, subscribed_BookmarkTag) 1727 bm->flags & subscribed_BookmarkFlag
1742 ? star_Icon " ${bookmark.untag.sub}" 1728 ? star_Icon " ${bookmark.untag.sub}"
1743 : star_Icon " ${bookmark.tag.sub}"); 1729 : star_Icon " ${bookmark.tag.sub}");
1744 setMenuItemLabel_Widget(d->menu, 1730 setMenuItemLabel_Widget(d->menu,
1745 "bookmark.tag tag:remotesource", 1731 "bookmark.tag tag:remotesource",
1746 hasTag_Bookmark(bm, remoteSource_BookmarkTag) 1732 bm->flags & remoteSource_BookmarkFlag
1747 ? downArrowBar_Icon " ${bookmark.untag.remote}" 1733 ? downArrowBar_Icon " ${bookmark.untag.remote}"
1748 : downArrowBar_Icon " ${bookmark.tag.remote}"); 1734 : downArrowBar_Icon " ${bookmark.tag.remote}");
1749 } 1735 }
@@ -1797,13 +1783,12 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1797 const iSidebarItem *hoverItem = hoverItem_ListWidget(d->list); 1783 const iSidebarItem *hoverItem = hoverItem_ListWidget(d->list);
1798 iAssert(hoverItem); 1784 iAssert(hoverItem);
1799 const iBookmark * bm = get_Bookmarks(bookmarks_App(), hoverItem->id); 1785 const iBookmark * bm = get_Bookmarks(bookmarks_App(), hoverItem->id);
1800 const iBool isRemote = hasTag_Bookmark(bm, remote_BookmarkTag); 1786 const iBool isRemote = (bm->flags & remote_BookmarkFlag) != 0;
1801 static const char *localOnlyCmds[] = { "bookmark.edit", 1787 static const char *localOnlyCmds[] = { "bookmark.edit",
1802 "bookmark.delete", 1788 "bookmark.delete",
1803 "bookmark.tag tag:" subscribed_BookmarkTag, 1789 "bookmark.tag tag:subscribed",
1804 "bookmark.tag tag:" homepage_BookmarkTag, 1790 "bookmark.tag tag:homepage",
1805 "bookmark.tag tag:" remoteSource_BookmarkTag, 1791 "bookmark.tag tag:remotesource" };
1806 "bookmark.tag tag:" subscribed_BookmarkTag };
1807 iForIndices(i, localOnlyCmds) { 1792 iForIndices(i, localOnlyCmds) {
1808 setFlags_Widget(as_Widget(findMenuItem_Widget(d->menu, localOnlyCmds[i])), 1793 setFlags_Widget(as_Widget(findMenuItem_Widget(d->menu, localOnlyCmds[i])),
1809 disabled_WidgetFlag, 1794 disabled_WidgetFlag,
diff --git a/src/ui/util.c b/src/ui/util.c
index baa05082..6f5eced3 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -2908,16 +2908,16 @@ static iBool handleBookmarkCreationCommands_SidebarWidget_(iWidget *editor, cons
2908 const uint32_t id = add_Bookmarks(bookmarks_App(), url, title, tags, first_String(icon)); 2908 const uint32_t id = add_Bookmarks(bookmarks_App(), url, title, tags, first_String(icon));
2909 iBookmark * bm = get_Bookmarks(bookmarks_App(), id); 2909 iBookmark * bm = get_Bookmarks(bookmarks_App(), id);
2910 if (!isEmpty_String(icon)) { 2910 if (!isEmpty_String(icon)) {
2911 addTagIfMissing_Bookmark(bm, userIcon_BookmarkTag); 2911 bm->flags |= userIcon_BookmarkFlag;
2912 } 2912 }
2913 if (isSelected_Widget(findChild_Widget(editor, "bmed.tag.home"))) { 2913 if (isSelected_Widget(findChild_Widget(editor, "bmed.tag.home"))) {
2914 addTag_Bookmark(bm, homepage_BookmarkTag); 2914 bm->flags |= homepage_BookmarkFlag;
2915 } 2915 }
2916 if (isSelected_Widget(findChild_Widget(editor, "bmed.tag.remote"))) { 2916 if (isSelected_Widget(findChild_Widget(editor, "bmed.tag.remote"))) {
2917 addTag_Bookmark(bm, remoteSource_BookmarkTag); 2917 bm->flags |= remoteSource_BookmarkFlag;
2918 } 2918 }
2919 if (isSelected_Widget(findChild_Widget(editor, "bmed.tag.linksplit"))) { 2919 if (isSelected_Widget(findChild_Widget(editor, "bmed.tag.linksplit"))) {
2920 addTag_Bookmark(bm, linkSplit_BookmarkTag); 2920 bm->flags |= linkSplit_BookmarkFlag;
2921 } 2921 }
2922 bm->parentId = folder ? id_Bookmark(folder) : 0; 2922 bm->parentId = folder ? id_Bookmark(folder) : 0;
2923 setRecentFolder_Bookmarks(bookmarks_App(), bm->parentId); 2923 setRecentFolder_Bookmarks(bookmarks_App(), bm->parentId);
@@ -2983,9 +2983,9 @@ static iBool handleFeedSettingCommands_(iWidget *dlg, const char *cmd) {
2983 iBookmark *bm = get_Bookmarks(bookmarks_App(), id); 2983 iBookmark *bm = get_Bookmarks(bookmarks_App(), id);
2984 iAssert(bm); 2984 iAssert(bm);
2985 set_String(&bm->title, feedTitle); 2985 set_String(&bm->title, feedTitle);
2986 addOrRemoveTag_Bookmark(bm, subscribed_BookmarkTag, iTrue); 2986 bm->flags |= subscribed_BookmarkFlag;
2987 addOrRemoveTag_Bookmark(bm, headings_BookmarkTag, headings); 2987 iChangeFlags(bm->flags, headings_BookmarkFlag, headings);
2988 addOrRemoveTag_Bookmark(bm, ignoreWeb_BookmarkTag, ignoreWeb); 2988 iChangeFlags(bm->flags, ignoreWeb_BookmarkFlag, ignoreWeb);
2989 postCommand_App("bookmarks.changed"); 2989 postCommand_App("bookmarks.changed");
2990 setupSheetTransition_Mobile(dlg, iFalse); 2990 setupSheetTransition_Mobile(dlg, iFalse);
2991 destroy_Widget(dlg); 2991 destroy_Widget(dlg);
@@ -3048,13 +3048,13 @@ iWidget *makeFeedSettings_Widget(uint32_t bookmarkId) {
3048 setText_InputWidget(findChild_Widget(dlg, "feedcfg.title"), 3048 setText_InputWidget(findChild_Widget(dlg, "feedcfg.title"),
3049 bm ? &bm->title : feedTitle_DocumentWidget(document_App())); 3049 bm ? &bm->title : feedTitle_DocumentWidget(document_App()));
3050 setFlags_Widget(findChild_Widget(dlg, 3050 setFlags_Widget(findChild_Widget(dlg,
3051 hasTag_Bookmark(bm, headings_BookmarkTag) 3051 bm->flags & headings_BookmarkFlag
3052 ? "feedcfg.type.headings" 3052 ? "feedcfg.type.headings"
3053 : "feedcfg.type.gemini"), 3053 : "feedcfg.type.gemini"),
3054 selected_WidgetFlag, 3054 selected_WidgetFlag,
3055 iTrue); 3055 iTrue);
3056 setToggle_Widget(findChild_Widget(dlg, "feedcfg.ignoreweb"), 3056 setToggle_Widget(findChild_Widget(dlg, "feedcfg.ignoreweb"),
3057 hasTag_Bookmark(bm, ignoreWeb_BookmarkTag)); 3057 bm->flags & ignoreWeb_BookmarkFlag);
3058 setCommandHandler_Widget(dlg, handleFeedSettingCommands_); 3058 setCommandHandler_Widget(dlg, handleFeedSettingCommands_);
3059 } 3059 }
3060 setupSheetTransition_Mobile(dlg, incoming_TransitionFlag); 3060 setupSheetTransition_Mobile(dlg, incoming_TransitionFlag);