1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : // vim:cindent:ts=2:et:sw=2:
3 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Mozilla Communicator client code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Netscape Communications Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 1998
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * L. David Baron <dbaron@dbaron.org>
25 : * Mats Palmgren <mats.palmgren@bredband.net>
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either of the GNU General Public License Version 2 or later (the "GPL"),
29 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : /* representation of one line within a block frame, a CSS line box */
42 :
43 : #ifndef nsLineBox_h___
44 : #define nsLineBox_h___
45 :
46 : #include "mozilla/Attributes.h"
47 :
48 : #include "nsILineIterator.h"
49 : #include "nsIFrame.h"
50 :
51 : class nsLineBox;
52 : class nsFloatCache;
53 : class nsFloatCacheList;
54 : class nsFloatCacheFreeList;
55 :
56 : // State cached after reflowing a float. This state is used during
57 : // incremental reflow when we avoid reflowing a float.
58 : class nsFloatCache {
59 : public:
60 : nsFloatCache();
61 : #ifdef NS_BUILD_REFCNT_LOGGING
62 : ~nsFloatCache();
63 : #else
64 : ~nsFloatCache() { }
65 : #endif
66 :
67 0 : nsFloatCache* Next() const { return mNext; }
68 :
69 : nsIFrame* mFloat; // floating frame
70 :
71 : protected:
72 : nsFloatCache* mNext;
73 :
74 : friend class nsFloatCacheList;
75 : friend class nsFloatCacheFreeList;
76 : };
77 :
78 : //----------------------------------------
79 :
80 : class nsFloatCacheList {
81 : public:
82 : #ifdef NS_BUILD_REFCNT_LOGGING
83 : nsFloatCacheList();
84 : #else
85 : nsFloatCacheList() : mHead(nsnull) { }
86 : #endif
87 : ~nsFloatCacheList();
88 :
89 0 : bool IsEmpty() const {
90 0 : return nsnull == mHead;
91 : }
92 :
93 0 : bool NotEmpty() const {
94 0 : return nsnull != mHead;
95 : }
96 :
97 0 : nsFloatCache* Head() const {
98 0 : return mHead;
99 : }
100 :
101 : nsFloatCache* Tail() const;
102 :
103 : void DeleteAll();
104 :
105 : nsFloatCache* Find(nsIFrame* aOutOfFlowFrame);
106 :
107 : // Remove a nsFloatCache from this list. Deleting this nsFloatCache
108 : // becomes the caller's responsibility.
109 0 : void Remove(nsFloatCache* aElement) { RemoveAndReturnPrev(aElement); }
110 :
111 : // Steal away aList's nsFloatCache objects and put them in this
112 : // list. aList must not be empty.
113 : void Append(nsFloatCacheFreeList& aList);
114 :
115 : protected:
116 : nsFloatCache* mHead;
117 :
118 : // Remove a nsFloatCache from this list. Deleting this nsFloatCache
119 : // becomes the caller's responsibility. Returns the nsFloatCache that was
120 : // before aElement, or nsnull if aElement was the first.
121 : nsFloatCache* RemoveAndReturnPrev(nsFloatCache* aElement);
122 :
123 : friend class nsFloatCacheFreeList;
124 : };
125 :
126 : //---------------------------------------
127 : // Like nsFloatCacheList, but with fast access to the tail
128 :
129 : class nsFloatCacheFreeList : private nsFloatCacheList {
130 : public:
131 : #ifdef NS_BUILD_REFCNT_LOGGING
132 : nsFloatCacheFreeList();
133 : ~nsFloatCacheFreeList();
134 : #else
135 : nsFloatCacheFreeList() : mTail(nsnull) { }
136 : ~nsFloatCacheFreeList() { }
137 : #endif
138 :
139 : // Reimplement trivial functions
140 0 : bool IsEmpty() const {
141 0 : return nsnull == mHead;
142 : }
143 :
144 0 : nsFloatCache* Head() const {
145 0 : return mHead;
146 : }
147 :
148 0 : nsFloatCache* Tail() const {
149 0 : return mTail;
150 : }
151 :
152 0 : bool NotEmpty() const {
153 0 : return nsnull != mHead;
154 : }
155 :
156 : void DeleteAll();
157 :
158 : // Steal away aList's nsFloatCache objects and put them on this
159 : // free-list. aList must not be empty.
160 : void Append(nsFloatCacheList& aList);
161 :
162 : void Append(nsFloatCache* aFloatCache);
163 :
164 : void Remove(nsFloatCache* aElement);
165 :
166 : // Remove an nsFloatCache object from this list and return it, or create
167 : // a new one if this one is empty; Set its mFloat to aFloat.
168 : nsFloatCache* Alloc(nsIFrame* aFloat);
169 :
170 : protected:
171 : nsFloatCache* mTail;
172 :
173 : friend class nsFloatCacheList;
174 : };
175 :
176 : //----------------------------------------------------------------------
177 :
178 : #define LINE_MAX_BREAK_TYPE ((1 << 4) - 1)
179 : #define LINE_MAX_CHILD_COUNT PR_INT32_MAX
180 :
181 : #if NS_STYLE_CLEAR_LAST_VALUE > 15
182 : need to rearrange the mBits bitfield;
183 : #endif
184 :
185 : /**
186 : * Function to create a line box and initialize it with a single frame.
187 : * If the frame was moved from another line then you're responsible
188 : * for notifying that line using NoteFrameRemoved(). Alternatively,
189 : * it's better to use the next function that does that for you in an
190 : * optimal way.
191 : */
192 : nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame,
193 : bool aIsBlock);
194 : /**
195 : * Function to create a line box and initialize it with aCount frames
196 : * that are currently on aFromLine.
197 : */
198 : nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine,
199 : nsIFrame* aFrame, PRInt32 aCount);
200 :
201 : class nsLineList;
202 :
203 : // don't use the following names outside of this file. Instead, use
204 : // nsLineList::iterator, etc. These are just here to allow them to
205 : // be specified as parameters to methods of nsLineBox.
206 : class nsLineList_iterator;
207 : class nsLineList_const_iterator;
208 : class nsLineList_reverse_iterator;
209 : class nsLineList_const_reverse_iterator;
210 :
211 : /**
212 : * Users must have the class that is to be part of the list inherit
213 : * from nsLineLink. If they want to be efficient, it should be the
214 : * first base class. (This was originally nsCLink in a templatized
215 : * nsCList, but it's still useful separately.)
216 : */
217 :
218 0 : class nsLineLink {
219 :
220 : public:
221 : friend class nsLineList;
222 : friend class nsLineList_iterator;
223 : friend class nsLineList_reverse_iterator;
224 : friend class nsLineList_const_iterator;
225 : friend class nsLineList_const_reverse_iterator;
226 :
227 : private:
228 : nsLineLink *_mNext; // or head
229 : nsLineLink *_mPrev; // or tail
230 :
231 : };
232 :
233 :
234 : /**
235 : * The nsLineBox class represents a horizontal line of frames. It contains
236 : * enough state to support incremental reflow of the frames, event handling
237 : * for the frames, and rendering of the frames.
238 : */
239 : class nsLineBox : public nsLineLink {
240 : private:
241 : nsLineBox(nsIFrame* aFrame, PRInt32 aCount, bool aIsBlock);
242 : ~nsLineBox();
243 :
244 : // Overloaded new operator. Uses an arena (which comes from the presShell)
245 : // to perform the allocation.
246 : void* operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW;
247 : void operator delete(void* aPtr, size_t sz) MOZ_DELETE;
248 :
249 : public:
250 : // Use these functions to allocate and destroy line boxes
251 : friend nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame,
252 : bool aIsBlock);
253 : friend nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine,
254 : nsIFrame* aFrame, PRInt32 aCount);
255 : void Destroy(nsIPresShell* aPresShell);
256 :
257 : // mBlock bit
258 0 : bool IsBlock() const {
259 0 : return mFlags.mBlock;
260 : }
261 0 : bool IsInline() const {
262 0 : return 0 == mFlags.mBlock;
263 : }
264 :
265 : // mDirty bit
266 0 : void MarkDirty() {
267 0 : mFlags.mDirty = 1;
268 0 : }
269 0 : void ClearDirty() {
270 0 : mFlags.mDirty = 0;
271 0 : }
272 0 : bool IsDirty() const {
273 0 : return mFlags.mDirty;
274 : }
275 :
276 : // mPreviousMarginDirty bit
277 0 : void MarkPreviousMarginDirty() {
278 0 : mFlags.mPreviousMarginDirty = 1;
279 0 : }
280 0 : void ClearPreviousMarginDirty() {
281 0 : mFlags.mPreviousMarginDirty = 0;
282 0 : }
283 0 : bool IsPreviousMarginDirty() const {
284 0 : return mFlags.mPreviousMarginDirty;
285 : }
286 :
287 : // mHasClearance bit
288 0 : void SetHasClearance() {
289 0 : mFlags.mHasClearance = 1;
290 0 : }
291 0 : void ClearHasClearance() {
292 0 : mFlags.mHasClearance = 0;
293 0 : }
294 0 : bool HasClearance() const {
295 0 : return mFlags.mHasClearance;
296 : }
297 :
298 : // mImpactedByFloat bit
299 0 : void SetLineIsImpactedByFloat(bool aValue) {
300 0 : mFlags.mImpactedByFloat = aValue;
301 0 : }
302 0 : bool IsImpactedByFloat() const {
303 0 : return mFlags.mImpactedByFloat;
304 : }
305 :
306 : // mLineWrapped bit
307 0 : void SetLineWrapped(bool aOn) {
308 0 : mFlags.mLineWrapped = aOn;
309 0 : }
310 0 : bool IsLineWrapped() const {
311 0 : return mFlags.mLineWrapped;
312 : }
313 :
314 : // mInvalidateTextRuns bit
315 0 : void SetInvalidateTextRuns(bool aOn) {
316 0 : mFlags.mInvalidateTextRuns = aOn;
317 0 : }
318 0 : bool GetInvalidateTextRuns() const {
319 0 : return mFlags.mInvalidateTextRuns;
320 : }
321 :
322 : // mResizeReflowOptimizationDisabled bit
323 0 : void DisableResizeReflowOptimization() {
324 0 : mFlags.mResizeReflowOptimizationDisabled = true;
325 0 : }
326 0 : void EnableResizeReflowOptimization() {
327 0 : mFlags.mResizeReflowOptimizationDisabled = false;
328 0 : }
329 0 : bool ResizeReflowOptimizationDisabled() const {
330 0 : return mFlags.mResizeReflowOptimizationDisabled;
331 : }
332 :
333 : // mHasBullet bit
334 0 : void SetHasBullet() {
335 0 : mFlags.mHasBullet = true;
336 0 : InvalidateCachedIsEmpty();
337 0 : }
338 0 : void ClearHasBullet() {
339 0 : mFlags.mHasBullet = false;
340 0 : InvalidateCachedIsEmpty();
341 0 : }
342 0 : bool HasBullet() const {
343 0 : return mFlags.mHasBullet;
344 : }
345 :
346 : // mHadFloatPushed bit
347 0 : void SetHadFloatPushed() {
348 0 : mFlags.mHadFloatPushed = true;
349 0 : }
350 0 : void ClearHadFloatPushed() {
351 0 : mFlags.mHadFloatPushed = false;
352 0 : }
353 0 : bool HadFloatPushed() const {
354 0 : return mFlags.mHadFloatPushed;
355 : }
356 :
357 : private:
358 : // Add a hash table for fast lookup when the line has more frames than this.
359 : static const PRUint32 kMinChildCountForHashtable = 200;
360 :
361 : /**
362 : * Take ownership of aFromLine's hash table and remove the frames that
363 : * stay on aFromLine from it, i.e. aFromLineNewCount frames starting with
364 : * mFirstChild. This method is used to optimize moving a large number
365 : * of frames from one line to the next.
366 : */
367 : void StealHashTableFrom(nsLineBox* aFromLine, PRUint32 aFromLineNewCount);
368 :
369 : /**
370 : * Does the equivalent of this->NoteFrameAdded and aFromLine->NoteFrameRemoved
371 : * for each frame on this line, but in a optimized way.
372 : */
373 : void NoteFramesMovedFrom(nsLineBox* aFromLine);
374 :
375 0 : void SwitchToHashtable()
376 : {
377 0 : MOZ_ASSERT(!mFlags.mHasHashedFrames);
378 0 : PRUint32 count = GetChildCount();
379 0 : mFrames = new nsTHashtable< nsPtrHashKey<nsIFrame> >();
380 0 : mFlags.mHasHashedFrames = 1;
381 : PRUint32 minSize =
382 0 : NS_MAX(kMinChildCountForHashtable, PRUint32(PL_DHASH_MIN_SIZE));
383 0 : mFrames->Init(NS_MAX(count, minSize));
384 0 : for (nsIFrame* f = mFirstChild; count-- > 0; f = f->GetNextSibling()) {
385 0 : mFrames->PutEntry(f);
386 : }
387 0 : }
388 0 : void SwitchToCounter() {
389 0 : MOZ_ASSERT(mFlags.mHasHashedFrames);
390 0 : PRUint32 count = GetChildCount();
391 0 : delete mFrames;
392 0 : mFlags.mHasHashedFrames = 0;
393 0 : mChildCount = count;
394 0 : }
395 :
396 : public:
397 0 : PRInt32 GetChildCount() const {
398 0 : return NS_UNLIKELY(mFlags.mHasHashedFrames) ? mFrames->Count() : mChildCount;
399 : }
400 :
401 : /**
402 : * Register that aFrame is now on this line.
403 : */
404 0 : void NoteFrameAdded(nsIFrame* aFrame) {
405 0 : if (NS_UNLIKELY(mFlags.mHasHashedFrames)) {
406 0 : mFrames->PutEntry(aFrame);
407 : } else {
408 0 : if (++mChildCount >= kMinChildCountForHashtable) {
409 0 : SwitchToHashtable();
410 : }
411 : }
412 0 : }
413 :
414 : /**
415 : * Register that aFrame is not on this line anymore.
416 : */
417 0 : void NoteFrameRemoved(nsIFrame* aFrame) {
418 0 : MOZ_ASSERT(GetChildCount() > 0);
419 0 : if (NS_UNLIKELY(mFlags.mHasHashedFrames)) {
420 0 : mFrames->RemoveEntry(aFrame);
421 0 : if (mFrames->Count() < kMinChildCountForHashtable) {
422 0 : SwitchToCounter();
423 : }
424 : } else {
425 0 : --mChildCount;
426 : }
427 0 : }
428 :
429 : // mBreakType value
430 : // Break information is applied *before* the line if the line is a block,
431 : // or *after* the line if the line is an inline. Confusing, I know, but
432 : // using different names should help.
433 : bool HasBreakBefore() const {
434 : return IsBlock() && NS_STYLE_CLEAR_NONE != mFlags.mBreakType;
435 : }
436 0 : void SetBreakTypeBefore(PRUint8 aBreakType) {
437 0 : NS_ASSERTION(IsBlock(), "Only blocks have break-before");
438 0 : NS_ASSERTION(aBreakType <= NS_STYLE_CLEAR_LEFT_AND_RIGHT,
439 : "Only float break types are allowed before a line");
440 0 : mFlags.mBreakType = aBreakType;
441 0 : }
442 0 : PRUint8 GetBreakTypeBefore() const {
443 0 : return IsBlock() ? mFlags.mBreakType : NS_STYLE_CLEAR_NONE;
444 : }
445 :
446 0 : bool HasBreakAfter() const {
447 0 : return !IsBlock() && NS_STYLE_CLEAR_NONE != mFlags.mBreakType;
448 : }
449 0 : void SetBreakTypeAfter(PRUint8 aBreakType) {
450 0 : NS_ASSERTION(!IsBlock(), "Only inlines have break-after");
451 0 : NS_ASSERTION(aBreakType <= LINE_MAX_BREAK_TYPE, "bad break type");
452 0 : mFlags.mBreakType = aBreakType;
453 0 : }
454 0 : bool HasFloatBreakAfter() const {
455 0 : return !IsBlock() && (NS_STYLE_CLEAR_LEFT == mFlags.mBreakType ||
456 : NS_STYLE_CLEAR_RIGHT == mFlags.mBreakType ||
457 0 : NS_STYLE_CLEAR_LEFT_AND_RIGHT == mFlags.mBreakType);
458 : }
459 0 : PRUint8 GetBreakTypeAfter() const {
460 0 : return !IsBlock() ? mFlags.mBreakType : NS_STYLE_CLEAR_NONE;
461 : }
462 :
463 : // mCarriedOutBottomMargin value
464 : nsCollapsingMargin GetCarriedOutBottomMargin() const;
465 : // Returns true if the margin changed
466 : bool SetCarriedOutBottomMargin(nsCollapsingMargin aValue);
467 :
468 : // mFloats
469 0 : bool HasFloats() const {
470 0 : return (IsInline() && mInlineData) && mInlineData->mFloats.NotEmpty();
471 : }
472 : nsFloatCache* GetFirstFloat();
473 : void FreeFloats(nsFloatCacheFreeList& aFreeList);
474 : void AppendFloats(nsFloatCacheFreeList& aFreeList);
475 : bool RemoveFloat(nsIFrame* aFrame);
476 :
477 : // Combined area is the area of the line that should influence the
478 : // overflow area of its parent block. The combined area should be
479 : // used for painting-related things, but should never be used for
480 : // layout (except for handling of 'overflow').
481 : void SetOverflowAreas(const nsOverflowAreas& aOverflowAreas);
482 0 : nsRect GetOverflowArea(nsOverflowType aType) {
483 0 : return mData ? mData->mOverflowAreas.Overflow(aType) : mBounds;
484 : }
485 0 : nsOverflowAreas GetOverflowAreas() {
486 0 : if (mData) {
487 0 : return mData->mOverflowAreas;
488 : }
489 0 : return nsOverflowAreas(mBounds, mBounds);
490 : }
491 0 : nsRect GetVisualOverflowArea()
492 0 : { return GetOverflowArea(eVisualOverflow); }
493 0 : nsRect GetScrollableOverflowArea()
494 0 : { return GetOverflowArea(eScrollableOverflow); }
495 :
496 0 : void SlideBy(nscoord aDY) {
497 0 : mBounds.y += aDY;
498 0 : if (mData) {
499 0 : NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
500 0 : mData->mOverflowAreas.Overflow(otype).y += aDY;
501 : }
502 : }
503 0 : }
504 :
505 : /**
506 : * The ascent (distance from top to baseline) of the linebox is the
507 : * ascent of the anonymous inline box (for which we don't actually
508 : * create a frame) that wraps all the consecutive inline children of a
509 : * block.
510 : *
511 : * This is currently unused for block lines.
512 : */
513 0 : nscoord GetAscent() const { return mAscent; }
514 0 : void SetAscent(nscoord aAscent) { mAscent = aAscent; }
515 :
516 0 : nscoord GetHeight() const {
517 0 : return mBounds.height;
518 : }
519 :
520 : static void DeleteLineList(nsPresContext* aPresContext, nsLineList& aLines,
521 : nsIFrame* aDestructRoot);
522 :
523 : // search from end to beginning of [aBegin, aEnd)
524 : // Returns true if it found the line and false if not.
525 : // Moves aEnd as it searches so that aEnd points to the resulting line.
526 : // aLastFrameBeforeEnd is the last frame before aEnd (so if aEnd is
527 : // the end of the line list, it's just the last frame in the frame
528 : // list).
529 : static bool RFindLineContaining(nsIFrame* aFrame,
530 : const nsLineList_iterator& aBegin,
531 : nsLineList_iterator& aEnd,
532 : nsIFrame* aLastFrameBeforeEnd,
533 : PRInt32* aFrameIndexInLine);
534 :
535 : #ifdef DEBUG
536 : char* StateToString(char* aBuf, PRInt32 aBufSize) const;
537 :
538 : void List(FILE* out, PRInt32 aIndent) const;
539 : nsIFrame* LastChild() const;
540 : #endif
541 :
542 : private:
543 : PRInt32 IndexOf(nsIFrame* aFrame) const;
544 : public:
545 :
546 0 : bool Contains(nsIFrame* aFrame) const {
547 0 : return NS_UNLIKELY(mFlags.mHasHashedFrames) ? mFrames->Contains(aFrame)
548 0 : : IndexOf(aFrame) >= 0;
549 : }
550 :
551 : // whether the line box is "logically" empty (just like nsIFrame::IsEmpty)
552 : bool IsEmpty() const;
553 :
554 : // Call this only while in Reflow() for the block the line belongs
555 : // to, only between reflowing the line (or sliding it, if we skip
556 : // reflowing it) and the end of reflowing the block.
557 : bool CachedIsEmpty();
558 :
559 0 : void InvalidateCachedIsEmpty() {
560 0 : mFlags.mEmptyCacheValid = false;
561 0 : }
562 :
563 : // For debugging purposes
564 : bool IsValidCachedIsEmpty() {
565 : return mFlags.mEmptyCacheValid;
566 : }
567 :
568 : #ifdef DEBUG
569 : static PRInt32 GetCtorCount();
570 : #endif
571 :
572 : nsIFrame* mFirstChild;
573 :
574 : nsRect mBounds;
575 :
576 : // mFlags.mHasHashedFrames says which one to use
577 : union {
578 : nsTHashtable< nsPtrHashKey<nsIFrame> >* mFrames;
579 : PRUint32 mChildCount;
580 : };
581 :
582 : struct FlagBits {
583 : PRUint32 mDirty : 1;
584 : PRUint32 mPreviousMarginDirty : 1;
585 : PRUint32 mHasClearance : 1;
586 : PRUint32 mBlock : 1;
587 : PRUint32 mImpactedByFloat : 1;
588 : PRUint32 mLineWrapped: 1;
589 : PRUint32 mInvalidateTextRuns : 1;
590 : PRUint32 mResizeReflowOptimizationDisabled: 1; // default 0 = means that the opt potentially applies to this line. 1 = never skip reflowing this line for a resize reflow
591 : PRUint32 mEmptyCacheValid: 1;
592 : PRUint32 mEmptyCacheState: 1;
593 : // mHasBullet indicates that this is an inline line whose block's
594 : // bullet is adjacent to this line and non-empty.
595 : PRUint32 mHasBullet : 1;
596 : // Indicates that this line *may* have a placeholder for a float
597 : // that was pushed to a later column or page.
598 : PRUint32 mHadFloatPushed : 1;
599 : PRUint32 mHasHashedFrames: 1;
600 : PRUint32 mBreakType : 4;
601 : };
602 :
603 0 : struct ExtraData {
604 0 : ExtraData(const nsRect& aBounds) : mOverflowAreas(aBounds, aBounds) {
605 0 : }
606 : nsOverflowAreas mOverflowAreas;
607 : };
608 :
609 0 : struct ExtraBlockData : public ExtraData {
610 0 : ExtraBlockData(const nsRect& aBounds)
611 : : ExtraData(aBounds),
612 0 : mCarriedOutBottomMargin()
613 : {
614 0 : }
615 : nsCollapsingMargin mCarriedOutBottomMargin;
616 : };
617 :
618 0 : struct ExtraInlineData : public ExtraData {
619 0 : ExtraInlineData(const nsRect& aBounds) : ExtraData(aBounds) {
620 0 : }
621 : nsFloatCacheList mFloats;
622 : };
623 :
624 : protected:
625 : nscoord mAscent; // see |SetAscent| / |GetAscent|
626 : union {
627 : PRUint32 mAllFlags;
628 : FlagBits mFlags;
629 : };
630 :
631 : union {
632 : ExtraData* mData;
633 : ExtraBlockData* mBlockData;
634 : ExtraInlineData* mInlineData;
635 : };
636 :
637 : void Cleanup();
638 : void MaybeFreeData();
639 : };
640 :
641 : /**
642 : * A linked list type where the items in the list must inherit from
643 : * a link type to fuse allocations.
644 : *
645 : * API heavily based on the |list| class in the C++ standard.
646 : */
647 :
648 : class nsLineList_iterator {
649 : public:
650 : friend class nsLineList;
651 : friend class nsLineList_reverse_iterator;
652 : friend class nsLineList_const_iterator;
653 : friend class nsLineList_const_reverse_iterator;
654 :
655 : typedef nsLineList_iterator iterator_self_type;
656 : typedef nsLineList_reverse_iterator iterator_reverse_type;
657 :
658 : typedef nsLineBox& reference;
659 : typedef const nsLineBox& const_reference;
660 :
661 : typedef nsLineBox* pointer;
662 : typedef const nsLineBox* const_pointer;
663 :
664 : typedef PRUint32 size_type;
665 : typedef PRInt32 difference_type;
666 :
667 : typedef nsLineLink link_type;
668 :
669 : #ifdef NS_DEBUG
670 0 : nsLineList_iterator() { memset(&mCurrent, 0xcd, sizeof(mCurrent)); }
671 : #else
672 : // Auto generated default constructor OK.
673 : #endif
674 : // Auto generated copy-constructor OK.
675 :
676 : inline iterator_self_type&
677 : operator=(const iterator_self_type& aOther);
678 : inline iterator_self_type&
679 : operator=(const iterator_reverse_type& aOther);
680 :
681 0 : iterator_self_type& operator++()
682 : {
683 0 : mCurrent = mCurrent->_mNext;
684 0 : return *this;
685 : }
686 :
687 : iterator_self_type operator++(int)
688 : {
689 : iterator_self_type rv(*this);
690 : mCurrent = mCurrent->_mNext;
691 : return rv;
692 : }
693 :
694 0 : iterator_self_type& operator--()
695 : {
696 0 : mCurrent = mCurrent->_mPrev;
697 0 : return *this;
698 : }
699 :
700 0 : iterator_self_type operator--(int)
701 : {
702 0 : iterator_self_type rv(*this);
703 0 : mCurrent = mCurrent->_mPrev;
704 : return rv;
705 : }
706 :
707 : reference operator*()
708 : {
709 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
710 : return *static_cast<pointer>(mCurrent);
711 : }
712 :
713 0 : pointer operator->()
714 : {
715 0 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
716 0 : return static_cast<pointer>(mCurrent);
717 : }
718 :
719 0 : pointer get()
720 : {
721 0 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
722 0 : return static_cast<pointer>(mCurrent);
723 : }
724 :
725 0 : operator pointer()
726 : {
727 0 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
728 0 : return static_cast<pointer>(mCurrent);
729 : }
730 :
731 : const_reference operator*() const
732 : {
733 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
734 : return *static_cast<const_pointer>(mCurrent);
735 : }
736 :
737 0 : const_pointer operator->() const
738 : {
739 0 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
740 0 : return static_cast<const_pointer>(mCurrent);
741 : }
742 :
743 : #ifndef __MWERKS__
744 : operator const_pointer() const
745 : {
746 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
747 : return static_cast<const_pointer>(mCurrent);
748 : }
749 : #endif /* !__MWERKS__ */
750 :
751 0 : iterator_self_type next()
752 : {
753 0 : iterator_self_type copy(*this);
754 0 : return ++copy;
755 : }
756 :
757 : const iterator_self_type next() const
758 : {
759 : iterator_self_type copy(*this);
760 : return ++copy;
761 : }
762 :
763 0 : iterator_self_type prev()
764 : {
765 0 : iterator_self_type copy(*this);
766 0 : return --copy;
767 : }
768 :
769 : const iterator_self_type prev() const
770 : {
771 : iterator_self_type copy(*this);
772 : return --copy;
773 : }
774 :
775 : // Passing by value rather than by reference and reference to const
776 : // to keep AIX happy.
777 : bool operator==(const iterator_self_type aOther) const
778 : {
779 : NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists");
780 : return mCurrent == aOther.mCurrent;
781 : }
782 0 : bool operator!=(const iterator_self_type aOther) const
783 : {
784 0 : NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists");
785 0 : return mCurrent != aOther.mCurrent;
786 : }
787 0 : bool operator==(const iterator_self_type aOther)
788 : {
789 0 : NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists");
790 0 : return mCurrent == aOther.mCurrent;
791 : }
792 0 : bool operator!=(const iterator_self_type aOther)
793 : {
794 0 : NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists");
795 0 : return mCurrent != aOther.mCurrent;
796 : }
797 :
798 : private:
799 : link_type *mCurrent;
800 : #ifdef DEBUG
801 : link_type *mListLink; // the list's link, i.e., the end
802 : #endif
803 : };
804 :
805 : class nsLineList_reverse_iterator {
806 :
807 : public:
808 :
809 : friend class nsLineList;
810 : friend class nsLineList_iterator;
811 : friend class nsLineList_const_iterator;
812 : friend class nsLineList_const_reverse_iterator;
813 :
814 : typedef nsLineList_reverse_iterator iterator_self_type;
815 : typedef nsLineList_iterator iterator_reverse_type;
816 :
817 : typedef nsLineBox& reference;
818 : typedef const nsLineBox& const_reference;
819 :
820 : typedef nsLineBox* pointer;
821 : typedef const nsLineBox* const_pointer;
822 :
823 : typedef PRUint32 size_type;
824 : typedef PRInt32 difference_type;
825 :
826 : typedef nsLineLink link_type;
827 :
828 : #ifdef NS_DEBUG
829 0 : nsLineList_reverse_iterator() { memset(&mCurrent, 0xcd, sizeof(mCurrent)); }
830 : #else
831 : // Auto generated default constructor OK.
832 : #endif
833 : // Auto generated copy-constructor OK.
834 :
835 : inline iterator_self_type&
836 : operator=(const iterator_reverse_type& aOther);
837 : inline iterator_self_type&
838 : operator=(const iterator_self_type& aOther);
839 :
840 0 : iterator_self_type& operator++()
841 : {
842 0 : mCurrent = mCurrent->_mPrev;
843 0 : return *this;
844 : }
845 :
846 : iterator_self_type operator++(int)
847 : {
848 : iterator_self_type rv(*this);
849 : mCurrent = mCurrent->_mPrev;
850 : return rv;
851 : }
852 :
853 : iterator_self_type& operator--()
854 : {
855 : mCurrent = mCurrent->_mNext;
856 : return *this;
857 : }
858 :
859 : iterator_self_type operator--(int)
860 : {
861 : iterator_self_type rv(*this);
862 : mCurrent = mCurrent->_mNext;
863 : return rv;
864 : }
865 :
866 : reference operator*()
867 : {
868 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
869 : return *static_cast<pointer>(mCurrent);
870 : }
871 :
872 0 : pointer operator->()
873 : {
874 0 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
875 0 : return static_cast<pointer>(mCurrent);
876 : }
877 :
878 : pointer get()
879 : {
880 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
881 : return static_cast<pointer>(mCurrent);
882 : }
883 :
884 : operator pointer()
885 : {
886 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
887 : return static_cast<pointer>(mCurrent);
888 : }
889 :
890 : const_reference operator*() const
891 : {
892 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
893 : return *static_cast<const_pointer>(mCurrent);
894 : }
895 :
896 : const_pointer operator->() const
897 : {
898 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
899 : return static_cast<const_pointer>(mCurrent);
900 : }
901 :
902 : #ifndef __MWERKS__
903 : operator const_pointer() const
904 : {
905 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
906 : return static_cast<const_pointer>(mCurrent);
907 : }
908 : #endif /* !__MWERKS__ */
909 :
910 : // Passing by value rather than by reference and reference to const
911 : // to keep AIX happy.
912 : bool operator==(const iterator_self_type aOther) const
913 : {
914 : NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
915 : return mCurrent == aOther.mCurrent;
916 : }
917 : bool operator!=(const iterator_self_type aOther) const
918 : {
919 : NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
920 : return mCurrent != aOther.mCurrent;
921 : }
922 : bool operator==(const iterator_self_type aOther)
923 : {
924 : NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
925 : return mCurrent == aOther.mCurrent;
926 : }
927 0 : bool operator!=(const iterator_self_type aOther)
928 : {
929 0 : NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
930 0 : return mCurrent != aOther.mCurrent;
931 : }
932 :
933 : private:
934 : link_type *mCurrent;
935 : #ifdef DEBUG
936 : link_type *mListLink; // the list's link, i.e., the end
937 : #endif
938 : };
939 :
940 : class nsLineList_const_iterator {
941 : public:
942 :
943 : friend class nsLineList;
944 : friend class nsLineList_iterator;
945 : friend class nsLineList_reverse_iterator;
946 : friend class nsLineList_const_reverse_iterator;
947 :
948 : typedef nsLineList_const_iterator iterator_self_type;
949 : typedef nsLineList_const_reverse_iterator iterator_reverse_type;
950 : typedef nsLineList_iterator iterator_nonconst_type;
951 : typedef nsLineList_reverse_iterator iterator_nonconst_reverse_type;
952 :
953 : typedef nsLineBox& reference;
954 : typedef const nsLineBox& const_reference;
955 :
956 : typedef nsLineBox* pointer;
957 : typedef const nsLineBox* const_pointer;
958 :
959 : typedef PRUint32 size_type;
960 : typedef PRInt32 difference_type;
961 :
962 : typedef nsLineLink link_type;
963 :
964 : #ifdef DEBUG
965 0 : nsLineList_const_iterator() { memset(&mCurrent, 0xcd, sizeof(mCurrent)); }
966 : #else
967 : // Auto generated default constructor OK.
968 : #endif
969 : // Auto generated copy-constructor OK.
970 :
971 : inline iterator_self_type&
972 : operator=(const iterator_nonconst_type& aOther);
973 : inline iterator_self_type&
974 : operator=(const iterator_nonconst_reverse_type& aOther);
975 : inline iterator_self_type&
976 : operator=(const iterator_self_type& aOther);
977 : inline iterator_self_type&
978 : operator=(const iterator_reverse_type& aOther);
979 :
980 0 : iterator_self_type& operator++()
981 : {
982 0 : mCurrent = mCurrent->_mNext;
983 0 : return *this;
984 : }
985 :
986 : iterator_self_type operator++(int)
987 : {
988 : iterator_self_type rv(*this);
989 : mCurrent = mCurrent->_mNext;
990 : return rv;
991 : }
992 :
993 : iterator_self_type& operator--()
994 : {
995 : mCurrent = mCurrent->_mPrev;
996 : return *this;
997 : }
998 :
999 : iterator_self_type operator--(int)
1000 : {
1001 : iterator_self_type rv(*this);
1002 : mCurrent = mCurrent->_mPrev;
1003 : return rv;
1004 : }
1005 :
1006 : const_reference operator*() const
1007 : {
1008 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
1009 : return *static_cast<const_pointer>(mCurrent);
1010 : }
1011 :
1012 0 : const_pointer operator->() const
1013 : {
1014 0 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
1015 0 : return static_cast<const_pointer>(mCurrent);
1016 : }
1017 :
1018 : const_pointer get() const
1019 : {
1020 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
1021 : return static_cast<const_pointer>(mCurrent);
1022 : }
1023 :
1024 : #ifndef __MWERKS__
1025 0 : operator const_pointer() const
1026 : {
1027 0 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
1028 0 : return static_cast<const_pointer>(mCurrent);
1029 : }
1030 : #endif /* !__MWERKS__ */
1031 :
1032 : const iterator_self_type next() const
1033 : {
1034 : iterator_self_type copy(*this);
1035 : return ++copy;
1036 : }
1037 :
1038 : const iterator_self_type prev() const
1039 : {
1040 : iterator_self_type copy(*this);
1041 : return --copy;
1042 : }
1043 :
1044 : // Passing by value rather than by reference and reference to const
1045 : // to keep AIX happy.
1046 : bool operator==(const iterator_self_type aOther) const
1047 : {
1048 : NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
1049 : return mCurrent == aOther.mCurrent;
1050 : }
1051 : bool operator!=(const iterator_self_type aOther) const
1052 : {
1053 : NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
1054 : return mCurrent != aOther.mCurrent;
1055 : }
1056 : bool operator==(const iterator_self_type aOther)
1057 : {
1058 : NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
1059 : return mCurrent == aOther.mCurrent;
1060 : }
1061 0 : bool operator!=(const iterator_self_type aOther)
1062 : {
1063 0 : NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
1064 0 : return mCurrent != aOther.mCurrent;
1065 : }
1066 :
1067 : private:
1068 : const link_type *mCurrent;
1069 : #ifdef DEBUG
1070 : const link_type *mListLink; // the list's link, i.e., the end
1071 : #endif
1072 : };
1073 :
1074 : class nsLineList_const_reverse_iterator {
1075 : public:
1076 :
1077 : friend class nsLineList;
1078 : friend class nsLineList_iterator;
1079 : friend class nsLineList_reverse_iterator;
1080 : friend class nsLineList_const_iterator;
1081 :
1082 : typedef nsLineList_const_reverse_iterator iterator_self_type;
1083 : typedef nsLineList_const_iterator iterator_reverse_type;
1084 : typedef nsLineList_iterator iterator_nonconst_reverse_type;
1085 : typedef nsLineList_reverse_iterator iterator_nonconst_type;
1086 :
1087 : typedef nsLineBox& reference;
1088 : typedef const nsLineBox& const_reference;
1089 :
1090 : typedef nsLineBox* pointer;
1091 : typedef const nsLineBox* const_pointer;
1092 :
1093 : typedef PRUint32 size_type;
1094 : typedef PRInt32 difference_type;
1095 :
1096 : typedef nsLineLink link_type;
1097 :
1098 : #ifdef DEBUG
1099 0 : nsLineList_const_reverse_iterator() { memset(&mCurrent, 0xcd, sizeof(mCurrent)); }
1100 : #else
1101 : // Auto generated default constructor OK.
1102 : #endif
1103 : // Auto generated copy-constructor OK.
1104 :
1105 : inline iterator_self_type&
1106 : operator=(const iterator_nonconst_type& aOther);
1107 : inline iterator_self_type&
1108 : operator=(const iterator_nonconst_reverse_type& aOther);
1109 : inline iterator_self_type&
1110 : operator=(const iterator_self_type& aOther);
1111 : inline iterator_self_type&
1112 : operator=(const iterator_reverse_type& aOther);
1113 :
1114 0 : iterator_self_type& operator++()
1115 : {
1116 0 : mCurrent = mCurrent->_mPrev;
1117 0 : return *this;
1118 : }
1119 :
1120 : iterator_self_type operator++(int)
1121 : {
1122 : iterator_self_type rv(*this);
1123 : mCurrent = mCurrent->_mPrev;
1124 : return rv;
1125 : }
1126 :
1127 : iterator_self_type& operator--()
1128 : {
1129 : mCurrent = mCurrent->_mNext;
1130 : return *this;
1131 : }
1132 :
1133 : iterator_self_type operator--(int)
1134 : {
1135 : iterator_self_type rv(*this);
1136 : mCurrent = mCurrent->_mNext;
1137 : return rv;
1138 : }
1139 :
1140 : const_reference operator*() const
1141 : {
1142 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
1143 : return *static_cast<const_pointer>(mCurrent);
1144 : }
1145 :
1146 0 : const_pointer operator->() const
1147 : {
1148 0 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
1149 0 : return static_cast<const_pointer>(mCurrent);
1150 : }
1151 :
1152 : const_pointer get() const
1153 : {
1154 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
1155 : return static_cast<const_pointer>(mCurrent);
1156 : }
1157 :
1158 : #ifndef __MWERKS__
1159 : operator const_pointer() const
1160 : {
1161 : NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
1162 : return static_cast<const_pointer>(mCurrent);
1163 : }
1164 : #endif /* !__MWERKS__ */
1165 :
1166 : // Passing by value rather than by reference and reference to const
1167 : // to keep AIX happy.
1168 : bool operator==(const iterator_self_type aOther) const
1169 : {
1170 : NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
1171 : return mCurrent == aOther.mCurrent;
1172 : }
1173 : bool operator!=(const iterator_self_type aOther) const
1174 : {
1175 : NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
1176 : return mCurrent != aOther.mCurrent;
1177 : }
1178 : bool operator==(const iterator_self_type aOther)
1179 : {
1180 : NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
1181 : return mCurrent == aOther.mCurrent;
1182 : }
1183 0 : bool operator!=(const iterator_self_type aOther)
1184 : {
1185 0 : NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
1186 0 : return mCurrent != aOther.mCurrent;
1187 : }
1188 :
1189 : //private:
1190 : const link_type *mCurrent;
1191 : #ifdef DEBUG
1192 : const link_type *mListLink; // the list's link, i.e., the end
1193 : #endif
1194 : };
1195 :
1196 : class nsLineList {
1197 :
1198 : public:
1199 :
1200 : friend class nsLineList_iterator;
1201 : friend class nsLineList_reverse_iterator;
1202 : friend class nsLineList_const_iterator;
1203 : friend class nsLineList_const_reverse_iterator;
1204 :
1205 : typedef PRUint32 size_type;
1206 : typedef PRInt32 difference_type;
1207 :
1208 : typedef nsLineLink link_type;
1209 :
1210 : private:
1211 : link_type mLink;
1212 :
1213 : public:
1214 : typedef nsLineList self_type;
1215 :
1216 : typedef nsLineBox& reference;
1217 : typedef const nsLineBox& const_reference;
1218 :
1219 : typedef nsLineBox* pointer;
1220 : typedef const nsLineBox* const_pointer;
1221 :
1222 : typedef nsLineList_iterator iterator;
1223 : typedef nsLineList_reverse_iterator reverse_iterator;
1224 : typedef nsLineList_const_iterator const_iterator;
1225 : typedef nsLineList_const_reverse_iterator const_reverse_iterator;
1226 :
1227 0 : nsLineList()
1228 : {
1229 0 : MOZ_COUNT_CTOR(nsLineList);
1230 0 : clear();
1231 0 : }
1232 :
1233 0 : ~nsLineList()
1234 : {
1235 0 : MOZ_COUNT_DTOR(nsLineList);
1236 0 : }
1237 :
1238 0 : const_iterator begin() const
1239 : {
1240 0 : const_iterator rv;
1241 0 : rv.mCurrent = mLink._mNext;
1242 : #ifdef DEBUG
1243 0 : rv.mListLink = &mLink;
1244 : #endif
1245 : return rv;
1246 : }
1247 :
1248 0 : iterator begin()
1249 : {
1250 0 : iterator rv;
1251 0 : rv.mCurrent = mLink._mNext;
1252 : #ifdef DEBUG
1253 0 : rv.mListLink = &mLink;
1254 : #endif
1255 : return rv;
1256 : }
1257 :
1258 0 : iterator begin(nsLineBox* aLine)
1259 : {
1260 0 : iterator rv;
1261 0 : rv.mCurrent = aLine;
1262 : #ifdef DEBUG
1263 0 : rv.mListLink = &mLink;
1264 : #endif
1265 : return rv;
1266 : }
1267 :
1268 0 : const_iterator end() const
1269 : {
1270 0 : const_iterator rv;
1271 0 : rv.mCurrent = &mLink;
1272 : #ifdef DEBUG
1273 0 : rv.mListLink = &mLink;
1274 : #endif
1275 : return rv;
1276 : }
1277 :
1278 0 : iterator end()
1279 : {
1280 0 : iterator rv;
1281 0 : rv.mCurrent = &mLink;
1282 : #ifdef DEBUG
1283 0 : rv.mListLink = &mLink;
1284 : #endif
1285 : return rv;
1286 : }
1287 :
1288 0 : const_reverse_iterator rbegin() const
1289 : {
1290 0 : const_reverse_iterator rv;
1291 0 : rv.mCurrent = mLink._mPrev;
1292 : #ifdef DEBUG
1293 0 : rv.mListLink = &mLink;
1294 : #endif
1295 : return rv;
1296 : }
1297 :
1298 : reverse_iterator rbegin()
1299 : {
1300 : reverse_iterator rv;
1301 : rv.mCurrent = mLink._mPrev;
1302 : #ifdef DEBUG
1303 : rv.mListLink = &mLink;
1304 : #endif
1305 : return rv;
1306 : }
1307 :
1308 0 : reverse_iterator rbegin(nsLineBox* aLine)
1309 : {
1310 0 : reverse_iterator rv;
1311 0 : rv.mCurrent = aLine;
1312 : #ifdef DEBUG
1313 0 : rv.mListLink = &mLink;
1314 : #endif
1315 : return rv;
1316 : }
1317 :
1318 0 : const_reverse_iterator rend() const
1319 : {
1320 0 : const_reverse_iterator rv;
1321 0 : rv.mCurrent = &mLink;
1322 : #ifdef DEBUG
1323 0 : rv.mListLink = &mLink;
1324 : #endif
1325 : return rv;
1326 : }
1327 :
1328 0 : reverse_iterator rend()
1329 : {
1330 0 : reverse_iterator rv;
1331 0 : rv.mCurrent = &mLink;
1332 : #ifdef DEBUG
1333 0 : rv.mListLink = &mLink;
1334 : #endif
1335 : return rv;
1336 : }
1337 :
1338 0 : bool empty() const
1339 : {
1340 0 : return mLink._mNext == &mLink;
1341 : }
1342 :
1343 : // NOTE: O(N).
1344 0 : size_type size() const
1345 : {
1346 0 : size_type count = 0;
1347 0 : for (const link_type *cur = mLink._mNext;
1348 : cur != &mLink;
1349 : cur = cur->_mNext)
1350 : {
1351 0 : ++count;
1352 : }
1353 0 : return count;
1354 : }
1355 :
1356 0 : pointer front()
1357 : {
1358 0 : NS_ASSERTION(!empty(), "no element to return");
1359 0 : return static_cast<pointer>(mLink._mNext);
1360 : }
1361 :
1362 0 : const_pointer front() const
1363 : {
1364 0 : NS_ASSERTION(!empty(), "no element to return");
1365 0 : return static_cast<const_pointer>(mLink._mNext);
1366 : }
1367 :
1368 0 : pointer back()
1369 : {
1370 0 : NS_ASSERTION(!empty(), "no element to return");
1371 0 : return static_cast<pointer>(mLink._mPrev);
1372 : }
1373 :
1374 : const_pointer back() const
1375 : {
1376 : NS_ASSERTION(!empty(), "no element to return");
1377 : return static_cast<const_pointer>(mLink._mPrev);
1378 : }
1379 :
1380 0 : void push_front(pointer aNew)
1381 : {
1382 0 : aNew->_mNext = mLink._mNext;
1383 0 : mLink._mNext->_mPrev = aNew;
1384 0 : aNew->_mPrev = &mLink;
1385 0 : mLink._mNext = aNew;
1386 0 : }
1387 :
1388 0 : void pop_front()
1389 : // NOTE: leaves dangling next/prev pointers
1390 : {
1391 0 : NS_ASSERTION(!empty(), "no element to pop");
1392 0 : link_type *newFirst = mLink._mNext->_mNext;
1393 0 : newFirst->_mPrev = &mLink;
1394 : // mLink._mNext->_mNext = nsnull;
1395 : // mLink._mNext->_mPrev = nsnull;
1396 0 : mLink._mNext = newFirst;
1397 0 : }
1398 :
1399 : void push_back(pointer aNew)
1400 : {
1401 : aNew->_mPrev = mLink._mPrev;
1402 : mLink._mPrev->_mNext = aNew;
1403 : aNew->_mNext = &mLink;
1404 : mLink._mPrev = aNew;
1405 : }
1406 :
1407 : void pop_back()
1408 : // NOTE: leaves dangling next/prev pointers
1409 : {
1410 : NS_ASSERTION(!empty(), "no element to pop");
1411 : link_type *newLast = mLink._mPrev->_mPrev;
1412 : newLast->_mNext = &mLink;
1413 : // mLink._mPrev->_mPrev = nsnull;
1414 : // mLink._mPrev->_mNext = nsnull;
1415 : mLink._mPrev = newLast;
1416 : }
1417 :
1418 : // inserts x before position
1419 0 : iterator before_insert(iterator position, pointer x)
1420 : {
1421 : // use |mCurrent| to prevent DEBUG_PASS_END assertions
1422 0 : x->_mPrev = position.mCurrent->_mPrev;
1423 0 : x->_mNext = position.mCurrent;
1424 0 : position.mCurrent->_mPrev->_mNext = x;
1425 0 : position.mCurrent->_mPrev = x;
1426 0 : return --position;
1427 : }
1428 :
1429 : // inserts x after position
1430 0 : iterator after_insert(iterator position, pointer x)
1431 : {
1432 : // use |mCurrent| to prevent DEBUG_PASS_END assertions
1433 0 : x->_mNext = position.mCurrent->_mNext;
1434 0 : x->_mPrev = position.mCurrent;
1435 0 : position.mCurrent->_mNext->_mPrev = x;
1436 0 : position.mCurrent->_mNext = x;
1437 0 : return ++position;
1438 : }
1439 :
1440 : // returns iterator pointing to after the element
1441 0 : iterator erase(iterator position)
1442 : // NOTE: leaves dangling next/prev pointers
1443 : {
1444 0 : position->_mPrev->_mNext = position->_mNext;
1445 0 : position->_mNext->_mPrev = position->_mPrev;
1446 0 : return ++position;
1447 : }
1448 :
1449 : void swap(self_type& y)
1450 : {
1451 : link_type tmp(y.mLink);
1452 : y.mLink = mLink;
1453 : mLink = tmp;
1454 :
1455 : if (!empty()) {
1456 : mLink._mNext->_mPrev = &mLink;
1457 : mLink._mPrev->_mNext = &mLink;
1458 : }
1459 :
1460 : if (!y.empty()) {
1461 : y.mLink._mNext->_mPrev = &y.mLink;
1462 : y.mLink._mPrev->_mNext = &y.mLink;
1463 : }
1464 : }
1465 :
1466 0 : void clear()
1467 : // NOTE: leaves dangling next/prev pointers
1468 : {
1469 0 : mLink._mNext = &mLink;
1470 0 : mLink._mPrev = &mLink;
1471 0 : }
1472 :
1473 : // inserts the conts of x before position and makes x empty
1474 0 : void splice(iterator position, self_type& x)
1475 : {
1476 : // use |mCurrent| to prevent DEBUG_PASS_END assertions
1477 0 : position.mCurrent->_mPrev->_mNext = x.mLink._mNext;
1478 0 : x.mLink._mNext->_mPrev = position.mCurrent->_mPrev;
1479 0 : x.mLink._mPrev->_mNext = position.mCurrent;
1480 0 : position.mCurrent->_mPrev = x.mLink._mPrev;
1481 0 : x.clear();
1482 0 : }
1483 :
1484 : // Inserts element *i from list x before position and removes
1485 : // it from x.
1486 : void splice(iterator position, self_type& x, iterator i)
1487 : {
1488 : NS_ASSERTION(!x.empty(), "Can't insert from empty list.");
1489 : NS_ASSERTION(position != i && position.mCurrent != i->_mNext,
1490 : "We don't check for this case.");
1491 :
1492 : // remove from |x|
1493 : i->_mPrev->_mNext = i->_mNext;
1494 : i->_mNext->_mPrev = i->_mPrev;
1495 :
1496 : // use |mCurrent| to prevent DEBUG_PASS_END assertions
1497 : // link into |this|, before-side
1498 : i->_mPrev = position.mCurrent->_mPrev;
1499 : position.mCurrent->_mPrev->_mNext = i.get();
1500 :
1501 : // link into |this|, after-side
1502 : i->_mNext = position.mCurrent;
1503 : position.mCurrent->_mPrev = i.get();
1504 : }
1505 :
1506 : // Inserts elements in [|first|, |last|), which are in |x|,
1507 : // into |this| before |position| and removes them from |x|.
1508 0 : void splice(iterator position, self_type& x, iterator first,
1509 : iterator last)
1510 : {
1511 0 : NS_ASSERTION(!x.empty(), "Can't insert from empty list.");
1512 :
1513 0 : if (first == last)
1514 0 : return;
1515 :
1516 0 : --last; // so we now want to move [first, last]
1517 : // remove from |x|
1518 0 : first->_mPrev->_mNext = last->_mNext;
1519 0 : last->_mNext->_mPrev = first->_mPrev;
1520 :
1521 : // use |mCurrent| to prevent DEBUG_PASS_END assertions
1522 : // link into |this|, before-side
1523 0 : first->_mPrev = position.mCurrent->_mPrev;
1524 0 : position.mCurrent->_mPrev->_mNext = first.get();
1525 :
1526 : // link into |this|, after-side
1527 0 : last->_mNext = position.mCurrent;
1528 0 : position.mCurrent->_mPrev = last.get();
1529 : }
1530 :
1531 : };
1532 :
1533 :
1534 : // Many of these implementations of operator= don't work yet. I don't
1535 : // know why.
1536 :
1537 : #ifdef DEBUG
1538 :
1539 : // NOTE: ASSIGN_FROM is meant to be used *only* as the entire body
1540 : // of a function and therefore lacks PR_{BEGIN,END}_MACRO
1541 : #define ASSIGN_FROM(other_) \
1542 : mCurrent = other_.mCurrent; \
1543 : mListLink = other_.mListLink; \
1544 : return *this;
1545 :
1546 : #else /* !NS_LINELIST_DEBUG_PASS_END */
1547 :
1548 : #define ASSIGN_FROM(other_) \
1549 : mCurrent = other_.mCurrent; \
1550 : return *this;
1551 :
1552 : #endif /* !NS_LINELIST_DEBUG_PASS_END */
1553 :
1554 : inline
1555 : nsLineList_iterator&
1556 0 : nsLineList_iterator::operator=(const nsLineList_iterator& aOther)
1557 : {
1558 0 : ASSIGN_FROM(aOther)
1559 : }
1560 :
1561 : inline
1562 : nsLineList_iterator&
1563 0 : nsLineList_iterator::operator=(const nsLineList_reverse_iterator& aOther)
1564 : {
1565 0 : ASSIGN_FROM(aOther)
1566 : }
1567 :
1568 : inline
1569 : nsLineList_reverse_iterator&
1570 : nsLineList_reverse_iterator::operator=(const nsLineList_iterator& aOther)
1571 : {
1572 : ASSIGN_FROM(aOther)
1573 : }
1574 :
1575 : inline
1576 : nsLineList_reverse_iterator&
1577 : nsLineList_reverse_iterator::operator=(const nsLineList_reverse_iterator& aOther)
1578 : {
1579 : ASSIGN_FROM(aOther)
1580 : }
1581 :
1582 : inline
1583 : nsLineList_const_iterator&
1584 : nsLineList_const_iterator::operator=(const nsLineList_iterator& aOther)
1585 : {
1586 : ASSIGN_FROM(aOther)
1587 : }
1588 :
1589 : inline
1590 : nsLineList_const_iterator&
1591 : nsLineList_const_iterator::operator=(const nsLineList_reverse_iterator& aOther)
1592 : {
1593 : ASSIGN_FROM(aOther)
1594 : }
1595 :
1596 : inline
1597 : nsLineList_const_iterator&
1598 : nsLineList_const_iterator::operator=(const nsLineList_const_iterator& aOther)
1599 : {
1600 : ASSIGN_FROM(aOther)
1601 : }
1602 :
1603 : inline
1604 : nsLineList_const_iterator&
1605 : nsLineList_const_iterator::operator=(const nsLineList_const_reverse_iterator& aOther)
1606 : {
1607 : ASSIGN_FROM(aOther)
1608 : }
1609 :
1610 : inline
1611 : nsLineList_const_reverse_iterator&
1612 : nsLineList_const_reverse_iterator::operator=(const nsLineList_iterator& aOther)
1613 : {
1614 : ASSIGN_FROM(aOther)
1615 : }
1616 :
1617 : inline
1618 : nsLineList_const_reverse_iterator&
1619 : nsLineList_const_reverse_iterator::operator=(const nsLineList_reverse_iterator& aOther)
1620 : {
1621 : ASSIGN_FROM(aOther)
1622 : }
1623 :
1624 : inline
1625 : nsLineList_const_reverse_iterator&
1626 : nsLineList_const_reverse_iterator::operator=(const nsLineList_const_iterator& aOther)
1627 : {
1628 : ASSIGN_FROM(aOther)
1629 : }
1630 :
1631 : inline
1632 : nsLineList_const_reverse_iterator&
1633 : nsLineList_const_reverse_iterator::operator=(const nsLineList_const_reverse_iterator& aOther)
1634 : {
1635 : ASSIGN_FROM(aOther)
1636 : }
1637 :
1638 :
1639 : //----------------------------------------------------------------------
1640 :
1641 : class nsLineIterator MOZ_FINAL : public nsILineIterator
1642 : {
1643 : public:
1644 : nsLineIterator();
1645 : ~nsLineIterator();
1646 :
1647 : virtual void DisposeLineIterator();
1648 :
1649 : virtual PRInt32 GetNumLines();
1650 : virtual bool GetDirection();
1651 : NS_IMETHOD GetLine(PRInt32 aLineNumber,
1652 : nsIFrame** aFirstFrameOnLine,
1653 : PRInt32* aNumFramesOnLine,
1654 : nsRect& aLineBounds,
1655 : PRUint32* aLineFlags);
1656 : virtual PRInt32 FindLineContaining(nsIFrame* aFrame, PRInt32 aStartLine = 0);
1657 : NS_IMETHOD FindFrameAt(PRInt32 aLineNumber,
1658 : nscoord aX,
1659 : nsIFrame** aFrameFound,
1660 : bool* aXIsBeforeFirstFrame,
1661 : bool* aXIsAfterLastFrame);
1662 :
1663 : NS_IMETHOD GetNextSiblingOnLine(nsIFrame*& aFrame, PRInt32 aLineNumber);
1664 : #ifdef IBMBIDI
1665 : NS_IMETHOD CheckLineOrder(PRInt32 aLine,
1666 : bool *aIsReordered,
1667 : nsIFrame **aFirstVisual,
1668 : nsIFrame **aLastVisual);
1669 : #endif
1670 : nsresult Init(nsLineList& aLines, bool aRightToLeft);
1671 :
1672 : private:
1673 : nsLineBox* PrevLine() {
1674 : if (0 == mIndex) {
1675 : return nsnull;
1676 : }
1677 : return mLines[--mIndex];
1678 : }
1679 :
1680 : nsLineBox* NextLine() {
1681 : if (mIndex >= mNumLines - 1) {
1682 : return nsnull;
1683 : }
1684 : return mLines[++mIndex];
1685 : }
1686 :
1687 : nsLineBox* LineAt(PRInt32 aIndex) {
1688 : if ((aIndex < 0) || (aIndex >= mNumLines)) {
1689 : return nsnull;
1690 : }
1691 : return mLines[aIndex];
1692 : }
1693 :
1694 : nsLineBox** mLines;
1695 : PRInt32 mIndex;
1696 : PRInt32 mNumLines;
1697 : bool mRightToLeft;
1698 : };
1699 :
1700 : #endif /* nsLineBox_h___ */
|