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