commit 262e436fc3e8e2a61e729b774b4d501bb7a7c83e
Author: Juergen Spitzmueller <[email protected]>
Date:   Thu Mar 14 14:24:43 2019 +0100

    Move labels and insets out of moving arguments
    
    Fixes: #2154
---
 src/OutputParams.cpp        |    4 ++--
 src/OutputParams.h          |   13 +++++++++++++
 src/Paragraph.cpp           |    3 +++
 src/insets/InsetCaption.cpp |    9 +++++++++
 src/insets/InsetIndex.cpp   |   11 ++++++++++-
 src/insets/InsetLabel.cpp   |   14 ++++++++++++++
 src/insets/InsetLabel.h     |    2 ++
 src/insets/InsetText.cpp    |    2 ++
 src/output_latex.cpp        |   33 ++++++++++++++++++++++++++++++++-
 9 files changed, 87 insertions(+), 4 deletions(-)

diff --git a/src/OutputParams.cpp b/src/OutputParams.cpp
index cb9d50c..36816c2 100644
--- a/src/OutputParams.cpp
+++ b/src/OutputParams.cpp
@@ -24,8 +24,8 @@ OutputParams::OutputParams(Encoding const * enc)
          master_language(0), encoding(enc), free_spacing(false),
          use_babel(false), use_polyglossia(false), use_CJK(false),
          use_indices(false), use_japanese(false), linelen(0), depth(0),
-         exportdata(new ExportData), inDisplayMath(false), 
wasDisplayMath(false),
-         inComment(false), openbtUnit(false), only_childbibs(false),
+         exportdata(new ExportData), postpone_fragile_stuff(false), 
inDisplayMath(false),
+         wasDisplayMath(false), inComment(false), openbtUnit(false), 
only_childbibs(false),
          inTableCell(NO), inFloat(NONFLOAT),
          inIndexEntry(false), inIPA(false), inDeletedInset(0),
          changeOfDeletedInset(Change::UNCHANGED),
diff --git a/src/OutputParams.h b/src/OutputParams.h
index ef7c16d..5faa68e 100644
--- a/src/OutputParams.h
+++ b/src/OutputParams.h
@@ -197,6 +197,19 @@ public:
        */
        std::shared_ptr<ExportData> exportdata;
 
+       /** Store labels, index entries (etc.) (in \ref post_macro)
+        *  and output them later. This is used in particular to get
+        *  labels and index entries (and potentially other fragile commands)
+        *  outside of moving arguments (bug 2154)
+        */
+       bool postpone_fragile_stuff;
+
+       /** Stuff to be postponed and output after the current macro
+        *  (if \ref postpone_fragile_stuff is true). Used for labels and index
+        *  entries in commands with moving arguments (\\section, \\caption 
etc.)
+        */
+       mutable docstring post_macro;
+
        /** Whether we are entering a display math inset.
         *  Needed to correctly strike out deleted math in change tracking.
         */
diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index 27aecb5..f1fc7bd 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -2833,6 +2833,9 @@ void Paragraph::latex(BufferParams const & bparams,
                // such as Note that do not produce any output, so that no
                // command is ever executed but its opening was recorded.
                runparams.inulemcmd = rp.inulemcmd;
+
+               // And finally, pass the post_macros upstream
+               runparams.post_macro = rp.post_macro;
        }
 
        // If we have an open font definition, we have to close it
diff --git a/src/insets/InsetCaption.cpp b/src/insets/InsetCaption.cpp
index 0ebbcea..941047f 100644
--- a/src/insets/InsetCaption.cpp
+++ b/src/insets/InsetCaption.cpp
@@ -264,7 +264,16 @@ void InsetCaption::latex(otexstream & os,
        // \caption{...}, later we will make it take advantage
        // of the one of the caption packages. (Lgb)
        OutputParams runparams = runparams_in;
+       // Some fragile commands (labels, index entries)
+       // are output after the caption (#2154)
+       runparams.postpone_fragile_stuff = true;
        InsetText::latex(os, runparams);
+       if (!runparams.post_macro.empty()) {
+               // Output the stored fragile commands (labels, indices etc.)
+               // that need to be output after the caption.
+               os << runparams.post_macro;
+               runparams.post_macro.clear();
+       }
        // Backwards compatibility: We always had a linebreak after
        // the caption (see #8514)
        os << breakln;
diff --git a/src/insets/InsetIndex.cpp b/src/insets/InsetIndex.cpp
index 9ac7680..f3fafce 100644
--- a/src/insets/InsetIndex.cpp
+++ b/src/insets/InsetIndex.cpp
@@ -59,11 +59,13 @@ InsetIndex::InsetIndex(Buffer * buf, InsetIndexParams const 
& params)
 {}
 
 
-void InsetIndex::latex(otexstream & os, OutputParams const & runparams_in) 
const
+void InsetIndex::latex(otexstream & ios, OutputParams const & runparams_in) 
const
 {
        OutputParams runparams(runparams_in);
        runparams.inIndexEntry = true;
 
+       otexstringstream os;
+
        if (buffer().masterBuffer()->params().use_indices && 
!params_.index.empty()
            && params_.index != "idx") {
                os << "\\sindex[";
@@ -170,6 +172,13 @@ void InsetIndex::latex(otexstream & os, OutputParams const 
& runparams_in) const
                os << "|" << cmd;
        }
        os << '}';
+
+       // In macros with moving arguments, such as \section,
+       // we store the index and output it after the macro (#2154)
+       if (runparams_in.postpone_fragile_stuff)
+               runparams_in.post_macro += os.str();
+       else
+               ios << os.release();
 }
 
 
diff --git a/src/insets/InsetLabel.cpp b/src/insets/InsetLabel.cpp
index e325f1e..9d6a031 100644
--- a/src/insets/InsetLabel.cpp
+++ b/src/insets/InsetLabel.cpp
@@ -28,6 +28,7 @@
 #include "output_xhtml.h"
 #include "ParIterator.h"
 #include "sgml.h"
+#include "texstream.h"
 #include "Text.h"
 #include "TextClass.h"
 #include "TocBackend.h"
@@ -294,6 +295,19 @@ void InsetLabel::doDispatch(Cursor & cur, FuncRequest & 
cmd)
 }
 
 
+void InsetLabel::latex(otexstream & os, OutputParams const & runparams_in) 
const
+{
+       OutputParams runparams = runparams_in;
+       docstring command = getCommand(runparams);
+       // In macros with moving arguments, such as \section,
+       // we store the label and output it after the macro (#2154)
+       if (runparams_in.postpone_fragile_stuff)
+               runparams_in.post_macro += command;
+       else
+               os << command;
+}
+
+
 int InsetLabel::plaintext(odocstringstream & os,
         OutputParams const &, size_t) const
 {
diff --git a/src/insets/InsetLabel.h b/src/insets/InsetLabel.h
index 92c3380..ef4fed9 100644
--- a/src/insets/InsetLabel.h
+++ b/src/insets/InsetLabel.h
@@ -48,6 +48,8 @@ public:
        ///
        InsetCode lyxCode() const { return LABEL_CODE; }
        ///
+       void latex(otexstream & os, OutputParams const & runparams_in) const;
+       ///
        int plaintext(odocstringstream & ods, OutputParams const & op,
                      size_t max_length = INT_MAX) const;
        ///
diff --git a/src/insets/InsetText.cpp b/src/insets/InsetText.cpp
index 8f2ba0c..85da8dd 100644
--- a/src/insets/InsetText.cpp
+++ b/src/insets/InsetText.cpp
@@ -509,6 +509,8 @@ void InsetText::latex(otexstream & os, OutputParams const & 
runparams) const
        // Output the contents of the inset
        latexParagraphs(buffer(), text_, os, rp);
        runparams.encoding = rp.encoding;
+       // Pass the post_macros upstream
+       runparams.post_macro = rp.post_macro;
 
        if (!il.rightdelim().empty())
                os << il.rightdelim();
diff --git a/src/output_latex.cpp b/src/output_latex.cpp
index d515ef4..8ccb9f5 100644
--- a/src/output_latex.cpp
+++ b/src/output_latex.cpp
@@ -777,6 +777,11 @@ void TeXOnePar(Buffer const & buf,
        if (style.pass_thru) {
                Font const outerfont = text.outerFont(pit);
                parStartCommand(par, os, runparams, style);
+               if (style.isCommand() && style.needprotect)
+                       // Due to the moving argument, some fragile
+                       // commands (labels, index entries)
+                       // are output after this command (#2154)
+                       runparams.postpone_fragile_stuff = true;
                if (intitle_command)
                        os << '{';
 
@@ -861,6 +866,11 @@ void TeXOnePar(Buffer const & buf,
        // (see #10849); thus open the command here.
        if (intitle_command) {
                parStartCommand(par, os, runparams, style);
+               if (style.isCommand() && style.needprotect)
+                       // Due to the moving argument, some fragile
+                       // commands (labels, index entries)
+                       // are output after this command (#2154)
+                       runparams.postpone_fragile_stuff = true;
                os << '{';
        }
 
@@ -1071,8 +1081,14 @@ void TeXOnePar(Buffer const & buf,
 
        // For InTitle commands, we already started the command before
        // the language switch
-       if (!intitle_command)
+       if (!intitle_command) {
                parStartCommand(par, os, runparams, style);
+               if (style.isCommand() && style.needprotect)
+                       // Due to the moving argument, some fragile
+                       // commands (labels, index entries)
+                       // are output after this command (#2154)
+                       runparams.postpone_fragile_stuff = true;
+       }
 
        Font const outerfont = text.outerFont(pit);
 
@@ -1092,6 +1108,12 @@ void TeXOnePar(Buffer const & buf,
                        os << '}';
                        if (!style.postcommandargs().empty())
                                latexArgInsets(par, os, runparams, 
style.postcommandargs(), "post:");
+                       if (!runparams.post_macro.empty()) {
+                               // Output the stored fragile commands (labels, 
indices etc.)
+                               // that need to be output after the command 
with moving argument.
+                               os << runparams.post_macro;
+                               runparams.post_macro.clear();
+                       }
                        if (runparams.encoding != prev_encoding) {
                                runparams.encoding = prev_encoding;
                                os << setEncoding(prev_encoding->iconvName());
@@ -1246,6 +1268,12 @@ void TeXOnePar(Buffer const & buf,
                        os << '}';
                        if (!style.postcommandargs().empty())
                                latexArgInsets(par, os, runparams, 
style.postcommandargs(), "post:");
+                       if (!runparams.post_macro.empty()) {
+                               // Output the stored fragile commands (labels, 
indices etc.)
+                               // that need to be output after the command 
with moving argument.
+                               os << runparams.post_macro;
+                               runparams.post_macro.clear();
+                       }
                        if (runparams.encoding != prev_encoding) {
                                runparams.encoding = prev_encoding;
                                os << setEncoding(prev_encoding->iconvName());
@@ -1324,6 +1352,9 @@ void TeXOnePar(Buffer const & buf,
        else
                runparams_in.encoding = runparams.encoding;
 
+       // Also pass the post_macros upstream
+       runparams_in.post_macro = runparams.post_macro;
+
 
        // we don't need a newline for the last paragraph!!!
        // Note from JMarc: we will re-add a \n explicitly in

Reply via email to