]> git.lyx.org Git - lyx.git/blobdiff - src/output_latex.cpp
Disable CheckTeX while buffer is processed
[lyx.git] / src / output_latex.cpp
index bc488ff79af8c85efd26e9dae28958d6a392d687..0ee9af100316836976f16612dbec82a064c58917 100644 (file)
@@ -85,11 +85,12 @@ OutputState * getOutputState()
 }
 
 
-string const & openPolyglossiaLang(OutputState const * state)
+string const & openLanguageName(OutputState const * state)
 {
        // Return a reference to the last active language opened with
-       // polyglossia. If none or when using babel, return a reference
-       // to an empty string.
+       // polyglossia or when using begin/end commands. If none or when
+       // using babel with only a begin command, return a reference to
+       // an empty string.
 
        static string const empty;
 
@@ -102,8 +103,9 @@ string const & openPolyglossiaLang(OutputState const * state)
 bool atSameLastLangSwitchDepth(OutputState const * state)
 {
        // Return true if the actual nest level is the same at which the
-       // language was switched when using polyglossia. Instead, return
-       // always true when using babel.
+       // language was switched when using polyglossia or begin/end
+       // commands. Instead, return always true when using babel with
+       // only a begin command.
 
        return state->lang_switch_depth_.size() == 0
                        ? true
@@ -113,7 +115,7 @@ bool atSameLastLangSwitchDepth(OutputState const * state)
 
 bool isLocalSwitch(OutputState const * state)
 {
-       // Return true if the language was opened by the \text<lang> command.
+       // Return true if the language was opened by a local command switch.
 
        return state->lang_switch_depth_.size()
                && state->lang_switch_depth_.top() < 0;
@@ -209,12 +211,14 @@ static TeXEnvironmentData prepareEnvironment(Buffer const & buf,
                "\\begin{$$lang}" : lyxrc.language_command_begin;
        string const lang_end_command = use_polyglossia ?
                "\\end{$$lang}" : lyxrc.language_command_end;
+       bool const using_begin_end = use_polyglossia ||
+                                       !lang_end_command.empty();
 
        // For polyglossia, switch language outside of environment, if possible.
        if (par_lang != prev_par_lang) {
-               if (!lang_end_command.empty() &&
+               if ((!using_begin_end || langOpenedAtThisLevel(state)) &&
+                   !lang_end_command.empty() &&
                    prev_par_lang != doc_lang &&
-                   atSameLastLangSwitchDepth(state) &&
                    !prev_par_lang.empty()) {
                        os << from_ascii(subst(
                                lang_end_command,
@@ -222,21 +226,21 @@ static TeXEnvironmentData prepareEnvironment(Buffer const & buf,
                                prev_par_lang))
                          // the '%' is necessary to prevent unwanted whitespace
                          << "%\n";
-                       if (use_polyglossia)
-                               popPolyglossiaLang();
+                       if (using_begin_end)
+                               popLanguageName();
                }
 
                // If no language was explicitly opened and we are using
-               // polyglossia, then the current polyglossia language is
-               // the document language.
-               string const & pol_lang = use_polyglossia
+               // polyglossia or begin/end commands, then the current
+               // language is the document language.
+               string const & cur_lang = using_begin_end
                                          && state->lang_switch_depth_.size()
-                                                 ? openPolyglossiaLang(state)
+                                                 ? openLanguageName(state)
                                                  : doc_lang;
 
                if ((lang_end_command.empty() ||
                    par_lang != doc_lang ||
-                   par_lang != pol_lang) &&
+                   par_lang != cur_lang) &&
                    !par_lang.empty()) {
                            string bc = use_polyglossia ?
                                        getPolyglossiaBegin(lang_begin_command, par_lang,
@@ -245,8 +249,8 @@ static TeXEnvironmentData prepareEnvironment(Buffer const & buf,
                            os << bc;
                            // the '%' is necessary to prevent unwanted whitespace
                            os << "%\n";
-                           if (use_polyglossia)
-                                   pushPolyglossiaLang(par_lang);
+                           if (using_begin_end)
+                                   pushLanguageName(par_lang);
                }
        }
 
@@ -258,8 +262,10 @@ static TeXEnvironmentData prepareEnvironment(Buffer const & buf,
                data.leftindent_open = true;
        }
 
-       if (style.isEnvironment()) {
+       if (style.isEnvironment())
                state->nest_level_ += 1;
+
+       if (style.isEnvironment() && !style.latexname().empty()) {
                os << "\\begin{" << from_ascii(style.latexname()) << '}';
                if (!style.latexargs().empty()) {
                        OutputParams rp = runparams;
@@ -310,21 +316,26 @@ static void finishEnvironment(otexstream & os, OutputParams const & runparams,
 
        if (data.style->isEnvironment()) {
                os << breakln;
-               // Close any polyglossia language opened at this nest level
-               if (runparams.use_polyglossia) {
+               bool const using_begin_end =
+                       runparams.use_polyglossia ||
+                               !lyxrc.language_command_end.empty();
+               // Close any language opened at this nest level
+               if (using_begin_end) {
                        while (langOpenedAtThisLevel(state)) {
                                if (isLocalSwitch(state)) {
                                        os << "}";
                                } else {
                                        os << "\\end{"
-                                          << openPolyglossiaLang(state)
+                                          << openLanguageName(state)
                                           << "}%\n";
                                }
-                               popPolyglossiaLang();
+                               popLanguageName();
                        }
                }
                state->nest_level_ -= 1;
-               os << "\\end{" << from_ascii(data.style->latexname()) << "}\n";
+               string const & name = data.style->latexname();
+               if (!name.empty())
+                       os << "\\end{" << from_ascii(name) << "}\n";
                state->prev_env_language_ = data.par_language;
                if (runparams.encoding != data.prev_encoding) {
                        runparams.encoding = data.prev_encoding;
@@ -499,10 +510,10 @@ void getArgInsets(otexstream & os, OutputParams const & runparams, Layout::LaTeX
 }
 
 
-} // namespace anon
+} // namespace
 
 
-void pushPolyglossiaLang(string const & lang_name, bool localswitch)
+void pushLanguageName(string const & lang_name, bool localswitch)
 {
        OutputState * state = getOutputState();
 
@@ -512,7 +523,7 @@ void pushPolyglossiaLang(string const & lang_name, bool localswitch)
 }
 
 
-void popPolyglossiaLang()
+void popLanguageName()
 {
        OutputState * state = getOutputState();
 
@@ -521,43 +532,65 @@ void popPolyglossiaLang()
 }
 
 
-void latexArgInsets(Paragraph const & par, otexstream & os,
-       OutputParams const & runparams, Layout::LaTeXArgMap const & latexargs, string const & prefix)
+string const & openLanguageName()
 {
-       map<int, InsetArgument const *> ilist;
-       vector<string> required;
+       OutputState * state = getOutputState();
 
-       InsetList::const_iterator it = par.insetList().begin();
-       InsetList::const_iterator end = par.insetList().end();
-       for (; it != end; ++it) {
-               if (it->inset->lyxCode() == ARG_CODE) {
-                       InsetArgument const * ins =
-                               static_cast<InsetArgument const *>(it->inset);
-                       if (ins->name().empty())
-                               LYXERR0("Error: Unnamed argument inset!");
-                       else {
-                               string const name = prefix.empty() ? ins->name() : split(ins->name(), ':');
-                               unsigned int const nr = convert<unsigned int>(name);
-                               ilist[nr] = ins;
-                               Layout::LaTeXArgMap::const_iterator const lit =
-                                               latexargs.find(ins->name());
-                               if (lit != latexargs.end()) {
-                                       Layout::latexarg const & arg = (*lit).second;
-                                       if (!arg.requires.empty()) {
-                                               vector<string> req = getVectorFromString(arg.requires);
-                                               required.insert(required.end(), req.begin(), req.end());
-                                       }
-                               }
-                       }
+       return openLanguageName(state);
+}
+
+
+namespace {
+
+void addArgInsets(Paragraph const & par, string const & prefix,
+                 Layout::LaTeXArgMap const & latexargs,
+                 map<int, InsetArgument const *> & ilist,
+                 vector<string> & required)
+{
+       for (auto const & table : par.insetList()) {
+               InsetArgument const * arg = table.inset->asInsetArgument();
+               if (!arg)
+                       continue;
+               if (arg->name().empty()) {
+                       LYXERR0("Error: Unnamed argument inset!");
+                       continue;
+               }
+               string const name = prefix.empty() ?
+                       arg->name() : split(arg->name(), ':');
+               // why converting into an integer?
+               unsigned int const nr = convert<unsigned int>(name);
+               if (ilist.find(nr) == ilist.end())
+                       ilist[nr] = arg;
+               Layout::LaTeXArgMap::const_iterator const lit =
+                       latexargs.find(arg->name());
+               if (lit != latexargs.end()) {
+                       Layout::latexarg const & larg = lit->second;
+                       vector<string> req = getVectorFromString(larg.requires);
+                       move(req.begin(), req.end(), back_inserter(required));
                }
        }
+}
+
+} // namespace
+
+
+void latexArgInsets(Paragraph const & par, otexstream & os,
+                    OutputParams const & runparams,
+                    Layout::LaTeXArgMap const & latexargs,
+                    string const & prefix)
+{
+       map<int, InsetArgument const *> ilist;
+       vector<string> required;
+       addArgInsets(par, prefix, latexargs, ilist, required);
        getArgInsets(os, runparams, latexargs, ilist, required, prefix);
 }
 
 
-void latexArgInsets(ParagraphList const & pars, ParagraphList::const_iterator pit,
-       otexstream & os, OutputParams const & runparams, Layout::LaTeXArgMap const & latexargs,
-       string const & prefix)
+void latexArgInsets(ParagraphList const & pars,
+                    ParagraphList::const_iterator pit,
+                    otexstream & os, OutputParams const & runparams,
+                    Layout::LaTeXArgMap const & latexargs,
+                    string const & prefix)
 {
        map<int, InsetArgument const *> ilist;
        vector<string> required;
@@ -581,44 +614,40 @@ void latexArgInsets(ParagraphList const & pars, ParagraphList::const_iterator pi
        ParagraphList::const_iterator spit = lyx::prev(pit, offset);
 
        for (; spit != pars.end(); ++spit) {
-               if (spit->layout() != current_layout || spit->params().depth() < current_depth)
+               if (spit->layout() != current_layout ||
+                   spit->params().depth() < current_depth)
                        break;
                if (spit->params().depth() > current_depth)
                        continue;
-               InsetList::const_iterator it = spit->insetList().begin();
-               InsetList::const_iterator end = spit->insetList().end();
-               for (; it != end; ++it) {
-                       if (it->inset->lyxCode() == ARG_CODE) {
-                               InsetArgument const * ins =
-                                       static_cast<InsetArgument const *>(it->inset);
-                               if (ins->name().empty())
-                                       LYXERR0("Error: Unnamed argument inset!");
-                               else {
-                                       string const name = prefix.empty() ? ins->name() : split(ins->name(), ':');
-                                       unsigned int const nr = convert<unsigned int>(name);
-                                       if (ilist.find(nr) == ilist.end())
-                                               ilist[nr] = ins;
-                                       Layout::LaTeXArgMap::const_iterator const lit =
-                                                       latexargs.find(ins->name());
-                                       if (lit != latexargs.end()) {
-                                               Layout::latexarg const & arg = (*lit).second;
-                                               if (!arg.requires.empty()) {
-                                                       vector<string> req = getVectorFromString(arg.requires);
-                                                       required.insert(required.end(), req.begin(), req.end());
-                                               }
-                                       }
-                               }
-                       }
-               }
+               addArgInsets(*spit, prefix, latexargs, ilist, required);
        }
        getArgInsets(os, runparams, latexargs, ilist, required, prefix);
 }
 
+
+void latexArgInsetsForParent(ParagraphList const & pars, otexstream & os,
+                             OutputParams const & runparams,
+                             Layout::LaTeXArgMap const & latexargs,
+                             string const & prefix)
+{
+       map<int, InsetArgument const *> ilist;
+       vector<string> required;
+
+       for (Paragraph const & par : pars) {
+               if (par.layout().hasArgs())
+                       // The InsetArguments inside this paragraph refer to this paragraph
+                       continue;
+               addArgInsets(par, prefix, latexargs, ilist, required);
+       }
+       getArgInsets(os, runparams, latexargs, ilist, required, prefix);
+}
+
+
 namespace {
 
 // output the proper paragraph start according to latextype.
 void parStartCommand(Paragraph const & par, otexstream & os,
-                    OutputParams const & runparams, Layout const & style) 
+                    OutputParams const & runparams, Layout const & style)
 {
        switch (style.latextype) {
        case LATEX_COMMAND:
@@ -645,7 +674,7 @@ void parStartCommand(Paragraph const & par, otexstream & os,
        }
 }
 
-} // namespace anon
+} // namespace
 
 // FIXME: this should be anonymous
 void TeXOnePar(Buffer const & buf,
@@ -780,10 +809,12 @@ void TeXOnePar(Buffer const & buf,
                "\\end{$$lang}" : lyxrc.language_command_end;
        // the '%' is necessary to prevent unwanted whitespace
        string lang_command_termination = "%\n";
+       bool const using_begin_end = use_polyglossia ||
+                                       !lang_end_command.empty();
 
        // In some insets (such as Arguments), we cannot use \selectlanguage
        bool const localswitch = text.inset().forceLocalFontSwitch()
-                       || (use_polyglossia && text.inset().forcePlainLayout());
+                       || (using_begin_end && text.inset().forcePlainLayout());
        if (localswitch) {
                lang_begin_command = use_polyglossia ?
                            "\\text$$lang$$opts{" : lyxrc.language_command_local;
@@ -798,17 +829,18 @@ void TeXOnePar(Buffer const & buf,
                                          && priorpar->getDepth() <= par.getDepth())
                                  || priorpar->getDepth() < par.getDepth())))
        {
-               if (!lang_end_command.empty() &&
+               if ((!using_begin_end || langOpenedAtThisLevel(state)) &&
+                   !lang_end_command.empty() &&
                    prev_lang != outer_lang &&
                    !prev_lang.empty() &&
-                   (!use_polyglossia || !style.isEnvironment()))
+                   (!using_begin_end || !style.isEnvironment()))
                {
                        os << from_ascii(subst(lang_end_command,
                                "$$lang",
                                prev_lang))
                           << lang_command_termination;
-                       if (use_polyglossia)
-                               popPolyglossiaLang();
+                       if (using_begin_end)
+                               popLanguageName();
                }
 
                // We need to open a new language if we couldn't close the previous
@@ -817,7 +849,7 @@ void TeXOnePar(Buffer const & buf,
                // outer_language (which is currently in effect once the previous one
                // is closed).
                if ((lang_end_command.empty() || par_lang != outer_lang
-                    || (!use_polyglossia
+                    || (!using_begin_end
                         || (style.isEnvironment() && par_lang != prev_lang)))
                        && !par_lang.empty()) {
                        // If we're inside an inset, and that inset is within an \L or \R
@@ -825,7 +857,7 @@ void TeXOnePar(Buffer const & buf,
                        // 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 (!use_polyglossia
+                       if (!using_begin_end
                            // not for ArabTeX
                                && par_language->lang() != "arabic_arabtex"
                                && outer_language->lang() != "arabic_arabtex"
@@ -858,15 +890,15 @@ void TeXOnePar(Buffer const & buf,
                        }
                        // With CJK, the CJK tag has to be closed first (see below)
                        if (runparams.encoding->package() != Encoding::CJK
-                           && par_lang != openPolyglossiaLang(state)
+                           && (par_lang != openLanguageName(state) || localswitch)
                            && !par_lang.empty()) {
                                string bc = use_polyglossia ?
                                          getPolyglossiaBegin(lang_begin_command, par_lang, par_language->polyglossiaOpts())
                                          : subst(lang_begin_command, "$$lang", par_lang);
                                os << bc;
                                os << lang_command_termination;
-                               if (use_polyglossia)
-                                       pushPolyglossiaLang(par_lang, localswitch);
+                               if (using_begin_end)
+                                       pushLanguageName(par_lang, localswitch);
                        }
                }
        }
@@ -918,15 +950,15 @@ void TeXOnePar(Buffer const & buf,
                                }
                                // With CJK, the CJK tag had to be closed first (see above)
                                if (runparams.encoding->package() == Encoding::CJK
-                                   && par_lang != openPolyglossiaLang(state)
+                                   && par_lang != openLanguageName(state)
                                    && !par_lang.empty()) {
                                        os << from_ascii(subst(
                                                lang_begin_command,
                                                "$$lang",
                                                par_lang))
                                        << lang_command_termination;
-                                       if (use_polyglossia)
-                                               pushPolyglossiaLang(par_lang, localswitch);
+                                       if (using_begin_end)
+                                               pushLanguageName(par_lang, localswitch);
                                }
                                runparams.encoding = encoding;
                        }
@@ -962,30 +994,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:");
@@ -1005,7 +1020,7 @@ void TeXOnePar(Buffer const & buf,
                             && nextpar->getDepth() == par.getDepth())
                    || (atSameLastLangSwitchDepth(state) && nextpar
                            && nextpar->getDepth() < par.getDepth()))
-                       close_lang_switch = use_polyglossia;
+                       close_lang_switch = using_begin_end;
                if (nextpar && par.params().depth() < nextpar->params().depth())
                        pending_newline = true;
                break;
@@ -1015,14 +1030,14 @@ void TeXOnePar(Buffer const & buf,
                if (nextpar
                    && ((nextpar->layout() != par.layout()
                           || nextpar->params().depth() != par.params().depth())
-                       || (!use_polyglossia || par_lang != nextpar_lang)))
+                       || (!using_begin_end || par_lang != nextpar_lang)))
                {
-                       close_lang_switch = use_polyglossia;
+                       close_lang_switch = using_begin_end;
                        break;
                }
        }
-
-       // fall through possible
+       // possible
+       // fall through
        default:
                // we don't need it for the last paragraph!!!
                if (nextpar)
@@ -1048,7 +1063,7 @@ 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 = !use_polyglossia
+       bool closing_rtl_ltr_environment = !using_begin_end
                // not for ArabTeX
                && (par_language->lang() != "arabic_arabtex"
                    && outer_language->lang() != "arabic_arabtex")
@@ -1061,7 +1076,7 @@ void TeXOnePar(Buffer const & buf,
 
        if (closing_rtl_ltr_environment
            || ((runparams.isLastPar || close_lang_switch)
-               && (par_lang != outer_lang || (use_polyglossia
+               && (par_lang != outer_lang || (using_begin_end
                                                && style.isEnvironment()
                                                && par_lang != nextpar_lang)))) {
                // Since \selectlanguage write the language to the aux file,
@@ -1084,7 +1099,7 @@ void TeXOnePar(Buffer const & buf,
                                        ? getPolyglossiaEnvName(current_language)
                                        : current_language->babel();
                                if (!current_lang.empty()
-                                   && current_lang != openPolyglossiaLang(state)) {
+                                   && current_lang != openLanguageName(state)) {
                                        string bc = use_polyglossia ?
                                                    getPolyglossiaBegin(lang_begin_command, current_lang,
                                                                        current_language->polyglossiaOpts())
@@ -1092,25 +1107,28 @@ void TeXOnePar(Buffer const & buf,
                                        os << bc;
                                        pending_newline = !localswitch;
                                        unskip_newline = !localswitch;
-                                       if (use_polyglossia)
-                                               pushPolyglossiaLang(current_lang, localswitch);
+                                       if (using_begin_end)
+                                               pushLanguageName(current_lang, localswitch);
                                }
-                       } else if (!par_lang.empty()) {
-                               // If we are in an environment, we have to close the "outer" language afterwards
-                               string const & pol_lang = openPolyglossiaLang(state);
+                       } else if ((!using_begin_end ||
+                                   langOpenedAtThisLevel(state)) &&
+                                  !par_lang.empty()) {
+                               // If we are in an environment, we have to
+                               // close the "outer" language afterwards
+                               string const & cur_lang = openLanguageName(state);
                                if (!style.isEnvironment()
                                    || (close_lang_switch
                                        && atSameLastLangSwitchDepth(state)
                                        && par_lang != outer_lang
-                                       && (par_lang != pol_lang
-                                           || (pol_lang != outer_lang
+                                       && (par_lang != cur_lang
+                                           || (cur_lang != outer_lang
                                                && nextpar
                                                && style != nextpar->layout())))
                                    || (atSameLastLangSwitchDepth(state)
                                        && state->lang_switch_depth_.size()
-                                       && pol_lang != par_lang))
+                                       && cur_lang != par_lang))
                                {
-                                       if (use_polyglossia && !localswitch)
+                                       if (using_begin_end && !localswitch)
                                                os << breakln;
                                        os << from_ascii(subst(
                                                lang_end_command,
@@ -1118,8 +1136,8 @@ void TeXOnePar(Buffer const & buf,
                                                par_lang));
                                        pending_newline = !localswitch;
                                        unskip_newline = !localswitch;
-                                       if (use_polyglossia)
-                                               popPolyglossiaLang();
+                                       if (using_begin_end)
+                                               popLanguageName();
                                }
                        }
                }
@@ -1135,7 +1153,7 @@ void TeXOnePar(Buffer const & buf,
                        // prevent unwanted whitespace
                        os << '%';
                if (!os.afterParbreak() && !last_was_separator)
-                       os << breakln;
+                       os << '\n';
        }
 
        // if this is a CJK-paragraph and the next isn't, close CJK
@@ -1259,10 +1277,9 @@ void TeXOnePar(Buffer const & buf,
 void latexParagraphs(Buffer const & buf,
                     Text const & text,
                     otexstream & os,
-                    OutputParams const & runparams_in,
+                    OutputParams const & runparams,
                     string const & everypar)
 {
-       OutputParams runparams = runparams_in;
        LASSERT(runparams.par_begin <= runparams.par_end,
                { os << "% LaTeX Output Error\n"; return; } );
 
@@ -1298,6 +1315,10 @@ void latexParagraphs(Buffer const & buf,
                : bparams.language->babel();
        string const lang_begin_command = runparams.use_polyglossia ?
                "\\begin{$$lang}$$opts" : lyxrc.language_command_begin;
+       string const lang_end_command = runparams.use_polyglossia ?
+               "\\end{$$lang}" : lyxrc.language_command_end;
+       bool const using_begin_end = runparams.use_polyglossia ||
+                                       !lang_end_command.empty();
 
        if (maintext && !lyxrc.language_auto_begin &&
            !mainlang.empty()) {
@@ -1308,8 +1329,8 @@ void latexParagraphs(Buffer const & buf,
                          : subst(lang_begin_command, "$$lang", mainlang);
                os << bc;
                os << '\n';
-               if (runparams.use_polyglossia)
-                       pushPolyglossiaLang(mainlang);
+               if (using_begin_end)
+                       pushLanguageName(mainlang);
        }
 
        ParagraphList const & paragraphs = text.paragraphs();
@@ -1342,7 +1363,7 @@ void latexParagraphs(Buffer const & buf,
 
                if (layout.intitle) {
                        if (already_title) {
-                               if (!gave_layout_warning) {
+                               if (!gave_layout_warning && !runparams.dryrun) {
                                        gave_layout_warning = true;
                                        frontend::Alert::warning(_("Error in latexParagraphs"),
                                                        bformat(_("You are using at least one "
@@ -1359,7 +1380,7 @@ void latexParagraphs(Buffer const & buf,
                                                        << "}\n";
                                }
                        }
-               } else if (was_title && !already_title) {
+               } else if (was_title && !already_title && !layout.inpreamble) {
                        if (tclass.titletype() == TITLE_ENVIRONMENT) {
                                os << "\\end{" << from_ascii(tclass.titlename())
                                                << "}\n";
@@ -1387,7 +1408,7 @@ void latexParagraphs(Buffer const & buf,
                        TeXOnePar(buf, text, pit, os, runparams, everypar);
                        continue;
                }
-               
+
                TeXEnvironmentData const data =
                        prepareEnvironment(buf, text, par, os, runparams);
                // pit can be changed in TeXEnvironment.
@@ -1418,16 +1439,14 @@ void latexParagraphs(Buffer const & buf,
 
        // if "auto end" is switched off, explicitly close the language at the end
        // but only if the last par is in a babel or polyglossia language
-       string const lang_end_command = runparams.use_polyglossia ?
-               "\\end{$$lang}" : lyxrc.language_command_end;
        if (maintext && !lyxrc.language_auto_end && !mainlang.empty() &&
                paragraphs.at(lastpit).getParLanguage(bparams)->encoding()->package() != Encoding::CJK) {
                os << from_utf8(subst(lang_end_command,
                                        "$$lang",
                                        mainlang))
                        << '\n';
-               if (runparams.use_polyglossia)
-                       popPolyglossiaLang();
+               if (using_begin_end)
+                       popLanguageName();
        }
 
        // If the last paragraph is an environment, we'll have to close
@@ -1436,15 +1455,15 @@ void latexParagraphs(Buffer const & buf,
                os << "\\end{CJK}\n";
                state->open_encoding_ = none;
        }
-       // Likewise for polyglossia
-       string const & pol_lang = openPolyglossiaLang(state);
-       if (maintext && !is_child && !pol_lang.empty()) {
+       // Likewise for polyglossia or when using begin/end commands
+       string const & cur_lang = openLanguageName(state);
+       if (maintext && !is_child && !cur_lang.empty()) {
                os << from_utf8(subst(lang_end_command,
                                        "$$lang",
-                                       pol_lang))
+                                       cur_lang))
                   << '\n';
-               if (runparams.use_polyglossia)
-                       popPolyglossiaLang();
+               if (using_begin_end)
+                       popLanguageName();
        }
 
        // reset inherited encoding
@@ -1469,13 +1488,13 @@ pair<bool, int> switchEncoding(odocstream & os, BufferParams const & bparams,
        // * with useNonTeXFonts: "utf8plain",
        // * with XeTeX and TeX fonts: "ascii" (inputenc fails),
        // * with LuaTeX and TeX fonts: only one encoding accepted by luainputenc.
-       if (runparams.isFullUnicode())
+       if (runparams.isFullUnicode() || newEnc.name() == "inherit")
                return make_pair(false, 0);
 
        Encoding const & oldEnc = *runparams.encoding;
        bool moving_arg = runparams.moving_arg;
        // If we switch from/to CJK, we need to switch anyway, despite custom inputenc
-       bool const from_to_cjk = 
+       bool const from_to_cjk =
                (oldEnc.package() == Encoding::CJK && newEnc.package() != Encoding::CJK)
                || (oldEnc.package() != Encoding::CJK && newEnc.package() == Encoding::CJK);
        if (!force && !from_to_cjk