LCOV - code coverage report
Current view: directory - layout/generic - nsLineBox.h (source / functions) Found Hit Coverage
Test: app.info Lines: 359 0 0.0 %
Date: 2012-06-02 Functions: 116 0 0.0 %

       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___ */

Generated by: LCOV version 1.7