diff options
-rw-r--r-- | src/defs.h | 2 | ||||
-rw-r--r-- | src/gempub.c | 37 | ||||
-rw-r--r-- | src/gempub.h | 4 | ||||
-rw-r--r-- | src/gmdocument.c | 3 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 80 |
5 files changed, 122 insertions, 4 deletions
@@ -36,6 +36,8 @@ enum iFileVersion { | |||
36 | 36 | ||
37 | /* Icons */ | 37 | /* Icons */ |
38 | 38 | ||
39 | #define rightArrowhead_Icon "\u27a4" | ||
40 | #define leftArrowhead_Icon "\u27a4" | ||
39 | #define warning_Icon "\u26a0" | 41 | #define warning_Icon "\u26a0" |
40 | #define openLock_Icon "\U0001f513" | 42 | #define openLock_Icon "\U0001f513" |
41 | #define closedLock_Icon "\U0001f512" | 43 | #define closedLock_Icon "\U0001f512" |
diff --git a/src/gempub.c b/src/gempub.c index aa03d835..f3021add 100644 --- a/src/gempub.c +++ b/src/gempub.c | |||
@@ -213,6 +213,10 @@ iBool isOpen_Gempub(const iGempub *d) { | |||
213 | return d->arch != NULL; | 213 | return d->arch != NULL; |
214 | } | 214 | } |
215 | 215 | ||
216 | const iString *property_Gempub(const iGempub *d, enum iGempubProperty prop) { | ||
217 | return &d->props[prop]; | ||
218 | } | ||
219 | |||
216 | const iString *coverPageUrl_Gempub(const iGempub *d) { | 220 | const iString *coverPageUrl_Gempub(const iGempub *d) { |
217 | return &d->baseUrl; | 221 | return &d->baseUrl; |
218 | } | 222 | } |
@@ -232,6 +236,39 @@ const iString *navStartLinkUrl_Gempub(const iGempub *d) { | |||
232 | return &((const iGempubNavLink *) constFront_Array(d->navLinks))->url; | 236 | return &((const iGempubNavLink *) constFront_Array(d->navLinks))->url; |
233 | } | 237 | } |
234 | 238 | ||
239 | size_t navSize_Gempub(const iGempub *d) { | ||
240 | parseNavigationLinks_Gempub_(d); | ||
241 | return size_Array(d->navLinks); | ||
242 | } | ||
243 | |||
244 | size_t navIndex_Gempub(const iGempub *d, const iString *url) { | ||
245 | parseNavigationLinks_Gempub_(d); | ||
246 | const iString *normUrl = withSpacesEncoded_String(url); | ||
247 | iConstForEach(Array, i, d->navLinks) { | ||
248 | const iGempubNavLink *nav = i.value; | ||
249 | if (equalCase_String(&nav->url, normUrl)) { | ||
250 | return index_ArrayConstIterator(&i); | ||
251 | } | ||
252 | } | ||
253 | return iInvalidPos; | ||
254 | } | ||
255 | |||
256 | const iString *navLinkUrl_Gempub(const iGempub *d, size_t index) { | ||
257 | parseNavigationLinks_Gempub_(d); | ||
258 | if (index < size_Array(d->navLinks)) { | ||
259 | return &constValue_Array(d->navLinks, index, iGempubNavLink).url; | ||
260 | } | ||
261 | return NULL; | ||
262 | } | ||
263 | |||
264 | const iString *navLinkLabel_Gempub(const iGempub *d, size_t index) { | ||
265 | parseNavigationLinks_Gempub_(d); | ||
266 | if (index < size_Array(d->navLinks)) { | ||
267 | return &constValue_Array(d->navLinks, index, iGempubNavLink).label; | ||
268 | } | ||
269 | return NULL; | ||
270 | } | ||
271 | |||
235 | static iBool hasProperty_Gempub_(const iGempub *d, enum iGempubProperty prop) { | 272 | static iBool hasProperty_Gempub_(const iGempub *d, enum iGempubProperty prop) { |
236 | return !isEmpty_String(&d->props[prop]); | 273 | return !isEmpty_String(&d->props[prop]); |
237 | } | 274 | } |
diff --git a/src/gempub.h b/src/gempub.h index 6912bcc9..c03cabe6 100644 --- a/src/gempub.h +++ b/src/gempub.h | |||
@@ -60,5 +60,9 @@ const iString * property_Gempub (const iGempub *, enum iGempubProperty); | |||
60 | const iString * coverPageUrl_Gempub (const iGempub *); | 60 | const iString * coverPageUrl_Gempub (const iGempub *); |
61 | const iString * indexPageUrl_Gempub (const iGempub *); | 61 | const iString * indexPageUrl_Gempub (const iGempub *); |
62 | const iString * navStartLinkUrl_Gempub (const iGempub *); /* for convenience */ | 62 | const iString * navStartLinkUrl_Gempub (const iGempub *); /* for convenience */ |
63 | size_t navSize_Gempub (const iGempub *); | ||
64 | size_t navIndex_Gempub (const iGempub *, const iString *url); | ||
65 | const iString * navLinkUrl_Gempub (const iGempub *, size_t index); | ||
66 | const iString * navLinkLabel_Gempub (const iGempub *, size_t index); | ||
63 | 67 | ||
64 | extern const char *mimeType_Gempub; | 68 | extern const char *mimeType_Gempub; |
diff --git a/src/gmdocument.c b/src/gmdocument.c index ec406a63..ad8616a3 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
30 | #include "visited.h" | 30 | #include "visited.h" |
31 | #include "bookmarks.h" | 31 | #include "bookmarks.h" |
32 | #include "app.h" | 32 | #include "app.h" |
33 | #include "defs.h" | ||
33 | 34 | ||
34 | #include <the_Foundation/ptrarray.h> | 35 | #include <the_Foundation/ptrarray.h> |
35 | #include <the_Foundation/regexp.h> | 36 | #include <the_Foundation/regexp.h> |
@@ -400,7 +401,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
400 | static const float bottomMargin[max_GmLineType] = { | 401 | static const float bottomMargin[max_GmLineType] = { |
401 | 0.0f, 0.333f, 1.0f, 0.5f, 0.5f, 0.5f, 0.5f, 0.25f | 402 | 0.0f, 0.333f, 1.0f, 0.5f, 0.5f, 0.5f, 0.5f, 0.25f |
402 | }; | 403 | }; |
403 | static const char *arrow = "\u27a4"; | 404 | static const char *arrow = rightArrowhead_Icon; |
404 | static const char *envelope = "\U0001f4e7"; | 405 | static const char *envelope = "\U0001f4e7"; |
405 | static const char *bullet = "\u2022"; | 406 | static const char *bullet = "\u2022"; |
406 | static const char *folder = "\U0001f4c1"; | 407 | static const char *folder = "\U0001f4c1"; |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index f354623e..c8aad02b 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -1222,15 +1222,89 @@ static void postProcessRequestContent_DocumentWidget_(iDocumentWidget *d, iBool | |||
1222 | } | 1222 | } |
1223 | if (d->sourceGempub) { | 1223 | if (d->sourceGempub) { |
1224 | if (equal_String(d->mod.url, coverPageUrl_Gempub(d->sourceGempub))) { | 1224 | if (equal_String(d->mod.url, coverPageUrl_Gempub(d->sourceGempub))) { |
1225 | makeFooterButtons_DocumentWidget_(d, (iMenuItem[]){ | 1225 | if (equalCase_Rangecc(urlScheme_String(d->mod.url), "file")) { |
1226 | { "Gempub Cover Page", 0, 0, NULL } | 1226 | iArray *items = collectNew_Array(sizeof(iMenuItem)); |
1227 | }, 1); | 1227 | pushBack_Array( |
1228 | items, | ||
1229 | &(iMenuItem){ book_Icon " ${gempub.cover.view}", | ||
1230 | 0, | ||
1231 | 0, | ||
1232 | format_CStr("!open url:%s", | ||
1233 | cstr_String(indexPageUrl_Gempub(d->sourceGempub))) }); | ||
1234 | if (navSize_Gempub(d->sourceGempub) > 0) { | ||
1235 | pushBack_Array( | ||
1236 | items, | ||
1237 | &(iMenuItem){ | ||
1238 | format_CStr(forwardArrow_Icon " %s", | ||
1239 | cstr_String(navLinkLabel_Gempub(d->sourceGempub, 0))), | ||
1240 | SDLK_RIGHT, | ||
1241 | 0, | ||
1242 | format_CStr("!open url:%s", | ||
1243 | cstr_String(navLinkUrl_Gempub(d->sourceGempub, 0))) }); | ||
1244 | } | ||
1245 | makeFooterButtons_DocumentWidget_(d, constData_Array(items), size_Array(items)); | ||
1246 | } | ||
1228 | if (preloadCoverImage_Gempub(d->sourceGempub, d->doc)) { | 1247 | if (preloadCoverImage_Gempub(d->sourceGempub, d->doc)) { |
1229 | redoLayout_GmDocument(d->doc); | 1248 | redoLayout_GmDocument(d->doc); |
1230 | updateVisible_DocumentWidget_(d); | 1249 | updateVisible_DocumentWidget_(d); |
1231 | invalidate_DocumentWidget_(d); | 1250 | invalidate_DocumentWidget_(d); |
1232 | } | 1251 | } |
1233 | } | 1252 | } |
1253 | else if (equal_String(d->mod.url, indexPageUrl_Gempub(d->sourceGempub))) { | ||
1254 | makeFooterButtons_DocumentWidget_( | ||
1255 | d, | ||
1256 | (iMenuItem[]){ { format_CStr(book_Icon " %s", | ||
1257 | cstr_String(property_Gempub(d->sourceGempub, | ||
1258 | title_GempubProperty))), | ||
1259 | SDLK_LEFT, | ||
1260 | 0, | ||
1261 | format_CStr("!open url:%s", | ||
1262 | cstr_String(coverPageUrl_Gempub(d->sourceGempub))) } }, | ||
1263 | 1); | ||
1264 | } | ||
1265 | else { | ||
1266 | /* Navigation buttons. */ | ||
1267 | iArray *items = collectNew_Array(sizeof(iMenuItem)); | ||
1268 | const size_t navIndex = navIndex_Gempub(d->sourceGempub, d->mod.url); | ||
1269 | if (navIndex != iInvalidPos) { | ||
1270 | if (navIndex < navSize_Gempub(d->sourceGempub) - 1) { | ||
1271 | pushBack_Array( | ||
1272 | items, | ||
1273 | &(iMenuItem){ | ||
1274 | format_CStr(forwardArrow_Icon " %s", | ||
1275 | cstr_String(navLinkLabel_Gempub(d->sourceGempub, navIndex + 1))), | ||
1276 | SDLK_RIGHT, | ||
1277 | 0, | ||
1278 | format_CStr("!open url:%s", | ||
1279 | cstr_String(navLinkUrl_Gempub(d->sourceGempub, navIndex + 1))) }); | ||
1280 | } | ||
1281 | if (navIndex > 0) { | ||
1282 | pushBack_Array( | ||
1283 | items, | ||
1284 | &(iMenuItem){ | ||
1285 | format_CStr(backArrow_Icon " %s", | ||
1286 | cstr_String(navLinkLabel_Gempub(d->sourceGempub, navIndex - 1))), | ||
1287 | SDLK_LEFT, | ||
1288 | 0, | ||
1289 | format_CStr("!open url:%s", | ||
1290 | cstr_String(navLinkUrl_Gempub(d->sourceGempub, navIndex - 1))) }); | ||
1291 | } | ||
1292 | else if (!equalCase_String(d->mod.url, indexPageUrl_Gempub(d->sourceGempub))) { | ||
1293 | pushBack_Array( | ||
1294 | items, | ||
1295 | &(iMenuItem){ | ||
1296 | format_CStr(book_Icon " %s", | ||
1297 | cstr_String(property_Gempub(d->sourceGempub, title_GempubProperty))), | ||
1298 | SDLK_LEFT, | ||
1299 | 0, | ||
1300 | format_CStr("!open url:%s", | ||
1301 | cstr_String(coverPageUrl_Gempub(d->sourceGempub))) }); | ||
1302 | } | ||
1303 | } | ||
1304 | if (!isEmpty_Array(items)) { | ||
1305 | makeFooterButtons_DocumentWidget_(d, constData_Array(items), size_Array(items)); | ||
1306 | } | ||
1307 | } | ||
1234 | if (!isCached && prefs_App()->pinSplit && | 1308 | if (!isCached && prefs_App()->pinSplit && |
1235 | equal_String(d->mod.url, indexPageUrl_Gempub(d->sourceGempub))) { | 1309 | equal_String(d->mod.url, indexPageUrl_Gempub(d->sourceGempub))) { |
1236 | const iString *navStart = navStartLinkUrl_Gempub(d->sourceGempub); | 1310 | const iString *navStart = navStartLinkUrl_Gempub(d->sourceGempub); |