summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-05-02 17:36:21 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-05-02 17:36:21 +0300
commit7584277f59646fb38c80242a2503176e073be367 (patch)
tree410d5f25b1a76c277f6f437be55f00b3d0069b8c /src
parentd6d3cfd9c1a16172bdcb8cbe8e09e77212f7094c (diff)
DocumentWidget: Retain Gempub data; cleanup
Keep hold of the `Gempub` data while the page is open so it can be used for other purposes.
Diffstat (limited to 'src')
-rw-r--r--src/gempub.c29
-rw-r--r--src/gempub.h5
-rw-r--r--src/mimehooks.c4
-rw-r--r--src/ui/documentwidget.c67
4 files changed, 65 insertions, 40 deletions
diff --git a/src/gempub.c b/src/gempub.c
index 45a4c1b3..448349c8 100644
--- a/src/gempub.c
+++ b/src/gempub.c
@@ -24,6 +24,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
24#include "gmutil.h" 24#include "gmutil.h"
25#include "lang.h" 25#include "lang.h"
26#include "defs.h" 26#include "defs.h"
27#include "gmdocument.h"
27#include "ui/util.h" 28#include "ui/util.h"
28 29
29#include <the_Foundation/archive.h> 30#include <the_Foundation/archive.h>
@@ -162,7 +163,7 @@ static iBool isRemote_Gempub_(const iGempub *d) {
162 return !equalCase_Rangecc(urlScheme_String(&d->baseUrl), "file"); 163 return !equalCase_Rangecc(urlScheme_String(&d->baseUrl), "file");
163} 164}
164 165
165iBlock *coverPageSource_Gempub(const iGempub *d) { 166iString *coverPageSource_Gempub(const iGempub *d) {
166 iAssert(!isEmpty_String(&d->baseUrl)); 167 iAssert(!isEmpty_String(&d->baseUrl));
167 const iString *baseUrl = withSpacesEncoded_String(&d->baseUrl); 168 const iString *baseUrl = withSpacesEncoded_String(&d->baseUrl);
168 iString *out = new_String(); 169 iString *out = new_String();
@@ -204,7 +205,27 @@ iBlock *coverPageSource_Gempub(const iGempub *d) {
204 appendProperty_Gempub_(d, "Language:", language_GempubProperty, out); 205 appendProperty_Gempub_(d, "Language:", language_GempubProperty, out);
205 appendProperty_Gempub_(d, "License:", license_GempubProperty, out); 206 appendProperty_Gempub_(d, "License:", license_GempubProperty, out);
206 appendProperty_Gempub_(d, "\u00a9", copyright_GempubProperty, out); 207 appendProperty_Gempub_(d, "\u00a9", copyright_GempubProperty, out);
207 iBlock *output = copy_Block(utf8_String(out)); 208 return out;
208 delete_String(out); 209}
209 return output; 210
211iBool preloadCoverImage_Gempub(const iGempub *d, iGmDocument *doc) {
212 iBool haveImage = iFalse;
213 for (size_t linkId = 1; ; linkId++) {
214 const iString *linkUrl = linkUrl_GmDocument(doc, linkId);
215 if (!linkUrl) break;
216 if (findLinkImage_Media(media_GmDocument(doc), linkId)) {
217 continue; /* got this already */
218 }
219 if (linkFlags_GmDocument(doc, linkId) & imageFileExtension_GmLinkFlag) {
220 iString *imgEntryPath = collect_String(copy_String(linkUrl));
221 remove_Block(&imgEntryPath->chars, 0, size_String(&d->baseUrl) + 1 /* slash, too */);
222 setData_Media(media_GmDocument(doc),
223 linkId,
224 collectNewCStr_String(mediaType_Path(linkUrl)),
225 data_Archive(d->arch, imgEntryPath),
226 0);
227 haveImage = iTrue;
228 }
229 }
230 return haveImage;
210} 231}
diff --git a/src/gempub.h b/src/gempub.h
index 41d14824..6c1103de 100644
--- a/src/gempub.h
+++ b/src/gempub.h
@@ -24,6 +24,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
24 24
25#include <the_Foundation/string.h> 25#include <the_Foundation/string.h>
26 26
27iDeclareType(GmDocument)
28
27iDeclareType(Gempub) 29iDeclareType(Gempub)
28iDeclareTypeConstruction(Gempub) 30iDeclareTypeConstruction(Gempub)
29 31
@@ -51,7 +53,8 @@ void close_Gempub (iGempub *);
51void setBaseUrl_Gempub (iGempub *, const iString *baseUrl); 53void setBaseUrl_Gempub (iGempub *, const iString *baseUrl);
52 54
53iBool isOpen_Gempub (const iGempub *); 55iBool isOpen_Gempub (const iGempub *);
54iBlock * coverPageSource_Gempub (const iGempub *); 56iString * coverPageSource_Gempub (const iGempub *);
57iBool preloadCoverImage_Gempub(const iGempub *, iGmDocument *doc);
55 58
56const iString *property_Gempub (const iGempub *, enum iGempubProperty); 59const iString *property_Gempub (const iGempub *, enum iGempubProperty);
57 60
diff --git a/src/mimehooks.c b/src/mimehooks.c
index 364449ec..4788d534 100644
--- a/src/mimehooks.c
+++ b/src/mimehooks.c
@@ -209,7 +209,9 @@ iBlock *translateGemPubCoverPage_(const iBlock *source, const iString *requestUr
209 if (open_Gempub(gempub, source)) { 209 if (open_Gempub(gempub, source)) {
210 setBaseUrl_Gempub(gempub, requestUrl); 210 setBaseUrl_Gempub(gempub, requestUrl);
211 output = newCStr_Block("20 text/gemini; charset=utf-8\r\n"); 211 output = newCStr_Block("20 text/gemini; charset=utf-8\r\n");
212 append_Block(output, collect_Block(coverPageSource_Gempub(gempub))); 212 iString *src = coverPageSource_Gempub(gempub);
213 append_Block(output, utf8_String(src));
214 delete_String(src);
213 } 215 }
214 delete_Gempub(gempub); 216 delete_Gempub(gempub);
215 return output; 217 return output;
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index b3dd2e83..290bf95e 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -244,6 +244,7 @@ struct Impl_DocumentWidget {
244 iString sourceMime; 244 iString sourceMime;
245 iBlock sourceContent; /* original content as received, for saving */ 245 iBlock sourceContent; /* original content as received, for saving */
246 iTime sourceTime; 246 iTime sourceTime;
247 iGempub * sourceGempub; /* NULL unless the page is Gempub content */
247 iGmDocument * doc; 248 iGmDocument * doc;
248 int certFlags; 249 int certFlags;
249 iBlock * certFingerprint; 250 iBlock * certFingerprint;
@@ -346,6 +347,7 @@ void init_DocumentWidget(iDocumentWidget *d) {
346 init_String(&d->sourceMime); 347 init_String(&d->sourceMime);
347 init_Block(&d->sourceContent, 0); 348 init_Block(&d->sourceContent, 0);
348 iZap(d->sourceTime); 349 iZap(d->sourceTime);
350 d->sourceGempub = NULL;
349 init_PtrArray(&d->visibleLinks); 351 init_PtrArray(&d->visibleLinks);
350 init_PtrArray(&d->visiblePre); 352 init_PtrArray(&d->visiblePre);
351 init_PtrArray(&d->visibleWideRuns); 353 init_PtrArray(&d->visibleWideRuns);
@@ -387,6 +389,7 @@ void deinit_DocumentWidget(iDocumentWidget *d) {
387 delete_PtrSet(d->invalidRuns); 389 delete_PtrSet(d->invalidRuns);
388 iRelease(d->media); 390 iRelease(d->media);
389 iRelease(d->request); 391 iRelease(d->request);
392 delete_Gempub(d->sourceGempub);
390 deinit_String(&d->pendingGotoHeading); 393 deinit_String(&d->pendingGotoHeading);
391 deinit_Block(&d->sourceContent); 394 deinit_Block(&d->sourceContent);
392 deinit_String(&d->sourceMime); 395 deinit_String(&d->sourceMime);
@@ -1067,51 +1070,43 @@ static const char *zipPageHeading_(const iRangecc mime) {
1067} 1070}
1068 1071
1069static void postProcessRequestContent_DocumentWidget_(iDocumentWidget *d) { 1072static void postProcessRequestContent_DocumentWidget_(iDocumentWidget *d) {
1073 delete_Gempub(d->sourceGempub);
1074 d->sourceGempub = NULL;
1070 if (!cmpCase_String(&d->sourceMime, "application/octet-stream") || 1075 if (!cmpCase_String(&d->sourceMime, "application/octet-stream") ||
1071 !cmpCase_String(&d->sourceMime, mimeType_Gempub) || 1076 !cmpCase_String(&d->sourceMime, mimeType_Gempub) ||
1072 endsWithCase_String(d->mod.url, ".gpub")) { 1077 endsWithCase_String(d->mod.url, ".gpub")) {
1073 iGempub *gempub = new_Gempub(); 1078 iGempub *gempub = new_Gempub();
1074 if (open_Gempub(gempub, &d->sourceContent)) { 1079 if (open_Gempub(gempub, &d->sourceContent)) {
1075 setBaseUrl_Gempub(gempub, d->mod.url); 1080 setBaseUrl_Gempub(gempub, d->mod.url);
1076 /* TODO: just return a String from coverPageSource_Gempub... */ 1081 setSource_DocumentWidget(d, collect_String(coverPageSource_Gempub(gempub)));
1077 setSource_DocumentWidget(d, collect_String(newBlock_String(collect_Block(coverPageSource_Gempub(gempub)))));
1078 setCStr_String(&d->sourceMime, mimeType_Gempub); 1082 setCStr_String(&d->sourceMime, mimeType_Gempub);
1083 d->sourceGempub = gempub;
1084 }
1085 else {
1086 delete_Gempub(gempub);
1079 } 1087 }
1080 delete_Gempub(gempub);
1081 } 1088 }
1082 /* Gempub: Preload cover image. */ { 1089 if (!d->sourceGempub) {
1083 /* TODO: move to gempub.c along with other related code */
1084 iString *localPath = localFilePathFromUrl_String(d->mod.url); 1090 iString *localPath = localFilePathFromUrl_String(d->mod.url);
1085 if (localPath) { 1091 if (localPath && equal_CStr(mediaType_Path(localPath), "application/gpub+zip")) {
1086 if (!iCmpStr(mediaType_Path(localPath), "application/gpub+zip")) { 1092 iGempub *gempub = new_Gempub();
1087 iArchive *arch = iClob(new_Archive()); 1093 if (openFile_Gempub(gempub, localPath)) {
1088 if (openFile_Archive(arch, localPath)) { 1094 setBaseUrl_Gempub(gempub, d->mod.url);
1089 iBool haveImage = iFalse; 1095 setSource_DocumentWidget(d, collect_String(coverPageSource_Gempub(gempub)));
1090 for (size_t linkId = 1; ; linkId++) { 1096 setCStr_String(&d->sourceMime, mimeType_Gempub);
1091 const iString *linkUrl = linkUrl_GmDocument(d->doc, linkId); 1097 d->sourceGempub = gempub;
1092 if (!linkUrl) break;
1093 if (findLinkImage_Media(media_GmDocument(d->doc), linkId)) {
1094 continue; /* got this already */
1095 }
1096 if (linkFlags_GmDocument(d->doc, linkId) & imageFileExtension_GmLinkFlag) {
1097 iString *imgEntryPath = collect_String(localFilePathFromUrl_String(linkUrl));
1098 remove_Block(&imgEntryPath->chars, 0, size_String(localPath) + 1 /* slash, too */);
1099 setData_Media(media_GmDocument(d->doc),
1100 linkId,
1101 collectNewCStr_String(mediaType_Path(linkUrl)),
1102 data_Archive(arch, imgEntryPath),
1103 0);
1104 haveImage = iTrue;
1105 }
1106 }
1107 if (haveImage) {
1108 redoLayout_GmDocument(d->doc);
1109 updateVisible_DocumentWidget_(d);
1110 invalidate_DocumentWidget_(d);
1111 }
1112 }
1113 } 1098 }
1114 delete_String(localPath); 1099 else {
1100 delete_Gempub(gempub);
1101 }
1102 }
1103 delete_String(localPath);
1104 }
1105 if (d->sourceGempub) {
1106 if (preloadCoverImage_Gempub(d->sourceGempub, d->doc)) {
1107 redoLayout_GmDocument(d->doc);
1108 updateVisible_DocumentWidget_(d);
1109 invalidate_DocumentWidget_(d);
1115 } 1110 }
1116 } 1111 }
1117} 1112}
@@ -1325,6 +1320,8 @@ static iBool updateFromHistory_DocumentWidget_(iDocumentWidget *d) {
1325 if (recent && recent->cachedResponse) { 1320 if (recent && recent->cachedResponse) {
1326 const iGmResponse *resp = recent->cachedResponse; 1321 const iGmResponse *resp = recent->cachedResponse;
1327 clear_ObjectList(d->media); 1322 clear_ObjectList(d->media);
1323 delete_Gempub(d->sourceGempub);
1324 d->sourceGempub = NULL;
1328 reset_GmDocument(d->doc); 1325 reset_GmDocument(d->doc);
1329 resetWideRuns_DocumentWidget_(d); 1326 resetWideRuns_DocumentWidget_(d);
1330 d->state = fetching_RequestState; 1327 d->state = fetching_RequestState;
@@ -1527,6 +1524,8 @@ static void checkResponse_DocumentWidget_(iDocumentWidget *d) {
1527 case categorySuccess_GmStatusCode: 1524 case categorySuccess_GmStatusCode:
1528 reset_SmoothScroll(&d->scrollY); 1525 reset_SmoothScroll(&d->scrollY);
1529 reset_GmDocument(d->doc); /* new content incoming */ 1526 reset_GmDocument(d->doc); /* new content incoming */
1527 delete_Gempub(d->sourceGempub);
1528 d->sourceGempub = NULL;
1530 resetWideRuns_DocumentWidget_(d); 1529 resetWideRuns_DocumentWidget_(d);
1531 updateDocument_DocumentWidget_(d, resp, iTrue); 1530 updateDocument_DocumentWidget_(d, resp, iTrue);
1532 break; 1531 break;