diff --git a/src/Font.cpp b/src/Font.cpp index 82d58a723d..355f632b14 100644 --- a/src/Font.cpp +++ b/src/Font.cpp @@ -447,6 +447,7 @@ int Font::latexWriteEndChanges(otexstream & os, BufferParams const & bparams, OutputParams const & runparams, Font const & base, Font const & next, + bool & needPar, bool const & closeLanguage) const { int count = 0; @@ -491,6 +492,11 @@ int Font::latexWriteEndChanges(otexstream & os, BufferParams const & bparams, if (f.size() != FONT_SIZE_INHERIT) { // We only have to close if only size changed if (!env) { + if (needPar && !closeLanguage) { + os << "\\par"; + count += 4; + needPar = false; + } os << '}'; ++count; } diff --git a/src/Font.h b/src/Font.h index 58f2696fa6..8b8ddf8d28 100644 --- a/src/Font.h +++ b/src/Font.h @@ -85,6 +85,7 @@ public: OutputParams const & runparams, Font const & base, Font const & next, + bool & needPar, bool const & closeLanguage = true) const; diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index a326bc8477..a5485fc4f0 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -51,6 +51,7 @@ #include "insets/InsetBibitem.h" #include "insets/InsetLabel.h" #include "insets/InsetSpecialChar.h" +#include "insets/InsetText.h" #include "mathed/InsetMathHull.h" @@ -68,6 +69,15 @@ using namespace std; using namespace lyx::support; +// gcc < 4.8.0 and msvc < 2015 do not support C++11 thread_local +#if defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ < 8) || __cplusplus < 201103L) +#define THREAD_LOCAL_STATIC static __thread +#elif defined(_MSC_VER) && ((_MSC_VER < 1900) || __cplusplus < 201103L) +#define THREAD_LOCAL_STATIC static __declspec(thread) +#else +#define THREAD_LOCAL_STATIC thread_local static +#endif + namespace lyx { namespace { @@ -1033,9 +1043,10 @@ void Paragraph::Private::latexInset(BufferParams const & bparams, os << '\n'; } else { if (open_font) { + bool needPar = false; column += running_font.latexWriteEndChanges( os, bparams, runparams, - basefont, basefont); + basefont, basefont, needPar); open_font = false; } @@ -1093,10 +1104,12 @@ void Paragraph::Private::latexInset(BufferParams const & bparams, bool arabtex = basefont.language()->lang() == "arabic_arabtex" || running_font.language()->lang() == "arabic_arabtex"; if (open_font && !inset->inheritFont()) { + bool needPar = false; bool closeLanguage = arabtex || basefont.isRightToLeft() == running_font.isRightToLeft(); unsigned int count = running_font.latexWriteEndChanges(os, - bparams, runparams, basefont, basefont, closeLanguage); + bparams, runparams, basefont, basefont, + needPar, closeLanguage); column += count; // if any font properties were closed, update the running_font, // making sure, however, to leave the language as it was @@ -2360,14 +2373,19 @@ void Paragraph::latex(BufferParams const & bparams, column += d->startTeXParParams(bparams, os, runparams); } + // Whether a \par can be issued for insets typeset inline with text. + // Yes if greater than 0. This has to be static. + THREAD_LOCAL_STATIC int parInline = 0; + for (pos_type i = 0; i < size(); ++i) { // First char in paragraph or after label? if (i == body_pos) { if (body_pos > 0) { if (open_font) { + bool needPar = false; column += running_font.latexWriteEndChanges( os, bparams, runparams, - basefont, basefont); + basefont, basefont, needPar); open_font = false; } basefont = getLayoutFont(bparams, outerfont); @@ -2420,8 +2438,10 @@ void Paragraph::latex(BufferParams const & bparams, if (bparams.output_changes && runningChange != change) { if (open_font) { + bool needPar = false; column += running_font.latexWriteEndChanges( - os, bparams, runparams, basefont, basefont); + os, bparams, runparams, + basefont, basefont, needPar); open_font = false; } basefont = getLayoutFont(bparams, outerfont); @@ -2449,9 +2469,11 @@ void Paragraph::latex(BufferParams const & bparams, (font != running_font || font.language() != running_font.language())) { + bool needPar = false; column += running_font.latexWriteEndChanges( - os, bparams, runparams, basefont, - (i == body_pos-1) ? basefont : font); + os, bparams, runparams, basefont, + (i == body_pos-1) ? basefont : font, + needPar); running_font = basefont; open_font = false; } @@ -2565,9 +2587,40 @@ void Paragraph::latex(BufferParams const & bparams, // and then split to handle the two modes separately. if (c == META_INSET) { if (i >= start_pos && (end_pos == -1 || i < end_pos)) { + // Greyedout notes and, in general, all insets + // with InsetLayout::isDisplay() == false, + // are typeset inline with the text. So, we + // can add a \par to the last paragraph of + // such insets only if nothing else follows. + bool incremented = false; + Inset const * inset = getInset(i); + InsetText const * textinset = inset + ? inset->asInsetText() + : 0; + if (i + 1 == size() && textinset + && !inset->getLayout().isDisplay()) { + ParagraphList const & pars = + textinset->text().paragraphs(); + pit_type const pit = pars.size() - 1; + Font const last_font = + pit < 0 || pars[pit].empty() + ? pars[pit].getLayoutFont( + bparams, + outerfont) + : pars[pit].getFont(bparams, + pars[pit].size() - 1, + outerfont); + if (last_font.fontInfo().size() != + basefont.fontInfo().size()) { + ++parInline; + incremented = true; + } + } d->latexInset(bparams, os, rp, running_font, basefont, outerfont, open_font, runningChange, style, i, column); + if (incremented) + --parInline; } } else if (i >= start_pos && (end_pos == -1 || i < end_pos)) { try { @@ -2601,22 +2654,62 @@ void Paragraph::latex(BufferParams const & bparams, // If we have an open font definition, we have to close it if (open_font) { + // Make sure that \\par is done with the font of the last + // character if this has another size as the default. + // This is necessary because LaTeX (and LyX on the screen) + // calculates the space between the baselines according + // to this font. (Matthias) + // + // We must not change the font for the last paragraph + // of non-multipar insets, tabular cells or commands, + // since this produces unwanted whitespace. + + Font const font = empty() + ? getLayoutFont(bparams, outerfont) + : getFont(bparams, size() - 1, outerfont); + + InsetText const * textinset = inInset().asInsetText(); + + bool const maintext = textinset + ? textinset->text().isMainText() + : false; + + size_t const numpars = textinset + ? textinset->text().paragraphs().size() + : 0; + + bool needPar = false; + + if (style.resfont.size() != font.fontInfo().size() + && (!runparams.isLastPar || maintext + || (numpars > 1 && d->ownerCode() != CELL_CODE + && (inInset().getLayout().isDisplay() + || parInline))) + && !style.isCommand()) { + needPar = true; + } #ifdef FIXED_LANGUAGE_END_DETECTION if (next_) { running_font.latexWriteEndChanges(os, bparams, runparams, basefont, - next_->getFont(bparams, 0, outerfont)); + next_->getFont(bparams, 0, outerfont), + needPar); } else { running_font.latexWriteEndChanges(os, bparams, - runparams, basefont, basefont); + runparams, basefont, basefont, needPar); } #else //FIXME: For now we ALWAYS have to close the foreign font settings if they are //FIXME: there as we start another \selectlanguage with the next paragraph if //FIXME: we are in need of this. This should be fixed sometime (Jug) running_font.latexWriteEndChanges(os, bparams, runparams, - basefont, basefont); + basefont, basefont, needPar); #endif + if (needPar) { + // The \par could not be inserted at the same nesting + // level of the font size change, so do it now. + os << "{\\" << font.latexSize() << "\\par}"; + } } column += Changes::latexMarkChange(os, bparams, runningChange, diff --git a/src/output_latex.cpp b/src/output_latex.cpp index c5fbbb71e7..cac1a770bb 100644 --- a/src/output_latex.cpp +++ b/src/output_latex.cpp @@ -962,30 +962,13 @@ void TeXOnePar(Buffer const & buf, os << from_utf8(everypar); par.latex(bparams, outerfont, os, runparams, start_pos, end_pos); - // Make sure that \\par is done with the font of the last - // character if this has another size as the default. - // This is necessary because LaTeX (and LyX on the screen) - // calculates the space between the baselines according - // to this font. (Matthias) - // - // We must not change the font for the last paragraph - // of non-multipar insets, tabular cells or commands, - // since this produces unwanted whitespace. - Font const font = par.empty() ? par.getLayoutFont(bparams, outerfont) : par.getFont(bparams, par.size() - 1, outerfont); bool const is_command = style.isCommand(); - if (style.resfont.size() != font.fontInfo().size() - && (nextpar || maintext - || (text.inset().paragraphs().size() > 1 - && text.inset().lyxCode() != CELL_CODE)) - && !is_command) { - os << '{'; - os << "\\" << from_ascii(font.latexSize()) << " \\par}"; - } else if (is_command) { + if (is_command) { os << '}'; if (!style.postcommandargs().empty()) latexArgInsets(par, os, runparams, style.postcommandargs(), "post:"); diff --git a/status.22x b/status.22x index 26373402bc..e9b61225f0 100644 --- a/status.22x +++ b/status.22x @@ -39,7 +39,8 @@ What's new * DOCUMENT INPUT/OUTPUT - +- Fix wrong spacing in output when the font size is changed inside + a center environment or a greyed out note (bugs 9598 and 10650). * LYX2LYX