LCOV - code coverage report
Current view: directory - layout/xul/base/src - nsBoxFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 629 0 0.0 %
Date: 2012-06-02 Functions: 58 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set ts=2 sw=2 et tw=80: */
       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                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : //
      41                 : // Eric Vaughan
      42                 : // Netscape Communications
      43                 : //
      44                 : // See documentation in associated header file
      45                 : //
      46                 : 
      47                 : // How boxes layout
      48                 : // ----------------
      49                 : // Boxes layout a bit differently than html. html does a bottom up layout. Where boxes do a top down.
      50                 : // 1) First thing a box does it goes out and askes each child for its min, max, and preferred sizes.
      51                 : // 2) It then adds them up to determine its size.
      52                 : // 3) If the box was asked to layout it self intrinically it will layout its children at their preferred size
      53                 : //    otherwise it will layout the child at the size it was told to. It will squeeze or stretch its children if 
      54                 : //    Necessary.
      55                 : //
      56                 : // However there is a catch. Some html components like block frames can not determine their preferred size. 
      57                 : // this is their size if they were laid out intrinsically. So the box will flow the child to determine this can
      58                 : // cache the value.
      59                 : 
      60                 : // Boxes and Incremental Reflow
      61                 : // ----------------------------
      62                 : // Boxes layout out top down by adding up their children's min, max, and preferred sizes. Only problem is if a incremental
      63                 : // reflow occurs. The preferred size of a child deep in the hierarchy could change. And this could change
      64                 : // any number of syblings around the box. Basically any children in the reflow chain must have their caches cleared
      65                 : // so when asked for there current size they can relayout themselves. 
      66                 : 
      67                 : #include "nsBoxLayoutState.h"
      68                 : #include "nsBoxFrame.h"
      69                 : #include "nsStyleContext.h"
      70                 : #include "nsPresContext.h"
      71                 : #include "nsCOMPtr.h"
      72                 : #include "nsINameSpaceManager.h"
      73                 : #include "nsGkAtoms.h"
      74                 : #include "nsIContent.h"
      75                 : #include "nsHTMLParts.h"
      76                 : #include "nsIViewManager.h"
      77                 : #include "nsIView.h"
      78                 : #include "nsIPresShell.h"
      79                 : #include "nsCSSRendering.h"
      80                 : #include "nsIServiceManager.h"
      81                 : #include "nsBoxLayout.h"
      82                 : #include "nsSprocketLayout.h"
      83                 : #include "nsIDocument.h"
      84                 : #include "nsIScrollableFrame.h"
      85                 : #include "nsWidgetsCID.h"
      86                 : #include "nsCSSAnonBoxes.h"
      87                 : #include "nsContainerFrame.h"
      88                 : #include "nsIDOMDocument.h"
      89                 : #include "nsIDOMElement.h"
      90                 : #include "nsITheme.h"
      91                 : #include "nsTransform2D.h"
      92                 : #include "nsEventStateManager.h"
      93                 : #include "nsEventDispatcher.h"
      94                 : #include "nsIDOMEvent.h"
      95                 : #include "nsIPrivateDOMEvent.h"
      96                 : #include "nsDisplayList.h"
      97                 : #include "mozilla/Preferences.h"
      98                 : 
      99                 : // Needed for Print Preview
     100                 : #include "nsIURI.h"
     101                 : 
     102                 : using namespace mozilla;
     103                 : 
     104                 : //define DEBUG_REDRAW
     105                 : 
     106                 : #define DEBUG_SPRING_SIZE 8
     107                 : #define DEBUG_BORDER_SIZE 2
     108                 : #define COIL_SIZE 8
     109                 : 
     110                 : //#define TEST_SANITY
     111                 : 
     112                 : #ifdef DEBUG_rods
     113                 : //#define DO_NOISY_REFLOW
     114                 : #endif
     115                 : 
     116                 : #ifdef DEBUG_LAYOUT
     117                 : bool nsBoxFrame::gDebug = false;
     118                 : nsIBox* nsBoxFrame::mDebugChild = nsnull;
     119                 : #endif
     120                 : 
     121                 : nsIFrame*
     122               0 : NS_NewBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, bool aIsRoot, nsBoxLayout* aLayoutManager)
     123                 : {
     124               0 :   return new (aPresShell) nsBoxFrame(aPresShell, aContext, aIsRoot, aLayoutManager);
     125                 : }
     126                 : 
     127                 : nsIFrame*
     128               0 : NS_NewBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
     129                 : {
     130               0 :   return new (aPresShell) nsBoxFrame(aPresShell, aContext);
     131                 : }
     132                 : 
     133               0 : NS_IMPL_FRAMEARENA_HELPERS(nsBoxFrame)
     134                 : 
     135               0 : nsBoxFrame::nsBoxFrame(nsIPresShell* aPresShell,
     136                 :                        nsStyleContext* aContext,
     137                 :                        bool aIsRoot,
     138                 :                        nsBoxLayout* aLayoutManager) :
     139               0 :   nsContainerFrame(aContext)
     140                 : {
     141               0 :   mState |= NS_STATE_IS_HORIZONTAL;
     142               0 :   mState |= NS_STATE_AUTO_STRETCH;
     143                 : 
     144               0 :   if (aIsRoot) 
     145               0 :      mState |= NS_STATE_IS_ROOT;
     146                 : 
     147               0 :   mValign = vAlign_Top;
     148               0 :   mHalign = hAlign_Left;
     149                 :   
     150                 :   // if no layout manager specified us the static sprocket layout
     151               0 :   nsCOMPtr<nsBoxLayout> layout = aLayoutManager;
     152                 : 
     153               0 :   if (layout == nsnull) {
     154               0 :     NS_NewSprocketLayout(aPresShell, layout);
     155                 :   }
     156                 : 
     157               0 :   SetLayoutManager(layout);
     158               0 : }
     159                 : 
     160               0 : nsBoxFrame::~nsBoxFrame()
     161                 : {
     162               0 : }
     163                 : 
     164                 : NS_IMETHODIMP
     165               0 : nsBoxFrame::SetInitialChildList(ChildListID     aListID,
     166                 :                                 nsFrameList&    aChildList)
     167                 : {
     168               0 :   nsresult r = nsContainerFrame::SetInitialChildList(aListID, aChildList);
     169               0 :   if (r == NS_OK) {
     170                 :     // initialize our list of infos.
     171               0 :     nsBoxLayoutState state(PresContext());
     172               0 :     CheckBoxOrder(state);
     173               0 :     if (mLayoutManager)
     174               0 :       mLayoutManager->ChildrenSet(this, state, mFrames.FirstChild());
     175                 :   } else {
     176               0 :     NS_WARNING("Warning add child failed!!\n");
     177                 :   }
     178                 : 
     179               0 :   return r;
     180                 : }
     181                 : 
     182                 : /* virtual */ void
     183               0 : nsBoxFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
     184                 : {
     185               0 :   nsContainerFrame::DidSetStyleContext(aOldStyleContext);
     186                 : 
     187                 :   // The values that CacheAttributes() computes depend on our style,
     188                 :   // so we need to recompute them here...
     189               0 :   CacheAttributes();
     190               0 : }
     191                 : 
     192                 : /**
     193                 :  * Initialize us. This is a good time to get the alignment of the box
     194                 :  */
     195                 : NS_IMETHODIMP
     196               0 : nsBoxFrame::Init(nsIContent*      aContent,
     197                 :                  nsIFrame*        aParent,
     198                 :                  nsIFrame*        aPrevInFlow)
     199                 : {
     200               0 :   nsresult  rv = nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
     201               0 :   NS_ENSURE_SUCCESS(rv, rv);
     202                 : 
     203               0 :   MarkIntrinsicWidthsDirty();
     204                 : 
     205               0 :   CacheAttributes();
     206                 : 
     207                 : #ifdef DEBUG_LAYOUT
     208                 :     // if we are root and this
     209                 :   if (mState & NS_STATE_IS_ROOT) 
     210                 :       GetDebugPref(GetPresContext());
     211                 : #endif
     212                 : 
     213               0 :   UpdateMouseThrough();
     214                 : 
     215                 :   // register access key
     216               0 :   rv = RegUnregAccessKey(true);
     217                 : 
     218               0 :   return rv;
     219                 : }
     220                 : 
     221               0 : void nsBoxFrame::UpdateMouseThrough()
     222                 : {
     223               0 :   if (mContent) {
     224                 :     static nsIContent::AttrValuesArray strings[] =
     225                 :       {&nsGkAtoms::never, &nsGkAtoms::always, nsnull};
     226               0 :     switch (mContent->FindAttrValueIn(kNameSpaceID_None,
     227               0 :               nsGkAtoms::mousethrough, strings, eCaseMatters)) {
     228               0 :       case 0: AddStateBits(NS_FRAME_MOUSE_THROUGH_NEVER); break;
     229               0 :       case 1: AddStateBits(NS_FRAME_MOUSE_THROUGH_ALWAYS); break;
     230                 :       case 2: {
     231               0 :         RemoveStateBits(NS_FRAME_MOUSE_THROUGH_ALWAYS);
     232               0 :         RemoveStateBits(NS_FRAME_MOUSE_THROUGH_NEVER);
     233               0 :         break;
     234                 :       }
     235                 :     }
     236                 :   }
     237               0 : }
     238                 : 
     239                 : void
     240               0 : nsBoxFrame::CacheAttributes()
     241                 : {
     242                 :   /*
     243                 :   printf("Caching: ");
     244                 :   DumpBox(stdout);
     245                 :   printf("\n");
     246                 :    */
     247                 : 
     248               0 :   mValign = vAlign_Top;
     249               0 :   mHalign = hAlign_Left;
     250                 : 
     251               0 :   bool orient = false;
     252               0 :   GetInitialOrientation(orient); 
     253               0 :   if (orient)
     254               0 :     mState |= NS_STATE_IS_HORIZONTAL;
     255                 :   else
     256               0 :     mState &= ~NS_STATE_IS_HORIZONTAL;
     257                 : 
     258               0 :   bool normal = true;
     259               0 :   GetInitialDirection(normal); 
     260               0 :   if (normal)
     261               0 :     mState |= NS_STATE_IS_DIRECTION_NORMAL;
     262                 :   else
     263               0 :     mState &= ~NS_STATE_IS_DIRECTION_NORMAL;
     264                 : 
     265               0 :   GetInitialVAlignment(mValign);
     266               0 :   GetInitialHAlignment(mHalign);
     267                 :   
     268               0 :   bool equalSize = false;
     269               0 :   GetInitialEqualSize(equalSize); 
     270               0 :   if (equalSize)
     271               0 :         mState |= NS_STATE_EQUAL_SIZE;
     272                 :     else
     273               0 :         mState &= ~NS_STATE_EQUAL_SIZE;
     274                 : 
     275               0 :   bool autostretch = !!(mState & NS_STATE_AUTO_STRETCH);
     276               0 :   GetInitialAutoStretch(autostretch);
     277               0 :   if (autostretch)
     278               0 :         mState |= NS_STATE_AUTO_STRETCH;
     279                 :      else
     280               0 :         mState &= ~NS_STATE_AUTO_STRETCH;
     281                 : 
     282                 : 
     283                 : #ifdef DEBUG_LAYOUT
     284                 :   bool debug = mState & NS_STATE_SET_TO_DEBUG;
     285                 :   bool debugSet = GetInitialDebug(debug); 
     286                 :   if (debugSet) {
     287                 :         mState |= NS_STATE_DEBUG_WAS_SET;
     288                 :         if (debug)
     289                 :             mState |= NS_STATE_SET_TO_DEBUG;
     290                 :         else
     291                 :             mState &= ~NS_STATE_SET_TO_DEBUG;
     292                 :   } else {
     293                 :         mState &= ~NS_STATE_DEBUG_WAS_SET;
     294                 :   }
     295                 : #endif
     296               0 : }
     297                 : 
     298                 : #ifdef DEBUG_LAYOUT
     299                 : bool
     300                 : nsBoxFrame::GetInitialDebug(bool& aDebug)
     301                 : {
     302                 :   if (!GetContent())
     303                 :     return false;
     304                 : 
     305                 :   static nsIContent::AttrValuesArray strings[] =
     306                 :     {&nsGkAtoms::_false, &nsGkAtoms::_true, nsnull};
     307                 :   PRInt32 index = GetContent()->FindAttrValueIn(kNameSpaceID_None,
     308                 :       nsGkAtoms::debug, strings, eCaseMatters);
     309                 :   if (index >= 0) {
     310                 :     aDebug = index == 1;
     311                 :     return true;
     312                 :   }
     313                 : 
     314                 :   return false;
     315                 : }
     316                 : #endif
     317                 : 
     318                 : bool
     319               0 : nsBoxFrame::GetInitialHAlignment(nsBoxFrame::Halignment& aHalign)
     320                 : {
     321               0 :   if (!GetContent())
     322               0 :     return false;
     323                 : 
     324                 :   // XXXdwh Everything inside this if statement is deprecated code.
     325                 :   static nsIContent::AttrValuesArray alignStrings[] =
     326                 :     {&nsGkAtoms::left, &nsGkAtoms::right, nsnull};
     327                 :   static const Halignment alignValues[] = {hAlign_Left, hAlign_Right};
     328               0 :   PRInt32 index = GetContent()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::align,
     329               0 :       alignStrings, eCaseMatters);
     330               0 :   if (index >= 0) {
     331               0 :     aHalign = alignValues[index];
     332               0 :     return true;
     333                 :   }
     334                 :       
     335                 :   // Now that the deprecated stuff is out of the way, we move on to check the appropriate 
     336                 :   // attribute.  For horizontal boxes, we are checking the PACK attribute.  For vertical boxes
     337                 :   // we are checking the ALIGN attribute.
     338               0 :   nsIAtom* attrName = IsHorizontal() ? nsGkAtoms::pack : nsGkAtoms::align;
     339                 :   static nsIContent::AttrValuesArray strings[] =
     340                 :     {&nsGkAtoms::_empty, &nsGkAtoms::start, &nsGkAtoms::center, &nsGkAtoms::end, nsnull};
     341                 :   static const Halignment values[] =
     342                 :     {hAlign_Left/*not used*/, hAlign_Left, hAlign_Center, hAlign_Right};
     343               0 :   index = GetContent()->FindAttrValueIn(kNameSpaceID_None, attrName,
     344               0 :       strings, eCaseMatters);
     345                 : 
     346               0 :   if (index == nsIContent::ATTR_VALUE_NO_MATCH) {
     347                 :     // The attr was present but had a nonsensical value. Revert to the default.
     348               0 :     return false;
     349                 :   }
     350               0 :   if (index > 0) {    
     351               0 :     aHalign = values[index];
     352               0 :     return true;
     353                 :   }
     354                 : 
     355                 :   // Now that we've checked for the attribute it's time to check CSS.  For 
     356                 :   // horizontal boxes we're checking PACK.  For vertical boxes we are checking
     357                 :   // ALIGN.
     358               0 :   const nsStyleXUL* boxInfo = GetStyleXUL();
     359               0 :   if (IsHorizontal()) {
     360               0 :     switch (boxInfo->mBoxPack) {
     361                 :       case NS_STYLE_BOX_PACK_START:
     362               0 :         aHalign = nsBoxFrame::hAlign_Left;
     363               0 :         return true;
     364                 :       case NS_STYLE_BOX_PACK_CENTER:
     365               0 :         aHalign = nsBoxFrame::hAlign_Center;
     366               0 :         return true;
     367                 :       case NS_STYLE_BOX_PACK_END:
     368               0 :         aHalign = nsBoxFrame::hAlign_Right;
     369               0 :         return true;
     370                 :       default: // Nonsensical value. Just bail.
     371               0 :         return false;
     372                 :     }
     373                 :   }
     374                 :   else {
     375               0 :     switch (boxInfo->mBoxAlign) {
     376                 :       case NS_STYLE_BOX_ALIGN_START:
     377               0 :         aHalign = nsBoxFrame::hAlign_Left;
     378               0 :         return true;
     379                 :       case NS_STYLE_BOX_ALIGN_CENTER:
     380               0 :         aHalign = nsBoxFrame::hAlign_Center;
     381               0 :         return true;
     382                 :       case NS_STYLE_BOX_ALIGN_END:
     383               0 :         aHalign = nsBoxFrame::hAlign_Right;
     384               0 :         return true;
     385                 :       default: // Nonsensical value. Just bail.
     386               0 :         return false;
     387                 :     }
     388                 :   }
     389                 : 
     390                 :   return false;
     391                 : }
     392                 : 
     393                 : bool
     394               0 : nsBoxFrame::GetInitialVAlignment(nsBoxFrame::Valignment& aValign)
     395                 : {
     396               0 :   if (!GetContent())
     397               0 :     return false;
     398                 : 
     399                 :   static nsIContent::AttrValuesArray valignStrings[] =
     400                 :     {&nsGkAtoms::top, &nsGkAtoms::baseline, &nsGkAtoms::middle, &nsGkAtoms::bottom, nsnull};
     401                 :   static const Valignment valignValues[] =
     402                 :     {vAlign_Top, vAlign_BaseLine, vAlign_Middle, vAlign_Bottom};
     403               0 :   PRInt32 index = GetContent()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::valign,
     404               0 :       valignStrings, eCaseMatters);
     405               0 :   if (index >= 0) {
     406               0 :     aValign = valignValues[index];
     407               0 :     return true;
     408                 :   }
     409                 : 
     410                 :   // Now that the deprecated stuff is out of the way, we move on to check the appropriate 
     411                 :   // attribute.  For horizontal boxes, we are checking the ALIGN attribute.  For vertical boxes
     412                 :   // we are checking the PACK attribute.
     413               0 :   nsIAtom* attrName = IsHorizontal() ? nsGkAtoms::align : nsGkAtoms::pack;
     414                 :   static nsIContent::AttrValuesArray strings[] =
     415                 :     {&nsGkAtoms::_empty, &nsGkAtoms::start, &nsGkAtoms::center,
     416                 :      &nsGkAtoms::baseline, &nsGkAtoms::end, nsnull};
     417                 :   static const Valignment values[] =
     418                 :     {vAlign_Top/*not used*/, vAlign_Top, vAlign_Middle, vAlign_BaseLine, vAlign_Bottom};
     419               0 :   index = GetContent()->FindAttrValueIn(kNameSpaceID_None, attrName,
     420               0 :       strings, eCaseMatters);
     421               0 :   if (index == nsIContent::ATTR_VALUE_NO_MATCH) {
     422                 :     // The attr was present but had a nonsensical value. Revert to the default.
     423               0 :     return false;
     424                 :   }
     425               0 :   if (index > 0) {
     426               0 :     aValign = values[index];
     427               0 :     return true;
     428                 :   }
     429                 : 
     430                 :   // Now that we've checked for the attribute it's time to check CSS.  For 
     431                 :   // horizontal boxes we're checking ALIGN.  For vertical boxes we are checking
     432                 :   // PACK.
     433               0 :   const nsStyleXUL* boxInfo = GetStyleXUL();
     434               0 :   if (IsHorizontal()) {
     435               0 :     switch (boxInfo->mBoxAlign) {
     436                 :       case NS_STYLE_BOX_ALIGN_START:
     437               0 :         aValign = nsBoxFrame::vAlign_Top;
     438               0 :         return true;
     439                 :       case NS_STYLE_BOX_ALIGN_CENTER:
     440               0 :         aValign = nsBoxFrame::vAlign_Middle;
     441               0 :         return true;
     442                 :       case NS_STYLE_BOX_ALIGN_BASELINE:
     443               0 :         aValign = nsBoxFrame::vAlign_BaseLine;
     444               0 :         return true;
     445                 :       case NS_STYLE_BOX_ALIGN_END:
     446               0 :         aValign = nsBoxFrame::vAlign_Bottom;
     447               0 :         return true;
     448                 :       default: // Nonsensical value. Just bail.
     449               0 :         return false;
     450                 :     }
     451                 :   }
     452                 :   else {
     453               0 :     switch (boxInfo->mBoxPack) {
     454                 :       case NS_STYLE_BOX_PACK_START:
     455               0 :         aValign = nsBoxFrame::vAlign_Top;
     456               0 :         return true;
     457                 :       case NS_STYLE_BOX_PACK_CENTER:
     458               0 :         aValign = nsBoxFrame::vAlign_Middle;
     459               0 :         return true;
     460                 :       case NS_STYLE_BOX_PACK_END:
     461               0 :         aValign = nsBoxFrame::vAlign_Bottom;
     462               0 :         return true;
     463                 :       default: // Nonsensical value. Just bail.
     464               0 :         return false;
     465                 :     }
     466                 :   }
     467                 : 
     468                 :   return false;
     469                 : }
     470                 : 
     471                 : void
     472               0 : nsBoxFrame::GetInitialOrientation(bool& aIsHorizontal)
     473                 : {
     474                 :  // see if we are a vertical or horizontal box.
     475               0 :   if (!GetContent())
     476               0 :     return;
     477                 : 
     478                 :   // Check the style system first.
     479               0 :   const nsStyleXUL* boxInfo = GetStyleXUL();
     480               0 :   if (boxInfo->mBoxOrient == NS_STYLE_BOX_ORIENT_HORIZONTAL)
     481               0 :     aIsHorizontal = true;
     482                 :   else 
     483               0 :     aIsHorizontal = false;
     484                 : 
     485                 :   // Now see if we have an attribute.  The attribute overrides
     486                 :   // the style system value.
     487                 :   static nsIContent::AttrValuesArray strings[] =
     488                 :     {&nsGkAtoms::vertical, &nsGkAtoms::horizontal, nsnull};
     489               0 :   PRInt32 index = GetContent()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::orient,
     490               0 :       strings, eCaseMatters);
     491               0 :   if (index >= 0) {
     492               0 :     aIsHorizontal = index == 1;
     493                 :   }
     494                 : }
     495                 : 
     496                 : void
     497               0 : nsBoxFrame::GetInitialDirection(bool& aIsNormal)
     498                 : {
     499               0 :   if (!GetContent())
     500               0 :     return;
     501                 : 
     502               0 :   if (IsHorizontal()) {
     503                 :     // For horizontal boxes only, we initialize our value based off the CSS 'direction' property.
     504                 :     // This means that BiDI users will end up with horizontally inverted chrome.
     505               0 :     aIsNormal = (GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_LTR); // If text runs RTL then so do we.
     506                 :   }
     507                 :   else
     508               0 :     aIsNormal = true; // Assume a normal direction in the vertical case.
     509                 : 
     510                 :   // Now check the style system to see if we should invert aIsNormal.
     511               0 :   const nsStyleXUL* boxInfo = GetStyleXUL();
     512               0 :   if (boxInfo->mBoxDirection == NS_STYLE_BOX_DIRECTION_REVERSE)
     513               0 :     aIsNormal = !aIsNormal; // Invert our direction.
     514                 :   
     515                 :   // Now see if we have an attribute.  The attribute overrides
     516                 :   // the style system value.
     517                 :   static nsIContent::AttrValuesArray strings[] =
     518                 :     {&nsGkAtoms::reverse, &nsGkAtoms::ltr, &nsGkAtoms::rtl, nsnull};
     519               0 :   PRInt32 index = GetContent()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::dir,
     520               0 :       strings, eCaseMatters);
     521               0 :   if (index >= 0) {
     522               0 :     bool values[] = {!aIsNormal, true, false};
     523               0 :     aIsNormal = values[index];
     524                 :   }
     525                 : }
     526                 : 
     527                 : /* Returns true if it was set.
     528                 :  */
     529                 : bool
     530               0 : nsBoxFrame::GetInitialEqualSize(bool& aEqualSize)
     531                 : {
     532                 :  // see if we are a vertical or horizontal box.
     533               0 :   if (!GetContent())
     534               0 :      return false;
     535                 : 
     536               0 :   if (GetContent()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::equalsize,
     537               0 :                            nsGkAtoms::always, eCaseMatters)) {
     538               0 :     aEqualSize = true;
     539               0 :     return true;
     540                 :   }
     541                 : 
     542               0 :   return false;
     543                 : }
     544                 : 
     545                 : /* Returns true if it was set.
     546                 :  */
     547                 : bool
     548               0 : nsBoxFrame::GetInitialAutoStretch(bool& aStretch)
     549                 : {
     550               0 :   if (!GetContent())
     551               0 :      return false;
     552                 :   
     553                 :   // Check the align attribute.
     554                 :   static nsIContent::AttrValuesArray strings[] =
     555                 :     {&nsGkAtoms::_empty, &nsGkAtoms::stretch, nsnull};
     556               0 :   PRInt32 index = GetContent()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::align,
     557               0 :       strings, eCaseMatters);
     558               0 :   if (index != nsIContent::ATTR_MISSING && index != 0) {
     559               0 :     aStretch = index == 1;
     560               0 :     return true;
     561                 :   }
     562                 : 
     563                 :   // Check the CSS box-align property.
     564               0 :   const nsStyleXUL* boxInfo = GetStyleXUL();
     565               0 :   aStretch = (boxInfo->mBoxAlign == NS_STYLE_BOX_ALIGN_STRETCH);
     566                 : 
     567               0 :   return true;
     568                 : }
     569                 : 
     570                 : NS_IMETHODIMP
     571               0 : nsBoxFrame::DidReflow(nsPresContext*           aPresContext,
     572                 :                       const nsHTMLReflowState*  aReflowState,
     573                 :                       nsDidReflowStatus         aStatus)
     574                 : {
     575                 :   nsFrameState preserveBits =
     576               0 :     mState & (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN);
     577               0 :   nsresult rv = nsFrame::DidReflow(aPresContext, aReflowState, aStatus);
     578               0 :   mState |= preserveBits;
     579               0 :   return rv;
     580                 : }
     581                 : 
     582                 : bool
     583               0 : nsBoxFrame::HonorPrintBackgroundSettings()
     584                 : {
     585               0 :   return (!mContent || !mContent->IsInNativeAnonymousSubtree()) &&
     586               0 :     nsContainerFrame::HonorPrintBackgroundSettings();
     587                 : }
     588                 : 
     589                 : #ifdef DO_NOISY_REFLOW
     590                 : static int myCounter = 0;
     591                 : static void printSize(char * aDesc, nscoord aSize) 
     592                 : {
     593                 :   printf(" %s: ", aDesc);
     594                 :   if (aSize == NS_UNCONSTRAINEDSIZE) {
     595                 :     printf("UC");
     596                 :   } else {
     597                 :     printf("%d", aSize);
     598                 :   }
     599                 : }
     600                 : #endif
     601                 : 
     602                 : /* virtual */ nscoord
     603               0 : nsBoxFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
     604                 : {
     605                 :   nscoord result;
     606               0 :   DISPLAY_MIN_WIDTH(this, result);
     607                 : 
     608               0 :   nsBoxLayoutState state(PresContext(), aRenderingContext);
     609               0 :   nsSize minSize = GetMinSize(state);
     610                 : 
     611                 :   // GetMinSize returns border-box width, and we want to return content
     612                 :   // width.  Since Reflow uses the reflow state's border and padding, we
     613                 :   // actually just want to subtract what GetMinSize added, which is the
     614                 :   // result of GetBorderAndPadding.
     615               0 :   nsMargin bp;
     616               0 :   GetBorderAndPadding(bp);
     617                 : 
     618               0 :   result = minSize.width - bp.LeftRight();
     619               0 :   result = NS_MAX(result, 0);
     620                 : 
     621               0 :   return result;
     622                 : }
     623                 : 
     624                 : /* virtual */ nscoord
     625               0 : nsBoxFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
     626                 : {
     627                 :   nscoord result;
     628               0 :   DISPLAY_PREF_WIDTH(this, result);
     629                 : 
     630               0 :   nsBoxLayoutState state(PresContext(), aRenderingContext);
     631               0 :   nsSize prefSize = GetPrefSize(state);
     632                 : 
     633                 :   // GetPrefSize returns border-box width, and we want to return content
     634                 :   // width.  Since Reflow uses the reflow state's border and padding, we
     635                 :   // actually just want to subtract what GetPrefSize added, which is the
     636                 :   // result of GetBorderAndPadding.
     637               0 :   nsMargin bp;
     638               0 :   GetBorderAndPadding(bp);
     639                 : 
     640               0 :   result = prefSize.width - bp.LeftRight();
     641               0 :   result = NS_MAX(result, 0);
     642                 : 
     643               0 :   return result;
     644                 : }
     645                 : 
     646                 : NS_IMETHODIMP
     647               0 : nsBoxFrame::Reflow(nsPresContext*          aPresContext,
     648                 :                    nsHTMLReflowMetrics&     aDesiredSize,
     649                 :                    const nsHTMLReflowState& aReflowState,
     650                 :                    nsReflowStatus&          aStatus)
     651                 : {
     652                 :   // If you make changes to this method, please keep nsLeafBoxFrame::Reflow
     653                 :   // in sync, if the changes are applicable there.
     654                 : 
     655               0 :   DO_GLOBAL_REFLOW_COUNT("nsBoxFrame");
     656               0 :   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
     657                 : 
     658               0 :   NS_ASSERTION(aReflowState.ComputedWidth() >=0 &&
     659                 :                aReflowState.ComputedHeight() >= 0, "Computed Size < 0");
     660                 : 
     661                 : #ifdef DO_NOISY_REFLOW
     662                 :   printf("\n-------------Starting BoxFrame Reflow ----------------------------\n");
     663                 :   printf("%p ** nsBF::Reflow %d ", this, myCounter++);
     664                 :   
     665                 :   printSize("AW", aReflowState.availableWidth);
     666                 :   printSize("AH", aReflowState.availableHeight);
     667                 :   printSize("CW", aReflowState.ComputedWidth());
     668                 :   printSize("CH", aReflowState.ComputedHeight());
     669                 : 
     670                 :   printf(" *\n");
     671                 : 
     672                 : #endif
     673                 : 
     674               0 :   aStatus = NS_FRAME_COMPLETE;
     675                 : 
     676                 :   // create the layout state
     677                 :   nsBoxLayoutState state(aPresContext, aReflowState.rendContext,
     678               0 :                          &aReflowState, aReflowState.mReflowDepth);
     679                 : 
     680               0 :   nsSize computedSize(aReflowState.ComputedWidth(),aReflowState.ComputedHeight());
     681                 : 
     682               0 :   nsMargin m;
     683               0 :   m = aReflowState.mComputedBorderPadding;
     684                 :   // GetBorderAndPadding(m);
     685                 : 
     686               0 :   nsSize prefSize(0,0);
     687                 : 
     688                 :   // if we are told to layout intrinsic then get our preferred size.
     689               0 :   NS_ASSERTION(computedSize.width != NS_INTRINSICSIZE,
     690                 :                "computed width should always be computed");
     691               0 :   if (computedSize.height == NS_INTRINSICSIZE) {
     692               0 :     prefSize = GetPrefSize(state);
     693               0 :     nsSize minSize = GetMinSize(state);
     694               0 :     nsSize maxSize = GetMaxSize(state);
     695                 :     // XXXbz isn't GetPrefSize supposed to bounds-check for us?
     696               0 :     prefSize = BoundsCheck(minSize, prefSize, maxSize);
     697                 :   }
     698                 : 
     699                 :   // get our desiredSize
     700               0 :   computedSize.width += m.left + m.right;
     701                 : 
     702               0 :   if (aReflowState.ComputedHeight() == NS_INTRINSICSIZE) {
     703               0 :     computedSize.height = prefSize.height;
     704                 :     // prefSize is border-box, so we need to figure out the right
     705                 :     // length to apply our min/max constraints to.
     706               0 :     nscoord outsideBoxSizing = 0;
     707               0 :     switch (GetStylePosition()->mBoxSizing) {
     708                 :       case NS_STYLE_BOX_SIZING_CONTENT:
     709               0 :         outsideBoxSizing = aReflowState.mComputedBorderPadding.TopBottom();
     710                 :         // fall through
     711                 :       case NS_STYLE_BOX_SIZING_PADDING:
     712               0 :         outsideBoxSizing -= aReflowState.mComputedPadding.TopBottom();
     713               0 :         break;
     714                 :     }
     715               0 :     computedSize.height -= outsideBoxSizing;
     716                 :     // Note: might be negative now, but that's OK because min-width is
     717                 :     // never negative.
     718               0 :     aReflowState.ApplyMinMaxConstraints(nsnull, &computedSize.height);
     719               0 :     computedSize.height += outsideBoxSizing;
     720                 :   } else {
     721               0 :     computedSize.height += m.top + m.bottom;
     722                 :   }
     723                 : 
     724               0 :   nsRect r(mRect.x, mRect.y, computedSize.width, computedSize.height);
     725                 : 
     726               0 :   SetBounds(state, r);
     727                 :  
     728                 :   // layout our children
     729               0 :   Layout(state);
     730                 :   
     731                 :   // ok our child could have gotten bigger. So lets get its bounds
     732                 :   
     733                 :   // get the ascent
     734               0 :   nscoord ascent = mRect.height;
     735                 : 
     736                 :   // getting the ascent could be a lot of work. Don't get it if
     737                 :   // we are the root. The viewport doesn't care about it.
     738               0 :   if (!(mState & NS_STATE_IS_ROOT)) {
     739               0 :     ascent = GetBoxAscent(state);
     740                 :   }
     741                 : 
     742               0 :   aDesiredSize.width  = mRect.width;
     743               0 :   aDesiredSize.height = mRect.height;
     744               0 :   aDesiredSize.ascent = ascent;
     745                 : 
     746               0 :   aDesiredSize.mOverflowAreas = GetOverflowAreas();
     747                 : 
     748                 : #ifdef DO_NOISY_REFLOW
     749                 :   {
     750                 :     printf("%p ** nsBF(done) W:%d H:%d  ", this, aDesiredSize.width, aDesiredSize.height);
     751                 : 
     752                 :     if (maxElementSize) {
     753                 :       printf("MW:%d\n", *maxElementWidth); 
     754                 :     } else {
     755                 :       printf("MW:?\n"); 
     756                 :     }
     757                 : 
     758                 :   }
     759                 : #endif
     760                 : 
     761               0 :   ReflowAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus);
     762                 : 
     763               0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
     764               0 :   return NS_OK;
     765                 : }
     766                 : 
     767                 : nsSize
     768               0 : nsBoxFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState)
     769                 : {
     770               0 :   NS_ASSERTION(aBoxLayoutState.GetRenderingContext(),
     771                 :                "must have rendering context");
     772                 : 
     773               0 :   nsSize size(0,0);
     774               0 :   DISPLAY_PREF_SIZE(this, size);
     775               0 :   if (!DoesNeedRecalc(mPrefSize)) {
     776               0 :      return mPrefSize;
     777                 :   }
     778                 : 
     779                 : #ifdef DEBUG_LAYOUT
     780                 :   PropagateDebug(aBoxLayoutState);
     781                 : #endif
     782                 : 
     783               0 :   if (IsCollapsed())
     784               0 :     return size;
     785                 : 
     786                 :   // if the size was not completely redefined in CSS then ask our children
     787                 :   bool widthSet, heightSet;
     788               0 :   if (!nsIBox::AddCSSPrefSize(this, size, widthSet, heightSet))
     789                 :   {
     790               0 :     if (mLayoutManager) {
     791               0 :       nsSize layoutSize = mLayoutManager->GetPrefSize(this, aBoxLayoutState);
     792               0 :       if (!widthSet)
     793               0 :         size.width = layoutSize.width;
     794               0 :       if (!heightSet)
     795               0 :         size.height = layoutSize.height;
     796                 :     }
     797                 :     else {
     798               0 :       size = nsBox::GetPrefSize(aBoxLayoutState);
     799                 :     }
     800                 :   }
     801                 : 
     802               0 :   nsSize minSize = GetMinSize(aBoxLayoutState);
     803               0 :   nsSize maxSize = GetMaxSize(aBoxLayoutState);
     804               0 :   mPrefSize = BoundsCheck(minSize, size, maxSize);
     805                 :  
     806               0 :   return mPrefSize;
     807                 : }
     808                 : 
     809                 : nscoord
     810               0 : nsBoxFrame::GetBoxAscent(nsBoxLayoutState& aBoxLayoutState)
     811                 : {
     812               0 :   if (!DoesNeedRecalc(mAscent))
     813               0 :      return mAscent;
     814                 : 
     815                 : #ifdef DEBUG_LAYOUT
     816                 :   PropagateDebug(aBoxLayoutState);
     817                 : #endif
     818                 : 
     819               0 :   if (IsCollapsed())
     820               0 :     return 0;
     821                 : 
     822               0 :   if (mLayoutManager)
     823               0 :     mAscent = mLayoutManager->GetAscent(this, aBoxLayoutState);
     824                 :   else
     825               0 :     mAscent = nsBox::GetBoxAscent(aBoxLayoutState);
     826                 : 
     827               0 :   return mAscent;
     828                 : }
     829                 : 
     830                 : nsSize
     831               0 : nsBoxFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState)
     832                 : {
     833               0 :   NS_ASSERTION(aBoxLayoutState.GetRenderingContext(),
     834                 :                "must have rendering context");
     835                 : 
     836               0 :   nsSize size(0,0);
     837               0 :   DISPLAY_MIN_SIZE(this, size);
     838               0 :   if (!DoesNeedRecalc(mMinSize)) {
     839               0 :     return mMinSize;
     840                 :   }
     841                 : 
     842                 : #ifdef DEBUG_LAYOUT
     843                 :   PropagateDebug(aBoxLayoutState);
     844                 : #endif
     845                 : 
     846               0 :   if (IsCollapsed())
     847               0 :     return size;
     848                 : 
     849                 :   // if the size was not completely redefined in CSS then ask our children
     850                 :   bool widthSet, heightSet;
     851               0 :   if (!nsIBox::AddCSSMinSize(aBoxLayoutState, this, size, widthSet, heightSet))
     852                 :   {
     853               0 :     if (mLayoutManager) {
     854               0 :       nsSize layoutSize = mLayoutManager->GetMinSize(this, aBoxLayoutState);
     855               0 :       if (!widthSet)
     856               0 :         size.width = layoutSize.width;
     857               0 :       if (!heightSet)
     858               0 :         size.height = layoutSize.height;
     859                 :     }
     860                 :     else {
     861               0 :       size = nsBox::GetMinSize(aBoxLayoutState);
     862                 :     }
     863                 :   }
     864                 :   
     865               0 :   mMinSize = size;
     866                 : 
     867               0 :   return size;
     868                 : }
     869                 : 
     870                 : nsSize
     871               0 : nsBoxFrame::GetMaxSize(nsBoxLayoutState& aBoxLayoutState)
     872                 : {
     873               0 :   NS_ASSERTION(aBoxLayoutState.GetRenderingContext(),
     874                 :                "must have rendering context");
     875                 : 
     876               0 :   nsSize size(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
     877               0 :   DISPLAY_MAX_SIZE(this, size);
     878               0 :   if (!DoesNeedRecalc(mMaxSize)) {
     879               0 :     return mMaxSize;
     880                 :   }
     881                 : 
     882                 : #ifdef DEBUG_LAYOUT
     883                 :   PropagateDebug(aBoxLayoutState);
     884                 : #endif
     885                 : 
     886               0 :   if (IsCollapsed())
     887               0 :     return size;
     888                 : 
     889                 :   // if the size was not completely redefined in CSS then ask our children
     890                 :   bool widthSet, heightSet;
     891               0 :   if (!nsIBox::AddCSSMaxSize(this, size, widthSet, heightSet))
     892                 :   {
     893               0 :     if (mLayoutManager) {
     894               0 :       nsSize layoutSize = mLayoutManager->GetMaxSize(this, aBoxLayoutState);
     895               0 :       if (!widthSet)
     896               0 :         size.width = layoutSize.width;
     897               0 :       if (!heightSet)
     898               0 :         size.height = layoutSize.height;
     899                 :     }
     900                 :     else {
     901               0 :       size = nsBox::GetMaxSize(aBoxLayoutState);
     902                 :     }
     903                 :   }
     904                 : 
     905               0 :   mMaxSize = size;
     906                 : 
     907               0 :   return size;
     908                 : }
     909                 : 
     910                 : nscoord
     911               0 : nsBoxFrame::GetFlex(nsBoxLayoutState& aBoxLayoutState)
     912                 : {
     913               0 :   if (!DoesNeedRecalc(mFlex))
     914               0 :      return mFlex;
     915                 : 
     916               0 :   mFlex = nsBox::GetFlex(aBoxLayoutState);
     917                 : 
     918               0 :   return mFlex;
     919                 : }
     920                 : 
     921                 : /**
     922                 :  * If subclassing please subclass this method not layout. 
     923                 :  * layout will call this method.
     924                 :  */
     925                 : NS_IMETHODIMP
     926               0 : nsBoxFrame::DoLayout(nsBoxLayoutState& aState)
     927                 : {
     928               0 :   PRUint32 oldFlags = aState.LayoutFlags();
     929               0 :   aState.SetLayoutFlags(0);
     930                 : 
     931               0 :   nsresult rv = NS_OK;
     932               0 :   if (mLayoutManager) {
     933               0 :     CoordNeedsRecalc(mAscent);
     934               0 :     rv = mLayoutManager->Layout(this, aState);
     935                 :   }
     936                 : 
     937               0 :   aState.SetLayoutFlags(oldFlags);
     938                 : 
     939               0 :   if (HasAbsolutelyPositionedChildren()) {
     940                 :     // Set up a |reflowState| to pass into ReflowAbsoluteFrames
     941                 :     nsHTMLReflowState reflowState(aState.PresContext(), this,
     942                 :                                   aState.GetRenderingContext(),
     943               0 :                                   nsSize(mRect.width, NS_UNCONSTRAINEDSIZE));
     944                 : 
     945                 :     // Set up a |desiredSize| to pass into ReflowAbsoluteFrames
     946               0 :     nsHTMLReflowMetrics desiredSize;
     947               0 :     desiredSize.width  = mRect.width;
     948               0 :     desiredSize.height = mRect.height;
     949                 : 
     950                 :     // get the ascent (cribbed from ::Reflow)
     951               0 :     nscoord ascent = mRect.height;
     952                 : 
     953                 :     // getting the ascent could be a lot of work. Don't get it if
     954                 :     // we are the root. The viewport doesn't care about it.
     955               0 :     if (!(mState & NS_STATE_IS_ROOT)) {
     956               0 :       ascent = GetBoxAscent(aState);
     957                 :     }
     958               0 :     desiredSize.ascent = ascent;
     959               0 :     desiredSize.mOverflowAreas = GetOverflowAreas();
     960                 : 
     961                 :     // Set up a |reflowStatus| to pass into ReflowAbsoluteFrames
     962                 :     // (just a dummy value; hopefully that's OK)
     963               0 :     nsReflowStatus reflowStatus = NS_FRAME_COMPLETE;
     964                 :     ReflowAbsoluteFrames(aState.PresContext(), desiredSize,
     965               0 :                          reflowState, reflowStatus);
     966                 :   }
     967                 : 
     968               0 :   return rv;
     969                 : }
     970                 : 
     971                 : void
     972               0 : nsBoxFrame::DestroyFrom(nsIFrame* aDestructRoot)
     973                 : {
     974                 :   // unregister access key
     975               0 :   RegUnregAccessKey(false);
     976                 : 
     977                 :   // clean up the container box's layout manager and child boxes
     978               0 :   SetLayoutManager(nsnull);
     979                 : 
     980               0 :   DestroyAbsoluteFrames(aDestructRoot);
     981                 : 
     982               0 :   nsContainerFrame::DestroyFrom(aDestructRoot);
     983               0 : } 
     984                 : 
     985                 : #ifdef DEBUG_LAYOUT
     986                 : NS_IMETHODIMP
     987                 : nsBoxFrame::SetDebug(nsBoxLayoutState& aState, bool aDebug)
     988                 : {
     989                 :   // see if our state matches the given debug state
     990                 :   bool debugSet = mState & NS_STATE_CURRENTLY_IN_DEBUG;
     991                 :   bool debugChanged = (!aDebug && debugSet) || (aDebug && !debugSet);
     992                 : 
     993                 :   // if it doesn't then tell each child below us the new debug state
     994                 :   if (debugChanged)
     995                 :   {
     996                 :      if (aDebug) {
     997                 :          mState |= NS_STATE_CURRENTLY_IN_DEBUG;
     998                 :      } else {
     999                 :          mState &= ~NS_STATE_CURRENTLY_IN_DEBUG;
    1000                 :      }
    1001                 :  
    1002                 :      SetDebugOnChildList(aState, mFirstChild, aDebug);
    1003                 : 
    1004                 :     MarkIntrinsicWidthsDirty();
    1005                 :   }
    1006                 : 
    1007                 :   return NS_OK;
    1008                 : }
    1009                 : #endif
    1010                 : 
    1011                 : /* virtual */ void
    1012               0 : nsBoxFrame::MarkIntrinsicWidthsDirty()
    1013                 : {
    1014               0 :   SizeNeedsRecalc(mPrefSize);
    1015               0 :   SizeNeedsRecalc(mMinSize);
    1016               0 :   SizeNeedsRecalc(mMaxSize);
    1017               0 :   CoordNeedsRecalc(mFlex);
    1018               0 :   CoordNeedsRecalc(mAscent);
    1019                 : 
    1020               0 :   if (mLayoutManager) {
    1021               0 :     nsBoxLayoutState state(PresContext());
    1022               0 :     mLayoutManager->IntrinsicWidthsDirty(this, state);
    1023                 :   }
    1024                 : 
    1025                 :   // Don't call base class method, since everything it does is within an
    1026                 :   // IsBoxWrapped check.
    1027               0 : }
    1028                 : 
    1029                 : NS_IMETHODIMP
    1030               0 : nsBoxFrame::RemoveFrame(ChildListID     aListID,
    1031                 :                         nsIFrame*       aOldFrame)
    1032                 : {
    1033               0 :   NS_PRECONDITION(aListID == kPrincipalList, "We don't support out-of-flow kids");
    1034               0 :   nsPresContext* presContext = PresContext();
    1035               0 :   nsBoxLayoutState state(presContext);
    1036                 : 
    1037                 :   // remove the child frame
    1038               0 :   mFrames.RemoveFrame(aOldFrame);
    1039                 : 
    1040                 :   // notify the layout manager
    1041               0 :   if (mLayoutManager)
    1042               0 :     mLayoutManager->ChildrenRemoved(this, state, aOldFrame);
    1043                 : 
    1044                 :   // destroy the child frame
    1045               0 :   aOldFrame->Destroy();
    1046                 : 
    1047                 :   // mark us dirty and generate a reflow command
    1048               0 :   PresContext()->PresShell()->
    1049                 :     FrameNeedsReflow(this, nsIPresShell::eTreeChange,
    1050               0 :                      NS_FRAME_HAS_DIRTY_CHILDREN);
    1051               0 :   return NS_OK;
    1052                 : }
    1053                 : 
    1054                 : NS_IMETHODIMP
    1055               0 : nsBoxFrame::InsertFrames(ChildListID     aListID,
    1056                 :                          nsIFrame*       aPrevFrame,
    1057                 :                          nsFrameList&    aFrameList)
    1058                 : {
    1059               0 :    NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
    1060                 :                 "inserting after sibling frame with different parent");
    1061               0 :    NS_ASSERTION(!aPrevFrame || mFrames.ContainsFrame(aPrevFrame),
    1062                 :                 "inserting after sibling frame not in our child list");
    1063               0 :    NS_PRECONDITION(aListID == kPrincipalList, "We don't support out-of-flow kids");
    1064               0 :    nsBoxLayoutState state(PresContext());
    1065                 : 
    1066                 :    // insert the child frames
    1067                 :    const nsFrameList::Slice& newFrames =
    1068               0 :      mFrames.InsertFrames(this, aPrevFrame, aFrameList);
    1069                 : 
    1070                 :    // notify the layout manager
    1071               0 :    if (mLayoutManager)
    1072               0 :      mLayoutManager->ChildrenInserted(this, state, aPrevFrame, newFrames);
    1073                 : 
    1074                 :    // Make sure to check box order _after_ notifying the layout
    1075                 :    // manager; otherwise the slice we give the layout manager will
    1076                 :    // just be bogus.  If the layout manager cares about the order, we
    1077                 :    // just lose.
    1078               0 :    CheckBoxOrder(state);
    1079                 : 
    1080                 : #ifdef DEBUG_LAYOUT
    1081                 :    // if we are in debug make sure our children are in debug as well.
    1082                 :    if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
    1083                 :        SetDebugOnChildList(state, mFrames.FirstChild(), true);
    1084                 : #endif
    1085                 : 
    1086               0 :    PresContext()->PresShell()->
    1087                 :      FrameNeedsReflow(this, nsIPresShell::eTreeChange,
    1088               0 :                       NS_FRAME_HAS_DIRTY_CHILDREN);
    1089               0 :    return NS_OK;
    1090                 : }
    1091                 : 
    1092                 : 
    1093                 : NS_IMETHODIMP
    1094               0 : nsBoxFrame::AppendFrames(ChildListID     aListID,
    1095                 :                          nsFrameList&    aFrameList)
    1096                 : {
    1097               0 :    NS_PRECONDITION(aListID == kPrincipalList, "We don't support out-of-flow kids");
    1098               0 :    nsBoxLayoutState state(PresContext());
    1099                 : 
    1100                 :    // append the new frames
    1101               0 :    const nsFrameList::Slice& newFrames = mFrames.AppendFrames(this, aFrameList);
    1102                 : 
    1103                 :    // notify the layout manager
    1104               0 :    if (mLayoutManager)
    1105               0 :      mLayoutManager->ChildrenAppended(this, state, newFrames);
    1106                 : 
    1107                 :    // Make sure to check box order _after_ notifying the layout
    1108                 :    // manager; otherwise the slice we give the layout manager will
    1109                 :    // just be bogus.  If the layout manager cares about the order, we
    1110                 :    // just lose.
    1111               0 :    CheckBoxOrder(state);
    1112                 : 
    1113                 : #ifdef DEBUG_LAYOUT
    1114                 :    // if we are in debug make sure our children are in debug as well.
    1115                 :    if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
    1116                 :        SetDebugOnChildList(state, mFrames.FirstChild(), true);
    1117                 : #endif
    1118                 : 
    1119                 :    // XXXbz why is this NS_FRAME_FIRST_REFLOW check here?
    1120               0 :    if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
    1121               0 :      PresContext()->PresShell()->
    1122                 :        FrameNeedsReflow(this, nsIPresShell::eTreeChange,
    1123               0 :                         NS_FRAME_HAS_DIRTY_CHILDREN);
    1124                 :    }
    1125               0 :    return NS_OK;
    1126                 : }
    1127                 : 
    1128                 : /* virtual */ nsIFrame*
    1129               0 : nsBoxFrame::GetContentInsertionFrame()
    1130                 : {
    1131               0 :   if (GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK)
    1132               0 :     return GetFirstPrincipalChild()->GetContentInsertionFrame();
    1133               0 :   return nsContainerFrame::GetContentInsertionFrame();
    1134                 : }
    1135                 : 
    1136                 : NS_IMETHODIMP
    1137               0 : nsBoxFrame::AttributeChanged(PRInt32 aNameSpaceID,
    1138                 :                              nsIAtom* aAttribute,
    1139                 :                              PRInt32 aModType)
    1140                 : {
    1141                 :   nsresult rv = nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute,
    1142               0 :                                                    aModType);
    1143                 : 
    1144                 :   // Ignore 'width', 'height', 'screenX', 'screenY' and 'sizemode' on a
    1145                 :   // <window>.
    1146               0 :   nsIAtom *tag = mContent->Tag();
    1147               0 :   if ((tag == nsGkAtoms::window ||
    1148                 :        tag == nsGkAtoms::page ||
    1149                 :        tag == nsGkAtoms::dialog ||
    1150                 :        tag == nsGkAtoms::wizard) &&
    1151                 :       (nsGkAtoms::width == aAttribute ||
    1152                 :        nsGkAtoms::height == aAttribute ||
    1153                 :        nsGkAtoms::screenX == aAttribute ||
    1154                 :        nsGkAtoms::screenY == aAttribute ||
    1155                 :        nsGkAtoms::sizemode == aAttribute)) {
    1156               0 :     return rv;
    1157                 :   }
    1158                 : 
    1159               0 :   if (aAttribute == nsGkAtoms::width       ||
    1160                 :       aAttribute == nsGkAtoms::height      ||
    1161                 :       aAttribute == nsGkAtoms::align       ||
    1162                 :       aAttribute == nsGkAtoms::valign      ||
    1163                 :       aAttribute == nsGkAtoms::left        ||
    1164                 :       aAttribute == nsGkAtoms::top         ||
    1165                 :       aAttribute == nsGkAtoms::right        ||
    1166                 :       aAttribute == nsGkAtoms::bottom       ||
    1167                 :       aAttribute == nsGkAtoms::start        ||
    1168                 :       aAttribute == nsGkAtoms::end          ||
    1169                 :       aAttribute == nsGkAtoms::minwidth     ||
    1170                 :       aAttribute == nsGkAtoms::maxwidth     ||
    1171                 :       aAttribute == nsGkAtoms::minheight    ||
    1172                 :       aAttribute == nsGkAtoms::maxheight    ||
    1173                 :       aAttribute == nsGkAtoms::flex         ||
    1174                 :       aAttribute == nsGkAtoms::orient       ||
    1175                 :       aAttribute == nsGkAtoms::pack         ||
    1176                 :       aAttribute == nsGkAtoms::dir          ||
    1177                 :       aAttribute == nsGkAtoms::mousethrough ||
    1178                 :       aAttribute == nsGkAtoms::equalsize) {
    1179                 : 
    1180               0 :     if (aAttribute == nsGkAtoms::align  ||
    1181                 :         aAttribute == nsGkAtoms::valign ||
    1182                 :         aAttribute == nsGkAtoms::orient  ||
    1183                 :         aAttribute == nsGkAtoms::pack    ||
    1184                 : #ifdef DEBUG_LAYOUT
    1185                 :         aAttribute == nsGkAtoms::debug   ||
    1186                 : #endif
    1187                 :         aAttribute == nsGkAtoms::dir) {
    1188                 : 
    1189               0 :       mValign = nsBoxFrame::vAlign_Top;
    1190               0 :       mHalign = nsBoxFrame::hAlign_Left;
    1191                 : 
    1192               0 :       bool orient = true;
    1193               0 :       GetInitialOrientation(orient); 
    1194               0 :       if (orient)
    1195               0 :         mState |= NS_STATE_IS_HORIZONTAL;
    1196                 :       else
    1197               0 :         mState &= ~NS_STATE_IS_HORIZONTAL;
    1198                 : 
    1199               0 :       bool normal = true;
    1200               0 :       GetInitialDirection(normal);
    1201               0 :       if (normal)
    1202               0 :         mState |= NS_STATE_IS_DIRECTION_NORMAL;
    1203                 :       else
    1204               0 :         mState &= ~NS_STATE_IS_DIRECTION_NORMAL;
    1205                 : 
    1206               0 :       GetInitialVAlignment(mValign);
    1207               0 :       GetInitialHAlignment(mHalign);
    1208                 : 
    1209               0 :       bool equalSize = false;
    1210               0 :       GetInitialEqualSize(equalSize); 
    1211               0 :       if (equalSize)
    1212               0 :         mState |= NS_STATE_EQUAL_SIZE;
    1213                 :       else
    1214               0 :         mState &= ~NS_STATE_EQUAL_SIZE;
    1215                 : 
    1216                 : #ifdef DEBUG_LAYOUT
    1217                 :       bool debug = mState & NS_STATE_SET_TO_DEBUG;
    1218                 :       bool debugSet = GetInitialDebug(debug);
    1219                 :       if (debugSet) {
    1220                 :         mState |= NS_STATE_DEBUG_WAS_SET;
    1221                 : 
    1222                 :         if (debug)
    1223                 :           mState |= NS_STATE_SET_TO_DEBUG;
    1224                 :         else
    1225                 :           mState &= ~NS_STATE_SET_TO_DEBUG;
    1226                 :       } else {
    1227                 :         mState &= ~NS_STATE_DEBUG_WAS_SET;
    1228                 :       }
    1229                 : #endif
    1230                 : 
    1231               0 :       bool autostretch = !!(mState & NS_STATE_AUTO_STRETCH);
    1232               0 :       GetInitialAutoStretch(autostretch);
    1233               0 :       if (autostretch)
    1234               0 :         mState |= NS_STATE_AUTO_STRETCH;
    1235                 :       else
    1236               0 :         mState &= ~NS_STATE_AUTO_STRETCH;
    1237                 :     }
    1238               0 :     else if (aAttribute == nsGkAtoms::left ||
    1239                 :              aAttribute == nsGkAtoms::top ||
    1240                 :              aAttribute == nsGkAtoms::right ||
    1241                 :              aAttribute == nsGkAtoms::bottom ||
    1242                 :              aAttribute == nsGkAtoms::start ||
    1243                 :              aAttribute == nsGkAtoms::end) {
    1244               0 :       mState &= ~NS_STATE_STACK_NOT_POSITIONED;
    1245                 :     }
    1246               0 :     else if (aAttribute == nsGkAtoms::mousethrough) {
    1247               0 :       UpdateMouseThrough();
    1248                 :     }
    1249                 : 
    1250               0 :     PresContext()->PresShell()->
    1251               0 :       FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
    1252                 :   }
    1253               0 :   else if (aAttribute == nsGkAtoms::ordinal) {
    1254               0 :     nsBoxLayoutState state(PresContext());
    1255               0 :     nsIBox* parent = GetParentBox();
    1256                 :     // If our parent is not a box, there's not much we can do... but in that
    1257                 :     // case our ordinal doesn't matter anyway, so that's ok.
    1258                 :     // Also don't bother with popup frames since they are kept on the 
    1259                 :     // kPopupList and RelayoutChildAtOrdinal() only handles
    1260                 :     // principal children.
    1261               0 :     if (parent && !(GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
    1262               0 :         GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_POPUP) {
    1263               0 :       parent->RelayoutChildAtOrdinal(state, this);
    1264                 :       // XXXldb Should this instead be a tree change on the child or parent?
    1265               0 :       PresContext()->PresShell()->
    1266                 :         FrameNeedsReflow(parent, nsIPresShell::eStyleChange,
    1267               0 :                          NS_FRAME_IS_DIRTY);
    1268                 :     }
    1269                 :   }
    1270                 :   // If the accesskey changed, register for the new value
    1271                 :   // The old value has been unregistered in nsXULElement::SetAttr
    1272               0 :   else if (aAttribute == nsGkAtoms::accesskey) {
    1273               0 :     RegUnregAccessKey(true);
    1274                 :   }
    1275                 : 
    1276               0 :   return rv;
    1277                 : }
    1278                 : 
    1279                 : #ifdef DEBUG_LAYOUT
    1280                 : void
    1281                 : nsBoxFrame::GetDebugPref(nsPresContext* aPresContext)
    1282                 : {
    1283                 :     gDebug = Preferences::GetBool("xul.debug.box");
    1284                 : }
    1285                 : 
    1286                 : class nsDisplayXULDebug : public nsDisplayItem {
    1287                 : public:
    1288                 :   nsDisplayXULDebug(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
    1289                 :     nsDisplayItem(aBuilder, aFrame) {
    1290                 :     MOZ_COUNT_CTOR(nsDisplayXULDebug);
    1291                 :   }
    1292                 : #ifdef NS_BUILD_REFCNT_LOGGING
    1293                 :   virtual ~nsDisplayXULDebug() {
    1294                 :     MOZ_COUNT_DTOR(nsDisplayXULDebug);
    1295                 :   }
    1296                 : #endif
    1297                 : 
    1298                 :   virtual void HitTest(nsDisplayListBuilder* aBuilder, nsRect aRect,
    1299                 :                        HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {
    1300                 :     nsPoint rectCenter(aRect.x + aRect.width / 2, aRect.y + aRect.height / 2);
    1301                 :     static_cast<nsBoxFrame*>(mFrame)->
    1302                 :       DisplayDebugInfoFor(this, rectCenter - ToReferenceFrame());
    1303                 :     aOutFrames->AppendElement(this);
    1304                 :   }
    1305                 :   virtual void Paint(nsDisplayListBuilder* aBuilder
    1306                 :                      nsRenderingContext* aCtx);
    1307                 :   NS_DISPLAY_DECL_NAME("XULDebug", TYPE_XUL_DEBUG)
    1308                 : };
    1309                 : 
    1310                 : void
    1311                 : nsDisplayXULDebug::Paint(nsDisplayListBuilder* aBuilder,
    1312                 :                          nsRenderingContext* aCtx)
    1313                 : {
    1314                 :   static_cast<nsBoxFrame*>(mFrame)->
    1315                 :     PaintXULDebugOverlay(*aCtx, ToReferenceFrame());
    1316                 : }
    1317                 : 
    1318                 : static void
    1319                 : PaintXULDebugBackground(nsIFrame* aFrame, nsRenderingContext* aCtx,
    1320                 :                         const nsRect& aDirtyRect, nsPoint aPt)
    1321                 : {
    1322                 :   static_cast<nsBoxFrame*>(aFrame)->PaintXULDebugBackground(*aCtx, aPt);
    1323                 : }
    1324                 : #endif
    1325                 : 
    1326                 : nsresult
    1327               0 : nsBoxFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
    1328                 :                              const nsRect&           aDirtyRect,
    1329                 :                              const nsDisplayListSet& aLists)
    1330                 : {
    1331                 :   // forcelayer is only supported on XUL elements with box layout
    1332                 :   bool forceLayer =
    1333               0 :     GetContent()->HasAttr(kNameSpaceID_None, nsGkAtoms::layer) &&
    1334               0 :     GetContent()->IsXUL();
    1335                 : 
    1336                 :   // Check for frames that are marked as a part of the region used
    1337                 :   // in calculating glass margins on Windows.
    1338               0 :   if (GetContent()->IsXUL()) {
    1339               0 :       const nsStyleDisplay* styles = mStyleContext->GetStyleDisplay();
    1340               0 :       if (styles && styles->mAppearance == NS_THEME_WIN_EXCLUDE_GLASS) {
    1341               0 :         nsRect rect = mRect + aBuilder->ToReferenceFrame(GetParent());
    1342               0 :         aBuilder->AddExcludedGlassRegion(rect);
    1343                 :       }
    1344                 :   }
    1345                 : 
    1346               0 :   nsDisplayListCollection tempLists;
    1347               0 :   const nsDisplayListSet& destination = forceLayer ? tempLists : aLists;
    1348                 : 
    1349               0 :   nsresult rv = DisplayBorderBackgroundOutline(aBuilder, destination);
    1350               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1351                 : 
    1352                 : #ifdef DEBUG_LAYOUT
    1353                 :   if (mState & NS_STATE_CURRENTLY_IN_DEBUG) {
    1354                 :     rv = destination.BorderBackground()->AppendNewToTop(new (aBuilder)
    1355                 :         nsDisplayGeneric(aBuilder, this, PaintXULDebugBackground,
    1356                 :                          "XULDebugBackground"));
    1357                 :     NS_ENSURE_SUCCESS(rv, rv);
    1358                 :     rv = destination.Outlines()->AppendNewToTop(new (aBuilder)
    1359                 :         nsDisplayXULDebug(aBuilder, this));
    1360                 :     NS_ENSURE_SUCCESS(rv, rv);
    1361                 :   }
    1362                 : #endif
    1363                 : 
    1364               0 :   rv = BuildDisplayListForChildren(aBuilder, aDirtyRect, destination);
    1365               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1366                 : 
    1367                 :   // see if we have to draw a selection frame around this container
    1368               0 :   rv = DisplaySelectionOverlay(aBuilder, destination.Content());
    1369               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1370                 : 
    1371               0 :   if (forceLayer) {
    1372                 :     // This is a bit of a hack. Collect up all descendant display items
    1373                 :     // and merge them into a single Content() list. This can cause us
    1374                 :     // to violate CSS stacking order, but forceLayer is a magic
    1375                 :     // XUL-only extension anyway.
    1376               0 :     nsDisplayList masterList;
    1377               0 :     masterList.AppendToTop(tempLists.BorderBackground());
    1378               0 :     masterList.AppendToTop(tempLists.BlockBorderBackgrounds());
    1379               0 :     masterList.AppendToTop(tempLists.Floats());
    1380               0 :     masterList.AppendToTop(tempLists.Content());
    1381               0 :     masterList.AppendToTop(tempLists.PositionedDescendants());
    1382               0 :     masterList.AppendToTop(tempLists.Outlines());
    1383                 :     // Wrap the list to make it its own layer
    1384                 :     rv = aLists.Content()->AppendNewToTop(new (aBuilder)
    1385               0 :         nsDisplayOwnLayer(aBuilder, this, &masterList));
    1386               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1387                 :   }
    1388               0 :   return NS_OK;
    1389                 : }
    1390                 : 
    1391                 : NS_IMETHODIMP
    1392               0 : nsBoxFrame::BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
    1393                 :                                         const nsRect&           aDirtyRect,
    1394                 :                                         const nsDisplayListSet& aLists)
    1395                 : {
    1396               0 :   nsIFrame* kid = mFrames.FirstChild();
    1397                 :   // Put each child's background onto the BlockBorderBackgrounds list
    1398                 :   // to emulate the existing two-layer XUL painting scheme.
    1399               0 :   nsDisplayListSet set(aLists, aLists.BlockBorderBackgrounds());
    1400                 :   // The children should be in the right order
    1401               0 :   while (kid) {
    1402               0 :     nsresult rv = BuildDisplayListForChild(aBuilder, kid, aDirtyRect, set);
    1403               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1404               0 :     kid = kid->GetNextSibling();
    1405                 :   }
    1406               0 :   return NS_OK;
    1407                 : }
    1408                 : 
    1409                 : // REVIEW: PaintChildren did a few things none of which are a big deal
    1410                 : // anymore:
    1411                 : // * Paint some debugging rects for this frame.
    1412                 : // This is done by nsDisplayXULDebugBackground, which goes in the
    1413                 : // BorderBackground() layer so it isn't clipped by OVERFLOW_CLIP.
    1414                 : // * Apply OVERFLOW_CLIP to the children.
    1415                 : // This is now in nsFrame::BuildDisplayListForStackingContext/Child.
    1416                 : // * Actually paint the children.
    1417                 : // Moved to BuildDisplayList.
    1418                 : // * Paint per-kid debug information.
    1419                 : // This is done by nsDisplayXULDebug, which is in the Outlines()
    1420                 : // layer so it goes on top. This means it is not clipped by OVERFLOW_CLIP,
    1421                 : // whereas it did used to respect OVERFLOW_CLIP, but too bad.
    1422                 : #ifdef DEBUG_LAYOUT
    1423                 : void
    1424                 : nsBoxFrame::PaintXULDebugBackground(nsRenderingContext& aRenderingContext,
    1425                 :                                     nsPoint aPt)
    1426                 : {
    1427                 :   nsMargin border;
    1428                 :   GetBorder(border);
    1429                 : 
    1430                 :   nsMargin debugBorder;
    1431                 :   nsMargin debugMargin;
    1432                 :   nsMargin debugPadding;
    1433                 : 
    1434                 :   bool isHorizontal = IsHorizontal();
    1435                 : 
    1436                 :   GetDebugBorder(debugBorder);
    1437                 :   PixelMarginToTwips(GetPresContext(), debugBorder);
    1438                 : 
    1439                 :   GetDebugMargin(debugMargin);
    1440                 :   PixelMarginToTwips(GetPresContext(), debugMargin);
    1441                 : 
    1442                 :   GetDebugPadding(debugPadding);
    1443                 :   PixelMarginToTwips(GetPresContext(), debugPadding);
    1444                 : 
    1445                 :   nsRect inner(mRect);
    1446                 :   inner.MoveTo(aPt);
    1447                 :   inner.Deflate(debugMargin);
    1448                 :   inner.Deflate(border);
    1449                 :   //nsRect borderRect(inner);
    1450                 : 
    1451                 :   nscolor color;
    1452                 :   if (isHorizontal) {
    1453                 :     color = NS_RGB(0,0,255);
    1454                 :   } else {
    1455                 :     color = NS_RGB(255,0,0);
    1456                 :   }
    1457                 : 
    1458                 :   aRenderingContext.SetColor(color);
    1459                 : 
    1460                 :   //left
    1461                 :   nsRect r(inner);
    1462                 :   r.width = debugBorder.left;
    1463                 :   aRenderingContext.FillRect(r);
    1464                 : 
    1465                 :   // top
    1466                 :   r = inner;
    1467                 :   r.height = debugBorder.top;
    1468                 :   aRenderingContext.FillRect(r);
    1469                 : 
    1470                 :   //right
    1471                 :   r = inner;
    1472                 :   r.x = r.x + r.width - debugBorder.right;
    1473                 :   r.width = debugBorder.right;
    1474                 :   aRenderingContext.FillRect(r);
    1475                 : 
    1476                 :   //bottom
    1477                 :   r = inner;
    1478                 :   r.y = r.y + r.height - debugBorder.bottom;
    1479                 :   r.height = debugBorder.bottom;
    1480                 :   aRenderingContext.FillRect(r);
    1481                 : 
    1482                 :   
    1483                 :   // if we have dirty children or we are dirty 
    1484                 :   // place a green border around us.
    1485                 :   if (NS_SUBTREE_DIRTY(this)) {
    1486                 :      nsRect dirtyr(inner);
    1487                 :      aRenderingContext.SetColor(NS_RGB(0,255,0));
    1488                 :      aRenderingContext.DrawRect(dirtyr);
    1489                 :      aRenderingContext.SetColor(color);
    1490                 :   }
    1491                 : }
    1492                 : 
    1493                 : void
    1494                 : nsBoxFrame::PaintXULDebugOverlay(nsRenderingContext& aRenderingContext,
    1495                 :                                  nsPoint aPt)
    1496                 :   nsMargin border;
    1497                 :   GetBorder(border);
    1498                 : 
    1499                 :   nsMargin debugMargin;
    1500                 :   GetDebugMargin(debugMargin);
    1501                 :   PixelMarginToTwips(GetPresContext(), debugMargin);
    1502                 : 
    1503                 :   nsRect inner(mRect);
    1504                 :   inner.MoveTo(aPt);
    1505                 :   inner.Deflate(debugMargin);
    1506                 :   inner.Deflate(border);
    1507                 : 
    1508                 :   nscoord onePixel = GetPresContext()->IntScaledPixelsToTwips(1);
    1509                 : 
    1510                 :   kid = GetChildBox();
    1511                 :   while (nsnull != kid) {
    1512                 :     bool isHorizontal = IsHorizontal();
    1513                 : 
    1514                 :     nscoord x, y, borderSize, spacerSize;
    1515                 :     
    1516                 :     nsRect cr(kid->mRect);
    1517                 :     nsMargin margin;
    1518                 :     kid->GetMargin(margin);
    1519                 :     cr.Inflate(margin);
    1520                 :     
    1521                 :     if (isHorizontal) 
    1522                 :     {
    1523                 :         cr.y = inner.y;
    1524                 :         x = cr.x;
    1525                 :         y = cr.y + onePixel;
    1526                 :         spacerSize = debugBorder.top - onePixel*4;
    1527                 :     } else {
    1528                 :         cr.x = inner.x;
    1529                 :         x = cr.y;
    1530                 :         y = cr.x + onePixel;
    1531                 :         spacerSize = debugBorder.left - onePixel*4;
    1532                 :     }
    1533                 : 
    1534                 :     nsBoxLayoutState state(GetPresContext());
    1535                 :     nscoord flex = kid->GetFlex(state);
    1536                 : 
    1537                 :     if (!kid->IsCollapsed()) {
    1538                 :       aRenderingContext.SetColor(NS_RGB(255,255,255));
    1539                 : 
    1540                 :       if (isHorizontal) 
    1541                 :           borderSize = cr.width;
    1542                 :       else 
    1543                 :           borderSize = cr.height;
    1544                 :     
    1545                 :       DrawSpacer(GetPresContext(), aRenderingContext, isHorizontal, flex, x, y, borderSize, spacerSize);
    1546                 :     }
    1547                 : 
    1548                 :     kid = kid->GetNextBox();
    1549                 :   }
    1550                 : }
    1551                 : #endif
    1552                 : 
    1553                 : #ifdef DEBUG_LAYOUT
    1554                 : void
    1555                 : nsBoxFrame::GetBoxName(nsAutoString& aName)
    1556                 : {
    1557                 :    GetFrameName(aName);
    1558                 : }
    1559                 : #endif
    1560                 : 
    1561                 : #ifdef DEBUG
    1562                 : NS_IMETHODIMP
    1563               0 : nsBoxFrame::GetFrameName(nsAString& aResult) const
    1564                 : {
    1565               0 :   return MakeFrameName(NS_LITERAL_STRING("Box"), aResult);
    1566                 : }
    1567                 : #endif
    1568                 : 
    1569                 : nsIAtom*
    1570               0 : nsBoxFrame::GetType() const
    1571                 : {
    1572               0 :   return nsGkAtoms::boxFrame;
    1573                 : }
    1574                 : 
    1575                 : #ifdef DEBUG_LAYOUT
    1576                 : NS_IMETHODIMP
    1577                 : nsBoxFrame::GetDebug(bool& aDebug)
    1578                 : {
    1579                 :   aDebug = (mState & NS_STATE_CURRENTLY_IN_DEBUG);
    1580                 :   return NS_OK;
    1581                 : }
    1582                 : #endif
    1583                 : 
    1584                 : // REVIEW: nsBoxFrame::GetFrameForPoint is a problem because of 'mousethrough'
    1585                 : // attribute support. Here's how it works:
    1586                 : // * For each child frame F, we determine the target frame T(F) by recursively
    1587                 : // invoking GetFrameForPoint on the child
    1588                 : // * Let F' be the last child frame such that T(F') doesn't have mousethrough.
    1589                 : // If F' exists, return T(F')
    1590                 : // * Otherwise let F'' be the first child frame such that T(F'') is non-null.
    1591                 : // If F'' exists, return T(F'')
    1592                 : // * Otherwise return this frame, if this frame contains the point
    1593                 : // * Otherwise return null
    1594                 : // It's not clear how this should work for more complex z-ordering situations.
    1595                 : // The basic principle seems to be that if a frame F has a descendant
    1596                 : // 'mousethrough' frame that includes the target position, then F
    1597                 : // will not receive events (unless it overrides GetFrameForPoint).
    1598                 : // A 'mousethrough' frame will only receive an event if, after applying that rule,
    1599                 : // all eligible frames are 'mousethrough'; the bottom-most inner-most 'mousethrough'
    1600                 : // frame is then chosen (the first eligible frame reached in a
    1601                 : // traversal of the frame tree --- pre/post is irrelevant since ancestors
    1602                 : // of the mousethrough frames can't be eligible).
    1603                 : // IMHO this is very bogus and adds a great deal of complexity for something
    1604                 : // that is very rarely used. So I'm redefining 'mousethrough' to the following:
    1605                 : // a frame with mousethrough is transparent to mouse events. This is compatible
    1606                 : // with the way 'mousethrough' is used in Seamonkey's navigator.xul and
    1607                 : // Firefox's browser.xul. The only other place it's used is in the 'expander'
    1608                 : // XBL binding, which in our tree is only used by Thunderbird SMIME Advanced
    1609                 : // Preferences, and I can't figure out what that does, so I'll have to test it.
    1610                 : // If it's broken I'll probably just change the binding to use it more sensibly.
    1611                 : // This new behaviour is implemented in nsDisplayList::HitTest. 
    1612                 : // REVIEW: This debug-box stuff is annoying. I'm just going to put debug boxes
    1613                 : // in the outline layer and avoid GetDebugBoxAt.
    1614                 : 
    1615                 : // REVIEW: GetCursor had debug-only event dumping code. I have replaced it
    1616                 : // with instrumentation in nsDisplayXULDebug.
    1617                 : 
    1618                 : #ifdef DEBUG_LAYOUT
    1619                 : void
    1620                 : nsBoxFrame::DrawLine(nsRenderingContext& aRenderingContext, bool aHorizontal, nscoord x1, nscoord y1, nscoord x2, nscoord y2)
    1621                 : {
    1622                 :     if (aHorizontal)
    1623                 :        aRenderingContext.DrawLine(x1,y1,x2,y2);
    1624                 :     else
    1625                 :        aRenderingContext.DrawLine(y1,x1,y2,x2);
    1626                 : }
    1627                 : 
    1628                 : void
    1629                 : nsBoxFrame::FillRect(nsRenderingContext& aRenderingContext, bool aHorizontal, nscoord x, nscoord y, nscoord width, nscoord height)
    1630                 : {
    1631                 :     if (aHorizontal)
    1632                 :        aRenderingContext.FillRect(x,y,width,height);
    1633                 :     else
    1634                 :        aRenderingContext.FillRect(y,x,height,width);
    1635                 : }
    1636                 : 
    1637                 : void 
    1638                 : nsBoxFrame::DrawSpacer(nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, bool aHorizontal, PRInt32 flex, nscoord x, nscoord y, nscoord size, nscoord spacerSize)
    1639                 : {    
    1640                 :          nscoord onePixel = aPresContext->IntScaledPixelsToTwips(1);
    1641                 : 
    1642                 :      // if we do draw the coils
    1643                 :         int distance = 0;
    1644                 :         int center = 0;
    1645                 :         int offset = 0;
    1646                 :         int coilSize = COIL_SIZE*onePixel;
    1647                 :         int halfSpacer = spacerSize/2;
    1648                 : 
    1649                 :         distance = size;
    1650                 :         center = y + halfSpacer;
    1651                 :         offset = x;
    1652                 : 
    1653                 :         int coils = distance/coilSize;
    1654                 : 
    1655                 :         int halfCoilSize = coilSize/2;
    1656                 : 
    1657                 :         if (flex == 0) {
    1658                 :             DrawLine(aRenderingContext, aHorizontal, x,y + spacerSize/2, x + size, y + spacerSize/2);
    1659                 :         } else {
    1660                 :             for (int i=0; i < coils; i++)
    1661                 :             {
    1662                 :                    DrawLine(aRenderingContext, aHorizontal, offset, center+halfSpacer, offset+halfCoilSize, center-halfSpacer);
    1663                 :                    DrawLine(aRenderingContext, aHorizontal, offset+halfCoilSize, center-halfSpacer, offset+coilSize, center+halfSpacer);
    1664                 : 
    1665                 :                    offset += coilSize;
    1666                 :             }
    1667                 :         }
    1668                 : 
    1669                 :         FillRect(aRenderingContext, aHorizontal, x + size - spacerSize/2, y, spacerSize/2, spacerSize);
    1670                 :         FillRect(aRenderingContext, aHorizontal, x, y, spacerSize/2, spacerSize);
    1671                 : 
    1672                 :         //DrawKnob(aPresContext, aRenderingContext, x + size - spacerSize, y, spacerSize);
    1673                 : }
    1674                 : 
    1675                 : void
    1676                 : nsBoxFrame::GetDebugBorder(nsMargin& aInset)
    1677                 : {
    1678                 :     aInset.SizeTo(2,2,2,2);
    1679                 : 
    1680                 :     if (IsHorizontal()) 
    1681                 :        aInset.top = 10;
    1682                 :     else 
    1683                 :        aInset.left = 10;
    1684                 : }
    1685                 : 
    1686                 : void
    1687                 : nsBoxFrame::GetDebugMargin(nsMargin& aInset)
    1688                 : {
    1689                 :     aInset.SizeTo(2,2,2,2);
    1690                 : }
    1691                 : 
    1692                 : void
    1693                 : nsBoxFrame::GetDebugPadding(nsMargin& aPadding)
    1694                 : {
    1695                 :     aPadding.SizeTo(2,2,2,2);
    1696                 : }
    1697                 : 
    1698                 : void 
    1699                 : nsBoxFrame::PixelMarginToTwips(nsPresContext* aPresContext, nsMargin& aMarginPixels)
    1700                 : {
    1701                 :   nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
    1702                 :   aMarginPixels.left   *= onePixel;
    1703                 :   aMarginPixels.right  *= onePixel;
    1704                 :   aMarginPixels.top    *= onePixel;
    1705                 :   aMarginPixels.bottom *= onePixel;
    1706                 : }
    1707                 : 
    1708                 : void
    1709                 : nsBoxFrame::GetValue(nsPresContext* aPresContext, const nsSize& a, const nsSize& b, char* ch) 
    1710                 : {
    1711                 :     float p2t = aPresContext->ScaledPixelsToTwips();
    1712                 : 
    1713                 :     char width[100];
    1714                 :     char height[100];
    1715                 :     
    1716                 :     if (a.width == NS_INTRINSICSIZE)
    1717                 :         sprintf(width,"%s","INF");
    1718                 :     else
    1719                 :         sprintf(width,"%d", nscoord(a.width/*/p2t*/));
    1720                 :     
    1721                 :     if (a.height == NS_INTRINSICSIZE)
    1722                 :         sprintf(height,"%s","INF");
    1723                 :     else 
    1724                 :         sprintf(height,"%d", nscoord(a.height/*/p2t*/));
    1725                 :     
    1726                 : 
    1727                 :     sprintf(ch, "(%s%s, %s%s)", width, (b.width != NS_INTRINSICSIZE ? "[SET]" : ""),
    1728                 :                     height, (b.height != NS_INTRINSICSIZE ? "[SET]" : ""));
    1729                 : 
    1730                 : }
    1731                 : 
    1732                 : void
    1733                 : nsBoxFrame::GetValue(nsPresContext* aPresContext, PRInt32 a, PRInt32 b, char* ch) 
    1734                 : {
    1735                 :     if (a == NS_INTRINSICSIZE)
    1736                 :       sprintf(ch, "%d[SET]", b);             
    1737                 :     else
    1738                 :       sprintf(ch, "%d", a);             
    1739                 : }
    1740                 : 
    1741                 : nsresult
    1742                 : nsBoxFrame::DisplayDebugInfoFor(nsIBox*  aBox,
    1743                 :                                 nsPoint& aPoint)
    1744                 : {
    1745                 :     nsBoxLayoutState state(GetPresContext());
    1746                 : 
    1747                 :     nscoord x = aPoint.x;
    1748                 :     nscoord y = aPoint.y;
    1749                 : 
    1750                 :     // get the area inside our border but not our debug margins.
    1751                 :     nsRect insideBorder(aBox->mRect);
    1752                 :     insideBorder.MoveTo(0,0):
    1753                 :     nsMargin border(0,0,0,0);
    1754                 :     aBox->GetBorderAndPadding(border);
    1755                 :     insideBorder.Deflate(border);
    1756                 : 
    1757                 :     bool isHorizontal = IsHorizontal();
    1758                 : 
    1759                 :     if (!insideBorder.Contains(nsPoint(x,y)))
    1760                 :         return NS_ERROR_FAILURE;
    1761                 : 
    1762                 :     //printf("%%%%%% inside box %%%%%%%\n");
    1763                 : 
    1764                 :     int count = 0;
    1765                 :     nsIBox* child = aBox->GetChildBox();
    1766                 : 
    1767                 :     nsMargin m;
    1768                 :     nsMargin m2;
    1769                 :     GetDebugBorder(m);
    1770                 :     PixelMarginToTwips(aPresContext, m);
    1771                 : 
    1772                 :     GetDebugMargin(m2);
    1773                 :     PixelMarginToTwips(aPresContext, m2);
    1774                 : 
    1775                 :     m += m2;
    1776                 : 
    1777                 :     if ((isHorizontal && y < insideBorder.y + m.top) ||
    1778                 :         (!isHorizontal && x < insideBorder.x + m.left)) {
    1779                 :         //printf("**** inside debug border *******\n");
    1780                 :         while (child) 
    1781                 :         {
    1782                 :             const nsRect& r = child->mRect;
    1783                 : 
    1784                 :             // if we are not in the child. But in the spacer above the child.
    1785                 :             if ((isHorizontal && x >= r.x && x < r.x + r.width) ||
    1786                 :                 (!isHorizontal && y >= r.y && y < r.y + r.height)) {
    1787                 :                 aCursor = NS_STYLE_CURSOR_POINTER;
    1788                 :                    // found it but we already showed it.
    1789                 :                     if (mDebugChild == child)
    1790                 :                         return NS_OK;
    1791                 : 
    1792                 :                     if (aBox->GetContent()) {
    1793                 :                       printf("---------------\n");
    1794                 :                       DumpBox(stdout);
    1795                 :                       printf("\n");
    1796                 :                     }
    1797                 : 
    1798                 :                     if (child->GetContent()) {
    1799                 :                         printf("child #%d: ", count);
    1800                 :                         child->DumpBox(stdout);
    1801                 :                         printf("\n");
    1802                 :                     }
    1803                 : 
    1804                 :                     mDebugChild = child;
    1805                 : 
    1806                 :                     nsSize prefSizeCSS(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
    1807                 :                     nsSize minSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
    1808                 :                     nsSize maxSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
    1809                 :                     nscoord flexCSS = NS_INTRINSICSIZE;
    1810                 : 
    1811                 :                     bool widthSet, heightSet;
    1812                 :                     nsIBox::AddCSSPrefSize(child, prefSizeCSS, widthSet, heightSet);
    1813                 :                     nsIBox::AddCSSMinSize (state, child, minSizeCSS, widthSet, heightSet);
    1814                 :                     nsIBox::AddCSSMaxSize (child, maxSizeCSS, widthSet, heightSet);
    1815                 :                     nsIBox::AddCSSFlex    (state, child, flexCSS);
    1816                 : 
    1817                 :                     nsSize prefSize = child->GetPrefSize(state);
    1818                 :                     nsSize minSize = child->GetMinSize(state);
    1819                 :                     nsSize maxSize = child->GetMaxSize(state);
    1820                 :                     nscoord flexSize = child->GetFlex(state);
    1821                 :                     nscoord ascentSize = child->GetBoxAscent(state);
    1822                 : 
    1823                 :                     char min[100];
    1824                 :                     char pref[100];
    1825                 :                     char max[100];
    1826                 :                     char calc[100];
    1827                 :                     char flex[100];
    1828                 :                     char ascent[100];
    1829                 :                   
    1830                 :                     nsSize actualSize;
    1831                 :                     GetFrameSizeWithMargin(child, actualSize);
    1832                 :                     nsSize actualSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
    1833                 : 
    1834                 :                     GetValue(aPresContext, minSize,  minSizeCSS, min);
    1835                 :                     GetValue(aPresContext, prefSize, prefSizeCSS, pref);
    1836                 :                     GetValue(aPresContext, maxSize,  maxSizeCSS, max);
    1837                 :                     GetValue(aPresContext, actualSize, actualSizeCSS, calc);
    1838                 :                     GetValue(aPresContext, flexSize,  flexCSS, flex);
    1839                 :                     GetValue(aPresContext, ascentSize,  NS_INTRINSICSIZE, ascent);
    1840                 : 
    1841                 : 
    1842                 :                     printf("min%s, pref%s, max%s, actual%s, flex=%s, ascent=%s\n\n", 
    1843                 :                         min,
    1844                 :                         pref,
    1845                 :                         max,
    1846                 :                         calc,
    1847                 :                         flex,
    1848                 :                         ascent
    1849                 :                     );
    1850                 : 
    1851                 :                     return NS_OK;   
    1852                 :             }
    1853                 : 
    1854                 :           child = child->GetNextBox();
    1855                 :           count++;
    1856                 :         }
    1857                 :     } else {
    1858                 :     }
    1859                 : 
    1860                 :     mDebugChild = nsnull;
    1861                 : 
    1862                 :     return NS_OK;
    1863                 : }
    1864                 : 
    1865                 : void
    1866                 : nsBoxFrame::SetDebugOnChildList(nsBoxLayoutState& aState, nsIBox* aChild, bool aDebug)
    1867                 : {
    1868                 :     nsIBox* child = GetChildBox();
    1869                 :      while (child)
    1870                 :      {
    1871                 :         child->SetDebug(aState, aDebug);
    1872                 :         child = child->GetNextBox();
    1873                 :      }
    1874                 : }
    1875                 : 
    1876                 : nsresult
    1877                 : nsBoxFrame::GetFrameSizeWithMargin(nsIBox* aBox, nsSize& aSize)
    1878                 : {
    1879                 :   nsRect rect(aBox->GetRect());
    1880                 :   nsMargin margin(0,0,0,0);
    1881                 :   aBox->GetMargin(margin);
    1882                 :   rect.Inflate(margin);
    1883                 :   aSize.width = rect.width;
    1884                 :   aSize.height = rect.height;
    1885                 :   return NS_OK;
    1886                 : }
    1887                 : #endif
    1888                 : 
    1889                 : // If you make changes to this function, check its counterparts
    1890                 : // in nsTextBoxFrame and nsXULLabelFrame
    1891                 : nsresult
    1892               0 : nsBoxFrame::RegUnregAccessKey(bool aDoReg)
    1893                 : {
    1894                 :   // if we have no content, we can't do anything
    1895               0 :   if (!mContent)
    1896               0 :     return NS_ERROR_FAILURE;
    1897                 : 
    1898                 :   // find out what type of element this is
    1899               0 :   nsIAtom *atom = mContent->Tag();
    1900                 : 
    1901                 :   // only support accesskeys for the following elements
    1902               0 :   if (atom != nsGkAtoms::button &&
    1903                 :       atom != nsGkAtoms::toolbarbutton &&
    1904                 :       atom != nsGkAtoms::checkbox &&
    1905                 :       atom != nsGkAtoms::textbox &&
    1906                 :       atom != nsGkAtoms::tab &&
    1907                 :       atom != nsGkAtoms::radio) {
    1908               0 :     return NS_OK;
    1909                 :   }
    1910                 : 
    1911               0 :   nsAutoString accessKey;
    1912               0 :   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, accessKey);
    1913                 : 
    1914               0 :   if (accessKey.IsEmpty())
    1915               0 :     return NS_OK;
    1916                 : 
    1917                 :   // With a valid PresContext we can get the ESM 
    1918                 :   // and register the access key
    1919               0 :   nsEventStateManager *esm = PresContext()->EventStateManager();
    1920                 : 
    1921               0 :   PRUint32 key = accessKey.First();
    1922               0 :   if (aDoReg)
    1923               0 :     esm->RegisterAccessKey(mContent, key);
    1924                 :   else
    1925               0 :     esm->UnregisterAccessKey(mContent, key);
    1926                 : 
    1927               0 :   return NS_OK;
    1928                 : }
    1929                 : 
    1930                 : bool
    1931               0 : nsBoxFrame::SupportsOrdinalsInChildren()
    1932                 : {
    1933               0 :   return true;
    1934                 : }
    1935                 : 
    1936                 : static nsIFrame*
    1937               0 : SortedMerge(nsBoxLayoutState& aState, nsIFrame *aLeft, nsIFrame *aRight)
    1938                 : {
    1939               0 :   NS_PRECONDITION(aLeft && aRight, "SortedMerge must have non-empty lists");
    1940                 : 
    1941                 :   nsIFrame *result;
    1942                 :   // Unroll first iteration to avoid null-check 'result' inside the loop.
    1943               0 :   if (aLeft->GetOrdinal(aState) <= aRight->GetOrdinal(aState)) {
    1944               0 :     result = aLeft;
    1945               0 :     aLeft = aLeft->GetNextSibling();
    1946               0 :     if (!aLeft) {
    1947               0 :       result->SetNextSibling(aRight);
    1948               0 :       return result;
    1949                 :     }
    1950                 :   }
    1951                 :   else {
    1952               0 :     result = aRight;
    1953               0 :     aRight = aRight->GetNextSibling();
    1954               0 :     if (!aRight) {
    1955               0 :       result->SetNextSibling(aLeft);
    1956               0 :       return result;
    1957                 :     }
    1958                 :   }
    1959                 : 
    1960               0 :   nsIFrame *last = result;
    1961               0 :   for (;;) {
    1962               0 :     if (aLeft->GetOrdinal(aState) <= aRight->GetOrdinal(aState)) {
    1963               0 :       last->SetNextSibling(aLeft);
    1964               0 :       last = aLeft;
    1965               0 :       aLeft = aLeft->GetNextSibling();
    1966               0 :       if (!aLeft) {
    1967               0 :         last->SetNextSibling(aRight);
    1968               0 :         return result;
    1969                 :       }
    1970                 :     }
    1971                 :     else {
    1972               0 :       last->SetNextSibling(aRight);
    1973               0 :       last = aRight;
    1974               0 :       aRight = aRight->GetNextSibling();
    1975               0 :       if (!aRight) {
    1976               0 :         last->SetNextSibling(aLeft);
    1977               0 :         return result;
    1978                 :       }
    1979                 :     }
    1980                 :   }
    1981                 : }
    1982                 : 
    1983                 : static nsIFrame*
    1984               0 : MergeSort(nsBoxLayoutState& aState, nsIFrame *aSource)
    1985                 : {
    1986               0 :   NS_PRECONDITION(aSource, "MergeSort null arg");
    1987                 : 
    1988               0 :   nsIFrame *sorted[32] = { nsnull };
    1989               0 :   nsIFrame **fill = &sorted[0];
    1990                 :   nsIFrame **left;
    1991               0 :   nsIFrame *rest = aSource;
    1992                 : 
    1993               0 :   do {
    1994               0 :     nsIFrame *current = rest;
    1995               0 :     rest = rest->GetNextSibling();
    1996               0 :     current->SetNextSibling(nsnull);
    1997                 : 
    1998                 :     // Merge it with sorted[0] if present; then merge the result with sorted[1] etc.
    1999                 :     // sorted[0] is a list of length 1 (or nsnull).
    2000                 :     // sorted[1] is a list of length 2 (or nsnull).
    2001                 :     // sorted[2] is a list of length 4 (or nsnull). etc.
    2002               0 :     for (left = &sorted[0]; left != fill && *left; ++left) {
    2003               0 :       current = SortedMerge(aState, *left, current);
    2004               0 :       *left = nsnull;
    2005                 :     }
    2006                 : 
    2007                 :     // Fill the empty slot that we couldn't merge with the last result.
    2008               0 :     *left = current;
    2009                 : 
    2010               0 :     if (left == fill)
    2011               0 :       ++fill;
    2012                 :   } while (rest);
    2013                 : 
    2014                 :   // Collect and merge the results.
    2015               0 :   nsIFrame *result = nsnull;
    2016               0 :   for (left = &sorted[0]; left != fill; ++left) {
    2017               0 :     if (*left) {
    2018               0 :       result = result ? SortedMerge(aState, *left, result) : *left;
    2019                 :     }
    2020                 :   }
    2021               0 :   return result;
    2022                 : }
    2023                 : 
    2024                 : void 
    2025               0 : nsBoxFrame::CheckBoxOrder(nsBoxLayoutState& aState)
    2026                 : {
    2027               0 :   nsIFrame *child = mFrames.FirstChild();
    2028               0 :   if (!child)
    2029               0 :     return;
    2030                 : 
    2031               0 :   if (!SupportsOrdinalsInChildren())
    2032               0 :     return;
    2033                 : 
    2034                 :   // Run through our list of children and check whether we
    2035                 :   // need to sort them.
    2036               0 :   PRUint32 maxOrdinal = child->GetOrdinal(aState);
    2037               0 :   child = child->GetNextSibling();
    2038               0 :   for ( ; child; child = child->GetNextSibling()) {
    2039               0 :     PRUint32 ordinal = child->GetOrdinal(aState);
    2040               0 :     if (ordinal < maxOrdinal)
    2041               0 :       break;
    2042               0 :     maxOrdinal = ordinal;
    2043                 :   }
    2044                 : 
    2045               0 :   if (!child)
    2046               0 :     return;
    2047                 : 
    2048               0 :   nsIFrame* head = MergeSort(aState, mFrames.FirstChild());
    2049               0 :   mFrames = nsFrameList(head, nsLayoutUtils::GetLastSibling(head));
    2050                 : }
    2051                 : 
    2052                 : nsresult
    2053               0 : nsBoxFrame::LayoutChildAt(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect)
    2054                 : {
    2055                 :   // get the current rect
    2056               0 :   nsRect oldRect(aBox->GetRect());
    2057               0 :   aBox->SetBounds(aState, aRect);
    2058                 : 
    2059               0 :   bool layout = NS_SUBTREE_DIRTY(aBox);
    2060                 :   
    2061               0 :   if (layout || (oldRect.width != aRect.width || oldRect.height != aRect.height))  {
    2062               0 :     return aBox->Layout(aState);
    2063                 :   }
    2064                 : 
    2065               0 :   return NS_OK;
    2066                 : }
    2067                 : 
    2068                 : NS_IMETHODIMP
    2069               0 : nsBoxFrame::RelayoutChildAtOrdinal(nsBoxLayoutState& aState, nsIBox* aChild)
    2070                 : {
    2071               0 :   if (!SupportsOrdinalsInChildren())
    2072               0 :     return NS_OK;
    2073                 : 
    2074               0 :   PRUint32 ord = aChild->GetOrdinal(aState);
    2075                 :   
    2076               0 :   nsIFrame* child = mFrames.FirstChild();
    2077               0 :   nsIFrame* newPrevSib = nsnull;
    2078                 : 
    2079               0 :   while (child) {
    2080               0 :     if (ord < child->GetOrdinal(aState)) {
    2081               0 :       break;
    2082                 :     }
    2083                 : 
    2084               0 :     if (child != aChild) {
    2085               0 :       newPrevSib = child;
    2086                 :     }
    2087                 : 
    2088               0 :     child = child->GetNextBox();
    2089                 :   }
    2090                 : 
    2091               0 :   if (aChild->GetPrevSibling() == newPrevSib) {
    2092                 :     // This box is not moving.
    2093               0 :     return NS_OK;
    2094                 :   }
    2095                 : 
    2096                 :   // Take |aChild| out of its old position in the child list.
    2097               0 :   mFrames.RemoveFrame(aChild);
    2098                 : 
    2099                 :   // Insert it after |newPrevSib| or at the start if it's null.
    2100               0 :   mFrames.InsertFrame(nsnull, newPrevSib, aChild);
    2101                 : 
    2102               0 :   return NS_OK;
    2103                 : }
    2104                 : 
    2105                 : /**
    2106                 :  * This wrapper class lets us redirect mouse hits from descendant frames
    2107                 :  * of a menu to the menu itself, if they didn't specify 'allowevents'.
    2108                 :  * 
    2109                 :  * The wrapper simply turns a hit on a descendant element
    2110                 :  * into a hit on the menu itself, unless there is an element between the target
    2111                 :  * and the menu with the "allowevents" attribute.
    2112                 :  * 
    2113                 :  * This is used by nsMenuFrame and nsTreeColFrame.
    2114                 :  * 
    2115                 :  * Note that turning a hit on a descendant element into nsnull, so events
    2116                 :  * could fall through to the menu background, might be an appealing simplification
    2117                 :  * but it would mean slightly strange behaviour in some cases, because grabber
    2118                 :  * wrappers can be created for many individual lists and items, so the exact
    2119                 :  * fallthrough behaviour would be complex. E.g. an element with "allowevents"
    2120                 :  * on top of the Content() list could receive the event even if it was covered
    2121                 :  * by a PositionedDescenants() element without "allowevents". It is best to
    2122                 :  * never convert a non-null hit into null.
    2123                 :  */
    2124                 : // REVIEW: This is roughly of what nsMenuFrame::GetFrameForPoint used to do.
    2125                 : // I've made 'allowevents' affect child elements because that seems the only
    2126                 : // reasonable thing to do.
    2127               0 : class nsDisplayXULEventRedirector : public nsDisplayWrapList {
    2128                 : public:
    2129               0 :   nsDisplayXULEventRedirector(nsDisplayListBuilder* aBuilder,
    2130                 :                               nsIFrame* aFrame, nsDisplayItem* aItem,
    2131                 :                               nsIFrame* aTargetFrame)
    2132               0 :     : nsDisplayWrapList(aBuilder, aFrame, aItem), mTargetFrame(aTargetFrame) {}
    2133               0 :   nsDisplayXULEventRedirector(nsDisplayListBuilder* aBuilder,
    2134                 :                               nsIFrame* aFrame, nsDisplayList* aList,
    2135                 :                               nsIFrame* aTargetFrame)
    2136               0 :     : nsDisplayWrapList(aBuilder, aFrame, aList), mTargetFrame(aTargetFrame) {}
    2137                 :   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
    2138                 :                        HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
    2139               0 :   NS_DISPLAY_DECL_NAME("XULEventRedirector", TYPE_XUL_EVENT_REDIRECTOR)
    2140                 : private:
    2141                 :   nsIFrame* mTargetFrame;
    2142                 : };
    2143                 : 
    2144               0 : void nsDisplayXULEventRedirector::HitTest(nsDisplayListBuilder* aBuilder,
    2145                 :     const nsRect& aRect, HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
    2146                 : {
    2147               0 :   nsTArray<nsIFrame*> outFrames;
    2148               0 :   mList.HitTest(aBuilder, aRect, aState, &outFrames);
    2149                 : 
    2150               0 :   bool topMostAdded = false;
    2151               0 :   PRUint32 localLength = outFrames.Length();
    2152                 : 
    2153               0 :   for (PRUint32 i = 0; i < localLength; i++) {
    2154                 : 
    2155               0 :     for (nsIContent* content = outFrames.ElementAt(i)->GetContent();
    2156               0 :          content && content != mTargetFrame->GetContent();
    2157               0 :          content = content->GetParent()) {
    2158               0 :       if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::allowevents,
    2159               0 :                                nsGkAtoms::_true, eCaseMatters)) {
    2160                 :         // Events are allowed on 'frame', so let it go.
    2161               0 :         aOutFrames->AppendElement(outFrames.ElementAt(i));
    2162               0 :         topMostAdded = true;
    2163                 :       }
    2164                 :     }
    2165                 : 
    2166                 :     // If there was no hit on the topmost frame or its ancestors,
    2167                 :     // add the target frame itself as the first candidate (see bug 562554).
    2168               0 :     if (!topMostAdded) {
    2169               0 :       topMostAdded = true;
    2170               0 :       aOutFrames->AppendElement(mTargetFrame);
    2171                 :     }
    2172                 :   }
    2173               0 : }
    2174                 : 
    2175                 : class nsXULEventRedirectorWrapper : public nsDisplayWrapper
    2176                 : {
    2177                 : public:
    2178               0 :   nsXULEventRedirectorWrapper(nsIFrame* aTargetFrame)
    2179               0 :       : mTargetFrame(aTargetFrame) {}
    2180               0 :   virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
    2181                 :                                   nsIFrame* aFrame, nsDisplayList* aList) {
    2182                 :     return new (aBuilder)
    2183               0 :         nsDisplayXULEventRedirector(aBuilder, aFrame, aList, mTargetFrame);
    2184                 :   }
    2185               0 :   virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
    2186                 :                                   nsDisplayItem* aItem) {
    2187                 :     return new (aBuilder)
    2188                 :         nsDisplayXULEventRedirector(aBuilder, aItem->GetUnderlyingFrame(), aItem,
    2189               0 :                                     mTargetFrame);
    2190                 :   }
    2191                 : private:
    2192                 :   nsIFrame* mTargetFrame;
    2193                 : };
    2194                 : 
    2195                 : nsresult
    2196               0 : nsBoxFrame::WrapListsInRedirector(nsDisplayListBuilder*   aBuilder,
    2197                 :                                   const nsDisplayListSet& aIn,
    2198                 :                                   const nsDisplayListSet& aOut)
    2199                 : {
    2200               0 :   nsXULEventRedirectorWrapper wrapper(this);
    2201               0 :   return wrapper.WrapLists(aBuilder, this, aIn, aOut);
    2202                 : }

Generated by: LCOV version 1.7