[LyX features/feature/docbook] WIP: clean some mess.

Thibaut Cuvelier tcuvelier at lyx.org
Sat Aug 29 01:27:59 UTC 2020


The branch, feature/docbook, has been updated.

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

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

    WIP: clean some mess.

diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index 4d156d0..e8edee1 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -708,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 cbbba04773004ef1331afc91c5afddde0b10405a
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..4d156d0 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());

commit b1a683c696abc4129adb6111e0be42797365c6de
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 4d038e49c39d8e08448b8f987b878f694922ab15
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 03:44:17 2020 +0200

    WIP...

diff --git a/autotests/export/docbook/lists.lyx b/autotests/export/docbook/lists.lyx
index 1f51b1d..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
 
@@ -106,7 +110,7 @@ I'm the second line
 Third item
 \end_layout
 
-\begin_layout Standard
+\begin_layout Plain Layout
 A simple enumerated list: 
 \end_layout
 
@@ -122,7 +126,7 @@ Second item on two lines
 I'm the second line
 \end_layout
 
-\begin_layout Standard
+\begin_layout Plain Layout
 Nested lists:
 \end_layout
 
@@ -154,11 +158,12 @@ Second second item
 \end_layout
 
 \end_deeper
-\begin_layout Standard
-\begin_inset Note Note
-status open
+\end_inset
 
-\begin_layout Plain Layout
+
+\end_layout
+
+\begin_layout Standard
 A complex list:
 \end_layout
 
@@ -175,7 +180,7 @@ First first item
 First second item
 \end_layout
 
-\begin_layout Plain Layout
+\begin_layout Standard
 Text after first item
 \end_layout
 
@@ -193,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 ee6a152..4b72f7f 100644
--- a/autotests/export/docbook/lists.xml
+++ b/autotests/export/docbook/lists.xml
@@ -3,30 +3,7 @@
   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>
-<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>
+<para>A complex list:</para>
 <itemizedlist>
 <listitem>
 <para>First item</para>
@@ -39,6 +16,8 @@
 </listitem>
 </itemizedlist>
 </listitem>
+Text after first item
+<itemizedlist>
 <listitem>
 <para>Second item</para>
 <itemizedlist>
@@ -50,5 +29,7 @@
 </listitem>
 </itemizedlist>
 </listitem>
+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 e632ceb..617d3b7 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -693,8 +693,8 @@ ParagraphList::const_iterator makeListEnvironment(Buffer const &buf,
 		// 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 = makeListEnvironment(buf, xs, runparams, text, par);
+		if (par != envend && par->getDepth() != currentDepth)
+			par = makeAny(buf, xs, runparams, text, par);
 
 		// Close the item.
 		closeTag(xs, style.docbookitemwrappertag(), style.docbookitemwrappertagtype());

commit ddd605523443078207e95614bb151dc97cbb33a3
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..1f51b1d 100644
--- a/autotests/export/docbook/lists.lyx
+++ b/autotests/export/docbook/lists.lyx
@@ -102,6 +102,10 @@ Second item on two lines
 I'm the second line
 \end_layout
 
+\begin_layout Itemize
+Third item
+\end_layout
+
 \begin_layout Standard
 A simple enumerated list: 
 \end_layout
@@ -119,10 +123,6 @@ 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,6 +154,10 @@ 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
diff --git a/autotests/export/docbook/lists.xml b/autotests/export/docbook/lists.xml
index 266cab6..ee6a152 100644
--- a/autotests/export/docbook/lists.xml
+++ b/autotests/export/docbook/lists.xml
@@ -2,15 +2,8 @@
 <!-- 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 simple list: </para>
 <itemizedlist>
 <listitem>
 <para>First item</para>
@@ -19,18 +12,11 @@
 <para>Second item on two lines</para>
 <para>I'm the second line</para>
 </listitem>
-</itemizedlist>
-<itemizedlist>
 <listitem>
-<para>Second item on two lines</para>
-<para>I'm the second line</para>
+<para>Third item</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 -->
+<para>A simple enumerated list: </para>
 <orderedlist>
 <listitem>
 <para>First item</para>
@@ -40,10 +26,29 @@
 <para>I'm the second line</para>
 </listitem>
 </orderedlist>
-<orderedlist>
+<para>Nested lists:</para>
+<itemizedlist>
 <listitem>
-<para>Second item on two lines</para>
-<para>I'm the second line</para>
+<para>First item</para>
+<itemizedlist>
+<listitem>
+<para>First first item</para>
 </listitem>
-</orderedlist>
+<listitem>
+<para>First second item</para>
+</listitem>
+</itemizedlist>
+</listitem>
+<listitem>
+<para>Second item</para>
+<itemizedlist>
+<listitem>
+<para>Second first item</para>
+</listitem>
+<listitem>
+<para>Second second item</para>
+</listitem>
+</itemizedlist>
+</listitem>
+</itemizedlist>
 </article>
\ No newline at end of file
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index 75095b6..e632ceb 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 = makeListEnvironment(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 eee7387c4912589bec354d967a925adb1143d744
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 d4801b8d49e386a15c094f08534d1b8f2f1eeb13
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 03:26:07 2020 +0200

    WIP: restore open/closeParTag.

diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index 3ec1d9e..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 -->";
 }
 
 

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

    WIP: rewrite makeListEnv.

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..3ec1d9e 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -660,41 +660,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 +742,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 61b0383cffeb0b586e28b987a11c5bb44f02363c
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 8f160bb840428aa7059e18808c0ccf957838bea0
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 4f2edfa7966deba19c823c054695be9c0376b122
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 9bbf953d8ca5830ccad2a6f6aeda3ab46205c5fb
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 fc5f06a7cb7c57d889c6733030cabbbc3e5e2a69
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 02:38:49 2020 +0200

    WIP... WORKS on many cases! But not all...

diff --git a/autotests/export/docbook/lists.lyx b/autotests/export/docbook/lists.lyx
index ecfb81d..d8b9c1b 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,11 +118,6 @@ Second item on two lines
 I'm the second line
 \end_layout
 
-\end_inset
-
-
-\end_layout
-
 \begin_layout Standard
 Nested lists:
 \end_layout
@@ -145,10 +136,6 @@ First second item
 \end_layout
 
 \end_deeper
-\begin_layout Standard
-\begin_inset Note Note
-status open
-
 \begin_layout Itemize
 Second item
 \end_layout
@@ -163,11 +150,6 @@ Second second item
 \end_layout
 
 \end_deeper
-\end_inset
-
-
-\end_layout
-
 \begin_layout Standard
 \begin_inset Note Note
 status open
@@ -213,6 +195,16 @@ Text after second item
 
 \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
 
diff --git a/autotests/export/docbook/lists.xml b/autotests/export/docbook/lists.xml
index ae6b6bf..4c3f588 100644
--- a/autotests/export/docbook/lists.xml
+++ b/autotests/export/docbook/lists.xml
@@ -7,6 +7,42 @@
 <!-- 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><!-- 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>
 <!-- closeWrapper has looped --><!-- 4 --><!-- Decision to open the wrapper: prevpar != nullptr;  --><!-- Result: 1 -->
 <itemizedlist>
@@ -27,4 +63,23 @@
 <!-- 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

commit 9f9f7302771535ad9b789c3b6570143441d2590a
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 02:37:20 2020 +0200

    WIP... WORKS on one example!

diff --git a/autotests/export/docbook/lists.lyx b/autotests/export/docbook/lists.lyx
index 05f23d3..ecfb81d 100644
--- a/autotests/export/docbook/lists.lyx
+++ b/autotests/export/docbook/lists.lyx
@@ -128,7 +128,7 @@ I'm the second line
 \end_layout
 
 \begin_layout Standard
-Nested lists: 
+Nested lists:
 \end_layout
 
 \begin_layout Itemize
diff --git a/autotests/export/docbook/lists.xml b/autotests/export/docbook/lists.xml
index 902fa7d..ae6b6bf 100644
--- a/autotests/export/docbook/lists.xml
+++ b/autotests/export/docbook/lists.xml
@@ -2,33 +2,29 @@
 <!-- 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 -->
-<para>Nested lists: <!-- closeWrapper: 0 --><!-- closeWrapper: condition met --></para>
-<!-- closeWrapper has looped --><!-- 4 -->
+<!-- closeWrapper has looped --><!-- Decision to open the wrapper: prevpar != nullptr;  --><!-- 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: 1 --></para>
-<!-- closeWrapper first iteration: 1 -->
-</listitem>
-</itemizedlist>
-<!-- closeWrapper has looped --><!-- 4 -->
+<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 -->
+<!-- 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 -->
-<!-- Output Error: Tried to close `listitem' when no tags were open! -->
-
-<!-- Output Error: Tried to close `itemizedlist' when no tags were open! -->
-
+</listitem>
+</itemizedlist>
 <!-- closeWrapper has looped --></article>
\ No newline at end of file
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index 4a6adde..a9140ab 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -269,24 +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") {
+			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.
-				openWrapper = true; // prevlay.docbookwrappertag() == lay.docbookwrappertag();
+				// 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)
@@ -314,7 +324,7 @@ void closeParTag(XMLStream & xs, Paragraph const * par, Paragraph const * nextpa
 	// 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 = (lay.docbookwrappertag() == "NONE") ? 0 : 1; // Avoid unsigned, as -1 might appear as value.
+	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 {
@@ -326,6 +336,7 @@ void closeParTag(XMLStream & xs, Paragraph const * par, Paragraph const * nextpa
 				               && !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.
@@ -337,6 +348,7 @@ void closeParTag(XMLStream & xs, Paragraph const * par, Paragraph const * nextpa
 				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.

commit e5e81a94489ed4a7ad4c898931de980b5cd7f233
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 02:31:23 2020 +0200

    WIP...

diff --git a/autotests/export/docbook/lists.lyx b/autotests/export/docbook/lists.lyx
index d5abc84..05f23d3 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,6 +122,11 @@ Second item on two lines
 I'm the second line
 \end_layout
 
+\end_inset
+
+
+\end_layout
+
 \begin_layout Standard
 Nested lists: 
 \end_layout
@@ -136,6 +145,10 @@ First second item
 \end_layout
 
 \end_deeper
+\begin_layout Standard
+\begin_inset Note Note
+status open
+
 \begin_layout Itemize
 Second item
 \end_layout
@@ -150,6 +163,11 @@ Second 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 255c802..902fa7d 100644
--- a/autotests/export/docbook/lists.xml
+++ b/autotests/export/docbook/lists.xml
@@ -2,58 +2,33 @@
 <!-- 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<!-- closeWrapper: 0 --></title>
-<para>A simple list: <!-- closeWrapper: 0 --></para>
-<!-- 4 -->
+<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 -->
+<para>Nested lists: <!-- closeWrapper: 0 --><!-- closeWrapper: condition met --></para>
+<!-- closeWrapper has looped --><!-- 4 -->
 <itemizedlist>
 <listitem>
-<para><!-- ENV: 0 --><!-- PREVDEPTH: 0 -->First item<!-- closeWrapper: 0 --></para>
-</listitem>
-<!-- 4 -->
-<listitem>
-<para><!-- ENV: 0 --><!-- PREVDEPTH: 0 -->Second item on two lines</para>
-<para>I'm the second line<!-- closeWrapper: 1 --></para>
-</listitem>
-</itemizedlist>
-<para>A simple enumerated list: <!-- closeWrapper: 0 --></para>
-<!-- 4 -->
-<orderedlist>
-<listitem>
-<para><!-- ENV: 0 --><!-- PREVDEPTH: 0 -->First item<!-- closeWrapper: 0 --></para>
-</listitem>
-<!-- 4 -->
-<listitem>
-<para><!-- ENV: 0 --><!-- PREVDEPTH: 0 -->Second item on two lines</para>
-<para>I'm the second line<!-- closeWrapper: 1 --></para>
-</listitem>
-</orderedlist>
-<para>Nested lists: <!-- closeWrapper: 0 --></para>
-<!-- 4 -->
-<itemizedlist>
-<listitem>
-<para><!-- ENV: 0 --><!-- PREVDEPTH: 0 -->First item<!-- closeWrapper: 0 --></para>
-<!-- 4 -->
-<itemizedlist>
-<listitem>
-<para><!-- ENV: 1 --><!-- PREVDEPTH: 0 -->First first item<!-- closeWrapper: 0 --></para>
-</listitem>
-<!-- 4 -->
-<listitem>
-<para><!-- ENV: 1 --><!-- PREVDEPTH: 1 -->First second item<!-- closeWrapper: 1 --></para>
+<para><!-- ENV DEPTH: 0. PREV DEPTH: 0. NEXT DEPTH: 1 -->First item<!-- closeWrapper: 1 --></para>
+<!-- closeWrapper first iteration: 1 -->
 </listitem>
 </itemizedlist>
-<!-- 4 -->
-<itemizedlist>
-<listitem>
-<para><!-- ENV: 0 --><!-- PREVDEPTH: 1 -->Second item<!-- closeWrapper: 0 --></para>
-<!-- 4 -->
+<!-- closeWrapper has looped --><!-- 4 -->
 <itemizedlist>
 <listitem>
-<para><!-- ENV: 1 --><!-- PREVDEPTH: 0 -->Second first item<!-- closeWrapper: 0 --></para>
+<para><!-- ENV DEPTH: 1. PREV DEPTH: 0. NEXT DEPTH: 1 -->First first item<!-- closeWrapper: 0 --></para>
+<!-- closeWrapper: condition met -->
 </listitem>
-<!-- 4 -->
+<!-- closeWrapper has looped --><!-- 4 -->
 <listitem>
-<para><!-- ENV: 1 --><!-- PREVDEPTH: 1 -->Second second item<!-- closeWrapper: 1 --></para>
+<para><!-- ENV DEPTH: 1. PREV DEPTH: 1. NEXT DEPTH: 0 -->First second item<!-- closeWrapper: 2 --></para>
+<!-- closeWrapper first iteration: 2 -->
 </listitem>
 </itemizedlist>
-</article>
\ No newline at end of file
+<!-- closeWrapper first iteration: 1 -->
+<!-- Output Error: Tried to close `listitem' when no tags were open! -->
+
+<!-- Output Error: Tried to close `itemizedlist' when no tags were open! -->
+
+<!-- closeWrapper has looped --></article>
\ No newline at end of file
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index ac867c1..4a6adde 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -281,8 +281,10 @@ void openParTag(XMLStream & xs, const Paragraph * par, const Paragraph * prevpar
 			} else {
 				// This paragraph is deeper than the previous one: open the wrapper,
 				// disregarding docbookwrappermergewithprevious.
-				openWrapper = prevlay.docbookwrappertag() == lay.docbookwrappertag();
+				openWrapper = true; // prevlay.docbookwrappertag() == lay.docbookwrappertag();
 			}
+		} else {
+//			openWrapper = false;
 		}
 	}
 
@@ -294,8 +296,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());
 	}
 
@@ -310,47 +312,61 @@ 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();
-	unsigned long long closeWrapper = (lay.docbookwrappertag() == "NONE") ? 0 : 1;
-	if (nextpar != nullptr) {
-		Layout const & nextlay = nextpar->layout();
+	long long closeWrapper = (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.
+				// The next paragraph is deeper: no need to close the wrapper, only to open it (cf. openParTag).
+			} 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).
 			} else {
 				// This paragraph is deeper than the next one: close the wrapper,
 				// disregarding docbookwrappermergewithprevious.
-				// Hypothesis: nextlay.docbookwrappertag() == lay.docbookwrappertag(). TODO: THIS IS WRONG! Use a stack?
-				closeWrapper = par->getDepth() - nextpar->getDepth();
+				// 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 {
-		closeWrapper = 1 + 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());
+
+	// - 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());
-		if (closeWrapper > 0) {
-			closeTag(xs, lay.docbookwrappertag(), lay.docbookwrappertagtype());
-			closeWrapper -= 1;
-		}
 	}
+
+	// - 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 -->";
 }
 
 
@@ -555,9 +571,15 @@ void makeEnvironment(
 	auto prevpar = text.paragraphs().getParagraphBefore(par);
 	openParTag(xs, &*par, prevpar); // TODO: switch in layout for par/block?
 
-	xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- ENV: " + to_string(par->getDepth()) + " -->");
+	xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- ENV DEPTH: " + to_string(par->getDepth()) + ". ");
 	if (prevpar)
-		xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- PREVDEPTH: " + to_string(prevpar->getDepth()) + " -->");
+		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();
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>

commit a83b01665274f087f5a82d5130161e7d4ed47dfb
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Thu Aug 27 02:07:41 2020 +0200

    WIP...

diff --git a/autotests/export/docbook/lists.xml b/autotests/export/docbook/lists.xml
index 0609b36..255c802 100644
--- a/autotests/export/docbook/lists.xml
+++ b/autotests/export/docbook/lists.xml
@@ -4,44 +4,54 @@
 <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<!-- closeWrapper: 0 --></title>
 <para>A simple list: <!-- closeWrapper: 0 --></para>
+<!-- 4 -->
 <itemizedlist>
 <listitem>
 <para><!-- ENV: 0 --><!-- PREVDEPTH: 0 -->First item<!-- closeWrapper: 0 --></para>
 </listitem>
+<!-- 4 -->
 <listitem>
 <para><!-- ENV: 0 --><!-- PREVDEPTH: 0 -->Second item on two lines</para>
 <para>I'm the second line<!-- closeWrapper: 1 --></para>
 </listitem>
 </itemizedlist>
 <para>A simple enumerated list: <!-- closeWrapper: 0 --></para>
+<!-- 4 -->
 <orderedlist>
 <listitem>
 <para><!-- ENV: 0 --><!-- PREVDEPTH: 0 -->First item<!-- closeWrapper: 0 --></para>
 </listitem>
+<!-- 4 -->
 <listitem>
 <para><!-- ENV: 0 --><!-- PREVDEPTH: 0 -->Second item on two lines</para>
 <para>I'm the second line<!-- closeWrapper: 1 --></para>
 </listitem>
 </orderedlist>
 <para>Nested lists: <!-- closeWrapper: 0 --></para>
+<!-- 4 -->
 <itemizedlist>
 <listitem>
 <para><!-- ENV: 0 --><!-- PREVDEPTH: 0 -->First item<!-- closeWrapper: 0 --></para>
+<!-- 4 -->
 <itemizedlist>
 <listitem>
 <para><!-- ENV: 1 --><!-- PREVDEPTH: 0 -->First first item<!-- closeWrapper: 0 --></para>
 </listitem>
+<!-- 4 -->
 <listitem>
 <para><!-- ENV: 1 --><!-- PREVDEPTH: 1 -->First second item<!-- closeWrapper: 1 --></para>
 </listitem>
 </itemizedlist>
+<!-- 4 -->
 <itemizedlist>
 <listitem>
 <para><!-- ENV: 0 --><!-- PREVDEPTH: 1 -->Second item<!-- closeWrapper: 0 --></para>
+<!-- 4 -->
 <itemizedlist>
 <listitem>
 <para><!-- ENV: 1 --><!-- PREVDEPTH: 0 -->Second first item<!-- closeWrapper: 0 --></para>
 </listitem>
+<!-- 4 -->
 <listitem>
 <para><!-- ENV: 1 --><!-- PREVDEPTH: 1 -->Second second item<!-- closeWrapper: 1 --></para>
 </listitem>
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index 9de9238..ac867c1 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -324,7 +324,7 @@ void closeParTag(XMLStream & xs, Paragraph const * par, Paragraph const * nextpa
 			} else if (nextpar->getDepth() > par->getDepth()) {
 				// The next paragraph is deeper: no need to close the wrapper.
 			} else {
-				// This paragraph is deeper than the previous one: open the wrapper,
+				// This paragraph is deeper than the next one: close the wrapper,
 				// disregarding docbookwrappermergewithprevious.
 				// Hypothesis: nextlay.docbookwrappertag() == lay.docbookwrappertag(). TODO: THIS IS WRONG! Use a stack?
 				closeWrapper = par->getDepth() - nextpar->getDepth();
@@ -548,6 +548,8 @@ 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);
@@ -631,6 +633,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;

commit 7fba82b4bcf0473f266078220262acd5a5ac2ab0
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..d5abc84 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,46 @@ 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
+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..0609b36 100644
--- a/autotests/export/docbook/lists.xml
+++ b/autotests/export/docbook/lists.xml
@@ -2,15 +2,48 @@
 <!-- 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>
+<title>Test document<!-- closeWrapper: 0 --></title>
+<para>A simple list: <!-- closeWrapper: 0 --></para>
 <itemizedlist>
 <listitem>
-<para>First item</para>
+<para><!-- ENV: 0 --><!-- PREVDEPTH: 0 -->First item<!-- closeWrapper: 0 --></para>
 </listitem>
 <listitem>
-<para>Second item on two lines</para>
-<para>I'm the second line</para>
+<para><!-- ENV: 0 --><!-- PREVDEPTH: 0 -->Second item on two lines</para>
+<para>I'm the second line<!-- closeWrapper: 1 --></para>
+</listitem>
+</itemizedlist>
+<para>A simple enumerated list: <!-- closeWrapper: 0 --></para>
+<orderedlist>
+<listitem>
+<para><!-- ENV: 0 --><!-- PREVDEPTH: 0 -->First item<!-- closeWrapper: 0 --></para>
+</listitem>
+<listitem>
+<para><!-- ENV: 0 --><!-- PREVDEPTH: 0 -->Second item on two lines</para>
+<para>I'm the second line<!-- closeWrapper: 1 --></para>
+</listitem>
+</orderedlist>
+<para>Nested lists: <!-- closeWrapper: 0 --></para>
+<itemizedlist>
+<listitem>
+<para><!-- ENV: 0 --><!-- PREVDEPTH: 0 -->First item<!-- closeWrapper: 0 --></para>
+<itemizedlist>
+<listitem>
+<para><!-- ENV: 1 --><!-- PREVDEPTH: 0 -->First first item<!-- closeWrapper: 0 --></para>
+</listitem>
+<listitem>
+<para><!-- ENV: 1 --><!-- PREVDEPTH: 1 -->First second item<!-- closeWrapper: 1 --></para>
+</listitem>
+</itemizedlist>
+<itemizedlist>
+<listitem>
+<para><!-- ENV: 0 --><!-- PREVDEPTH: 1 -->Second item<!-- closeWrapper: 0 --></para>
+<itemizedlist>
+<listitem>
+<para><!-- ENV: 1 --><!-- PREVDEPTH: 0 -->Second first item<!-- closeWrapper: 0 --></para>
+</listitem>
+<listitem>
+<para><!-- ENV: 1 --><!-- PREVDEPTH: 1 -->Second second item<!-- closeWrapper: 1 --></para>
 </listitem>
 </itemizedlist>
 </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..9de9238 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -272,8 +272,17 @@ void openParTag(XMLStream & xs, const Paragraph * par, const Paragraph * prevpar
 	if (prevpar != nullptr) {
 		Layout const & prevlay = prevpar->layout();
 		if (prevlay.docbookwrappertag() != "NONE") {
-			openWrapper = prevlay.docbookwrappertag() == lay.docbookwrappertag()
-					&& !lay.docbookwrappermergewithprevious();
+			if (prevpar->getDepth() == par->getDepth()) {
+				// Same depth: the basic condition applies.
+				openWrapper = prevlay.docbookwrappertag() == lay.docbookwrappertag()
+				              && !lay.docbookwrappermergewithprevious();
+			} else if (prevpar->getDepth() > par->getDepth()) {
+				// The previous paragraph was deeper: close the wrapper, no need to open it.
+			} else {
+				// This paragraph is deeper than the previous one: open the wrapper,
+				// disregarding docbookwrappermergewithprevious.
+				openWrapper = prevlay.docbookwrappertag() == lay.docbookwrappertag();
+			}
 		}
 	}
 
@@ -302,21 +311,46 @@ void closeParTag(XMLStream & xs, Paragraph const * par, Paragraph const * nextpa
 
 	// See comment in openParTag.
 	Layout const & lay = par->layout();
-	bool closeWrapper = lay.docbookwrappertag() != "NONE";
+	unsigned long long closeWrapper = (lay.docbookwrappertag() == "NONE") ? 0 : 1;
 	if (nextpar != nullptr) {
 		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.
+			} else {
+				// This paragraph is deeper than the previous one: open the wrapper,
+				// disregarding docbookwrappermergewithprevious.
+				// Hypothesis: nextlay.docbookwrappertag() == lay.docbookwrappertag(). TODO: THIS IS WRONG! Use a stack?
+				closeWrapper = par->getDepth() - nextpar->getDepth();
+			}
 		}
+	} else {
+		closeWrapper = 1 + par->getDepth();
 	}
 
 	// Main logic.
+	xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- closeWrapper: " + to_string(closeWrapper) + " -->");
 	closeTag(xs, lay.docbookiteminnertag(), lay.docbookiteminnertagtype());
-	closeTag(xs, lay.docbookitemtag(), lay.docbookitemtagtype());
-	closeTag(xs, lay.docbooktag(), lay.docbooktagtype());
-	if (closeWrapper)
+	if (!nextpar || nextpar->getDepth() == par->getDepth()) {
+		closeTag(xs, lay.docbookitemtag(), lay.docbookitemtagtype());
+		closeTag(xs, lay.docbooktag(), lay.docbooktagtype());
+		if (closeWrapper > 0) {
+			closeTag(xs, lay.docbookwrappertag(), lay.docbookwrappertagtype());
+			closeWrapper -= 1;
+		}
+	}
+	while (closeWrapper > 0) {
+		closeTag(xs, lay.docbookitemtag(), lay.docbookitemtagtype());
+		closeTag(xs, lay.docbooktag(), lay.docbooktagtype());
 		closeTag(xs, lay.docbookwrappertag(), lay.docbookwrappertagtype());
+		closeWrapper -= 1;
+	}
 }
 
 
@@ -519,6 +553,10 @@ void makeEnvironment(
 	auto prevpar = text.paragraphs().getParagraphBefore(par);
 	openParTag(xs, &*par, prevpar); // TODO: switch in layout for par/block?
 
+	xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- ENV: " + to_string(par->getDepth()) + " -->");
+	if (prevpar)
+		xs << XMLStream::ESCAPE_NONE << from_ascii("<!-- PREVDEPTH: " + to_string(prevpar->getDepth()) + " -->");
+
 	// 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) {

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

Summary of changes:
 autotests/export/docbook/lists.lyx |   99 ++++++++++++++++--
 autotests/export/docbook/lists.xml |   92 ++++++++++++++++
 lib/layouts/stdlists.inc           |    4 +-
 src/output_docbook.cpp             |  205 ++++++++++++++++++++++++++++--------
 src/xml.cpp                        |   18 +++-
 src/xml.h                          |    9 +-
 6 files changed, 363 insertions(+), 64 deletions(-)


hooks/post-receive
-- 
Repository for new features


More information about the lyx-cvs mailing list