From 64d4526ee0c5f59c9ecf85724c36300ab5cb0f83 Mon Sep 17 00:00:00 2001 From: Michael Sweet Date: Fri, 7 Apr 2017 16:46:56 -0400 Subject: [PATCH] Add initial support for cover images. Update ZIPC functions. --- mxmldoc.c | 69 +++++++++++++++++++++++++++++++++++++-------------- zipc.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ zipc.h | 1 + 3 files changed, 125 insertions(+), 19 deletions(-) diff --git a/mxmldoc.c b/mxmldoc.c index 23ecddb..38e70c7 100644 --- a/mxmldoc.c +++ b/mxmldoc.c @@ -182,11 +182,11 @@ static void write_docset(const char *docset, const char *section, const char *t #endif /* __APPLE__ */ static void write_element(FILE *out, mxml_node_t *doc, mxml_node_t *element, int mode); #ifdef HAVE_ZLIB_H -static void write_epub(const char *epubfile, const char *section, const char *title, const char *author, const char *copyright, const char *docversion, const char *cssfile, const char *headerfile, const char *introfile, mxml_node_t *doc, const char *footerfile); +static void write_epub(const char *epubfile, const char *section, const char *title, const char *author, const char *copyright, const char *docversion, const char *cssfile, const char *coverimage, const char *headerfile, const char *introfile, mxml_node_t *doc, const char *footerfile); #endif /* HAVE_ZLIB_H */ static void write_file(FILE *out, const char *file, int mode); static void write_function(FILE *out, int mode, mxml_node_t *doc, mxml_node_t *function, int level); -static void write_html(const char *framefile, const char *section, const char *title, const char *author, const char *copyright, const char *docversion, const char *cssfile, const char *headerfile, const char *introfile, mxml_node_t *doc, const char *footerfile); +static void write_html(const char *framefile, const char *section, const char *title, const char *author, const char *copyright, const char *docversion, const char *cssfile, const char *coverimage, const char *headerfile, const char *introfile, mxml_node_t *doc, const char *footerfile); static void write_html_body(FILE *out, int mode, const char *introfile, mxml_node_t *doc); static void write_html_head(FILE *out, int mode, const char *section, const char *title, const char *author, const char *copyright, const char *docversion, const char *cssfile); static void write_html_toc(FILE *out, const char *title, toc_t *toc, const char *filename, const char *target); @@ -222,6 +222,7 @@ main(int argc, /* I - Number of command-line args */ *framefile = NULL, /* Framed HTML basename */ *headerfile = NULL, /* Header file */ *introfile = NULL, /* Introduction file */ + *coverimage = NULL, /* Cover image file */ *name = NULL, /* Name of manpage */ *path = NULL, /* Path to help file for tokens */ *section = NULL, /* Section/keywords of documentation */ @@ -277,6 +278,18 @@ main(int argc, /* I - Number of command-line args */ else usage(NULL); } + else if (!strcmp(argv[i], "--coverimage") && !coverimage) + { + /* + * Set cover image file... + */ + + i ++; + if (i < argc) + coverimage = argv[i]; + else + usage(NULL); + } else if (!strcmp(argv[i], "--css") && !cssfile) { /* @@ -608,7 +621,7 @@ main(int argc, /* I - Number of command-line args */ */ #ifdef HAVE_ZLIB_H - write_epub(epubfile, section, title ? title : "Documentation", author ? author : "Unknown", copyright ? copyright : "Unknown", docversion ? docversion : "0.0", cssfile, headerfile, introfile, mxmldoc, footerfile); + write_epub(epubfile, section, title ? title : "Documentation", author ? author : "Unknown", copyright ? copyright : "Unknown", docversion ? docversion : "0.0", cssfile, coverimage, headerfile, introfile, mxmldoc, footerfile); #else fputs("mxmldoc: Sorry, not compiled with EPUB support.\n", stderr); #endif /* HAVE_ZLIB_H */ @@ -619,7 +632,7 @@ main(int argc, /* I - Number of command-line args */ * Write HTML documentation... */ - write_html(framefile, section, title ? title : "Documentation", author ? author : "Unknown", copyright ? copyright : "Unknown", docversion ? docversion : "0.0", cssfile, headerfile, introfile, mxmldoc, footerfile); + write_html(framefile, section, title ? title : "Documentation", author ? author : "Unknown", copyright ? copyright : "Unknown", docversion ? docversion : "0.0", cssfile, coverimage, headerfile, introfile, mxmldoc, footerfile); break; case OUTPUT_MAN : @@ -3786,6 +3799,7 @@ write_epub(const char *epubfile, /* I - EPUB file (output) */ const char *copyright, /* I - Copyright */ const char *docversion, /* I - Document version */ const char *cssfile, /* I - Stylesheet file */ + const char *coverimage, /* I - Cover image file */ const char *headerfile, /* I - Header file */ const char *introfile, /* I - Intro file */ mxml_node_t *doc, /* I - XML documentation */ @@ -3840,6 +3854,9 @@ write_epub(const char *epubfile, /* I - EPUB file (output) */ write_html_head(fp, OUTPUT_EPUB, section, title, author, copyright, docversion, cssfile); + if (coverimage) + fputs("

", fp); + /* * Header... */ @@ -3925,6 +3942,13 @@ write_epub(const char *epubfile, /* I - EPUB file (output) */ status |= zipcCreateFileWithString(epub, "mimetype", mimetype); + /* + * Add the cover image, if specified... + */ + + if (coverimage) + status |= zipcCopyFile(epub, "iTunesArtwork.png", coverimage, 0, 0); + /* * The META-INF/ directory... */ @@ -3953,24 +3977,16 @@ write_epub(const char *epubfile, /* I - EPUB file (output) */ * Copy the OEBPS/body.xhtml file... */ - if ((epubf = zipcCreateFile(epub, "OEBPS/body.xhtml", 1)) != NULL) - { - if ((fp = fopen(xhtmlfile, "r")) != NULL) - { - char buffer[65536]; /* Copy buffer */ - int length; /* Number of bytes */ + status |= zipcCopyFile(epub, "OEBPS/body.xhtml", xhtmlfile, 1, 1); - while ((length = (int)fread(buffer, 1, sizeof(buffer), fp)) > 0) - zipcFileWrite(epubf, buffer, length); + unlink(xhtmlfile); - fclose(fp); - zipcFileFinish(epubf); - } - } - else - status = -1; + /* + * Add the cover image again, if specified... + */ - unlink(xhtmlfile); + if (coverimage) + status |= zipcCopyFile(epub, "OEBPS/cover.png", coverimage, 0, 0); /* * Now the OEBPS/package.opf file... @@ -4312,6 +4328,7 @@ write_html(const char *framefile, /* I - Framed HTML basename */ const char *copyright, /* I - Copyright string */ const char *docversion, /* I - Documentation set version */ const char *cssfile, /* I - Stylesheet file */ + const char *coverimage, /* I - Cover image file */ const char *headerfile, /* I - Header file */ const char *introfile, /* I - Intro file */ mxml_node_t *doc, /* I - XML documentation */ @@ -4412,6 +4429,13 @@ write_html(const char *framefile, /* I - Framed HTML basename */ write_html_head(out, OUTPUT_HTML, section, title, author, copyright, docversion, cssfile); + if (coverimage) + { + fputs("

\n", out); + } + snprintf(filename, sizeof(filename), "%s-body.html", basename); write_html_toc(out, title, toc, filename, "body"); @@ -4442,6 +4466,13 @@ write_html(const char *framefile, /* I - Framed HTML basename */ write_html_head(out, OUTPUT_HTML, section, title, author, copyright, docversion, cssfile); + if (!framefile && coverimage) + { + fputs("

\n", out); + } + /* * Header... */ diff --git a/zipc.c b/zipc.c index 3074b20..8298383 100644 --- a/zipc.c +++ b/zipc.c @@ -161,6 +161,80 @@ zipcClose(zipc_t *zc) /* I - ZIP container */ } +/* + * 'zipcCopyFile()' - Copy a file into a ZIP container. + * + * The file referenced by "srcname" will be efficiently copied into the ZIP + * container with the name "dstname". + * + * The "compressed" value determines whether the file is compressed within the + * container. + */ + +int /* O - 0 on success, -1 on error */ +zipcCopyFile(zipc_t *zc, /* I - ZIP container */ + const char *dstname, /* I - Destination file (in ZIP container) */ + const char *srcname, /* I - Source file (on disk) */ + int text, /* I - 0 for binary, 1 for text */ + int compressed) /* I - 0 for uncompressed, 1 for compressed */ +{ + zipc_file_t *dstfile; /* Destination file */ + FILE *srcfile; /* Source file */ + char buffer[65536]; /* Copy buffer */ + size_t length; /* Number of bytes read */ + + + if ((srcfile = fopen(srcname, text ? "r" : "rb")) == NULL) + { + zc->error = strerror(errno); + return (-1); + } + + if ((dstfile = zipcCreateFile(zc, dstname, compressed)) == NULL) + { + fclose(srcfile); + return (-1); + } + + if (text) + { + /* + * Copy as text... + */ + + while (fgets(buffer, sizeof(buffer), srcfile)) + { + if (zipcFilePuts(dstfile, buffer)) + { + fclose(srcfile); + zipcFileFinish(dstfile); + return (-1); + } + } + } + else + { + /* + * Copy as binary... + */ + + while ((length = fread(buffer, 1, sizeof(buffer), srcfile)) > 0) + { + if (zipcFileWrite(dstfile, buffer, length)) + { + fclose(srcfile); + zipcFileFinish(dstfile); + return (-1); + } + } + } + + fclose(srcfile); + + return (zipcFileFinish(dstfile)); +} + + /* * 'zipcCreateDirectory()' - Create a directory in a ZIP container. * diff --git a/zipc.h b/zipc.h index 20265c6..6bb2a8f 100644 --- a/zipc.h +++ b/zipc.h @@ -50,6 +50,7 @@ typedef struct _zipc_file_s zipc_file_t;/* File/directory in ZIP container */ */ extern int zipcClose(zipc_t *zc); +extern int zipcCopyFile(zipc_t *zc, const char *dstname, const char *srcname, int text, int compressed); extern int zipcCreateDirectory(zipc_t *zc, const char *filename); extern zipc_file_t *zipcCreateFile(zipc_t *zc, const char *filename, int compressed); extern int zipcCreateFileWithString(zipc_t *zc, const char *filename, const char *contents);