summaryrefslogtreecommitdiff
path: root/src/gmdocument.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-07-12 12:47:41 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-07-12 12:47:41 +0300
commitfe5c564a6d0b99223b2ad56e1856f651a49f2f46 (patch)
treeb93ba8ee2ff9c205242b411744836afc96bcaf25 /src/gmdocument.c
parentaea927e6932fd2ef415b1f592d1c7a137ee0511f (diff)
Update link visited status when navigating
When an URL is visited, ensure that links to that URL update their visual state.
Diffstat (limited to 'src/gmdocument.c')
-rw-r--r--src/gmdocument.c81
1 files changed, 58 insertions, 23 deletions
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. */
33#include "app.h" 33#include "app.h"
34#include "defs.h" 34#include "defs.h"
35 35
36#include <the_Foundation/intset.h>
36#include <the_Foundation/ptrarray.h> 37#include <the_Foundation/ptrarray.h>
37#include <the_Foundation/regexp.h> 38#include <the_Foundation/regexp.h>
38#include <the_Foundation/stringset.h> 39#include <the_Foundation/stringset.h>
@@ -799,33 +800,31 @@ static void doLayout_GmDocument_(iGmDocument *d) {
799 meta->flags |= topLeft_GmPreMetaFlag; 800 meta->flags |= topLeft_GmPreMetaFlag;
800 } 801 }
801 } 802 }
802 float lineHeightReduction = 0.0f;
803 if (!isMono) {
804 /* Upper-level headings are typeset a bit tighter. */
805 if (type == heading1_GmLineType) {
806 lineHeightReduction = 0.10f;
807 }
808 else if (type == heading2_GmLineType) {
809 lineHeightReduction = 0.06f;
810 }
811 /* Visited links are never bold. */
812 if (run.linkId && linkFlags_GmDocument(d, run.linkId) & visited_GmLinkFlag) {
813 run.font = paragraph_FontId;
814 }
815 }
816 iAssert(!isEmpty_Range(&runLine)); /* must have something at this point */ 803 iAssert(!isEmpty_Range(&runLine)); /* must have something at this point */
817 /* Typeset the paragraph. */ { 804 /* Typeset the paragraph. */ {
818 iRunTypesetter rts; 805 iRunTypesetter rts;
819 init_RunTypesetter_(&rts); 806 init_RunTypesetter_(&rts);
820 rts.run = run; 807 rts.run = run;
821 rts.pos = pos; 808 rts.pos = pos;
822 rts.lineHeightReduction = lineHeightReduction; 809 rts.fonts = fonts;
823 rts.layoutWidth = d->size.x; 810 rts.isWordWrapped = isWordWrapped;
824 rts.indent = indent * gap_Text; 811 rts.isPreformat = isPreformat;
825 rts.rightMargin = rightMargin * gap_Text; 812 rts.layoutWidth = d->size.x;
826 rts.isWordWrapped = isWordWrapped; 813 rts.indent = indent * gap_Text;
827 rts.isPreformat = isPreformat; 814 rts.rightMargin = rightMargin * gap_Text;
828 rts.fonts = fonts; 815 if (!isMono) {
816 /* Upper-level headings are typeset a bit tighter. */
817 if (type == heading1_GmLineType) {
818 rts.lineHeightReduction = 0.10f;
819 }
820 else if (type == heading2_GmLineType) {
821 rts.lineHeightReduction = 0.06f;
822 }
823 /* Visited links are never bold. */
824 if (run.linkId && linkFlags_GmDocument(d, run.linkId) & visited_GmLinkFlag) {
825 rts.run.font = paragraph_FontId;
826 }
827 }
829 iWrapText wrapText = { .text = runLine, 828 iWrapText wrapText = { .text = runLine,
830 .maxWidth = isWordWrapped ? d->size.x - run.bounds.pos.x - 829 .maxWidth = isWordWrapped ? d->size.x - run.bounds.pos.x -
831 rts.indent - rts.rightMargin 830 rts.indent - rts.rightMargin
@@ -1520,9 +1519,25 @@ void redoLayout_GmDocument(iGmDocument *d) {
1520 doLayout_GmDocument_(d); 1519 doLayout_GmDocument_(d);
1521} 1520}
1522 1521
1522static void markLinkRunsVisited_GmDocument_(iGmDocument *d, const iIntSet *linkIds) {
1523 iForEach(Array, r, &d->layout) {
1524 iGmRun *run = r.value;
1525 if (run->linkId && !run->mediaId && contains_IntSet(linkIds, run->linkId)) {
1526 if (run->font == bold_FontId) {
1527 run->font = paragraph_FontId;
1528 }
1529 else if (run->flags & decoration_GmRunFlag) {
1530 run->color = linkColor_GmDocument(d, run->linkId, icon_GmLinkPart);
1531 }
1532 }
1533 }
1534}
1535
1523iBool updateOpenURLs_GmDocument(iGmDocument *d) { 1536iBool updateOpenURLs_GmDocument(iGmDocument *d) {
1524 iBool wasChanged = iFalse; 1537 iBool wasChanged = iFalse;
1525 updateOpenURLs_GmDocument_(d); 1538 updateOpenURLs_GmDocument_(d);
1539 iIntSet linkIds;
1540 init_IntSet(&linkIds);
1526 iForEach(PtrArray, i, &d->links) { 1541 iForEach(PtrArray, i, &d->links) {
1527 iGmLink *link = i.ptr; 1542 iGmLink *link = i.ptr;
1528 if (!equal_String(&link->url, &d->url)) { 1543 if (!equal_String(&link->url, &d->url)) {
@@ -1531,11 +1546,14 @@ iBool updateOpenURLs_GmDocument(iGmDocument *d) {
1531 iChangeFlags(link->flags, isOpen_GmLinkFlag, isOpen); 1546 iChangeFlags(link->flags, isOpen_GmLinkFlag, isOpen);
1532 if (isOpen) { 1547 if (isOpen) {
1533 link->flags |= visited_GmLinkFlag; 1548 link->flags |= visited_GmLinkFlag;
1549 insert_IntSet(&linkIds, index_PtrArrayIterator(&i) + 1);
1534 } 1550 }
1535 wasChanged = iTrue; 1551 wasChanged = iTrue;
1536 } 1552 }
1537 } 1553 }
1538 } 1554 }
1555 markLinkRunsVisited_GmDocument_(d, &linkIds);
1556 deinit_IntSet(&linkIds);
1539 return wasChanged; 1557 return wasChanged;
1540} 1558}
1541 1559
@@ -1672,6 +1690,23 @@ void foldPre_GmDocument(iGmDocument *d, uint16_t preId) {
1672 } 1690 }
1673} 1691}
1674 1692
1693void updateVisitedLinks_GmDocument(iGmDocument *d) {
1694 iIntSet linkIds;
1695 init_IntSet(&linkIds);
1696 iForEach(PtrArray, i, &d->links) {
1697 iGmLink *link = i.ptr;
1698 if (~link->flags & visited_GmLinkFlag) {
1699 iTime visitTime = urlVisitTime_Visited(visited_App(), &link->url);
1700 if (isValid_Time(&visitTime)) {
1701 link->flags |= visited_GmLinkFlag;
1702 insert_IntSet(&linkIds, index_PtrArrayIterator(&i) + 1);
1703 }
1704 }
1705 }
1706 markLinkRunsVisited_GmDocument_(d, &linkIds);
1707 deinit_IntSet(&linkIds);
1708}
1709
1675const iGmPreMeta *preMeta_GmDocument(const iGmDocument *d, uint16_t preId) { 1710const iGmPreMeta *preMeta_GmDocument(const iGmDocument *d, uint16_t preId) {
1676 if (preId > 0 && preId <= size_Array(&d->preMeta)) { 1711 if (preId > 0 && preId <= size_Array(&d->preMeta)) {
1677 return constAt_Array(&d->preMeta, preId - 1); 1712 return constAt_Array(&d->preMeta, preId - 1);