X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Foutput_latex.cpp;h=8a6ed8f4e5230501c7b5a3a0e1f99ea75f27c6bc;hb=66c5d055e776e0cd08fb35c164b49d9ccc7812b7;hp=ad4db9b5270b75f2821706dc5928eda1642d3784;hpb=f995fba310c203fdba6a55f0ad62830a7d2d704c;p=lyx.git diff --git a/src/output_latex.cpp b/src/output_latex.cpp index ad4db9b527..8a6ed8f4e5 100644 --- a/src/output_latex.cpp +++ b/src/output_latex.cpp @@ -434,6 +434,22 @@ void TeXEnvironment(Buffer const & buf, Text const & text, continue; } + // Do not output empty environments if the whole paragraph has + // been deleted with ct and changes are not output. + if (size_t(pit + 1) < paragraphs.size()) { + ParagraphList::const_iterator nextpar = paragraphs.constIterator(pit + 1); + Paragraph const & cpar = paragraphs.at(pit); + if ((par->layout() != nextpar->layout() + || par->params().depth() == nextpar->params().depth() + || par->params().leftIndent() == nextpar->params().leftIndent()) + && !runparams.for_search && cpar.size() > 0 + && cpar.isDeleted(0, cpar.size()) && !buf.params().output_changes) { + if (!buf.params().output_changes && !cpar.parEndChange().deleted()) + os << '\n' << '\n'; + continue; + } + } + // This is a new environment. TeXEnvironmentData const data = prepareEnvironment(buf, text, par, os, runparams); @@ -681,8 +697,8 @@ void parStartCommand(Paragraph const & par, otexstream & os, case LATEX_COMMAND: if (par.needsCProtection(runparams.moving_arg)) { if (contains(runparams.active_chars, '^')) - // cprotect relies on ^ being ignored - os << "\\begingroup\\catcode`\\^=9"; + // cprotect relies on ^ being on catcode 7 + os << "\\begingroup\\catcode`\\^=7"; os << "\\cprotect"; } os << '\\' << from_ascii(style.latexname()); @@ -742,6 +758,12 @@ void TeXOnePar(Buffer const & buf, if (style.inpreamble && !force) return; + // Do not output empty commands if the whole paragraph has + // been deleted with ct and changes are not output. + if (!runparams_in.for_search && style.latextype != LATEX_ENVIRONMENT + && par.size() > 0 && par.isDeleted(0, par.size()) && !bparams.output_changes) + return; + LYXERR(Debug::LATEX, "TeXOnePar for paragraph " << pit << " ptr " << &par << " '" << everypar << "'"); @@ -763,11 +785,14 @@ void TeXOnePar(Buffer const & buf, state->open_encoding_ = none; } + // This paragraph is merged and we do not show changes in the output + bool const merged_par = !bparams.output_changes && par.parEndChange().deleted(); + if (text.inset().isPassThru()) { Font const outerfont = text.outerFont(pit); // No newline before first paragraph in this lyxtext - if (pit > 0 && !text.inset().getLayout().parbreakIgnored()) { + if (pit > 0 && !text.inset().getLayout().parbreakIgnored() && !merged_par) { os << '\n'; if (!text.inset().getLayout().parbreakIsNewline()) os << '\n'; @@ -780,7 +805,11 @@ void TeXOnePar(Buffer const & buf, Paragraph const * nextpar = runparams.isLastPar ? nullptr : ¶graphs.at(pit + 1); - bool const intitle_command = style.intitle && style.latextype == LATEX_COMMAND; + bool const intitle_command = style.intitle && style.isCommand(); + // Intitle commands switch languages locally, thus increase + // language nesting level + if (intitle_command) + state->nest_level_ += 1; if (style.pass_thru) { Font const outerfont = text.outerFont(pit); @@ -789,7 +818,8 @@ void TeXOnePar(Buffer const & buf, // Due to the moving argument, some fragile // commands (labels, index entries) // are output after this command (#2154) - runparams.postpone_fragile_stuff = true; + runparams.postpone_fragile_stuff = + bparams.postpone_fragile_content; if (intitle_command) os << '{'; @@ -803,17 +833,20 @@ void TeXOnePar(Buffer const & buf, if (par.needsCProtection(runparams.moving_arg) && contains(runparams.active_chars, '^')) os << "\\endgroup"; - os << "\n"; + if (merged_par) + os << "{}"; + else + os << "\n"; } - else + else if (!merged_par) os << '\n'; - if (!style.parbreak_is_newline) { + if (!style.parbreak_is_newline && !merged_par) { os << '\n'; } else if (nextpar && !style.isEnvironment()) { Layout const nextstyle = text.inset().forcePlainLayout() ? bparams.documentClass().plainLayout() : nextpar->layout(); - if (nextstyle.name() != style.name()) + if (nextstyle.name() != style.name() && !merged_par) os << '\n'; } @@ -847,14 +880,31 @@ void TeXOnePar(Buffer const & buf, && priorpar->layout().isEnvironment() && (priorpar->getDepth() > par.getDepth() || (priorpar->getDepth() == par.getDepth() - && priorpar->layout() != par.layout())); + && priorpar->layout() != par.layout())); + + // We need to ignore previous intitle commands since languages + // are switched locally there (# 11514) + // There might be paragraphs before the title, so we check this. + Paragraph * prior_nontitle_par = nullptr; + if (!intitle_command) { + pit_type ppit = pit; + while (ppit > 0) { + --ppit; + Paragraph const * tmppar = ¶graphs.at(ppit); + if (tmppar->layout().intitle && tmppar->layout().isCommand()) + continue; + prior_nontitle_par = const_cast(tmppar); + break; + } + } Language const * const prev_language = - runparams_in.for_search ? - languages.getLanguage("ignore") - :(priorpar && !priorpar->isPassThru()) - ? (use_prev_env_language ? state->prev_env_language_ - : priorpar->getParLanguage(bparams)) - : outer_language; + runparams_in.for_search + ? languages.getLanguage("ignore") + : (prior_nontitle_par && !prior_nontitle_par->isPassThru()) + ? (use_prev_env_language + ? state->prev_env_language_ + : prior_nontitle_par->getParLanguage(bparams)) + : outer_language; bool const use_polyglossia = runparams.use_polyglossia; string const par_lang = use_polyglossia ? @@ -883,7 +933,8 @@ void TeXOnePar(Buffer const & buf, // Due to the moving argument, some fragile // commands (labels, index entries) // are output after this command (#2154) - runparams.postpone_fragile_stuff = true; + runparams.postpone_fragile_stuff = + bparams.postpone_fragile_content; os << '{'; } @@ -896,10 +947,12 @@ void TeXOnePar(Buffer const & buf, && runparams.local_font != nullptr && outer_language->rightToLeft() && !par_language->rightToLeft(); - bool const localswitch = runparams_in.for_search + bool const localswitch = + (runparams_in.for_search || text.inset().forceLocalFontSwitch() || (using_begin_end && text.inset().forcePlainLayout()) - || in_polyglossia_rtl_env; + || in_polyglossia_rtl_env) + && !text.inset().forceParDirectionSwitch(); if (localswitch) { lang_begin_command = use_polyglossia ? "\\text$$lang$$opts{" : lyxrc.language_command_local; @@ -979,7 +1032,7 @@ void TeXOnePar(Buffer const & buf, if ((runparams.encoding->package() != Encoding::CJK || bparams.useNonTeXFonts || runparams.for_search) - && (par_lang != openLanguageName(state) || localswitch) + && (par_lang != openLanguageName(state) || localswitch || intitle_command) && !par_lang.empty()) { string bc = use_polyglossia ? getPolyglossiaBegin(lang_begin_command, par_lang, @@ -1098,7 +1151,8 @@ void TeXOnePar(Buffer const & buf, // Due to the moving argument, some fragile // commands (labels, index entries) // are output after this command (#2154) - runparams.postpone_fragile_stuff = true; + runparams.postpone_fragile_stuff = + bparams.postpone_fragile_content; } Font const outerfont = text.outerFont(pit); @@ -1147,7 +1201,7 @@ void TeXOnePar(Buffer const & buf, && nextpar->getDepth() < par.getDepth())) close_lang_switch = using_begin_end; if (nextpar && par.params().depth() < nextpar->params().depth()) - pending_newline = !text.inset().getLayout().parbreakIgnored(); + pending_newline = !text.inset().getLayout().parbreakIgnored() && !merged_par; break; case LATEX_ENVIRONMENT: { // if it's the last paragraph of the current environment @@ -1166,7 +1220,7 @@ void TeXOnePar(Buffer const & buf, default: // we don't need it for the last paragraph and in InTitle commands!!! if (nextpar && !intitle_command) - pending_newline = !text.inset().getLayout().parbreakIgnored(); + pending_newline = !text.inset().getLayout().parbreakIgnored() && !merged_par; } // InTitle commands use switches (not environments) for space settings @@ -1282,29 +1336,35 @@ void TeXOnePar(Buffer const & buf, // InTitle commands need to be closed after the language has been closed. if (intitle_command) { - if (is_command) { - os << '}'; - if (!style.postcommandargs().empty()) - latexArgInsets(par, os, runparams, style.postcommandargs(), "post:"); - if (!runparams.post_macro.empty()) { - // Output the stored fragile commands (labels, indices etc.) - // that need to be output after the command with moving argument. - os << runparams.post_macro; - runparams.post_macro.clear(); - } - if (par.needsCProtection(runparams.moving_arg) - && contains(runparams.active_chars, '^')) - os << "\\endgroup"; - if (runparams.encoding != prev_encoding) { - runparams.encoding = prev_encoding; - os << setEncoding(prev_encoding->iconvName()); - } + os << '}'; + if (!style.postcommandargs().empty()) + latexArgInsets(par, os, runparams, style.postcommandargs(), "post:"); + if (!runparams.post_macro.empty()) { + // Output the stored fragile commands (labels, indices etc.) + // that need to be output after the command with moving argument. + os << runparams.post_macro; + runparams.post_macro.clear(); + } + if (par.needsCProtection(runparams.moving_arg) + && contains(runparams.active_chars, '^')) + os << "\\endgroup"; + if (runparams.encoding != prev_encoding) { + runparams.encoding = prev_encoding; + os << setEncoding(prev_encoding->iconvName()); } } bool const last_was_separator = par.size() > 0 && par.isEnvSeparator(par.size() - 1); + // Signify added/deleted par break in output if show changes in output + if (nextpar && !os.afterParbreak() && !last_was_separator + && bparams.output_changes && par.parEndChange().changed()) { + Changes::latexMarkChange(os, bparams, Change(Change::UNCHANGED), + par.parEndChange(), runparams); + os << bparams.encoding().latexString(docstring(1, 0x00b6)).first << "}"; + } + if (pending_newline) { if (unskip_newline) // prevent unwanted whitespace @@ -1388,7 +1448,7 @@ void TeXOnePar(Buffer const & buf, // TeXEnvironment, because it is needed in this case if (nextpar && !os.afterParbreak() && !last_was_separator) { Layout const & next_layout = nextpar->layout(); - if (!text.inset().getLayout().parbreakIgnored()) + if (!text.inset().getLayout().parbreakIgnored() && !merged_par) // Make sure to start a new line os << breakln; // A newline '\n' is always output before a command, @@ -1432,11 +1492,18 @@ void TeXOnePar(Buffer const & buf, && next_layout.align == nextpar->getAlign(bparams)) || (style.align != par.getAlign(bparams) && tclass.isDefaultLayout(next_layout))) { - os << '\n'; + // and omit paragraph break if it has been deleted with ct + // and changes are not shown in output + if (!merged_par) + os << '\n'; } } } + // Reset language nesting level after intitle command + if (intitle_command) + state->nest_level_ -= 1; + LYXERR(Debug::LATEX, "TeXOnePar for paragraph " << pit << " done; ptr " << &par << " next " << nextpar); @@ -1589,6 +1656,22 @@ void latexParagraphs(Buffer const & buf, continue; } + // Do not output empty environments if the whole paragraph has + // been deleted with ct and changes are not output. + if (size_t(pit + 1) < paragraphs.size()) { + ParagraphList::const_iterator nextpar = paragraphs.constIterator(pit + 1); + Paragraph const & cpar = paragraphs.at(pit); + if ((par->layout() != nextpar->layout() + || par->params().depth() == nextpar->params().depth() + || par->params().leftIndent() == nextpar->params().leftIndent()) + && !runparams.for_search && cpar.size() > 0 + && cpar.isDeleted(0, cpar.size()) && !bparams.output_changes) { + if (!bparams.output_changes && !cpar.parEndChange().deleted()) + os << '\n' << '\n'; + continue; + } + } + TeXEnvironmentData const data = prepareEnvironment(buf, text, par, os, runparams); // pit can be changed in TeXEnvironment. @@ -1628,7 +1711,9 @@ void latexParagraphs(Buffer const & buf, "$$lang", mainlang)) << '\n'; - if (using_begin_end) + // If we have language_auto_begin, the stack will + // already be empty, nothing to pop() + if (using_begin_end && !lyxrc.language_auto_begin) popLanguageName(); }