From 49a558574f29c72733c951e1bf67ec4eabd8933b Mon Sep 17 00:00:00 2001
From: Pierre-Yves Rollo <dev@pyrollo.com>
Date: Thu, 26 Mar 2020 19:56:35 +0100
Subject: [PATCH] Hypertext: Fix alignment tags adding unwanted newlines
 (#9548)

---
 src/gui/guiHyperText.cpp | 33 ++++++++++++++++++++++++---------
 src/gui/guiHyperText.h   |  6 +++++-
 2 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/src/gui/guiHyperText.cpp b/src/gui/guiHyperText.cpp
index 68fb8ea3d..482b74f04 100644
--- a/src/gui/guiHyperText.cpp
+++ b/src/gui/guiHyperText.cpp
@@ -167,6 +167,7 @@ ParsedText::ParsedText(const wchar_t *text)
 
 	m_element = NULL;
 	m_paragraph = NULL;
+	m_end_paragraph_reason = ER_NONE;
 
 	parse(text);
 }
@@ -191,7 +192,7 @@ void ParsedText::parse(const wchar_t *text)
 				cursor++;
 			// If text has begun, don't skip empty line
 			if (m_paragraph) {
-				endParagraph();
+				endParagraph(ER_NEWLINE);
 				enterElement(ELEMENT_SEPARATOR);
 			}
 			escape = false;
@@ -201,7 +202,7 @@ void ParsedText::parse(const wchar_t *text)
 		if (c == L'\n') { // Unix breaks
 			// If text has begun, don't skip empty line
 			if (m_paragraph) {
-				endParagraph();
+				endParagraph(ER_NEWLINE);
 				enterElement(ELEMENT_SEPARATOR);
 			}
 			escape = false;
@@ -232,7 +233,7 @@ void ParsedText::parse(const wchar_t *text)
 		pushChar(c);
 	}
 
-	endParagraph();
+	endParagraph(ER_NONE);
 }
 
 void ParsedText::endElement()
@@ -240,11 +241,20 @@ void ParsedText::endElement()
 	m_element = NULL;
 }
 
-void ParsedText::endParagraph()
+void ParsedText::endParagraph(EndReason reason)
 {
 	if (!m_paragraph)
 		return;
 
+	EndReason previous = m_end_paragraph_reason;
+	m_end_paragraph_reason = reason;
+	if (m_empty_paragraph && (reason == ER_TAG ||
+			(reason == ER_NEWLINE && previous == ER_TAG))) {
+		// Ignore last empty paragraph
+		m_paragraph = nullptr;
+		m_paragraphs.pop_back();
+		return;
+	}
 	endElement();
 	m_paragraph = NULL;
 }
@@ -255,6 +265,7 @@ void ParsedText::enterParagraph()
 		m_paragraphs.emplace_back();
 		m_paragraph = &m_paragraphs.back();
 		m_paragraph->setStyle(m_style);
+		m_empty_paragraph = true;
 	}
 }
 
@@ -274,11 +285,15 @@ void ParsedText::enterElement(ElementType type)
 void ParsedText::pushChar(wchar_t c)
 {
 	// New word if needed
-	if (c == L' ' || c == L'\t')
-		enterElement(ELEMENT_SEPARATOR);
-	else
+	if (c == L' ' || c == L'\t') {
+		if (!m_empty_paragraph)
+			enterElement(ELEMENT_SEPARATOR);
+		else
+			return;
+	} else {
+		m_empty_paragraph = false;
 		enterElement(ELEMENT_TEXT);
-
+	}
 	m_element->text += c;
 }
 
@@ -571,7 +586,7 @@ u32 ParsedText::parseTag(const wchar_t *text, u32 cursor)
 		} else {
 			openTag(name, attrs)->style = m_paragraphtags[name];
 		}
-		endParagraph();
+		endParagraph(ER_TAG);
 
 	} else
 		return 0; // Unknown tag
diff --git a/src/gui/guiHyperText.h b/src/gui/guiHyperText.h
index 093c84ccd..c55f8a705 100644
--- a/src/gui/guiHyperText.h
+++ b/src/gui/guiHyperText.h
@@ -134,11 +134,13 @@ public:
 	Tag m_root_tag;
 
 protected:
+	typedef enum { ER_NONE, ER_TAG, ER_NEWLINE } EndReason;
+
 	// Parser functions
 	void enterElement(ElementType type);
 	void endElement();
 	void enterParagraph();
-	void endParagraph();
+	void endParagraph(EndReason reason);
 	void pushChar(wchar_t c);
 	ParsedText::Tag *newTag(const std::string &name, const AttrsList &attrs);
 	ParsedText::Tag *openTag(const std::string &name, const AttrsList &attrs);
@@ -160,6 +162,8 @@ protected:
 	StyleList m_style;
 	Element *m_element;
 	Paragraph *m_paragraph;
+	bool m_empty_paragraph;
+	EndReason m_end_paragraph_reason;
 };
 
 class TextDrawer
-- 
2.25.1