diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-05-02 17:36:21 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-05-02 17:36:21 +0300 |
commit | 7584277f59646fb38c80242a2503176e073be367 (patch) | |
tree | 410d5f25b1a76c277f6f437be55f00b3d0069b8c /src | |
parent | d6d3cfd9c1a16172bdcb8cbe8e09e77212f7094c (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.c | 29 | ||||
-rw-r--r-- | src/gempub.h | 5 | ||||
-rw-r--r-- | src/mimehooks.c | 4 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 67 |
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 | ||
165 | iBlock *coverPageSource_Gempub(const iGempub *d) { | 166 | iString *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 | |
211 | iBool 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 | ||
27 | iDeclareType(GmDocument) | ||
28 | |||
27 | iDeclareType(Gempub) | 29 | iDeclareType(Gempub) |
28 | iDeclareTypeConstruction(Gempub) | 30 | iDeclareTypeConstruction(Gempub) |
29 | 31 | ||
@@ -51,7 +53,8 @@ void close_Gempub (iGempub *); | |||
51 | void setBaseUrl_Gempub (iGempub *, const iString *baseUrl); | 53 | void setBaseUrl_Gempub (iGempub *, const iString *baseUrl); |
52 | 54 | ||
53 | iBool isOpen_Gempub (const iGempub *); | 55 | iBool isOpen_Gempub (const iGempub *); |
54 | iBlock * coverPageSource_Gempub (const iGempub *); | 56 | iString * coverPageSource_Gempub (const iGempub *); |
57 | iBool preloadCoverImage_Gempub(const iGempub *, iGmDocument *doc); | ||
55 | 58 | ||
56 | const iString *property_Gempub (const iGempub *, enum iGempubProperty); | 59 | const 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 | ||
1069 | static void postProcessRequestContent_DocumentWidget_(iDocumentWidget *d) { | 1072 | static 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; |