diff --git a/src/mminou.c b/src/mminou.c index a36d60e3..e6c8579a 100644 --- a/src/mminou.c +++ b/src/mminou.c @@ -501,7 +501,7 @@ void printLongLine(const char *line, const char *startNextLine, const char *brea vstring_def(prefix); vstring_def(startNextLine1); vstring_def(breakMatch1); - long i, j, p; + long i, p; long startNextLineLen; flag firstLine; flag tildeFlag = 0; @@ -559,11 +559,6 @@ void printLongLine(const char *line, const char *startNextLine, const char *brea // where all ASCII 3's are converted back to space. // Note added 20-Oct-02: tidy.exe breaks HREF quotes with new line. // Check HTML spec - do we really need this code? - j = (long)strlen(multiLine); - // Do a bug check to make sure no real ASCII 3's are ever printed - for (i = 0; i < j; i++) { - if (multiLine[i] == QUOTED_SPACE) bug(1514); // Should never be the case - } if (breakMatch1[0] == '\"') { breakMatch1[0] = ' '; // Change to a space (the real break character) // Scan string for quoted strings diff --git a/src/mmwtex.c b/src/mmwtex.c index 60d9f34d..96f5063f 100644 --- a/src/mmwtex.c +++ b/src/mmwtex.c @@ -59,6 +59,15 @@ pntrString_def(g_mathboxUser); // User name vs. mathbox # // in a math string in a comment to be removed for HTML output. #define CLOSING_PUNCTUATION ".,;)?!:]'\"_-" +/*! + * \def QUOTED_SPACE + * The general line wrapping algorithm looks out for spaces as break positions. + * To prevent a quote delimited by __"__ be broken down, spaces are temporarily + * replaced with 0x03 (ETX, end of transmission), hopefully never used in + * text in this application. + */ +#define QUOTED_SPACE 3 // ASCII 3 that temporarily zaps a space + // Tex output file FILE *g_texFilePtr = NULL; flag g_texFileOpenFlag = 0; @@ -2806,10 +2815,11 @@ void printTexLongMath(nmbrString *mathString, long indentationLevel) { #define INDENTATION_OFFSET 1 - long i; + long i, j, k, n; long pos; vstring_def(tex); vstring_def(texLine); + vstring_def(texFull); vstring_def(sPrefix); vstring_def(htmStep); vstring_def(htmStepTag); @@ -3047,56 +3057,72 @@ void printTexLongMath(nmbrString *mathString, if (!g_oldTexFlag) { if (refType == 'e' || refType == 'f') { // A hypothesis - don't include \ref{} - printLongLine(cat(" ", - // If not first step, so print "\\" LaTeX line break - !strcmp(htmStep, "1") ? "" : "\\\\ ", - htmStep, // Step number - " && ", - " & ", - texLine, - // Don't put space to help prevent bad line break - "&\\text{Hyp~", - // The following puts a hypothesis number such as "2" if - // $e label is "abc.2"; if no ".", will be whole label. - right(htmRef, instr(1, htmRef, ".") + 1), - "}\\notag%", - // Add full label as LaTeX comment - note lack of space after - // "%" above to prevent bad line break. - htmRef, NULL), - " \\notag \\\\ && & \\qquad ", // Continuation line prefix - " "); + texFull = cat(" ", // texFull[0] should not be a "{" character. + // If not first step, so print "\\" LaTeX line break + !strcmp(htmStep, "1") ? "" : "\\\\ ", + htmStep, // Step number + " && ", + " & ", + texLine, + // Don't put space to help prevent bad line break + "&\\text{Hyp~", + // The following puts a hypothesis number such as "2" if + // $e label is "abc.2"; if no ".", will be whole label. + right(htmRef, instr(1, htmRef, ".") + 1), + "}\\notag%", + // Add full label as LaTeX comment - note lack of space after + // "%" above to prevent bad line break. + htmRef, NULL); } else { - printLongLine(cat(" ", - // If not first step, so print "\\" LaTeX line break - !strcmp(htmStep, "1") ? "" : "\\\\ ", - htmStep, // Step number - " && ", - - // Local label if any e.g. "@2:" - (htmLocLab[0] != 0) ? cat(htmLocLab, "\\ ", NULL) : "", - - " & ", - texLine, - // Don't put space to help prevent bad line break - - // Surround \ref with \mbox for non-math-mode - // symbolic labels (due to \tag{..} in mmcmds.c). Also, - // move hypotheses to after referenced label. - "&", - "(", - - // Don't make local label a \ref - (htmRef[0] != '@') ? - cat("\\mbox{\\ref{eq:", htmRef, "}}", NULL) - : htmRef, - - htmHyp[0] ? "," : "", - htmHyp, - ")\\notag", NULL), - - " \\notag \\\\ && & \\qquad ", // Continuation line prefix - " "); + texFull = cat(" ", // texFull[0] should not be a "{" character. + // If not first step, so print "\\" LaTeX line break + !strcmp(htmStep, "1") ? "" : "\\\\ ", + htmStep, // Step number + " && ", + + // Local label if any e.g. "@2:" + (htmLocLab[0] != 0) ? cat(htmLocLab, "\\ ", NULL) : "", + + " & ", + texLine, + // Don't put space to help prevent bad line break + + // Surround \ref with \mbox for non-math-mode + // symbolic labels (due to \tag{..} in mmcmds.c). Also, + // move hypotheses to after referenced label. + "&", + "(", + + // Don't make local label a \ref + (htmRef[0] != '@') ? + cat("\\mbox{\\ref{eq:", htmRef, "}}", NULL) + : htmRef, + + htmHyp[0] ? "," : "", + htmHyp, + ")\\notag", NULL); + } + // To avoid generating incorrect TeX, line breaking is forbidden inside + // scopes of curly braces. However breaking between '\{' and '\}' is + // allowed. + // The spaces that should not be matched with 'breakMatch' are + // temporarily changed to ASCII 3 before the 'printLongLine' procedure + // is called. The procedure rewraps the 'line' argument matching the + // unchanged spaces only, thus ensuring bad breaks will be avoided. + // The reverse is done in the 'print2()' function, where all ASCII 3's + // are converted back to spaces. + // k counts the scope level we are in. + k = 0; + n = (long)strlen(texFull); + for (j = 1; j < n; j++) { // We don't need to check texFull[0]. + // We enter a non "\{" scope. + if (texFull[j] == '{' && texFull[j - 1] != '\\') k++; + // We escape a non "\}" scope. + if (texFull[j] == '}' && texFull[j - 1] != '\\') k--; + // If k > 0 then we are inside a scope. + if (texFull[j] == ' ' && k > 0) texFull[j] = QUOTED_SPACE; } + printLongLine(texFull, " \\notag \\\\ && & \\qquad ", /* Continuation line prefix */ " "); } else { printLongLine(texLine, "", "\\"); print2("\\endm\n"); diff --git a/tests/.gitignore b/tests/.gitignore index 43f7c2e6..74bcd279 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,2 +1,3 @@ +issue129.tex issue134.tex underscores.html \ No newline at end of file diff --git a/tests/issue129.expected b/tests/issue129.expected new file mode 100644 index 00000000..1e109f83 --- /dev/null +++ b/tests/issue129.expected @@ -0,0 +1,44 @@ +MM> READ "issue129.mm" +Reading source file "issue129.mm"... 121 bytes +121 bytes were read into the source buffer. +The source has 3 statements; 1 are $a and 1 are $p. +No errors were found. However, proofs were not checked. Type VERIFY PROOF * +if you want to check them. +MM> Continuous scrolling is now in effect. +MM> Created LaTeX output file "issue129.tex". +Reading definitions from $t statement of issue129.mm... +1 typesetting statements were read from "issue129.mm". +MM> Outputting proof of "th1"... +The LaTeX source was written to "issue129.tex". +MM> The LaTeX output file "issue129.tex" has been closed. +MM> Entering the Text Tools utilities. Type HELP for help, EXIT to exit. +TOOLS> The input had 28 lines, the output has 27 lines. First output line: +\documentclass{article} +TOOLS> Exiting the Text Tools. Type EXIT again to exit Metamath. +MM> \documentclass{article} +\usepackage{amssymb} % amssymb must be loaded before phonetic +\usepackage{phonetic} % for \riota +\usepackage{mathrsfs} % for \mathscr +\usepackage{mathtools} % loads package amsmath +\usepackage{amsthm} % amsthm must be loaded after amsmath +\usepackage{accents} % accents should be loaded after mathtools +\theoremstyle{plain} +\newtheorem{theorem}{Theorem}[section] +\newtheorem{definition}[theorem]{Definition} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{axiom}{Axiom} +\allowdisplaybreaks[1] % Allow page breaks in {align} +\usepackage[plainpages=false,pdfpagelabels]{hyperref} +\hypersetup{colorlinks} % Get rid of boxes around links +\begin{document} + +\begin{proof} +\begin{align} + 1 && & \text{ A A A A A A A A A A } \text{ A A A A A A A A A A } + \notag \\ && & \qquad \text{ A A A A A A A A A A } + \notag \\ && & \qquad \text{ A A A A A A A A A A } +\text{ A A A A A A A A A A }&(\mbox{\ref{eq:ax-1}})\notag +\end{align} +\end{proof} + +\end{document} diff --git a/tests/issue129.in b/tests/issue129.in new file mode 100644 index 00000000..6078bc29 --- /dev/null +++ b/tests/issue129.in @@ -0,0 +1,7 @@ +open tex issue129.tex +show proof th1 /tex +close tex +tools +match issue129.tex "% This LaTeX file was created by Metamath on " N +exit +"cat issue129.tex" diff --git a/tests/issue129.mm b/tests/issue129.mm new file mode 100644 index 00000000..5ef3b6d4 --- /dev/null +++ b/tests/issue129.mm @@ -0,0 +1,9 @@ +$c A $. + +ax-1 $a A A A A A $. + +th1 $p A A A A A $= ax-1 $. + +$( $t + latexdef "A" as "\text{ A A A A A A A A A A }"; +$) diff --git a/tests/run_test.sh b/tests/run_test.sh index 052782f1..d9e6afe3 100755 --- a/tests/run_test.sh +++ b/tests/run_test.sh @@ -110,7 +110,7 @@ for test in "$@"; do # a new version comes out. # The last line is always 'MM> EXIT' which is not relevant. # The sed is to redact timings, which are nondeterministic - echo "$result" | head -n -1 | tail -n +2 \ + printf "%s" "$result" | head -n -1 | tail -n +2 \ | sed -e 's/ \+[0-9]\+\.[0-9]\+ s/ x.xx s/g' \ > "$outfile"