From ad56bb7286cabddefb4d2e470b833ac1874623a3 Mon Sep 17 00:00:00 2001
From: Richard Heck <rgheck@lyx.org>
Date: Tue, 7 May 2013 01:16:14 -0400
Subject: [PATCH] Rework how paragraph ids are handled.

Previously, an empty paragraph would always yield something like:
	<div><a id='magicparid-35' /></div>
because we had no way to "defer" the anchor tag. Now this is wrapped
into the div, in effect, and we abandon it all if there's no content.
---
 src/Paragraph.cpp    |  6 -----
 src/output_xhtml.cpp | 58 +++++++++++++++++++++++++++++++++++++++++---
 src/output_xhtml.h   | 38 ++++++++++++++++++++++-------
 3 files changed, 83 insertions(+), 19 deletions(-)

diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index c7e65650e8..535506f9d4 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -2864,12 +2864,6 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf,
 
 	xs.startParagraph(allowEmpty());
 
-	if (!runparams.for_toc && runparams.html_make_pars) {
-		// generate a magic label for this paragraph
-		string const attr = "id='" + magicLabel() + "'";
-		xs << html::CompTag("a", attr);
-	}
-
 	FontInfo font_old =
 		style.labeltype == LABEL_MANUAL ? style.labelfont : style.font;
 
diff --git a/src/output_xhtml.cpp b/src/output_xhtml.cpp
index 13e5c19f00..b06f8bd5d1 100644
--- a/src/output_xhtml.cpp
+++ b/src/output_xhtml.cpp
@@ -46,7 +46,6 @@ namespace lyx {
 
 namespace html {
 
-
 docstring escapeChar(char_type c, XHTMLStream::EscapeSettings e)
 {
 	docstring str;
@@ -174,6 +173,19 @@ docstring StartTag::asEndTag() const
 }
 
 
+docstring ParTag::asTag() const
+{
+	docstring output = StartTag::asTag();
+
+	if (parid_.empty())
+		return output;
+
+	string const pattr = "id='" + parid_ + "'";
+	output += html::CompTag("a", pattr).asTag();
+	return output;
+}
+
+
 docstring EndTag::asEndTag() const
 {
 	string output = "</" + tag_ + ">";
@@ -398,6 +410,15 @@ XHTMLStream & XHTMLStream::operator<<(html::StartTag const & tag)
 }
 
 
+XHTMLStream & XHTMLStream::operator<<(html::ParTag const & tag)
+{
+	if (tag.tag_.empty())
+		return *this;
+	pending_tags_.push_back(makeTagPtr(tag));
+	return *this;
+}
+
+
 XHTMLStream & XHTMLStream::operator<<(html::CompTag const & tag) 
 {
 	if (tag.tag_.empty())
@@ -611,6 +632,28 @@ void openTag(XHTMLStream & xs, Layout const & lay,
 }
 
 
+inline void openParTag(XHTMLStream & xs, Layout const & lay,
+                       std::string parlabel)
+{
+	xs << html::ParTag(lay.htmltag(), lay.htmlattr(), parlabel);
+}
+
+
+void openParTag(XHTMLStream & xs, Layout const & lay,
+                ParagraphParameters const & params,
+                std::string parlabel)
+{
+	// FIXME Are there other things we should handle here?
+	string const align = alignmentToCSS(params.align());
+	if (align.empty()) {
+		openParTag(xs, lay, parlabel);
+		return;
+	}
+	string attrs = lay.htmlattr() + " style='text-align: " + align + ";'";
+	xs << html::ParTag(lay.htmltag(), attrs, parlabel);
+}
+
+
 inline void closeTag(XHTMLStream & xs, Layout const & lay)
 {
 	xs << html::EndTag(lay.htmltag());
@@ -721,8 +764,12 @@ ParagraphList::const_iterator makeParagraphs(Buffer const & buf,
 		// multiple paragraphs.
 		bool const opened = runparams.html_make_pars &&
 			(par != pbegin || !runparams.html_in_par);
+		bool const make_parid = !runparams.for_toc && runparams.html_make_pars;
+
 		if (opened)
-			openTag(xs, lay, par->params());
+			openParTag(xs, lay, par->params(),
+			           make_parid ? par->magicLabel() : "");
+
 		docstring const deferred = 
 			par->simpleLyXHTMLOnePar(buf, xs, runparams, text.outerFont(distance(begin, par)));
 
@@ -789,7 +836,7 @@ ParagraphList::const_iterator makeEnvironment(Buffer const & buf,
 	depth_type const origdepth = pbegin->params().depth();
 
 	// open tag for this environment
-	openTag(xs, bstyle);
+	openParTag(xs, bstyle, pbegin->magicLabel());
 	xs << html::CR();
 
 	// we will on occasion need to remember a layout from before.
@@ -930,7 +977,10 @@ void makeCommand(Buffer const & buf,
 		buf.masterBuffer()->params().
 		    documentClass().counters().step(style.counter, OutputUpdate);
 
-	openTag(xs, style, pbegin->params());
+	bool const make_parid = !runparams.for_toc && runparams.html_make_pars;
+
+	openParTag(xs, style, pbegin->params(),
+	           make_parid ? pbegin->magicLabel() : "");
 
 	// Label around sectioning number:
 	// FIXME Probably need to account for LABEL_MANUAL
diff --git a/src/output_xhtml.h b/src/output_xhtml.h
index 99d07be9d7..ceabc42dcf 100644
--- a/src/output_xhtml.h
+++ b/src/output_xhtml.h
@@ -32,17 +32,20 @@ class Text;
 namespace html {
 /// Attributes will be escaped automatically and so should NOT
 /// be escaped before being passed to the constructor.
-struct StartTag {
+struct StartTag
+{
 	///
 	explicit StartTag(std::string const & tag) : tag_(tag), keepempty_(false) {}
 	///
 	explicit StartTag(std::string const & tag, std::string const & attr, 
 		bool keepempty = false) 
 		: tag_(tag), attr_(attr), keepempty_(keepempty) {}
+	///
+	~StartTag() {}
 	/// <tag_ attr_>
-	docstring asTag() const;
+	virtual docstring asTag() const;
 	/// </tag_>
-	docstring asEndTag() const;
+	virtual docstring asEndTag() const;
 	///
 	std::string tag_;
 	///
@@ -53,7 +56,25 @@ struct StartTag {
 };
 
 
-struct EndTag {
+/// A special case of StartTag, used exclusively for tags that wrap paragraphs.
+struct ParTag : public StartTag
+{
+	///
+	ParTag(std::string const & tag, std::string const & attr,
+	       std::string const & parid)
+	  : StartTag(tag, attr), parid_(parid)
+	{}
+	///
+	~ParTag() {}
+	///
+	docstring asTag() const;
+	/// the "magic par label" for this paragraph
+	std::string parid_;
+};
+
+
+struct EndTag
+{
 	///
 	explicit EndTag(std::string tag) : tag_(tag) {}
 	/// </tag_>
@@ -63,14 +84,11 @@ struct EndTag {
 };
 
 
-// FIXME XHTML
-// We need to allow these to be deferrable, which means it should
-// inherit from StartTag. This is probably better, anyway, but we'll
-// need to re-work a bit of code....
 /// Tags like <img />
 /// Attributes will be escaped automatically and so should NOT
 /// be escaped before being passed to the constructor.
-struct CompTag {
+struct CompTag
+{
 	///
 	explicit CompTag(std::string const & tag)
 		: tag_(tag) {}
@@ -127,6 +145,8 @@ public:
 	///
 	XHTMLStream & operator<<(html::CompTag const &);
 	///
+	XHTMLStream & operator<<(html::ParTag const &);
+	///
 	XHTMLStream & operator<<(html::CR const &);
 	///
 	enum EscapeSettings {