summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);