[LyX features/feature/docbook] WIP: lists seem to work properly!

Thibaut Cuvelier tcuvelier at lyx.org
Sat Aug 29 01:30:25 UTC 2020


The branch, feature/docbook, has been updated.
  discards  a0a88840cdf96e3f21386c55c54294d452a7b7c9 (commit)
  discards  cbbba04773004ef1331afc91c5afddde0b10405a (commit)
  discards  b1a683c696abc4129adb6111e0be42797365c6de (commit)
  discards  4d038e49c39d8e08448b8f987b878f694922ab15 (commit)
  discards  ddd605523443078207e95614bb151dc97cbb33a3 (commit)
  discards  eee7387c4912589bec354d967a925adb1143d744 (commit)
  discards  d4801b8d49e386a15c094f08534d1b8f2f1eeb13 (commit)
  discards  d7c6cc78d4f27777062032c9dd8fee54a1d200e2 (commit)
  discards  61b0383cffeb0b586e28b987a11c5bb44f02363c (commit)
  discards  8f160bb840428aa7059e18808c0ccf957838bea0 (commit)
  discards  4f2edfa7966deba19c823c054695be9c0376b122 (commit)
  discards  9bbf953d8ca5830ccad2a6f6aeda3ab46205c5fb (commit)
  discards  fc5f06a7cb7c57d889c6733030cabbbc3e5e2a69 (commit)
  discards  9f9f7302771535ad9b789c3b6570143441d2590a (commit)
  discards  e5e81a94489ed4a7ad4c898931de980b5cd7f233 (commit)
  discards  a83b01665274f087f5a82d5130161e7d4ed47dfb (commit)
  discards  7fba82b4bcf0473f266078220262acd5a5ac2ab0 (commit)

This update added new revisions after undoing existing revisions.  That is
to say, the old revision is not a strict subset of the new revision.  This
situation occurs when you --force push a change and generate a repository
containing something like this:

 * -- * -- B -- O -- O -- O (a0a88840cdf96e3f21386c55c54294d452a7b7c9)
            \
             N -- N -- N (47ce2b2f69a7da79951d627a82b6d4b6412c81a6)

When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.

- Log -----------------------------------------------------------------

commit 47ce2b2f69a7da79951d627a82b6d4b6412c81a6
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 03:53:17 2020 +0200

    WIP: lists seem to work properly!

diff --git a/autotests/export/docbook/lists.lyx b/autotests/export/docbook/lists.lyx
index 2e7c0e0..3e8e72a 100644
--- a/autotests/export/docbook/lists.lyx
+++ b/autotests/export/docbook/lists.lyx
@@ -87,10 +87,6 @@ Test document
 \end_layout
 
 \begin_layout Standard
-\begin_inset Note Note
-status open
-
-\begin_layout Plain Layout
 A simple list: 
 \end_layout
 
@@ -110,7 +106,7 @@ I'm the second line
 Third item
 \end_layout
 
-\begin_layout Plain Layout
+\begin_layout Standard
 A simple enumerated list: 
 \end_layout
 
@@ -126,7 +122,7 @@ Second item on two lines
 I'm the second line
 \end_layout
 
-\begin_layout Plain Layout
+\begin_layout Standard
 Nested lists:
 \end_layout
 
@@ -158,11 +154,6 @@ Second second item
 \end_layout
 
 \end_deeper
-\end_inset
-
-
-\end_layout
-
 \begin_layout Standard
 A complex list:
 \end_layout
@@ -204,10 +195,6 @@ Text after second item
 
 \end_deeper
 \begin_layout Standard
-\begin_inset Note Note
-status open
-
-\begin_layout Plain Layout
 A very complex list:
 \end_layout
 
@@ -224,20 +211,11 @@ First first item
 First second item
 \end_layout
 
-\begin_layout Plain Layout
+\begin_layout Standard
 Text after first item
 \end_layout
 
 \end_deeper
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\begin_inset Note Note
-status open
-
 \begin_layout Itemize
 Second item
 \end_layout
@@ -251,15 +229,10 @@ Second first item
 Second second item
 \end_layout
 
-\begin_layout Plain Layout
+\begin_layout Standard
 Text after second item
 \end_layout
 
 \end_deeper
-\end_inset
-
-
-\end_layout
-
 \end_body
 \end_document
diff --git a/autotests/export/docbook/lists.xml b/autotests/export/docbook/lists.xml
index 4b72f7f..c0dad39 100644
--- a/autotests/export/docbook/lists.xml
+++ b/autotests/export/docbook/lists.xml
@@ -3,7 +3,30 @@
   See http://www.lyx.org/ for more information -->
 <article xml:lang="en_US" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:xi="http://www.w3.org/2001/XInclude" version="5.2">
 <title>Test document</title>
-<para>A complex list:</para>
+<para>A simple list: </para>
+<itemizedlist>
+<listitem>
+<para>First item</para>
+</listitem>
+<listitem>
+<para>Second item on two lines</para>
+<para>I'm the second line</para>
+</listitem>
+<listitem>
+<para>Third item</para>
+</listitem>
+</itemizedlist>
+<para>A simple enumerated list: </para>
+<orderedlist>
+<listitem>
+<para>First item</para>
+</listitem>
+<listitem>
+<para>Second item on two lines</para>
+<para>I'm the second line</para>
+</listitem>
+</orderedlist>
+<para>Nested lists:</para>
 <itemizedlist>
 <listitem>
 <para>First item</para>
@@ -16,9 +39,33 @@
 </listitem>
 </itemizedlist>
 </listitem>
-Text after first item
+<listitem>
+<para>Second item</para>
+<itemizedlist>
+<listitem>
+<para>Second first item</para>
+</listitem>
+<listitem>
+<para>Second second item</para>
+</listitem>
+</itemizedlist>
+</listitem>
+</itemizedlist>
+<para>A complex list:</para>
+<itemizedlist>
+<listitem>
+<para>First item</para>
 <itemizedlist>
 <listitem>
+<para>First first item</para>
+</listitem>
+<listitem>
+<para>First second item</para>
+</listitem>
+</itemizedlist>
+<para>Text after first item</para>
+</listitem>
+<listitem>
 <para>Second item</para>
 <itemizedlist>
 <listitem>
@@ -28,8 +75,34 @@ Text after first item
 <para>Second second item</para>
 </listitem>
 </itemizedlist>
+<para>Text after second item</para>
+</listitem>
+</itemizedlist>
+<para>A very complex list:</para>
+<itemizedlist>
+<listitem>
+<para>First item</para>
+<itemizedlist>
+<listitem>
+<para>First first item</para>
+</listitem>
+<listitem>
+<para>First second item</para>
 </listitem>
-Text after second item
 </itemizedlist>
+<para>Text after first item</para>
+</listitem>
+<listitem>
+<para>Second item</para>
+<orderedlist>
+<listitem>
+<para>Second first item</para>
+</listitem>
+<listitem>
+<para>Second second item</para>
+</listitem>
+</orderedlist>
+<para>Text after second item</para>
+</listitem>
 </itemizedlist>
 </article>
\ No newline at end of file
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index ba1fd47..e8edee1 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -693,8 +693,10 @@ ParagraphList::const_iterator makeListEnvironment(Text const &text,
 		// By construction, with findEndOfEnvironment, depth can only stay constant or increase, never decrease.
 		depth_type currentDepth = par->getDepth();
 		++par;
-		if (par != envend && par->getDepth() != currentDepth)
-			par = makeAny(buf, xs, runparams, text, par);
+		while (par != envend && par->getDepth() != currentDepth)
+			par = makeAny(text, buf, xs, runparams, par);
+		// Usually, this loop only makes one iteration, except in complex scenarios, like an item with a paragraph,
+		// a list, and another paragraph.
 
 		// Close the item.
 		closeTag(xs, style.docbookitemwrappertag(), style.docbookitemwrappertagtype());
@@ -706,108 +708,6 @@ ParagraphList::const_iterator makeListEnvironment(Text const &text,
 	closeTag(xs, envstyle.docbookwrappertag(), envstyle.docbookwrappertagtype());
 
 	return envend;
-
-//	xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- ENV DEPTH: " + to_string(par->getDepth()) + ". ");
-//	if (prevpar)
-//		xs << XMLStream::ESCAPE_NONE << from_ascii("PREV DEPTH: " + to_string(prevpar->getDepth()) + ". ");
-//	if (par != end) {
-//		auto nextpar = par;
-//		++nextpar;
-//		xs << XMLStream::ESCAPE_NONE << from_ascii("NEXT DEPTH: " + to_string(nextpar->getDepth()));
-//	}
-//	xs << XMLStream::ESCAPE_NONE << from_ascii(" -->");
-
-//	// Generate the contents of this environment. There is a special case if this is like some environment.
-//	Layout const & style = par->layout();
-//	if (envstyle.latextype == LATEX_COMMAND) {
-//		// Nothing to do (otherwise, infinite loops).
-//	} else if (envstyle.latextype == LATEX_ENVIRONMENT ||
-//	           envstyle.latextype == LATEX_LIST_ENVIRONMENT ||
-//	           envstyle.latextype == LATEX_ITEM_ENVIRONMENT) {
-//		// Open a wrapper tag if needed.
-//		if (envstyle.docbookitemwrappertag() != "NONE")
-//			openTag(xs, envstyle.docbookitemwrappertag(), envstyle.docbookitemwrapperattr(), envstyle.docbookitemwrappertagtype());
-//
-//		// Generate the label, if need be. If it is taken from the text, sep != 0 and corresponds to the first
-//		// character after the label.
-//		pos_type sep = 0;
-//		if (envstyle.labeltype != LABEL_NO_LABEL && envstyle.docbookitemlabeltag() != "NONE") {
-//			// At least one condition must be met:
-//			//  - this environment is not a list
-//			//  - if this is a list, the label must not be manual (i.e. it must be taken from the layout)
-//			if (envstyle.latextype != LATEX_LIST_ENVIRONMENT || envstyle.labeltype != LABEL_MANUAL) {
-//				// Usual cases: maybe there is something specified at the layout level. Highly unlikely, though.
-//				docstring const lbl = par->params().labelString();
-//
-//				if (lbl.empty()) {
-//					xs << xml::CR();
-//				} else {
-//					openLabelTag(xs, envstyle);
-//					xs << lbl;
-//					closeLabelTag(xs, envstyle);
-//				}
-//			} else {
-//				// Only variablelist gets here (or similar items defined as an extension in the layout).
-//				openLabelTag(xs, envstyle);
-//				sep = par->firstWordDocBook(xs, runparams);
-//				closeLabelTag(xs, envstyle);
-//			}
-//		}
-//
-//		// Maybe the item is completely empty, i.e. if the first word ends at the end of the current paragraph
-//		// AND if the next paragraph doesn't have the same depth (if there is such a paragraph).
-//		// Common case: there is only the first word on the line, but there is a nested list instead
-//		// of more text.
-//		bool emptyItem = false;
-//		if (sep == par->size()) { // If the separator is already at the end of this paragraph...
-//			auto next_par = par;
-//			++next_par;
-//			if (next_par == text.paragraphs().end()) // There is no next paragraph.
-//				emptyItem = true;
-//			else // There is a next paragraph: check depth.
-//				emptyItem = par->params().depth() >= next_par->params().depth();
-//		}
-//
-//		if (emptyItem) {
-//			// Avoid having an empty item, this is not valid DocBook. A single character is enough to force
-//			// generation of a full <para>.
-//			// TODO: this always worked only by magic...
-//			xs << ' ';
-//		} else {
-//			// Generate the rest of the paragraph, if need be. Open as many inner tags as necessary.
-//			auto pars = par->simpleDocBookOnePar(buf, runparams, text.outerFont(std::distance(text.paragraphs().begin(), par)), sep);
-//			auto p = pars.begin();
-//			while (true) {
-//				xs << XMLStream::ESCAPE_NONE << *p;
-//				++p;
-//				if (p != pars.end()) {
-//					closeTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnertagtype());
-//					openTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnerattr(), par->layout().docbookiteminnertagtype());
-//				} else
-//					break;
-//			}
-//		}
-//	} else {
-//		makeAny(text, buf, xs, runparams, par);
-//	}
-//
-////	stack<Layout> previous_;
-////	int curdepth = -1; text.paragraphs().front().getDepth();
-////	for (auto const & p : text.paragraphs()) {
-////		if (p.layout().latextype == LATEX_ITEM_ENVIRONMENT) {
-////			if (curdepth ) {
-////				;
-////			}
-////			curdepth = p.getDepth();
-////		} else if (curdepth > 0)
-////	}
-//
-//	// Close the environment.
-//	auto nextpar = par;
-//	++nextpar;
-//	closeParTag(xs, &*par, (nextpar != end) ? &*nextpar : nullptr); // TODO: switch in layout for par/block?
-//
-//	return nextpar;
 }
 
 

commit e08d94883b346e5e121b27285c2cd07d19212836
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 03:46:30 2020 +0200

    DocBook: make all make* functions have the same argument order.

diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index 617d3b7..ba1fd47 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -351,11 +351,11 @@ ParagraphList::const_iterator makeAny(Text const &,
 		                              ParagraphList::const_iterator);
 
 
-void makeParagraphBibliography(
+void makeBibliography(
+		Text const & text,
 		Buffer const & buf,
 		XMLStream & xs,
 		OutputParams const & runparams,
-		Text const & text,
 		ParagraphList::const_iterator const & par)
 {
 	// If this is the first paragraph in a bibliography, open the bibliography tag.
@@ -406,10 +406,10 @@ void makeParagraphBibliography(
 
 
 void makeParagraph(
+		Text const & text,
 		Buffer const & buf,
 		XMLStream & xs,
 		OutputParams const & runparams,
-		Text const & text,
 		ParagraphList::const_iterator const & par)
 {
 	auto const begin = text.paragraphs().begin();
@@ -504,10 +504,10 @@ void makeParagraph(
 }
 
 
-void makeEnvironment(Buffer const &buf,
+void makeEnvironment(Text const &text,
+					 Buffer const &buf,
                      XMLStream &xs,
                      OutputParams const &runparams,
-                     Text const &text,
                      ParagraphList::const_iterator const & par)
 {
 	// TODO: simplify me!
@@ -632,10 +632,10 @@ ParagraphList::const_iterator findEndOfEnvironment(
 }
 
 
-ParagraphList::const_iterator makeListEnvironment(Buffer const &buf,
+ParagraphList::const_iterator makeListEnvironment(Text const &text,
+												  Buffer const &buf,
 		                                          XMLStream &xs,
 		                                          OutputParams const &runparams,
-		                                          Text const &text,
 		                                          ParagraphList::const_iterator const & begin)
 {
 	auto par = begin;
@@ -812,10 +812,10 @@ ParagraphList::const_iterator makeListEnvironment(Buffer const &buf,
 
 
 void makeCommand(
+		Text const & text,
 		Buffer const & buf,
 		XMLStream & xs,
 		OutputParams const & runparams,
-		Text const & text,
 		ParagraphList::const_iterator const & par)
 {
 	// Unlike XHTML, no need for labels, as they are handled by DocBook tags.
@@ -840,25 +840,25 @@ void makeCommand(
 ParagraphList::const_iterator makeAny(Text const &text,
 		                              Buffer const &buf,
 		                              XMLStream &xs,
-		                              OutputParams const &ourparams,
+		                              OutputParams const &runparams,
 		                              ParagraphList::const_iterator par)
 {
 	switch (par->layout().latextype) {
 	case LATEX_COMMAND:
-		makeCommand(buf, xs, ourparams, text, par);
+		makeCommand(text, buf, xs, runparams, par);
 		break;
 	case LATEX_ENVIRONMENT:
-		makeEnvironment(buf, xs, ourparams, text, par);
+		makeEnvironment(text, buf, xs, runparams, par);
 		break;
 	case LATEX_LIST_ENVIRONMENT:
 	case LATEX_ITEM_ENVIRONMENT:
 		// Only case when makeAny() might consume more than one paragraph.
-		return makeListEnvironment(buf, xs, ourparams, text, par);
+		return makeListEnvironment(text, buf, xs, runparams, par);
 	case LATEX_PARAGRAPH:
-		makeParagraph(buf, xs, ourparams, text, par);
+		makeParagraph(text, buf, xs, runparams, par);
 		break;
 	case LATEX_BIB_ENVIRONMENT:
-		makeParagraphBibliography(buf, xs, ourparams, text, par);
+		makeBibliography(text, buf, xs, runparams, par);
 		break;
 	}
 	++par;

commit 99cfceb0904249c50ec7916899aae2bcdc2aa1a5
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 03:42:11 2020 +0200

    WIP: works for nested lists!

diff --git a/autotests/export/docbook/lists.lyx b/autotests/export/docbook/lists.lyx
index 68a91b2..2e7c0e0 100644
--- a/autotests/export/docbook/lists.lyx
+++ b/autotests/export/docbook/lists.lyx
@@ -87,6 +87,10 @@ Test document
 \end_layout
 
 \begin_layout Standard
+\begin_inset Note Note
+status open
+
+\begin_layout Plain Layout
 A simple list: 
 \end_layout
 
@@ -102,7 +106,11 @@ Second item on two lines
 I'm the second line
 \end_layout
 
-\begin_layout Standard
+\begin_layout Itemize
+Third item
+\end_layout
+
+\begin_layout Plain Layout
 A simple enumerated list: 
 \end_layout
 
@@ -118,10 +126,6 @@ Second item on two lines
 I'm the second line
 \end_layout
 
-\begin_layout Standard
-\begin_inset Note Note
-status open
-
 \begin_layout Plain Layout
 Nested lists:
 \end_layout
@@ -154,7 +158,12 @@ Second second item
 \end_layout
 
 \end_deeper
-\begin_layout Plain Layout
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
 A complex list:
 \end_layout
 
@@ -171,7 +180,7 @@ First first item
 First second item
 \end_layout
 
-\begin_layout Plain Layout
+\begin_layout Standard
 Text after first item
 \end_layout
 
@@ -189,16 +198,11 @@ Second first item
 Second second item
 \end_layout
 
-\begin_layout Plain Layout
+\begin_layout Standard
 Text after second item
 \end_layout
 
 \end_deeper
-\end_inset
-
-
-\end_layout
-
 \begin_layout Standard
 \begin_inset Note Note
 status open
diff --git a/autotests/export/docbook/lists.xml b/autotests/export/docbook/lists.xml
index 266cab6..4b72f7f 100644
--- a/autotests/export/docbook/lists.xml
+++ b/autotests/export/docbook/lists.xml
@@ -2,48 +2,34 @@
 <!-- This DocBook file was created by LyX 2.4.0dev
   See http://www.lyx.org/ for more information -->
 <article xml:lang="en_US" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:xi="http://www.w3.org/2001/XInclude" version="5.2">
-<!-- Decision to open the wrapper:  --><!-- Result: 0 -->
-<title>Test document<!-- closeWrapper: 1 --><!-- closeWrapper: condition met --></title>
-<!-- closeWrapper first iteration: 1 --><!-- Output Error: Tried to close `title' when no tags were open! -->
-
-<!-- closeWrapper has looped --><!-- Decision to open the wrapper: prevpar != nullptr;  --><!-- Result: 0 -->
-<para>A simple list: <!-- closeWrapper: 1 --><!-- closeWrapper: condition met --></para>
-<!-- closeWrapper first iteration: 1 --><!-- Output Error: Tried to close `para' when no tags were open! -->
-
-<!-- closeWrapper has looped -->
+<title>Test document</title>
+<para>A complex list:</para>
 <itemizedlist>
 <listitem>
 <para>First item</para>
+<itemizedlist>
+<listitem>
+<para>First first item</para>
 </listitem>
 <listitem>
-<para>Second item on two lines</para>
-<para>I'm the second line</para>
+<para>First second item</para>
 </listitem>
 </itemizedlist>
+</listitem>
+Text after first item
 <itemizedlist>
 <listitem>
-<para>Second item on two lines</para>
-<para>I'm the second line</para>
-</listitem>
-</itemizedlist>
-<!-- Decision to open the wrapper: prevpar != nullptr;  --><!-- Result: 0 -->
-<para>A simple enumerated list: <!-- closeWrapper: 1 --><!-- closeWrapper: condition met --></para>
-<!-- closeWrapper first iteration: 1 --><!-- Output Error: Tried to close `para' when no tags were open! -->
-
-<!-- closeWrapper has looped -->
-<orderedlist>
+<para>Second item</para>
+<itemizedlist>
 <listitem>
-<para>First item</para>
+<para>Second first item</para>
 </listitem>
 <listitem>
-<para>Second item on two lines</para>
-<para>I'm the second line</para>
+<para>Second second item</para>
 </listitem>
-</orderedlist>
-<orderedlist>
-<listitem>
-<para>Second item on two lines</para>
-<para>I'm the second line</para>
+</itemizedlist>
 </listitem>
-</orderedlist>
+Text after second item
+</itemizedlist>
+</itemizedlist>
 </article>
\ No newline at end of file
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index 75095b6..617d3b7 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -689,12 +689,16 @@ ParagraphList::const_iterator makeListEnvironment(Buffer const &buf,
 			closeTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnertagtype());
 		}
 
+		// If the next item is deeper, it must go entirely within this item (do it recursively).
+		// By construction, with findEndOfEnvironment, depth can only stay constant or increase, never decrease.
+		depth_type currentDepth = par->getDepth();
+		++par;
+		if (par != envend && par->getDepth() != currentDepth)
+			par = makeAny(buf, xs, runparams, text, par);
+
 		// Close the item.
 		closeTag(xs, style.docbookitemwrappertag(), style.docbookitemwrappertagtype());
 		closeTag(xs, style.docbookitemtag(), style.docbookitemtagtype());
-
-		// Go to the next item.
-		++par;
 	}
 
 	// Close this environment in exactly the same way as it was opened.

commit 15ed212126f7299a855de47f2709b77ce897ab3a
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 03:31:12 2020 +0200

    DocBook: same refactoring for docbookSimpleAllParagraphs.

diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index b7190bc..75095b6 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -601,6 +601,8 @@ ParagraphList::const_iterator findEndOfEnvironment(
 		ParagraphList::const_iterator const & pstart,
 		ParagraphList::const_iterator const & pend)
 {
+	// Copy-paste from XHTML. Should be factored out at some point...
+
 	ParagraphList::const_iterator p = pstart;
 	Layout const & bstyle = p->layout();
 	size_t const depth = p->params().depth();
@@ -855,6 +857,7 @@ ParagraphList::const_iterator makeAny(Text const &text,
 		makeParagraphBibliography(buf, xs, ourparams, text, par);
 		break;
 	}
+	++par;
 	return par;
 }
 
@@ -1126,12 +1129,13 @@ void docbookSimpleAllParagraphs(
 	outputDocBookInfo(text, buf, xs, runparams, paragraphs, info);
 
 	// Then, the content. It starts where the <info> ends.
-	bpit = info.epit;
-	while (bpit < epit) {
-		auto par = paragraphs.iterator_at(bpit);
+	auto par = text.paragraphs().iterator_at(info.epit);
+	auto end = text.paragraphs().iterator_at(epit);
+	while (par != end) {
 		if (!hasOnlyNotes(*par))
-			makeAny(text, buf, xs, runparams, par);
-		bpit += 1;
+			par = makeAny(text, buf, xs, runparams, par);
+		else
+			++par;
 	}
 }
 

commit 50d5a1ffcbafc1909d6a26718783d8d0b28719a1
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 03:24:43 2020 +0200

    WIP: rewrite makeListEnv.
    WIP: restore open/closeParTag.

diff --git a/autotests/export/docbook/lists.lyx b/autotests/export/docbook/lists.lyx
index 76df45e..68a91b2 100644
--- a/autotests/export/docbook/lists.lyx
+++ b/autotests/export/docbook/lists.lyx
@@ -87,10 +87,6 @@ Test document
 \end_layout
 
 \begin_layout Standard
-\begin_inset Note Note
-status open
-
-\begin_layout Plain Layout
 A simple list: 
 \end_layout
 
@@ -106,7 +102,7 @@ Second item on two lines
 I'm the second line
 \end_layout
 
-\begin_layout Plain Layout
+\begin_layout Standard
 A simple enumerated list: 
 \end_layout
 
@@ -122,6 +118,10 @@ Second item on two lines
 I'm the second line
 \end_layout
 
+\begin_layout Standard
+\begin_inset Note Note
+status open
+
 \begin_layout Plain Layout
 Nested lists:
 \end_layout
@@ -200,6 +200,10 @@ Text after second item
 \end_layout
 
 \begin_layout Standard
+\begin_inset Note Note
+status open
+
+\begin_layout Plain Layout
 A very complex list:
 \end_layout
 
@@ -216,11 +220,16 @@ First first item
 First second item
 \end_layout
 
-\begin_layout Standard
+\begin_layout Plain Layout
 Text after first item
 \end_layout
 
 \end_deeper
+\end_inset
+
+
+\end_layout
+
 \begin_layout Standard
 \begin_inset Note Note
 status open
diff --git a/autotests/export/docbook/lists.xml b/autotests/export/docbook/lists.xml
index ede9acb..266cab6 100644
--- a/autotests/export/docbook/lists.xml
+++ b/autotests/export/docbook/lists.xml
@@ -3,26 +3,47 @@
   See http://www.lyx.org/ for more information -->
 <article xml:lang="en_US" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:xi="http://www.w3.org/2001/XInclude" version="5.2">
 <!-- Decision to open the wrapper:  --><!-- Result: 0 -->
-<title>Test document<!-- closeWrapper: 0 --><!-- closeWrapper: condition met --></title>
+<title>Test document<!-- closeWrapper: 1 --><!-- closeWrapper: condition met --></title>
+<!-- closeWrapper first iteration: 1 --><!-- Output Error: Tried to close `title' when no tags were open! -->
+
 <!-- closeWrapper has looped --><!-- Decision to open the wrapper: prevpar != nullptr;  --><!-- Result: 0 -->
-<para>A very complex list:<!-- closeWrapper: 0 --><!-- closeWrapper: condition met --></para>
-<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr;  --><!-- Result: 1 -->
+<para>A simple list: <!-- closeWrapper: 1 --><!-- closeWrapper: condition met --></para>
+<!-- closeWrapper first iteration: 1 --><!-- Output Error: Tried to close `para' when no tags were open! -->
+
+<!-- closeWrapper has looped -->
 <itemizedlist>
 <listitem>
-<para><!-- ENV DEPTH: 0. PREV DEPTH: 0. NEXT DEPTH: 1 -->First item<!-- closeWrapper: 0 --></para>
-<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; PREV SHALLOWER  --><!-- Result: 1 -->
-<itemizedlist>
+<para>First item</para>
+</listitem>
 <listitem>
-<para><!-- ENV DEPTH: 1. PREV DEPTH: 0. NEXT DEPTH: 1 -->First first item<!-- closeWrapper: 0 --></para>
-<!-- closeWrapper: condition met -->
+<para>Second item on two lines</para>
+<para>I'm the second line</para>
 </listitem>
-<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; SAME DEPTH  --><!-- Result: 0 -->
+</itemizedlist>
+<itemizedlist>
 <listitem>
-<para><!-- ENV DEPTH: 1. PREV DEPTH: 1. NEXT DEPTH: 1 -->First second item<!-- closeWrapper: 0 --></para>
-<!-- closeWrapper: condition met -->
+<para>Second item on two lines</para>
+<para>I'm the second line</para>
 </listitem>
-<!-- closeWrapper has looped --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; SAME DEPTH  --><!-- Result: 0 -->
-<para>Text after first item<!-- closeWrapper: 2 --><!-- closeWrapper first iteration: 2 --></para>
-<!-- closeWrapper first iteration: 1 --><!-- Output Error: Tried to close `para' when tag was not open. Tag discarded. -->
+</itemizedlist>
+<!-- Decision to open the wrapper: prevpar != nullptr;  --><!-- Result: 0 -->
+<para>A simple enumerated list: <!-- closeWrapper: 1 --><!-- closeWrapper: condition met --></para>
+<!-- closeWrapper first iteration: 1 --><!-- Output Error: Tried to close `para' when no tags were open! -->
 
-<!-- closeWrapper has looped --></article>
\ No newline at end of file
+<!-- closeWrapper has looped -->
+<orderedlist>
+<listitem>
+<para>First item</para>
+</listitem>
+<listitem>
+<para>Second item on two lines</para>
+<para>I'm the second line</para>
+</listitem>
+</orderedlist>
+<orderedlist>
+<listitem>
+<para>Second item on two lines</para>
+<para>I'm the second line</para>
+</listitem>
+</orderedlist>
+</article>
\ No newline at end of file
diff --git a/lib/layouts/stdlists.inc b/lib/layouts/stdlists.inc
index f6dd411..700402f 100644
--- a/lib/layouts/stdlists.inc
+++ b/lib/layouts/stdlists.inc
@@ -43,9 +43,7 @@ Style Itemize
 			Color latex
 		EndFont
 	EndArgument
-	DocBookWrapperTag     itemizedlist
-	DocBookWrapperMergeWithPrevious    true
-	DocBookTag            NONE
+	DocBookTag            itemizedlist
 	DocBookItemTag        listitem
 	DocBookItemInnerTag   para
 End
@@ -87,9 +85,7 @@ Style Enumerate
 			Color latex
 		EndFont
 	EndArgument
-	DocBookWrapperTag     orderedlist
-	DocBookWrapperMergeWithPrevious    true
-	DocBookTag            NONE
+	DocBookTag            orderedlist
 	DocBookItemTag        listitem
 	DocBookItemInnerTag   para
 End
@@ -131,9 +127,7 @@ Style Description
 			Color latex
 		EndFont
 	EndArgument
-	DocBookWrapperTag     variablelist
-	DocBookWrapperMergeWithPrevious  true
-	DocBookTag            NONE
+	DocBookTag            variablelist
 	DocBookItemWrapperTag varlistentry
 	DocBookItemTag        listitem
 	DocBookItemInnerTag   para
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index a573159..b7190bc 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -269,34 +269,13 @@ void openParTag(XMLStream & xs, const Paragraph * par, const Paragraph * prevpar
 	// next paragraph is the affiliation, then it should be output in the same <author> tag (different
 	// layout, same wrapper tag).
 	bool openWrapper = lay.docbookwrappertag() != "NONE";
-	xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- Decision to open the wrapper: ");
 	if (prevpar != nullptr) {
-		xs << XMLStream::ESCAPE_NONE << from_ascii("prevpar != nullptr; ");
 		Layout const & prevlay = prevpar->layout();
 		if (prevlay.docbookwrappertag() != "NONE") {
-			xs << XMLStream::ESCAPE_NONE << from_ascii("prevlay.docbookwrappertag() != NONE; ");
-			if (prevpar->getDepth() == par->getDepth()) {
-				// Same depth: the basic condition applies.
-				openWrapper = prevlay.docbookwrappertag() == lay.docbookwrappertag()
-				              && !lay.docbookwrappermergewithprevious();
-				xs << XMLStream::ESCAPE_NONE << from_ascii("SAME DEPTH ");
-			} else if (prevpar->getDepth() > par->getDepth()) {
-				// The previous paragraph was deeper: close the wrapper, no need to open it.
-				xs << XMLStream::ESCAPE_NONE << from_ascii("PREV DEEPER ");
-			} else {
-				// This paragraph is deeper than the previous one: open the wrapper,
-				// disregarding docbookwrappermergewithprevious.
-				// Don't change openWrapper!
-				openWrapper = lay.docbookwrappertag() != "NONE"; // prevlay.docbookwrappertag() == lay.docbookwrappertag();
-				xs << XMLStream::ESCAPE_NONE << from_ascii("PREV SHALLOWER ");
-			}
-		} else {
-//			openWrapper = false;
+			openWrapper = prevlay.docbookwrappertag() == lay.docbookwrappertag()
+			              && !lay.docbookwrappermergewithprevious();
 		}
 	}
-	xs << XMLStream::ESCAPE_NONE << from_ascii(" -->");
-
-	xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- Result: " + to_string(openWrapper) + " -->");
 
 	// Main logic.
 	if (openWrapper)
@@ -306,8 +285,8 @@ void openParTag(XMLStream & xs, const Paragraph * par, const Paragraph * prevpar
 	if (tag != "NONE") {
 		auto xmltag = xml::ParTag(tag, lay.docbookattr());
 		if (!xs.isTagOpen(xmltag, 1)) // Don't nest a paragraph directly in a paragraph.
-			// TODO: is this condition required or not?
-			// TODO: avoid creating a ParTag object (xmltag) just for this query...
+			// TODO: required or not?
+			// TODO: avoid creating a ParTag object just for this query...
 			openTag(xs, lay.docbooktag(), lay.docbookattr(), lay.docbooktagtype());
 	}
 
@@ -322,64 +301,22 @@ void closeParTag(XMLStream & xs, Paragraph const * par, Paragraph const * nextpa
 		nextpar = nullptr;
 
 	// See comment in openParTag.
-	// If closeWrapper == 0, the wrapper should not be closed: the next paragraph is another item to add to this list.
 	Layout const & lay = par->layout();
-	long long closeWrapper = 0; // (lay.docbookwrappertag() == "NONE") ? 0 : 1; // Avoid unsigned, as -1 might appear as value.
-	if (nextpar == nullptr) {
-		closeWrapper = 1L + (long long) par->getDepth();
-	} else {
-		Layout const &nextlay = nextpar->layout();
+	bool closeWrapper = lay.docbookwrappertag() != "NONE";
+	if (nextpar != nullptr) {
+		Layout const & nextlay = nextpar->layout();
 		if (nextlay.docbookwrappertag() != "NONE") {
-			if (nextpar->getDepth() == par->getDepth()) {
-				// Same depth: the basic condition applies.
-				closeWrapper = nextlay.docbookwrappertag() == lay.docbookwrappertag()
-				               && !nextlay.docbookwrappermergewithprevious();
-			} else if (nextpar->getDepth() > par->getDepth()) {
-				// The next paragraph is deeper: no need to close the wrapper, only to open it (cf. openParTag).
-				closeWrapper = 0;
-			} else {
-				// This paragraph is deeper than the next one: close the wrapper,
-				// disregarding docbookwrappermergewithprevious.
-				// Hypothesis: nextlay.docbookwrappertag() == lay.docbookwrappertag(). TODO: THIS IS WRONG! Loop back until a layout with the right depth is found?
-				closeWrapper = 1L + (long long) par->getDepth() - (long long) nextpar->getDepth(); // > 0, as nextpar->getDepth() < par->getDepth()
-			}
-		} else {
-			if (nextpar->getDepth() == par->getDepth()) {
-				// This is not wrapped: this must be the rest of the item, still within the wrapper.
-				closeWrapper = 1;
-			} else if (nextpar->getDepth() > par->getDepth()) {
-				// The next paragraph is deeper: no need to close the wrapper, only to open it (cf. openParTag).
-				closeWrapper = 0;
-			} else {
-				// This paragraph is deeper than the next one: close the wrapper,
-				// disregarding docbookwrappermergewithprevious.
-				// Hypothesis: nextlay.docbookwrappertag() == lay.docbookwrappertag(). TODO: THIS IS WRONG! Loop back until a layout with the right depth is found?
-				closeWrapper = 1L + (long long) par->getDepth() - (long long) nextpar->getDepth(); // > 0, as nextpar->getDepth() < par->getDepth()
-			}
+			closeWrapper = nextlay.docbookwrappertag() == lay.docbookwrappertag()
+			               && !nextlay.docbookwrappermergewithprevious();
 		}
 	}
 
-	// Main logic. (Comments mostly correspond to lists.)
-	xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- closeWrapper: " + to_string(closeWrapper) + " -->");
-	// - Close this paragraph.
+	// Main logic.
 	closeTag(xs, lay.docbookiteminnertag(), lay.docbookiteminnertagtype());
-
-	// - Close the current item.
-	if (!nextpar || nextpar->getDepth() == par->getDepth()) {
-		xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- closeWrapper: condition met -->");
-		closeTag(xs, lay.docbookitemtag(), lay.docbookitemtagtype());
-		closeTag(xs, lay.docbooktag(), lay.docbooktagtype());
-	}
-
-	// - Close wrapper tags as many times as required.
-	while (closeWrapper > 0) {
-		xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- closeWrapper first iteration: " + to_string(closeWrapper) + " -->");
-		closeTag(xs, lay.docbookitemtag(), lay.docbookitemtagtype());
-		closeTag(xs, lay.docbooktag(), lay.docbooktagtype());
+	closeTag(xs, lay.docbookitemtag(), lay.docbookitemtagtype());
+	closeTag(xs, lay.docbooktag(), lay.docbooktagtype());
+	if (closeWrapper)
 		closeTag(xs, lay.docbookwrappertag(), lay.docbookwrappertagtype());
-		closeWrapper -= 1;
-	}
-	xs << XMLStream::ESCAPE_NONE << "<!-- closeWrapper has looped -->";
 }
 
 
@@ -660,41 +597,61 @@ void makeEnvironment(Buffer const &buf,
 }
 
 
+ParagraphList::const_iterator findEndOfEnvironment(
+		ParagraphList::const_iterator const & pstart,
+		ParagraphList::const_iterator const & pend)
+{
+	ParagraphList::const_iterator p = pstart;
+	Layout const & bstyle = p->layout();
+	size_t const depth = p->params().depth();
+	for (++p; p != pend; ++p) {
+		Layout const & style = p->layout();
+		// It shouldn't happen that e.g. a section command occurs inside
+		// a quotation environment, at a higher depth, but as of 6/2009,
+		// it can happen. We pretend that it's just at lowest depth.
+		if (style.latextype == LATEX_COMMAND)
+			return p;
+
+		// If depth is down, we're done
+		if (p->params().depth() < depth)
+			return p;
+
+		// If depth is up, we're not done
+		if (p->params().depth() > depth)
+			continue;
+
+		// FIXME I am not sure about the first check.
+		// Surely we *could* have different layouts that count as
+		// LATEX_PARAGRAPH, right?
+		if (style.latextype == LATEX_PARAGRAPH || style != bstyle)
+			return p;
+	}
+	return pend;
+}
+
+
 ParagraphList::const_iterator makeListEnvironment(Buffer const &buf,
 		                                          XMLStream &xs,
 		                                          OutputParams const &runparams,
 		                                          Text const &text,
-		                                          ParagraphList::const_iterator const & par)
+		                                          ParagraphList::const_iterator const & begin)
 {
+	auto par = begin;
 	auto const end = text.paragraphs().end();
+	auto const envend = findEndOfEnvironment(par, end);
 
-	xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- " + to_string(par->layout().latextype) + " -->");
+	// Output the opening tag for this environment.
+	Layout const & envstyle = par->layout();
+	openTag(xs, envstyle.docbookwrappertag(), envstyle.docbookwrapperattr(), envstyle.docbookwrappertagtype());
+	openTag(xs, envstyle.docbooktag(), envstyle.docbookattr(), envstyle.docbooktagtype());
 
-	// Output the opening tag for this environment, but only if it has not been previously opened (condition
-	// implemented in openParTag).
-	auto prevpar = text.paragraphs().getParagraphBefore(par);
-	openParTag(xs, &*par, prevpar); // TODO: switch in layout for par/block?
+	// Handle the content of the list environment, item by item.
+	while (par != envend) {
+		Layout const & style = par->layout();
 
-	xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- ENV DEPTH: " + to_string(par->getDepth()) + ". ");
-	if (prevpar)
-		xs << XMLStream::ESCAPE_NONE << from_ascii("PREV DEPTH: " + to_string(prevpar->getDepth()) + ". ");
-	if (par != end) {
-		auto nextpar = par;
-		++nextpar;
-		xs << XMLStream::ESCAPE_NONE << from_ascii("NEXT DEPTH: " + to_string(nextpar->getDepth()));
-	}
-	xs << XMLStream::ESCAPE_NONE << from_ascii(" -->");
-
-	// Generate the contents of this environment. There is a special case if this is like some environment.
-	Layout const & style = par->layout();
-	if (style.latextype == LATEX_COMMAND) {
-		// Nothing to do (otherwise, infinite loops).
-	} else if (style.latextype == LATEX_ENVIRONMENT ||
-			style.latextype == LATEX_LIST_ENVIRONMENT ||
-			style.latextype == LATEX_ITEM_ENVIRONMENT) {
-		// Open a wrapper tag if needed.
-		if (style.docbookitemwrappertag() != "NONE")
-			openTag(xs, style.docbookitemwrappertag(), style.docbookitemwrapperattr(), style.docbookitemwrappertagtype());
+		// Open the item.
+		openTag(xs, style.docbookitemtag(), style.docbookitemattr(), style.docbookitemtagtype());
+		openTag(xs, style.docbookitemwrappertag(), style.docbookitemwrapperattr(), style.docbookitemwrappertagtype());
 
 		// Generate the label, if need be. If it is taken from the text, sep != 0 and corresponds to the first
 		// character after the label.
@@ -722,60 +679,129 @@ ParagraphList::const_iterator makeListEnvironment(Buffer const &buf,
 			}
 		}
 
-		// Maybe the item is completely empty, i.e. if the first word ends at the end of the current paragraph
-		// AND if the next paragraph doesn't have the same depth (if there is such a paragraph).
-		// Common case: there is only the first word on the line, but there is a nested list instead
-		// of more text.
-		bool emptyItem = false;
-		if (sep == par->size()) { // If the separator is already at the end of this paragraph...
-			auto next_par = par;
-			++next_par;
-			if (next_par == text.paragraphs().end()) // There is no next paragraph.
-				emptyItem = true;
-			else // There is a next paragraph: check depth.
-				emptyItem = par->params().depth() >= next_par->params().depth();
+		// Generate the content of the item.
+		auto pars = par->simpleDocBookOnePar(buf, runparams, text.outerFont(std::distance(text.paragraphs().begin(), par)), sep);
+		for (auto & p : pars) {
+			openTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnerattr(), par->layout().docbookiteminnertagtype());
+			xs << XMLStream::ESCAPE_NONE << p;
+			closeTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnertagtype());
 		}
 
-		if (emptyItem) {
-			// Avoid having an empty item, this is not valid DocBook. A single character is enough to force
-			// generation of a full <para>.
-			// TODO: this always worked only by magic...
-			xs << ' ';
-		} else {
-			// Generate the rest of the paragraph, if need be. Open as many inner tags as necessary.
-			auto pars = par->simpleDocBookOnePar(buf, runparams, text.outerFont(std::distance(text.paragraphs().begin(), par)), sep);
-			auto p = pars.begin();
-			while (true) {
-				xs << XMLStream::ESCAPE_NONE << *p;
-				++p;
-				if (p != pars.end()) {
-					closeTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnertagtype());
-					openTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnerattr(), par->layout().docbookiteminnertagtype());
-				} else
-					break;
-			}
-		}
-	} else {
-		makeAny(text, buf, xs, runparams, par);
+		// Close the item.
+		closeTag(xs, style.docbookitemwrappertag(), style.docbookitemwrappertagtype());
+		closeTag(xs, style.docbookitemtag(), style.docbookitemtagtype());
+
+		// Go to the next item.
+		++par;
 	}
 
-//	stack<Layout> previous_;
-//	int curdepth = -1; text.paragraphs().front().getDepth();
-//	for (auto const & p : text.paragraphs()) {
-//		if (p.layout().latextype == LATEX_ITEM_ENVIRONMENT) {
-//			if (curdepth ) {
-//				;
-//			}
-//			curdepth = p.getDepth();
-//		} else if (curdepth > 0)
-//	}
+	// Close this environment in exactly the same way as it was opened.
+	closeTag(xs, envstyle.docbooktag(), envstyle.docbooktagtype());
+	closeTag(xs, envstyle.docbookwrappertag(), envstyle.docbookwrappertagtype());
 
-	// Close the environment.
-	auto nextpar = par;
-	++nextpar;
-	closeParTag(xs, &*par, (nextpar != end) ? &*nextpar : nullptr); // TODO: switch in layout for par/block?
+	return envend;
 
-	return nextpar;
+//	xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- ENV DEPTH: " + to_string(par->getDepth()) + ". ");
+//	if (prevpar)
+//		xs << XMLStream::ESCAPE_NONE << from_ascii("PREV DEPTH: " + to_string(prevpar->getDepth()) + ". ");
+//	if (par != end) {
+//		auto nextpar = par;
+//		++nextpar;
+//		xs << XMLStream::ESCAPE_NONE << from_ascii("NEXT DEPTH: " + to_string(nextpar->getDepth()));
+//	}
+//	xs << XMLStream::ESCAPE_NONE << from_ascii(" -->");
+
+//	// Generate the contents of this environment. There is a special case if this is like some environment.
+//	Layout const & style = par->layout();
+//	if (envstyle.latextype == LATEX_COMMAND) {
+//		// Nothing to do (otherwise, infinite loops).
+//	} else if (envstyle.latextype == LATEX_ENVIRONMENT ||
+//	           envstyle.latextype == LATEX_LIST_ENVIRONMENT ||
+//	           envstyle.latextype == LATEX_ITEM_ENVIRONMENT) {
+//		// Open a wrapper tag if needed.
+//		if (envstyle.docbookitemwrappertag() != "NONE")
+//			openTag(xs, envstyle.docbookitemwrappertag(), envstyle.docbookitemwrapperattr(), envstyle.docbookitemwrappertagtype());
+//
+//		// Generate the label, if need be. If it is taken from the text, sep != 0 and corresponds to the first
+//		// character after the label.
+//		pos_type sep = 0;
+//		if (envstyle.labeltype != LABEL_NO_LABEL && envstyle.docbookitemlabeltag() != "NONE") {
+//			// At least one condition must be met:
+//			//  - this environment is not a list
+//			//  - if this is a list, the label must not be manual (i.e. it must be taken from the layout)
+//			if (envstyle.latextype != LATEX_LIST_ENVIRONMENT || envstyle.labeltype != LABEL_MANUAL) {
+//				// Usual cases: maybe there is something specified at the layout level. Highly unlikely, though.
+//				docstring const lbl = par->params().labelString();
+//
+//				if (lbl.empty()) {
+//					xs << xml::CR();
+//				} else {
+//					openLabelTag(xs, envstyle);
+//					xs << lbl;
+//					closeLabelTag(xs, envstyle);
+//				}
+//			} else {
+//				// Only variablelist gets here (or similar items defined as an extension in the layout).
+//				openLabelTag(xs, envstyle);
+//				sep = par->firstWordDocBook(xs, runparams);
+//				closeLabelTag(xs, envstyle);
+//			}
+//		}
+//
+//		// Maybe the item is completely empty, i.e. if the first word ends at the end of the current paragraph
+//		// AND if the next paragraph doesn't have the same depth (if there is such a paragraph).
+//		// Common case: there is only the first word on the line, but there is a nested list instead
+//		// of more text.
+//		bool emptyItem = false;
+//		if (sep == par->size()) { // If the separator is already at the end of this paragraph...
+//			auto next_par = par;
+//			++next_par;
+//			if (next_par == text.paragraphs().end()) // There is no next paragraph.
+//				emptyItem = true;
+//			else // There is a next paragraph: check depth.
+//				emptyItem = par->params().depth() >= next_par->params().depth();
+//		}
+//
+//		if (emptyItem) {
+//			// Avoid having an empty item, this is not valid DocBook. A single character is enough to force
+//			// generation of a full <para>.
+//			// TODO: this always worked only by magic...
+//			xs << ' ';
+//		} else {
+//			// Generate the rest of the paragraph, if need be. Open as many inner tags as necessary.
+//			auto pars = par->simpleDocBookOnePar(buf, runparams, text.outerFont(std::distance(text.paragraphs().begin(), par)), sep);
+//			auto p = pars.begin();
+//			while (true) {
+//				xs << XMLStream::ESCAPE_NONE << *p;
+//				++p;
+//				if (p != pars.end()) {
+//					closeTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnertagtype());
+//					openTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnerattr(), par->layout().docbookiteminnertagtype());
+//				} else
+//					break;
+//			}
+//		}
+//	} else {
+//		makeAny(text, buf, xs, runparams, par);
+//	}
+//
+////	stack<Layout> previous_;
+////	int curdepth = -1; text.paragraphs().front().getDepth();
+////	for (auto const & p : text.paragraphs()) {
+////		if (p.layout().latextype == LATEX_ITEM_ENVIRONMENT) {
+////			if (curdepth ) {
+////				;
+////			}
+////			curdepth = p.getDepth();
+////		} else if (curdepth > 0)
+////	}
+//
+//	// Close the environment.
+//	auto nextpar = par;
+//	++nextpar;
+//	closeParTag(xs, &*par, (nextpar != end) ? &*nextpar : nullptr); // TODO: switch in layout for par/block?
+//
+//	return nextpar;
 }
 
 

commit a412f4e4d4bd0569c7652a3c12dd8d699705add4
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 03:03:16 2020 +0200

    DocBook: start splitting environment handling in two, to have proper things for lists.

diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index f5e92b7..a573159 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -407,12 +407,11 @@ void closeItemTag(XMLStream & xs, Layout const & lay)
 }
 
 
-void makeAny(
-		Text const &,
-		Buffer const &,
-		XMLStream &,
-		OutputParams const &,
-		ParagraphList::const_iterator);
+ParagraphList::const_iterator makeAny(Text const &,
+		                              Buffer const &,
+		                              XMLStream &,
+		                              OutputParams const &,
+		                              ParagraphList::const_iterator);
 
 
 void makeParagraphBibliography(
@@ -568,12 +567,104 @@ void makeParagraph(
 }
 
 
-void makeEnvironment(
-		Buffer const &buf,
-		XMLStream &xs,
-		OutputParams const &runparams,
-		Text const &text,
-		ParagraphList::const_iterator const & par)
+void makeEnvironment(Buffer const &buf,
+                     XMLStream &xs,
+                     OutputParams const &runparams,
+                     Text const &text,
+                     ParagraphList::const_iterator const & par)
+{
+	// TODO: simplify me!
+	auto const end = text.paragraphs().end();
+
+	// Output the opening tag for this environment, but only if it has not been previously opened (condition
+	// implemented in openParTag).
+	auto prevpar = text.paragraphs().getParagraphBefore(par);
+	openParTag(xs, &*par, prevpar); // TODO: switch in layout for par/block?
+
+	// Generate the contents of this environment. There is a special case if this is like some environment.
+	Layout const & style = par->layout();
+	if (style.latextype == LATEX_COMMAND) {
+		// Nothing to do (otherwise, infinite loops).
+	} else if (style.latextype == LATEX_ENVIRONMENT) {
+		// Open a wrapper tag if needed.
+		if (style.docbookitemwrappertag() != "NONE")
+			openTag(xs, style.docbookitemwrappertag(), style.docbookitemwrapperattr(), style.docbookitemwrappertagtype());
+
+		// Generate the label, if need be. If it is taken from the text, sep != 0 and corresponds to the first
+		// character after the label.
+		pos_type sep = 0;
+		if (style.labeltype != LABEL_NO_LABEL && style.docbookitemlabeltag() != "NONE") {
+			// At least one condition must be met:
+			//  - this environment is not a list
+			//  - if this is a list, the label must not be manual (i.e. it must be taken from the layout)
+			if (style.latextype != LATEX_LIST_ENVIRONMENT || style.labeltype != LABEL_MANUAL) {
+				// Usual cases: maybe there is something specified at the layout level. Highly unlikely, though.
+				docstring const lbl = par->params().labelString();
+
+				if (lbl.empty()) {
+					xs << xml::CR();
+				} else {
+					openLabelTag(xs, style);
+					xs << lbl;
+					closeLabelTag(xs, style);
+				}
+			} else {
+				// Only variablelist gets here (or similar items defined as an extension in the layout).
+				openLabelTag(xs, style);
+				sep = par->firstWordDocBook(xs, runparams);
+				closeLabelTag(xs, style);
+			}
+		}
+
+		// Maybe the item is completely empty, i.e. if the first word ends at the end of the current paragraph
+		// AND if the next paragraph doesn't have the same depth (if there is such a paragraph).
+		// Common case: there is only the first word on the line, but there is a nested list instead
+		// of more text.
+		bool emptyItem = false;
+		if (sep == par->size()) { // If the separator is already at the end of this paragraph...
+			auto next_par = par;
+			++next_par;
+			if (next_par == text.paragraphs().end()) // There is no next paragraph.
+				emptyItem = true;
+			else // There is a next paragraph: check depth.
+				emptyItem = par->params().depth() >= next_par->params().depth();
+		}
+
+		if (emptyItem) {
+			// Avoid having an empty item, this is not valid DocBook. A single character is enough to force
+			// generation of a full <para>.
+			// TODO: this always worked only by magic...
+			xs << ' ';
+		} else {
+			// Generate the rest of the paragraph, if need be. Open as many inner tags as necessary.
+			auto pars = par->simpleDocBookOnePar(buf, runparams, text.outerFont(std::distance(text.paragraphs().begin(), par)), sep);
+			auto p = pars.begin();
+			while (true) {
+				xs << XMLStream::ESCAPE_NONE << *p;
+				++p;
+				if (p != pars.end()) {
+					closeTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnertagtype());
+					openTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnerattr(), par->layout().docbookiteminnertagtype());
+				} else
+					break;
+			}
+		}
+	} else {
+		makeAny(text, buf, xs, runparams, par);
+	}
+
+	// Close the environment.
+	auto nextpar = par;
+	++nextpar;
+	closeParTag(xs, &*par, (nextpar != end) ? &*nextpar : nullptr); // TODO: switch in layout for par/block?
+}
+
+
+ParagraphList::const_iterator makeListEnvironment(Buffer const &buf,
+		                                          XMLStream &xs,
+		                                          OutputParams const &runparams,
+		                                          Text const &text,
+		                                          ParagraphList::const_iterator const & par)
 {
 	auto const end = text.paragraphs().end();
 
@@ -683,6 +774,8 @@ void makeEnvironment(
 	auto nextpar = par;
 	++nextpar;
 	closeParTag(xs, &*par, (nextpar != end) ? &*nextpar : nullptr); // TODO: switch in layout for par/block?
+
+	return nextpar;
 }
 
 
@@ -712,22 +805,23 @@ void makeCommand(
 }
 
 
-void makeAny(
-		Text const &text,
-		Buffer const &buf,
-		XMLStream &xs,
-		OutputParams const &ourparams,
-		ParagraphList::const_iterator par)
+ParagraphList::const_iterator makeAny(Text const &text,
+		                              Buffer const &buf,
+		                              XMLStream &xs,
+		                              OutputParams const &ourparams,
+		                              ParagraphList::const_iterator par)
 {
 	switch (par->layout().latextype) {
 	case LATEX_COMMAND:
 		makeCommand(buf, xs, ourparams, text, par);
 		break;
 	case LATEX_ENVIRONMENT:
-	case LATEX_LIST_ENVIRONMENT:
-	case LATEX_ITEM_ENVIRONMENT:
 		makeEnvironment(buf, xs, ourparams, text, par);
 		break;
+	case LATEX_LIST_ENVIRONMENT:
+	case LATEX_ITEM_ENVIRONMENT:
+		// Only case when makeAny() might consume more than one paragraph.
+		return makeListEnvironment(buf, xs, ourparams, text, par);
 	case LATEX_PARAGRAPH:
 		makeParagraph(buf, xs, ourparams, text, par);
 		break;
@@ -735,6 +829,7 @@ void makeAny(
 		makeParagraphBibliography(buf, xs, ourparams, text, par);
 		break;
 	}
+	return par;
 }
 
 
@@ -1140,7 +1235,7 @@ void docbookParagraphs(Text const &text,
 		}
 
 		// Generate this paragraph.
-		makeAny(text, buf, xs, ourparams, par);
+		par = makeAny(text, buf, xs, ourparams, par);
 	}
 
 	// If need be, close <section>s, but only at the end of the document (otherwise, dealt with at the beginning

commit 7cd8196c19c76e53c088c5efdf46b5e5b0db569f
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 02:55:47 2020 +0200

    DocBook: partially remove use of bpit/epit in docbookParagraphs.
    
    This will help with the next refactoring to be much cleaner (only work with iterators, don't maintain twice the same information).

diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index 78c4bda..f5e92b7 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -346,7 +346,7 @@ void closeParTag(XMLStream & xs, Paragraph const * par, Paragraph const * nextpa
 		} else {
 			if (nextpar->getDepth() == par->getDepth()) {
 				// This is not wrapped: this must be the rest of the item, still within the wrapper.
-				closeWrapper = 0;
+				closeWrapper = 1;
 			} else if (nextpar->getDepth() > par->getDepth()) {
 				// The next paragraph is deeper: no need to close the wrapper, only to open it (cf. openParTag).
 				closeWrapper = 0;
@@ -1051,21 +1051,20 @@ void docbookParagraphs(Text const &text,
 
 	bool currentlyInAppendix = false;
 
-	while (bpit < epit) {
+	auto par = text.paragraphs().iterator_at(bpit);
+	auto end = text.paragraphs().iterator_at(epit);
+	while (par != end) {
 		OutputParams ourparams = runparams;
 
-		auto par = paragraphs.iterator_at(bpit);
 		if (par->params().startOfAppendix())
 			currentlyInAppendix = true;
-		Layout const &style = par->layout();
-		ParagraphList::const_iterator const lastStartedPar = par;
-		ParagraphList::const_iterator send;
-
 		if (hasOnlyNotes(*par)) {
-			bpit += 1;
+			++par;
 			continue;
 		}
 
+		Layout const &style = par->layout();
+
 		// Think about adding <section> and/or </section>s.
 		const bool isLayoutSectioning = style.category() == from_utf8("Sectioning");
 		if (isLayoutSectioning) {
@@ -1142,7 +1141,6 @@ void docbookParagraphs(Text const &text,
 
 		// Generate this paragraph.
 		makeAny(text, buf, xs, ourparams, par);
-		bpit += 1;
 	}
 
 	// If need be, close <section>s, but only at the end of the document (otherwise, dealt with at the beginning

commit 65a8ea8a3f86f58669bdb6d7bf0dd783a5249771
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 02:50:47 2020 +0200

    WIP: argh!

diff --git a/autotests/export/docbook/lists.lyx b/autotests/export/docbook/lists.lyx
index d8b9c1b..76df45e 100644
--- a/autotests/export/docbook/lists.lyx
+++ b/autotests/export/docbook/lists.lyx
@@ -87,6 +87,10 @@ Test document
 \end_layout
 
 \begin_layout Standard
+\begin_inset Note Note
+status open
+
+\begin_layout Plain Layout
 A simple list: 
 \end_layout
 
@@ -102,7 +106,7 @@ Second item on two lines
 I'm the second line
 \end_layout
 
-\begin_layout Standard
+\begin_layout Plain Layout
 A simple enumerated list: 
 \end_layout
 
@@ -118,7 +122,7 @@ Second item on two lines
 I'm the second line
 \end_layout
 
-\begin_layout Standard
+\begin_layout Plain Layout
 Nested lists:
 \end_layout
 
@@ -150,10 +154,6 @@ Second second item
 \end_layout
 
 \end_deeper
-\begin_layout Standard
-\begin_inset Note Note
-status open
-
 \begin_layout Plain Layout
 A complex list:
 \end_layout
@@ -194,17 +194,12 @@ Text after second item
 \end_layout
 
 \end_deeper
-\begin_layout Plain Layout
-
-\end_layout
-
 \end_inset
 
 
-\begin_inset Note Note
-status open
+\end_layout
 
-\begin_layout Plain Layout
+\begin_layout Standard
 A very complex list:
 \end_layout
 
@@ -221,11 +216,15 @@ First first item
 First second item
 \end_layout
 
-\begin_layout Plain Layout
+\begin_layout Standard
 Text after first item
 \end_layout
 
 \end_deeper
+\begin_layout Standard
+\begin_inset Note Note
+status open
+
 \begin_layout Itemize
 Second item
 \end_layout
diff --git a/autotests/export/docbook/lists.xml b/autotests/export/docbook/lists.xml
index 4c3f588..ede9acb 100644
--- a/autotests/export/docbook/lists.xml
+++ b/autotests/export/docbook/lists.xml
@@ -3,47 +3,9 @@
   See http://www.lyx.org/ for more information -->
 <article xml:lang="en_US" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:xi="http://www.w3.org/2001/XInclude" version="5.2">
 <!-- Decision to open the wrapper:  --><!-- Result: 0 -->
-<title>Test document<!-- closeWrapper: 1 --><!-- closeWrapper: condition met --></title>
-<!-- closeWrapper first iteration: 1 --><!-- Output Error: Tried to close `title' when no tags were open! -->
-
+<title>Test document<!-- closeWrapper: 0 --><!-- closeWrapper: condition met --></title>
 <!-- closeWrapper has looped --><!-- Decision to open the wrapper: prevpar != nullptr;  --><!-- Result: 0 -->
-<para>A simple list: <!-- closeWrapper: 0 --><!-- closeWrapper: condition met --></para>
-<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr;  --><!-- Result: 1 -->
-<itemizedlist>
-<listitem>
-<para><!-- ENV DEPTH: 0. PREV DEPTH: 0. NEXT DEPTH: 0 -->First item<!-- closeWrapper: 0 --></para>
-<!-- closeWrapper: condition met -->
-</listitem>
-<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; SAME DEPTH  --><!-- Result: 0 -->
-<listitem>
-<para><!-- ENV DEPTH: 0. PREV DEPTH: 0. NEXT DEPTH: 0 -->Second item on two lines</para>
-<para>I'm the second line<!-- closeWrapper: 1 --></para>
-<!-- closeWrapper: condition met -->
-</listitem>
-<!-- closeWrapper first iteration: 1 -->
-<!-- Output Error: Tried to close `listitem' when tag was not open. Tag discarded. -->
-
-</itemizedlist>
-<!-- closeWrapper has looped --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; SAME DEPTH  --><!-- Result: 0 -->
-<para>A simple enumerated list: <!-- closeWrapper: 0 --><!-- closeWrapper: condition met --></para>
-<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr;  --><!-- Result: 1 -->
-<orderedlist>
-<listitem>
-<para><!-- ENV DEPTH: 0. PREV DEPTH: 0. NEXT DEPTH: 0 -->First item<!-- closeWrapper: 0 --></para>
-<!-- closeWrapper: condition met -->
-</listitem>
-<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; SAME DEPTH  --><!-- Result: 0 -->
-<listitem>
-<para><!-- ENV DEPTH: 0. PREV DEPTH: 0. NEXT DEPTH: 0 -->Second item on two lines</para>
-<para>I'm the second line<!-- closeWrapper: 1 --></para>
-<!-- closeWrapper: condition met -->
-</listitem>
-<!-- closeWrapper first iteration: 1 -->
-<!-- Output Error: Tried to close `listitem' when tag was not open. Tag discarded. -->
-
-</orderedlist>
-<!-- closeWrapper has looped --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; SAME DEPTH  --><!-- Result: 0 -->
-<para>Nested lists:<!-- closeWrapper: 0 --><!-- closeWrapper: condition met --></para>
+<para>A very complex list:<!-- closeWrapper: 0 --><!-- closeWrapper: condition met --></para>
 <!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr;  --><!-- Result: 1 -->
 <itemizedlist>
 <listitem>
@@ -56,30 +18,11 @@
 </listitem>
 <!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; SAME DEPTH  --><!-- Result: 0 -->
 <listitem>
-<para><!-- ENV DEPTH: 1. PREV DEPTH: 1. NEXT DEPTH: 0 -->First second item<!-- closeWrapper: 2 --></para>
-<!-- closeWrapper first iteration: 2 -->
-</listitem>
-</itemizedlist>
-<!-- closeWrapper first iteration: 1 -->
-</listitem>
-</itemizedlist>
-<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; PREV DEEPER  --><!-- Result: 1 -->
-<itemizedlist>
-<listitem>
-<para><!-- ENV DEPTH: 0. PREV DEPTH: 1. NEXT DEPTH: 1 -->Second item<!-- closeWrapper: 0 --></para>
-<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; PREV SHALLOWER  --><!-- Result: 1 -->
-<itemizedlist>
-<listitem>
-<para><!-- ENV DEPTH: 1. PREV DEPTH: 0. NEXT DEPTH: 1 -->Second first item<!-- closeWrapper: 0 --></para>
+<para><!-- ENV DEPTH: 1. PREV DEPTH: 1. NEXT DEPTH: 1 -->First second item<!-- closeWrapper: 0 --></para>
 <!-- closeWrapper: condition met -->
 </listitem>
-<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; SAME DEPTH  --><!-- Result: 0 -->
-<listitem>
-<para><!-- ENV DEPTH: 1. PREV DEPTH: 1. NEXT DEPTH: 0 -->Second second item<!-- closeWrapper: 2 --></para>
-<!-- closeWrapper first iteration: 2 -->
-</listitem>
-</itemizedlist>
-<!-- closeWrapper first iteration: 1 -->
-</listitem>
-</itemizedlist>
+<!-- closeWrapper has looped --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; SAME DEPTH  --><!-- Result: 0 -->
+<para>Text after first item<!-- closeWrapper: 2 --><!-- closeWrapper first iteration: 2 --></para>
+<!-- closeWrapper first iteration: 1 --><!-- Output Error: Tried to close `para' when tag was not open. Tag discarded. -->
+
 <!-- closeWrapper has looped --></article>
\ No newline at end of file
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index a9140ab..78c4bda 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -345,7 +345,8 @@ void closeParTag(XMLStream & xs, Paragraph const * par, Paragraph const * nextpa
 			}
 		} else {
 			if (nextpar->getDepth() == par->getDepth()) {
-				closeWrapper = 1;
+				// This is not wrapped: this must be the rest of the item, still within the wrapper.
+				closeWrapper = 0;
 			} else if (nextpar->getDepth() > par->getDepth()) {
 				// The next paragraph is deeper: no need to close the wrapper, only to open it (cf. openParTag).
 				closeWrapper = 0;

commit 54e11837056cbd66b806c86e41361388b995b8ea
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 02:43:30 2020 +0200

    XML: use the new mechanisms for CR detection with errors.
    
    This helps tracking down line problems even in the presence of errors.

diff --git a/src/xml.cpp b/src/xml.cpp
index 1a25e54..0daa9d8 100644
--- a/src/xml.cpp
+++ b/src/xml.cpp
@@ -167,17 +167,21 @@ bool FontTag::operator==(StartTag const & tag) const
 } // namespace xml
 
 
-void XMLStream::writeError(std::string const &s) const
+void XMLStream::writeError(std::string const &s)
 {
 	LYXERR0(s);
-	os_ << from_utf8("<!-- Output Error: " + s + " -->\n");
+	*this << ESCAPE_NONE << from_utf8("<!-- Output Error: " + s + " -->");
+	*this << xml::CR();
 }
 
 
-void XMLStream::writeError(docstring const &s) const
+void XMLStream::writeError(docstring const &s)
 {
 	LYXERR0(s);
-	os_ << from_utf8("<!-- Output Error: ") << s << from_utf8(" -->\n");
+	*this << ESCAPE_NONE << from_utf8("<!-- Output Error: ");
+	*this << s;
+	*this << ESCAPE_NONE << from_utf8(" -->");
+	*this << xml::CR();
 }
 
 
diff --git a/src/xml.h b/src/xml.h
index ccb1293..bbf5b58 100644
--- a/src/xml.h
+++ b/src/xml.h
@@ -105,9 +105,9 @@ public:
 	/// that simplifies the logic using this code.
 	bool isLastTagCR() const { return is_last_tag_cr_; };
 	///
-	void writeError(std::string const &) const;
+	void writeError(std::string const &);
 	///
-	void writeError(docstring const &) const;
+	void writeError(docstring const &);
 	///
 	typedef std::shared_ptr<xml::StartTag> TagPtr;
 	/// Returns the last element on the tag stack. XMLStream keeps ownership of the item.

commit bd274b5ffce1cca4949584c8c988f1a15312fedf
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Thu Aug 27 00:52:06 2020 +0200

    WIP...

diff --git a/autotests/export/docbook/lists.lyx b/autotests/export/docbook/lists.lyx
index f4a58c2..d8b9c1b 100644
--- a/autotests/export/docbook/lists.lyx
+++ b/autotests/export/docbook/lists.lyx
@@ -103,8 +103,56 @@ I'm the second line
 \end_layout
 
 \begin_layout Standard
+A simple enumerated list: 
+\end_layout
+
+\begin_layout Enumerate
+First item
+\end_layout
+
+\begin_layout Enumerate
+Second item on two lines
+\begin_inset Newline newline
+\end_inset
+
+I'm the second line
+\end_layout
+
+\begin_layout Standard
+Nested lists:
+\end_layout
+
+\begin_layout Itemize
+First item
+\end_layout
+
+\begin_deeper
+\begin_layout Itemize
+First first item
+\end_layout
+
+\begin_layout Itemize
+First second item
+\end_layout
+
+\end_deeper
+\begin_layout Itemize
+Second item
+\end_layout
+
+\begin_deeper
+\begin_layout Itemize
+Second first item
+\end_layout
+
+\begin_layout Itemize
+Second second item
+\end_layout
+
+\end_deeper
+\begin_layout Standard
 \begin_inset Note Note
-status collapsed
+status open
 
 \begin_layout Plain Layout
 A complex list:
@@ -133,6 +181,56 @@ Second item
 \end_layout
 
 \begin_deeper
+\begin_layout Itemize
+Second first item
+\end_layout
+
+\begin_layout Itemize
+Second second item
+\end_layout
+
+\begin_layout Plain Layout
+Text after second item
+\end_layout
+
+\end_deeper
+\begin_layout Plain Layout
+
+\end_layout
+
+\end_inset
+
+
+\begin_inset Note Note
+status open
+
+\begin_layout Plain Layout
+A very complex list:
+\end_layout
+
+\begin_layout Itemize
+First item
+\end_layout
+
+\begin_deeper
+\begin_layout Itemize
+First first item
+\end_layout
+
+\begin_layout Itemize
+First second item
+\end_layout
+
+\begin_layout Plain Layout
+Text after first item
+\end_layout
+
+\end_deeper
+\begin_layout Itemize
+Second item
+\end_layout
+
+\begin_deeper
 \begin_layout Enumerate
 Second first item
 \end_layout
diff --git a/autotests/export/docbook/lists.xml b/autotests/export/docbook/lists.xml
index d7b24f6..4c3f588 100644
--- a/autotests/export/docbook/lists.xml
+++ b/autotests/export/docbook/lists.xml
@@ -2,15 +2,84 @@
 <!-- This DocBook file was created by LyX 2.4.0dev
   See http://www.lyx.org/ for more information -->
 <article xml:lang="en_US" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:xi="http://www.w3.org/2001/XInclude" version="5.2">
-<title>Test document</title>
-<para>A simple list: </para>
+<!-- Decision to open the wrapper:  --><!-- Result: 0 -->
+<title>Test document<!-- closeWrapper: 1 --><!-- closeWrapper: condition met --></title>
+<!-- closeWrapper first iteration: 1 --><!-- Output Error: Tried to close `title' when no tags were open! -->
+
+<!-- closeWrapper has looped --><!-- Decision to open the wrapper: prevpar != nullptr;  --><!-- Result: 0 -->
+<para>A simple list: <!-- closeWrapper: 0 --><!-- closeWrapper: condition met --></para>
+<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr;  --><!-- Result: 1 -->
 <itemizedlist>
 <listitem>
-<para>First item</para>
+<para><!-- ENV DEPTH: 0. PREV DEPTH: 0. NEXT DEPTH: 0 -->First item<!-- closeWrapper: 0 --></para>
+<!-- closeWrapper: condition met -->
 </listitem>
+<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; SAME DEPTH  --><!-- Result: 0 -->
 <listitem>
-<para>Second item on two lines</para>
-<para>I'm the second line</para>
+<para><!-- ENV DEPTH: 0. PREV DEPTH: 0. NEXT DEPTH: 0 -->Second item on two lines</para>
+<para>I'm the second line<!-- closeWrapper: 1 --></para>
+<!-- closeWrapper: condition met -->
 </listitem>
+<!-- closeWrapper first iteration: 1 -->
+<!-- Output Error: Tried to close `listitem' when tag was not open. Tag discarded. -->
+
 </itemizedlist>
-</article>
\ No newline at end of file
+<!-- closeWrapper has looped --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; SAME DEPTH  --><!-- Result: 0 -->
+<para>A simple enumerated list: <!-- closeWrapper: 0 --><!-- closeWrapper: condition met --></para>
+<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr;  --><!-- Result: 1 -->
+<orderedlist>
+<listitem>
+<para><!-- ENV DEPTH: 0. PREV DEPTH: 0. NEXT DEPTH: 0 -->First item<!-- closeWrapper: 0 --></para>
+<!-- closeWrapper: condition met -->
+</listitem>
+<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; SAME DEPTH  --><!-- Result: 0 -->
+<listitem>
+<para><!-- ENV DEPTH: 0. PREV DEPTH: 0. NEXT DEPTH: 0 -->Second item on two lines</para>
+<para>I'm the second line<!-- closeWrapper: 1 --></para>
+<!-- closeWrapper: condition met -->
+</listitem>
+<!-- closeWrapper first iteration: 1 -->
+<!-- Output Error: Tried to close `listitem' when tag was not open. Tag discarded. -->
+
+</orderedlist>
+<!-- closeWrapper has looped --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; SAME DEPTH  --><!-- Result: 0 -->
+<para>Nested lists:<!-- closeWrapper: 0 --><!-- closeWrapper: condition met --></para>
+<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr;  --><!-- Result: 1 -->
+<itemizedlist>
+<listitem>
+<para><!-- ENV DEPTH: 0. PREV DEPTH: 0. NEXT DEPTH: 1 -->First item<!-- closeWrapper: 0 --></para>
+<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; PREV SHALLOWER  --><!-- Result: 1 -->
+<itemizedlist>
+<listitem>
+<para><!-- ENV DEPTH: 1. PREV DEPTH: 0. NEXT DEPTH: 1 -->First first item<!-- closeWrapper: 0 --></para>
+<!-- closeWrapper: condition met -->
+</listitem>
+<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; SAME DEPTH  --><!-- Result: 0 -->
+<listitem>
+<para><!-- ENV DEPTH: 1. PREV DEPTH: 1. NEXT DEPTH: 0 -->First second item<!-- closeWrapper: 2 --></para>
+<!-- closeWrapper first iteration: 2 -->
+</listitem>
+</itemizedlist>
+<!-- closeWrapper first iteration: 1 -->
+</listitem>
+</itemizedlist>
+<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; PREV DEEPER  --><!-- Result: 1 -->
+<itemizedlist>
+<listitem>
+<para><!-- ENV DEPTH: 0. PREV DEPTH: 1. NEXT DEPTH: 1 -->Second item<!-- closeWrapper: 0 --></para>
+<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; PREV SHALLOWER  --><!-- Result: 1 -->
+<itemizedlist>
+<listitem>
+<para><!-- ENV DEPTH: 1. PREV DEPTH: 0. NEXT DEPTH: 1 -->Second first item<!-- closeWrapper: 0 --></para>
+<!-- closeWrapper: condition met -->
+</listitem>
+<!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr; prevlay.docbookwrappertag() != NONE; SAME DEPTH  --><!-- Result: 0 -->
+<listitem>
+<para><!-- ENV DEPTH: 1. PREV DEPTH: 1. NEXT DEPTH: 0 -->Second second item<!-- closeWrapper: 2 --></para>
+<!-- closeWrapper first iteration: 2 -->
+</listitem>
+</itemizedlist>
+<!-- closeWrapper first iteration: 1 -->
+</listitem>
+</itemizedlist>
+<!-- closeWrapper has looped --></article>
\ No newline at end of file
diff --git a/lib/layouts/stdlists.inc b/lib/layouts/stdlists.inc
index c0b346d..f6dd411 100644
--- a/lib/layouts/stdlists.inc
+++ b/lib/layouts/stdlists.inc
@@ -87,7 +87,9 @@ Style Enumerate
 			Color latex
 		EndFont
 	EndArgument
-	DocBookTag            orderedlist
+	DocBookWrapperTag     orderedlist
+	DocBookWrapperMergeWithPrevious    true
+	DocBookTag            NONE
 	DocBookItemTag        listitem
 	DocBookItemInnerTag   para
 End
@@ -129,7 +131,9 @@ Style Description
 			Color latex
 		EndFont
 	EndArgument
-	DocBookTag            variablelist
+	DocBookWrapperTag     variablelist
+	DocBookWrapperMergeWithPrevious  true
+	DocBookTag            NONE
 	DocBookItemWrapperTag varlistentry
 	DocBookItemTag        listitem
 	DocBookItemInnerTag   para
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index 6668ee7..a9140ab 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -269,13 +269,34 @@ void openParTag(XMLStream & xs, const Paragraph * par, const Paragraph * prevpar
 	// next paragraph is the affiliation, then it should be output in the same <author> tag (different
 	// layout, same wrapper tag).
 	bool openWrapper = lay.docbookwrappertag() != "NONE";
+	xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- Decision to open the wrapper: ");
 	if (prevpar != nullptr) {
+		xs << XMLStream::ESCAPE_NONE << from_ascii("prevpar != nullptr; ");
 		Layout const & prevlay = prevpar->layout();
 		if (prevlay.docbookwrappertag() != "NONE") {
-			openWrapper = prevlay.docbookwrappertag() == lay.docbookwrappertag()
-					&& !lay.docbookwrappermergewithprevious();
+			xs << XMLStream::ESCAPE_NONE << from_ascii("prevlay.docbookwrappertag() != NONE; ");
+			if (prevpar->getDepth() == par->getDepth()) {
+				// Same depth: the basic condition applies.
+				openWrapper = prevlay.docbookwrappertag() == lay.docbookwrappertag()
+				              && !lay.docbookwrappermergewithprevious();
+				xs << XMLStream::ESCAPE_NONE << from_ascii("SAME DEPTH ");
+			} else if (prevpar->getDepth() > par->getDepth()) {
+				// The previous paragraph was deeper: close the wrapper, no need to open it.
+				xs << XMLStream::ESCAPE_NONE << from_ascii("PREV DEEPER ");
+			} else {
+				// This paragraph is deeper than the previous one: open the wrapper,
+				// disregarding docbookwrappermergewithprevious.
+				// Don't change openWrapper!
+				openWrapper = lay.docbookwrappertag() != "NONE"; // prevlay.docbookwrappertag() == lay.docbookwrappertag();
+				xs << XMLStream::ESCAPE_NONE << from_ascii("PREV SHALLOWER ");
+			}
+		} else {
+//			openWrapper = false;
 		}
 	}
+	xs << XMLStream::ESCAPE_NONE << from_ascii(" -->");
+
+	xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- Result: " + to_string(openWrapper) + " -->");
 
 	// Main logic.
 	if (openWrapper)
@@ -285,8 +306,8 @@ void openParTag(XMLStream & xs, const Paragraph * par, const Paragraph * prevpar
 	if (tag != "NONE") {
 		auto xmltag = xml::ParTag(tag, lay.docbookattr());
 		if (!xs.isTagOpen(xmltag, 1)) // Don't nest a paragraph directly in a paragraph.
-			// TODO: required or not?
-			// TODO: avoid creating a ParTag object just for this query...
+			// TODO: is this condition required or not?
+			// TODO: avoid creating a ParTag object (xmltag) just for this query...
 			openTag(xs, lay.docbooktag(), lay.docbookattr(), lay.docbooktagtype());
 	}
 
@@ -301,22 +322,63 @@ void closeParTag(XMLStream & xs, Paragraph const * par, Paragraph const * nextpa
 		nextpar = nullptr;
 
 	// See comment in openParTag.
+	// If closeWrapper == 0, the wrapper should not be closed: the next paragraph is another item to add to this list.
 	Layout const & lay = par->layout();
-	bool closeWrapper = lay.docbookwrappertag() != "NONE";
-	if (nextpar != nullptr) {
-		Layout const & nextlay = nextpar->layout();
+	long long closeWrapper = 0; // (lay.docbookwrappertag() == "NONE") ? 0 : 1; // Avoid unsigned, as -1 might appear as value.
+	if (nextpar == nullptr) {
+		closeWrapper = 1L + (long long) par->getDepth();
+	} else {
+		Layout const &nextlay = nextpar->layout();
 		if (nextlay.docbookwrappertag() != "NONE") {
-			closeWrapper = nextlay.docbookwrappertag() == lay.docbookwrappertag()
-					&& !nextlay.docbookwrappermergewithprevious();
+			if (nextpar->getDepth() == par->getDepth()) {
+				// Same depth: the basic condition applies.
+				closeWrapper = nextlay.docbookwrappertag() == lay.docbookwrappertag()
+				               && !nextlay.docbookwrappermergewithprevious();
+			} else if (nextpar->getDepth() > par->getDepth()) {
+				// The next paragraph is deeper: no need to close the wrapper, only to open it (cf. openParTag).
+				closeWrapper = 0;
+			} else {
+				// This paragraph is deeper than the next one: close the wrapper,
+				// disregarding docbookwrappermergewithprevious.
+				// Hypothesis: nextlay.docbookwrappertag() == lay.docbookwrappertag(). TODO: THIS IS WRONG! Loop back until a layout with the right depth is found?
+				closeWrapper = 1L + (long long) par->getDepth() - (long long) nextpar->getDepth(); // > 0, as nextpar->getDepth() < par->getDepth()
+			}
+		} else {
+			if (nextpar->getDepth() == par->getDepth()) {
+				closeWrapper = 1;
+			} else if (nextpar->getDepth() > par->getDepth()) {
+				// The next paragraph is deeper: no need to close the wrapper, only to open it (cf. openParTag).
+				closeWrapper = 0;
+			} else {
+				// This paragraph is deeper than the next one: close the wrapper,
+				// disregarding docbookwrappermergewithprevious.
+				// Hypothesis: nextlay.docbookwrappertag() == lay.docbookwrappertag(). TODO: THIS IS WRONG! Loop back until a layout with the right depth is found?
+				closeWrapper = 1L + (long long) par->getDepth() - (long long) nextpar->getDepth(); // > 0, as nextpar->getDepth() < par->getDepth()
+			}
 		}
 	}
 
-	// Main logic.
+	// Main logic. (Comments mostly correspond to lists.)
+	xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- closeWrapper: " + to_string(closeWrapper) + " -->");
+	// - Close this paragraph.
 	closeTag(xs, lay.docbookiteminnertag(), lay.docbookiteminnertagtype());
-	closeTag(xs, lay.docbookitemtag(), lay.docbookitemtagtype());
-	closeTag(xs, lay.docbooktag(), lay.docbooktagtype());
-	if (closeWrapper)
+
+	// - Close the current item.
+	if (!nextpar || nextpar->getDepth() == par->getDepth()) {
+		xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- closeWrapper: condition met -->");
+		closeTag(xs, lay.docbookitemtag(), lay.docbookitemtagtype());
+		closeTag(xs, lay.docbooktag(), lay.docbooktagtype());
+	}
+
+	// - Close wrapper tags as many times as required.
+	while (closeWrapper > 0) {
+		xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- closeWrapper first iteration: " + to_string(closeWrapper) + " -->");
+		closeTag(xs, lay.docbookitemtag(), lay.docbookitemtagtype());
+		closeTag(xs, lay.docbooktag(), lay.docbooktagtype());
 		closeTag(xs, lay.docbookwrappertag(), lay.docbookwrappertagtype());
+		closeWrapper -= 1;
+	}
+	xs << XMLStream::ESCAPE_NONE << "<!-- closeWrapper has looped -->";
 }
 
 
@@ -514,11 +576,23 @@ void makeEnvironment(
 {
 	auto const end = text.paragraphs().end();
 
+	xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- " + to_string(par->layout().latextype) + " -->");
+
 	// Output the opening tag for this environment, but only if it has not been previously opened (condition
 	// implemented in openParTag).
 	auto prevpar = text.paragraphs().getParagraphBefore(par);
 	openParTag(xs, &*par, prevpar); // TODO: switch in layout for par/block?
 
+	xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- ENV DEPTH: " + to_string(par->getDepth()) + ". ");
+	if (prevpar)
+		xs << XMLStream::ESCAPE_NONE << from_ascii("PREV DEPTH: " + to_string(prevpar->getDepth()) + ". ");
+	if (par != end) {
+		auto nextpar = par;
+		++nextpar;
+		xs << XMLStream::ESCAPE_NONE << from_ascii("NEXT DEPTH: " + to_string(nextpar->getDepth()));
+	}
+	xs << XMLStream::ESCAPE_NONE << from_ascii(" -->");
+
 	// Generate the contents of this environment. There is a special case if this is like some environment.
 	Layout const & style = par->layout();
 	if (style.latextype == LATEX_COMMAND) {
@@ -593,6 +667,17 @@ void makeEnvironment(
 		makeAny(text, buf, xs, runparams, par);
 	}
 
+//	stack<Layout> previous_;
+//	int curdepth = -1; text.paragraphs().front().getDepth();
+//	for (auto const & p : text.paragraphs()) {
+//		if (p.layout().latextype == LATEX_ITEM_ENVIRONMENT) {
+//			if (curdepth ) {
+//				;
+//			}
+//			curdepth = p.getDepth();
+//		} else if (curdepth > 0)
+//	}
+
 	// Close the environment.
 	auto nextpar = par;
 	++nextpar;
diff --git a/src/xml.cpp b/src/xml.cpp
index b4004af..1a25e54 100644
--- a/src/xml.cpp
+++ b/src/xml.cpp
@@ -181,6 +181,12 @@ void XMLStream::writeError(docstring const &s) const
 }
 
 
+XMLStream::TagPtr XMLStream::getLastStackTag()
+{
+	return tag_stack_.back();
+}
+
+
 bool XMLStream::closeFontTags()
 {
 	if (isTagPending(xml::parsep_tag))
diff --git a/src/xml.h b/src/xml.h
index 576a4f2..ccb1293 100644
--- a/src/xml.h
+++ b/src/xml.h
@@ -108,6 +108,10 @@ public:
 	void writeError(std::string const &) const;
 	///
 	void writeError(docstring const &) const;
+	///
+	typedef std::shared_ptr<xml::StartTag> TagPtr;
+	/// Returns the last element on the tag stack. XMLStream keeps ownership of the item.
+	TagPtr getLastStackTag();
 private:
 	///
 	void clearTagDeque();
@@ -123,7 +127,6 @@ private:
 	// own these pointers and how they will be deleted, so we use shared
 	// pointers.
 	///
-	typedef std::shared_ptr<xml::StartTag> TagPtr;
 	typedef std::deque<TagPtr> TagDeque;
 	///
 	template <typename T>

-----------------------------------------------------------------------

Summary of changes:


hooks/post-receive
-- 
Repository for new features


More information about the lyx-cvs mailing list