From e96dbacfee560ea01b4e4f3d23fe103090bb60d7 Mon Sep 17 00:00:00 2001 From: Enrico Forestieri Date: Tue, 28 Jul 2009 16:15:34 +0000 Subject: [PATCH] Refine fix for bug #5096: Language switch fails in environments. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@30800 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/output_latex.cpp | 139 ++++++++++++++++++++++++++++++------------- 1 file changed, 97 insertions(+), 42 deletions(-) diff --git a/src/output_latex.cpp b/src/output_latex.cpp index 606dec005e..cbeee40511 100644 --- a/src/output_latex.cpp +++ b/src/output_latex.cpp @@ -94,6 +94,74 @@ TeXDeeper(Buffer const & buf, } +Language const * +priorLanguage(ParagraphList::const_iterator const pit, + ParagraphList::const_iterator const priorpit, + ParagraphList::const_iterator const pars_begin, + BufferParams const & bparams) +{ + ParagraphList::const_iterator outpit = priorpit; + ParagraphList::const_iterator refpit = priorpit; + + // We go back until the depth kept increasing or the current layout + // matches the reference one. When the depth decreases, we should stop + // only if we started from inside the enclosing environment, otherwise + // we should continue to go back. + + bool topped = false; + depth_type const refdepth = + priorpit->getDepth() ? priorpit->getDepth() - 1 : 0; + while (outpit != pars_begin + && (outpit->hasSameLayout(*refpit) + || outpit->getDepth() > pit->getDepth())) { + outpit = boost::prior(outpit); + if (outpit->getDepth() == pit->getDepth() + && outpit->layout() == pit->layout() + && (priorpit->getAlign() != priorpit->layout().align + || priorpit->getDepth() > pit->getDepth())) { + // After skipping either a nested or non-default + // aligned environment, we ended at an environment with + // same layout and nesting depth as the current one. + break; + } + if (outpit->getDepth() == refdepth) { + if (outpit->getDepth() >= pit->getDepth() + && (priorpit->getDepth() > pit->getDepth() + || outpit->layout() == refpit->layout())) { + // The prior environment was nested in + // another one, or was enclosing some other + // one, or we are still in it. In any case, + // we still have to go back. + refpit = outpit; + } else { + topped = true; + break; + } + } + } + ParagraphList::const_iterator const inpit = + topped ? refpit : boost::next(outpit); + // Check if we stopped at the first paragraph, + // but we should still go back. + topped = !topped && (outpit == pars_begin + && (outpit->hasSameLayout(*refpit) + || outpit->getDepth() > pit->getDepth()) + && !(outpit->getDepth() == pit->getDepth() + && outpit->layout() == pit->layout() + && (priorpit->getAlign() != priorpit->layout().align + || priorpit->getDepth() > pit->getDepth()))); + Language const * const outenv_language = + topped ? bparams.language + : outpit->getParLanguage(bparams); + Language const * const inenv_language = + topped ? outpit->getParLanguage(bparams) + : inpit->getParLanguage(bparams); + if (outenv_language->babel() != inenv_language->babel()) + return inenv_language; + return outenv_language; +} + + ParagraphList::const_iterator TeXEnvironment(Buffer const & buf, Text const & text, @@ -111,13 +179,21 @@ TeXEnvironment(Buffer const & buf, bparams.documentClass().plainLayout() : pit->layout(); ParagraphList const & paragraphs = text.paragraphs(); + ParagraphList::const_iterator const priorpit = + pit == paragraphs.begin() ? pit : boost::prior(pit); Language const * const par_language = pit->getParLanguage(bparams); Language const * const doc_language = bparams.language; + Language const * const prior_language = + (pit != paragraphs.begin() && priorpit != paragraphs.begin() + && priorpit->getDepth() >= pit->getDepth() + && !priorpit->hasSameLayout(*pit) + && !priorpit->layout().isParagraph()) + ? priorLanguage(pit, priorpit, paragraphs.begin(), bparams) + : priorpit->getParLanguage(bparams); Language const * const prev_par_language = - (pit != paragraphs.begin()) - ? boost::prior(pit)->getParLanguage(bparams) - : doc_language; + (pit != paragraphs.begin()) ? prior_language : doc_language; + if (par_language->babel() != prev_par_language->babel()) { if (!lyxrc.language_command_end.empty() && @@ -336,46 +412,25 @@ ParagraphList::const_iterator TeXOnePar(Buffer const & buf, Language const * const outer_language = (runparams.local_font != 0) ? runparams.local_font->language() : doc_language; - // The previous language that was in effect is either the language of - // the previous paragraph, if there is one, or else the outer language - // if there is no previous paragraph - Language const * prev_language = - (pit != paragraphs.begin()) ? - priorpit->getParLanguage(bparams) : outer_language; - - // When the language is changed at the very start of a LyX environment, - // the language switch in the LaTeX code occurs just before switching to - // the corresponding LaTeX environment. So, when the environment ends, - // we have to properly restore the language that was in effect. - bool env_lang_switch = false; - if (!priorpit->hasSameLayout(*pit)) { - ParagraphList::const_iterator outpit = priorpit; - while (outpit != paragraphs.begin() - && (outpit->hasSameLayout(*priorpit) - || outpit->getDepth() > pit->getDepth() - || outpit->getAlign() != outpit->layout().align)) - outpit = boost::prior(outpit); - ParagraphList::const_iterator inpit = boost::next(outpit); - bool topped = outpit == paragraphs.begin() - && (outpit->hasSameLayout(*priorpit) - || outpit->getDepth() > pit->getDepth() - || outpit->getAlign() != outpit->layout().align - || outpit->layout().isEnvironment()); - Language const * const outenv_language = topped ? - outer_language - : outpit->getParLanguage(bparams); - Language const * const inenv_language = topped ? - outpit->getParLanguage(bparams) - : inpit->getParLanguage(bparams); - if (outenv_language->babel() != inenv_language->babel()) { - if (inenv_language->babel() != par_language->babel()) - env_lang_switch = true; - prev_language = inenv_language; - } else - prev_language = outenv_language; - } - if ((par_language->babel() != prev_language->babel() || env_lang_switch) + // The language that was in effect before the current paragraph. + Language const * const prior_language = + (pit != paragraphs.begin() && priorpit != paragraphs.begin() + && priorpit->getDepth() >= pit->getDepth() + && !priorpit->hasSameLayout(*pit) + && !priorpit->layout().isParagraph()) + ? priorLanguage(pit, priorpit, paragraphs.begin(), bparams) + : priorpit->getParLanguage(bparams); + + // The previous language that was in effect is the language of the + // previous paragraph, unless the previous paragraph is inside an + // environment and the current one is nested in it but with a lower + // depth. If there is no previous paragraph, the previous language + // is the outer language. + Language const * const prev_language = + (pit != paragraphs.begin()) ? prior_language : outer_language; + + if (par_language->babel() != prev_language->babel() // check if we already put language command in TeXEnvironment() && !(style.isEnvironment() && (pit == paragraphs.begin() || -- 2.39.2