summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-09-17 07:24:23 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-09-17 07:24:23 +0300
commit115602cf34dfb2f151846673468a41f16712eb49 (patch)
treed6f4330d55799fdb18df2bcd5d96e2c04c8d51f5 /src
parenta48aa018640b2d631f318585da23e4ec7f8e8bdc (diff)
DocumentWidget: Permanent images
A dynamically generated page showing nothing but an image should not be treated the same way as an inline image. I.e., disallow hiding the image on an image page.
Diffstat (limited to 'src')
-rw-r--r--src/gmdocument.c18
-rw-r--r--src/gmdocument.h7
-rw-r--r--src/ui/documentwidget.c20
3 files changed, 34 insertions, 11 deletions
diff --git a/src/gmdocument.c b/src/gmdocument.c
index 723e3eaf..b2561ee0 100644
--- a/src/gmdocument.c
+++ b/src/gmdocument.c
@@ -64,11 +64,13 @@ struct Impl_GmImage {
64 size_t numBytes; 64 size_t numBytes;
65 iString mime; 65 iString mime;
66 iGmLinkId linkId; 66 iGmLinkId linkId;
67 iBool isPermanent;
67 SDL_Texture *texture; 68 SDL_Texture *texture;
68}; 69};
69 70
70void init_GmImage(iGmImage *d, const iBlock *data) { 71void init_GmImage(iGmImage *d, const iBlock *data) {
71 init_String(&d->mime); 72 init_String(&d->mime);
73 d->isPermanent = iFalse;
72 d->numBytes = size_Block(data); 74 d->numBytes = size_Block(data);
73 uint8_t *imgData = stbi_load_from_memory( 75 uint8_t *imgData = stbi_load_from_memory(
74 constData_Block(data), size_Block(data), &d->size.x, &d->size.y, NULL, 4); 76 constData_Block(data), size_Block(data), &d->size.x, &d->size.y, NULL, 4);
@@ -542,8 +544,14 @@ static void doLayout_GmDocument_(iGmDocument *d) {
542 if (type == link_GmLineType) { 544 if (type == link_GmLineType) {
543 const size_t imgIndex = findLinkImage_GmDocument_(d, run.linkId); 545 const size_t imgIndex = findLinkImage_GmDocument_(d, run.linkId);
544 if (imgIndex != iInvalidPos) { 546 if (imgIndex != iInvalidPos) {
545 ((iGmLink *) at_PtrArray(&d->links, run.linkId - 1))->flags |= content_GmLinkFlag;
546 const iGmImage *img = constAt_PtrArray(&d->images, imgIndex); 547 const iGmImage *img = constAt_PtrArray(&d->images, imgIndex);
548 /* Mark the link as having content. */ {
549 iGmLink *link = at_PtrArray(&d->links, run.linkId - 1);
550 link->flags |= content_GmLinkFlag;
551 if (img->isPermanent) {
552 link->flags |= permanent_GmLinkFlag;
553 }
554 }
547 const int margin = 0.5f * lineHeight_Text(paragraph_FontId); 555 const int margin = 0.5f * lineHeight_Text(paragraph_FontId);
548 pos.y += margin; 556 pos.y += margin;
549 run.bounds.pos = pos; 557 run.bounds.pos = pos;
@@ -952,7 +960,8 @@ void setSource_GmDocument(iGmDocument *d, const iString *source, int width, int
952 setWidth_GmDocument(d, width, forceBreakWidth); /* re-do layout */ 960 setWidth_GmDocument(d, width, forceBreakWidth); /* re-do layout */
953} 961}
954 962
955void setImage_GmDocument(iGmDocument *d, iGmLinkId linkId, const iString *mime, const iBlock *data) { 963void setImage_GmDocument(iGmDocument *d, iGmLinkId linkId, const iString *mime, const iBlock *data,
964 iBool allowHide) {
956 if (!mime || !data) { 965 if (!mime || !data) {
957 iGmImage *img; 966 iGmImage *img;
958 if (take_PtrArray(&d->images, findLinkImage_GmDocument_(d, linkId), (void **) &img)) { 967 if (take_PtrArray(&d->images, findLinkImage_GmDocument_(d, linkId), (void **) &img)) {
@@ -961,16 +970,17 @@ void setImage_GmDocument(iGmDocument *d, iGmLinkId linkId, const iString *mime,
961 } 970 }
962 else { 971 else {
963 /* TODO: check if we know this MIME type */ 972 /* TODO: check if we know this MIME type */
964 /* Load the image. */ { 973 /* Upload the image. */ {
965 iGmImage *img = new_GmImage(data); 974 iGmImage *img = new_GmImage(data);
966 img->linkId = linkId; /* TODO: use a hash? */ 975 img->linkId = linkId; /* TODO: use a hash? */
976 img->isPermanent = !allowHide;
967 set_String(&img->mime, mime); 977 set_String(&img->mime, mime);
968 if (img->texture) { 978 if (img->texture) {
969 pushBack_PtrArray(&d->images, img); 979 pushBack_PtrArray(&d->images, img);
970 } 980 }
971 else { 981 else {
972 delete_GmImage(img); 982 delete_GmImage(img);
973 } 983 }
974 } 984 }
975 } 985 }
976 doLayout_GmDocument_(d); 986 doLayout_GmDocument_(d);
diff --git a/src/gmdocument.h b/src/gmdocument.h
index 5e5f282e..23ce5e8a 100644
--- a/src/gmdocument.h
+++ b/src/gmdocument.h
@@ -44,13 +44,15 @@ enum iGmLinkFlags {
44 file_GmLinkFlag = iBit(4), 44 file_GmLinkFlag = iBit(4),
45 data_GmLinkFlag = iBit(5), 45 data_GmLinkFlag = iBit(5),
46 about_GmLinkFlag = iBit(6), 46 about_GmLinkFlag = iBit(6),
47 supportedProtocol_GmLinkFlag = 0x3f, 47 mailto_GmLinkFlag = iBit(7),
48 supportedProtocol_GmLinkFlag = 0xff,
48 remote_GmLinkFlag = iBit(9), 49 remote_GmLinkFlag = iBit(9),
49 userFriendly_GmLinkFlag = iBit(10), 50 userFriendly_GmLinkFlag = iBit(10),
50 imageFileExtension_GmLinkFlag = iBit(11), 51 imageFileExtension_GmLinkFlag = iBit(11),
51 audioFileExtension_GmLinkFlag = iBit(12), 52 audioFileExtension_GmLinkFlag = iBit(12),
52 content_GmLinkFlag = iBit(13), /* content visible below */ 53 content_GmLinkFlag = iBit(13), /* content visible below */
53 visited_GmLinkFlag = iBit(14), /* in the history */ 54 visited_GmLinkFlag = iBit(14), /* in the history */
55 permanent_GmLinkFlag = iBit(15), /* content cannot be dismissed; media link */
54}; 56};
55 57
56struct Impl_GmImageInfo { 58struct Impl_GmImageInfo {
@@ -98,7 +100,8 @@ void setFormat_GmDocument (iGmDocument *, enum iGmDocumentFormat format);
98void setWidth_GmDocument (iGmDocument *, int width, int forceBreakWidth); 100void setWidth_GmDocument (iGmDocument *, int width, int forceBreakWidth);
99void setUrl_GmDocument (iGmDocument *, const iString *url); 101void setUrl_GmDocument (iGmDocument *, const iString *url);
100void setSource_GmDocument (iGmDocument *, const iString *source, int width, int forceBreakWidth); 102void setSource_GmDocument (iGmDocument *, const iString *source, int width, int forceBreakWidth);
101void setImage_GmDocument (iGmDocument *, iGmLinkId linkId, const iString *mime, const iBlock *data); 103void setImage_GmDocument (iGmDocument *, iGmLinkId linkId, const iString *mime, const iBlock *data,
104 iBool allowHide);
102 105
103void reset_GmDocument (iGmDocument *); /* free images */ 106void reset_GmDocument (iGmDocument *); /* free images */
104 107
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index ab8af9b8..84ad1139 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -363,6 +363,10 @@ static void updateHover_DocumentWidget_(iDocumentWidget *d, iInt2 mouse) {
363 if (isHover_Widget(w) && !contains_Widget(constAs_Widget(d->scroll), mouse)) { 363 if (isHover_Widget(w) && !contains_Widget(constAs_Widget(d->scroll), mouse)) {
364 setCursor_Window(get_Window(), 364 setCursor_Window(get_Window(),
365 d->hoverLink ? SDL_SYSTEM_CURSOR_HAND : SDL_SYSTEM_CURSOR_IBEAM); 365 d->hoverLink ? SDL_SYSTEM_CURSOR_HAND : SDL_SYSTEM_CURSOR_IBEAM);
366 if (d->hoverLink &&
367 linkFlags_GmDocument(d->doc, d->hoverLink->linkId) & permanent_GmLinkFlag) {
368 setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_ARROW); /* not dismissable */
369 }
366 } 370 }
367} 371}
368 372
@@ -575,7 +579,7 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, const iGmResponse
575 } 579 }
576 format_String( 580 format_String(
577 &str, "=> %s %s\n", cstr_String(d->mod.url), imageTitle); 581 &str, "=> %s %s\n", cstr_String(d->mod.url), imageTitle);
578 setImage_GmDocument(d->doc, 1, mimeStr, &response->body); 582 setImage_GmDocument(d->doc, 1, mimeStr, &response->body, iFalse /* it's fixed */);
579 } 583 }
580 else { 584 else {
581 clear_String(&str); 585 clear_String(&str);
@@ -974,7 +978,7 @@ static iBool handleMediaCommand_DocumentWidget_(iDocumentWidget *d, const char *
974// cstr_String(meta_GmRequest(req->req))); 978// cstr_String(meta_GmRequest(req->req)));
975 if (startsWith_String(meta_GmRequest(req->req), "image/")) { 979 if (startsWith_String(meta_GmRequest(req->req), "image/")) {
976 setImage_GmDocument(d->doc, req->linkId, meta_GmRequest(req->req), 980 setImage_GmDocument(d->doc, req->linkId, meta_GmRequest(req->req),
977 body_GmRequest(req->req)); 981 body_GmRequest(req->req), iTrue);
978 updateVisible_DocumentWidget_(d); 982 updateVisible_DocumentWidget_(d);
979 invalidate_DocumentWidget_(d); 983 invalidate_DocumentWidget_(d);
980 refresh_Widget(as_Widget(d)); 984 refresh_Widget(as_Widget(d));
@@ -1489,10 +1493,16 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
1489 iAssert(linkId); 1493 iAssert(linkId);
1490 /* Media links are opened inline by default. */ 1494 /* Media links are opened inline by default. */
1491 if (isMediaLink_GmDocument(d->doc, linkId)) { 1495 if (isMediaLink_GmDocument(d->doc, linkId)) {
1496 const int linkFlags = linkFlags_GmDocument(d->doc, linkId);
1497 if (linkFlags & content_GmLinkFlag && linkFlags & permanent_GmLinkFlag) {
1498 /* We have the image and it cannot be dismissed, so nothing
1499 further to do. */
1500 return iTrue;
1501 }
1492 if (!requestMedia_DocumentWidget_(d, linkId)) { 1502 if (!requestMedia_DocumentWidget_(d, linkId)) {
1493 if (linkFlags_GmDocument(d->doc, linkId) & content_GmLinkFlag) { 1503 if (linkFlags & content_GmLinkFlag) {
1494 /* Dismiss shown content on click. */ 1504 /* Dismiss shown content on click. */
1495 setImage_GmDocument(d->doc, linkId, NULL, NULL); 1505 setImage_GmDocument(d->doc, linkId, NULL, NULL, iTrue);
1496 d->hoverLink = NULL; 1506 d->hoverLink = NULL;
1497 scroll_DocumentWidget_(d, 0); 1507 scroll_DocumentWidget_(d, 0);
1498 updateVisible_DocumentWidget_(d); 1508 updateVisible_DocumentWidget_(d);
@@ -1505,7 +1515,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
1505 iMediaRequest *req = findMediaRequest_DocumentWidget_(d, linkId); 1515 iMediaRequest *req = findMediaRequest_DocumentWidget_(d, linkId);
1506 if (req) { 1516 if (req) {
1507 setImage_GmDocument(d->doc, linkId, meta_GmRequest(req->req), 1517 setImage_GmDocument(d->doc, linkId, meta_GmRequest(req->req),
1508 body_GmRequest(req->req)); 1518 body_GmRequest(req->req), iTrue);
1509 updateVisible_DocumentWidget_(d); 1519 updateVisible_DocumentWidget_(d);
1510 invalidate_DocumentWidget_(d); 1520 invalidate_DocumentWidget_(d);
1511 refresh_Widget(w); 1521 refresh_Widget(w);