Back to index

lightning-sunbird  0.9+nobinonly
nsLineBox.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 // vim:cindent:ts=2:et:sw=2:
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is Mozilla Communicator client code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   L. David Baron <dbaron@dbaron.org>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 #ifndef nsLineBox_h___
00040 #define nsLineBox_h___
00041 
00042 #include "nsVoidArray.h"
00043 #include "nsPlaceholderFrame.h"
00044 #include "nsILineIterator.h"
00045 
00046 class nsSpaceManager;
00047 class nsLineBox;
00048 class nsFloatCache;
00049 class nsFloatCacheList;
00050 class nsFloatCacheFreeList;
00051 
00052 // State cached after reflowing a float. This state is used during
00053 // incremental reflow when we avoid reflowing a float.
00054 class nsFloatCache {
00055 public:
00056   nsFloatCache();
00057 #ifdef NS_BUILD_REFCNT_LOGGING
00058   ~nsFloatCache();
00059 #else
00060   ~nsFloatCache() { }
00061 #endif
00062 
00063   nsFloatCache* Next() const { return mNext; }
00064 
00065   nsPlaceholderFrame* mPlaceholder;     // nsPlaceholderFrame
00066 
00067   // This will be true if the float was placed on the current line
00068   // instead of below the current line.
00069   PRBool mIsCurrentLineFloat;
00070 
00071   nsMargin mMargins;                    // computed margins
00072 
00073   nsMargin mOffsets;                    // computed offsets (relative pos)
00074 
00075   // Region in the spacemanager impacted by this float; the
00076   // coordinates are relative to the containing block frame. The
00077   // region includes the margins around the float, but doesn't
00078   // include the relative offsets.
00079   nsRect mRegion;
00080 
00081   // Combined area for the float. This will not include the margins
00082   // for the float. Like mRegion, the coordinates are relative to
00083   // the containing block frame.
00084   nsRect mCombinedArea;
00085 
00086   // The float's max-element-width.
00087   nscoord mMaxElementWidth;
00088 
00089 protected:
00090   nsFloatCache* mNext;
00091 
00092   friend class nsFloatCacheList;
00093   friend class nsFloatCacheFreeList;
00094 };
00095 
00096 //----------------------------------------
00097 
00098 class nsFloatCacheList {
00099 public:
00100   nsFloatCacheList() : mHead(nsnull) { }
00101   ~nsFloatCacheList();
00102 
00103   PRBool IsEmpty() const {
00104     return nsnull == mHead;
00105   }
00106 
00107   PRBool NotEmpty() const {
00108     return nsnull != mHead;
00109   }
00110 
00111   nsFloatCache* Head() const {
00112     return mHead;
00113   }
00114 
00115   nsFloatCache* Tail() const;
00116 
00117   nsFloatCache* Find(nsIFrame* aOutOfFlowFrame);
00118 
00119   void Remove(nsFloatCache* aElement);
00120 
00121   // Steal away aList's nsFloatCache objects and put them in this
00122   // list.  aList must not be empty.
00123   void Append(nsFloatCacheFreeList& aList);
00124 
00125 protected:
00126   nsFloatCache* mHead;
00127 
00128   friend class nsFloatCacheFreeList;
00129 };
00130 
00131 //---------------------------------------
00132 
00133 class nsFloatCacheFreeList : public nsFloatCacheList {
00134 public:
00135   nsFloatCacheFreeList() : mTail(nsnull) { }
00136   ~nsFloatCacheFreeList() { }
00137 
00138   // Steal away aList's nsFloatCache objects and put them on this
00139   // free-list.  aList must not be empty.
00140   void Append(nsFloatCacheList& aList);
00141 
00142   void Append(nsFloatCache* aFloatCache);
00143 
00144   // Allocate a new nsFloatCache object
00145   nsFloatCache* Alloc();
00146 
00147 protected:
00148   nsFloatCache* mTail;
00149 
00150   friend class nsFloatCacheList;
00151 };
00152 
00153 //----------------------------------------------------------------------
00154 
00155 #define LINE_MAX_BREAK_TYPE  ((1 << 4) - 1)
00156 #define LINE_MAX_CHILD_COUNT ((1 << 20) - 1)
00157 
00158 #if NS_STYLE_CLEAR_LAST_VALUE > 15
00159 need to rearrange the mBits bitfield;
00160 #endif
00161 
00162 // Funtion to create a line box
00163 nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame,
00164                          PRInt32 aCount, PRBool aIsBlock);
00165 
00166 class nsLineList;
00167 
00168 // don't use the following names outside of this file.  Instead, use
00169 // nsLineList::iterator, etc.  These are just here to allow them to
00170 // be specified as parameters to methods of nsLineBox.
00171 class nsLineList_iterator;
00172 class nsLineList_const_iterator;
00173 class nsLineList_reverse_iterator;
00174 class nsLineList_const_reverse_iterator;
00175 
00183 class nsLineLink {
00184 
00185   public:
00186     friend class nsLineList;
00187     friend class nsLineList_iterator;
00188     friend class nsLineList_reverse_iterator;
00189     friend class nsLineList_const_iterator;
00190     friend class nsLineList_const_reverse_iterator;
00191 
00192   private:
00193     nsLineLink *_mNext; // or head
00194     nsLineLink *_mPrev; // or tail
00195 
00196 };
00197 
00198 
00204 class nsLineBox : public nsLineLink {
00205 private:
00206   nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRBool aIsBlock);
00207   ~nsLineBox();
00208   
00209   // Overloaded new operator. Uses an arena (which comes from the presShell)
00210   // to perform the allocation.
00211   void* operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW;
00212   void operator delete(void* aPtr, size_t sz);
00213 
00214 public:
00215   // Use these two functions to allocate and destroy line boxes
00216   friend nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame,
00217                                   PRInt32 aCount, PRBool aIsBlock);
00218 
00219   void Destroy(nsIPresShell* aPresShell);
00220 
00221   // mBlock bit
00222   PRBool IsBlock() const {
00223     return mFlags.mBlock;
00224   }
00225   PRBool IsInline() const {
00226     return 0 == mFlags.mBlock;
00227   }
00228 
00229   // mDirty bit
00230   void MarkDirty() {
00231     mFlags.mDirty = 1;
00232   }
00233   void ClearDirty() {
00234     mFlags.mDirty = 0;
00235   }
00236   PRBool IsDirty() const {
00237     return mFlags.mDirty;
00238   }
00239 
00240   // mPreviousMarginDirty bit
00241   void MarkPreviousMarginDirty() {
00242     mFlags.mPreviousMarginDirty = 1;
00243   }
00244   void ClearPreviousMarginDirty() {
00245     mFlags.mPreviousMarginDirty = 0;
00246   }
00247   PRBool IsPreviousMarginDirty() const {
00248     return mFlags.mPreviousMarginDirty;
00249   }
00250 
00251   // mHasClearance bit
00252   void SetHasClearance() {
00253     mFlags.mHasClearance = 1;
00254   }
00255   void ClearHasClearance() {
00256     mFlags.mHasClearance = 0;
00257   }
00258   PRBool HasClearance() const {
00259     return mFlags.mHasClearance;
00260   }
00261 
00262   // mImpactedByFloat bit
00263   void SetLineIsImpactedByFloat(PRBool aValue) {
00264     NS_ASSERTION((PR_FALSE==aValue || PR_TRUE==aValue), "somebody is playing fast and loose with bools and bits!");
00265     mFlags.mImpactedByFloat = aValue;
00266   }
00267   PRBool IsImpactedByFloat() const {
00268     return mFlags.mImpactedByFloat;
00269   }
00270 
00271   // mHasPercentageChild bit
00272   void SetHasPercentageChild(PRBool aOn) {
00273     NS_ASSERTION((PR_FALSE==aOn || PR_TRUE==aOn), "somebody is playing fast and loose with bools and bits!");
00274     mFlags.mHasPercentageChild = aOn;
00275   }
00276   PRBool HasPercentageChild() const {
00277     return mFlags.mHasPercentageChild;
00278   }
00279 
00280   // mLineWrapped bit
00281   void SetLineWrapped(PRBool aOn) {
00282     NS_ASSERTION((PR_FALSE==aOn || PR_TRUE==aOn), "somebody is playing fast and loose with bools and bits!");
00283     mFlags.mLineWrapped = aOn;
00284   }
00285   PRBool IsLineWrapped() const {
00286     return mFlags.mLineWrapped;
00287   }
00288 
00289   // mResizeReflowOptimizationDisabled bit
00290   void DisableResizeReflowOptimization() {
00291     mFlags.mResizeReflowOptimizationDisabled = PR_TRUE;
00292   }
00293   void EnableResizeReflowOptimization() {
00294     mFlags.mResizeReflowOptimizationDisabled = PR_FALSE;
00295   }
00296   PRBool ResizeReflowOptimizationDisabled() const {
00297     return mFlags.mResizeReflowOptimizationDisabled;
00298   }
00299   
00300   // mChildCount value
00301   PRInt32 GetChildCount() const {
00302     return (PRInt32) mFlags.mChildCount;
00303   }
00304   void SetChildCount(PRInt32 aNewCount) {
00305     if (aNewCount < 0) {
00306       NS_WARNING("negative child count");
00307       aNewCount = 0;
00308     }
00309     if (aNewCount > LINE_MAX_CHILD_COUNT) {
00310       aNewCount = LINE_MAX_CHILD_COUNT;
00311     }
00312     mFlags.mChildCount = aNewCount;
00313   }
00314 
00315   // mBreakType value
00316   // Break information is applied *before* the line if the line is a block,
00317   // or *after* the line if the line is an inline. Confusing, I know, but
00318   // using different names should help.
00319   PRBool HasBreakBefore() const {
00320     return IsBlock() && NS_STYLE_CLEAR_NONE != mFlags.mBreakType;
00321   }
00322   void SetBreakTypeBefore(PRUint8 aBreakType) {
00323     NS_ASSERTION(IsBlock(), "Only blocks have break-before");
00324     NS_ASSERTION(aBreakType <= NS_STYLE_CLEAR_LEFT_AND_RIGHT,
00325                  "Only float break types are allowed before a line");
00326     mFlags.mBreakType = aBreakType;
00327   }
00328   PRUint8 GetBreakTypeBefore() const {
00329     return IsBlock() ? mFlags.mBreakType : NS_STYLE_CLEAR_NONE;
00330   }
00331 
00332   PRBool HasBreakAfter() const {
00333     return !IsBlock() && NS_STYLE_CLEAR_NONE != mFlags.mBreakType;
00334   }
00335   void SetBreakTypeAfter(PRUint8 aBreakType) {
00336     NS_ASSERTION(!IsBlock(), "Only inlines have break-after");
00337     NS_ASSERTION(aBreakType <= LINE_MAX_BREAK_TYPE, "bad break type");
00338     mFlags.mBreakType = aBreakType;
00339   }
00340   PRBool HasFloatBreakAfter() const {
00341     return !IsBlock() && (NS_STYLE_CLEAR_LEFT == mFlags.mBreakType ||
00342                           NS_STYLE_CLEAR_RIGHT == mFlags.mBreakType ||
00343                           NS_STYLE_CLEAR_LEFT_AND_RIGHT == mFlags.mBreakType);
00344   }
00345   PRUint8 GetBreakTypeAfter() const {
00346     return !IsBlock() ? mFlags.mBreakType : NS_STYLE_CLEAR_NONE;
00347   }
00348 
00349   // mCarriedOutBottomMargin value
00350   nsCollapsingMargin GetCarriedOutBottomMargin() const;
00351   // Returns PR_TRUE if the margin changed
00352   PRBool SetCarriedOutBottomMargin(nsCollapsingMargin aValue);
00353 
00354   // mFloats
00355   PRBool HasFloats() const {
00356     return (IsInline() && mInlineData) && mInlineData->mFloats.NotEmpty();
00357   }
00358   nsFloatCache* GetFirstFloat();
00359   void FreeFloats(nsFloatCacheFreeList& aFreeList);
00360   void AppendFloats(nsFloatCacheFreeList& aFreeList);
00361   PRBool RemoveFloat(nsIFrame* aFrame);
00362 
00363   // Combined area is the area of the line that should influence the
00364   // overflow area of its parent block.  The combined area should be
00365   // used for painting-related things, but should never be used for
00366   // layout (except for handling of 'overflow').
00367   void SetCombinedArea(const nsRect& aCombinedArea);
00368   nsRect GetCombinedArea() {
00369     return mData ? mData->mCombinedArea : mBounds;
00370   }
00371   PRBool CombinedAreaIntersects(const nsRect& aDamageRect) {
00372     nsRect* ca = (mData ? &mData->mCombinedArea : &mBounds);
00373     return !((ca->YMost() <= aDamageRect.y) ||
00374              (ca->y >= aDamageRect.YMost()));
00375   }
00376 
00377   void SlideBy(nscoord aDY) {
00378     mBounds.y += aDY;
00379     if (mData) {
00380       mData->mCombinedArea.y += aDY;
00381     }
00382   }
00383 
00392   nscoord GetAscent() const { return mAscent; }
00393   void SetAscent(nscoord aAscent) { mAscent = aAscent; }
00394 
00395   nscoord GetHeight() const {
00396     return mBounds.height;
00397   }
00398 
00399   static void DeleteLineList(nsPresContext* aPresContext, nsLineList& aLines);
00400 
00401   // search from beginning to end
00402   // XXX Should switch to API below
00403   static nsLineBox* FindLineContaining(nsLineList& aLines, nsIFrame* aFrame,
00404                                        PRInt32* aFrameIndexInLine);
00405 
00406   // search from end to beginning of [aBegin, aEnd)
00407   // Returns PR_TRUE if it found the line and PR_FALSE if not.
00408   // Moves aEnd as it searches so that aEnd points to the resulting line.
00409   static PRBool RFindLineContaining(nsIFrame* aFrame,
00410                                     const nsLineList_iterator& aBegin,
00411                                     nsLineList_iterator& aEnd,
00412                                     PRInt32* aFrameIndexInLine);
00413 
00414 #ifdef DEBUG
00415   char* StateToString(char* aBuf, PRInt32 aBufSize) const;
00416 
00417   void List(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent) const;
00418 #endif
00419 
00420   nsIFrame* LastChild() const;
00421 
00422   PRBool IsLastChild(nsIFrame* aFrame) const;
00423 
00424   PRInt32 IndexOf(nsIFrame* aFrame) const;
00425 
00426   PRBool Contains(nsIFrame* aFrame) const {
00427     return IndexOf(aFrame) >= 0;
00428   }
00429 
00430   // whether the line box is "logically" empty (just like nsIFrame::IsEmpty)
00431   PRBool IsEmpty() const;
00432 
00433   // Call this only while in Reflow() for the block the line belongs
00434   // to, only between reflowing the line (or sliding it, if we skip
00435   // reflowing it) and the end of reflowing the the block.
00436   PRBool CachedIsEmpty();
00437 
00438   void InvalidateCachedIsEmpty() {
00439     mFlags.mEmptyCacheValid = PR_FALSE;
00440   }
00441 
00442   // For debugging purposes
00443   PRBool IsValidCachedIsEmpty() {
00444     return mFlags.mEmptyCacheValid;
00445   }
00446 
00447 #ifdef DEBUG
00448   static PRInt32 GetCtorCount();
00449 #endif
00450 
00451   nsIFrame* mFirstChild;
00452 
00453   nsRect mBounds;
00454   nscoord mMaxElementWidth;  // width part of max-element-size
00455   nscoord mMaximumWidth;     // maximum width (needed for incremental reflow of tables)
00456                              // includes the left border/padding but not the right
00457 
00458   struct FlagBits {
00459     PRUint32 mDirty : 1;
00460     PRUint32 mPreviousMarginDirty : 1;
00461     PRUint32 mHasClearance : 1;
00462     PRUint32 mBlock : 1;
00463     PRUint32 mImpactedByFloat : 1;
00464     PRUint32 mHasPercentageChild : 1;
00465     PRUint32 mLineWrapped: 1;
00466     PRUint32 mResizeReflowOptimizationDisabled: 1;  // default 0 = means that the opt potentially applies to this line. 1 = never skip reflowing this line for a resize reflow
00467     PRUint32 mEmptyCacheValid: 1;
00468     PRUint32 mEmptyCacheState: 1;
00469     PRUint32 mBreakType : 4;
00470 
00471     PRUint32 mChildCount : 18;
00472   };
00473 
00474   struct ExtraData {
00475     ExtraData(const nsRect& aBounds) : mCombinedArea(aBounds) {
00476     }
00477     nsRect mCombinedArea;
00478   };
00479 
00480   struct ExtraBlockData : public ExtraData {
00481     ExtraBlockData(const nsRect& aBounds)
00482       : ExtraData(aBounds),
00483         mCarriedOutBottomMargin()
00484     {
00485     }
00486     nsCollapsingMargin mCarriedOutBottomMargin;
00487   };
00488 
00489   struct ExtraInlineData : public ExtraData {
00490     ExtraInlineData(const nsRect& aBounds) : ExtraData(aBounds) {
00491     }
00492     nsFloatCacheList mFloats;
00493   };
00494 
00495 protected:
00496   nscoord mAscent;           // see |SetAscent| / |GetAscent|
00497   union {
00498     PRUint32 mAllFlags;
00499     FlagBits mFlags;
00500   };
00501 
00502   union {
00503     ExtraData* mData;
00504     ExtraBlockData* mBlockData;
00505     ExtraInlineData* mInlineData;
00506   };
00507 
00508   void Cleanup();
00509   void MaybeFreeData();
00510 };
00511 
00512 #ifdef DEBUG
00513 #define NS_LINELIST_DEBUG_PASS_END
00514 #else
00515 #undef NS_LINELIST_DEBUG_PASS_END
00516 #endif
00517 
00525 class nsLineList_iterator {
00526   public:
00527     friend class nsLineList;
00528     friend class nsLineList_reverse_iterator;
00529     friend class nsLineList_const_iterator;
00530     friend class nsLineList_const_reverse_iterator;
00531 
00532     typedef nsLineList_iterator         iterator_self_type;
00533     typedef nsLineList_reverse_iterator iterator_reverse_type;
00534 
00535     typedef nsLineBox&                  reference;
00536     typedef const nsLineBox&            const_reference;
00537 
00538     typedef nsLineBox*                  pointer;
00539     typedef const nsLineBox*            const_pointer;
00540 
00541     typedef PRUint32                    size_type;
00542     typedef PRInt32                     difference_type;
00543 
00544     typedef nsLineLink                  link_type;
00545 
00546     // Auto generated default constructor OK.
00547     // Auto generated copy-constructor OK.
00548 
00549     inline iterator_self_type&
00550         operator=(const iterator_self_type& aOther);
00551     inline iterator_self_type&
00552         operator=(const iterator_reverse_type& aOther);
00553 
00554     iterator_self_type& operator++()
00555     {
00556       mCurrent = mCurrent->_mNext;
00557       return *this;
00558     }
00559 
00560     iterator_self_type operator++(int)
00561     {
00562       iterator_self_type rv(*this);
00563       mCurrent = mCurrent->_mNext;
00564       return rv;
00565     }
00566 
00567     iterator_self_type& operator--()
00568     {
00569       mCurrent = mCurrent->_mPrev;
00570       return *this;
00571     }
00572 
00573     iterator_self_type operator--(int)
00574     {
00575       iterator_self_type rv(*this);
00576       mCurrent = mCurrent->_mPrev;
00577       return rv;
00578     }
00579 
00580     reference operator*()
00581     {
00582 #ifdef NS_LINELIST_DEBUG_PASS_END
00583       NS_ASSERTION(mCurrent != mListLink, "running past end");
00584 #endif
00585       return *NS_STATIC_CAST(pointer, mCurrent);
00586     }
00587 
00588     pointer operator->()
00589     {
00590 #ifdef NS_LINELIST_DEBUG_PASS_END
00591       NS_ASSERTION(mCurrent != mListLink, "running past end");
00592 #endif
00593       return NS_STATIC_CAST(pointer, mCurrent);
00594     }
00595 
00596     pointer get()
00597     {
00598 #ifdef NS_LINELIST_DEBUG_PASS_END
00599       NS_ASSERTION(mCurrent != mListLink, "running past end");
00600 #endif
00601       return NS_STATIC_CAST(pointer, mCurrent);
00602     }
00603 
00604     operator pointer()
00605     {
00606 #ifdef NS_LINELIST_DEBUG_PASS_END
00607       NS_ASSERTION(mCurrent != mListLink, "running past end");
00608 #endif
00609       return NS_STATIC_CAST(pointer, mCurrent);
00610     }
00611 
00612     const_reference operator*() const
00613     {
00614 #ifdef NS_LINELIST_DEBUG_PASS_END
00615       NS_ASSERTION(mCurrent != mListLink, "running past end");
00616 #endif
00617       return *NS_STATIC_CAST(const_pointer, mCurrent);
00618     }
00619 
00620     const_pointer operator->() const
00621     {
00622 #ifdef NS_LINELIST_DEBUG_PASS_END
00623       NS_ASSERTION(mCurrent != mListLink, "running past end");
00624 #endif
00625       return NS_STATIC_CAST(const_pointer, mCurrent);
00626     }
00627 
00628 #ifndef __MWERKS__
00629     operator const_pointer() const
00630     {
00631 #ifdef NS_LINELIST_DEBUG_PASS_END
00632       NS_ASSERTION(mCurrent != mListLink, "running past end");
00633 #endif
00634       return NS_STATIC_CAST(const_pointer, mCurrent);
00635     }
00636 #endif /* !__MWERKS__ */
00637 
00638     iterator_self_type next()
00639     {
00640       iterator_self_type copy(*this);
00641       return ++copy;
00642     }
00643 
00644     const iterator_self_type next() const
00645     {
00646       iterator_self_type copy(*this);
00647       return ++copy;
00648     }
00649 
00650     iterator_self_type prev()
00651     {
00652       iterator_self_type copy(*this);
00653       return --copy;
00654     }
00655 
00656     const iterator_self_type prev() const
00657     {
00658       iterator_self_type copy(*this);
00659       return --copy;
00660     }
00661 
00662     // Passing by value rather than by reference and reference to const
00663     // to keep AIX happy.
00664     // XXX Should add assertions that |mListLink| is the same for both.
00665     PRBool operator==(const iterator_self_type aOther) const
00666         { return mCurrent == aOther.mCurrent; }
00667     PRBool operator!=(const iterator_self_type aOther) const
00668         { return mCurrent != aOther.mCurrent; }
00669     PRBool operator==(const iterator_self_type aOther)
00670         { return mCurrent == aOther.mCurrent; }
00671     PRBool operator!=(const iterator_self_type aOther)
00672         { return mCurrent != aOther.mCurrent; }
00673 
00674   private:
00675     link_type *mCurrent;
00676 #ifdef NS_LINELIST_DEBUG_PASS_END
00677     link_type *mListLink; // the list's link, i.e., the end
00678 #endif
00679 };
00680 
00681 class nsLineList_reverse_iterator {
00682 
00683   public:
00684 
00685     friend class nsLineList;
00686     friend class nsLineList_iterator;
00687     friend class nsLineList_const_iterator;
00688     friend class nsLineList_const_reverse_iterator;
00689 
00690     typedef nsLineList_reverse_iterator iterator_self_type;
00691     typedef nsLineList_iterator         iterator_reverse_type;
00692 
00693     typedef nsLineBox&                  reference;
00694     typedef const nsLineBox&            const_reference;
00695 
00696     typedef nsLineBox*                  pointer;
00697     typedef const nsLineBox*            const_pointer;
00698 
00699     typedef PRUint32                    size_type;
00700     typedef PRInt32                     difference_type;
00701 
00702     typedef nsLineLink                  link_type;
00703 
00704     // Auto generated default constructor OK.
00705     // Auto generated copy-constructor OK.
00706 
00707     inline iterator_self_type&
00708         operator=(const iterator_reverse_type& aOther);
00709     inline iterator_self_type&
00710         operator=(const iterator_self_type& aOther);
00711 
00712     iterator_self_type& operator++()
00713     {
00714       mCurrent = mCurrent->_mPrev;
00715       return *this;
00716     }
00717 
00718     iterator_self_type operator++(int)
00719     {
00720       iterator_self_type rv(*this);
00721       mCurrent = mCurrent->_mPrev;
00722       return rv;
00723     }
00724 
00725     iterator_self_type& operator--()
00726     {
00727       mCurrent = mCurrent->_mNext;
00728       return *this;
00729     }
00730 
00731     iterator_self_type operator--(int)
00732     {
00733       iterator_self_type rv(*this);
00734       mCurrent = mCurrent->_mNext;
00735       return rv;
00736     }
00737 
00738     reference operator*()
00739     {
00740 #ifdef NS_LINELIST_DEBUG_PASS_END
00741       NS_ASSERTION(mCurrent != mListLink, "running past end");
00742 #endif
00743       return *NS_STATIC_CAST(pointer, mCurrent);
00744     }
00745 
00746     pointer operator->()
00747     {
00748 #ifdef NS_LINELIST_DEBUG_PASS_END
00749       NS_ASSERTION(mCurrent != mListLink, "running past end");
00750 #endif
00751       return NS_STATIC_CAST(pointer, mCurrent);
00752     }
00753 
00754     pointer get()
00755     {
00756 #ifdef NS_LINELIST_DEBUG_PASS_END
00757       NS_ASSERTION(mCurrent != mListLink, "running past end");
00758 #endif
00759       return NS_STATIC_CAST(pointer, mCurrent);
00760     }
00761 
00762     operator pointer()
00763     {
00764 #ifdef NS_LINELIST_DEBUG_PASS_END
00765       NS_ASSERTION(mCurrent != mListLink, "running past end");
00766 #endif
00767       return NS_STATIC_CAST(pointer, mCurrent);
00768     }
00769 
00770     const_reference operator*() const
00771     {
00772 #ifdef NS_LINELIST_DEBUG_PASS_END
00773       NS_ASSERTION(mCurrent != mListLink, "running past end");
00774 #endif
00775       return *NS_STATIC_CAST(const_pointer, mCurrent);
00776     }
00777 
00778     const_pointer operator->() const
00779     {
00780 #ifdef NS_LINELIST_DEBUG_PASS_END
00781       NS_ASSERTION(mCurrent != mListLink, "running past end");
00782 #endif
00783       return NS_STATIC_CAST(const_pointer, mCurrent);
00784     }
00785 
00786 #ifndef __MWERKS__
00787     operator const_pointer() const
00788     {
00789 #ifdef NS_LINELIST_DEBUG_PASS_END
00790       NS_ASSERTION(mCurrent != mListLink, "running past end");
00791 #endif
00792       return NS_STATIC_CAST(const_pointer, mCurrent);
00793     }
00794 #endif /* !__MWERKS__ */
00795 
00796     // Passing by value rather than by reference and reference to const
00797     // to keep AIX happy.
00798     PRBool operator==(const iterator_self_type aOther) const
00799         { return mCurrent == aOther.mCurrent; }
00800     PRBool operator!=(const iterator_self_type aOther) const
00801         { return mCurrent != aOther.mCurrent; }
00802     PRBool operator==(const iterator_self_type aOther)
00803         { return mCurrent == aOther.mCurrent; }
00804     PRBool operator!=(const iterator_self_type aOther)
00805         { return mCurrent != aOther.mCurrent; }
00806 
00807   private:
00808     link_type *mCurrent;
00809 #ifdef NS_LINELIST_DEBUG_PASS_END
00810     link_type *mListLink; // the list's link, i.e., the end
00811 #endif
00812 };
00813 
00814 class nsLineList_const_iterator {
00815   public:
00816 
00817     friend class nsLineList;
00818     friend class nsLineList_iterator;
00819     friend class nsLineList_reverse_iterator;
00820     friend class nsLineList_const_reverse_iterator;
00821 
00822     typedef nsLineList_const_iterator           iterator_self_type;
00823     typedef nsLineList_const_reverse_iterator   iterator_reverse_type;
00824     typedef nsLineList_iterator                 iterator_nonconst_type;
00825     typedef nsLineList_reverse_iterator         iterator_nonconst_reverse_type;
00826 
00827     typedef nsLineBox&                  reference;
00828     typedef const nsLineBox&            const_reference;
00829 
00830     typedef nsLineBox*                  pointer;
00831     typedef const nsLineBox*            const_pointer;
00832 
00833     typedef PRUint32                    size_type;
00834     typedef PRInt32                     difference_type;
00835 
00836     typedef nsLineLink                  link_type;
00837 
00838     // Auto generated default constructor OK.
00839     // Auto generated copy-constructor OK.
00840 
00841     inline iterator_self_type&
00842         operator=(const iterator_nonconst_type& aOther);
00843     inline iterator_self_type&
00844         operator=(const iterator_nonconst_reverse_type& aOther);
00845     inline iterator_self_type&
00846         operator=(const iterator_self_type& aOther);
00847     inline iterator_self_type&
00848         operator=(const iterator_reverse_type& aOther);
00849 
00850     iterator_self_type& operator++()
00851     {
00852       mCurrent = mCurrent->_mNext;
00853       return *this;
00854     }
00855 
00856     iterator_self_type operator++(int)
00857     {
00858       iterator_self_type rv(*this);
00859       mCurrent = mCurrent->_mNext;
00860       return rv;
00861     }
00862 
00863     iterator_self_type& operator--()
00864     {
00865       mCurrent = mCurrent->_mPrev;
00866       return *this;
00867     }
00868 
00869     iterator_self_type operator--(int)
00870     {
00871       iterator_self_type rv(*this);
00872       mCurrent = mCurrent->_mPrev;
00873       return rv;
00874     }
00875 
00876     const_reference operator*() const
00877     {
00878 #ifdef NS_LINELIST_DEBUG_PASS_END
00879       NS_ASSERTION(mCurrent != mListLink, "running past end");
00880 #endif
00881       return *NS_STATIC_CAST(const_pointer, mCurrent);
00882     }
00883 
00884     const_pointer operator->() const
00885     {
00886 #ifdef NS_LINELIST_DEBUG_PASS_END
00887       NS_ASSERTION(mCurrent != mListLink, "running past end");
00888 #endif
00889       return NS_STATIC_CAST(const_pointer, mCurrent);
00890     }
00891 
00892     const_pointer get() const
00893     {
00894 #ifdef NS_LINELIST_DEBUG_PASS_END
00895       NS_ASSERTION(mCurrent != mListLink, "running past end");
00896 #endif
00897       return NS_STATIC_CAST(const_pointer, mCurrent);
00898     }
00899 
00900 #ifndef __MWERKS__
00901     operator const_pointer() const
00902     {
00903 #ifdef NS_LINELIST_DEBUG_PASS_END
00904       NS_ASSERTION(mCurrent != mListLink, "running past end");
00905 #endif
00906       return NS_STATIC_CAST(const_pointer, mCurrent);
00907     }
00908 #endif /* !__MWERKS__ */
00909 
00910     const iterator_self_type next() const
00911     {
00912       iterator_self_type copy(*this);
00913       return ++copy;
00914     }
00915 
00916     const iterator_self_type prev() const
00917     {
00918       iterator_self_type copy(*this);
00919       return --copy;
00920     }
00921 
00922     // Passing by value rather than by reference and reference to const
00923     // to keep AIX happy.
00924     PRBool operator==(const iterator_self_type aOther) const
00925         { return mCurrent == aOther.mCurrent; }
00926     PRBool operator!=(const iterator_self_type aOther) const
00927         { return mCurrent != aOther.mCurrent; }
00928     PRBool operator==(const iterator_self_type aOther)
00929         { return mCurrent == aOther.mCurrent; }
00930     PRBool operator!=(const iterator_self_type aOther)
00931         { return mCurrent != aOther.mCurrent; }
00932 
00933   private:
00934     const link_type *mCurrent;
00935 #ifdef NS_LINELIST_DEBUG_PASS_END
00936     const link_type *mListLink; // the list's link, i.e., the end
00937 #endif
00938 };
00939 
00940 class nsLineList_const_reverse_iterator {
00941   public:
00942 
00943     friend class nsLineList;
00944     friend class nsLineList_iterator;
00945     friend class nsLineList_reverse_iterator;
00946     friend class nsLineList_const_iterator;
00947 
00948     typedef nsLineList_const_reverse_iterator   iterator_self_type;
00949     typedef nsLineList_const_iterator           iterator_reverse_type;
00950     typedef nsLineList_iterator                 iterator_nonconst_reverse_type;
00951     typedef nsLineList_reverse_iterator         iterator_nonconst_type;
00952 
00953     typedef nsLineBox&                  reference;
00954     typedef const nsLineBox&            const_reference;
00955 
00956     typedef nsLineBox*                  pointer;
00957     typedef const nsLineBox*            const_pointer;
00958 
00959     typedef PRUint32                    size_type;
00960     typedef PRInt32                     difference_type;
00961 
00962     typedef nsLineLink                  link_type;
00963 
00964     // Auto generated default constructor OK.
00965     // Auto generated copy-constructor OK.
00966 
00967     inline iterator_self_type&
00968         operator=(const iterator_nonconst_type& aOther);
00969     inline iterator_self_type&
00970         operator=(const iterator_nonconst_reverse_type& aOther);
00971     inline iterator_self_type&
00972         operator=(const iterator_self_type& aOther);
00973     inline iterator_self_type&
00974         operator=(const iterator_reverse_type& aOther);
00975 
00976     iterator_self_type& operator++()
00977     {
00978       mCurrent = mCurrent->_mPrev;
00979       return *this;
00980     }
00981 
00982     iterator_self_type operator++(int)
00983     {
00984       iterator_self_type rv(*this);
00985       mCurrent = mCurrent->_mPrev;
00986       return rv;
00987     }
00988 
00989     iterator_self_type& operator--()
00990     {
00991       mCurrent = mCurrent->_mNext;
00992       return *this;
00993     }
00994 
00995     iterator_self_type operator--(int)
00996     {
00997       iterator_self_type rv(*this);
00998       mCurrent = mCurrent->_mNext;
00999       return rv;
01000     }
01001 
01002     const_reference operator*() const
01003     {
01004 #ifdef NS_LINELIST_DEBUG_PASS_END
01005       NS_ASSERTION(mCurrent != mListLink, "running past end");
01006 #endif
01007       return *NS_STATIC_CAST(const_pointer, mCurrent);
01008     }
01009 
01010     const_pointer operator->() const
01011     {
01012 #ifdef NS_LINELIST_DEBUG_PASS_END
01013       NS_ASSERTION(mCurrent != mListLink, "running past end");
01014 #endif
01015       return NS_STATIC_CAST(const_pointer, mCurrent);
01016     }
01017 
01018     const_pointer get() const
01019     {
01020 #ifdef NS_LINELIST_DEBUG_PASS_END
01021       NS_ASSERTION(mCurrent != mListLink, "running past end");
01022 #endif
01023       return NS_STATIC_CAST(const_pointer, mCurrent);
01024     }
01025 
01026 #ifndef __MWERKS__
01027     operator const_pointer() const
01028     {
01029 #ifdef NS_LINELIST_DEBUG_PASS_END
01030       NS_ASSERTION(mCurrent != mListLink, "running past end");
01031 #endif
01032       return NS_STATIC_CAST(const_pointer, mCurrent);
01033     }
01034 #endif /* !__MWERKS__ */
01035 
01036     // Passing by value rather than by reference and reference to const
01037     // to keep AIX happy.
01038     PRBool operator==(const iterator_self_type aOther) const
01039         { return mCurrent == aOther.mCurrent; }
01040     PRBool operator!=(const iterator_self_type aOther) const
01041         { return mCurrent != aOther.mCurrent; }
01042     PRBool operator==(const iterator_self_type aOther)
01043         { return mCurrent == aOther.mCurrent; }
01044     PRBool operator!=(const iterator_self_type aOther)
01045         { return mCurrent != aOther.mCurrent; }
01046 
01047 //private:
01048     const link_type *mCurrent;
01049 #ifdef NS_LINELIST_DEBUG_PASS_END
01050     const link_type *mListLink; // the list's link, i.e., the end
01051 #endif
01052 };
01053 
01054 class nsLineList {
01055 
01056   public:
01057 
01058   friend class nsLineList_iterator;
01059   friend class nsLineList_reverse_iterator;
01060   friend class nsLineList_const_iterator;
01061   friend class nsLineList_const_reverse_iterator;
01062 
01063   typedef PRUint32                    size_type;
01064   typedef PRInt32                     difference_type;
01065 
01066   typedef nsLineLink                  link_type;
01067 
01068   private:
01069     link_type mLink;
01070 
01071   public:
01072     typedef nsLineList                  self_type;
01073 
01074     typedef nsLineBox&                  reference;
01075     typedef const nsLineBox&            const_reference;
01076 
01077     typedef nsLineBox*                  pointer;
01078     typedef const nsLineBox*            const_pointer;
01079 
01080     typedef nsLineList_iterator         iterator;
01081     typedef nsLineList_reverse_iterator reverse_iterator;
01082     typedef nsLineList_const_iterator   const_iterator;
01083     typedef nsLineList_const_reverse_iterator const_reverse_iterator;
01084 
01085     nsLineList()
01086     {
01087       clear();
01088     }
01089 
01090     const_iterator begin() const
01091     {
01092       const_iterator rv;
01093       rv.mCurrent = mLink._mNext;
01094 #ifdef NS_LINELIST_DEBUG_PASS_END
01095       rv.mListLink = &mLink;
01096 #endif
01097       return rv;
01098     }
01099 
01100     iterator begin()
01101     {
01102       iterator rv;
01103       rv.mCurrent = mLink._mNext;
01104 #ifdef NS_LINELIST_DEBUG_PASS_END
01105       rv.mListLink = &mLink;
01106 #endif
01107       return rv;
01108     }
01109 
01110     iterator begin(nsLineBox* aLine)
01111     {
01112       iterator rv;
01113       rv.mCurrent = aLine;
01114 #ifdef NS_LINELIST_DEBUG_PASS_END
01115       rv.mListLink = &mLink;
01116 #endif
01117       return rv;
01118     }
01119 
01120     const_iterator end() const
01121     {
01122       const_iterator rv;
01123       rv.mCurrent = &mLink;
01124 #ifdef NS_LINELIST_DEBUG_PASS_END
01125       rv.mListLink = &mLink;
01126 #endif
01127       return rv;
01128     }
01129 
01130     iterator end()
01131     {
01132       iterator rv;
01133       rv.mCurrent = &mLink;
01134 #ifdef NS_LINELIST_DEBUG_PASS_END
01135       rv.mListLink = &mLink;
01136 #endif
01137       return rv;
01138     }
01139 
01140     const_reverse_iterator rbegin() const
01141     {
01142       const_reverse_iterator rv;
01143       rv.mCurrent = mLink._mPrev;
01144 #ifdef NS_LINELIST_DEBUG_PASS_END
01145       rv.mListLink = &mLink;
01146 #endif
01147       return rv;
01148     }
01149 
01150     reverse_iterator rbegin()
01151     {
01152       reverse_iterator rv;
01153       rv.mCurrent = mLink._mPrev;
01154 #ifdef NS_LINELIST_DEBUG_PASS_END
01155       rv.mListLink = &mLink;
01156 #endif
01157       return rv;
01158     }
01159 
01160     const_reverse_iterator rend() const
01161     {
01162       const_reverse_iterator rv;
01163       rv.mCurrent = &mLink;
01164 #ifdef NS_LINELIST_DEBUG_PASS_END
01165       rv.mListLink = &mLink;
01166 #endif
01167       return rv;
01168     }
01169 
01170     reverse_iterator rend()
01171     {
01172       reverse_iterator rv;
01173       rv.mCurrent = &mLink;
01174 #ifdef NS_LINELIST_DEBUG_PASS_END
01175       rv.mListLink = &mLink;
01176 #endif
01177       return rv;
01178     }
01179 
01180     PRBool empty() const
01181     {
01182       return mLink._mNext == &mLink;
01183     }
01184 
01185     // NOTE: O(N).
01186     size_type size() const
01187     {
01188       size_type count = 0;
01189       for (const link_type *cur = mLink._mNext;
01190            cur != &mLink;
01191            cur = cur->_mNext)
01192       {
01193         ++count;
01194       }
01195       return count;
01196     }
01197 
01198     pointer front()
01199     {
01200       NS_ASSERTION(!empty(), "no element to return");
01201       return NS_STATIC_CAST(pointer, mLink._mNext);
01202     }
01203 
01204     const_pointer front() const
01205     {
01206       NS_ASSERTION(!empty(), "no element to return");
01207       return NS_STATIC_CAST(const_pointer, mLink._mNext);
01208     }
01209 
01210     pointer back()
01211     {
01212       NS_ASSERTION(!empty(), "no element to return");
01213       return NS_STATIC_CAST(pointer, mLink._mPrev);
01214     }
01215 
01216     const_pointer back() const
01217     {
01218       NS_ASSERTION(!empty(), "no element to return");
01219       return NS_STATIC_CAST(const_pointer, mLink._mPrev);
01220     }
01221 
01222     void push_front(pointer aNew)
01223     {
01224       aNew->_mNext = mLink._mNext;
01225       mLink._mNext->_mPrev = aNew;
01226       aNew->_mPrev = &mLink;
01227       mLink._mNext = aNew;
01228     }
01229 
01230     void pop_front()
01231         // NOTE: leaves dangling next/prev pointers
01232     {
01233       NS_ASSERTION(!empty(), "no element to pop");
01234       link_type *newFirst = mLink._mNext->_mNext;
01235       newFirst->_mPrev = &mLink;
01236       // mLink._mNext->_mNext = nsnull;
01237       // mLink._mNext->_mPrev = nsnull;
01238       mLink._mNext = newFirst;
01239     }
01240 
01241     void push_back(pointer aNew)
01242     {
01243       aNew->_mPrev = mLink._mPrev;
01244       mLink._mPrev->_mNext = aNew;
01245       aNew->_mNext = &mLink;
01246       mLink._mPrev = aNew;
01247     }
01248 
01249     void pop_back()
01250         // NOTE: leaves dangling next/prev pointers
01251     {
01252       NS_ASSERTION(!empty(), "no element to pop");
01253       link_type *newLast = mLink._mPrev->_mPrev;
01254       newLast->_mNext = &mLink;
01255       // mLink._mPrev->_mPrev = nsnull;
01256       // mLink._mPrev->_mNext = nsnull;
01257       mLink._mPrev = newLast;
01258     }
01259 
01260     // inserts x before position
01261     iterator before_insert(iterator position, pointer x)
01262     {
01263       // use |mCurrent| to prevent DEBUG_PASS_END assertions
01264       x->_mPrev = position.mCurrent->_mPrev;
01265       x->_mNext = position.mCurrent;
01266       position.mCurrent->_mPrev->_mNext = x;
01267       position.mCurrent->_mPrev = x;
01268       return --position;
01269     }
01270 
01271     // inserts x after position
01272     iterator after_insert(iterator position, pointer x)
01273     {
01274       // use |mCurrent| to prevent DEBUG_PASS_END assertions
01275       x->_mNext = position.mCurrent->_mNext;
01276       x->_mPrev = position.mCurrent;
01277       position.mCurrent->_mNext->_mPrev = x;
01278       position.mCurrent->_mNext = x;
01279       return ++position;
01280     }
01281 
01282     // returns iterator pointing to after the element
01283     iterator erase(iterator position)
01284         // NOTE: leaves dangling next/prev pointers
01285     {
01286       position->_mPrev->_mNext = position->_mNext;
01287       position->_mNext->_mPrev = position->_mPrev;
01288       return ++position;
01289     }
01290 
01291     void swap(self_type& y)
01292     {
01293       link_type tmp(y.mLink);
01294       y.mLink = mLink;
01295       mLink = tmp;
01296     }
01297 
01298     void clear()
01299         // NOTE:  leaves dangling next/prev pointers
01300     {
01301       mLink._mNext = &mLink;
01302       mLink._mPrev = &mLink;
01303     }
01304 
01305     // inserts the conts of x before position and makes x empty
01306     void splice(iterator position, self_type& x)
01307     {
01308       // use |mCurrent| to prevent DEBUG_PASS_END assertions
01309       position.mCurrent->_mPrev->_mNext = x.mLink._mNext;
01310       x.mLink._mNext->_mPrev = position.mCurrent->_mPrev;
01311       x.mLink._mPrev->_mNext = position.mCurrent;
01312       position.mCurrent->_mPrev = x.mLink._mPrev;
01313       x.clear();
01314     }
01315 
01316     // Inserts element *i from list x before position and removes
01317     // it from x.
01318     void splice(iterator position, self_type& x, iterator i)
01319     {
01320       NS_ASSERTION(!x.empty(), "Can't insert from empty list.");
01321       NS_ASSERTION(position != i && position.mCurrent != i->_mNext,
01322                    "We don't check for this case.");
01323 
01324       // remove from |x|
01325       i->_mPrev->_mNext = i->_mNext;
01326       i->_mNext->_mPrev = i->_mPrev;
01327 
01328       // use |mCurrent| to prevent DEBUG_PASS_END assertions
01329       // link into |this|, before-side
01330       i->_mPrev = position.mCurrent->_mPrev;
01331       position.mCurrent->_mPrev->_mNext = i.get();
01332 
01333       // link into |this|, after-side
01334       i->_mNext = position.mCurrent;
01335       position.mCurrent->_mPrev = i.get();
01336     }
01337 
01338     // Inserts elements in [|first|, |last|), which are in |x|,
01339     // into |this| before |position| and removes them from |x|.
01340     void splice(iterator position, self_type& x, iterator first,
01341                 iterator last)
01342     {
01343       NS_ASSERTION(!x.empty(), "Can't insert from empty list.");
01344 
01345       if (first == last)
01346         return;
01347 
01348       --last; // so we now want to move [first, last]
01349       // remove from |x|
01350       first->_mPrev->_mNext = last->_mNext;
01351       last->_mNext->_mPrev = first->_mPrev;
01352 
01353       // use |mCurrent| to prevent DEBUG_PASS_END assertions
01354       // link into |this|, before-side
01355       first->_mPrev = position.mCurrent->_mPrev;
01356       position.mCurrent->_mPrev->_mNext = first.get();
01357 
01358       // link into |this|, after-side
01359       last->_mNext = position.mCurrent;
01360       position.mCurrent->_mPrev = last.get();
01361     }
01362 
01363 };
01364 
01365 
01366 // Many of these implementations of operator= don't work yet.  I don't
01367 // know why.
01368 
01369 #ifdef NS_LINELIST_DEBUG_PASS_END
01370 
01371   // NOTE: ASSIGN_FROM is meant to be used *only* as the entire body
01372   // of a function and therefore lacks PR_{BEGIN,END}_MACRO
01373 #define ASSIGN_FROM(other_)          \
01374   mCurrent = other_.mCurrent;        \
01375   mListLink = other_.mListLink;      \
01376   return *this;
01377 
01378 #else /* !NS_LINELIST_DEBUG_PASS_END */
01379 
01380 #define ASSIGN_FROM(other_)          \
01381   mCurrent = other_.mCurrent;        \
01382   return *this;
01383 
01384 #endif /* !NS_LINELIST_DEBUG_PASS_END */
01385 
01386 inline
01387 nsLineList_iterator&
01388 nsLineList_iterator::operator=(const nsLineList_iterator& aOther)
01389 {
01390   ASSIGN_FROM(aOther)
01391 }
01392 
01393 inline
01394 nsLineList_iterator&
01395 nsLineList_iterator::operator=(const nsLineList_reverse_iterator& aOther)
01396 {
01397   ASSIGN_FROM(aOther)
01398 }
01399 
01400 inline
01401 nsLineList_reverse_iterator&
01402 nsLineList_reverse_iterator::operator=(const nsLineList_iterator& aOther)
01403 {
01404   ASSIGN_FROM(aOther)
01405 }
01406 
01407 inline
01408 nsLineList_reverse_iterator&
01409 nsLineList_reverse_iterator::operator=(const nsLineList_reverse_iterator& aOther)
01410 {
01411   ASSIGN_FROM(aOther)
01412 }
01413 
01414 inline
01415 nsLineList_const_iterator&
01416 nsLineList_const_iterator::operator=(const nsLineList_iterator& aOther)
01417 {
01418   ASSIGN_FROM(aOther)
01419 }
01420 
01421 inline
01422 nsLineList_const_iterator&
01423 nsLineList_const_iterator::operator=(const nsLineList_reverse_iterator& aOther)
01424 {
01425   ASSIGN_FROM(aOther)
01426 }
01427 
01428 inline
01429 nsLineList_const_iterator&
01430 nsLineList_const_iterator::operator=(const nsLineList_const_iterator& aOther)
01431 {
01432   ASSIGN_FROM(aOther)
01433 }
01434 
01435 inline
01436 nsLineList_const_iterator&
01437 nsLineList_const_iterator::operator=(const nsLineList_const_reverse_iterator& aOther)
01438 {
01439   ASSIGN_FROM(aOther)
01440 }
01441 
01442 inline
01443 nsLineList_const_reverse_iterator&
01444 nsLineList_const_reverse_iterator::operator=(const nsLineList_iterator& aOther)
01445 {
01446   ASSIGN_FROM(aOther)
01447 }
01448 
01449 inline
01450 nsLineList_const_reverse_iterator&
01451 nsLineList_const_reverse_iterator::operator=(const nsLineList_reverse_iterator& aOther)
01452 {
01453   ASSIGN_FROM(aOther)
01454 }
01455 
01456 inline
01457 nsLineList_const_reverse_iterator&
01458 nsLineList_const_reverse_iterator::operator=(const nsLineList_const_iterator& aOther)
01459 {
01460   ASSIGN_FROM(aOther)
01461 }
01462 
01463 inline
01464 nsLineList_const_reverse_iterator&
01465 nsLineList_const_reverse_iterator::operator=(const nsLineList_const_reverse_iterator& aOther)
01466 {
01467   ASSIGN_FROM(aOther)
01468 }
01469 
01470 
01471 //----------------------------------------------------------------------
01472 
01473 class nsLineIterator : public nsILineIteratorNavigator {
01474 public:
01475   nsLineIterator();
01476   virtual ~nsLineIterator();
01477 
01478   NS_DECL_ISUPPORTS
01479 
01480   NS_IMETHOD GetNumLines(PRInt32* aResult);
01481   NS_IMETHOD GetDirection(PRBool* aIsRightToLeft);
01482   NS_IMETHOD GetLine(PRInt32 aLineNumber,
01483                      nsIFrame** aFirstFrameOnLine,
01484                      PRInt32* aNumFramesOnLine,
01485                      nsRect& aLineBounds,
01486                      PRUint32* aLineFlags);
01487   NS_IMETHOD FindLineContaining(nsIFrame* aFrame,
01488                                 PRInt32* aLineNumberResult);
01489   NS_IMETHOD FindLineAt(nscoord aY,
01490                         PRInt32* aLineNumberResult);
01491   NS_IMETHOD FindFrameAt(PRInt32 aLineNumber,
01492                          nscoord aX,
01493                          nsIFrame** aFrameFound,
01494                          PRBool* aXIsBeforeFirstFrame,
01495                          PRBool* aXIsAfterLastFrame);
01496 
01497   NS_IMETHOD GetNextSiblingOnLine(nsIFrame*& aFrame, PRInt32 aLineNumber);
01498 #ifdef IBMBIDI
01499   NS_IMETHOD CheckLineOrder(PRInt32                  aLine,
01500                             PRBool                   *aIsReordered,
01501                             nsIFrame                 **aFirstVisual,
01502                             nsIFrame                 **aLastVisual);
01503 #endif
01504   nsresult Init(nsLineList& aLines, PRBool aRightToLeft);
01505 
01506 protected:
01507   PRInt32 NumLines() const {
01508     return mNumLines;
01509   }
01510 
01511   nsLineBox* CurrentLine() {
01512     return mLines[mIndex];
01513   }
01514 
01515   nsLineBox* PrevLine() {
01516     if (0 == mIndex) {
01517       return nsnull;
01518     }
01519     return mLines[--mIndex];
01520   }
01521 
01522   nsLineBox* NextLine() {
01523     if (mIndex >= mNumLines - 1) {
01524       return nsnull;
01525     }
01526     return mLines[++mIndex];
01527   }
01528 
01529   nsLineBox* LineAt(PRInt32 aIndex) {
01530     if ((aIndex < 0) || (aIndex >= mNumLines)) {
01531       return nsnull;
01532     }
01533     return mLines[aIndex];
01534   }
01535 
01536   nsLineBox** mLines;
01537   PRInt32 mIndex;
01538   PRInt32 mNumLines;
01539   PRPackedBool mRightToLeft;
01540 };
01541 
01542 #endif /* nsLineBox_h___ */