[LyX/master] More appropriate label output in plaintext copy (part of #7558)

Juergen Spitzmueller spitz at lyx.org
Thu Aug 13 11:10:17 UTC 2026


commit 072117082d330dc3ac85bc8ec9e2c57e19511c5d
Author: Juergen Spitzmueller <spitz at lyx.org>
Date:   Thu Aug 13 13:07:31 2026 +0200

    More appropriate label output in plaintext copy (part of #7558)
    
    * Output the label only once in a paragraph sequence of the same layout
      (analoguous to the workarea and the LaTeX output)
    * output ABOVE and CENTERED labels in an own paragraph
    
    For the search context, the output is not changed.
---
 src/Cursor.cpp    | 27 ++++++++++++++++++++++++---
 src/Paragraph.cpp | 11 ++++++++---
 2 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/src/Cursor.cpp b/src/Cursor.cpp
index c41fe2c9c9..7683dcd1e2 100644
--- a/src/Cursor.cpp
+++ b/src/Cursor.cpp
@@ -350,10 +350,15 @@ docstring CursorData::selectionAsString(bool const with_label, bool const skipde
 
 	int label = with_label
 		? AS_STR_LABEL | AS_STR_INSETS : AS_STR_INSETS;
-	if (skipdelete)
+	// In STATIC, ABOVE and CENTERED sequences, the label
+	// is only added to the first paragraph
+	int seq_label = AS_STR_INSETS;
+	if (skipdelete) {
 		label = with_label
 				? AS_STR_LABEL | AS_STR_INSETS | AS_STR_SKIPDELETE
 				: AS_STR_INSETS | AS_STR_SKIPDELETE;
+		seq_label = AS_STR_INSETS | AS_STR_SKIPDELETE;
+	}
 
 	idx_type const startidx = selBegin().idx();
 	idx_type const endidx = selEnd().idx();
@@ -382,12 +387,28 @@ docstring CursorData::selectionAsString(bool const with_label, bool const skipde
 	// The paragraphs in between (if any)
 	for (pit_type pit = startpit + 1; pit != endpit; ++pit) {
 		Paragraph const & par = pars[pit];
-		result += par.asString(0, par.size(), label)
+		Layout const & lay = par.layout();
+		bool const is_first =
+			text()->isFirstInSequence(pit) || !lay.isParagraphGroup();
+		// The actual label depends on the label type and whether this
+		// is the first paragraph in a sequence
+		int act_label = (lay.labelIsInline()
+				&& (lay.labeltype != LABEL_STATIC || is_first))
+				|| (is_first && lay.labelIsAbove()) ? label : seq_label;
+		result += par.asString(0, par.size(), act_label)
 			+ parbreak(this);
 	}
 
 	// Last paragraph in selection
-	result += pars[endpit].asString(0, endpos, label);
+	Layout const & lay = pars[endpit].layout();
+	bool const is_first =
+		text()->isFirstInSequence(endpit) || !lay.isParagraphGroup();
+	// The actual label depends on the label type and whether this
+	// is the first paragraph in a sequence
+	int act_label = (lay.labelIsInline()
+			&& (lay.labeltype != LABEL_STATIC || is_first))
+			|| (is_first && lay.labelIsAbove()) ? label : seq_label;
+	result += pars[endpit].asString(0, endpos, act_label);
 
 	return result;
 }
diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index 63f6cbeecd..8ed864f761 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -4596,15 +4596,20 @@ docstring Paragraph::asString(int options) const
 }
 
 
-docstring Paragraph::asString(pos_type beg, pos_type end, int options, const OutputParams *runparams) const
+docstring Paragraph::asString(pos_type beg, pos_type end, int options, const OutputParams * runparams) const
 {
 	odocstringstream os;
 
 	if (beg == 0
 	    && options & AS_STR_LABEL
 	    && d->layout_->labeltype != LABEL_MANUAL
-	    && !d->params_.labelString().empty())
-		os << d->params_.labelString() << ' ';
+	    && !d->params_.labelString().empty()) {
+		os << d->params_.labelString();
+		if (layout().labelIsAbove() && !runparams->find_effective())
+			os << "\n\n";
+		else
+			os << " ";
+	}
 
 	for (pos_type i = beg; i < end; ++i) {
 		if ((options & AS_STR_SKIPDELETE) && isDeleted(i))


More information about the lyx-cvs mailing list