nyctergatis.com

Contact

Projects
Sysquake Remote Live
NME
PDF
Hike
Sudoku
GifBuilder
jpeglib for Palm OS
MySQL Client
Cross-GCC for Mac OS
NMEEPubMain.c
Go to the documentation of this file.
00001 
00008 /* License: new BSD license (see NME.h) */
00009 
00010 #include <stdlib.h>
00011 #include <stdio.h>
00012 #include <string.h>
00013 #include "zip.h"
00014 #include "NME.h"
00015 #include "NMEAutolink.h"
00016 #include "NMEEPub.h"
00017 #include "NE.h"
00018 
00020 #define SIZE (8 * 1024 * 1024L)
00021 
00022 #define kNMENEEndnoteError kNMEErr1stUser
00023 
00024 static NMEBoolean debug = FALSE;
00025 
00027 static NMEAutoconvert autoconverts[16];
00028 
00030 static NMEInterwiki const interwikis[] =
00031 {
00032     {"Dictionary:",
00033         "http://www.dict.org/bin/Dict?Database=*&Form=Dict1&Strategy=*&Query="},
00034     {"Foldoc:", "http://www.foldoc.org/foldoc/foldoc.cgi?"},
00035     {"Google:", "http://www.google.com/search?q="},
00036     {"WhoIs:", "http://www.whois.sc/"},
00037     {"WikiPedia:", "http://en.wikipedia.org/wiki/"},
00038     {NULL, NULL}
00039 };
00040 
00041 static void DisplayUsageAndExit(char const *progName, int status)
00042 {
00043     fprintf(stderr, "Usage: %s [options] -o epubFilename file1 ...\n"
00044             "Required arguments:\n"
00045             "-o epubFilename   specified the EPUB file to create (e.g. book.epub)\n"
00046             "file1 ...         NME files constituting  the contents of the book\n"
00047             "Options:\n"
00048             "--1eol            single eol as paragraph breaks\n"
00049             "--2eol            double eol as paragraph breaks (default)\n"
00050             "--autocclink      automatic conversion of camelCase words to links\n"
00051             "--autourllink     automatic conversion of URLs to links\n"
00052             "--debug           XML debug format, sublists outside list items\n"
00053             "--headernum1      numbering of level-1 headers\n"
00054             "--headernum2      numbering of level-2 headers\n",
00055             progName);
00056     exit(status);
00057 }
00058 
00060 typedef struct
00061 {
00062     NMEOutputFormat *outputFormat;
00063     NE *ne;
00064     
00065     // titles
00066     char const *filename;
00067     int titleSrcOffset;
00068     
00069     // images
00070     NEBoolean inImageMarkup;    
00071 } HookData;
00072 
00086 static NMEErr parHookTOC(NMEInt level,
00087         NMEInt item,
00088         NMEBoolean enter,
00089         NMEConstText markup,
00090         NMEInt srcIndex,
00091         NMEInt srcLineNumber,
00092         NMEContext *context,
00093         void *data)
00094 {
00095     HookData *d = (HookData *)data;
00096     
00097     if (markup[0] == '=' && level == 1)
00098         if (enter)
00099         {
00100             NMEResetOutput(context);
00101             *d->outputFormat = NMEOutputFormatNull;
00102             d->outputFormat->space = " ";
00103             d->outputFormat->encodeCharFun = NULL;
00104             d->outputFormat->parHookFun = parHookTOC;
00105             d->outputFormat->hookData = data;
00106             d->titleSrcOffset = NMECurrentInputIndex(context);
00107         }
00108         else
00109         {
00110             NMEConstText output;
00111             NMEInt outputLength;
00112             char title[512], url[512];
00113             
00114             NMECurrentOutput(context, &output, &outputLength);
00115             if (outputLength > 511)
00116                 outputLength = 511;
00117             sprintf(title, "%.*s", outputLength, output);
00118             sprintf(url, "%s#h%d", d->filename, d->titleSrcOffset);
00119             NEAddTOCEntry(d->ne, title, url, 1);
00120             
00121             *d->outputFormat = NMEOutputFormatNull;
00122             d->outputFormat->parHookFun = parHookTOC;
00123             d->outputFormat->hookData = data;
00124         }
00125     
00126     return kNMEErrOk;
00127 }
00128 
00143 static NMEErr spanHookImg(NMEInt level,
00144         NMEInt item,
00145         NMEBoolean enter,
00146         NMEConstText markup,
00147         NMEInt srcIndex,
00148         NMEInt srcLineNumber,
00149         NMEContext *context,
00150         void *data)
00151 {
00152     HookData *d = (HookData *)data;
00153     
00154     if (!strcmp(markup, "{{"))
00155         d->inImageMarkup = enter;
00156     
00157     return kNMEErrOk;
00158 }
00159 
00169 static NMEErr encodeURL(NMEConstText link, NMEInt linkLen,
00170         NMEContext *context, void *data)
00171 {
00172     HookData *d = (HookData *)data;
00173     
00174     if (d->inImageMarkup)
00175         NEAddOther(d->ne, link, linkLen, NULL);
00176     
00177     return NMEAddRawString(link, linkLen, context); // no conversion
00178 }
00179 
00192 NMEErr PluginEndnote(NMEConstText name, NMEInt nameLen,
00193         NMEConstText data, NMEInt dataLen,
00194         NMEContext *context,
00195         void *userData)
00196 {
00197     NMEText buf, output;
00198     NMEInt bufSize, outputLen;
00199     NMEErr nmeerr;
00200     NEErr neerr;
00201     char const *refLink;
00202     
00203     NMEGetTempMemory(context, &buf, &bufSize);
00204     nmeerr = NMEProcess(data, dataLen,
00205             buf, bufSize,
00206             kNMEProcessOptNoPreAndPost, "\n", &NMEOutputFormatOPSXHTML, 0,
00207             &output, &outputLen, NULL);
00208     if (nmeerr != kNMEErrOk)
00209         return nmeerr;
00210     
00211     neerr = NEAddEndnote((NEPtr)userData,
00212         output, outputLen,
00213         ((NEPtr)userData)->currentDoc, -1,
00214         &refLink);
00215     if (neerr != kNEErrOk)
00216         return kNMENEEndnoteError;
00217     
00218     // insert link
00219     if (!NMEAddString(refLink, -1, '\0', context))
00220         return kNMEErrNotEnoughMemory;
00221     
00222     return kNMEErrOk;
00223 }
00224 
00241 NMEErr PluginMeta(NMEConstText name, NMEInt nameLen,
00242         NMEConstText data, NMEInt dataLen,
00243         NMEContext *context,
00244         void *userData)
00245 {
00246     NEPtr ne = (NEPtr)userData;
00247     
00248     // remove trailing spaces
00249     while (dataLen > 0 && data[dataLen - 1] <= ' ' && data[dataLen - 1] >= '\0')
00250         dataLen--;
00251     
00252     if (!strncmp(name, "title", nameLen))
00253         NEAddMetadata(ne, kNEMetaTitle, data, dataLen);
00254     else if (!strncmp(name, "author", nameLen))
00255         NEAddMetadata(ne, kNEMetaCreator, data, dataLen);
00256     else if (!strncmp(name, "identifier", nameLen))
00257         NEAddMetadata(ne, kNEMetaIdentifier, data, dataLen);
00258     else if (!strncmp(name, "language", nameLen))
00259         NEAddMetadata(ne, kNEMetaLanguage, data, dataLen);
00260     else if (!strncmp(name, "subject", nameLen))
00261         NEAddMetadata(ne, kNEMetaSubject, data, dataLen);
00262     else if (!strncmp(name, "description", nameLen))
00263         NEAddMetadata(ne, kNEMetaDescription, data, dataLen);
00264     else if (!strncmp(name, "publisher", nameLen))
00265         NEAddMetadata(ne, kNEMetaPublisher, data, dataLen);
00266     else if (!strncmp(name, "date", nameLen))
00267         NEAddMetadata(ne, kNEMetaDate, data, dataLen);
00268     else if (!strncmp(name, "source", nameLen))
00269         NEAddMetadata(ne, kNEMetaSource, data, dataLen);
00270     else if (!strncmp(name, "rights", nameLen))
00271         NEAddMetadata(ne, kNEMetaRights, data, dataLen);
00272     else if (!strncmp(name, "cover", nameLen))
00273         NESetCoverImage(ne, data, dataLen);
00274     return kNMEErrOk;
00275 }
00276 
00299 NMEErr PluginGuide(NMEConstText name, NMEInt nameLen,
00300         NMEConstText data, NMEInt dataLen,
00301         NMEContext *context,
00302         void *userData)
00303 {
00304     
00305     return kNMEErrOk;
00306 }
00307 
00309 int main(int argc, char **argv)
00310 {
00311     char const *epubFilename = NULL;
00312     char epubFilenameStr[512];
00313     FILE *fp;
00314     NMEText src = NULL, buf, dest;
00315     NMEInt srcLen, destLen;
00316     NMEOutputFormat outputFormat;
00317     NMEInt options = kNMEProcessOptDefault | kNMEProcessOptXRef;
00318     NMEBoolean autoURLLink = FALSE, autoCCLink = FALSE;
00319     int i;
00320     int iFiles;
00321     char const *imgFilename;
00322     int imgFilenameLength;
00323     NEErr neerr;
00324     NMEErr nmeerr;
00325     NE ne;
00326     HookData hookData;
00327     NMEPlugin plugins[] =
00328     {
00329         {"endnote", kNMEPluginOptDefault, PluginEndnote, NULL},
00330         {"title", kNMEPluginOptDefault, PluginMeta, NULL},
00331         {"author", kNMEPluginOptDefault, PluginMeta, NULL},
00332         {"identifier", kNMEPluginOptDefault, PluginMeta, NULL},
00333         {"language", kNMEPluginOptDefault, PluginMeta, NULL},
00334         {"subject", kNMEPluginOptDefault, PluginMeta, NULL},
00335         {"description", kNMEPluginOptDefault, PluginMeta, NULL},
00336         {"publisher", kNMEPluginOptDefault, PluginMeta, NULL},
00337         {"date", kNMEPluginOptDefault, PluginMeta, NULL},
00338         {"source", kNMEPluginOptDefault, PluginMeta, NULL},
00339         {"rights", kNMEPluginOptDefault, PluginMeta, NULL},
00340         {"cover", kNMEPluginOptDefault, PluginMeta, NULL},
00341         {"guide", kNMEPluginOptDefault, PluginGuide, NULL},
00342         NMEPluginTableEnd
00343     };
00344     
00345     for (i = 1; i < argc; i++)
00346         if (!strcmp(argv[i], "-o") && i + 1 < argc)
00347             epubFilename = argv[++i];
00348         else if (!strcmp(argv[i], "--1eol"))
00349             options |= kNMEProcessOptNoMultilinePar;
00350         else if (!strcmp(argv[i], "--2eol"))
00351             options &= ~kNMEProcessOptNoMultilinePar;
00352         else if (!strcmp(argv[i], "--autocclink"))
00353             autoCCLink = TRUE;
00354         else if (!strcmp(argv[i], "--autourllink"))
00355             autoURLLink = TRUE;
00356         else if (!strcmp(argv[i], "--headernum1"))
00357             options |= kNMEProcessOptH1Num;
00358         else if (!strcmp(argv[i], "--headernum2"))
00359             options |= kNMEProcessOptH2Num;
00360         else if (!strcmp(argv[i], "--debug"))
00361             debug = TRUE;
00362         else if (!strcmp(argv[i], "--strictcreole"))
00363             options |= kNMEProcessOptNoUnderline | kNMEProcessOptNoMonospace
00364                     | kNMEProcessOptNoSubSuperscript | kNMEProcessOptNoIndentedPar
00365                     | kNMEProcessOptNoDL | kNMEProcessOptVerbatimMono;
00366         else if (!strcmp(argv[i], "--help"))
00367             DisplayUsageAndExit(argv[0], 0);
00368         else if (argv[i][0] == '-')
00369         {
00370             fprintf(stderr, "Unknown option %s\n", argv[i]);
00371             DisplayUsageAndExit(argv[0], 1);
00372         }
00373         else
00374             break;
00375     
00376     if (i == argc)
00377     {
00378         fprintf(stderr, "No document file.\n");
00379         DisplayUsageAndExit(argv[0], 1);
00380     }
00381     
00382     iFiles = i;
00383     
00384     if (!epubFilename && !debug)
00385     {
00386         strncpy(epubFilenameStr, argv[iFiles], 505);
00387         epubFilenameStr[505] = '\0';
00388         for (i = strlen(epubFilenameStr); i > 1 && epubFilenameStr[i] != '.'; i--)
00389             ;
00390         strcpy(epubFilenameStr + i, ".epub");
00391         epubFilename = epubFilenameStr;
00392     }
00393     
00394     NEBegin(&ne, epubFilename);
00395     
00396     // alloc buffers
00397     src = malloc(SIZE);
00398     buf = malloc(SIZE);
00399     if (!src || !buf)
00400     {
00401         fprintf(stderr, "Not enough memory.\n");
00402         exit(1);
00403     }
00404     
00405     // process all files for adding XHTML parts
00406     outputFormat = NMEOutputFormatOPSXHTML;
00407     
00408     // add URL encoding fun to grab image references
00409     hookData.outputFormat = &outputFormat;
00410     hookData.ne = &ne;
00411     hookData.titleSrcOffset = 0;
00412     hookData.inImageMarkup = FALSE;
00413     outputFormat.encodeURLFun = encodeURL;
00414     outputFormat.encodeURLData = (void *)&hookData;
00415     outputFormat.spanHookFun = spanHookImg;
00416     outputFormat.hookData = (void *)&hookData;
00417     
00418     for (i = 0; ; i++)
00419         if (plugins[i].cb == PluginEndnote || plugins[i].cb == PluginMeta)
00420             plugins[i].userData = &ne;
00421         else if (plugins[i].cb == NULL)
00422             break;
00423     outputFormat.plugins = plugins;
00424     outputFormat.interwikis = interwikis;
00425     if (autoCCLink || autoURLLink)
00426     {
00427         int n = 0;
00428         if (autoCCLink)
00429             autoconverts[n++].cb = NMEAutoconvertCamelCase;
00430         if (autoURLLink)
00431             autoconverts[n++].cb = NMEAutoconvertURL;
00432         outputFormat.autoconverts = autoconverts;
00433     }
00434     for (i = iFiles; i < argc; i++)
00435     {
00436         // convert NME to XHTML
00437         fp = fopen(argv[i], "rb");
00438         if (!fp)
00439         {
00440             fprintf(stderr, "Cannot open file \"%s\".\n", argv[i]);
00441             exit(1);
00442         }
00443         srcLen = fread(src, 1, SIZE, fp);
00444         if (srcLen < 0)
00445         {
00446             free(src);
00447             exit(1);
00448         }
00449         fclose(fp);
00450         
00451         ne.currentDoc = argv[i];
00452         
00453         nmeerr = NMEProcess(src, srcLen,
00454                 buf, SIZE,
00455                 options, "\n", &outputFormat, 0,
00456                 &dest, &destLen, NULL);
00457         
00458         if (nmeerr != kNMEErrOk)
00459         {
00460             fprintf(stderr, "Conversion error %d\n", nmeerr);
00461             exit(1);
00462         }
00463         
00464         // add converted file to epub
00465         NENewFile(&ne, argv[i]);
00466         NEWriteToFile(&ne, dest, destLen);
00467         NECloseFile(&ne);
00468         NEAddPart(&ne, argv[i], FALSE);
00469     }
00470     
00471     // add images
00472     imgFilename = NULL;
00473     for (;;)
00474     {
00475         char f[512];
00476         NEEnumOther(&ne, &imgFilename, &imgFilenameLength);
00477         if (!imgFilename)
00478             break;
00479         if (imgFilenameLength > 511)
00480             imgFilenameLength = 511;
00481         strncpy(f, imgFilename, imgFilenameLength);
00482         f[imgFilenameLength] = '\0';
00483         neerr = NEAddFile(&ne, f, f);
00484         if (neerr != kNEErrOk)
00485         {
00486             fprintf(stderr, "Cannot add image \"%s\"\n", f);
00487             exit(1);
00488         }
00489     }
00490     
00491     // process all parts for adding TOC entries
00492     outputFormat = NMEOutputFormatTextCompact;
00493     outputFormat.parHookFun = parHookTOC;
00494     outputFormat.hookData = (void *)&hookData;
00495     
00496     for (i = iFiles; i < argc; i++)
00497     {
00498         // convert NME to extract titles and add TOC entries
00499         fp = fopen(argv[i], "rb");
00500         if (!fp)
00501         {
00502             fprintf(stderr, "Cannot open file \"%s\".\n", argv[i]);
00503             exit(1);
00504         }
00505         srcLen = fread(src, 1, SIZE, fp);
00506         if (srcLen < 0)
00507         {
00508             free(src);
00509             exit(1);
00510         }
00511         fclose(fp);
00512         
00513         hookData.filename = argv[i];
00514         nmeerr = NMEProcess(src, srcLen,
00515                 buf, SIZE,
00516                 kNMEProcessOptDefault, "\n", &outputFormat, 0,
00517                 &dest, &destLen, NULL);
00518         
00519         if (nmeerr != kNMEErrOk)
00520         {
00521             fprintf(stderr, "Conversion error %d\n", nmeerr);
00522             exit(1);
00523         }
00524     }
00525     
00526     NEMakeCover(&ne);
00527     
00528     NEEnd(&ne);
00529     
00530     // deallocate memory used for conversion
00531     free((void *)buf);
00532     free((void *)src);
00533     
00534     return 0;
00535 }
Generated by Doxygen.
Copyright 2007-2013, Yves Piguet.
All rights reserved.