Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | /* |
michael@0 | 7 | * nsIContentSerializer implementation that can be used with an |
michael@0 | 8 | * nsIDocumentEncoder to convert a DOM into plaintext in a nice way |
michael@0 | 9 | * (eg for copy/paste as plaintext). |
michael@0 | 10 | */ |
michael@0 | 11 | |
michael@0 | 12 | #ifndef nsPlainTextSerializer_h__ |
michael@0 | 13 | #define nsPlainTextSerializer_h__ |
michael@0 | 14 | |
michael@0 | 15 | #include "mozilla/Attributes.h" |
michael@0 | 16 | #include "nsAutoPtr.h" |
michael@0 | 17 | #include "nsCOMPtr.h" |
michael@0 | 18 | #include "nsIAtom.h" |
michael@0 | 19 | #include "nsIContentSerializer.h" |
michael@0 | 20 | #include "nsIDocumentEncoder.h" |
michael@0 | 21 | #include "nsILineBreaker.h" |
michael@0 | 22 | #include "nsString.h" |
michael@0 | 23 | #include "nsTArray.h" |
michael@0 | 24 | |
michael@0 | 25 | class nsIContent; |
michael@0 | 26 | |
michael@0 | 27 | namespace mozilla { |
michael@0 | 28 | namespace dom { |
michael@0 | 29 | class Element; |
michael@0 | 30 | } // namespace dom |
michael@0 | 31 | } // namespace mozilla |
michael@0 | 32 | |
michael@0 | 33 | class nsPlainTextSerializer : public nsIContentSerializer |
michael@0 | 34 | { |
michael@0 | 35 | public: |
michael@0 | 36 | nsPlainTextSerializer(); |
michael@0 | 37 | virtual ~nsPlainTextSerializer(); |
michael@0 | 38 | |
michael@0 | 39 | NS_DECL_ISUPPORTS |
michael@0 | 40 | |
michael@0 | 41 | // nsIContentSerializer |
michael@0 | 42 | NS_IMETHOD Init(uint32_t flags, uint32_t aWrapColumn, |
michael@0 | 43 | const char* aCharSet, bool aIsCopying, |
michael@0 | 44 | bool aIsWholeDocument) MOZ_OVERRIDE; |
michael@0 | 45 | |
michael@0 | 46 | NS_IMETHOD AppendText(nsIContent* aText, int32_t aStartOffset, |
michael@0 | 47 | int32_t aEndOffset, nsAString& aStr) MOZ_OVERRIDE; |
michael@0 | 48 | NS_IMETHOD AppendCDATASection(nsIContent* aCDATASection, |
michael@0 | 49 | int32_t aStartOffset, int32_t aEndOffset, |
michael@0 | 50 | nsAString& aStr) MOZ_OVERRIDE; |
michael@0 | 51 | NS_IMETHOD AppendProcessingInstruction(nsIContent* aPI, |
michael@0 | 52 | int32_t aStartOffset, |
michael@0 | 53 | int32_t aEndOffset, |
michael@0 | 54 | nsAString& aStr) MOZ_OVERRIDE { return NS_OK; } |
michael@0 | 55 | NS_IMETHOD AppendComment(nsIContent* aComment, int32_t aStartOffset, |
michael@0 | 56 | int32_t aEndOffset, nsAString& aStr) MOZ_OVERRIDE { return NS_OK; } |
michael@0 | 57 | NS_IMETHOD AppendDoctype(nsIContent *aDoctype, |
michael@0 | 58 | nsAString& aStr) MOZ_OVERRIDE { return NS_OK; } |
michael@0 | 59 | NS_IMETHOD AppendElementStart(mozilla::dom::Element* aElement, |
michael@0 | 60 | mozilla::dom::Element* aOriginalElement, |
michael@0 | 61 | nsAString& aStr) MOZ_OVERRIDE; |
michael@0 | 62 | NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement, |
michael@0 | 63 | nsAString& aStr) MOZ_OVERRIDE; |
michael@0 | 64 | NS_IMETHOD Flush(nsAString& aStr) MOZ_OVERRIDE; |
michael@0 | 65 | |
michael@0 | 66 | NS_IMETHOD AppendDocumentStart(nsIDocument *aDocument, |
michael@0 | 67 | nsAString& aStr) MOZ_OVERRIDE; |
michael@0 | 68 | |
michael@0 | 69 | protected: |
michael@0 | 70 | nsresult GetAttributeValue(nsIAtom* aName, nsString& aValueRet); |
michael@0 | 71 | void AddToLine(const char16_t* aStringToAdd, int32_t aLength); |
michael@0 | 72 | void EndLine(bool softlinebreak, bool aBreakBySpace = false); |
michael@0 | 73 | void EnsureVerticalSpace(int32_t noOfRows); |
michael@0 | 74 | void FlushLine(); |
michael@0 | 75 | void OutputQuotesAndIndent(bool stripTrailingSpaces=false); |
michael@0 | 76 | void Output(nsString& aString); |
michael@0 | 77 | void Write(const nsAString& aString); |
michael@0 | 78 | bool IsInPre(); |
michael@0 | 79 | bool IsInOL(); |
michael@0 | 80 | bool IsCurrentNodeConverted(); |
michael@0 | 81 | bool MustSuppressLeaf(); |
michael@0 | 82 | |
michael@0 | 83 | /** |
michael@0 | 84 | * Returns the local name of the element as an atom if the element is an |
michael@0 | 85 | * HTML element and the atom is a static atom. Otherwise, nullptr is returned. |
michael@0 | 86 | */ |
michael@0 | 87 | static nsIAtom* GetIdForContent(nsIContent* aContent); |
michael@0 | 88 | nsresult DoOpenContainer(nsIAtom* aTag); |
michael@0 | 89 | nsresult DoCloseContainer(nsIAtom* aTag); |
michael@0 | 90 | nsresult DoAddLeaf(nsIAtom* aTag); |
michael@0 | 91 | void DoAddText(bool aIsWhitespace, const nsAString& aText); |
michael@0 | 92 | |
michael@0 | 93 | // Inlined functions |
michael@0 | 94 | inline bool MayWrap() |
michael@0 | 95 | { |
michael@0 | 96 | return mWrapColumn && |
michael@0 | 97 | ((mFlags & nsIDocumentEncoder::OutputFormatted) || |
michael@0 | 98 | (mFlags & nsIDocumentEncoder::OutputWrap)); |
michael@0 | 99 | } |
michael@0 | 100 | |
michael@0 | 101 | inline bool DoOutput() |
michael@0 | 102 | { |
michael@0 | 103 | return mHeadLevel == 0; |
michael@0 | 104 | } |
michael@0 | 105 | |
michael@0 | 106 | // Stack handling functions |
michael@0 | 107 | bool GetLastBool(const nsTArray<bool>& aStack); |
michael@0 | 108 | void SetLastBool(nsTArray<bool>& aStack, bool aValue); |
michael@0 | 109 | void PushBool(nsTArray<bool>& aStack, bool aValue); |
michael@0 | 110 | bool PopBool(nsTArray<bool>& aStack); |
michael@0 | 111 | |
michael@0 | 112 | bool ShouldReplaceContainerWithPlaceholder(nsIAtom* aTag); |
michael@0 | 113 | |
michael@0 | 114 | protected: |
michael@0 | 115 | nsString mCurrentLine; |
michael@0 | 116 | uint32_t mHeadLevel; |
michael@0 | 117 | bool mAtFirstColumn; |
michael@0 | 118 | |
michael@0 | 119 | // Handling of quoted text (for mail): |
michael@0 | 120 | // Quotes need to be wrapped differently from non-quoted text, |
michael@0 | 121 | // because quoted text has a few extra characters (e.g. ">> ") |
michael@0 | 122 | // which makes the line length longer. |
michael@0 | 123 | // Mail can represent quotes in different ways: |
michael@0 | 124 | // Not wrapped in any special tag (if mail.compose.wrap_to_window_width) |
michael@0 | 125 | // or in a <span>. |
michael@0 | 126 | bool mDontWrapAnyQuotes; // no special quote markers |
michael@0 | 127 | |
michael@0 | 128 | bool mStructs; // Output structs (pref) |
michael@0 | 129 | |
michael@0 | 130 | // If we've just written out a cite blockquote, we need to remember it |
michael@0 | 131 | // so we don't duplicate spaces before a <pre wrap> (which mail uses to quote |
michael@0 | 132 | // old messages). |
michael@0 | 133 | bool mHasWrittenCiteBlockquote; |
michael@0 | 134 | |
michael@0 | 135 | int32_t mIndent; |
michael@0 | 136 | // mInIndentString keeps a header that has to be written in the indent. |
michael@0 | 137 | // That could be, for instance, the bullet in a bulleted list. |
michael@0 | 138 | nsString mInIndentString; |
michael@0 | 139 | int32_t mCiteQuoteLevel; |
michael@0 | 140 | int32_t mFlags; |
michael@0 | 141 | int32_t mFloatingLines; // To store the number of lazy line breaks |
michael@0 | 142 | |
michael@0 | 143 | // The wrap column is how many standard sized chars (western languages) |
michael@0 | 144 | // should be allowed on a line. There could be less chars if the chars |
michael@0 | 145 | // are wider than latin chars of more if the chars are more narrow. |
michael@0 | 146 | uint32_t mWrapColumn; |
michael@0 | 147 | |
michael@0 | 148 | // The width of the line as it will appear on the screen (approx.) |
michael@0 | 149 | uint32_t mCurrentLineWidth; |
michael@0 | 150 | |
michael@0 | 151 | // Treat quoted text as though it's preformatted -- don't wrap it. |
michael@0 | 152 | // Having it on a pref is a temporary measure, See bug 69638. |
michael@0 | 153 | int32_t mSpanLevel; |
michael@0 | 154 | |
michael@0 | 155 | |
michael@0 | 156 | int32_t mEmptyLines; // Will be the number of empty lines before |
michael@0 | 157 | // the current. 0 if we are starting a new |
michael@0 | 158 | // line and -1 if we are in a line. |
michael@0 | 159 | |
michael@0 | 160 | bool mInWhitespace; |
michael@0 | 161 | bool mPreFormatted; |
michael@0 | 162 | bool mStartedOutput; // we've produced at least a character |
michael@0 | 163 | |
michael@0 | 164 | // While handling a new tag, this variable should remind if any line break |
michael@0 | 165 | // is due because of a closing tag. Setting it to "TRUE" while closing the tags. |
michael@0 | 166 | // Hence opening tags are guaranteed to start with appropriate line breaks. |
michael@0 | 167 | bool mLineBreakDue; |
michael@0 | 168 | |
michael@0 | 169 | nsString mURL; |
michael@0 | 170 | int32_t mHeaderStrategy; /* Header strategy (pref) |
michael@0 | 171 | 0 = no indention |
michael@0 | 172 | 1 = indention, increased with |
michael@0 | 173 | header level (default) |
michael@0 | 174 | 2 = numbering and slight indention */ |
michael@0 | 175 | int32_t mHeaderCounter[7]; /* For header-numbering: |
michael@0 | 176 | Number of previous headers of |
michael@0 | 177 | the same depth and in the same |
michael@0 | 178 | section. |
michael@0 | 179 | mHeaderCounter[1] for <h1> etc. */ |
michael@0 | 180 | |
michael@0 | 181 | nsRefPtr<mozilla::dom::Element> mElement; |
michael@0 | 182 | |
michael@0 | 183 | // For handling table rows |
michael@0 | 184 | nsAutoTArray<bool, 8> mHasWrittenCellsForRow; |
michael@0 | 185 | |
michael@0 | 186 | // Values gotten in OpenContainer that is (also) needed in CloseContainer |
michael@0 | 187 | nsAutoTArray<bool, 8> mIsInCiteBlockquote; |
michael@0 | 188 | |
michael@0 | 189 | // The output data |
michael@0 | 190 | nsAString* mOutputString; |
michael@0 | 191 | |
michael@0 | 192 | // The tag stack: the stack of tags we're operating on, so we can nest. |
michael@0 | 193 | // The stack only ever points to static atoms, so they don't need to be |
michael@0 | 194 | // refcounted. |
michael@0 | 195 | nsIAtom** mTagStack; |
michael@0 | 196 | uint32_t mTagStackIndex; |
michael@0 | 197 | |
michael@0 | 198 | // Content in the stack above this index should be ignored: |
michael@0 | 199 | uint32_t mIgnoreAboveIndex; |
michael@0 | 200 | |
michael@0 | 201 | // The stack for ordered lists |
michael@0 | 202 | int32_t *mOLStack; |
michael@0 | 203 | uint32_t mOLStackIndex; |
michael@0 | 204 | |
michael@0 | 205 | uint32_t mULCount; |
michael@0 | 206 | |
michael@0 | 207 | nsString mLineBreak; |
michael@0 | 208 | nsCOMPtr<nsILineBreaker> mLineBreaker; |
michael@0 | 209 | |
michael@0 | 210 | // Conveniance constant. It would be nice to have it as a const static |
michael@0 | 211 | // variable, but that causes issues with OpenBSD and module unloading. |
michael@0 | 212 | const nsString kSpace; |
michael@0 | 213 | |
michael@0 | 214 | // If nsIDocumentEncoder::OutputNonTextContentAsPlaceholder is set, the child |
michael@0 | 215 | // nodes of specific nodes - <iframe>, <canvas>, etc. should be ignored. |
michael@0 | 216 | // mIgnoredChildNodeLevel is used to tell if current node is an ignorable |
michael@0 | 217 | // child node. The initial value of mIgnoredChildNodeLevel is 0. When |
michael@0 | 218 | // serializer enters those specific nodes, mIgnoredChildNodeLevel increases |
michael@0 | 219 | // and is greater than 0. Otherwise when serializer leaves those nodes, |
michael@0 | 220 | // mIgnoredChildNodeLevel decreases. |
michael@0 | 221 | uint32_t mIgnoredChildNodeLevel; |
michael@0 | 222 | }; |
michael@0 | 223 | |
michael@0 | 224 | nsresult |
michael@0 | 225 | NS_NewPlainTextSerializer(nsIContentSerializer** aSerializer); |
michael@0 | 226 | |
michael@0 | 227 | #endif |