From 7262a9f23c1cfa4e051e712d19c6eea87c2c00b3 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Sat, 17 Jan 2015 17:31:59 -0500 Subject: [PATCH] Bug 1119503 - Part 2: Insert a line break between preformatted block boundaries when creating raw output; r=bzbarsky --- dom/base/nsCopySupport.cpp | 3 ++- dom/base/nsIDocumentEncoder.idl | 7 +++++++ dom/base/nsPlainTextSerializer.cpp | 24 ++++++++++++++++++++++++ dom/base/nsPlainTextSerializer.h | 4 +++- dom/base/test/test_bug116083.html | 8 ++++++++ 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/dom/base/nsCopySupport.cpp b/dom/base/nsCopySupport.cpp index 56ac20eb145e..3f6db3928da1 100644 --- a/dom/base/nsCopySupport.cpp +++ b/dom/base/nsCopySupport.cpp @@ -97,7 +97,8 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc, // Do the first and potentially trial encoding as preformatted and raw. uint32_t flags = aFlags | nsIDocumentEncoder::OutputPreformatted - | nsIDocumentEncoder::OutputRaw; + | nsIDocumentEncoder::OutputRaw + | nsIDocumentEncoder::OutputForPlainTextClipboardCopy; nsCOMPtr domDoc = do_QueryInterface(aDoc); NS_ASSERTION(domDoc, "Need a document"); diff --git a/dom/base/nsIDocumentEncoder.idl b/dom/base/nsIDocumentEncoder.idl index b5963bb2db89..155e5c375c6e 100644 --- a/dom/base/nsIDocumentEncoder.idl +++ b/dom/base/nsIDocumentEncoder.idl @@ -227,6 +227,13 @@ interface nsIDocumentEncoder : nsISupports */ const unsigned long OutputDontRemoveLineEndingSpaces = (1 << 24); + /** + * Serialize in a way that is suitable for copying a plaintext version of the + * document to the clipboard. This can for example cause line endings to be + * injected at preformatted block element boundaries. + */ + const unsigned long OutputForPlainTextClipboardCopy = (1 << 25); + /** * Initialize with a pointer to the document and the mime type. * @param aDocument Document to encode. diff --git a/dom/base/nsPlainTextSerializer.cpp b/dom/base/nsPlainTextSerializer.cpp index aaf5d44ee396..eb7e4b1cff43 100644 --- a/dom/base/nsPlainTextSerializer.cpp +++ b/dom/base/nsPlainTextSerializer.cpp @@ -91,6 +91,8 @@ nsPlainTextSerializer::nsPlainTextSerializer() mPreFormatted = false; mStartedOutput = false; + mPreformattedBlockBoundary = false; + // initialize the tag stack to zero: // The stack only ever contains pointers to static atoms, so they don't // need refcounting. @@ -167,6 +169,8 @@ nsPlainTextSerializer::Init(uint32_t aFlags, uint32_t aWrapColumn, mLineBreakDue = false; mFloatingLines = -1; + mPreformattedBlockBoundary = false; + if (mFlags & nsIDocumentEncoder::OutputFormatted) { // Get some prefs that controls how we do formatted output mStructs = Preferences::GetBool(PREF_STRUCTS, mStructs); @@ -437,6 +441,16 @@ nsPlainTextSerializer::DoOpenContainer(nsIAtom* aTag) return NS_OK; } + if (mFlags & nsIDocumentEncoder::OutputForPlainTextClipboardCopy) { + if (mPreformattedBlockBoundary && DoOutput()) { + // Should always end a line, but get no more whitespace + if (mFloatingLines < 0) + mFloatingLines = 0; + mLineBreakDue = true; + } + mPreformattedBlockBoundary = false; + } + if (mFlags & nsIDocumentEncoder::OutputRaw) { // Raw means raw. Don't even think about doing anything fancy // here like indenting, adding line breaks or any other @@ -767,6 +781,14 @@ nsPlainTextSerializer::DoCloseContainer(nsIAtom* aTag) return NS_OK; } + if (mFlags & nsIDocumentEncoder::OutputForPlainTextClipboardCopy) { + if (DoOutput() && IsInPre() && IsElementBlock(mElement)) { + // If we're closing a preformatted block element, output a line break + // when we find a new container. + mPreformattedBlockBoundary = true; + } + } + if (mFlags & nsIDocumentEncoder::OutputRaw) { // Raw means raw. Don't even think about doing anything fancy // here like indenting, adding line breaks or any other @@ -1036,6 +1058,8 @@ nsPlainTextSerializer::DoAddText(bool aIsLineBreak, const nsAString& aText) nsresult nsPlainTextSerializer::DoAddLeaf(nsIAtom* aTag) { + mPreformattedBlockBoundary = false; + // If we don't want any output, just return if (!DoOutput()) { return NS_OK; diff --git a/dom/base/nsPlainTextSerializer.h b/dom/base/nsPlainTextSerializer.h index ea2d049ca9ab..9535a59d9d52 100644 --- a/dom/base/nsPlainTextSerializer.h +++ b/dom/base/nsPlainTextSerializer.h @@ -170,7 +170,9 @@ private: // While handling a new tag, this variable should remind if any line break // is due because of a closing tag. Setting it to "TRUE" while closing the tags. // Hence opening tags are guaranteed to start with appropriate line breaks. - bool mLineBreakDue; + bool mLineBreakDue; + + bool mPreformattedBlockBoundary; nsString mURL; int32_t mHeaderStrategy; /* Header strategy (pref) diff --git a/dom/base/test/test_bug116083.html b/dom/base/test/test_bug116083.html index 4244a13aef69..5ac1181536e3 100644 --- a/dom/base/test/test_bug116083.html +++ b/dom/base/test/test_bug116083.html @@ -20,6 +20,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=116083
bar baz
bar baz
bar baz
+
foo
bar

!


baz
+
foo
bar

!


baz
+
foo
bar

!


baz
+
foo
bar

!


baz
+
foo
bar

!


baz
+
foo
bar

!


baz
+
foo
bar

!


baz
+
foo
bar

!


baz
foo bar