[LyX features/feature/docbook] DocBook: generate <partintro> when required.

Thibaut Cuvelier tcuvelier at lyx.org
Sat Aug 29 23:38:23 UTC 2020


The branch, feature/docbook, has been updated.

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

commit ecf93ca5aaf9c087e98a168752855177d808f868
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sun Aug 30 01:14:44 2020 +0200

    DocBook: generate <partintro> when required.

diff --git a/autotests/export/docbook/basic.xml b/autotests/export/docbook/basic.xml
index ea91d3d..49ec1f4 100644
--- a/autotests/export/docbook/basic.xml
+++ b/autotests/export/docbook/basic.xml
@@ -12,7 +12,9 @@
 <para>I am an abstract</para>
 <para>I am also an abstract</para>
 </abstract>
+
 </info>
+<para>I am a standard paragraph. </para>
 <section xml:id="sec.Sec-1">
 <title>I am the first section </title>
 <para>I am the first paragraph of the first section. </para>
diff --git a/autotests/export/docbook/basic_book.xml b/autotests/export/docbook/basic_book.xml
index 18496b9..c6e9078 100644
--- a/autotests/export/docbook/basic_book.xml
+++ b/autotests/export/docbook/basic_book.xml
@@ -17,7 +17,9 @@
 </chapter>
 <part>
 <title>First part</title>
+<partintro>
 <para>Part intro. </para>
+</partintro>
 <chapter>
 <title>First chapter of first part</title>
 <para>Paragraph. </para>
@@ -29,7 +31,9 @@
 </part>
 <part>
 <title>Second part</title>
+<partintro>
 <para>Part 2 intro. </para>
+</partintro>
 <chapter>
 <title>First chapter of second part</title>
 <para>Paragraph. </para>
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index 609f45c..f584b8b 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -819,7 +819,7 @@ bool hasOnlyNotes(Paragraph const & par)
 	for (int i = 0; i < par.size(); ++i)
 		// If you find something that is not an inset (like actual text) or an inset that is not a note,
 		// return false.
-		if (!par.isInset(i) || !dynamic_cast<InsetNote *>(par.insetList().get(i)))
+		if (!par.isInset(i) || par.getInset(i)->lyxCode() != NOTE_CODE)
 			return false;
 	return true;
 }
@@ -849,7 +849,7 @@ DocBookInfoTag getParagraphsWithInfo(ParagraphList const &paragraphs,
 	for (; cpit < epit; ++cpit) {
 		// Skip paragraphs that don't generate anything in DocBook.
 		Paragraph const & par = paragraphs[cpit];
-		if (par.empty() || par.emptyTag() || hasOnlyNotes(par))
+		if (hasOnlyNotes(par))
 			continue;
 
 		// There should never be any section here. (Just a sanity check: if this fails, this function could end up
@@ -867,14 +867,14 @@ DocBookInfoTag getParagraphsWithInfo(ParagraphList const &paragraphs,
 		}
 
 		// Based on layout information, store this paragraph in one set: should be in <info>, must be,
-		// or abstract ().
+		// or abstract (either because of layout or of position).
 		Layout const &style = par.layout();
 
 		if (style.docbookininfo() == "always")
 			mustBeInInfo.emplace(cpit);
 		else if (style.docbookininfo() == "maybe")
 			shouldBeInInfo.emplace(cpit);
-		else if (!hasAbstractLayout)
+		else if (documentHasSections && !hasAbstractLayout)
 			abstractNoLayout.emplace(cpit);
 		else // This should definitely not be in <info>.
 			break;
@@ -991,17 +991,17 @@ void docbookSimpleAllParagraphs(
 {
 	// Handle the given text, supposing it has no sections (i.e. a "simple" text). The input may vary in length
 	// between a single paragraph to a whole document.
+	pit_type const bpit = runparams.par_begin;
+	pit_type const epit = runparams.par_end;
+	ParagraphList const &paragraphs = text.paragraphs();
 
 	// First, the <info> tag.
-	ParagraphList const &paragraphs = text.paragraphs();
-	pit_type bpit = runparams.par_begin;
-	pit_type const epit = runparams.par_end;
 	DocBookInfoTag info = getParagraphsWithInfo(paragraphs, bpit, epit, false);
 	outputDocBookInfo(text, buf, xs, runparams, paragraphs, info);
 
 	// Then, the content. It starts where the <info> ends.
-	auto par = text.paragraphs().iterator_at(info.epit);
-	auto end = text.paragraphs().iterator_at(epit);
+	auto par = paragraphs.iterator_at(info.epit);
+	auto end = paragraphs.iterator_at(epit);
 	while (par != end) {
 		if (!hasOnlyNotes(*par))
 			par = makeAny(text, buf, xs, runparams, par);
@@ -1038,7 +1038,7 @@ void docbookParagraphs(Text const &text,
 	tie(documentHasSections, eppit) = hasDocumentSectioning(paragraphs, bpit, epit);
 
 	// Deal with "simple" documents, i.e. those without sections.
-	if (!documentHasSections){
+	if (!documentHasSections) {
 		docbookSimpleAllParagraphs(text, buf, xs, runparams);
 		return;
 	}
@@ -1046,7 +1046,7 @@ void docbookParagraphs(Text const &text,
 	// Output the first <info> tag (or just the title).
 	DocBookInfoTag info = getParagraphsWithInfo(paragraphs, bpit, eppit, true);
 	outputDocBookInfo(text, buf, xs, runparams, paragraphs, info);
-	bpit = eppit;
+	bpit = info.epit;
 
 	// Then, iterate through the paragraphs of this document.
 	bool currentlyInAppendix = false;
@@ -1139,6 +1139,29 @@ void docbookParagraphs(Text const &text,
 
 		// Generate this paragraph.
 		par = makeAny(text, buf, xs, ourparams, par);
+
+		// Some special sections may require abstracts (mostly parts, in books).
+		// TODO: docbookforceabstracttag is a bit contrived here, but it does the job. Having another field just for this would be cleaner, but that's just for <part> and <partintro>, so it's probably not worth the effort.
+		if (isLayoutSectioning(style) && style.docbookforceabstracttag() != "NONE") {
+			// This abstract may be found between the next paragraph and the next title.
+			pit_type cpit = std::distance(text.paragraphs().begin(), par);
+			pit_type ppit = std::get<1>(hasDocumentSectioning(paragraphs, cpit, epit));
+
+			// Generate this abstract (this code corresponds to parts of outputDocBookInfo).
+			DocBookInfoTag secInfo = getParagraphsWithInfo(paragraphs, cpit, ppit, true);
+
+			if (!secInfo.abstract.empty()) {
+				xs << xml::StartTag(style.docbookforceabstracttag());
+				xs << xml::CR();
+				for (auto const &p : secInfo.abstract)
+					makeAny(text, buf, xs, runparams, paragraphs.iterator_at(p));
+				xs << xml::EndTag(style.docbookforceabstracttag());
+				xs << xml::CR();
+			}
+
+			// Skip all the text that just has been generated.
+			par = paragraphs.iterator_at(ppit);
+		}
 	}
 
 	// If need be, close <section>s, but only at the end of the document (otherwise, dealt with at the beginning

commit 67c1425cba16e55c20e710515691c980b0ac85de
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sun Aug 30 00:58:50 2020 +0200

    DocBook: streamline code to handle sections.

diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index 375babb..609f45c 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -1069,18 +1069,18 @@ void docbookParagraphs(Text const &text,
 		if (isLayoutSectioning(style)) {
 			int level = style.toclevel;
 
-			// Need to close a previous section if it has the same level or a higher one (close <section> if opening a <h2>
-			// after a <h2>, <h3>, <h4>, <h5> or <h6>). More examples:
+			// Need to close a previous section if it has the same level or a higher one (close <section> if opening a
+			// <h2> after a <h2>, <h3>, <h4>, <h5> or <h6>). More examples:
 			//   - current: h2; back: h1; do not close any <section>
 			//   - current: h1; back: h2; close two <section> (first the <h2>, then the <h1>, so a new <h1> can come)
 			while (!headerLevels.empty() && level <= headerLevels.top().first) {
+				// Output the tag only if it corresponds to a legit section.
 				int stackLevel = headerLevels.top().first;
-				docstring stackTag = from_utf8("</" + headerLevels.top().second + ">");
+				if (stackLevel != Layout::NOT_IN_TOC) {
+					xs << xml::EndTag(headerLevels.top().second);
+					xs << xml::CR();
+				}
 				headerLevels.pop();
-
-				// Output the tag only if it corresponds to a legit section.
-				if (stackLevel != Layout::NOT_IN_TOC)
-					xs << XMLStream::ESCAPE_NONE << stackTag << xml::CR();
 			}
 
 			// Open the new section: first push it onto the stack, then output it in DocBook.
@@ -1109,11 +1109,10 @@ void docbookParagraphs(Text const &text,
 				}
 
 				// Write the open tag for this section.
-				docstring tag = from_utf8("<" + sectionTag);
+				docstring attrs;
 				if (!id.empty())
-					tag += from_utf8(" ") + id;
-				tag += from_utf8(">");
-				xs << XMLStream::ESCAPE_NONE << tag;
+					attrs = id;
+				xs << xml::StartTag(sectionTag, attrs);
 				xs << xml::CR();
 			}
 		}

commit a36ebdd3940a69f8dad26fa65b8cc6977624cb4b
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sun Aug 30 00:35:47 2020 +0200

    DocBook: streamline code to handle abstracts.

diff --git a/autotests/export/docbook/basic_book.xml b/autotests/export/docbook/basic_book.xml
index c94d2fa..18496b9 100644
--- a/autotests/export/docbook/basic_book.xml
+++ b/autotests/export/docbook/basic_book.xml
@@ -1,12 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- This DocBook file was created by LyX 2.4.0dev
   See http://www.lyx.org/ for more information -->
-<book 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.1">
-
-<info><title>Book title</title>
-<author><personname>Book author</personname></author>
-
-<abstract><para>Book abstract in info. </para>
+<book 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">
+<info>
+<title>Book title</title>
+<author>
+<personname>Book author</personname>
+</author>
+<abstract>
+<para>Book abstract in info. </para>
 </abstract>
 </info>
 <chapter>
@@ -15,9 +17,7 @@
 </chapter>
 <part>
 <title>First part</title>
-
-<partintro><para>Part intro. </para>
-</partintro>
+<para>Part intro. </para>
 <chapter>
 <title>First chapter of first part</title>
 <para>Paragraph. </para>
@@ -29,9 +29,7 @@
 </part>
 <part>
 <title>Second part</title>
-
-<partintro><para>Part 2 intro. </para>
-</partintro>
+<para>Part 2 intro. </para>
 <chapter>
 <title>First chapter of second part</title>
 <para>Paragraph. </para>
@@ -41,5 +39,4 @@
 <para>Paragraph. </para>
 </chapter>
 </part>
-
 </book>
\ No newline at end of file
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index 419de20..375babb 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -771,21 +771,28 @@ ParagraphList::const_iterator makeAny(Text const &text,
 }
 
 
+bool isLayoutSectioning(Layout const & lay)
+{
+	return lay.category() == from_utf8("Sectioning");
+}
+
+
 using DocBookDocumentSectioning = tuple<bool, pit_type>;
 
 
 struct DocBookInfoTag
 {
 	const set<pit_type> shouldBeInInfo;
-	const set<pit_type> mustBeInInfo;
+	const set<pit_type> mustBeInInfo; // With the notable exception of the abstract!
 	const set<pit_type> abstract;
+	const bool abstractLayout;
 	pit_type bpit;
 	pit_type epit;
 
 	DocBookInfoTag(const set<pit_type> & shouldBeInInfo, const set<pit_type> & mustBeInInfo,
-				   const set<pit_type> & abstract, pit_type bpit, pit_type epit) :
+				   const set<pit_type> & abstract, bool abstractLayout, pit_type bpit, pit_type epit) :
 				   shouldBeInInfo(shouldBeInInfo), mustBeInInfo(mustBeInInfo), abstract(abstract),
-				   bpit(bpit), epit(epit) {}
+				   abstractLayout(abstractLayout), bpit(bpit), epit(epit) {}
 };
 
 
@@ -794,7 +801,7 @@ DocBookDocumentSectioning hasDocumentSectioning(ParagraphList const &paragraphs,
 
 	while (bpit < epit) {
 		Layout const &style = paragraphs[bpit].layout();
-		documentHasSections |= style.category() == from_utf8("Sectioning");
+		documentHasSections |= isLayoutSectioning(style);
 
 		if (documentHasSections)
 			break;
@@ -818,10 +825,14 @@ bool hasOnlyNotes(Paragraph const & par)
 }
 
 
-DocBookInfoTag getParagraphsWithInfo(ParagraphList const &paragraphs, pit_type bpit, pit_type const epit) {
+DocBookInfoTag getParagraphsWithInfo(ParagraphList const &paragraphs,
+									 pit_type bpit, pit_type const epit,
+									 // Typically, bpit is the beginning of the document and epit the end *or* the first section.
+									 bool documentHasSections) {
 	set<pit_type> shouldBeInInfo;
 	set<pit_type> mustBeInInfo;
-	set<pit_type> abstract;
+	set<pit_type> abstractWithLayout;
+	set<pit_type> abstractNoLayout;
 
 	// Find the first non empty paragraph by mutating bpit.
 	while (bpit < epit) {
@@ -832,78 +843,48 @@ DocBookInfoTag getParagraphsWithInfo(ParagraphList const &paragraphs, pit_type b
 			break;
 	}
 
-	// Find the last info-like paragraph.
-	pit_type cpit = bpit;
+	// Traverse everything that might belong to <info>.
 	bool hasAbstractLayout = false;
-	while (cpit < epit) {
-		// Skip paragraphs only containing one note.
+	pit_type cpit = bpit;
+	for (; cpit < epit; ++cpit) {
+		// Skip paragraphs that don't generate anything in DocBook.
 		Paragraph const & par = paragraphs[cpit];
-		if (hasOnlyNotes(par)) {
-			cpit += 1;
+		if (par.empty() || par.emptyTag() || hasOnlyNotes(par))
 			continue;
+
+		// There should never be any section here. (Just a sanity check: if this fails, this function could end up
+		// processing the whole document.)
+		if (isLayoutSectioning(par.layout())) {
+			LYXERR0("Assertion failed: section found in potential <info> paragraphs.");
+			break;
 		}
 
-		if (par.layout().docbookabstract())
+		// If this is marked as an abstract by the layout, put it in the right set.
+		if (par.layout().docbookabstract()) {
 			hasAbstractLayout = true;
+			abstractWithLayout.emplace(cpit);
+			continue;
+		}
 
-		// Based on layout information, store this paragraph in one set: should be in <info>, must be.
+		// Based on layout information, store this paragraph in one set: should be in <info>, must be,
+		// or abstract ().
 		Layout const &style = par.layout();
 
-		if (style.docbookininfo() == "always") {
+		if (style.docbookininfo() == "always")
 			mustBeInInfo.emplace(cpit);
-		} else if (style.docbookininfo() == "maybe") {
+		else if (style.docbookininfo() == "maybe")
 			shouldBeInInfo.emplace(cpit);
-		} else {
-			// Hypothesis: the <info> parts should be grouped together near the beginning bpit.
-			// There may be notes in between, but nothing else.
+		else if (!hasAbstractLayout)
+			abstractNoLayout.emplace(cpit);
+		else // This should definitely not be in <info>.
 			break;
-		}
-		cpit += 1;
 	}
-	// Now, cpit points to the last paragraph that has things that could go in <info>.
+	// Now, cpit points to the first paragraph that no more has things that could go in <info>.
 	// bpit is the beginning of the <info> part.
 
-	// Go once again through the list of paragraphs to find the abstract. If there is an abstract
-	// layout, only consider it. Otherwise, an abstract is just a sequence of paragraphs with text.
-	if (hasAbstractLayout) {
-		pit_type pit = bpit;
-		while (pit < cpit) { // Don't overshoot the <info> part.
-			if (paragraphs[pit].layout().docbookabstract())
-				abstract.emplace(pit);
-			pit++;
-		}
-	} else {
-		pit_type lastAbstract = epit + 1; // A nonsensical value.
-		docstring lastAbstractLayout;
-
-		pit_type pit = bpit;
-		while (pit < cpit) { // Don't overshoot the <info> part.
-			const Paragraph & par = paragraphs.at(pit);
-			if (!par.insetList().empty()) {
-				for (const auto &i : par.insetList()) {
-					if (i.inset->getText(0) != nullptr) {
-						if (lastAbstract == epit + 1) {
-							// First paragraph that matches the heuristic definition of abstract.
-							lastAbstract = pit;
-							lastAbstractLayout = par.layout().name();
-						} else if (pit > lastAbstract + 1 || par.layout().name() != lastAbstractLayout) {
-							// This is either too far from the last abstract paragraph or doesn't
-							// have the right layout name, BUT there has already been an abstract
-							// in this document: done with detecting the abstract.
-							goto done; // Easier to get out of two nested loops.
-						}
-
-						abstract.emplace(pit);
-						break;
-					}
-				}
-			}
-			pit++;
-		}
-	}
-
-	done:
-	return DocBookInfoTag(shouldBeInInfo, mustBeInInfo, abstract, bpit, cpit);
+	return DocBookInfoTag(shouldBeInInfo, mustBeInInfo,
+					      hasAbstractLayout ? abstractWithLayout : abstractNoLayout,
+					      hasAbstractLayout, bpit, cpit);
 }
 
 } // end anonymous namespace
@@ -938,17 +919,9 @@ void outputDocBookInfo(
 	if (hasAbstract) {
 		// Generate the abstract XML into a string before further checks.
 		odocstringstream os2;
-		{
-			XMLStream xs2(os2);
-			auto bpit = *std::min_element(info.abstract.begin(), info.abstract.end());
-			auto epit = 1 + *std::max_element(info.abstract.begin(), info.abstract.end());
-			// info.abstract is inclusive, epit is exclusive, hence +1 for looping.
-
-			while (bpit < epit) {
-				makeAny(text, buf, xs2, runparams, paragraphs.iterator_at(bpit));
-				bpit += 1;
-			}
-		}
+		XMLStream xs2(os2);
+		for (auto const & p : info.abstract)
+			makeAny(text, buf, xs2, runparams, paragraphs.iterator_at(p));
 
 		// Actually output the abstract if there is something to do. Don't count line feeds or spaces in this,
 		// even though they must be properly output if there is some abstract.
@@ -972,27 +945,33 @@ void outputDocBookInfo(
 	}
 
 	// Output the elements that should go in <info>, before and after the abstract.
-	for (auto pit : info.shouldBeInInfo) { // Typically, the title: these elements are so important and ubiquitous
+	for (auto pit : info.shouldBeInInfo) // Typically, the title: these elements are so important and ubiquitous
 		// that mandating a wrapper like <info> would repel users. Thus, generate them first.
 		makeAny(text, buf, xs, runparams, paragraphs.iterator_at(pit));
-	}
-	for (auto pit : info.mustBeInInfo) {
+	for (auto pit : info.mustBeInInfo)
 		if (info.abstract.find(pit) == info.abstract.end()) // The abstract must be in info, but is dealt with after.
 			makeAny(text, buf, xs, runparams, paragraphs.iterator_at(pit));
-	}
 
 	// Always output the abstract as the last item of the <info>, as it requires special treatment (especially if
 	// it contains several paragraphs that are empty).
 	if (hasAbstract) {
-//		string tag = paragraphs[*info.abstract.begin()].layout().docbookforceabstracttag();
-//		if (tag == "NONE")
-//			tag = "abstract";
-//
-//		xs << xml::StartTag(tag);
-//		xs << xml::CR();
-		xs << XMLStream::ESCAPE_NONE << abstract;
-//		xs << xml::EndTag(tag);
-//		xs << xml::CR();
+		if (info.abstractLayout) {
+			xs << XMLStream::ESCAPE_NONE << abstract;
+			xs << xml::CR();
+		} else {
+			string tag = paragraphs[*info.abstract.begin()].layout().docbookforceabstracttag();
+			if (tag == "NONE")
+				tag = "abstract";
+
+			if (!xs.isLastTagCR())
+				xs << xml::CR();
+
+			xs << xml::StartTag(tag);
+			xs << xml::CR();
+			xs << XMLStream::ESCAPE_NONE << abstract;
+			xs << xml::EndTag(tag);
+			xs << xml::CR();
+		}
 	}
 
 	// End the <info> tag if it was started.
@@ -1004,23 +983,6 @@ void outputDocBookInfo(
 }
 
 
-void docbookFirstParagraphs(
-		Text const &text,
-		Buffer const &buf,
-		XMLStream &xs,
-		OutputParams const &runparams,
-		pit_type epit)
-{
-	// Handle the beginning of the document, supposing it has sections.
-	// Major role: output the first <info> tag.
-
-	ParagraphList const &paragraphs = text.paragraphs();
-	pit_type bpit = runparams.par_begin;
-	DocBookInfoTag info = getParagraphsWithInfo(paragraphs, bpit, epit);
-	outputDocBookInfo(text, buf, xs, runparams, paragraphs, info);
-}
-
-
 void docbookSimpleAllParagraphs(
 		Text const & text,
 		Buffer const & buf,
@@ -1034,7 +996,7 @@ void docbookSimpleAllParagraphs(
 	ParagraphList const &paragraphs = text.paragraphs();
 	pit_type bpit = runparams.par_begin;
 	pit_type const epit = runparams.par_end;
-	DocBookInfoTag info = getParagraphsWithInfo(paragraphs, bpit, epit);
+	DocBookInfoTag info = getParagraphsWithInfo(paragraphs, bpit, epit, false);
 	outputDocBookInfo(text, buf, xs, runparams, paragraphs, info);
 
 	// Then, the content. It starts where the <info> ends.
@@ -1069,20 +1031,24 @@ void docbookParagraphs(Text const &text,
 	std::stack<std::pair<int, string>> headerLevels; // Used to determine when to open/close sections: store the depth
 	// of the section and the tag that was used to open it.
 
-	// Detect whether the document contains sections. If there are no sections, there can be no automatically
-	// discovered abstract.
+	// Detect whether the document contains sections. If there are no sections, treatment is largely simplified.
+	// In particular, there can't be an abstract, unless it is manually marked.
 	bool documentHasSections;
 	pit_type eppit;
 	tie(documentHasSections, eppit) = hasDocumentSectioning(paragraphs, bpit, epit);
 
-	if (documentHasSections) {
-		docbookFirstParagraphs(text, buf, xs, runparams, eppit);
-		bpit = eppit;
-	} else {
+	// Deal with "simple" documents, i.e. those without sections.
+	if (!documentHasSections){
 		docbookSimpleAllParagraphs(text, buf, xs, runparams);
 		return;
 	}
 
+	// Output the first <info> tag (or just the title).
+	DocBookInfoTag info = getParagraphsWithInfo(paragraphs, bpit, eppit, true);
+	outputDocBookInfo(text, buf, xs, runparams, paragraphs, info);
+	bpit = eppit;
+
+	// Then, iterate through the paragraphs of this document.
 	bool currentlyInAppendix = false;
 
 	auto par = text.paragraphs().iterator_at(bpit);
@@ -1100,8 +1066,7 @@ void docbookParagraphs(Text const &text,
 		Layout const &style = par->layout();
 
 		// Think about adding <section> and/or </section>s.
-		const bool isLayoutSectioning = style.category() == from_utf8("Sectioning");
-		if (isLayoutSectioning) {
+		if (isLayoutSectioning(style)) {
 			int level = style.toclevel;
 
 			// Need to close a previous section if it has the same level or a higher one (close <section> if opening a <h2>

commit 932bb3fc61419dffa8e25254ebd94e791dca28d5
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sun Aug 30 00:30:44 2020 +0200

    Fix warning.

diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index ea9180b..419de20 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -444,7 +444,7 @@ void makeParagraph(
 			special_case = true;
 	}
 
-	int nInsets = std::distance(par->insetList().begin(), par->insetList().end());
+	size_t nInsets = std::distance(par->insetList().begin(), par->insetList().end());
 
 	// Plain layouts must be ignored.
 	special_case |= buf.params().documentClass().isPlainLayout(par->layout()) && !runparams.docbook_force_pars;

commit a2ed7d2ce7eeeda4acb6af231242fd4e3f5f019b
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 23:41:28 2020 +0200

    DocBook: fix handling of index end-of-range.

diff --git a/autotests/export/docbook/basic.xml b/autotests/export/docbook/basic.xml
index a4dc276..ea91d3d 100644
--- a/autotests/export/docbook/basic.xml
+++ b/autotests/export/docbook/basic.xml
@@ -205,9 +205,9 @@ I am a second line of code.
 <para>Then several terms for the first index: <indexterm type="idx"><primary>Term</primary><secondary>to</secondary><tertiary>index</tertiary></indexterm>. </para>
 <para>With a see: <indexterm type="idx"><primary>Term</primary><see>index</see></indexterm>. With a see also: <indexterm type="idx"><primary>Term</primary><seealso>index</seealso></indexterm>. </para>
 <para>Several terms with a see: <indexterm type="idx"><primary>Term</primary><secondary>to</secondary><tertiary>index</tertiary><see>index</see></indexterm>. Several terms with a see also: <indexterm type="idx"><primary>Term</primary><secondary>to</secondary><tertiary>index</tertiary><seealso>index</seealso></indexterm>. </para>
-<para>A start of range: <indexterm type="idx" class="startofrange" xml:id="Term-to-index"><primary>Term to index</primary></indexterm>. The corresponding end of range: <indexterm type="idx" class="endofrange" startref="Term-to-index"><primary>Term to index</primary></indexterm>.</para>
-<para>Several terms with a start of range: <indexterm type="idx" class="startofrange" xml:id="Term.to.index"><primary>Term</primary><secondary>to</secondary><tertiary>index</tertiary></indexterm>. The corresponding end of range: <indexterm type="idx" class="endofrange" startref="Term.to.index"><primary>Term</primary><secondary>to</secondary><tertiary>index</tertiary></indexterm>.</para>
-<para>These terms already appeared before! Start of range: <indexterm type="idx" class="startofrange" xml:id="Term.to.index-0"><primary>Term</primary><secondary>to</secondary><tertiary>index</tertiary></indexterm>. The corresponding end of range: <indexterm type="idx" class="endofrange" startref="Term.to.index-0"><primary>Term</primary><secondary>to</secondary><tertiary>index</tertiary></indexterm>.</para>
+<para>A start of range: <indexterm type="idx" class="startofrange" xml:id="Term-to-index"><primary>Term to index</primary></indexterm>. The corresponding end of range: <indexterm class="endofrange" startref="Term-to-index" />.</para>
+<para>Several terms with a start of range: <indexterm type="idx" class="startofrange" xml:id="Term.to.index"><primary>Term</primary><secondary>to</secondary><tertiary>index</tertiary></indexterm>. The corresponding end of range: <indexterm class="endofrange" startref="Term.to.index" />.</para>
+<para>These terms already appeared before! Start of range: <indexterm type="idx" class="startofrange" xml:id="Term.to.index-0"><primary>Term</primary><secondary>to</secondary><tertiary>index</tertiary></indexterm>. The corresponding end of range: <indexterm class="endofrange" startref="Term.to.index-0" />.</para>
 </section>
 <section>
 <title>I am the eight section and I deal with star sections</title>
diff --git a/src/insets/InsetIndex.cpp b/src/insets/InsetIndex.cpp
index 987c138..149ef65 100644
--- a/src/insets/InsetIndex.cpp
+++ b/src/insets/InsetIndex.cpp
@@ -287,14 +287,17 @@ void InsetIndex::docbook(XMLStream & xs, OutputParams const & runparams) const
 		// Hence the thread-local storage, as the numbers must strictly be unique, and thus cannot be shared across
 		// a paragraph (making the solution used for HTML worthless). This solution is very similar to the one used in
 		// xml::cleanID.
-		docstring attrs = indexType;
-		if (hasStartRange || hasEndRange) {
+		// indexType can only be used for singular and startofrange types!
+		docstring attrs;
+		if (!hasStartRange && !hasEndRange) {
+			attrs = indexType;
+		} else {
 			// Append an ID if uniqueness is not guaranteed across the document.
 			static QThreadStorage<set<docstring>> tKnownTermLists;
 			static QThreadStorage<int> tID;
 
-			set<docstring> & knownTermLists = tKnownTermLists.localData();
-			int & ID = tID.localData();
+			set<docstring> &knownTermLists = tKnownTermLists.localData();
+			int &ID = tID.localData();
 
 			if (!tID.hasLocalData()) {
 				tID.localData() = 0;
@@ -319,47 +322,51 @@ void InsetIndex::docbook(XMLStream & xs, OutputParams const & runparams) const
 			// Generate the attributes.
 			docstring id = xml::cleanID(newIndexTerms);
 			if (hasStartRange) {
-				attrs += " class=\"startofrange\" xml:id=\"" + id + "\"";
+				attrs = indexType + " class=\"startofrange\" xml:id=\"" + id + "\"";
 			} else {
-				attrs += " class=\"endofrange\" startref=\"" + id + "\"";
+				attrs = " class=\"endofrange\" startref=\"" + id + "\"";
 			}
 		}
 
 		// Handle the index terms (including the specific index for this entry).
-		xs << xml::StartTag("indexterm", attrs);
-		if (terms.size() > 0) { // hasEndRange has no content.
-			xs << xml::StartTag("primary");
-			xs << terms[0];
-			xs << xml::EndTag("primary");
-		}
-		if (terms.size() > 1) {
-			xs << xml::StartTag("secondary");
-			xs << terms[1];
-			xs << xml::EndTag("secondary");
-		}
-		if (terms.size() > 2) {
-			xs << xml::StartTag("tertiary");
-			xs << terms[2];
-			xs << xml::EndTag("tertiary");
-		}
+		if (hasEndRange) {
+			xs << xml::CompTag("indexterm", attrs);
+		} else {
+			xs << xml::StartTag("indexterm", attrs);
+			if (!terms.empty()) { // hasEndRange has no content.
+				xs << xml::StartTag("primary");
+				xs << terms[0];
+				xs << xml::EndTag("primary");
+			}
+			if (terms.size() > 1) {
+				xs << xml::StartTag("secondary");
+				xs << terms[1];
+				xs << xml::EndTag("secondary");
+			}
+			if (terms.size() > 2) {
+				xs << xml::StartTag("tertiary");
+				xs << terms[2];
+				xs << xml::EndTag("tertiary");
+			}
 
-		// Handle see and see also.
-		if (!see.empty()) {
-			xs << xml::StartTag("see");
-			xs << see;
-			xs << xml::EndTag("see");
-		}
+			// Handle see and see also.
+			if (!see.empty()) {
+				xs << xml::StartTag("see");
+				xs << see;
+				xs << xml::EndTag("see");
+			}
 
-		if (!seeAlsoes.empty()) {
-			for (auto & entry : seeAlsoes) {
-				xs << xml::StartTag("seealso");
-				xs << entry;
-				xs << xml::EndTag("seealso");
+			if (!seeAlsoes.empty()) {
+				for (auto &entry : seeAlsoes) {
+					xs << xml::StartTag("seealso");
+					xs << entry;
+					xs << xml::EndTag("seealso");
+				}
 			}
-		}
 
-		// Close the entry.
-		xs << xml::EndTag("indexterm");
+			// Close the entry.
+			xs << xml::EndTag("indexterm");
+		}
 	}
 }
 
diff --git a/src/xml.cpp b/src/xml.cpp
index 0daa9d8..557bb01 100644
--- a/src/xml.cpp
+++ b/src/xml.cpp
@@ -140,11 +140,11 @@ docstring EndTag::writeEndTag() const
 
 docstring CompTag::writeTag() const
 {
-	docstring output = '<' + from_utf8(tag_);
+	docstring output = '<' + tag_;
 	if (!attr_.empty()) {
 		// Erase the beginning of the attributes if it contains space characters: this function deals with that
 		// automatically.
-		docstring attributes = escapeString(from_utf8(attr_), XMLStream::ESCAPE_NONE);
+		docstring attributes = escapeString(attr_, XMLStream::ESCAPE_NONE);
 		attributes.erase(attributes.begin(), std::find_if(attributes.begin(), attributes.end(),
                                                           [](int c) {return !std::isspace(c);}));
 		if (!attributes.empty()) {
diff --git a/src/xml.h b/src/xml.h
index bbf5b58..ebb8b8e 100644
--- a/src/xml.h
+++ b/src/xml.h
@@ -242,16 +242,19 @@ struct CompTag
 {
 	///
 	explicit CompTag(std::string const & tag)
-			: tag_(tag) {}
+			: tag_(from_utf8(tag)) {}
 	///
 	explicit CompTag(std::string const & tag, std::string const & attr)
-			: tag_(tag), attr_(attr) {}
+			: tag_(from_utf8(tag)), attr_(from_utf8(attr)) {}
+	///
+	explicit CompTag(std::string const & tag, docstring const & attr)
+			: tag_(from_utf8(tag)), attr_(attr) {}
 	/// <tag_ attr_ />
 	docstring writeTag() const;
 	///
-	std::string tag_;
+	docstring tag_;
 	///
-	std::string attr_;
+	docstring attr_;
 };
 
 

commit 2d02d355c16dfb69e58d81019404e88b7085f1fb
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 22:58:23 2020 +0200

    DocBook: fix float tags (was unduly overridden).
    
    The output was not valid for floats without title.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 62eff71..3dbf98b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,6 +6,11 @@
 
 cmake_minimum_required(VERSION 3.1.0)
 
+set(CMAKE_CXX_STANDARD 20)
+set(GNUWIN32_DIR D:/LyX/lyx-unstable/lyx-windows-deps-msvc2017)
+set(LYX_USE_QT "QT5")
+set(LYX_REQUIRE_SPELLCHECK true)
+
 set(LYX_PROJECT LyX)
 
 # Instruct cmake to not use gnu extensions,
diff --git a/autotests/export/docbook/basic.xml b/autotests/export/docbook/basic.xml
index 430611e..a4dc276 100644
--- a/autotests/export/docbook/basic.xml
+++ b/autotests/export/docbook/basic.xml
@@ -164,7 +164,7 @@ I am a second line of code.
 </tr>
 </tbody>
 </table>
-<table>
+<informaltable>
 <tbody>
 <tr>
 <td align='center' valign='top'>Table that has no caption 1</td>
@@ -182,7 +182,7 @@ I am a second line of code.
 <td align='center' valign='top'>Col 3, row 2</td>
 </tr>
 </tbody>
-</table>
+</informaltable>
 
 <para>Then, one figure: </para>
 <figure>
diff --git a/lib/layouts/stdfloats.inc b/lib/layouts/stdfloats.inc
index cd6614a..044fcb2 100644
--- a/lib/layouts/stdfloats.inc
+++ b/lib/layouts/stdfloats.inc
@@ -20,7 +20,6 @@ Float
 	UsesFloatPkg          false
 	ListCommand           listoftables
 	RefPrefix             tab
-	DocBookTag            table
 End
 
 
@@ -36,7 +35,6 @@ Float
 	UsesFloatPkg          false
 	ListCommand           listoffigures
 	RefPrefix             fig
-	DocBookTag            figure
 End
 
 
@@ -51,7 +49,6 @@ Float
 	IsPredefined          false
 	UsesFloatPkg          true
 	RefPrefix             alg
-	DocBookTag            figure # TODO: No DocBook tag really corresponds...
 End
 
 
diff --git a/src/Floating.cpp b/src/Floating.cpp
index d44afc3..19fbf5f 100644
--- a/src/Floating.cpp
+++ b/src/Floating.cpp
@@ -40,8 +40,7 @@ Floating::Floating(string const & type, string const & placement,
 	  usesfloatpkg_(usesfloat), ispredefined_(ispredefined),
 	  allowswide_(allowswide), allowssideways_(allowssideways),
 	  html_tag_(htmlTag), html_attrib_(htmlAttrib), html_style_(htmlStyle),
-	  docbook_tag_(docbookTag), docbook_attr_(docbookAttr),
-	  docbook_tag_type_(docbookTagType)
+	  docbook_attr_(docbookAttr), docbook_tag_type_(docbookTagType)
 {}
 
 
@@ -89,21 +88,17 @@ string const & Floating::docbookAttr() const
 }
 
 
-string const & Floating::docbookTag(bool hasTitle) const
+string Floating::docbookTag(bool hasTitle) const
 {
-	if (docbook_tag_.empty()) {
-		docbook_tag_ = "";
-		if (floattype_ == "figure") {
-			docbook_tag_ = hasTitle ? "figure" : "informalfigure";
-		} else if (floattype_ == "table") {
-			docbook_tag_ = hasTitle ? "table" : "informaltable";
-		} else if (floattype_ == "algorithm") {
-			// TODO: no good translation for now! Figures are the closest match, as they can contain text.
-			// Solvable as soon as https://github.com/docbook/docbook/issues/157 has a definitive answer.
-			docbook_tag_ = "figure";
-		}
+	if (floattype_ == "figure") {
+		return hasTitle ? "figure" : "informalfigure";
+	} else if (floattype_ == "table") {
+		return hasTitle ? "table" : "informaltable";
+	} else if (floattype_ == "algorithm") {
+		// TODO: no good translation for now! Figures are the closest match, as they can contain text.
+		// Solvable as soon as https://github.com/docbook/docbook/issues/157 has a definitive answer.
+		return "figure";
 	}
-	return docbook_tag_;
 }
 
 
diff --git a/src/Floating.h b/src/Floating.h
index 5cfea08..977958b 100644
--- a/src/Floating.h
+++ b/src/Floating.h
@@ -81,7 +81,7 @@ public:
 	/// tag type, defaults to "div"
 	std::string const & htmlTag() const;
 	///
-	std::string const & docbookTag(bool hasTitle = false) const;
+	std::string docbookTag(bool hasTitle = false) const;
 	///
 	std::string const & docbookAttr() const;
 	///
@@ -129,8 +129,8 @@ private:
 	mutable std::string defaultcssclass_;
 	///
 	docstring html_style_;
-	/// DocBook tag
-	mutable std::string docbook_tag_;
+	// There is no way to override the DocBook tag based on the layouts: half of it is determined by whether the float
+	// has a title or not, an information that is not available in the layouts.
 	/// attribute (mostly, role)
 	mutable std::string docbook_caption_;
 	/// caption tag (mostly, either caption or title)
diff --git a/src/insets/InsetFloat.cpp b/src/insets/InsetFloat.cpp
index b0a48f2..8914cfe 100644
--- a/src/insets/InsetFloat.cpp
+++ b/src/insets/InsetFloat.cpp
@@ -654,7 +654,7 @@ void docbookNoSubfigures(XMLStream & xs, OutputParams const & runparams, const I
 
 	xs << xml::StartTag(ftype.docbookTag(caption != nullptr), attr);
 	xs << xml::CR();
-	if (caption != nullptr) {
+	if (caption) {
 		xs << xml::StartTag(titleTag);
 		caption->getCaptionAsDocBook(xs, rpNoLabel);
 		xs << xml::EndTag(titleTag);
diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp
index 35c8a36..e8dc3af 100644
--- a/src/mathed/InsetMathHull.cpp
+++ b/src/mathed/InsetMathHull.cpp
@@ -2419,7 +2419,7 @@ void InsetMathHull::docbook(XMLStream & xs, OutputParams const & runparams) cons
 	}
 
 	// DocBook also has <equation>, but it comes with a title.
-	// TODO: recognise \tag from amsmath?
+	// TODO: recognise \tag from amsmath? This would allow having <equation> with a proper title.
 
 	docstring attr;
 	for (row_type i = 0; i < nrows(); ++i) {

commit 79950e1824899b711007f32764d21cb803ce4391
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 19:05:59 2020 +0200

    DocBook: improve equation formatting (new lines for block equations).

diff --git a/autotests/export/docbook/basic.lyx b/autotests/export/docbook/basic.lyx
index 1735dc4..fa98d65 100644
--- a/autotests/export/docbook/basic.lyx
+++ b/autotests/export/docbook/basic.lyx
@@ -185,7 +185,7 @@ noprefix "false"
 
 \begin_layout Standard
 Also, a formula with an user-defined macro that outputs well in LaTeX but
- cannot in MathML (hence replaced by picture): 
+ cannot in MathML: 
 \begin_inset Formula $\testmacro$
 \end_inset
 
diff --git a/autotests/export/docbook/basic.xml b/autotests/export/docbook/basic.xml
index 7980289..430611e 100644
--- a/autotests/export/docbook/basic.xml
+++ b/autotests/export/docbook/basic.xml
@@ -30,7 +30,7 @@
 </inlineequation>. </para>
 </blockquote>
 <para>Now, we're outside quotes.</para>
-<para><informalequation>
+<informalequation>
 <alt role='tex'>Formula!</alt>
  <m:math>
  
@@ -39,7 +39,8 @@
   </m:mrow>
  </m:mrow>
  </m:math>
-</informalequation><informalequation xml:id="eq.EQ.">
+</informalequation>
+<informalequation xml:id="eq.EQ.">
 <alt role='tex'>\text{I am a formula with a ref.}\label{eq:EQ.}</alt>
  <m:math>
  
@@ -50,9 +51,9 @@
   </m:mstyle>
  </m:mrow>
  </m:math>
-</informalequation></para>
+</informalequation>
 <para>See <xref linkend="sec.Sec-2kqgsdiflhqsdlifgjuzer-povtuizmvnuer-t-vmsrmfli--uh--a--rtpfuo----rtpc.m-ca-rgifzapeu-tvgz" />.</para>
-<para>Also, a formula with an user-defined macro that outputs well in LaTeX but cannot in MathML (hence replaced by picture): <inlineequation>
+<para>Also, a formula with an user-defined macro that outputs well in LaTeX but cannot in MathML: <inlineequation>
 <alt role='tex'>\testmacro</alt>
 <mathphrase>MathML export failed. Please report this as a bug.</mathphrase>
 </inlineequation>. </para>
diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index 5ee6171..91c8bf3 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -3336,7 +3336,8 @@ std::vector<docstring> Paragraph::simpleDocBookOnePar(Buffer const & buf,
 
 	std::vector<docstring> generatedParagraphs;
 	odocstringstream os;
-	auto * xs = new XMLStream(os);
+	auto * xs = new XMLStream(os); // XMLStream has no copy constructor: to create a new object, the only solution
+	// is to hold a pointer to the XMLStream (xs = XMLStream(os) is not allowed once the first object is built).
 
 	// Parsing main loop.
 	for (pos_type i = initial; i < size(); ++i) {
@@ -3348,7 +3349,6 @@ std::vector<docstring> Paragraph::simpleDocBookOnePar(Buffer const & buf,
 		if (getInset(i) != nullptr && getInset(i)->lyxCode() == NEWLINE_CODE) {
 			generatedParagraphs.push_back(os.str());
 			os = odocstringstream();
-			// XMLStream has no copy constructor.
 			delete xs;
 			xs = new XMLStream(os);
 		}
diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp
index 2cecba9..35c8a36 100644
--- a/src/mathed/InsetMathHull.cpp
+++ b/src/mathed/InsetMathHull.cpp
@@ -2410,10 +2410,16 @@ void InsetMathHull::docbook(XMLStream & xs, OutputParams const & runparams) cons
 	docstring name;
 	if (getType() == hullSimple)
 		name = from_ascii("inlineequation");
-	else
+	else {
+		// This is a block equation, always have <informalequation> on its own line.
+		if (!xs.isLastTagCR())
+			xs << xml::CR();
+
 		name = from_ascii("informalequation");
+	}
 
 	// DocBook also has <equation>, but it comes with a title.
+	// TODO: recognise \tag from amsmath?
 
 	docstring attr;
 	for (row_type i = 0; i < nrows(); ++i) {
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index 6c61dc6..ea9180b 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -444,10 +444,16 @@ void makeParagraph(
 			special_case = true;
 	}
 
+	int nInsets = std::distance(par->insetList().begin(), par->insetList().end());
+
 	// Plain layouts must be ignored.
-	if (!special_case && buf.params().documentClass().isPlainLayout(par->layout()) && !runparams.docbook_force_pars)
-		special_case = true;
-	// TODO: Could get rid of this with a DocBook equivalent to htmlisblock?
+	special_case |= buf.params().documentClass().isPlainLayout(par->layout()) && !runparams.docbook_force_pars;
+	// Equations do not deserve their own paragraph (DocBook allows them outside paragraphs).
+	special_case |= nInsets == par->size() && std::all_of(par->insetList().begin(), par->insetList().end(), [](InsetList::Element inset) {
+		return inset.inset && inset.inset->asInsetMath();
+	});
+
+	// TODO: Could get rid of this with a DocBook equivalent to htmlisblock? Not for all cases, unfortunately... See above for those that have been determined not to be allowable for this potential refactoring.
 	if (!special_case && par->size() == 1 && par->getInset(0)) {
 		Inset const * firstInset = par->getInset(0);
 
@@ -458,10 +464,6 @@ void makeParagraph(
 		if (!special_case && firstInset->asInsetCommand())
 			special_case = firstInset->asInsetCommand()->params().getCmdName() == "bibtex";
 
-		// Equations do not deserve their own paragraph (DocBook allows them outside paragraphs).
-		if (!special_case && firstInset->asInsetMath())
-			special_case = true;
-
 		// ERTs are in comments, not paragraphs.
 		if (!special_case && firstInset->lyxCode() == lyx::ERT_CODE)
 			special_case = true;

commit 7189e5ae41f3c0ddc7ff305b7aee7c882f928e58
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Sat Aug 29 18:40:31 2020 +0200

    DocBook: fix indentation for section titles (including stars).

diff --git a/autotests/export/docbook/basic.lyx b/autotests/export/docbook/basic.lyx
index 0bd87ce..1735dc4 100644
--- a/autotests/export/docbook/basic.lyx
+++ b/autotests/export/docbook/basic.lyx
@@ -1,5 +1,5 @@
-#LyX 2.4 created this file. For more info see http://www.lyx.org/
-\lyxformat 544
+#LyX 2.4 created this file. For more info see https://www.lyx.org/
+\lyxformat 598
 \begin_document
 \begin_header
 \save_transient_properties true
@@ -9,11 +9,11 @@
 \newcommand{\testmacro}{\ensuremath{\operatorname{testmacro}}}
 \end_preamble
 \use_default_options true
-\maintain_unincluded_children false
+\maintain_unincluded_children no
 \language english
 \language_package default
-\inputencoding auto
-\fontencoding global
+\inputencoding auto-legacy
+\fontencoding auto
 \font_roman "default" "default"
 \font_sans "default" "default"
 \font_typewriter "default" "default"
@@ -21,7 +21,9 @@
 \font_default_family default
 \use_non_tex_fonts false
 \font_sc false
-\font_osf false
+\font_roman_osf false
+\font_sans_osf false
+\font_typewriter_osf false
 \font_sf_scale 100 100
 \font_tt_scale 100 100
 \use_microtype false
@@ -56,6 +58,7 @@
 \justification true
 \use_refstyle 1
 \use_minted 0
+\use_lineno 0
 \index Index
 \shortcut idx
 \color #008000
@@ -75,11 +78,15 @@
 \papercolumns 1
 \papersides 1
 \paperpagestyle default
+\tablestyle default
 \tracking_changes false
 \output_changes false
+\change_bars false
+\postpone_fragile_content false
 \html_math_output 0
 \html_css_as_file 0
 \html_be_strict false
+\docbook_table_output 0
 \end_header
 
 \begin_body
@@ -140,6 +147,10 @@ I am a quote
 \end_layout
 
 \begin_layout Standard
+Now, we're outside quotes.
+\end_layout
+
+\begin_layout Standard
 \begin_inset Formula 
 \[
 Formula!
@@ -386,6 +397,8 @@ Now, three tables:
 
 \begin_layout Standard
 \begin_inset Float table
+placement document
+alignment document
 wide false
 sideways false
 status open
@@ -511,6 +524,8 @@ I am a table caption below the table.
 
 \begin_layout Standard
 \begin_inset Float table
+placement document
+alignment document
 wide false
 sideways false
 status open
@@ -636,6 +651,8 @@ Col 3, row 2
 
 \begin_layout Standard
 \begin_inset Float table
+placement document
+alignment document
 wide false
 sideways false
 status open
@@ -753,6 +770,8 @@ Then, one figure:
 
 \begin_layout Standard
 \begin_inset Float figure
+placement document
+alignment document
 wide false
 sideways false
 status open
diff --git a/autotests/export/docbook/basic.xml b/autotests/export/docbook/basic.xml
index 6f4a828..7980289 100644
--- a/autotests/export/docbook/basic.xml
+++ b/autotests/export/docbook/basic.xml
@@ -29,6 +29,7 @@
  </m:math>
 </inlineequation>. </para>
 </blockquote>
+<para>Now, we're outside quotes.</para>
 <para><informalequation>
 <alt role='tex'>Formula!</alt>
  <m:math>
@@ -72,22 +73,37 @@
 </section>
 <section>
 <title>I am the third section and I have fun with lists</title>
-<orderedlist><listitem>First item. 
-<br />
-Second line of the first item, after a line break. </listitem></orderedlist>
-<orderedlist><listitem>Second item. </listitem></orderedlist>
-<itemizedlist><listitem>Item has no order (1). </listitem></itemizedlist>
-<itemizedlist><listitem>Item has no order (2). </listitem></itemizedlist>
-<variablelist><listitem><varlistentry>
-
-Word description<!-- Output Error: Closing tag `listitem' when other tags are open, namely: -->
-<!-- Output Error: varlistentry -->
-</varlistentry></listitem></variablelist>
-<variablelist><listitem><varlistentry>
-
-Sentence meaning<!-- Output Error: Closing tag `listitem' when other tags are open, namely: -->
-<!-- Output Error: varlistentry -->
-</varlistentry></listitem></variablelist>
+<orderedlist>
+<listitem>
+<para>First item. </para>
+<para>Second line of the first item, after a line break. </para>
+</listitem>
+<listitem>
+<para>Second item. </para>
+</listitem>
+</orderedlist>
+<itemizedlist>
+<listitem>
+<para>Item has no order (1). </para>
+</listitem>
+<listitem>
+<para>Item has no order (2). </para>
+</listitem>
+</itemizedlist>
+<variablelist>
+<varlistentry>
+<term>Word</term>
+<listitem>
+<para>description</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>Sentence</term>
+<listitem>
+<para>meaning</para>
+</listitem>
+</varlistentry>
+</variablelist>
 </section>
 <section>
 <title>I am the fourth section and I deal with formatting. </title>
@@ -95,9 +111,11 @@ Sentence meaning<!-- Output Error: Closing tag `listitem' when other tags are op
 <para><programlisting>I am some code. 
 I am a second line of code. 
 </programlisting>I am no more code. </para>
-<para>This line has inline code. <code>This has typewriter font</code><footnote><para>I repeat that in a footnote.</para>
+<para>This line has inline code. <code>This has typewriter font</code><footnote>
+<para>I repeat that in a footnote.</para>
 </footnote>. </para>
-<para>On the other hand, <footnote><para>this footnote</para>
+<para>On the other hand, <footnote>
+<para>this footnote</para>
 <para>has multiple </para>
 <para>paragraphs.</para>
 </footnote>. </para>
@@ -145,7 +163,7 @@ I am a second line of code.
 </tr>
 </tbody>
 </table>
-<informaltable>
+<table>
 <tbody>
 <tr>
 <td align='center' valign='top'>Table that has no caption 1</td>
@@ -163,7 +181,8 @@ I am a second line of code.
 <td align='center' valign='top'>Col 3, row 2</td>
 </tr>
 </tbody>
-</informaltable>
+</table>
+
 <para>Then, one figure: </para>
 <figure>
 <title>Caption.</title>
@@ -334,5 +353,4 @@ I am a second line of code.
 </author>
 </authorgroup>
 </biblioentry>
-</bibliography>
-</article>
\ No newline at end of file
+</bibliography></article>
\ No newline at end of file
diff --git a/lib/layouts/stdsections.inc b/lib/layouts/stdsections.inc
index fa42eac..30b64ea 100644
--- a/lib/layouts/stdsections.inc
+++ b/lib/layouts/stdsections.inc
@@ -7,7 +7,7 @@
 # commands that are useful for article-like document classes, but not
 # for letters.
 
-Format 82
+Format 84
 
 Style Part
 	Category              Sectioning
@@ -40,6 +40,7 @@ Style Part
 	EndFont
 	HTMLTag               h1
 	DocBookTag            title
+	DocBookTagType        paragraph
 	DocBookSectionTag     part
 	DocBookForceAbstractTag	partintro
 End
@@ -75,6 +76,7 @@ Style Chapter
 	EndFont
 	HTMLTag               h1
 	DocBookTag            title
+	DocBookTagType        paragraph
 	DocBookSectionTag     chapter
 End
 
@@ -108,6 +110,7 @@ Style Section
 	EndFont
 	HTMLTag               h2
 	DocBookTag            title
+	DocBookTagType        paragraph
 	DocBookSectionTag     section
 End
 

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

Summary of changes:
 CMakeLists.txt                          |    5 +
 autotests/export/docbook/basic.lyx      |   33 +++-
 autotests/export/docbook/basic.xml      |   75 ++++++---
 autotests/export/docbook/basic_book.xml |   23 ++--
 lib/layouts/stdfloats.inc               |    3 -
 lib/layouts/stdsections.inc             |    5 +-
 src/Floating.cpp                        |   25 ++--
 src/Floating.h                          |    6 +-
 src/Paragraph.cpp                       |    4 +-
 src/insets/InsetFloat.cpp               |    2 +-
 src/insets/InsetIndex.cpp               |   79 +++++-----
 src/mathed/InsetMathHull.cpp            |    8 +-
 src/output_docbook.cpp                  |  263 +++++++++++++++----------------
 src/xml.cpp                             |    4 +-
 src/xml.h                               |   11 +-
 15 files changed, 296 insertions(+), 250 deletions(-)


hooks/post-receive
-- 
Repository for new features


More information about the lyx-cvs mailing list