From fe5c564a6d0b99223b2ad56e1856f651a49f2f46 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Mon, 12 Jul 2021 12:47:41 +0300 Subject: Update link visited status when navigating When an URL is visited, ensure that links to that URL update their visual state. --- src/gmdocument.c | 81 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 23 deletions(-) (limited to 'src/gmdocument.c') diff --git a/src/gmdocument.c b/src/gmdocument.c index f6db8a1d..d0420c9a 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c @@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "app.h" #include "defs.h" +#include #include #include #include @@ -799,33 +800,31 @@ static void doLayout_GmDocument_(iGmDocument *d) { meta->flags |= topLeft_GmPreMetaFlag; } } - float lineHeightReduction = 0.0f; - if (!isMono) { - /* Upper-level headings are typeset a bit tighter. */ - if (type == heading1_GmLineType) { - lineHeightReduction = 0.10f; - } - else if (type == heading2_GmLineType) { - lineHeightReduction = 0.06f; - } - /* Visited links are never bold. */ - if (run.linkId && linkFlags_GmDocument(d, run.linkId) & visited_GmLinkFlag) { - run.font = paragraph_FontId; - } - } iAssert(!isEmpty_Range(&runLine)); /* must have something at this point */ /* Typeset the paragraph. */ { iRunTypesetter rts; init_RunTypesetter_(&rts); - rts.run = run; - rts.pos = pos; - rts.lineHeightReduction = lineHeightReduction; - rts.layoutWidth = d->size.x; - rts.indent = indent * gap_Text; - rts.rightMargin = rightMargin * gap_Text; - rts.isWordWrapped = isWordWrapped; - rts.isPreformat = isPreformat; - rts.fonts = fonts; + rts.run = run; + rts.pos = pos; + rts.fonts = fonts; + rts.isWordWrapped = isWordWrapped; + rts.isPreformat = isPreformat; + rts.layoutWidth = d->size.x; + rts.indent = indent * gap_Text; + rts.rightMargin = rightMargin * gap_Text; + if (!isMono) { + /* Upper-level headings are typeset a bit tighter. */ + if (type == heading1_GmLineType) { + rts.lineHeightReduction = 0.10f; + } + else if (type == heading2_GmLineType) { + rts.lineHeightReduction = 0.06f; + } + /* Visited links are never bold. */ + if (run.linkId && linkFlags_GmDocument(d, run.linkId) & visited_GmLinkFlag) { + rts.run.font = paragraph_FontId; + } + } iWrapText wrapText = { .text = runLine, .maxWidth = isWordWrapped ? d->size.x - run.bounds.pos.x - rts.indent - rts.rightMargin @@ -1520,9 +1519,25 @@ void redoLayout_GmDocument(iGmDocument *d) { doLayout_GmDocument_(d); } +static void markLinkRunsVisited_GmDocument_(iGmDocument *d, const iIntSet *linkIds) { + iForEach(Array, r, &d->layout) { + iGmRun *run = r.value; + if (run->linkId && !run->mediaId && contains_IntSet(linkIds, run->linkId)) { + if (run->font == bold_FontId) { + run->font = paragraph_FontId; + } + else if (run->flags & decoration_GmRunFlag) { + run->color = linkColor_GmDocument(d, run->linkId, icon_GmLinkPart); + } + } + } +} + iBool updateOpenURLs_GmDocument(iGmDocument *d) { iBool wasChanged = iFalse; updateOpenURLs_GmDocument_(d); + iIntSet linkIds; + init_IntSet(&linkIds); iForEach(PtrArray, i, &d->links) { iGmLink *link = i.ptr; if (!equal_String(&link->url, &d->url)) { @@ -1531,11 +1546,14 @@ iBool updateOpenURLs_GmDocument(iGmDocument *d) { iChangeFlags(link->flags, isOpen_GmLinkFlag, isOpen); if (isOpen) { link->flags |= visited_GmLinkFlag; + insert_IntSet(&linkIds, index_PtrArrayIterator(&i) + 1); } wasChanged = iTrue; } } } + markLinkRunsVisited_GmDocument_(d, &linkIds); + deinit_IntSet(&linkIds); return wasChanged; } @@ -1672,6 +1690,23 @@ void foldPre_GmDocument(iGmDocument *d, uint16_t preId) { } } +void updateVisitedLinks_GmDocument(iGmDocument *d) { + iIntSet linkIds; + init_IntSet(&linkIds); + iForEach(PtrArray, i, &d->links) { + iGmLink *link = i.ptr; + if (~link->flags & visited_GmLinkFlag) { + iTime visitTime = urlVisitTime_Visited(visited_App(), &link->url); + if (isValid_Time(&visitTime)) { + link->flags |= visited_GmLinkFlag; + insert_IntSet(&linkIds, index_PtrArrayIterator(&i) + 1); + } + } + } + markLinkRunsVisited_GmDocument_(d, &linkIds); + deinit_IntSet(&linkIds); +} + const iGmPreMeta *preMeta_GmDocument(const iGmDocument *d, uint16_t preId) { if (preId > 0 && preId <= size_Array(&d->preMeta)) { return constAt_Array(&d->preMeta, preId - 1); -- cgit v1.2.3