commit bd879efaa8107b9064124c186967a500a53e7807
Author: Juergen Spitzmueller <sp...@lyx.org>
Date:   Sat Dec 23 13:25:13 2017 +0100

    Fix switch of language and line spacing in InTitle commands.
    
    Fixes: #9332, #10849
    (cherry picked from commit 49e3f8e830a7c8a15f4d9f73e4dab78e93b24bf7)
---
 src/Paragraph.cpp    |    8 +++-
 src/Spacing.cpp      |   22 ++++++++++++
 src/Spacing.h        |    3 ++
 src/output_latex.cpp |   88 +++++++++++++++++++++++++++++++++++++-------------
 4 files changed, 96 insertions(+), 25 deletions(-)

diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index c905856..dd0920b 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -2426,7 +2426,9 @@ void Paragraph::latex(BufferParams const & bparams,
 
        // if the paragraph is empty, the loop will not be entered at all
        if (empty()) {
-               if (style.isCommand()) {
+               // For InTitle commands, we have already opened a group
+               // in output_latex::TeXOnePar.
+               if (style.isCommand() && style.intitle) {
                        os << '{';
                        ++column;
                }
@@ -2464,7 +2466,9 @@ void Paragraph::latex(BufferParams const & bparams,
                                os << "}] ";
                                column +=3;
                        }
-                       if (style.isCommand()) {
+                       // For InTitle commands, we have already opened a group
+                       // in output_latex::TeXOnePar.
+                       if (style.isCommand() && !style.intitle) {
                                os << '{';
                                ++column;
                        }
diff --git a/src/Spacing.cpp b/src/Spacing.cpp
index cd5816e..9ac8345 100644
--- a/src/Spacing.cpp
+++ b/src/Spacing.cpp
@@ -99,6 +99,18 @@ string envName(Spacing::Space space, bool useSetSpace)
        return useSetSpace ? name : support::ascii_lowercase(name);
 }
 
+string cmdName(Spacing::Space space, bool useSetSpace)
+{
+       static char const * const cmd_names[]
+               = { "SingleSpacing", "OnehalfSpacing", "DoubleSpacing", 
"SetStretch", ""};
+       string const name = cmd_names[space];
+
+       if (useSetSpace && name == "SetStretch")
+               return "setSpacing";
+
+       return useSetSpace ? name : support::ascii_lowercase(name);
+}
+
 } // namespace
 
 string const Spacing::writeEnvirBegin(bool useSetSpace) const
@@ -118,6 +130,16 @@ string const Spacing::writeEnvirEnd(bool useSetSpace) const
 }
 
 
+string const Spacing::writeCmd(bool useSetSpace) const
+{
+       string const name = cmdName(space, useSetSpace);
+       if (space == Other)
+               return "\\" + name + "{" + getValueAsString() + '}';
+       else
+               return name.empty() ? string() : "\\" + name + "{}";
+}
+
+
 string const Spacing::writePreamble(bool useSetSpace) const
 {
        string preamble;
diff --git a/src/Spacing.h b/src/Spacing.h
index 274cfc2..7311f79 100644
--- a/src/Spacing.h
+++ b/src/Spacing.h
@@ -62,6 +62,9 @@ public:
        std::string const writeEnvirEnd(bool useSetSpace) const;
        /// useSetSpace is true when using the variant supported by
        /// the memoir class.
+       std::string const writeCmd(bool useSetSpace) const;
+       /// useSetSpace is true when using the variant supported by
+       /// the memoir class.
        std::string const writePreamble(bool useSetSpace) const;
 
 private:
diff --git a/src/output_latex.cpp b/src/output_latex.cpp
index 0ee9af1..5cac0ad 100644
--- a/src/output_latex.cpp
+++ b/src/output_latex.cpp
@@ -812,6 +812,14 @@ void TeXOnePar(Buffer const & buf,
        bool const using_begin_end = use_polyglossia ||
                                        !lang_end_command.empty();
 
+       // For InTitle commands, we need to switch the language inside the 
command
+       // (see #10849); thus open the command here.
+       bool const intitle_command = style.intitle && style.latextype == 
LATEX_COMMAND;
+       if (intitle_command) {
+               parStartCommand(par, os, runparams, style);
+               os << '{';
+       }
+
        // In some insets (such as Arguments), we cannot use \selectlanguage
        bool const localswitch = text.inset().forceLocalFontSwitch()
                        || (using_begin_end && text.inset().forcePlainLayout());
@@ -975,19 +983,34 @@ void TeXOnePar(Buffer const & buf,
                        os << "\n\\appendix\n";
                }
 
-               if (!par.params().spacing().isDefault()
-                       && (pit == 0 || !priorpar->hasSameLayout(par)))
-               {
-                       os << 
from_ascii(par.params().spacing().writeEnvirBegin(useSetSpace))
-                           << '\n';
-               }
+               // InTitle commands must use switches (not environments)
+               // inside the commands (see #9332)
+               if (style.intitle) {
+                       if (!par.params().spacing().isDefault())
+                       {
+                               if (runparams.moving_arg)
+                                       os << "\\protect";
+                               os << 
from_ascii(par.params().spacing().writeCmd(useSetSpace));
+                       }
+               } else {
+                       if (!par.params().spacing().isDefault()
+                               && (pit == 0 || !priorpar->hasSameLayout(par)))
+                       {
+                               os << 
from_ascii(par.params().spacing().writeEnvirBegin(useSetSpace))
+                                   << '\n';
+                       }
 
-               if (style.isCommand()) {
-                       os << '\n';
+                       if (style.isCommand()) {
+                               os << '\n';
+                       }
                }
        }
 
-       parStartCommand(par, os, runparams, style);
+       // For InTitle commands, we already started the command before
+       // the language switch
+       if (!intitle_command)
+               parStartCommand(par, os, runparams, style);
+
        Font const outerfont = text.outerFont(pit);
 
        // FIXME UNICODE
@@ -1000,13 +1023,16 @@ void TeXOnePar(Buffer const & buf,
 
        bool const is_command = style.isCommand();
 
-       if (is_command) {
-               os << '}';
-               if (!style.postcommandargs().empty())
-                       latexArgInsets(par, os, runparams, 
style.postcommandargs(), "post:");
-               if (runparams.encoding != prev_encoding) {
-                       runparams.encoding = prev_encoding;
-                       os << setEncoding(prev_encoding->iconvName());
+       // 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.encoding != prev_encoding) {
+                               runparams.encoding = prev_encoding;
+                               os << setEncoding(prev_encoding->iconvName());
+                       }
                }
        }
 
@@ -1039,12 +1065,13 @@ void TeXOnePar(Buffer const & buf,
        // possible
        // fall through
        default:
-               // we don't need it for the last paragraph!!!
-               if (nextpar)
+               // we don't need it for the last paragraph and in InTitle 
commands!!!
+               if (nextpar && !intitle_command)
                        pending_newline = true;
        }
 
-       if (par.allowParagraphCustomization()) {
+       // InTitle commands use switches (not environments) for space settings
+       if (par.allowParagraphCustomization() && !style.intitle) {
                if (!par.params().spacing().isDefault()
                        && (runparams.isLastPar || 
!nextpar->hasSameLayout(par))) {
                        if (pending_newline)
@@ -1060,9 +1087,10 @@ 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.
+       // Closing the language is needed for the last paragraph in a given 
language
+       // as well as for any InTitleCommand (since these set the language 
locally);
+       // 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 = !using_begin_end
                // not for ArabTeX
                && (par_language->lang() != "arabic_arabtex"
@@ -1074,7 +1102,8 @@ void TeXOnePar(Buffer const & buf,
                &&((nextpar && par_lang != nextpar_lang)
                   || (runparams.isLastPar && par_lang != outer_lang));
 
-       if (closing_rtl_ltr_environment
+       if ((intitle_command && using_begin_end)
+           || closing_rtl_ltr_environment
            || ((runparams.isLastPar || close_lang_switch)
                && (par_lang != outer_lang || (using_begin_end
                                                && style.isEnvironment()
@@ -1145,6 +1174,19 @@ void TeXOnePar(Buffer const & buf,
        if (closing_rtl_ltr_environment)
                os << "}";
 
+       // 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.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);
 

Reply via email to