]> git.lyx.org Git - lyx.git/blobdiff - src/output_latex.cpp
start the timer in the correct thread
[lyx.git] / src / output_latex.cpp
index 4f39ee58d783a17d6e8681cf54f766e23331246b..63e61ac4b13fd746c486abf971aaca24caf21079 100644 (file)
@@ -237,82 +237,90 @@ static void finishEnvironement(odocstream & os, TexRow & texrow,
 }
 
 
-ParagraphList::const_iterator
-TeXEnvironment(Buffer const & buf,
-              Text const & text,
-              ParagraphList::const_iterator pit,
-              odocstream & os, TexRow & texrow,
-              OutputParams const & runparams)
+void TeXEnvironment(Buffer const & buf,
+              Text const & text, OutputParams const & runparams,
+                  pit_type & pit, odocstream & os, TexRow & texrow)
 {
-       LYXERR(Debug::LATEX, "TeXEnvironment...     " << &*pit);
        ParagraphList const & paragraphs = text.paragraphs();
+       ParagraphList::const_iterator par = paragraphs.constIterator(pit);
+       LYXERR(Debug::LATEX, "TeXEnvironment for paragraph " << pit);
+
+       Layout const & current_layout = par->layout();
+       depth_type const current_depth = par->params().depth();
+       Length const & current_left_indent = par->params().leftIndent();
+
+       // This is for debugging purpose at the end.
+       pit_type const par_begin = pit;
+       for (; pit < runparams.par_end; ++pit) {
+       
+               ParagraphList::const_iterator par = paragraphs.constIterator(pit);
+
+               // check first if this is an higher depth paragraph.
+               bool go_out = (par->params().depth() < current_depth);
+               if (par->params().depth() == current_depth) {
+                       // This environment is finished.
+                       go_out |= (par->layout() != current_layout);
+                       go_out |= (par->params().leftIndent() != current_left_indent);
+               }
+               if (go_out) {
+                       // nothing to do here, restore pit and go out.
+                       pit--;
+                       break;
+               }
 
-       ParagraphList::const_iterator par = pit;
-       do {
-               TeXOnePar(buf, text, par, os, texrow, runparams);
-               if (par != paragraphs.end())
-                       par++;
+               if (par->layout() == current_layout
+                       && par->params().depth() == current_depth
+                       && par->params().leftIndent() == current_left_indent) {
+                       // We are still in the same environment so TeXOnePar and continue;
+                       TeXOnePar(buf, text, pit, os, texrow, runparams);
+                       continue;
+               }
 
-               if (par == paragraphs.end()) {
-                       // Make sure that the last paragraph is
-                       // correctly terminated (because TeXOnePar does
-                       // not add a \n in this case)
+               // We are now in a deeper environment.
+               // Either par->layout() != current_layout
+               // Or     par->params().depth() > current_depth
+               // Or     par->params().leftIndent() != current_left_indent)
+
+               if (par->layout().isParagraph()) {
+                       // FIXME (Lgb): How to handle this? 
+                       //&& !suffixIs(os, "\n\n")
+
+                       // (ARRae) There should be at least one '\n' already but we need there to
+                       // be two for Standard paragraphs that are depth-increment'ed to be
+                       // output correctly. However, tables can also be paragraphs so
+                       // don't adjust them.
+                       // 
+
+                       // FIXME (Lgb): Will it ever harm to have one '\n' too
+                       // many? i.e. that we sometimes will have
+                       // three in a row.
                        os << '\n';
                        texrow.newline();
-               } else if (par->params().depth() > pit->params().depth()) {
-                       if (par->layout().isParagraph()) {
-                         // Thinko!
-                         // How to handle this? (Lgb)
-                         //&& !suffixIs(os, "\n\n")
-
-                               // There should be at least one '\n' already
-                               // but we need there to be two for Standard
-                               // paragraphs that are depth-increment'ed to be
-                               // output correctly.  However, tables can
-                               // also be paragraphs so don't adjust them.
-                               // ARRae
-                               // Thinkee:
-                               // Will it ever harm to have one '\n' too
-                               // many? i.e. that we sometimes will have
-                               // three in a row. (Lgb)
-                               os << '\n';
-                               texrow.newline();
-                       }
+               }
 
-                       LYXERR(Debug::LATEX, "TeXDeeper...     " << &*par);
-                       bool const force_plain_layout = text.inset().forcePlainLayout();
-                       depth_type const max_depth = par->params().depth();
-
-                       // FIXME: move that to a for loop!
-                       while (par != paragraphs.end()
-                               && par->params().depth() == max_depth) {
-                               // FIXME This test should not be necessary.
-                               // We should perhaps issue an error if it is.
-                               Layout const & style = force_plain_layout
-                                       ? buf.params().documentClass().plainLayout() : par->layout();
-                               if (style.isEnvironment()) {
-                                       TeXEnvironementData const data = prepareEnvironement(buf,
-                                               text, par, os, texrow, runparams);
-                                       // Recursive call to TeXEnvironment!
-                                       par = TeXEnvironment(buf, text, par, os, texrow, runparams);
-                                       finishEnvironement(os, texrow, runparams, data);
-                               } else {
-                                       TeXOnePar(buf, text, par, os, texrow, runparams);
-                                       if (par != text.paragraphs().end())
-                                               par++;
-                               }
-                       }
-                       LYXERR(Debug::LATEX, "TeXDeeper...done ");
+               // FIXME This test should not be necessary.
+               // We should perhaps issue an error if it is.
+               bool const force_plain_layout = text.inset().forcePlainLayout();
+               Layout const & style = force_plain_layout
+                       ? buf.params().documentClass().plainLayout()
+                       : par->layout();
+
+               if (!style.isEnvironment()) {
+                       // This is a standard paragraph, no need to call TeXEnvironment.
+                       TeXOnePar(buf, text, pit, os, texrow, runparams);
+                       continue;
                }
-       } while (par != paragraphs.end()
-                && par->layout() == pit->layout()
-                && par->params().depth() == pit->params().depth()
-                && par->params().leftIndent() == pit->params().leftIndent());
 
-       if (par != paragraphs.end())
-               LYXERR(Debug::LATEX, "TeXEnvironment...done " << &*par);
+               // This is a new environment.
+               TeXEnvironementData const data = prepareEnvironement(buf, text, par,
+                       os, texrow, runparams);
+               // Recursive call to TeXEnvironment!
+               TeXEnvironment(buf, text, runparams, pit, os, texrow);
+               finishEnvironement(os, texrow, runparams, data);
+       }
 
-       return par;
+       if (pit != runparams.par_end)
+               LYXERR(Debug::LATEX, "TeXEnvironment for paragraph " << par_begin << " done.");
 }
 
 } // namespace anon
@@ -376,48 +384,48 @@ int latexArgInsets(Paragraph const & par, odocstream & os,
 // FIXME: this should be anonymous
 void TeXOnePar(Buffer const & buf,
          Text const & text,
-         ParagraphList::const_iterator const pit,
+         pit_type pit,
          odocstream & os, TexRow & texrow,
          OutputParams const & runparams_in,
          string const & everypar,
          int start_pos, int end_pos)
 {
-       LYXERR(Debug::LATEX, "TeXOnePar...     " << &*pit << " '"
-               << everypar << "'");
-
        BufferParams const & bparams = buf.params();
+       ParagraphList const & paragraphs = text.paragraphs();
+       Paragraph const & par = paragraphs.at(pit);
        // FIXME This check should not really be needed.
        // Perhaps we should issue an error if it is.
        Layout const style = text.inset().forcePlainLayout() ?
-               bparams.documentClass().plainLayout() : pit->layout();
-
-       ParagraphList const & paragraphs = text.paragraphs();
-       ParagraphList::const_iterator const priorpit = 
-               pit == paragraphs.begin() ? pit : boost::prior(pit);
-       ParagraphList::const_iterator const nextpit = 
-               pit == paragraphs.end() ? pit : boost::next(pit);
+               bparams.documentClass().plainLayout() : par.layout();
 
        if (style.inpreamble)
                return;
 
+       LYXERR(Debug::LATEX, "TeXOnePar for paragraph " << pit << " ptr " << &par << " '"
+               << everypar << "'");
+
        OutputParams runparams = runparams_in;
-       runparams.isLastPar = nextpit == paragraphs.end();
+       runparams.isLastPar = (pit == pit_type(paragraphs.size() - 1));
+       // We reinitialze par begin and end to be on the safe side
+       // with embedded inset as we don't know if they set those
+       // value correctly.
+       runparams.par_begin = 0;
+       runparams.par_end = 0;
 
        bool const maintext = text.isMainText();
        // we are at the beginning of an inset and CJK is already open;
        // we count inheritation levels to get the inset nesting right.
-       if (pit == paragraphs.begin() && !maintext
+       if (pit == 0 && !maintext
            && (cjk_inherited_ > 0 || open_encoding_ == CJK)) {
                cjk_inherited_ += 1;
                open_encoding_ = none;
        }
 
        if (text.inset().getLayout().isPassThru()) {
-               int const dist = distance(paragraphs.begin(), pit);
-               Font const outerfont = text.outerFont(dist);
+               Font const outerfont = text.outerFont(pit);
 
                // No newline before first paragraph in this lyxtext
-               if (dist > 0) {
+               if (pit > 0) {
                        os << '\n';
                        texrow.newline();
                        if (!text.inset().getLayout().parbreakIsNewline()) {
@@ -426,24 +434,26 @@ void TeXOnePar(Buffer const & buf,
                        }
                }
 
-               pit->latex(bparams, outerfont, os, texrow,
-                          runparams, start_pos, end_pos);
+               par.latex(bparams, outerfont, os, texrow, runparams, start_pos,
+                       end_pos);
                return;
        }
 
+       Paragraph const * nextpar = runparams.isLastPar
+               ? 0 : &paragraphs.at(pit + 1);
+
        if (style.pass_thru) {
-               int const dist = distance(paragraphs.begin(), pit);
-               Font const outerfont = text.outerFont(dist);
-               pit->latex(bparams, outerfont, os, texrow,
-                          runparams, start_pos, end_pos);
+               Font const outerfont = text.outerFont(pit);
+               par.latex(bparams, outerfont, os, texrow, runparams, start_pos,
+                       end_pos);
                os << '\n';
                texrow.newline();
                if (!style.parbreak_is_newline) {
                        os << '\n';
                        texrow.newline();
-               } else if (nextpit != paragraphs.end()) {
+               } else if (nextpar) {
                        Layout const nextstyle = text.inset().forcePlainLayout() ?
-                               bparams.documentClass().plainLayout() : nextpit->layout();
+                               bparams.documentClass().plainLayout() : nextpar->layout();
                        if (nextstyle.name() != style.name()) {
                                os << '\n';
                                texrow.newline();
@@ -454,7 +464,7 @@ void TeXOnePar(Buffer const & buf,
        }
 
        // This paragraph's language
-       Language const * const par_language = pit->getParLanguage(bparams);
+       Language const * const par_language = par.getParLanguage(bparams);
        // The document's language
        Language const * const doc_language = bparams.language;
        // The language that was in effect when the environment this paragraph is
@@ -463,20 +473,23 @@ void TeXOnePar(Buffer const & buf,
                (runparams.local_font != 0) ?
                        runparams.local_font->language() : doc_language;
 
+       Paragraph const * priorpar = (pit == 0) ? 0 : &paragraphs.at(pit - 1);
+
        // The previous language that was in effect is the language of the
        // previous paragraph, unless the previous paragraph is inside an
        // environment with nesting depth greater than (or equal to, but with
        // a different layout) the current one. If there is no previous
        // paragraph, the previous language is the outer language.
        bool const use_prev_env_language = prev_env_language_ != 0
-                       && priorpit->layout().isEnvironment()
-                       && (priorpit->getDepth() > pit->getDepth()
-                           || (priorpit->getDepth() == pit->getDepth()
-                               && priorpit->layout() != pit->layout()));
+                       && priorpar
+                       && priorpar->layout().isEnvironment()
+                       && (priorpar->getDepth() > par.getDepth()
+                           || (priorpar->getDepth() == par.getDepth()
+                                   && priorpar->layout() != par.layout()));
        Language const * const prev_language =
-               (pit != paragraphs.begin())
+               (pit != 0)
                ? (use_prev_env_language ? prev_env_language_
-                                        : priorpit->getParLanguage(bparams))
+                                        : priorpar->getParLanguage(bparams))
                : outer_language;
 
        string par_lang = par_language->babel();
@@ -495,12 +508,11 @@ void TeXOnePar(Buffer const & buf,
                lang_end_command = "\\end{$$lang}";
        }
        if (par_lang != prev_lang
-           // check if we already put language command in TeXEnvironment()
-           && !(style.isEnvironment()
-                && (pit == paragraphs.begin() ||
-                    (priorpit->layout() != pit->layout() &&
-                     priorpit->getDepth() <= pit->getDepth())
-                    || priorpit->getDepth() < pit->getDepth())))
+               // check if we already put language command in TeXEnvironment()
+               && !(style.isEnvironment()
+                    && (pit == 0 || (priorpar->layout() != par.layout()
+                                         && priorpar->getDepth() <= par.getDepth())
+                                 || priorpar->getDepth() < par.getDepth())))
        {
                if (!lang_end_command.empty() &&
                    prev_lang != outer_lang &&
@@ -519,20 +531,19 @@ void TeXOnePar(Buffer const & buf,
                // the previous one, if the current language is different than the
                // outer_language (which is currently in effect once the previous one
                // is closed).
-               if ((lang_end_command.empty() ||
-                    par_lang != outer_lang) &&
-                   !par_lang.empty()) {
+               if ((lang_end_command.empty() || par_lang != outer_lang)
+                       && !par_lang.empty()) {
                        // If we're inside an inset, and that inset is within an \L or \R
                        // (or equivalents), then within the inset, too, any opposite
                        // language paragraph should appear within an \L or \R (in addition
                        // to, outside of, the normal language switch commands).
                        // This behavior is not correct for ArabTeX, though.
-                       if (!runparams.use_polyglossia &&
+                       if (!runparams.use_polyglossia
                            // not for ArabTeX
-                           (par_language->lang() != "arabic_arabtex" &&
-                            outer_language->lang() != "arabic_arabtex") &&
+                               && par_language->lang() != "arabic_arabtex"
+                               && outer_language->lang() != "arabic_arabtex"
                            // are we in an inset?
-                           runparams.local_font != 0 &&
+                           && runparams.local_font != 0
                            // is the inset within an \L or \R?
                            //
                            // FIXME: currently, we don't check this; this means that
@@ -540,9 +551,7 @@ void TeXOnePar(Buffer const & buf,
                            // doesn't seem to hurt (though latex will complain)
                            //
                            // is this paragraph in the opposite direction?
-                           runparams.local_font->isRightToLeft() !=
-                                 par_language->rightToLeft()
-                           ) {
+                           && runparams.local_font->isRightToLeft() != par_language->rightToLeft()) {
                                // FIXME: I don't have a working copy of the Arabi package, so
                                // I'm not sure if the farsi and arabic_arabi stuff is correct
                                // or not...
@@ -581,61 +590,62 @@ void TeXOnePar(Buffer const & buf,
        // Switch file encoding if necessary; no need to do this for "default"
        // encoding, since this only affects the position of the outputted
        // \inputencoding command; the encoding switch will occur when necessary
-       if (bparams.inputenc == "auto" &&
-           runparams.encoding->package() != Encoding::none) {
+       if (bparams.inputenc == "auto"
+               && runparams.encoding->package() != Encoding::none) {
                // Look ahead for future encoding changes.
                // We try to output them at the beginning of the paragraph,
                // since the \inputencoding command is not allowed e.g. in
                // sections. For this reason we only set runparams.moving_arg
                // after checking for the encoding change, otherwise the
                // change would be always avoided by switchEncoding().
-               for (pos_type i = 0; i < pit->size(); ++i) {
-                       char_type const c = pit->getChar(i);
+               for (pos_type i = 0; i < par.size(); ++i) {
+                       char_type const c = par.getChar(i);
                        Encoding const * const encoding =
-                               pit->getFontSettings(bparams, i).language()->encoding();
-                       if (encoding->package() != Encoding::CJK &&
-                           runparams.encoding->package() == Encoding::inputenc &&
-                           c < 0x80)
+                               par.getFontSettings(bparams, i).language()->encoding();
+                       if (encoding->package() != Encoding::CJK
+                               && runparams.encoding->package() == Encoding::inputenc
+                               && c < 0x80)
                                continue;
-                       if (pit->isInset(i))
+                       if (par.isInset(i))
                                break;
                        // All characters before c are in the ASCII range, and
                        // c is non-ASCII (but no inset), so change the
                        // encoding to that required by the language of c.
                        // With CJK, only add switch if we have CJK content at the beginning
                        // of the paragraph
-                       if (encoding->package() != Encoding::CJK || i == 0) {
-                               pair<bool, int> enc_switch = switchEncoding(os, bparams, runparams,
-                                       *encoding);
-                               // the following is necessary after a CJK environment in a multilingual
-                               // context (nesting issue).
-                               if (par_language->encoding()->package() == Encoding::CJK &&
-                                   open_encoding_ != CJK && cjk_inherited_ == 0) {
-                                       os << "\\begin{CJK}{" << from_ascii(par_language->encoding()->latexName())
-                                          << "}{" << from_ascii(bparams.fonts_cjk) << "}%\n";
-                                       open_encoding_ = CJK;
+                       if (i != 0 && encoding->package() == Encoding::CJK)
+                               continue;
+
+                       pair<bool, int> enc_switch = switchEncoding(os, bparams, runparams,
+                               *encoding);
+                       // the following is necessary after a CJK environment in a multilingual
+                       // context (nesting issue).
+                       if (par_language->encoding()->package() == Encoding::CJK
+                               && open_encoding_ != CJK && cjk_inherited_ == 0) {
+                               os << "\\begin{CJK}{" << from_ascii(par_language->encoding()->latexName())
+                                  << "}{" << from_ascii(bparams.fonts_cjk) << "}%\n";
+                               open_encoding_ = CJK;
+                               texrow.newline();
+                       }
+                       if (encoding->package() != Encoding::none && enc_switch.first) {
+                               if (enc_switch.second > 0) {
+                                       // the '%' is necessary to prevent unwanted whitespace
+                                       os << "%\n";
                                        texrow.newline();
                                }
-                               if (encoding->package() != Encoding::none && enc_switch.first) {
-                                       if (enc_switch.second > 0) {
-                                               // the '%' is necessary to prevent unwanted whitespace
-                                               os << "%\n";
-                                               texrow.newline();
-                                       }
-                                       // With CJK, the CJK tag had to be closed first (see above)
-                                       if (runparams.encoding->package() == Encoding::CJK) {
-                                               os << from_ascii(subst(
-                                                       lang_begin_command,
-                                                       "$$lang",
-                                                       par_lang))
-                                               // the '%' is necessary to prevent unwanted whitespace
-                                               << "%\n";
-                                               texrow.newline();
-                                       }
-                                       runparams.encoding = encoding;
+                               // With CJK, the CJK tag had to be closed first (see above)
+                               if (runparams.encoding->package() == Encoding::CJK) {
+                                       os << from_ascii(subst(
+                                               lang_begin_command,
+                                               "$$lang",
+                                               par_lang))
+                                       // the '%' is necessary to prevent unwanted whitespace
+                                       << "%\n";
+                                       texrow.newline();
                                }
-                               break;
+                               runparams.encoding = encoding;
                        }
+                       break;
                }
        }
 
@@ -643,17 +653,16 @@ void TeXOnePar(Buffer const & buf,
        Encoding const * const prev_encoding = runparams.encoding;
 
        bool const useSetSpace = bparams.documentClass().provides("SetSpace");
-       if (pit->allowParagraphCustomization()) {
-               if (pit->params().startOfAppendix()) {
+       if (par.allowParagraphCustomization()) {
+               if (par.params().startOfAppendix()) {
                        os << "\\appendix\n";
                        texrow.newline();
                }
 
-               if (!pit->params().spacing().isDefault()
-                       && (pit == paragraphs.begin()
-                           || !priorpit->hasSameLayout(*pit)))
+               if (!par.params().spacing().isDefault()
+                       && (pit == 0 || !priorpar->hasSameLayout(par)))
                {
-                       os << from_ascii(pit->params().spacing().writeEnvirBegin(useSetSpace))
+                       os << from_ascii(par.params().spacing().writeEnvirBegin(useSetSpace))
                            << '\n';
                        texrow.newline();
                }
@@ -670,7 +679,7 @@ void TeXOnePar(Buffer const & buf,
 
                // Separate handling of optional argument inset.
                if (style.optargs != 0 || style.reqargs != 0) {
-                       int ret = latexArgInsets(*pit, os, runparams, style.reqargs, style.optargs);
+                       int ret = latexArgInsets(par, os, runparams, style.reqargs, style.optargs);
                        while (ret > 0) {
                                texrow.newline();
                                --ret;
@@ -690,12 +699,11 @@ void TeXOnePar(Buffer const & buf,
                break;
        }
 
-       Font const outerfont = text.outerFont(distance(paragraphs.begin(), pit));
+       Font const outerfont = text.outerFont(pit);
 
        // FIXME UNICODE
        os << from_utf8(everypar);
-       pit->latex(bparams, outerfont, os, texrow,
-                                                runparams, start_pos, end_pos);
+       par.latex(bparams, outerfont, os, texrow, 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.
@@ -707,14 +715,14 @@ void TeXOnePar(Buffer const & buf,
        // We do not need to use to change the font for the last paragraph
        // or for a command.
 
-       Font const font = pit->empty()
-                ? pit->getLayoutFont(bparams, outerfont)
-                : pit->getFont(bparams, pit->size() - 1, outerfont);
+       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()
-           && nextpit != paragraphs.end()
+           && nextpar
            && !is_command) {
                os << '{';
                os << "\\" << from_ascii(font.latexSize()) << " \\par}";
@@ -731,35 +739,33 @@ void TeXOnePar(Buffer const & buf,
        switch (style.latextype) {
        case LATEX_ITEM_ENVIRONMENT:
        case LATEX_LIST_ENVIRONMENT:
-               if (nextpit != paragraphs.end()
-                   && (pit->params().depth() < nextpit->params().depth()))
+               if (nextpar && (par.params().depth() < nextpar->params().depth()))
                        pending_newline = true;
                break;
        case LATEX_ENVIRONMENT: {
                // if its the last paragraph of the current environment
                // skip it otherwise fall through
-               if (nextpit != paragraphs.end() && 
-                   (nextpit->layout() != pit->layout()
-                    || nextpit->params().depth() != pit->params().depth()))
+               if (nextpar
+                       && (nextpar->layout() != par.layout()
+                       || nextpar->params().depth() != par.params().depth()))
                        break;
        }
 
        // fall through possible
        default:
                // we don't need it for the last paragraph!!!
-               if (nextpit != paragraphs.end())
+               if (nextpar)
                        pending_newline = true;
        }
 
-       if (pit->allowParagraphCustomization()) {
-               if (!pit->params().spacing().isDefault()
-                       && (nextpit == paragraphs.end() || !nextpit->hasSameLayout(*pit)))
-               {
+       if (par.allowParagraphCustomization()) {
+               if (!par.params().spacing().isDefault()
+                       && (runparams.isLastPar || !nextpar->hasSameLayout(par))) {
                        if (pending_newline) {
                                os << '\n';
                                texrow.newline();
                        }
-                       os << from_ascii(pit->params().spacing().writeEnvirEnd(useSetSpace));
+                       os << from_ascii(par.params().spacing().writeEnvirEnd(useSetSpace));
                        pending_newline = true;
                }
        }
@@ -767,23 +773,19 @@ void TeXOnePar(Buffer const & buf,
        // Closing the language is needed for the last paragraph; it is also
        // needed if we're within an \L or \R that we may have opened above (not
        // necessarily in this paragraph) and are about to close.
-       bool closing_rtl_ltr_environment =
-               !runparams.use_polyglossia &&
+       bool closing_rtl_ltr_environment = !runparams.use_polyglossia
                // not for ArabTeX
-               (par_language->lang() != "arabic_arabtex" &&
-                outer_language->lang() != "arabic_arabtex") &&
-               // have we opened and \L or \R environment?
-               runparams.local_font != 0 &&
-               runparams.local_font->isRightToLeft() != par_language->rightToLeft() &&
+               && (par_language->lang() != "arabic_arabtex"
+                   && outer_language->lang() != "arabic_arabtex")
+                    // have we opened and \L or \R environment?
+               && runparams.local_font != 0
+               && runparams.local_font->isRightToLeft() != par_language->rightToLeft()
                // are we about to close the language?
-               ((nextpit != paragraphs.end() &&
-                 par_language->babel() !=
-                   (nextpit->getParLanguage(bparams))->babel()) ||
-                 (nextpit == paragraphs.end() &&
-                   par_language->babel() != outer_language->babel()));
-
-       if (closing_rtl_ltr_environment || (nextpit == paragraphs.end()
-           && par_language->babel() != outer_language->babel())) {
+               &&((nextpar && par_language->babel() != (nextpar->getParLanguage(bparams))->babel())
+                  || (runparams.isLastPar && par_language->babel() != outer_language->babel()));
+
+       if (closing_rtl_ltr_environment
+               || (runparams.isLastPar && par_language->babel() != outer_language->babel())) {
                // Since \selectlanguage write the language to the aux file,
                // we need to reset the language at the end of footnote or
                // float.
@@ -798,8 +800,7 @@ void TeXOnePar(Buffer const & buf,
                                // If this is a child, we should restore the
                                // master language after the last paragraph.
                                Language const * const current_language =
-                                       (nextpit == paragraphs.end()
-                                       && runparams.master_language)
+                                       (runparams.isLastPar && runparams.master_language)
                                                ? runparams.master_language
                                                : outer_language;
                                string const current_lang = runparams.use_polyglossia ?
@@ -831,18 +832,19 @@ void TeXOnePar(Buffer const & buf,
 
        // if this is a CJK-paragraph and the next isn't, close CJK
        // also if the next paragraph is a multilingual environment (because of nesting)
-       if (nextpit != paragraphs.end() && open_encoding_ == CJK &&
-           (nextpit->getParLanguage(bparams)->encoding()->package() != Encoding::CJK ||
-            (nextpit->layout().isEnvironment() && nextpit->isMultiLingual(bparams)))
-            // inbetween environments, CJK has to be closed later (nesting!)
-            && (!style.isEnvironment() || !nextpit->layout().isEnvironment())) {
+       if (nextpar
+               && open_encoding_ == CJK
+               && (nextpar->getParLanguage(bparams)->encoding()->package() != Encoding::CJK
+                  || (nextpar->layout().isEnvironment() && nextpar->isMultiLingual(bparams)))
+               // inbetween environments, CJK has to be closed later (nesting!)
+               && (!style.isEnvironment() || !nextpar->layout().isEnvironment())) {
                os << "\\end{CJK}\n";
                open_encoding_ = none;
        }
 
        // If this is the last paragraph, close the CJK environment
        // if necessary. If it's an environment, we'll have to \end that first.
-       if (nextpit == paragraphs.end() && !style.isEnvironment()) {
+       if (runparams.isLastPar && !style.isEnvironment()) {
                switch (open_encoding_) {
                        case CJK: {
                                // do nothing at the end of child documents
@@ -877,7 +879,7 @@ void TeXOnePar(Buffer const & buf,
        // should be set back to that local_font's encoding.
        // However, do not change the encoding when a fully unicode aware backend
        // such as XeTeX is used.
-       if (nextpit == paragraphs.end() && runparams_in.local_font != 0
+       if (runparams.isLastPar && runparams_in.local_font != 0
            && runparams_in.encoding != runparams_in.local_font->language()->encoding()
            && (bparams.inputenc == "auto" || bparams.inputenc == "default")
            && (!runparams.isFullUnicode())) {
@@ -892,8 +894,8 @@ void TeXOnePar(Buffer const & buf,
        // we don't need a newline for the last paragraph!!!
        // Note from JMarc: we will re-add a \n explicitly in
        // TeXEnvironment, because it is needed in this case
-       if (nextpit != paragraphs.end()) {
-               Layout const & next_layout = nextpit->layout();
+       if (nextpar) {
+               Layout const & next_layout = nextpar->layout();
                if (style == next_layout
                    // no blank lines before environments!
                    || !next_layout.isEnvironment()
@@ -904,14 +906,14 @@ void TeXOnePar(Buffer const & buf,
                    // information whether the current TeX row is empty or not.
                    // For some ideas about how to fix this, see this thread:
                    // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg145787.html
-                   || nextpit->params().depth() != pit->params().depth()) {
+                   || nextpar->params().depth() != par.params().depth()) {
                        os << '\n';
                        texrow.newline();
                }
        }
 
-       if (nextpit != paragraphs.end())
-               LYXERR(Debug::LATEX, "TeXOnePar...done " << &*nextpit);
+       LYXERR(Debug::LATEX, "TeXOnePar for paragraph " << pit << " done; ptr "
+               << &par << " next " << nextpar);
 
        return;
 }
@@ -925,24 +927,7 @@ void latexParagraphs(Buffer const & buf,
                     OutputParams const & runparams,
                     string const & everypar)
 {
-       bool was_title = false;
-       bool already_title = false;
        BufferParams const & bparams = buf.params();
-       DocumentClass const & tclass = bparams.documentClass();
-       ParagraphList const & paragraphs = text.paragraphs();
-       ParagraphList::const_iterator par = paragraphs.begin();
-       ParagraphList::const_iterator endpar = paragraphs.end();
-
-       LASSERT(runparams.par_begin <= runparams.par_end, /**/);
-       // if only part of the paragraphs will be outputed
-       if (runparams.par_begin !=  runparams.par_end) {
-               par = boost::next(paragraphs.begin(), runparams.par_begin);
-               endpar = boost::next(paragraphs.begin(), runparams.par_end);
-               // runparams will be passed to nested paragraphs, so
-               // we have to reset the range parameters.
-               const_cast<OutputParams&>(runparams).par_begin = 0;
-               const_cast<OutputParams&>(runparams).par_end = 0;
-       }
 
        bool const maintext = text.isMainText();
        bool const is_child = buf.masterBuffer() != &buf;
@@ -980,10 +965,28 @@ void latexParagraphs(Buffer const & buf,
                texrow.newline();
        }
 
-       ParagraphList::const_iterator lastpar;
-       // if only_body
-       while (par != endpar) {
-               lastpar = par;
+       ParagraphList const & paragraphs = text.paragraphs();
+       LASSERT(runparams.par_begin <= runparams.par_end, /**/);
+
+       if (runparams.par_begin == runparams.par_end) {
+               // The full doc will be exported but it is easier to just rely on
+               // runparams range parameters that will be passed TeXEnvironment.
+               runparams.par_begin = 0;
+               runparams.par_end = paragraphs.size();
+       }
+
+       pit_type pit = runparams.par_begin;
+       // lastpit is for the language check after the loop.
+       pit_type lastpit = pit;
+       // variables used in the loop:
+       bool was_title = false;
+       bool already_title = false;
+       DocumentClass const & tclass = bparams.documentClass();
+
+       for (; pit < runparams.par_end; ++pit) {
+               lastpit = pit;
+               ParagraphList::const_iterator par = paragraphs.constIterator(pit);
+
                // FIXME This check should not be needed. We should
                // perhaps issue an error if it is.
                Layout const & layout = text.inset().forcePlainLayout() ?
@@ -991,9 +994,9 @@ void latexParagraphs(Buffer const & buf,
 
                if (layout.intitle) {
                        if (already_title) {
-                               lyxerr << "Error in latexParagraphs: You"
+                               LYXERR0("Error in latexParagraphs: You"
                                        " should not mix title layouts"
-                                       " with normal ones." << endl;
+                                       " with normal ones.");
                        } else if (!was_title) {
                                was_title = true;
                                if (tclass.titletype() == TITLE_ENVIRONMENT) {
@@ -1017,19 +1020,26 @@ void latexParagraphs(Buffer const & buf,
                        was_title = false;
                }
 
-               if (layout.isEnvironment() ||
-                                       !par->params().leftIndent().zero()) {
-                       TeXEnvironementData const data = prepareEnvironement(buf, text,
-                               par, os, texrow, runparams);
-                       par = TeXEnvironment(buf, text, par, os, texrow, runparams);
-                       finishEnvironement(os, texrow, runparams, data);
-               } else {
-                       TeXOnePar(buf, text, par, os, texrow, runparams, everypar);
-                       if (par != paragraphs.end())
-                               par++;
+
+               if (!layout.isEnvironment() && par->params().leftIndent().zero()) {
+                       // This is a standard top level paragraph, TeX it and continue.
+                       TeXOnePar(buf, text, pit, os, texrow, runparams, everypar);
+                       continue;
                }
-               if (distance(lastpar, par) >= distance(lastpar, endpar))
-                       break;
+               
+               TeXEnvironementData const data = prepareEnvironement(buf, text, par,
+                       os, texrow, runparams);
+               // pit can be changed in TeXEnvironment.
+               TeXEnvironment(buf, text, runparams, pit, os, texrow);
+               finishEnvironement(os, texrow, runparams, data);
+       }
+
+       if (pit == runparams.par_end) {
+                       // Make sure that the last paragraph is
+                       // correctly terminated (because TeXOnePar does
+                       // not add a \n in this case)
+                       //os << '\n';
+                       //texrow.newline();
        }
 
        // It might be that we only have a title in this document
@@ -1050,7 +1060,7 @@ void latexParagraphs(Buffer const & buf,
        string const lang_end_command = runparams.use_polyglossia ?
                "\\end{$$lang}" : lyxrc.language_command_end;
        if (maintext && !lyxrc.language_auto_end && !mainlang.empty() &&
-               lastpar->getParLanguage(bparams)->encoding()->package() != Encoding::CJK) {
+               paragraphs.at(lastpit).getParLanguage(bparams)->encoding()->package() != Encoding::CJK) {
                os << from_utf8(subst(lang_end_command,
                                        "$$lang",
                                        mainlang))