///////////////////////////////////////////////////////////////////////////// /* Copyright 2001,2002 Ronald S. Burkey. Copyright 2001 Joe Cherry. This file is part of GutenMark. GutenMark is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GutenMark is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GutenMark; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Filename: OutputLatex.c Purpose: Outputs the LaTeX file. Mods: 01/13/02 RSB Split off from AutoMark.c 06/15/02 RSB Eliminated the arbitrary addition of "Chapter 1", "Chapter 2", etc., at the section breaks. Added stuff for ISO8859-1 characters in the numerical range 0x80-0xFF. 06/16/02 RSB Fixed up page headings. No longer creates a table of contents. (This is related to the problem of adding "Chapter 1" etc. fixed yesterday. Doesn't seem to be any way to create the table of contents without this extra crap.) Now no longer outputs carriage returns at all (it only outputs the linefeeds) to accomodate some wacky files that contained constructs like ^M^M. */ #include #include #include #include #include "AutoMark.h" //-------------------------------------------------------------------------- // 06/15/02 RSB. // Characters with diacriticals et al. Each ISO8859-1 character // is converted instead to a string. These aren't always right, // but they're the best I can see how to do at the moment. // Entries which are NULL mean "don't translate the character". static const char *ISO88591[256] = { "", "", "", "", "", "", "", "", "", "", NULL, "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", NULL, NULL, NULL, "\\#", "\\$", "\\%%", "\\&", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "$<$", NULL, "$>$", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "$\\backslash$", NULL, "\\verb.^.", "\\_", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\\{", "$|$", "\\}", "\\verb.~.", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "<", " cents ", "\\pounds", "", " Yen ", "$|$", "\\S", "\\\"{ }", "\\copyright", "$^{\\underline{a}}$", "$\\ll$", "", "", " (R) ", "\\={ }", "$^{\\circ}$", "$\\pm$", "$^{2}$", "$^{3}$", "\\\'{ }", "$\\mu$", "\\P", "$\\cdot$", "\\c{ }", "$^{1}$", "$^{\\underline{o}}$", "$\\gg$", " 1/4", " 1/2", " 3/4", ">", "\\`{A}", "\\\'{A}", "\\^{A}", "\\~{A}", "\\\"{A}", "\\AA", "\\AE", "\\c{C}", "\\`{E}", "\\\'{E}", "\\^{E}", "\\\"{E}", "\\`{I}", "\\\'{I}", "\\^{I}", "\\\"{I}", "D", "\\~{N}", "\\`{O}", "\\\'{O}", "\\^{O}", "\\~{O}", "\\\"{O}", "$\\times$", "\\O", "\\`{U}", "\\\'{U}", "\\^{U}", "\\\"{U}", "\\`{Y}", "P", "\\ss{}", "\\`{a}", "\\\'{a}", "\\^{a}", "\\~{a}", "\\\"{a}", "\\aa", "\\ae", "\\c{c}", "\\`{e}", "\\\'{e}", "\\^{e}", "\\\"{e}", "\\`{\\i}", "\\\'{\\i}", "\\^{\\i}", "\\\"{\\i}", "d", "\\~{n}", "\\`{o}", "\\\'{o}", "\\^{o}", "\\~{o}", "\\\"{o}", "$\\div$", "\\o", "\\`{u}", "\\\'{u}", "\\^{u}", "\\\"{u}", "\\\'{y}", "p", "\\\"{y}" }; //-------------------------------------------------------------------------- static char Chapter[256]; static int ChapterNameSize = 0; static void OutputChar (FILE *OutputFile, int c, int InChapter) { if (ISO88591[c] == NULL) { if (InChapter == 1 && (c == '\r' || c == '\n')) c = ' '; if (InChapter && ChapterNameSize < (sizeof (Chapter) - 1)) Chapter[ChapterNameSize++] = c; putc (c, OutputFile); } else { int Len; Len = ChapterNameSize + strlen (ISO88591[c]); if (InChapter && Len < sizeof (Chapter)) strcpy (&Chapter[ChapterNameSize], ISO88591[c]); ChapterNameSize = Len; fputs (ISO88591[c], OutputFile); } } //-------------------------------------------------------------------------- // Handles just the output, after all analysis has been completed. // Returns 0 on success, non-zero on error. int OutputLatex (FILE * OutputFile, AnalysisDataset * Dataset) { int ErrorCode, c, lastc, Remove, AtEnd; MarkupRecord Mark; unsigned long Offset; char s[256], Title[256]; int InParagraph = 0; int InChapter = 0; int InPreformatted = 0, LastNewline = 1; int SentPgHeader = 0; int AfterBreak = 0; char *InputFilename = NULL; int Removed = -1; int JumpedPastHeader = 0; int InPrefatoryArea = 0; // Print output header. fprintf (OutputFile, "\\documentclass{book}\n"); if (!Dataset->NoParskip) // 06/15/02 RSB fprintf (OutputFile, "\\usepackage{parskip}\n"); fseek (Dataset->InputFile, 0, SEEK_SET); fgets (s, sizeof (s) - 1, Dataset->InputFile); fgets (s + strlen (s), sizeof (s) - strlen (s) - 1, Dataset->InputFile); NormalizeTitle (s, sizeof (s)); strcpy (Title, s); fprintf (OutputFile, "\\title{%s}\n", Title); fprintf (OutputFile, "\\begin{document}\n"); fprintf (OutputFile, "\\pagestyle{myheadings}\n"); fprintf (OutputFile, "\\maketitle\n"); //fprintf (OutputFile, "\\tableofcontents\n"); // Print marked-up text. This is basically a matter // of merging the markup file with the input file. fseek (Dataset->MarkupFile, 0, SEEK_SET); fseek (Dataset->InputFile, 0, SEEK_SET); if (Dataset->YesHeader) { ErrorCode = fread (&Mark, sizeof (Mark), 1, Dataset->MarkupFile); if (ErrorCode != 1) Mark.Type = MarkNoMoreMarks; Offset = 0; } else { do { ErrorCode = fread (&Mark, sizeof (Mark), 1, Dataset->MarkupFile); if (ErrorCode != 1) { Mark.Type = MarkNoMoreMarks; break; } } while (Mark.Offset < Dataset->TextStart); fseek (Dataset->InputFile, Dataset->TextStart, SEEK_SET); Offset = Dataset->TextStart; } for (Remove = AtEnd = c = 0; (lastc = c, c = fgetc (Dataset->InputFile)) != EOF; Offset++) { if (!isspace (c)) AfterBreak = 0; LastShot: while (Offset == Mark.Offset && Mark.Type != MarkNoMoreMarks) { switch (Mark.Type) { case MarkTolower: //if (Removed != Offset) putc (DiacriticalTolower (c), OutputFile); Remove = 1; break; case MarkToupper: //if (Removed != Offset) putc (DiacriticalToupper (c), OutputFile); Remove = 1; break; case MarkBeginSmartQuote: fprintf (OutputFile, "``"); Remove = 1; break; case MarkEndSmartQuote: fprintf (OutputFile, "''"); Remove = 1; break; case MarkLsquo: fprintf (OutputFile, "`"); Remove = 1; break; case MarkRsquo: fprintf (OutputFile, "'"); Remove = 1; break; case MarkRemoveChar: Remove = 1; Removed = Offset; break; case MarkInsertChar: //putc (Mark.Insert, OutputFile); //OutputCharacter (Dataset->ForceNumeric, OutputFile, Mark.Insert); OutputChar (OutputFile, Mark.Insert, InChapter); break; case MarkNbsp: fprintf (OutputFile, "~"); break; case MarkBeginJustifiedParagraph: InParagraph = 1; if (Dataset->NoJustify) fprintf (OutputFile, "\n\n"); else fprintf (OutputFile, "\n\n"); break; case MarkBeginRaggedParagraph: InParagraph = 1; fprintf (OutputFile, "\n\n"); break; case MarkBeginCenteredParagraph: InParagraph = 1; fprintf (OutputFile, "\n\n"); break; case MarkEndParagraph: InParagraph = 0; fprintf (OutputFile, "\n\n"); break; case MarkBeginItalics: fprintf (OutputFile, "\\textit{"); break; case MarkEndItalics: fprintf (OutputFile, "}"); break; case MarkBeginBold: fprintf (OutputFile, "\\textbf{"); break; case MarkEndBold: fprintf (OutputFile, "}"); break; case MarkBeginUnderline: fprintf (OutputFile, "\\emph{"); break; case MarkEndUnderline: fprintf (OutputFile, "}"); break; case MarkBreak: AfterBreak = 1; fprintf (OutputFile, "\n\n"); break; case MarkBlockquote: // I think, not used. InParagraph = 1; fprintf (OutputFile, "\\begin{quotation}\n"); break; case MarkEndBlockquote: // I think, not used. InParagraph = 0; fprintf (OutputFile, "\\end{quotation}\n"); break; case MarkHeader1: InPrefatoryArea = 0; fprintf (OutputFile, "\\chapter*{"); InChapter = 1; ChapterNameSize = 0; break; case MarkEndHeader1: fprintf (OutputFile, "}"); InChapter = 0; Chapter[ChapterNameSize] = 0; fprintf (OutputFile, "\\markboth{%s}{%s}\n", Title, Chapter); break; case MarkBeginSubtitle: fprintf (OutputFile, "\\section{"); InChapter = 1; break; case MarkEndSubtitle: fprintf (OutputFile, "}"); InChapter = 0; break; case MarkBeginTable: InPreformatted = 1; LastNewline = 0; fprintf (OutputFile, "\\begin{verbatim}\n"); break; case MarkEndTable: InPreformatted = 0; fprintf (OutputFile, "\\end{verbatim}\n"); break; case MarkInsertMdash: fprintf (OutputFile, "--"); break; case MarkInsertNdash: fprintf (OutputFile, "-"); break; case MarkSoftHyphen: fprintf (OutputFile, "\\-"); break; case MarkJumpPastGutenbergHeader: JumpedPastHeader = 1; fprintf (OutputFile, "\\chapter*{Project Gutenberg Fine Print}\\begin{verbatim}\n" "\\markboth{%s}{Project Gutenberg Fine Print}\n", Title); SentPgHeader = 1; break; case MarkEndOfGutenbergHeader: if (SentPgHeader == 1) fprintf (OutputFile, "\\end{verbatim}\n"); SentPgHeader = 0; if (Dataset->LowestNonPrefatoryLine > 0) { InPrefatoryArea = 1; fprintf (OutputFile, "\\chapter*{Prefatory Materials}\n" "\\markboth{%s}{Prefatory Materials}\n" "\\begin{quotation}\n" "\\textit{This is a modified " "etext created by \\textbf{GutenMark} " "software, version " __DATE__ ".", Title); if (InputFilename != NULL) fprintf (OutputFile, "~ The original text was contained " "in a computer file named \"%s.\"", InputFilename); fprintf (OutputFile, "~ Any comments below " "about the preparation of the text " "refer to the \\emph{original} " "etext file, and do not directly " "refer to this modified version of " "the text.~ In particular, no individuals " "named below bear any responsibility for " "changes to the text.}\n" "\\end{quotation}\n"); } break; case MarkGutenbergEnder: if (Dataset->YesHeader) { } else AtEnd = 1; break; case MarkNoMoreMarks: break; } ErrorCode = fread (&Mark, sizeof (Mark), 1, Dataset->MarkupFile); if (ErrorCode != 1) Mark.Type = MarkNoMoreMarks; } if (AtEnd) break; if (Remove) Remove = 0; else OutputChar (OutputFile, c, InChapter); } // What this does is to allow us to process any remaining markups that // are supposed to occur at the very end of the input (such as end of // paragraph. if (AtEnd == 0) { AtEnd = 1; goto LastShot; } // Last stage: Close the output stream. fprintf (OutputFile, "\\end{document}\n"); return (0); }