1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #ifndef __wsrunobject_h__
39 : #define __wsrunobject_h__
40 :
41 : #include "nsCOMPtr.h"
42 : #include "nsIDOMNode.h"
43 : #include "nsCOMArray.h"
44 : #include "nsIContent.h"
45 : #include "nsIEditor.h"
46 : #include "nsEditorUtils.h"
47 :
48 : class nsIDOMDocument;
49 : class nsIDOMNode;
50 : class nsHTMLEditor;
51 :
52 : // class nsWSRunObject represents the entire whitespace situation
53 : // around a given point. It collects up a list of nodes that contain
54 : // whitespace and categorizes in up to 3 different WSFragments (detailed
55 : // below). Each WSFragment is a collection of whitespace that is
56 : // either all insignificant, or that is significant. A WSFragment could
57 : // consist of insignificant whitespace because it is after a block
58 : // boundary or after a break. Or it could be insignificant because it
59 : // is before a block. Or it could be significant because it is
60 : // surrounded by text, or starts and ends with nbsps, etc.
61 :
62 : // Throughout I refer to LeadingWS, NormalWS, TrailingWS. LeadingWS & TrailingWS
63 : // are runs of ascii ws that are insignificant (do not render) because they
64 : // are adjacent to block boundaries, or after a break. NormalWS is ws that
65 : // does cause soem rendering. Note that not all the ws in a NormalWS run need
66 : // render. For example, two ascii spaces surrounded by text on both sides
67 : // will only render as one space (in non-preformatted stlye html), yet both
68 : // spaces count as NormalWS. Together, they render as the one visible space.
69 :
70 : class NS_STACK_CLASS nsWSRunObject
71 : {
72 : public:
73 :
74 : enum BlockBoundary
75 : {
76 : kBeforeBlock,
77 : kBlockStart,
78 : kBlockEnd,
79 : kAfterBlock
80 : };
81 :
82 : // constructor / destructor -----------------------------------------------
83 : nsWSRunObject(nsHTMLEditor *aEd, nsIDOMNode *aNode, PRInt32 aOffset);
84 : ~nsWSRunObject();
85 :
86 : // public methods ---------------------------------------------------------
87 :
88 : // ScrubBlockBoundary removes any non-visible whitespace at the specified
89 : // location relative to a block node.
90 : static nsresult ScrubBlockBoundary(nsHTMLEditor *aHTMLEd,
91 : nsCOMPtr<nsIDOMNode> *aBlock,
92 : BlockBoundary aBoundary,
93 : PRInt32 *aOffset = 0);
94 :
95 : // PrepareToJoinBlocks fixes up ws at the end of aLeftParent and the
96 : // beginning of aRightParent in preperation for them to be joined.
97 : // example of fixup: trailingws in aLeftParent needs to be removed.
98 : static nsresult PrepareToJoinBlocks(nsHTMLEditor *aEd,
99 : nsIDOMNode *aLeftParent,
100 : nsIDOMNode *aRightParent);
101 :
102 : // PrepareToDeleteRange fixes up ws before {aStartNode,aStartOffset}
103 : // and after {aEndNode,aEndOffset} in preperation for content
104 : // in that range to be deleted. Note that the nodes and offsets
105 : // are adjusted in response to any dom changes we make while
106 : // adjusting ws.
107 : // example of fixup: trailingws before {aStartNode,aStartOffset}
108 : // needs to be removed.
109 : static nsresult PrepareToDeleteRange(nsHTMLEditor *aHTMLEd,
110 : nsCOMPtr<nsIDOMNode> *aStartNode,
111 : PRInt32 *aStartOffset,
112 : nsCOMPtr<nsIDOMNode> *aEndNode,
113 : PRInt32 *aEndOffset);
114 :
115 : // PrepareToDeleteNode fixes up ws before and after aNode in preperation
116 : // for aNode to be deleted.
117 : // example of fixup: trailingws before aNode needs to be removed.
118 : static nsresult PrepareToDeleteNode(nsHTMLEditor *aHTMLEd,
119 : nsIDOMNode *aNode);
120 :
121 : // PrepareToSplitAcrossBlocks fixes up ws before and after
122 : // {aSplitNode,aSplitOffset} in preperation for a block
123 : // parent to be split. Note that the aSplitNode and aSplitOffset
124 : // are adjusted in response to any dom changes we make while
125 : // adjusting ws.
126 : // example of fixup: normalws before {aSplitNode,aSplitOffset}
127 : // needs to end with nbsp.
128 : static nsresult PrepareToSplitAcrossBlocks(nsHTMLEditor *aHTMLEd,
129 : nsCOMPtr<nsIDOMNode> *aSplitNode,
130 : PRInt32 *aSplitOffset);
131 :
132 : // InsertBreak inserts a br node at {aInOutParent,aInOutOffset}
133 : // and makes any needed adjustments to ws around that point.
134 : // example of fixup: normalws after {aInOutParent,aInOutOffset}
135 : // needs to begin with nbsp.
136 : nsresult InsertBreak(nsCOMPtr<nsIDOMNode> *aInOutParent,
137 : PRInt32 *aInOutOffset,
138 : nsCOMPtr<nsIDOMNode> *outBRNode,
139 : nsIEditor::EDirection aSelect);
140 :
141 : // InsertText inserts a string at {aInOutParent,aInOutOffset}
142 : // and makes any needed adjustments to ws around that point.
143 : // example of fixup: trailingws before {aInOutParent,aInOutOffset}
144 : // needs to be removed.
145 : nsresult InsertText(const nsAString& aStringToInsert,
146 : nsCOMPtr<nsIDOMNode> *aInOutNode,
147 : PRInt32 *aInOutOffset,
148 : nsIDOMDocument *aDoc);
149 :
150 : // DeleteWSBackward deletes a single visible piece of ws before
151 : // the ws point (the point to create the wsRunObject, passed to
152 : // its constructor). It makes any needed conversion to adjacent
153 : // ws to retain its significance.
154 : nsresult DeleteWSBackward();
155 :
156 : // DeleteWSForward deletes a single visible piece of ws after
157 : // the ws point (the point to create the wsRunObject, passed to
158 : // its constructor). It makes any needed conversion to adjacent
159 : // ws to retain its significance.
160 : nsresult DeleteWSForward();
161 :
162 : // PriorVisibleNode returns the first piece of visible thing
163 : // before {aNode,aOffset}. If there is no visible ws qualifying
164 : // it returns what is before the ws run. Note that
165 : // {outVisNode,outVisOffset} is set to just AFTER the visible
166 : // object.
167 : nsresult PriorVisibleNode(nsIDOMNode *aNode,
168 : PRInt32 aOffset,
169 : nsCOMPtr<nsIDOMNode> *outVisNode,
170 : PRInt32 *outVisOffset,
171 : PRInt16 *outType);
172 :
173 : // NextVisibleNode returns the first piece of visible thing
174 : // after {aNode,aOffset}. If there is no visible ws qualifying
175 : // it returns what is after the ws run. Note that
176 : // {outVisNode,outVisOffset} is set to just BEFORE the visible
177 : // object.
178 : nsresult NextVisibleNode (nsIDOMNode *aNode,
179 : PRInt32 aOffset,
180 : nsCOMPtr<nsIDOMNode> *outVisNode,
181 : PRInt32 *outVisOffset,
182 : PRInt16 *outType);
183 :
184 : // AdjustWhitespace examines the ws object for nbsp's that can
185 : // be safely converted to regular ascii space and converts them.
186 : nsresult AdjustWhitespace();
187 :
188 : // public enums ---------------------------------------------------------
189 : enum {eNone = 0};
190 : enum {eLeadingWS = 1}; // leading insignificant ws, ie, after block or br
191 : enum {eTrailingWS = 1 << 1}; // trailing insignificant ws, ie, before block
192 : enum {eNormalWS = 1 << 2}; // normal significant ws, ie, after text, image, ...
193 : enum {eText = 1 << 3}; // indicates regular (non-ws) text
194 : enum {eSpecial = 1 << 4}; // indicates an inline non-container, like image
195 : enum {eBreak = 1 << 5}; // indicates a br node
196 : enum {eOtherBlock = 1 << 6}; // indicates a block other than one ws run is in
197 : enum {eThisBlock = 1 << 7}; // indicates the block ws run is in
198 : enum {eBlock = eOtherBlock | eThisBlock}; // block found
199 :
200 : enum {eBefore = 1};
201 : enum {eAfter = 1 << 1};
202 : enum {eBoth = eBefore | eAfter};
203 :
204 : protected:
205 :
206 : // WSFragment struct ---------------------------------------------------------
207 : // WSFragment represents a single run of ws (all leadingws, or all normalws,
208 : // or all trailingws, or all leading+trailingws). Note that this single run may
209 : // still span multiple nodes.
210 : struct WSFragment
211 0 : {
212 : nsCOMPtr<nsIDOMNode> mStartNode; // node where ws run starts
213 : nsCOMPtr<nsIDOMNode> mEndNode; // node where ws run ends
214 : PRInt16 mStartOffset; // offset where ws run starts
215 : PRInt16 mEndOffset; // offset where ws run ends
216 : PRInt16 mType, mLeftType, mRightType; // type of ws, and what is to left and right of it
217 : WSFragment *mLeft, *mRight; // other ws runs to left or right. may be null.
218 :
219 0 : WSFragment() : mStartNode(0),mEndNode(0),mStartOffset(0),
220 : mEndOffset(0),mType(0),mLeftType(0),
221 0 : mRightType(0),mLeft(0),mRight(0) {}
222 : };
223 :
224 : // WSPoint struct ------------------------------------------------------------
225 : // A WSPoint struct represents a unique location within the ws run. It is
226 : // always within a textnode that is one of the nodes stored in the list
227 : // in the wsRunObject. For convenience, the character at that point is also
228 : // stored in the struct.
229 : struct NS_STACK_CLASS WSPoint
230 0 : {
231 : nsCOMPtr<nsIContent> mTextNode;
232 : PRUint32 mOffset;
233 : PRUnichar mChar;
234 :
235 0 : WSPoint() : mTextNode(0),mOffset(0),mChar(0) {}
236 0 : WSPoint(nsIDOMNode *aNode, PRInt32 aOffset, PRUnichar aChar) :
237 0 : mTextNode(do_QueryInterface(aNode)),mOffset(aOffset),mChar(aChar)
238 : {
239 0 : if (!mTextNode->IsNodeOfType(nsINode::eDATA_NODE)) {
240 : // Not sure if this is needed, but it'll maintain the same
241 : // functionality
242 0 : mTextNode = nsnull;
243 : }
244 0 : }
245 0 : WSPoint(nsIContent *aTextNode, PRInt32 aOffset, PRUnichar aChar) :
246 0 : mTextNode(aTextNode),mOffset(aOffset),mChar(aChar) {}
247 : };
248 :
249 : enum AreaRestriction
250 : {
251 : eAnywhere, eOutsideUserSelectAll
252 : };
253 :
254 : // protected methods ---------------------------------------------------------
255 : // tons of utility methods.
256 :
257 : /**
258 : * Return the node which we will handle white-space under. This is the
259 : * closest block within the DOM subtree we're editing, or if none is
260 : * found, the (inline) root of the editable subtree.
261 : */
262 : already_AddRefed<nsIDOMNode> GetWSBoundingParent();
263 :
264 : nsresult GetWSNodes();
265 : nsresult GetRuns();
266 : void ClearRuns();
267 : nsresult MakeSingleWSRun(PRInt16 aType);
268 : nsresult PrependNodeToList(nsIDOMNode *aNode);
269 : nsresult AppendNodeToList(nsIDOMNode *aNode);
270 : nsresult GetPreviousWSNode(nsIDOMNode *aStartNode,
271 : nsIDOMNode *aBlockParent,
272 : nsCOMPtr<nsIDOMNode> *aPriorNode);
273 : nsresult GetPreviousWSNode(nsIDOMNode *aStartNode,
274 : PRInt16 aOffset,
275 : nsIDOMNode *aBlockParent,
276 : nsCOMPtr<nsIDOMNode> *aPriorNode);
277 : nsresult GetPreviousWSNode(DOMPoint aPoint,
278 : nsIDOMNode *aBlockParent,
279 : nsCOMPtr<nsIDOMNode> *aPriorNode);
280 : nsresult GetNextWSNode(nsIDOMNode *aStartNode,
281 : nsIDOMNode *aBlockParent,
282 : nsCOMPtr<nsIDOMNode> *aNextNode);
283 : nsresult GetNextWSNode(nsIDOMNode *aStartNode,
284 : PRInt16 aOffset,
285 : nsIDOMNode *aBlockParent,
286 : nsCOMPtr<nsIDOMNode> *aNextNode);
287 : nsresult GetNextWSNode(DOMPoint aPoint,
288 : nsIDOMNode *aBlockParent,
289 : nsCOMPtr<nsIDOMNode> *aNextNode);
290 : nsresult PrepareToDeleteRangePriv(nsWSRunObject* aEndObject);
291 : nsresult PrepareToSplitAcrossBlocksPriv();
292 : nsresult DeleteChars(nsIDOMNode *aStartNode, PRInt32 aStartOffset,
293 : nsIDOMNode *aEndNode, PRInt32 aEndOffset,
294 : AreaRestriction aAR = eAnywhere);
295 : nsresult GetCharAfter(nsIDOMNode *aNode, PRInt32 aOffset, WSPoint *outPoint);
296 : nsresult GetCharBefore(nsIDOMNode *aNode, PRInt32 aOffset, WSPoint *outPoint);
297 : nsresult GetCharAfter(WSPoint &aPoint, WSPoint *outPoint);
298 : nsresult GetCharBefore(WSPoint &aPoint, WSPoint *outPoint);
299 : nsresult ConvertToNBSP(WSPoint aPoint,
300 : AreaRestriction aAR = eAnywhere);
301 : nsresult GetAsciiWSBounds(PRInt16 aDir, nsIDOMNode *aNode, PRInt32 aOffset,
302 : nsCOMPtr<nsIDOMNode> *outStartNode, PRInt32 *outStartOffset,
303 : nsCOMPtr<nsIDOMNode> *outEndNode, PRInt32 *outEndOffset);
304 : nsresult FindRun(nsIDOMNode *aNode, PRInt32 aOffset, WSFragment **outRun, bool after);
305 : PRUnichar GetCharAt(nsIContent *aTextNode, PRInt32 aOffset);
306 : nsresult GetWSPointAfter(nsIDOMNode *aNode, PRInt32 aOffset, WSPoint *outPoint);
307 : nsresult GetWSPointBefore(nsIDOMNode *aNode, PRInt32 aOffset, WSPoint *outPoint);
308 : nsresult CheckTrailingNBSPOfRun(WSFragment *aRun);
309 : nsresult CheckTrailingNBSP(WSFragment *aRun, nsIDOMNode *aNode, PRInt32 aOffset);
310 : nsresult CheckLeadingNBSP(WSFragment *aRun, nsIDOMNode *aNode, PRInt32 aOffset);
311 :
312 : static nsresult ScrubBlockBoundaryInner(nsHTMLEditor *aHTMLEd,
313 : nsCOMPtr<nsIDOMNode> *aBlock,
314 : BlockBoundary aBoundary);
315 : nsresult Scrub();
316 :
317 : // member variables ---------------------------------------------------------
318 :
319 : nsCOMPtr<nsIDOMNode> mNode; // the node passed to our constructor
320 : PRInt32 mOffset; // the offset passed to our contructor
321 : // together, the above represent the point at which we are building up ws info.
322 :
323 : bool mPRE; // true if we are in preformatted whitespace context
324 : nsCOMPtr<nsIDOMNode> mStartNode; // node/offset where ws starts
325 : PRInt32 mStartOffset; // ...
326 : PRInt16 mStartReason; // reason why ws starts (eText, eOtherBlock, etc)
327 : nsCOMPtr<nsIDOMNode> mStartReasonNode;// the node that implicated by start reason
328 :
329 : nsCOMPtr<nsIDOMNode> mEndNode; // node/offset where ws ends
330 : PRInt32 mEndOffset; // ...
331 : PRInt16 mEndReason; // reason why ws ends (eText, eOtherBlock, etc)
332 : nsCOMPtr<nsIDOMNode> mEndReasonNode; // the node that implicated by end reason
333 :
334 : nsCOMPtr<nsIDOMNode> mFirstNBSPNode; // location of first nbsp in ws run, if any
335 : PRInt32 mFirstNBSPOffset; // ...
336 :
337 : nsCOMPtr<nsIDOMNode> mLastNBSPNode; // location of last nbsp in ws run, if any
338 : PRInt32 mLastNBSPOffset; // ...
339 :
340 : nsCOMArray<nsIDOMNode> mNodeArray;//the list of nodes containing ws in this run
341 :
342 : WSFragment *mStartRun; // the first WSFragment in the run
343 : WSFragment *mEndRun; // the last WSFragment in the run, may be same as first
344 :
345 : nsHTMLEditor *mHTMLEditor; // non-owning.
346 :
347 : friend class nsHTMLEditRules; // opening this class up for pillaging
348 : friend class nsHTMLEditor; // opening this class up for more pillaging
349 : };
350 :
351 : #endif
352 :
|