diff options
-rw-r--r-- | src/gmdocument.c | 81 | ||||
-rw-r--r-- | src/gmdocument.h | 6 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 6 |
3 files changed, 68 insertions, 25 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 | ||
1522 | static 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 | |||
1523 | iBool updateOpenURLs_GmDocument(iGmDocument *d) { | 1536 | iBool 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 | ||
1693 | void 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 | |||
1675 | const iGmPreMeta *preMeta_GmDocument(const iGmDocument *d, uint16_t preId) { | 1710 | const 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); |
diff --git a/src/gmdocument.h b/src/gmdocument.h index 831459d8..0d50e6ad 100644 --- a/src/gmdocument.h +++ b/src/gmdocument.h | |||
@@ -170,8 +170,10 @@ void setUrl_GmDocument (iGmDocument *, const iString *url); | |||
170 | void setSource_GmDocument (iGmDocument *, const iString *source, int width, | 170 | void setSource_GmDocument (iGmDocument *, const iString *source, int width, |
171 | enum iGmDocumentUpdate updateType); | 171 | enum iGmDocumentUpdate updateType); |
172 | void foldPre_GmDocument (iGmDocument *, uint16_t preId); | 172 | void foldPre_GmDocument (iGmDocument *, uint16_t preId); |
173 | void invalidatePalette_GmDocument(iGmDocument *); | 173 | |
174 | void makePaletteGlobal_GmDocument(const iGmDocument *); /* copies document colors to the global palette */ | 174 | void updateVisitedLinks_GmDocument (iGmDocument *); /* check all links for visited status */ |
175 | void invalidatePalette_GmDocument (iGmDocument *); | ||
176 | void makePaletteGlobal_GmDocument (const iGmDocument *); /* copies document colors to the global palette */ | ||
175 | 177 | ||
176 | //void reset_GmDocument (iGmDocument *); /* free images */ | 178 | //void reset_GmDocument (iGmDocument *); /* free images */ |
177 | 179 | ||
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index b59233c7..6524d454 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -1029,6 +1029,7 @@ static void showOrHidePinningIndicator_DocumentWidget_(iDocumentWidget *d) { | |||
1029 | } | 1029 | } |
1030 | 1030 | ||
1031 | static void documentWasChanged_DocumentWidget_(iDocumentWidget *d) { | 1031 | static void documentWasChanged_DocumentWidget_(iDocumentWidget *d) { |
1032 | updateVisitedLinks_GmDocument(d->doc); | ||
1032 | documentRunsInvalidated_DocumentWidget_(d); | 1033 | documentRunsInvalidated_DocumentWidget_(d); |
1033 | updateWindowTitle_DocumentWidget_(d); | 1034 | updateWindowTitle_DocumentWidget_(d); |
1034 | updateVisible_DocumentWidget_(d); | 1035 | updateVisible_DocumentWidget_(d); |
@@ -2417,6 +2418,11 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
2417 | } | 2418 | } |
2418 | return iFalse; | 2419 | return iFalse; |
2419 | } | 2420 | } |
2421 | if (equal_Command(cmd, "visited.changed")) { | ||
2422 | updateVisitedLinks_GmDocument(d->doc); | ||
2423 | invalidateVisibleLinks_DocumentWidget_(d); | ||
2424 | return iFalse; | ||
2425 | } | ||
2420 | if (equal_Command(cmd, "document.render")) /* `Periodic` makes direct dispatch to here */ { | 2426 | if (equal_Command(cmd, "document.render")) /* `Periodic` makes direct dispatch to here */ { |
2421 | // printf("%u: document.render\n", SDL_GetTicks()); | 2427 | // printf("%u: document.render\n", SDL_GetTicks()); |
2422 | if (SDL_GetTicks() - d->drawBufs->lastRenderTime > 150) { | 2428 | if (SDL_GetTicks() - d->drawBufs->lastRenderTime > 150) { |