LCOV - code coverage report
Current view: directory - layout/generic - nsFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 4140 27 0.7 %
Date: 2012-06-02 Functions: 365 6 1.6 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : // vim:cindent:ts=2:et:sw=2:
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org 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                 :  *   Uri Bernstein <uriber@gmail.com>
      26                 :  *   Eli Friedman <sharparrow1@yahoo.com>
      27                 :  *   Mats Palmgren <matspal@gmail.com>
      28                 :  *
      29                 :  * Alternatively, the contents of this file may be used under the terms of
      30                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      31                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      32                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      33                 :  * of those above. If you wish to allow use of your version of this file only
      34                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      35                 :  * use your version of this file under the terms of the MPL, indicate your
      36                 :  * decision by deleting the provisions above and replace them with the notice
      37                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      38                 :  * the provisions above, a recipient may use your version of this file under
      39                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      40                 :  *
      41                 :  * ***** END LICENSE BLOCK ***** */
      42                 : 
      43                 : /* base class of all rendering objects */
      44                 : 
      45                 : #include "mozilla/Attributes.h"
      46                 : #include "mozilla/Util.h"
      47                 : 
      48                 : #include "nsCOMPtr.h"
      49                 : #include "nsFrame.h"
      50                 : #include "nsFrameList.h"
      51                 : #include "nsPlaceholderFrame.h"
      52                 : #include "nsLineLayout.h"
      53                 : #include "nsIContent.h"
      54                 : #include "nsContentUtils.h"
      55                 : #include "nsIAtom.h"
      56                 : #include "nsString.h"
      57                 : #include "nsReadableUtils.h"
      58                 : #include "nsStyleContext.h"
      59                 : #include "nsIView.h"
      60                 : #include "nsIViewManager.h"
      61                 : #include "nsIScrollableFrame.h"
      62                 : #include "nsPresContext.h"
      63                 : #include "nsCRT.h"
      64                 : #include "nsGUIEvent.h"
      65                 : #include "nsIDOMEvent.h"
      66                 : #include "nsAsyncDOMEvent.h"
      67                 : #include "nsStyleConsts.h"
      68                 : #include "nsIPresShell.h"
      69                 : #include "prlog.h"
      70                 : #include "prprf.h"
      71                 : #include <stdarg.h>
      72                 : #include "nsFrameManager.h"
      73                 : #include "nsCSSRendering.h"
      74                 : #include "nsLayoutUtils.h"
      75                 : #ifdef ACCESSIBILITY
      76                 : #include "nsIAccessible.h"
      77                 : #endif
      78                 : 
      79                 : #include "nsIDOMNode.h"
      80                 : #include "nsIEditorDocShell.h"
      81                 : #include "nsEventStateManager.h"
      82                 : #include "nsISelection.h"
      83                 : #include "nsISelectionPrivate.h"
      84                 : #include "nsFrameSelection.h"
      85                 : #include "nsHTMLParts.h"
      86                 : #include "nsGkAtoms.h"
      87                 : #include "nsCSSAnonBoxes.h"
      88                 : #include "nsCSSPseudoElements.h"
      89                 : #include "nsIHTMLContentSink.h" 
      90                 : #include "nsCSSFrameConstructor.h"
      91                 : 
      92                 : #include "nsFrameTraversal.h"
      93                 : #include "nsStyleChangeList.h"
      94                 : #include "nsIDOMRange.h"
      95                 : #include "nsRange.h"
      96                 : #include "nsITableLayout.h"    //selection necessity
      97                 : #include "nsITableCellLayout.h"//  "
      98                 : #include "nsITextControlFrame.h"
      99                 : #include "nsINameSpaceManager.h"
     100                 : #include "nsIPercentHeightObserver.h"
     101                 : #include "nsStyleStructInlines.h"
     102                 : 
     103                 : #ifdef IBMBIDI
     104                 : #include "nsBidiPresUtils.h"
     105                 : #endif
     106                 : 
     107                 : // For triple-click pref
     108                 : #include "nsIServiceManager.h"
     109                 : #include "imgIContainer.h"
     110                 : #include "imgIRequest.h"
     111                 : #include "nsLayoutCID.h"
     112                 : #include "nsUnicharUtils.h"
     113                 : #include "nsLayoutErrors.h"
     114                 : #include "nsContentErrors.h"
     115                 : #include "nsContainerFrame.h"
     116                 : #include "nsBoxLayoutState.h"
     117                 : #include "nsBlockFrame.h"
     118                 : #include "nsDisplayList.h"
     119                 : #include "nsIObjectLoadingContent.h"
     120                 : #include "nsExpirationTracker.h"
     121                 : #include "nsSVGIntegrationUtils.h"
     122                 : #include "nsSVGEffects.h"
     123                 : #include "nsChangeHint.h"
     124                 : #include "nsDeckFrame.h"
     125                 : 
     126                 : #include "gfxContext.h"
     127                 : #include "CSSCalc.h"
     128                 : #include "nsAbsoluteContainingBlock.h"
     129                 : 
     130                 : #include "mozilla/Preferences.h"
     131                 : #include "mozilla/LookAndFeel.h"
     132                 : 
     133                 : using namespace mozilla;
     134                 : using namespace mozilla::layers;
     135                 : using namespace mozilla::layout;
     136                 : 
     137                 : // Struct containing cached metrics for box-wrapped frames.
     138                 : struct nsBoxLayoutMetrics
     139               0 : {
     140                 :   nsSize mPrefSize;
     141                 :   nsSize mMinSize;
     142                 :   nsSize mMaxSize;
     143                 : 
     144                 :   nsSize mBlockMinSize;
     145                 :   nsSize mBlockPrefSize;
     146                 :   nscoord mBlockAscent;
     147                 : 
     148                 :   nscoord mFlex;
     149                 :   nscoord mAscent;
     150                 : 
     151                 :   nsSize mLastSize;
     152                 : };
     153                 : 
     154                 : struct nsContentAndOffset
     155                 : {
     156                 :   nsIContent* mContent;
     157                 :   PRInt32 mOffset;
     158                 : };
     159                 : 
     160                 : // Some Misc #defines
     161                 : #define SELECTION_DEBUG        0
     162                 : #define FORCE_SELECTION_UPDATE 1
     163                 : #define CALC_DEBUG             0
     164                 : 
     165                 : 
     166                 : #include "nsILineIterator.h"
     167                 : 
     168                 : //non Hack prototypes
     169                 : #if 0
     170                 : static void RefreshContentFrames(nsPresContext* aPresContext, nsIContent * aStartContent, nsIContent * aEndContent);
     171                 : #endif
     172                 : 
     173                 : #include "prenv.h"
     174                 : 
     175                 : // Formerly the nsIFrameDebug interface
     176                 : 
     177                 : #ifdef NS_DEBUG
     178                 : static bool gShowFrameBorders = false;
     179                 : 
     180               0 : void nsFrame::ShowFrameBorders(bool aEnable)
     181                 : {
     182               0 :   gShowFrameBorders = aEnable;
     183               0 : }
     184                 : 
     185               0 : bool nsFrame::GetShowFrameBorders()
     186                 : {
     187               0 :   return gShowFrameBorders;
     188                 : }
     189                 : 
     190                 : static bool gShowEventTargetFrameBorder = false;
     191                 : 
     192               0 : void nsFrame::ShowEventTargetFrameBorder(bool aEnable)
     193                 : {
     194               0 :   gShowEventTargetFrameBorder = aEnable;
     195               0 : }
     196                 : 
     197               0 : bool nsFrame::GetShowEventTargetFrameBorder()
     198                 : {
     199               0 :   return gShowEventTargetFrameBorder;
     200                 : }
     201                 : 
     202                 : /**
     203                 :  * Note: the log module is created during library initialization which
     204                 :  * means that you cannot perform logging before then.
     205                 :  */
     206                 : static PRLogModuleInfo* gLogModule;
     207                 : 
     208                 : static PRLogModuleInfo* gStyleVerifyTreeLogModuleInfo;
     209                 : 
     210                 : static PRUint32 gStyleVerifyTreeEnable = 0x55;
     211                 : 
     212                 : bool
     213               0 : nsFrame::GetVerifyStyleTreeEnable()
     214                 : {
     215               0 :   if (gStyleVerifyTreeEnable == 0x55) {
     216               0 :     if (nsnull == gStyleVerifyTreeLogModuleInfo) {
     217               0 :       gStyleVerifyTreeLogModuleInfo = PR_NewLogModule("styleverifytree");
     218               0 :       gStyleVerifyTreeEnable = 0 != gStyleVerifyTreeLogModuleInfo->level;
     219                 :     }
     220                 :   }
     221               0 :   return gStyleVerifyTreeEnable;
     222                 : }
     223                 : 
     224                 : void
     225               0 : nsFrame::SetVerifyStyleTreeEnable(bool aEnabled)
     226                 : {
     227               0 :   gStyleVerifyTreeEnable = aEnabled;
     228               0 : }
     229                 : 
     230                 : PRLogModuleInfo*
     231               0 : nsFrame::GetLogModuleInfo()
     232                 : {
     233               0 :   if (nsnull == gLogModule) {
     234               0 :     gLogModule = PR_NewLogModule("frame");
     235                 :   }
     236               0 :   return gLogModule;
     237                 : }
     238                 : 
     239                 : void
     240               0 : nsFrame::DumpFrameTree(nsIFrame* aFrame)
     241                 : {
     242               0 :     RootFrameList(aFrame->PresContext(), stdout, 0);
     243               0 : }
     244                 : 
     245                 : void
     246               0 : nsFrame::RootFrameList(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent)
     247                 : {
     248               0 :   if (!aPresContext || !out)
     249               0 :     return;
     250                 : 
     251               0 :   nsIPresShell *shell = aPresContext->GetPresShell();
     252               0 :   if (shell) {
     253               0 :     nsIFrame* frame = shell->FrameManager()->GetRootFrame();
     254               0 :     if(frame) {
     255               0 :       frame->List(out, aIndent);
     256                 :     }
     257                 :   }
     258                 : }
     259                 : #endif
     260                 : 
     261                 : static void
     262               0 : DestroyAbsoluteContainingBlock(void* aPropertyValue)
     263                 : {
     264               0 :   delete static_cast<nsAbsoluteContainingBlock*>(aPropertyValue);
     265               0 : }
     266                 : 
     267               0 : NS_DECLARE_FRAME_PROPERTY(AbsoluteContainingBlockProperty, DestroyAbsoluteContainingBlock)
     268                 : 
     269                 : bool
     270               0 : nsIFrame::HasAbsolutelyPositionedChildren() const {
     271               0 :   return IsAbsoluteContainer() && GetAbsoluteContainingBlock()->HasAbsoluteFrames();
     272                 : }
     273                 : 
     274                 : nsAbsoluteContainingBlock*
     275               0 : nsIFrame::GetAbsoluteContainingBlock() const {
     276               0 :   NS_ASSERTION(IsAbsoluteContainer(), "The frame is not marked as an abspos container correctly");
     277                 :   nsAbsoluteContainingBlock* absCB = static_cast<nsAbsoluteContainingBlock*>
     278               0 :     (Properties().Get(AbsoluteContainingBlockProperty()));
     279               0 :   NS_ASSERTION(absCB, "The frame is marked as an abspos container but doesn't have the property");
     280               0 :   return absCB;
     281                 : }
     282                 : 
     283                 : void
     284               0 : nsIFrame::MarkAsAbsoluteContainingBlock() {
     285               0 :   AddStateBits(NS_FRAME_HAS_ABSPOS_CHILDREN);
     286               0 :   Properties().Set(AbsoluteContainingBlockProperty(), new nsAbsoluteContainingBlock(GetAbsoluteListID()));
     287               0 : }
     288                 : 
     289                 : bool
     290               0 : nsIFrame::CheckAndClearPaintedState()
     291                 : {
     292               0 :   bool result = (GetStateBits() & NS_FRAME_PAINTED_THEBES);
     293               0 :   RemoveStateBits(NS_FRAME_PAINTED_THEBES);
     294                 :   
     295               0 :   nsIFrame::ChildListIterator lists(this);
     296               0 :   for (; !lists.IsDone(); lists.Next()) {
     297               0 :     nsFrameList::Enumerator childFrames(lists.CurrentList());
     298               0 :     for (; !childFrames.AtEnd(); childFrames.Next()) {
     299               0 :       nsIFrame* child = childFrames.get();
     300               0 :       if (child->CheckAndClearPaintedState()) {
     301               0 :         result = true;
     302                 :       }
     303                 :     }
     304                 :   }
     305               0 :   return result;
     306                 : }
     307                 : 
     308                 : bool
     309               0 : nsIFrame::IsVisibleConsideringAncestors(PRUint32 aFlags) const
     310                 : {
     311               0 :   if (!GetStyleVisibility()->IsVisible()) {
     312               0 :     return false;
     313                 :   }
     314                 : 
     315               0 :   const nsIFrame* frame = this;
     316               0 :   while (frame) {
     317               0 :     nsIView* view = frame->GetView();
     318               0 :     if (view && view->GetVisibility() == nsViewVisibility_kHide)
     319               0 :       return false;
     320                 :     
     321               0 :     nsIFrame* parent = frame->GetParent();
     322               0 :     nsDeckFrame* deck = do_QueryFrame(parent);
     323               0 :     if (deck) {
     324               0 :       if (deck->GetSelectedBox() != frame)
     325               0 :         return false;
     326                 :     }
     327                 : 
     328               0 :     if (parent) {
     329               0 :       frame = parent;
     330                 :     } else {
     331               0 :       parent = nsLayoutUtils::GetCrossDocParentFrame(frame);
     332               0 :       if (!parent)
     333               0 :         break;
     334                 : 
     335               0 :       if ((aFlags & nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY) == 0 &&
     336               0 :           parent->PresContext()->IsChrome() && !frame->PresContext()->IsChrome()) {
     337               0 :         break;
     338                 :       }
     339                 : 
     340               0 :       if (!parent->GetStyleVisibility()->IsVisible())
     341               0 :         return false;
     342                 : 
     343               0 :       frame = parent;
     344                 :     }
     345                 :   }
     346                 : 
     347               0 :   return true;
     348                 : }
     349                 : 
     350                 : static bool ApplyOverflowClipping(nsDisplayListBuilder* aBuilder,
     351                 :                                     const nsIFrame* aFrame,
     352                 :                                     const nsStyleDisplay* aDisp, 
     353                 :                                     nsRect* aRect);
     354                 : 
     355                 : static bool ApplyClipPropClipping(nsDisplayListBuilder* aBuilder,
     356                 :                                   const nsStyleDisplay* aDisp, 
     357                 :                                   const nsIFrame* aFrame,
     358                 :                                   nsRect* aRect);
     359                 : 
     360                 : void
     361               0 : NS_MergeReflowStatusInto(nsReflowStatus* aPrimary, nsReflowStatus aSecondary)
     362                 : {
     363                 :   *aPrimary |= aSecondary &
     364                 :     (NS_FRAME_NOT_COMPLETE | NS_FRAME_OVERFLOW_INCOMPLETE |
     365               0 :      NS_FRAME_TRUNCATED | NS_FRAME_REFLOW_NEXTINFLOW);
     366               0 :   if (*aPrimary & NS_FRAME_NOT_COMPLETE) {
     367               0 :     *aPrimary &= ~NS_FRAME_OVERFLOW_INCOMPLETE;
     368                 :   }
     369               0 : }
     370                 : 
     371                 : void
     372            2928 : nsWeakFrame::InitInternal(nsIFrame* aFrame)
     373                 : {
     374            2928 :   Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nsnull);
     375            2928 :   mFrame = aFrame;
     376            2928 :   if (mFrame) {
     377               0 :     nsIPresShell* shell = mFrame->PresContext()->GetPresShell();
     378               0 :     NS_WARN_IF_FALSE(shell, "Null PresShell in nsWeakFrame!");
     379               0 :     if (shell) {
     380               0 :       shell->AddWeakFrame(this);
     381                 :     } else {
     382               0 :       mFrame = nsnull;
     383                 :     }
     384                 :   }
     385            2928 : }
     386                 : 
     387                 : nsIFrame*
     388               0 : NS_NewEmptyFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
     389                 : {
     390               0 :   return new (aPresShell) nsFrame(aContext);
     391                 : }
     392                 : 
     393               0 : nsFrame::nsFrame(nsStyleContext* aContext)
     394                 : {
     395               0 :   MOZ_COUNT_CTOR(nsFrame);
     396                 : 
     397               0 :   mState = NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY;
     398               0 :   mStyleContext = aContext;
     399               0 :   mStyleContext->AddRef();
     400               0 : }
     401                 : 
     402               0 : nsFrame::~nsFrame()
     403                 : {
     404               0 :   MOZ_COUNT_DTOR(nsFrame);
     405                 : 
     406               0 :   NS_IF_RELEASE(mContent);
     407               0 :   if (mStyleContext)
     408               0 :     mStyleContext->Release();
     409               0 : }
     410                 : 
     411               0 : NS_IMPL_FRAMEARENA_HELPERS(nsFrame)
     412                 : 
     413                 : // Dummy operator delete.  Will never be called, but must be defined
     414                 : // to satisfy some C++ ABIs.
     415                 : void
     416               0 : nsFrame::operator delete(void *, size_t)
     417                 : {
     418               0 :   NS_RUNTIMEABORT("nsFrame::operator delete should never be called");
     419               0 : }
     420                 : 
     421               0 : NS_QUERYFRAME_HEAD(nsFrame)
     422               0 :   NS_QUERYFRAME_ENTRY(nsIFrame)
     423               0 : NS_QUERYFRAME_TAIL_INHERITANCE_ROOT
     424                 : 
     425                 : /////////////////////////////////////////////////////////////////////////////
     426                 : // nsIFrame
     427                 : 
     428                 : static bool
     429               0 : IsFontSizeInflationContainer(nsIFrame* aFrame,
     430                 :                              const nsStyleDisplay* aStyleDisplay)
     431                 : {
     432                 :   /*
     433                 :    * Font size inflation is built around the idea that we're inflating
     434                 :    * the fonts for a pan-and-zoom UI so that when the user scales up a
     435                 :    * block or other container to fill the width of the device, the fonts
     436                 :    * will be readable.  To do this, we need to pick what counts as a
     437                 :    * container.
     438                 :    *
     439                 :    * From a code perspective, the only hard requirement is that frames
     440                 :    * that are line participants
     441                 :    * (nsIFrame::IsFrameOfType(nsIFrame::eLineParticipant)) are never
     442                 :    * containers, since line layout assumes that the inflation is
     443                 :    * consistent within a line.
     444                 :    *
     445                 :    * This is not an imposition, since we obviously want a bunch of text
     446                 :    * (possibly with inline elements) flowing within a block to count the
     447                 :    * block (or higher) as its container.
     448                 :    *
     449                 :    * We also want form controls, including the text in the anonymous
     450                 :    * content inside of them, to match each other and the text next to
     451                 :    * them, so they and their anonymous content should also not be a
     452                 :    * container.
     453                 :    *
     454                 :    * However, because we can't reliably compute sizes across XUL during
     455                 :    * reflow, any XUL frame with a XUL parent is always a container.
     456                 :    *
     457                 :    * There are contexts where it would be nice if some blocks didn't
     458                 :    * count as a container, so that, for example, an indented quotation
     459                 :    * didn't end up with a smaller font size.  However, it's hard to
     460                 :    * distinguish these situations where we really do want the indented
     461                 :    * thing to count as a container, so we don't try, and blocks are
     462                 :    * always containers.
     463                 :    */
     464               0 :   nsIContent *content = aFrame->GetContent();
     465                 :   bool isInline = (aStyleDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE ||
     466               0 :                    (aStyleDisplay->IsFloating() &&
     467               0 :                     aFrame->GetType() == nsGkAtoms::letterFrame) ||
     468                 :                    // Given multiple frames for the same node, only the
     469                 :                    // outer one should be considered a container.
     470                 :                    // (Important, e.g., for nsSelectsAreaFrame.)
     471               0 :                    (aFrame->GetParent() &&
     472               0 :                     aFrame->GetParent()->GetContent() == content) ||
     473               0 :                    (content && (content->IsHTML(nsGkAtoms::option) ||
     474               0 :                                 content->IsHTML(nsGkAtoms::optgroup) ||
     475               0 :                                 content->IsInNativeAnonymousSubtree()))) &&
     476               0 :                   !(aFrame->IsBoxFrame() && aFrame->GetParent() &&
     477               0 :                     aFrame->GetParent()->IsBoxFrame());
     478               0 :   NS_ASSERTION(!aFrame->IsFrameOfType(nsIFrame::eLineParticipant) ||
     479                 :                isInline ||
     480                 :                // br frames and mathml frames report being line
     481                 :                // participants even when their position or display is
     482                 :                // set
     483                 :                aFrame->GetType() == nsGkAtoms::brFrame ||
     484                 :                aFrame->IsFrameOfType(nsIFrame::eMathML),
     485                 :                "line participants must not be containers");
     486               0 :   NS_ASSERTION(aFrame->GetType() != nsGkAtoms::bulletFrame || isInline,
     487                 :                "bullets should not be containers");
     488               0 :   return !isInline;
     489                 : }
     490                 : 
     491                 : NS_IMETHODIMP
     492               0 : nsFrame::Init(nsIContent*      aContent,
     493                 :               nsIFrame*        aParent,
     494                 :               nsIFrame*        aPrevInFlow)
     495                 : {
     496               0 :   NS_PRECONDITION(!mContent, "Double-initing a frame?");
     497               0 :   NS_ASSERTION(IsFrameOfType(eDEBUGAllFrames) &&
     498                 :                !IsFrameOfType(eDEBUGNoFrames),
     499                 :                "IsFrameOfType implementation that doesn't call base class");
     500                 : 
     501               0 :   mContent = aContent;
     502               0 :   mParent = aParent;
     503                 : 
     504               0 :   if (aContent) {
     505               0 :     NS_ADDREF(aContent);
     506                 :   }
     507                 : 
     508               0 :   if (aPrevInFlow) {
     509                 :     // Make sure the general flags bits are the same
     510               0 :     nsFrameState state = aPrevInFlow->GetStateBits();
     511                 : 
     512                 :     // Make bits that are currently off (see constructor) the same:
     513                 :     mState |= state & (NS_FRAME_INDEPENDENT_SELECTION |
     514                 :                        NS_FRAME_IS_SPECIAL |
     515               0 :                        NS_FRAME_MAY_BE_TRANSFORMED);
     516                 :   }
     517               0 :   if (mParent) {
     518               0 :     nsFrameState state = mParent->GetStateBits();
     519                 : 
     520                 :     // Make bits that are currently off (see constructor) the same:
     521                 :     mState |= state & (NS_FRAME_INDEPENDENT_SELECTION |
     522               0 :                        NS_FRAME_GENERATED_CONTENT);
     523                 :   }
     524               0 :   const nsStyleDisplay *disp = GetStyleDisplay();
     525               0 :   if (disp->HasTransform()) {
     526                 :     // The frame gets reconstructed if we toggle the -moz-transform
     527                 :     // property, so we can set this bit here and then ignore it.
     528               0 :     mState |= NS_FRAME_MAY_BE_TRANSFORMED;
     529                 :   }
     530                 : 
     531               0 :   if (nsLayoutUtils::FontSizeInflationEnabled(PresContext())
     532                 : #ifdef DEBUG
     533                 :       // We have assertions that check inflation invariants even when
     534                 :       // font size inflation is not enabled.
     535                 :       || true
     536                 : #endif
     537                 :       ) {
     538               0 :     if (IsFontSizeInflationContainer(this, disp)) {
     539               0 :       mState |= NS_FRAME_FONT_INFLATION_CONTAINER;
     540                 :     }
     541                 :   }
     542                 : 
     543               0 :   DidSetStyleContext(nsnull);
     544                 : 
     545               0 :   if (IsBoxWrapped())
     546               0 :     InitBoxMetrics(false);
     547                 : 
     548               0 :   return NS_OK;
     549                 : }
     550                 : 
     551               0 : NS_IMETHODIMP nsFrame::SetInitialChildList(ChildListID     aListID,
     552                 :                                            nsFrameList&    aChildList)
     553                 : {
     554                 :   // XXX This shouldn't be getting called at all, but currently is for backwards
     555                 :   // compatility reasons...
     556                 : #if 0
     557                 :   NS_ERROR("not a container");
     558                 :   return NS_ERROR_UNEXPECTED;
     559                 : #else
     560               0 :   NS_ASSERTION(aChildList.IsEmpty(), "not a container");
     561               0 :   return NS_OK;
     562                 : #endif
     563                 : }
     564                 : 
     565                 : NS_IMETHODIMP
     566               0 : nsFrame::AppendFrames(ChildListID     aListID,
     567                 :                       nsFrameList&    aFrameList)
     568                 : {
     569               0 :   NS_PRECONDITION(false, "not a container");
     570               0 :   return NS_ERROR_UNEXPECTED;
     571                 : }
     572                 : 
     573                 : NS_IMETHODIMP
     574               0 : nsFrame::InsertFrames(ChildListID     aListID,
     575                 :                       nsIFrame*       aPrevFrame,
     576                 :                       nsFrameList&    aFrameList)
     577                 : {
     578               0 :   NS_PRECONDITION(false, "not a container");
     579               0 :   return NS_ERROR_UNEXPECTED;
     580                 : }
     581                 : 
     582                 : NS_IMETHODIMP
     583               0 : nsFrame::RemoveFrame(ChildListID     aListID,
     584                 :                      nsIFrame*       aOldFrame)
     585                 : {
     586               0 :   NS_PRECONDITION(false, "not a container");
     587               0 :   return NS_ERROR_UNEXPECTED;
     588                 : }
     589                 : 
     590                 : void
     591               0 : nsFrame::DestroyFrom(nsIFrame* aDestructRoot)
     592                 : {
     593               0 :   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
     594                 :     "destroy called on frame while scripts not blocked");
     595               0 :   NS_ASSERTION(!GetNextSibling() && !GetPrevSibling(),
     596                 :                "Frames should be removed before destruction.");
     597               0 :   NS_ASSERTION(aDestructRoot, "Must specify destruct root");
     598                 : 
     599               0 :   nsSVGEffects::InvalidateDirectRenderingObservers(this);
     600                 : 
     601                 :   // Get the view pointer now before the frame properties disappear
     602                 :   // when we call NotifyDestroyingFrame()
     603               0 :   nsIView* view = GetView();
     604               0 :   nsPresContext* presContext = PresContext();
     605                 : 
     606               0 :   nsIPresShell *shell = presContext->GetPresShell();
     607               0 :   if (mState & NS_FRAME_OUT_OF_FLOW) {
     608                 :     nsPlaceholderFrame* placeholder =
     609               0 :       shell->FrameManager()->GetPlaceholderFrameFor(this);
     610               0 :     NS_ASSERTION(!placeholder || (aDestructRoot != this),
     611                 :                  "Don't call Destroy() on OOFs, call Destroy() on the placeholder.");
     612               0 :     NS_ASSERTION(!placeholder ||
     613                 :                  nsLayoutUtils::IsProperAncestorFrame(aDestructRoot, placeholder),
     614                 :                  "Placeholder relationship should have been torn down already; "
     615                 :                  "this might mean we have a stray placeholder in the tree.");
     616               0 :     if (placeholder) {
     617               0 :       shell->FrameManager()->UnregisterPlaceholderFrame(placeholder);
     618               0 :       placeholder->SetOutOfFlowFrame(nsnull);
     619                 :     }
     620                 :   }
     621                 : 
     622                 :   // If we have any IB split special siblings, clear their references to us.
     623                 :   // (Note: This has to happen before we call shell->NotifyDestroyingFrame,
     624                 :   // because that clears our Properties() table.)
     625               0 :   if (mState & NS_FRAME_IS_SPECIAL) {
     626                 :     // Delete previous sibling's reference to me.
     627                 :     nsIFrame* prevSib = static_cast<nsIFrame*>
     628               0 :       (Properties().Get(nsIFrame::IBSplitSpecialPrevSibling()));
     629               0 :     if (prevSib) {
     630               0 :       NS_WARN_IF_FALSE(this ==
     631                 :          prevSib->Properties().Get(nsIFrame::IBSplitSpecialSibling()),
     632                 :          "IB sibling chain is inconsistent");
     633               0 :       prevSib->Properties().Delete(nsIFrame::IBSplitSpecialSibling());
     634                 :     }
     635                 : 
     636                 :     // Delete next sibling's reference to me.
     637                 :     nsIFrame* nextSib = static_cast<nsIFrame*>
     638               0 :       (Properties().Get(nsIFrame::IBSplitSpecialSibling()));
     639               0 :     if (nextSib) {
     640               0 :       NS_WARN_IF_FALSE(this ==
     641                 :          nextSib->Properties().Get(nsIFrame::IBSplitSpecialPrevSibling()),
     642                 :          "IB sibling chain is inconsistent");
     643               0 :       nextSib->Properties().Delete(nsIFrame::IBSplitSpecialPrevSibling());
     644                 :     }
     645                 :   }
     646                 : 
     647               0 :   shell->NotifyDestroyingFrame(this);
     648                 : 
     649               0 :   if (mState & NS_FRAME_EXTERNAL_REFERENCE) {
     650               0 :     shell->ClearFrameRefs(this);
     651                 :   }
     652                 : 
     653               0 :   if (view) {
     654                 :     // Break association between view and frame
     655               0 :     view->SetFrame(nsnull);
     656                 : 
     657                 :     // Destroy the view
     658               0 :     view->Destroy();
     659                 :   }
     660                 : 
     661                 :   // Make sure that our deleted frame can't be returned from GetPrimaryFrame()
     662               0 :   if (mContent && mContent->GetPrimaryFrame() == this) {
     663               0 :     mContent->SetPrimaryFrame(nsnull);
     664                 :   }
     665                 : 
     666                 :   // Must retrieve the object ID before calling destructors, so the
     667                 :   // vtable is still valid.
     668                 :   //
     669                 :   // Note to future tweakers: having the method that returns the
     670                 :   // object size call the destructor will not avoid an indirect call;
     671                 :   // the compiler cannot devirtualize the call to the destructor even
     672                 :   // if it's from a method defined in the same class.
     673                 : 
     674               0 :   nsQueryFrame::FrameIID id = GetFrameId();
     675               0 :   this->~nsFrame();
     676                 : 
     677                 :   // Now that we're totally cleaned out, we need to add ourselves to
     678                 :   // the presshell's recycler.
     679               0 :   shell->FreeFrame(id, this);
     680               0 : }
     681                 : 
     682                 : NS_IMETHODIMP
     683               0 : nsFrame::GetOffsets(PRInt32 &aStart, PRInt32 &aEnd) const
     684                 : {
     685               0 :   aStart = 0;
     686               0 :   aEnd = 0;
     687               0 :   return NS_OK;
     688                 : }
     689                 : 
     690                 : static bool
     691               0 : EqualImages(imgIRequest *aOldImage, imgIRequest *aNewImage)
     692                 : {
     693               0 :   if (aOldImage == aNewImage)
     694               0 :     return true;
     695                 : 
     696               0 :   if (!aOldImage || !aNewImage)
     697               0 :     return false;
     698                 : 
     699               0 :   nsCOMPtr<nsIURI> oldURI, newURI;
     700               0 :   aOldImage->GetURI(getter_AddRefs(oldURI));
     701               0 :   aNewImage->GetURI(getter_AddRefs(newURI));
     702                 :   bool equal;
     703               0 :   return NS_SUCCEEDED(oldURI->Equals(newURI, &equal)) && equal;
     704                 : }
     705                 : 
     706                 : // Subclass hook for style post processing
     707                 : /* virtual */ void
     708               0 : nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
     709                 : {
     710               0 :   if (aOldStyleContext) {
     711                 :     // If the old context had a background image image and new context
     712                 :     // does not have the same image, clear the image load notifier
     713                 :     // (which keeps the image loading, if it still is) for the frame.
     714                 :     // We want to do this conservatively because some frames paint their
     715                 :     // backgrounds from some other frame's style data, and we don't want
     716                 :     // to clear those notifiers unless we have to.  (They'll be reset
     717                 :     // when we paint, although we could miss a notification in that
     718                 :     // interval.)
     719               0 :     const nsStyleBackground *oldBG = aOldStyleContext->GetStyleBackground();
     720               0 :     const nsStyleBackground *newBG = GetStyleBackground();
     721               0 :     NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, oldBG) {
     722               0 :       if (i >= newBG->mImageCount ||
     723               0 :           oldBG->mLayers[i].mImage != newBG->mLayers[i].mImage) {
     724                 :         // stop the image loading for the frame, the image has changed
     725                 :         PresContext()->SetImageLoaders(this,
     726               0 :           nsPresContext::BACKGROUND_IMAGE, nsnull);
     727               0 :         break;
     728                 :       }
     729                 :     }
     730                 : 
     731                 :     // If we detect a change on margin, padding or border, we store the old
     732                 :     // values on the frame itself between now and reflow, so if someone
     733                 :     // calls GetUsed(Margin|Border|Padding)() before the next reflow, we
     734                 :     // can give an accurate answer.
     735                 :     // We don't want to set the property if one already exists.
     736               0 :     FrameProperties props = Properties();
     737               0 :     nsMargin oldValue(0, 0, 0, 0);
     738               0 :     nsMargin newValue(0, 0, 0, 0);
     739               0 :     const nsStyleMargin* oldMargin = aOldStyleContext->PeekStyleMargin();
     740               0 :     if (oldMargin && oldMargin->GetMargin(oldValue)) {
     741               0 :       if ((!GetStyleMargin()->GetMargin(newValue) || oldValue != newValue) &&
     742               0 :           !props.Get(UsedMarginProperty())) {
     743               0 :         props.Set(UsedMarginProperty(), new nsMargin(oldValue));
     744                 :       }
     745                 :     }
     746                 : 
     747               0 :     const nsStylePadding* oldPadding = aOldStyleContext->PeekStylePadding();
     748               0 :     if (oldPadding && oldPadding->GetPadding(oldValue)) {
     749               0 :       if ((!GetStylePadding()->GetPadding(newValue) || oldValue != newValue) &&
     750               0 :           !props.Get(UsedPaddingProperty())) {
     751               0 :         props.Set(UsedPaddingProperty(), new nsMargin(oldValue));
     752                 :       }
     753                 :     }
     754                 : 
     755               0 :     const nsStyleBorder* oldBorder = aOldStyleContext->PeekStyleBorder();
     756               0 :     if (oldBorder) {
     757               0 :       oldValue = oldBorder->GetActualBorder();
     758               0 :       newValue = GetStyleBorder()->GetActualBorder();
     759               0 :       if (oldValue != newValue &&
     760               0 :           !props.Get(UsedBorderProperty())) {
     761               0 :         props.Set(UsedBorderProperty(), new nsMargin(oldValue));
     762                 :       }
     763                 :     }
     764                 :   }
     765                 : 
     766                 :   imgIRequest *oldBorderImage = aOldStyleContext
     767               0 :     ? aOldStyleContext->GetStyleBorder()->GetBorderImage()
     768               0 :     : nsnull;
     769                 :   // For border-images, we can't be as conservative (we need to set the
     770                 :   // new loaders if there has been any change) since the CalcDifference
     771                 :   // call depended on the result of GetActualBorder() and that result
     772                 :   // depends on whether the image has loaded, start the image load now
     773                 :   // so that we'll get notified when it completes loading and can do a
     774                 :   // restyle.  Otherwise, the image might finish loading from the
     775                 :   // network before we start listening to its notifications, and then
     776                 :   // we'll never know that it's finished loading.  Likewise, we want to
     777                 :   // do this for freshly-created frames to prevent a similar race if the
     778                 :   // image loads between reflow (which can depend on whether the image
     779                 :   // is loaded) and paint.  We also don't really care about any callers
     780                 :   // who try to paint borders with a different style context, because
     781                 :   // they won't have the correct size for the border either.
     782               0 :   if (!EqualImages(oldBorderImage, GetStyleBorder()->GetBorderImage())) {
     783                 :     // stop and restart the image loading/notification
     784               0 :     PresContext()->SetupBorderImageLoaders(this, GetStyleBorder());
     785                 :   }
     786                 : 
     787                 :   // If the page contains markup that overrides text direction, and
     788                 :   // does not contain any characters that would activate the Unicode
     789                 :   // bidi algorithm, we need to call |SetBidiEnabled| on the pres
     790                 :   // context before reflow starts.  See bug 115921.
     791               0 :   if (GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
     792               0 :     PresContext()->SetBidiEnabled();
     793                 :   }
     794               0 : }
     795                 : 
     796                 : // MSVC fails with link error "one or more multiply defined symbols found",
     797                 : // gcc fails with "hidden symbol `nsIFrame::kPrincipalList' isn't defined"
     798                 : // etc if they are not defined.
     799                 : #ifndef _MSC_VER
     800                 : // static nsIFrame constants; initialized in the header file.
     801                 : const nsIFrame::ChildListID nsIFrame::kPrincipalList;
     802                 : const nsIFrame::ChildListID nsIFrame::kAbsoluteList;
     803                 : const nsIFrame::ChildListID nsIFrame::kBulletList;
     804                 : const nsIFrame::ChildListID nsIFrame::kCaptionList;
     805                 : const nsIFrame::ChildListID nsIFrame::kColGroupList;
     806                 : const nsIFrame::ChildListID nsIFrame::kExcessOverflowContainersList;
     807                 : const nsIFrame::ChildListID nsIFrame::kFixedList;
     808                 : const nsIFrame::ChildListID nsIFrame::kFloatList;
     809                 : const nsIFrame::ChildListID nsIFrame::kOverflowContainersList;
     810                 : const nsIFrame::ChildListID nsIFrame::kOverflowList;
     811                 : const nsIFrame::ChildListID nsIFrame::kOverflowOutOfFlowList;
     812                 : const nsIFrame::ChildListID nsIFrame::kPopupList;
     813                 : const nsIFrame::ChildListID nsIFrame::kPushedFloatsList;
     814                 : const nsIFrame::ChildListID nsIFrame::kSelectPopupList;
     815                 : const nsIFrame::ChildListID nsIFrame::kNoReflowPrincipalList;
     816                 : #endif
     817                 : 
     818                 : /* virtual */ nsMargin
     819               0 : nsIFrame::GetUsedMargin() const
     820                 : {
     821               0 :   nsMargin margin(0, 0, 0, 0);
     822               0 :   if ((mState & NS_FRAME_FIRST_REFLOW) &&
     823               0 :       !(mState & NS_FRAME_IN_REFLOW))
     824               0 :     return margin;
     825                 : 
     826                 :   nsMargin *m = static_cast<nsMargin*>
     827               0 :                            (Properties().Get(UsedMarginProperty()));
     828               0 :   if (m) {
     829               0 :     margin = *m;
     830                 :   } else {
     831                 : #ifdef DEBUG
     832                 :     bool hasMargin = 
     833                 : #endif
     834               0 :     GetStyleMargin()->GetMargin(margin);
     835               0 :     NS_ASSERTION(hasMargin, "We should have a margin here! (out of memory?)");
     836                 :   }
     837               0 :   return margin;
     838                 : }
     839                 : 
     840                 : /* virtual */ nsMargin
     841               0 : nsIFrame::GetUsedBorder() const
     842                 : {
     843               0 :   nsMargin border(0, 0, 0, 0);
     844               0 :   if ((mState & NS_FRAME_FIRST_REFLOW) &&
     845               0 :       !(mState & NS_FRAME_IN_REFLOW))
     846               0 :     return border;
     847                 : 
     848                 :   // Theme methods don't use const-ness.
     849               0 :   nsIFrame *mutable_this = const_cast<nsIFrame*>(this);
     850                 : 
     851               0 :   const nsStyleDisplay *disp = GetStyleDisplay();
     852               0 :   if (mutable_this->IsThemed(disp)) {
     853               0 :     nsIntMargin result;
     854               0 :     nsPresContext *presContext = PresContext();
     855               0 :     presContext->GetTheme()->GetWidgetBorder(presContext->DeviceContext(),
     856                 :                                              mutable_this, disp->mAppearance,
     857               0 :                                              &result);
     858               0 :     border.left = presContext->DevPixelsToAppUnits(result.left);
     859               0 :     border.top = presContext->DevPixelsToAppUnits(result.top);
     860               0 :     border.right = presContext->DevPixelsToAppUnits(result.right);
     861               0 :     border.bottom = presContext->DevPixelsToAppUnits(result.bottom);
     862               0 :     return border;
     863                 :   }
     864                 : 
     865                 :   nsMargin *b = static_cast<nsMargin*>
     866               0 :                            (Properties().Get(UsedBorderProperty()));
     867               0 :   if (b) {
     868               0 :     border = *b;
     869                 :   } else {
     870               0 :     border = GetStyleBorder()->GetActualBorder();
     871                 :   }
     872               0 :   return border;
     873                 : }
     874                 : 
     875                 : /* virtual */ nsMargin
     876               0 : nsIFrame::GetUsedPadding() const
     877                 : {
     878               0 :   nsMargin padding(0, 0, 0, 0);
     879               0 :   if ((mState & NS_FRAME_FIRST_REFLOW) &&
     880               0 :       !(mState & NS_FRAME_IN_REFLOW))
     881               0 :     return padding;
     882                 : 
     883                 :   // Theme methods don't use const-ness.
     884               0 :   nsIFrame *mutable_this = const_cast<nsIFrame*>(this);
     885                 : 
     886               0 :   const nsStyleDisplay *disp = GetStyleDisplay();
     887               0 :   if (mutable_this->IsThemed(disp)) {
     888               0 :     nsPresContext *presContext = PresContext();
     889               0 :     nsIntMargin widget;
     890               0 :     if (presContext->GetTheme()->GetWidgetPadding(presContext->DeviceContext(),
     891                 :                                                   mutable_this,
     892                 :                                                   disp->mAppearance,
     893               0 :                                                   &widget)) {
     894               0 :       padding.top = presContext->DevPixelsToAppUnits(widget.top);
     895               0 :       padding.right = presContext->DevPixelsToAppUnits(widget.right);
     896               0 :       padding.bottom = presContext->DevPixelsToAppUnits(widget.bottom);
     897               0 :       padding.left = presContext->DevPixelsToAppUnits(widget.left);
     898               0 :       return padding;
     899                 :     }
     900                 :   }
     901                 : 
     902                 :   nsMargin *p = static_cast<nsMargin*>
     903               0 :                            (Properties().Get(UsedPaddingProperty()));
     904               0 :   if (p) {
     905               0 :     padding = *p;
     906                 :   } else {
     907                 : #ifdef DEBUG
     908                 :     bool hasPadding = 
     909                 : #endif
     910               0 :     GetStylePadding()->GetPadding(padding);
     911               0 :     NS_ASSERTION(hasPadding, "We should have padding here! (out of memory?)");
     912                 :   }
     913               0 :   return padding;
     914                 : }
     915                 : 
     916                 : void
     917               0 : nsIFrame::ApplySkipSides(nsMargin& aMargin) const
     918                 : {
     919               0 :   PRIntn skipSides = GetSkipSides();
     920               0 :   if (skipSides & (1 << NS_SIDE_TOP))
     921               0 :     aMargin.top = 0;
     922               0 :   if (skipSides & (1 << NS_SIDE_RIGHT))
     923               0 :     aMargin.right = 0;
     924               0 :   if (skipSides & (1 << NS_SIDE_BOTTOM))
     925               0 :     aMargin.bottom = 0;
     926               0 :   if (skipSides & (1 << NS_SIDE_LEFT))
     927               0 :     aMargin.left = 0;
     928               0 : }
     929                 : 
     930                 : nsRect
     931               0 : nsIFrame::GetPaddingRectRelativeToSelf() const
     932                 : {
     933               0 :   nsMargin bp(GetUsedBorder());
     934               0 :   ApplySkipSides(bp);
     935               0 :   nsRect r(0, 0, mRect.width, mRect.height);
     936               0 :   r.Deflate(bp);
     937                 :   return r;
     938                 : }
     939                 : 
     940                 : nsRect
     941               0 : nsIFrame::GetPaddingRect() const
     942                 : {
     943               0 :   return GetPaddingRectRelativeToSelf() + GetPosition();
     944                 : }
     945                 : 
     946                 : bool
     947               0 : nsIFrame::IsTransformed() const
     948                 : {
     949                 :   return (mState & NS_FRAME_MAY_BE_TRANSFORMED) &&
     950               0 :     GetStyleDisplay()->HasTransform();
     951                 : }
     952                 : 
     953                 : bool
     954               0 : nsIFrame::Preserves3DChildren() const
     955                 : {
     956               0 :   if (GetStyleDisplay()->mTransformStyle != NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D || !IsTransformed())
     957               0 :       return false;
     958                 : 
     959                 :   // If we're all scroll frame, then all descendants will be clipped, so we can't preserve 3d.
     960               0 :   if (GetType() == nsGkAtoms::scrollFrame)
     961               0 :       return false;
     962                 : 
     963               0 :   nsRect temp;
     964               0 :   return (!ApplyOverflowClipping(nsnull, this, GetStyleDisplay(), &temp) &&
     965               0 :       !ApplyClipPropClipping(nsnull, GetStyleDisplay(), this, &temp) &&
     966               0 :       !nsSVGIntegrationUtils::UsingEffectsForFrame(this));
     967                 : }
     968                 : 
     969                 : bool
     970               0 : nsIFrame::Preserves3D() const
     971                 : {
     972               0 :   if (!GetParent() || !GetParent()->Preserves3DChildren() || !IsTransformed()) {
     973               0 :     return false;
     974                 :   }
     975               0 :   return true;
     976                 : }
     977                 : 
     978                 : bool
     979               0 : nsIFrame::HasPerspective() const
     980                 : {
     981               0 :   if (!IsTransformed()) {
     982               0 :     return false;
     983                 :   }
     984               0 :   const nsStyleDisplay* parentDisp = nsnull;
     985               0 :   nsStyleContext* parentStyleContext = GetStyleContext()->GetParent();
     986               0 :   if (parentStyleContext) {
     987               0 :     parentDisp = parentStyleContext->GetStyleDisplay();
     988                 :   }
     989                 : 
     990               0 :   if (parentDisp &&
     991               0 :       parentDisp->mChildPerspective.GetUnit() == eStyleUnit_Coord &&
     992               0 :       parentDisp->mChildPerspective.GetCoordValue() > 0.0) {
     993               0 :     return true;
     994                 :   }
     995               0 :   return false;
     996                 : }
     997                 : 
     998                 : bool
     999               0 : nsIFrame::ChildrenHavePerspective() const
    1000                 : {
    1001               0 :   const nsStyleDisplay *disp = GetStyleContext()->GetStyleDisplay();
    1002               0 :   if (disp &&
    1003               0 :       disp->mChildPerspective.GetUnit() == eStyleUnit_Coord &&
    1004               0 :       disp->mChildPerspective.GetCoordValue() > 0.0) {
    1005               0 :     return true;
    1006                 :   }
    1007               0 :   return false;
    1008                 : }
    1009                 : 
    1010                 : nsRect
    1011               0 : nsIFrame::GetContentRectRelativeToSelf() const
    1012                 : {
    1013               0 :   nsMargin bp(GetUsedBorderAndPadding());
    1014               0 :   ApplySkipSides(bp);
    1015               0 :   nsRect r(0, 0, mRect.width, mRect.height);
    1016               0 :   r.Deflate(bp);
    1017                 :   return r;
    1018                 : }
    1019                 : 
    1020                 : nsRect
    1021               0 : nsIFrame::GetContentRect() const
    1022                 : {
    1023               0 :   return GetContentRectRelativeToSelf() + GetPosition();
    1024                 : }
    1025                 : 
    1026                 : bool
    1027               0 : nsIFrame::ComputeBorderRadii(const nsStyleCorners& aBorderRadius,
    1028                 :                              const nsSize& aFrameSize,
    1029                 :                              const nsSize& aBorderArea,
    1030                 :                              PRIntn aSkipSides,
    1031                 :                              nscoord aRadii[8])
    1032                 : {
    1033                 :   // Percentages are relative to whichever side they're on.
    1034               0 :   NS_FOR_CSS_HALF_CORNERS(i) {
    1035               0 :     const nsStyleCoord c = aBorderRadius.Get(i);
    1036                 :     nscoord axis =
    1037               0 :       NS_HALF_CORNER_IS_X(i) ? aFrameSize.width : aFrameSize.height;
    1038                 : 
    1039               0 :     if (c.IsCoordPercentCalcUnit()) {
    1040               0 :       aRadii[i] = nsRuleNode::ComputeCoordPercentCalc(c, axis);
    1041               0 :       if (aRadii[i] < 0) {
    1042                 :         // clamp calc()
    1043               0 :         aRadii[i] = 0;
    1044                 :       }
    1045                 :     } else {
    1046               0 :       NS_NOTREACHED("ComputeBorderRadii: bad unit");
    1047               0 :       aRadii[i] = 0;
    1048                 :     }
    1049                 :   }
    1050                 : 
    1051               0 :   if (aSkipSides & (1 << NS_SIDE_TOP)) {
    1052               0 :     aRadii[NS_CORNER_TOP_LEFT_X] = 0;
    1053               0 :     aRadii[NS_CORNER_TOP_LEFT_Y] = 0;
    1054               0 :     aRadii[NS_CORNER_TOP_RIGHT_X] = 0;
    1055               0 :     aRadii[NS_CORNER_TOP_RIGHT_Y] = 0;
    1056                 :   }
    1057                 : 
    1058               0 :   if (aSkipSides & (1 << NS_SIDE_RIGHT)) {
    1059               0 :     aRadii[NS_CORNER_TOP_RIGHT_X] = 0;
    1060               0 :     aRadii[NS_CORNER_TOP_RIGHT_Y] = 0;
    1061               0 :     aRadii[NS_CORNER_BOTTOM_RIGHT_X] = 0;
    1062               0 :     aRadii[NS_CORNER_BOTTOM_RIGHT_Y] = 0;
    1063                 :   }
    1064                 : 
    1065               0 :   if (aSkipSides & (1 << NS_SIDE_BOTTOM)) {
    1066               0 :     aRadii[NS_CORNER_BOTTOM_RIGHT_X] = 0;
    1067               0 :     aRadii[NS_CORNER_BOTTOM_RIGHT_Y] = 0;
    1068               0 :     aRadii[NS_CORNER_BOTTOM_LEFT_X] = 0;
    1069               0 :     aRadii[NS_CORNER_BOTTOM_LEFT_Y] = 0;
    1070                 :   }
    1071                 : 
    1072               0 :   if (aSkipSides & (1 << NS_SIDE_LEFT)) {
    1073               0 :     aRadii[NS_CORNER_BOTTOM_LEFT_X] = 0;
    1074               0 :     aRadii[NS_CORNER_BOTTOM_LEFT_Y] = 0;
    1075               0 :     aRadii[NS_CORNER_TOP_LEFT_X] = 0;
    1076               0 :     aRadii[NS_CORNER_TOP_LEFT_Y] = 0;
    1077                 :   }
    1078                 : 
    1079                 :   // css3-background specifies this algorithm for reducing
    1080                 :   // corner radii when they are too big.
    1081               0 :   bool haveRadius = false;
    1082               0 :   double ratio = 1.0f;
    1083               0 :   NS_FOR_CSS_SIDES(side) {
    1084               0 :     PRUint32 hc1 = NS_SIDE_TO_HALF_CORNER(side, false, true);
    1085               0 :     PRUint32 hc2 = NS_SIDE_TO_HALF_CORNER(side, true, true);
    1086                 :     nscoord length =
    1087               0 :       NS_SIDE_IS_VERTICAL(side) ? aBorderArea.height : aBorderArea.width;
    1088               0 :     nscoord sum = aRadii[hc1] + aRadii[hc2];
    1089               0 :     if (sum)
    1090               0 :       haveRadius = true;
    1091                 : 
    1092                 :     // avoid floating point division in the normal case
    1093               0 :     if (length < sum)
    1094               0 :       ratio = NS_MIN(ratio, double(length)/sum);
    1095                 :   }
    1096               0 :   if (ratio < 1.0) {
    1097               0 :     NS_FOR_CSS_HALF_CORNERS(corner) {
    1098               0 :       aRadii[corner] *= ratio;
    1099                 :     }
    1100                 :   }
    1101                 : 
    1102               0 :   return haveRadius;
    1103                 : }
    1104                 : 
    1105                 : /* static */ void
    1106               0 : nsIFrame::InsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets)
    1107                 : {
    1108               0 :   NS_FOR_CSS_SIDES(side) {
    1109               0 :     nscoord offset = aOffsets.Side(side);
    1110               0 :     PRUint32 hc1 = NS_SIDE_TO_HALF_CORNER(side, false, false);
    1111               0 :     PRUint32 hc2 = NS_SIDE_TO_HALF_CORNER(side, true, false);
    1112               0 :     aRadii[hc1] = NS_MAX(0, aRadii[hc1] - offset);
    1113               0 :     aRadii[hc2] = NS_MAX(0, aRadii[hc2] - offset);
    1114                 :   }
    1115               0 : }
    1116                 : 
    1117                 : /* static */ void
    1118               0 : nsIFrame::OutsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets)
    1119                 : {
    1120               0 :   NS_FOR_CSS_SIDES(side) {
    1121               0 :     nscoord offset = aOffsets.Side(side);
    1122               0 :     PRUint32 hc1 = NS_SIDE_TO_HALF_CORNER(side, false, false);
    1123               0 :     PRUint32 hc2 = NS_SIDE_TO_HALF_CORNER(side, true, false);
    1124               0 :     if (aRadii[hc1] > 0)
    1125               0 :       aRadii[hc1] += offset;
    1126               0 :     if (aRadii[hc2] > 0)
    1127               0 :       aRadii[hc2] += offset;
    1128                 :   }
    1129               0 : }
    1130                 : 
    1131                 : /* virtual */ bool
    1132               0 : nsIFrame::GetBorderRadii(nscoord aRadii[8]) const
    1133                 : {
    1134               0 :   if (IsThemed()) {
    1135                 :     // When we're themed, the native theme code draws the border and
    1136                 :     // background, and therefore it doesn't make sense to tell other
    1137                 :     // code that's interested in border-radius that we have any radii.
    1138                 :     //
    1139                 :     // In an ideal world, we might have a way for the them to tell us an
    1140                 :     // border radius, but since we don't, we're better off assuming
    1141                 :     // zero.
    1142               0 :     NS_FOR_CSS_HALF_CORNERS(corner) {
    1143               0 :       aRadii[corner] = 0;
    1144                 :     }
    1145               0 :     return false;
    1146                 :   }
    1147               0 :   nsSize size = GetSize();
    1148               0 :   return ComputeBorderRadii(GetStyleBorder()->mBorderRadius, size, size,
    1149               0 :                             GetSkipSides(), aRadii);
    1150                 : }
    1151                 : 
    1152                 : bool
    1153               0 : nsIFrame::GetPaddingBoxBorderRadii(nscoord aRadii[8]) const
    1154                 : {
    1155               0 :   if (!GetBorderRadii(aRadii))
    1156               0 :     return false;
    1157               0 :   InsetBorderRadii(aRadii, GetUsedBorder());
    1158               0 :   NS_FOR_CSS_HALF_CORNERS(corner) {
    1159               0 :     if (aRadii[corner])
    1160               0 :       return true;
    1161                 :   }
    1162               0 :   return false;
    1163                 : }
    1164                 : 
    1165                 : bool
    1166               0 : nsIFrame::GetContentBoxBorderRadii(nscoord aRadii[8]) const
    1167                 : {
    1168               0 :   if (!GetBorderRadii(aRadii))
    1169               0 :     return false;
    1170               0 :   InsetBorderRadii(aRadii, GetUsedBorderAndPadding());
    1171               0 :   NS_FOR_CSS_HALF_CORNERS(corner) {
    1172               0 :     if (aRadii[corner])
    1173               0 :       return true;
    1174                 :   }
    1175               0 :   return false;
    1176                 : }
    1177                 : 
    1178                 : nsStyleContext*
    1179               0 : nsFrame::GetAdditionalStyleContext(PRInt32 aIndex) const
    1180                 : {
    1181               0 :   NS_PRECONDITION(aIndex >= 0, "invalid index number");
    1182               0 :   return nsnull;
    1183                 : }
    1184                 : 
    1185                 : void
    1186               0 : nsFrame::SetAdditionalStyleContext(PRInt32 aIndex, 
    1187                 :                                    nsStyleContext* aStyleContext)
    1188                 : {
    1189               0 :   NS_PRECONDITION(aIndex >= 0, "invalid index number");
    1190               0 : }
    1191                 : 
    1192                 : nscoord
    1193               0 : nsFrame::GetBaseline() const
    1194                 : {
    1195               0 :   NS_ASSERTION(!NS_SUBTREE_DIRTY(this),
    1196                 :                "frame must not be dirty");
    1197                 :   // Default to the bottom margin edge, per CSS2.1's definition of the
    1198                 :   // 'baseline' value of 'vertical-align'.
    1199               0 :   return mRect.height + GetUsedMargin().bottom;
    1200                 : }
    1201                 : 
    1202                 : const nsFrameList&
    1203               0 : nsFrame::GetChildList(ChildListID aListID) const
    1204                 : {
    1205               0 :   if (IsAbsoluteContainer() &&
    1206               0 :       aListID == GetAbsoluteListID()) {
    1207               0 :     return GetAbsoluteContainingBlock()->GetChildList();
    1208                 :   } else {
    1209               0 :     return nsFrameList::EmptyList();
    1210                 :   }
    1211                 : }
    1212                 : 
    1213                 : void
    1214               0 : nsFrame::GetChildLists(nsTArray<ChildList>* aLists) const
    1215                 : {
    1216               0 :   if (IsAbsoluteContainer()) {
    1217               0 :     nsFrameList absoluteList = GetAbsoluteContainingBlock()->GetChildList();
    1218               0 :     absoluteList.AppendIfNonempty(aLists, GetAbsoluteListID());
    1219                 :   }
    1220               0 : }
    1221                 : 
    1222                 : static nsIFrame*
    1223               0 : GetActiveSelectionFrame(nsPresContext* aPresContext, nsIFrame* aFrame)
    1224                 : {
    1225               0 :   nsIContent* capturingContent = nsIPresShell::GetCapturingContent();
    1226               0 :   if (capturingContent) {
    1227               0 :     nsIFrame* activeFrame = aPresContext->GetPrimaryFrameFor(capturingContent);
    1228               0 :     return activeFrame ? activeFrame : aFrame;
    1229                 :   }
    1230                 : 
    1231               0 :   return aFrame;
    1232                 : }
    1233                 : 
    1234                 : PRInt16
    1235               0 : nsFrame::DisplaySelection(nsPresContext* aPresContext, bool isOkToTurnOn)
    1236                 : {
    1237               0 :   PRInt16 selType = nsISelectionController::SELECTION_OFF;
    1238                 : 
    1239               0 :   nsCOMPtr<nsISelectionController> selCon;
    1240               0 :   nsresult result = GetSelectionController(aPresContext, getter_AddRefs(selCon));
    1241               0 :   if (NS_SUCCEEDED(result) && selCon) {
    1242               0 :     result = selCon->GetDisplaySelection(&selType);
    1243               0 :     if (NS_SUCCEEDED(result) && (selType != nsISelectionController::SELECTION_OFF)) {
    1244                 :       // Check whether style allows selection.
    1245                 :       bool selectable;
    1246               0 :       IsSelectable(&selectable, nsnull);
    1247               0 :       if (!selectable) {
    1248               0 :         selType = nsISelectionController::SELECTION_OFF;
    1249               0 :         isOkToTurnOn = false;
    1250                 :       }
    1251                 :     }
    1252               0 :     if (isOkToTurnOn && (selType == nsISelectionController::SELECTION_OFF)) {
    1253               0 :       selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
    1254               0 :       selType = nsISelectionController::SELECTION_ON;
    1255                 :     }
    1256                 :   }
    1257               0 :   return selType;
    1258                 : }
    1259                 : 
    1260                 : class nsDisplaySelectionOverlay : public nsDisplayItem {
    1261                 : public:
    1262               0 :   nsDisplaySelectionOverlay(nsDisplayListBuilder* aBuilder,
    1263                 :                             nsFrame* aFrame, PRInt16 aSelectionValue)
    1264               0 :     : nsDisplayItem(aBuilder, aFrame), mSelectionValue(aSelectionValue) {
    1265               0 :     MOZ_COUNT_CTOR(nsDisplaySelectionOverlay);
    1266               0 :   }
    1267                 : #ifdef NS_BUILD_REFCNT_LOGGING
    1268               0 :   virtual ~nsDisplaySelectionOverlay() {
    1269               0 :     MOZ_COUNT_DTOR(nsDisplaySelectionOverlay);
    1270               0 :   }
    1271                 : #endif
    1272                 : 
    1273                 :   virtual void Paint(nsDisplayListBuilder* aBuilder,
    1274                 :                      nsRenderingContext* aCtx);
    1275               0 :   NS_DISPLAY_DECL_NAME("SelectionOverlay", TYPE_SELECTION_OVERLAY)
    1276                 : private:
    1277                 :   PRInt16 mSelectionValue;
    1278                 : };
    1279                 : 
    1280               0 : void nsDisplaySelectionOverlay::Paint(nsDisplayListBuilder* aBuilder,
    1281                 :                                       nsRenderingContext* aCtx)
    1282                 : {
    1283                 :   LookAndFeel::ColorID colorID;
    1284               0 :   if (mSelectionValue == nsISelectionController::SELECTION_ON) {
    1285               0 :     colorID = LookAndFeel::eColorID_TextSelectBackground;
    1286               0 :   } else if (mSelectionValue == nsISelectionController::SELECTION_ATTENTION) {
    1287               0 :     colorID = LookAndFeel::eColorID_TextSelectBackgroundAttention;
    1288                 :   } else {
    1289               0 :     colorID = LookAndFeel::eColorID_TextSelectBackgroundDisabled;
    1290                 :   }
    1291                 : 
    1292               0 :   nscolor color = LookAndFeel::GetColor(colorID, NS_RGB(255, 255, 255));
    1293                 : 
    1294               0 :   gfxRGBA c(color);
    1295               0 :   c.a = .5;
    1296                 : 
    1297               0 :   gfxContext *ctx = aCtx->ThebesContext();
    1298               0 :   ctx->SetColor(c);
    1299                 : 
    1300                 :   nsIntRect pxRect =
    1301               0 :     mVisibleRect.ToOutsidePixels(mFrame->PresContext()->AppUnitsPerDevPixel());
    1302               0 :   ctx->NewPath();
    1303               0 :   ctx->Rectangle(gfxRect(pxRect.x, pxRect.y, pxRect.width, pxRect.height), true);
    1304               0 :   ctx->Fill();
    1305               0 : }
    1306                 : 
    1307                 : /********************************************************
    1308                 : * Refreshes each content's frame
    1309                 : *********************************************************/
    1310                 : 
    1311                 : nsresult
    1312               0 : nsFrame::DisplaySelectionOverlay(nsDisplayListBuilder*   aBuilder,
    1313                 :                                  nsDisplayList*          aList,
    1314                 :                                  PRUint16                aContentType)
    1315                 : {
    1316               0 :   if (!IsSelected() || !IsVisibleForPainting(aBuilder))
    1317               0 :     return NS_OK;
    1318                 :     
    1319               0 :   nsPresContext* presContext = PresContext();
    1320               0 :   nsIPresShell *shell = presContext->PresShell();
    1321               0 :   if (!shell)
    1322               0 :     return NS_OK;
    1323                 : 
    1324               0 :   PRInt16 displaySelection = shell->GetSelectionFlags();
    1325               0 :   if (!(displaySelection & aContentType))
    1326               0 :     return NS_OK;
    1327                 : 
    1328               0 :   const nsFrameSelection* frameSelection = GetConstFrameSelection();
    1329               0 :   PRInt16 selectionValue = frameSelection->GetDisplaySelection();
    1330                 : 
    1331               0 :   if (selectionValue <= nsISelectionController::SELECTION_HIDDEN)
    1332               0 :     return NS_OK; // selection is hidden or off
    1333                 : 
    1334               0 :   nsIContent *newContent = mContent->GetParent();
    1335                 : 
    1336                 :   //check to see if we are anonymous content
    1337               0 :   PRInt32 offset = 0;
    1338               0 :   if (newContent) {
    1339                 :     // XXXbz there has GOT to be a better way of determining this!
    1340               0 :     offset = newContent->IndexOf(mContent);
    1341                 :   }
    1342                 : 
    1343                 :   SelectionDetails *details;
    1344                 :   //look up to see what selection(s) are on this frame
    1345               0 :   details = frameSelection->LookUpSelection(newContent, offset, 1, false);
    1346                 :   // XXX is the above really necessary? We don't actually DO anything
    1347                 :   // with the details other than test that they're non-null
    1348               0 :   if (!details)
    1349               0 :     return NS_OK;
    1350                 :   
    1351               0 :   while (details) {
    1352               0 :     SelectionDetails *next = details->mNext;
    1353               0 :     delete details;
    1354               0 :     details = next;
    1355                 :   }
    1356                 : 
    1357                 :   return aList->AppendNewToTop(new (aBuilder)
    1358               0 :       nsDisplaySelectionOverlay(aBuilder, this, selectionValue));
    1359                 : }
    1360                 : 
    1361                 : nsresult
    1362               0 : nsFrame::DisplayOutlineUnconditional(nsDisplayListBuilder*   aBuilder,
    1363                 :                                      const nsDisplayListSet& aLists)
    1364                 : {
    1365               0 :   if (GetStyleOutline()->GetOutlineStyle() == NS_STYLE_BORDER_STYLE_NONE)
    1366               0 :     return NS_OK;
    1367                 :     
    1368                 :   return aLists.Outlines()->AppendNewToTop(
    1369               0 :       new (aBuilder) nsDisplayOutline(aBuilder, this));
    1370                 : }
    1371                 : 
    1372                 : nsresult
    1373               0 : nsFrame::DisplayOutline(nsDisplayListBuilder*   aBuilder,
    1374                 :                         const nsDisplayListSet& aLists)
    1375                 : {
    1376               0 :   if (!IsVisibleForPainting(aBuilder))
    1377               0 :     return NS_OK;
    1378                 : 
    1379               0 :   return DisplayOutlineUnconditional(aBuilder, aLists);
    1380                 : }
    1381                 : 
    1382                 : nsresult
    1383               0 : nsIFrame::DisplayCaret(nsDisplayListBuilder* aBuilder,
    1384                 :                        const nsRect& aDirtyRect, nsDisplayList* aList)
    1385                 : {
    1386               0 :   if (!IsVisibleForPainting(aBuilder))
    1387               0 :     return NS_OK;
    1388                 : 
    1389                 :   return aList->AppendNewToTop(
    1390               0 :       new (aBuilder) nsDisplayCaret(aBuilder, this, aBuilder->GetCaret()));
    1391                 : }
    1392                 : 
    1393                 : nscolor
    1394               0 : nsIFrame::GetCaretColorAt(PRInt32 aOffset)
    1395                 : {
    1396                 :   // Use text color.
    1397               0 :   return GetStyleColor()->mColor;
    1398                 : }
    1399                 : 
    1400                 : bool
    1401               0 : nsIFrame::HasBorder() const
    1402                 : {
    1403                 :   // Border images contribute to the background of the content area
    1404                 :   // even if there's no border proper.
    1405               0 :   return (GetUsedBorder() != nsMargin(0,0,0,0) ||
    1406               0 :           GetStyleBorder()->IsBorderImageLoaded());
    1407                 : }
    1408                 : 
    1409                 : nsresult
    1410               0 : nsFrame::DisplayBackgroundUnconditional(nsDisplayListBuilder*   aBuilder,
    1411                 :                                         const nsDisplayListSet& aLists,
    1412                 :                                         bool                    aForceBackground)
    1413                 : {
    1414                 :   // Here we don't try to detect background propagation. Frames that might
    1415                 :   // receive a propagated background should just set aForceBackground to
    1416                 :   // true.
    1417               0 :   if (aBuilder->IsForEventDelivery() || aForceBackground ||
    1418               0 :       !GetStyleBackground()->IsTransparent() || GetStyleDisplay()->mAppearance) {
    1419                 :     return aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
    1420               0 :         nsDisplayBackground(aBuilder, this));
    1421                 :   }
    1422               0 :   return NS_OK;
    1423                 : }
    1424                 : 
    1425                 : nsresult
    1426               0 : nsFrame::DisplayBorderBackgroundOutline(nsDisplayListBuilder*   aBuilder,
    1427                 :                                         const nsDisplayListSet& aLists,
    1428                 :                                         bool                    aForceBackground)
    1429                 : {
    1430                 :   // The visibility check belongs here since child elements have the
    1431                 :   // opportunity to override the visibility property and display even if
    1432                 :   // their parent is hidden.
    1433               0 :   if (!IsVisibleForPainting(aBuilder))
    1434               0 :     return NS_OK;
    1435                 : 
    1436               0 :   bool hasBoxShadow = GetStyleBorder()->mBoxShadow != nsnull;
    1437               0 :   if (hasBoxShadow) {
    1438                 :     nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
    1439               0 :         nsDisplayBoxShadowOuter(aBuilder, this));
    1440               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1441                 :   }
    1442                 : 
    1443                 :   nsresult rv =
    1444               0 :     DisplayBackgroundUnconditional(aBuilder, aLists, aForceBackground);
    1445               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1446                 : 
    1447               0 :   if (hasBoxShadow) {
    1448                 :     rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
    1449               0 :         nsDisplayBoxShadowInner(aBuilder, this));
    1450               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1451                 :   }
    1452                 :   
    1453               0 :   if (HasBorder()) {
    1454                 :     rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
    1455               0 :         nsDisplayBorder(aBuilder, this));
    1456               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1457                 :   }
    1458                 : 
    1459               0 :   return DisplayOutlineUnconditional(aBuilder, aLists);
    1460                 : }
    1461                 : 
    1462                 : bool
    1463               0 : nsIFrame::GetClipPropClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
    1464                 :                               const nsSize& aSize) const
    1465                 : {
    1466               0 :   NS_PRECONDITION(aRect, "Must have aRect out parameter");
    1467                 : 
    1468               0 :   if (!aDisp->IsAbsolutelyPositioned() ||
    1469               0 :       !(aDisp->mClipFlags & NS_STYLE_CLIP_RECT))
    1470               0 :     return false;
    1471                 : 
    1472               0 :   *aRect = aDisp->mClip;
    1473               0 :   if (NS_STYLE_CLIP_RIGHT_AUTO & aDisp->mClipFlags) {
    1474               0 :     aRect->width = aSize.width - aRect->x;
    1475                 :   }
    1476               0 :   if (NS_STYLE_CLIP_BOTTOM_AUTO & aDisp->mClipFlags) {
    1477               0 :     aRect->height = aSize.height - aRect->y;
    1478                 :   }
    1479               0 :   return true;
    1480                 : }
    1481                 : 
    1482               0 : static bool ApplyClipPropClipping(nsDisplayListBuilder* aBuilder,
    1483                 :                                   const nsStyleDisplay* aDisp, const nsIFrame* aFrame,
    1484                 :                                   nsRect* aRect) {
    1485               0 :   if (!aFrame->GetClipPropClipRect(aDisp, aRect, aFrame->GetSize()))
    1486               0 :     return false;
    1487                 : 
    1488               0 :   if (aBuilder) {
    1489               0 :     *aRect += aBuilder->ToReferenceFrame(aFrame);
    1490                 :   }
    1491               0 :   return true;
    1492                 : }
    1493                 : 
    1494               0 : static bool ApplyOverflowClipping(nsDisplayListBuilder* aBuilder,
    1495                 :                                   const nsIFrame* aFrame,
    1496                 :                                   const nsStyleDisplay* aDisp, nsRect* aRect) {
    1497                 :   // REVIEW: from nsContainerFrame.cpp SyncFrameViewGeometryDependentProperties,
    1498                 :   // except that that function used the border-edge for
    1499                 :   // -moz-hidden-unscrollable which I don't think is correct... Also I've
    1500                 :   // changed -moz-hidden-unscrollable to apply to any kind of frame.
    1501                 : 
    1502                 :   // Only -moz-hidden-unscrollable is handled here (and 'hidden' for table
    1503                 :   // frames, and any non-visible value for blocks in a paginated context).
    1504                 :   // Other overflow clipping is applied by nsHTML/XULScrollFrame.
    1505                 :   // We allow -moz-hidden-unscrollable to apply to any kind of frame. This
    1506                 :   // is required by comboboxes which make their display text (an inline frame)
    1507                 :   // have clipping.
    1508               0 :   if (!nsFrame::ApplyOverflowClipping(aFrame, aDisp)) {
    1509               0 :     return false;
    1510                 :   }
    1511               0 :   *aRect = aFrame->GetPaddingRect() - aFrame->GetPosition();
    1512               0 :   if (aBuilder) {
    1513               0 :     *aRect += aBuilder->ToReferenceFrame(aFrame);
    1514                 :   }
    1515               0 :   return true;
    1516                 : }
    1517                 : 
    1518                 : class nsOverflowClipWrapper : public nsDisplayWrapper
    1519               0 : {
    1520                 : public:
    1521                 :   /**
    1522                 :    * Create a wrapper to apply overflow clipping for aContainer.
    1523                 :    * @param aClipBorderBackground set to true to clip the BorderBackground()
    1524                 :    * list, otherwise it will not be clipped
    1525                 :    * @param aClipAll set to true to clip all descendants, even those for
    1526                 :    * which we aren't the containing block
    1527                 :    */
    1528               0 :   nsOverflowClipWrapper(nsIFrame* aContainer, const nsRect& aRect,
    1529                 :                         const nscoord aRadii[8],
    1530                 :                         bool aClipBorderBackground, bool aClipAll)
    1531                 :     : mContainer(aContainer), mRect(aRect),
    1532                 :       mClipBorderBackground(aClipBorderBackground), mClipAll(aClipAll),
    1533               0 :       mHaveRadius(false)
    1534                 :   {
    1535               0 :     memcpy(mRadii, aRadii, sizeof(mRadii));
    1536               0 :     NS_FOR_CSS_HALF_CORNERS(corner) {
    1537               0 :       if (aRadii[corner] > 0) {
    1538               0 :         mHaveRadius = true;
    1539               0 :         break;
    1540                 :       }
    1541                 :     }
    1542               0 :   }
    1543               0 :   virtual bool WrapBorderBackground() { return mClipBorderBackground; }
    1544               0 :   virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
    1545                 :                                   nsIFrame* aFrame, nsDisplayList* aList) {
    1546                 :     // We are not a stacking context root. There is no valid underlying
    1547                 :     // frame for the whole list. These items are all in-flow descendants so
    1548                 :     // we can safely just clip them.
    1549               0 :     if (mHaveRadius) {
    1550                 :       return new (aBuilder) nsDisplayClipRoundedRect(aBuilder, nsnull, aList,
    1551               0 :                                                      mRect, mRadii);
    1552                 :     }
    1553               0 :     return new (aBuilder) nsDisplayClip(aBuilder, nsnull, aList, mRect);
    1554                 :   }
    1555               0 :   virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
    1556                 :                                   nsDisplayItem* aItem) {
    1557               0 :     nsIFrame* f = aItem->GetUnderlyingFrame();
    1558               0 :     if (mClipAll ||
    1559               0 :         nsLayoutUtils::IsProperAncestorFrame(mContainer, f, nsnull)) {
    1560               0 :       if (mHaveRadius) {
    1561                 :         return new (aBuilder) nsDisplayClipRoundedRect(aBuilder, f, aItem,
    1562               0 :                                                        mRect, mRadii);
    1563                 :       }
    1564               0 :       return new (aBuilder) nsDisplayClip(aBuilder, f, aItem, mRect);
    1565                 :     }
    1566               0 :     return aItem;
    1567                 :   }
    1568                 : protected:
    1569                 :   nsIFrame*    mContainer;
    1570                 :   nsRect       mRect;
    1571                 :   nscoord      mRadii[8];
    1572                 :   bool mClipBorderBackground;
    1573                 :   bool mClipAll;
    1574                 :   bool mHaveRadius;
    1575                 : };
    1576                 : 
    1577                 : class nsDisplayClipPropWrapper : public nsDisplayWrapper
    1578               0 : {
    1579                 : public:
    1580               0 :   nsDisplayClipPropWrapper(const nsRect& aRect)
    1581               0 :     : mRect(aRect) {}
    1582               0 :   virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
    1583                 :                                   nsIFrame* aFrame, nsDisplayList* aList) {
    1584                 :     // We are not a stacking context root. There is no valid underlying
    1585                 :     // frame for the whole list.
    1586               0 :     return new (aBuilder) nsDisplayClip(aBuilder, nsnull, aList, mRect);
    1587                 :   }
    1588               0 :   virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
    1589                 :                                   nsDisplayItem* aItem) {
    1590                 :     return new (aBuilder) nsDisplayClip(aBuilder, aItem->GetUnderlyingFrame(),
    1591               0 :                                         aItem, mRect);
    1592                 :   }
    1593                 : protected:
    1594                 :   nsRect    mRect;
    1595                 : };
    1596                 : 
    1597                 : nsresult
    1598               0 : nsIFrame::OverflowClip(nsDisplayListBuilder*   aBuilder,
    1599                 :                        const nsDisplayListSet& aFromSet,
    1600                 :                        const nsDisplayListSet& aToSet,
    1601                 :                        const nsRect&           aClipRect,
    1602                 :                        const nscoord           aClipRadii[8],
    1603                 :                        bool                    aClipBorderBackground,
    1604                 :                        bool                    aClipAll)
    1605                 : {
    1606                 :   nsOverflowClipWrapper wrapper(this, aClipRect, aClipRadii,
    1607               0 :                                 aClipBorderBackground, aClipAll);
    1608               0 :   return wrapper.WrapLists(aBuilder, this, aFromSet, aToSet);
    1609                 : }
    1610                 : 
    1611                 : static nsresult
    1612               0 : BuildDisplayListWithOverflowClip(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
    1613                 :     const nsRect& aDirtyRect, const nsDisplayListSet& aSet,
    1614                 :     const nsRect& aClipRect, const nscoord aClipRadii[8])
    1615                 : {
    1616               0 :   nsDisplayListCollection set;
    1617               0 :   nsresult rv = aFrame->BuildDisplayList(aBuilder, aDirtyRect, set);
    1618               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1619               0 :   rv = aBuilder->DisplayCaret(aFrame, aDirtyRect, aSet.Content());
    1620               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1621                 : 
    1622               0 :   return aFrame->OverflowClip(aBuilder, set, aSet, aClipRect, aClipRadii);
    1623                 : }
    1624                 : 
    1625                 : #ifdef NS_DEBUG
    1626               0 : static void PaintDebugBorder(nsIFrame* aFrame, nsRenderingContext* aCtx,
    1627                 :      const nsRect& aDirtyRect, nsPoint aPt) {
    1628               0 :   nsRect r(aPt, aFrame->GetSize());
    1629               0 :   if (aFrame->HasView()) {
    1630               0 :     aCtx->SetColor(NS_RGB(0,0,255));
    1631                 :   } else {
    1632               0 :     aCtx->SetColor(NS_RGB(255,0,0));
    1633                 :   }
    1634               0 :   aCtx->DrawRect(r);
    1635               0 : }
    1636                 : 
    1637               0 : static void PaintEventTargetBorder(nsIFrame* aFrame, nsRenderingContext* aCtx,
    1638                 :      const nsRect& aDirtyRect, nsPoint aPt) {
    1639               0 :   nsRect r(aPt, aFrame->GetSize());
    1640               0 :   aCtx->SetColor(NS_RGB(128,0,128));
    1641               0 :   aCtx->DrawRect(r);
    1642               0 : }
    1643                 : 
    1644                 : static void
    1645               0 : DisplayDebugBorders(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
    1646                 :                     const nsDisplayListSet& aLists) {
    1647                 :   // Draw a border around the child
    1648                 :   // REVIEW: From nsContainerFrame::PaintChild
    1649               0 :   if (nsFrame::GetShowFrameBorders() && !aFrame->GetRect().IsEmpty()) {
    1650                 :     aLists.Outlines()->AppendNewToTop(new (aBuilder)
    1651                 :         nsDisplayGeneric(aBuilder, aFrame, PaintDebugBorder, "DebugBorder",
    1652               0 :                          nsDisplayItem::TYPE_DEBUG_BORDER));
    1653                 :   }
    1654                 :   // Draw a border around the current event target
    1655               0 :   if (nsFrame::GetShowEventTargetFrameBorder() &&
    1656               0 :       aFrame->PresContext()->PresShell()->GetDrawEventTargetFrame() == aFrame) {
    1657                 :     aLists.Outlines()->AppendNewToTop(new (aBuilder)
    1658                 :         nsDisplayGeneric(aBuilder, aFrame, PaintEventTargetBorder, "EventTargetBorder",
    1659               0 :                          nsDisplayItem::TYPE_EVENT_TARGET_BORDER));
    1660                 :   }
    1661               0 : }
    1662                 : #endif
    1663                 : 
    1664                 : static nsresult
    1665               0 : WrapPreserve3DListInternal(nsIFrame* aFrame, nsDisplayListBuilder *aBuilder, nsDisplayList *aList, PRUint32& aIndex)
    1666                 : {
    1667               0 :   if (aIndex > nsDisplayTransform::INDEX_MAX) {
    1668               0 :     return NS_OK;
    1669                 :   }
    1670                 : 
    1671               0 :   nsresult rv = NS_OK;
    1672               0 :   nsDisplayList newList;
    1673               0 :   nsDisplayList temp;
    1674               0 :   while (nsDisplayItem *item = aList->RemoveBottom()) {
    1675               0 :     nsIFrame *childFrame = item->GetUnderlyingFrame();
    1676                 : 
    1677                 :     // We accumulate sequential items that aren't transforms into the 'temp' list
    1678                 :     // and then flush this list into newList by wrapping the whole lot with a single
    1679                 :     // nsDisplayTransform.
    1680                 : 
    1681               0 :     if (childFrame && (childFrame->GetParent()->Preserves3DChildren() || childFrame == aFrame)) {
    1682               0 :       switch (item->GetType()) {
    1683                 :         case nsDisplayItem::TYPE_TRANSFORM: {
    1684               0 :           if (!temp.IsEmpty()) {
    1685               0 :             newList.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, &temp, aIndex++));
    1686                 :           }
    1687               0 :           newList.AppendToTop(item);
    1688               0 :           break;
    1689                 :         }
    1690                 :         case nsDisplayItem::TYPE_WRAP_LIST: {
    1691               0 :           if (!temp.IsEmpty()) {
    1692               0 :             newList.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, &temp, aIndex++));
    1693                 :           }
    1694               0 :           nsDisplayWrapList *list = static_cast<nsDisplayWrapList*>(item);
    1695               0 :           rv = WrapPreserve3DListInternal(aFrame, aBuilder, list->GetList(), aIndex);
    1696               0 :           newList.AppendToTop(list->GetList());
    1697               0 :           list->~nsDisplayWrapList();
    1698               0 :           break;
    1699                 :         }
    1700                 :         case nsDisplayItem::TYPE_OPACITY: {
    1701               0 :           if (!temp.IsEmpty()) {
    1702               0 :             newList.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, &temp, aIndex++));
    1703                 :           }
    1704               0 :           nsDisplayOpacity *opacity = static_cast<nsDisplayOpacity*>(item);
    1705               0 :           rv = WrapPreserve3DListInternal(aFrame, aBuilder, opacity->GetList(), aIndex);
    1706               0 :           newList.AppendToTop(item);
    1707               0 :           break;
    1708                 :         }
    1709                 :         default: {
    1710               0 :           temp.AppendToTop(item);
    1711               0 :           break;
    1712                 :         }
    1713                 :       } 
    1714                 :     } else {
    1715               0 :       temp.AppendToTop(item);
    1716                 :     }
    1717                 :  
    1718               0 :     if (NS_FAILED(rv) || !item || aIndex > nsDisplayTransform::INDEX_MAX)
    1719               0 :       return rv;
    1720                 :   }
    1721                 :     
    1722               0 :   if (!temp.IsEmpty()) {
    1723               0 :     newList.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, &temp, aIndex++));
    1724                 :   }
    1725                 : 
    1726               0 :   aList->AppendToTop(&newList);
    1727               0 :   return NS_OK;
    1728                 : }
    1729                 : 
    1730                 : static nsresult
    1731               0 : WrapPreserve3DList(nsIFrame* aFrame, nsDisplayListBuilder* aBuilder, nsDisplayList *aList)
    1732                 : {
    1733               0 :   PRUint32 index = 0;
    1734               0 :   return WrapPreserve3DListInternal(aFrame, aBuilder, aList, index);
    1735                 : }
    1736                 : 
    1737                 : nsresult
    1738               0 : nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
    1739                 :                                              const nsRect&         aDirtyRect,
    1740                 :                                              nsDisplayList*        aList) {
    1741               0 :   if (GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE)
    1742               0 :     return NS_OK;
    1743                 : 
    1744                 :   // Replaced elements have their visibility handled here, because
    1745                 :   // they're visually atomic
    1746               0 :   if (IsFrameOfType(eReplaced) && !IsVisibleForPainting(aBuilder))
    1747               0 :     return NS_OK;
    1748                 : 
    1749               0 :   nsRect clipPropClip;
    1750               0 :   const nsStyleDisplay* disp = GetStyleDisplay();
    1751                 :   // We can stop right away if this is a zero-opacity stacking context and
    1752                 :   // we're painting.
    1753               0 :   if (disp->mOpacity == 0.0 && aBuilder->IsForPainting())
    1754               0 :     return NS_OK;
    1755                 : 
    1756                 :   bool applyClipPropClipping =
    1757               0 :       ApplyClipPropClipping(aBuilder, disp, this, &clipPropClip);
    1758               0 :   nsRect dirtyRect = aDirtyRect;
    1759                 : 
    1760               0 :   bool inTransform = aBuilder->IsInTransform();
    1761               0 :   if ((mState & NS_FRAME_MAY_BE_TRANSFORMED) &&
    1762               0 :       disp->HasTransform()) {
    1763               0 :     if (nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder, this) ||
    1764               0 :         Preserves3DChildren()) {
    1765               0 :       dirtyRect = GetVisualOverflowRectRelativeToSelf();
    1766                 :     } else {
    1767                 :       // Transform dirtyRect into our frame's local coordinate space. Note that
    1768                 :       // the new value is the bounds of the old value's transformed vertices, so
    1769                 :       // the area covered by dirtyRect may increase here.
    1770                 :       //
    1771                 :       // Although we don't bother to check for and maintain the 1x1 size of the
    1772                 :       // magic rect indicating a hit test point, in reality this is extremely
    1773                 :       // unlikely to matter. The rect starts off with dimensions of 1x1 *app*
    1774                 :       // units, and it would require a very large number of elements with
    1775                 :       // transforms along a parent chain to noticably expand this by an entire
    1776                 :       // device pixel.
    1777               0 :       if (!nsDisplayTransform::UntransformRect(dirtyRect, this, nsPoint(0, 0), &dirtyRect)) {
    1778                 :         // we have a singular transform - just grab the entire overflow rect
    1779               0 :         dirtyRect = GetVisualOverflowRectRelativeToSelf();
    1780                 :       }
    1781                 :     }
    1782               0 :     inTransform = true;
    1783                 :   }
    1784                 : 
    1785               0 :   if (applyClipPropClipping) {
    1786                 :     dirtyRect.IntersectRect(dirtyRect,
    1787               0 :                             clipPropClip - aBuilder->ToReferenceFrame(this));
    1788                 :   }
    1789                 : 
    1790               0 :   bool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this);
    1791               0 :   if (usingSVGEffects) {
    1792                 :     dirtyRect =
    1793               0 :       nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect);
    1794                 :   }
    1795                 : 
    1796                 :   // Mark the display list items for absolutely positioned children
    1797               0 :   MarkAbsoluteFramesForDisplayList(aBuilder, dirtyRect);
    1798                 : 
    1799               0 :   nsDisplayListCollection set;
    1800                 :   nsresult rv;
    1801                 :   {    
    1802               0 :     nsDisplayListBuilder::AutoIsRootSetter rootSetter(aBuilder, true);
    1803                 :     nsDisplayListBuilder::AutoInTransformSetter
    1804               0 :       inTransformSetter(aBuilder, inTransform);
    1805               0 :     rv = BuildDisplayList(aBuilder, dirtyRect, set);
    1806                 :   }
    1807               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1808                 :     
    1809               0 :   if (aBuilder->IsBackgroundOnly()) {
    1810               0 :     set.BlockBorderBackgrounds()->DeleteAll();
    1811               0 :     set.Floats()->DeleteAll();
    1812               0 :     set.Content()->DeleteAll();
    1813               0 :     set.PositionedDescendants()->DeleteAll();
    1814               0 :     set.Outlines()->DeleteAll();
    1815                 :   }
    1816                 :   
    1817                 :   // This z-order sort also sorts secondarily by content order. We need to do
    1818                 :   // this so that boxes produced by the same element are placed together
    1819                 :   // in the sort. Consider a position:relative inline element that breaks
    1820                 :   // across lines and has absolutely positioned children; all the abs-pos
    1821                 :   // children should be z-ordered after all the boxes for the position:relative
    1822                 :   // element itself.
    1823               0 :   set.PositionedDescendants()->SortByZOrder(aBuilder, GetContent());
    1824                 :   
    1825               0 :   nsRect overflowClip;
    1826               0 :   if (ApplyOverflowClipping(aBuilder, this, disp, &overflowClip)) {
    1827                 :     nscoord radii[8];
    1828               0 :     this->GetPaddingBoxBorderRadii(radii);
    1829                 :     nsOverflowClipWrapper wrapper(this, overflowClip, radii,
    1830               0 :                                   false, false);
    1831               0 :     rv = wrapper.WrapListsInPlace(aBuilder, this, set);
    1832               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1833                 :   }
    1834                 :   // We didn't use overflowClip to restrict the dirty rect, since some of the
    1835                 :   // descendants may not be clipped by it. Even if we end up with unnecessary
    1836                 :   // display items, they'll be pruned during ComputeVisibility.  
    1837                 : 
    1838               0 :   nsDisplayList resultList;
    1839                 :   // Now follow the rules of http://www.w3.org/TR/CSS21/zindex.html
    1840                 :   // 1,2: backgrounds and borders
    1841               0 :   resultList.AppendToTop(set.BorderBackground());
    1842                 :   // 3: negative z-index children.
    1843               0 :   for (;;) {
    1844               0 :     nsDisplayItem* item = set.PositionedDescendants()->GetBottom();
    1845               0 :     if (item) {
    1846               0 :       nsIFrame* f = item->GetUnderlyingFrame();
    1847               0 :       NS_ASSERTION(f, "After sorting, every item in the list should have an underlying frame");
    1848               0 :       if (nsLayoutUtils::GetZIndex(f) < 0) {
    1849               0 :         set.PositionedDescendants()->RemoveBottom();
    1850               0 :         resultList.AppendToTop(item);
    1851               0 :         continue;
    1852                 :       }
    1853                 :     }
    1854                 :     break;
    1855                 :   }
    1856                 :   // 4: block backgrounds
    1857               0 :   resultList.AppendToTop(set.BlockBorderBackgrounds());
    1858                 :   // 5: floats
    1859               0 :   resultList.AppendToTop(set.Floats());
    1860                 :   // 7: general content
    1861               0 :   resultList.AppendToTop(set.Content());
    1862                 :   // 7.5: outlines, in content tree order. We need to sort by content order
    1863                 :   // because an element with outline that breaks and has children with outline
    1864                 :   // might have placed child outline items between its own outline items.
    1865                 :   // The element's outline items need to all come before any child outline
    1866                 :   // items.
    1867               0 :   set.Outlines()->SortByContentOrder(aBuilder, GetContent());
    1868                 : #ifdef NS_DEBUG
    1869               0 :   DisplayDebugBorders(aBuilder, this, set);
    1870                 : #endif
    1871               0 :   resultList.AppendToTop(set.Outlines());
    1872                 :   // 8, 9: non-negative z-index children
    1873               0 :   resultList.AppendToTop(set.PositionedDescendants());
    1874                 : 
    1875                 :   /* If we have absolute position clipping and we have, or will have, items to
    1876                 :    * be clipped, wrap the list in a clip wrapper.
    1877                 :    */
    1878               0 :   if (applyClipPropClipping &&
    1879               0 :       (!resultList.IsEmpty() || usingSVGEffects)) {
    1880               0 :     nsDisplayClipPropWrapper wrapper(clipPropClip);
    1881               0 :     nsDisplayItem* item = wrapper.WrapList(aBuilder, this, &resultList);
    1882               0 :     if (!item)
    1883               0 :       return NS_ERROR_OUT_OF_MEMORY;
    1884                 :     // resultList was emptied
    1885               0 :     resultList.AppendToTop(item);
    1886                 :   }
    1887                 : 
    1888                 :   /* If there are any SVG effects, wrap the list up in an SVG effects item
    1889                 :    * (which also handles CSS group opacity). Note that we create an SVG effects
    1890                 :    * item even if resultList is empty, since a filter can produce graphical
    1891                 :    * output even if the element being filtered wouldn't otherwise do so.
    1892                 :    */
    1893               0 :   if (usingSVGEffects) {
    1894                 :     /* List now emptied, so add the new list to the top. */
    1895                 :     rv = resultList.AppendNewToTop(
    1896               0 :         new (aBuilder) nsDisplaySVGEffects(aBuilder, this, &resultList));
    1897               0 :     if (NS_FAILED(rv))
    1898               0 :       return rv;
    1899                 :   }
    1900                 :   /* Else, if the list is non-empty and there is CSS group opacity without SVG
    1901                 :    * effects, wrap it up in an opacity item.
    1902                 :    */
    1903               0 :   else if (disp->mOpacity < 1.0f && !resultList.IsEmpty()) {
    1904                 :     rv = resultList.AppendNewToTop(
    1905               0 :         new (aBuilder) nsDisplayOpacity(aBuilder, this, &resultList));
    1906               0 :     if (NS_FAILED(rv))
    1907               0 :       return rv;
    1908                 :   }
    1909                 : 
    1910                 :   /* If we're going to apply a transformation and don't have preserve-3d set, wrap 
    1911                 :    * everything in an nsDisplayTransform. If there's nothing in the list, don't add 
    1912                 :    * anything.
    1913                 :    *
    1914                 :    * For the preserve-3d case we want to individually wrap every child in the list with
    1915                 :    * a separate nsDisplayTransform instead. When the child is already an nsDisplayTransform,
    1916                 :    * we can skip this step, as the computed transform will already include our own.
    1917                 :    *
    1918                 :    * We also traverse into sublists created by nsDisplayWrapList or nsDisplayOpacity, so that
    1919                 :    * we find all the correct children.
    1920                 :    */
    1921               0 :   if ((mState & NS_FRAME_MAY_BE_TRANSFORMED) &&
    1922               0 :       disp->HasTransform() && !resultList.IsEmpty()) {
    1923               0 :     if (Preserves3DChildren()) {
    1924               0 :       rv = WrapPreserve3DList(this, aBuilder, &resultList);
    1925               0 :       if (NS_FAILED(rv))
    1926               0 :         return rv;
    1927                 :     } else {
    1928                 :       rv = resultList.AppendNewToTop(
    1929               0 :         new (aBuilder) nsDisplayTransform(aBuilder, this, &resultList));
    1930               0 :       if (NS_FAILED(rv))
    1931               0 :         return rv;
    1932                 :     }
    1933                 :   }
    1934                 : 
    1935               0 :   aList->AppendToTop(&resultList);
    1936               0 :   return rv;
    1937                 : }
    1938                 : 
    1939                 : nsresult
    1940               0 : nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder*   aBuilder,
    1941                 :                                    nsIFrame*               aChild,
    1942                 :                                    const nsRect&           aDirtyRect,
    1943                 :                                    const nsDisplayListSet& aLists,
    1944                 :                                    PRUint32                aFlags) {
    1945                 :   // If painting is restricted to just the background of the top level frame,
    1946                 :   // then we have nothing to do here.
    1947               0 :   if (aBuilder->IsBackgroundOnly())
    1948               0 :     return NS_OK;
    1949                 : 
    1950               0 :   nsIFrame* child = aChild;
    1951               0 :   if (child->GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE)
    1952               0 :     return NS_OK;
    1953                 : 
    1954                 :   // true if this is a real or pseudo stacking context
    1955                 :   bool pseudoStackingContext =
    1956               0 :     (aFlags & DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT) != 0;
    1957               0 :   if ((aFlags & DISPLAY_CHILD_INLINE) &&
    1958               0 :       !child->IsFrameOfType(eLineParticipant)) {
    1959                 :     // child is a non-inline frame in an inline context, i.e.,
    1960                 :     // it acts like inline-block or inline-table. Therefore it is a
    1961                 :     // pseudo-stacking-context.
    1962               0 :     pseudoStackingContext = true;
    1963                 :   }
    1964                 : 
    1965                 :   // dirty rect in child-relative coordinates
    1966               0 :   nsRect dirty = aDirtyRect - child->GetOffsetTo(this);
    1967                 : 
    1968               0 :   nsIAtom* childType = child->GetType();
    1969               0 :   if (childType == nsGkAtoms::placeholderFrame) {
    1970               0 :     nsPlaceholderFrame* placeholder = static_cast<nsPlaceholderFrame*>(child);
    1971               0 :     child = placeholder->GetOutOfFlowFrame();
    1972               0 :     NS_ASSERTION(child, "No out of flow frame?");
    1973                 :     // If 'child' is a pushed float then it's owned by a block that's not an
    1974                 :     // ancestor of the placeholder, and it will be painted by that block and
    1975                 :     // should not be painted through the placeholder.
    1976               0 :     if (!child || nsLayoutUtils::IsPopup(child) ||
    1977               0 :         (child->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT))
    1978               0 :       return NS_OK;
    1979                 :     // Make sure that any attempt to use childType below is disappointed. We
    1980                 :     // could call GetType again but since we don't currently need it, let's
    1981                 :     // avoid the virtual call.
    1982               0 :     childType = nsnull;
    1983                 :     // Recheck NS_FRAME_TOO_DEEP_IN_FRAME_TREE
    1984               0 :     if (child->GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE)
    1985               0 :       return NS_OK;
    1986                 :     nsRect* savedDirty = static_cast<nsRect*>
    1987               0 :       (child->Properties().Get(nsDisplayListBuilder::OutOfFlowDirtyRectProperty()));
    1988               0 :     if (savedDirty) {
    1989               0 :       dirty = *savedDirty;
    1990                 :     } else {
    1991                 :       // The out-of-flow frame did not intersect the dirty area. We may still
    1992                 :       // need to traverse into it, since it may contain placeholders we need
    1993                 :       // to enter to reach other out-of-flow frames that are visible.
    1994               0 :       dirty.SetEmpty();
    1995                 :     }
    1996               0 :     pseudoStackingContext = true;
    1997                 :   }
    1998                 : 
    1999                 :   // Mark the display list items for absolutely positioned children
    2000               0 :   child->MarkAbsoluteFramesForDisplayList(aBuilder, dirty);
    2001                 : 
    2002               0 :   if (childType != nsGkAtoms::placeholderFrame &&
    2003               0 :       aBuilder->GetSelectedFramesOnly() &&
    2004               0 :       child->IsLeaf() &&
    2005               0 :       !aChild->IsSelected()) {
    2006               0 :     return NS_OK;
    2007                 :   }
    2008                 : 
    2009               0 :   if (aBuilder->GetIncludeAllOutOfFlows() &&
    2010               0 :       (child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
    2011               0 :     dirty = child->GetVisualOverflowRect();
    2012               0 :   } else if (!(child->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) {
    2013                 :     // No need to descend into child to catch placeholders for visible
    2014                 :     // positioned stuff. So see if we can short-circuit frame traversal here.
    2015                 : 
    2016                 :     // We can stop if child's frame subtree's intersection with the
    2017                 :     // dirty area is empty.
    2018                 :     // If the child is a scrollframe that we want to ignore, then we need
    2019                 :     // to descend into it because its scrolled child may intersect the dirty
    2020                 :     // area even if the scrollframe itself doesn't.
    2021               0 :     if (child != aBuilder->GetIgnoreScrollFrame()) {
    2022               0 :       nsRect childDirty;
    2023               0 :       if (!childDirty.IntersectRect(dirty, child->GetVisualOverflowRect()))
    2024               0 :         return NS_OK;
    2025                 :       // Usually we could set dirty to childDirty now but there's no
    2026                 :       // benefit, and it can be confusing. It can especially confuse
    2027                 :       // situations where we're going to ignore a scrollframe's clipping;
    2028                 :       // we wouldn't want to clip the dirty area to the scrollframe's
    2029                 :       // bounds in that case.
    2030                 :     }
    2031                 :   }
    2032                 : 
    2033                 :   // XXX need to have inline-block and inline-table set pseudoStackingContext
    2034                 :   
    2035               0 :   const nsStyleDisplay* ourDisp = GetStyleDisplay();
    2036                 :   // REVIEW: Taken from nsBoxFrame::Paint
    2037                 :   // Don't paint our children if the theme object is a leaf.
    2038               0 :   if (IsThemed(ourDisp) &&
    2039               0 :       !PresContext()->GetTheme()->WidgetIsContainer(ourDisp->mAppearance))
    2040               0 :     return NS_OK;
    2041                 : 
    2042                 :   // Child is composited if it's transformed, partially transparent, or has
    2043                 :   // SVG effects.
    2044               0 :   const nsStyleDisplay* disp = child->GetStyleDisplay();
    2045                 :   bool isVisuallyAtomic = disp->mOpacity != 1.0f
    2046               0 :     || child->IsTransformed()
    2047               0 :     || nsSVGIntegrationUtils::UsingEffectsForFrame(child);
    2048                 : 
    2049               0 :   bool isPositioned = disp->IsPositioned();
    2050               0 :   if (isVisuallyAtomic || isPositioned || disp->IsFloating() ||
    2051                 :       (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
    2052                 :     // If you change this, also change IsPseudoStackingContextFromStyle()
    2053               0 :     pseudoStackingContext = true;
    2054                 :   }
    2055                 :   
    2056               0 :   nsRect overflowClip;
    2057                 :   nscoord overflowClipRadii[8];
    2058                 :   bool applyOverflowClip =
    2059               0 :     ApplyOverflowClipping(aBuilder, child, disp, &overflowClip);
    2060               0 :   if (applyOverflowClip) {
    2061               0 :     child->GetPaddingBoxBorderRadii(overflowClipRadii);
    2062                 :   }
    2063                 :   // Don't use overflowClip to restrict the dirty rect, since some of the
    2064                 :   // descendants may not be clipped by it. Even if we end up with unnecessary
    2065                 :   // display items, they'll be pruned during ComputeVisibility. Note that
    2066                 :   // this overflow-clipping here only applies to overflow:-moz-hidden-unscrollable;
    2067                 :   // overflow:hidden etc creates an nsHTML/XULScrollFrame which does its own
    2068                 :   // clipping.
    2069                 : 
    2070               0 :   nsDisplayListBuilder::AutoIsRootSetter rootSetter(aBuilder, pseudoStackingContext);
    2071                 :   nsresult rv;
    2072               0 :   if (!pseudoStackingContext) {
    2073                 :     // THIS IS THE COMMON CASE.
    2074                 :     // Not a pseudo or real stacking context. Do the simple thing and
    2075                 :     // return early.
    2076               0 :     if (applyOverflowClip) {
    2077                 :       rv = BuildDisplayListWithOverflowClip(aBuilder, child, dirty, aLists,
    2078               0 :                                             overflowClip, overflowClipRadii);
    2079                 :     } else {
    2080               0 :       rv = child->BuildDisplayList(aBuilder, dirty, aLists);
    2081               0 :       if (NS_SUCCEEDED(rv)) {
    2082               0 :         rv = aBuilder->DisplayCaret(child, dirty, aLists.Content());
    2083                 :       }
    2084                 :     }
    2085                 : #ifdef NS_DEBUG
    2086               0 :     DisplayDebugBorders(aBuilder, child, aLists);
    2087                 : #endif
    2088               0 :     return rv;
    2089                 :   }
    2090                 :   
    2091               0 :   nsDisplayList list;
    2092               0 :   nsDisplayList extraPositionedDescendants;
    2093               0 :   const nsStylePosition* pos = child->GetStylePosition();
    2094               0 :   if ((isPositioned && pos->mZIndex.GetUnit() == eStyleUnit_Integer) ||
    2095                 :       isVisuallyAtomic || (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
    2096                 :     // True stacking context
    2097               0 :     rv = child->BuildDisplayListForStackingContext(aBuilder, dirty, &list);
    2098               0 :     if (NS_SUCCEEDED(rv)) {
    2099               0 :       rv = aBuilder->DisplayCaret(child, dirty, &list);
    2100                 :     }
    2101                 :   } else {
    2102               0 :     nsRect clipRect;
    2103                 :     bool applyClipPropClipping =
    2104               0 :         ApplyClipPropClipping(aBuilder, disp, child, &clipRect);
    2105                 :     // A pseudo-stacking context (e.g., a positioned element with z-index auto).
    2106                 :     // We allow positioned descendants of the child to escape to our parent
    2107                 :     // stacking context's positioned descendant list, because they might be
    2108                 :     // z-index:non-auto
    2109               0 :     nsDisplayListCollection pseudoStack;
    2110               0 :     nsRect clippedDirtyRect = dirty;
    2111               0 :     if (applyClipPropClipping) {
    2112                 :       // clipRect is in builder-reference-frame coordinates,
    2113                 :       // dirty/clippedDirtyRect are in child coordinates
    2114                 :       clippedDirtyRect.IntersectRect(clippedDirtyRect,
    2115               0 :                                      clipRect - aBuilder->ToReferenceFrame(child));
    2116                 :     }
    2117                 :     
    2118               0 :     if (applyOverflowClip) {
    2119                 :       rv = BuildDisplayListWithOverflowClip(aBuilder, child, clippedDirtyRect,
    2120                 :                                             pseudoStack, overflowClip,
    2121               0 :                                             overflowClipRadii);
    2122                 :     } else {
    2123               0 :       rv = child->BuildDisplayList(aBuilder, clippedDirtyRect, pseudoStack);
    2124               0 :       if (NS_SUCCEEDED(rv)) {
    2125               0 :         rv = aBuilder->DisplayCaret(child, dirty, pseudoStack.Content());
    2126                 :       }
    2127                 :     }
    2128                 :     
    2129               0 :     if (NS_SUCCEEDED(rv)) {
    2130               0 :       if (applyClipPropClipping) {
    2131               0 :         nsDisplayClipPropWrapper wrapper(clipRect);
    2132               0 :         rv = wrapper.WrapListsInPlace(aBuilder, child, pseudoStack);
    2133                 :       }
    2134                 :     }
    2135               0 :     list.AppendToTop(pseudoStack.BorderBackground());
    2136               0 :     list.AppendToTop(pseudoStack.BlockBorderBackgrounds());
    2137               0 :     list.AppendToTop(pseudoStack.Floats());
    2138               0 :     list.AppendToTop(pseudoStack.Content());
    2139               0 :     list.AppendToTop(pseudoStack.Outlines());
    2140               0 :     extraPositionedDescendants.AppendToTop(pseudoStack.PositionedDescendants());
    2141                 : #ifdef NS_DEBUG
    2142               0 :     DisplayDebugBorders(aBuilder, child, aLists);
    2143                 : #endif
    2144                 :   }
    2145               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2146                 :     
    2147               0 :   if (isPositioned || isVisuallyAtomic ||
    2148                 :       (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
    2149                 :     // Genuine stacking contexts, and positioned pseudo-stacking-contexts,
    2150                 :     // go in this level.
    2151                 :     rv = aLists.PositionedDescendants()->AppendNewToTop(new (aBuilder)
    2152               0 :         nsDisplayWrapList(aBuilder, child, &list));
    2153               0 :     NS_ENSURE_SUCCESS(rv, rv);
    2154               0 :   } else if (disp->IsFloating()) {
    2155                 :     rv = aLists.Floats()->AppendNewToTop(new (aBuilder)
    2156               0 :         nsDisplayWrapList(aBuilder, child, &list));
    2157               0 :     NS_ENSURE_SUCCESS(rv, rv);
    2158                 :   } else {
    2159               0 :     aLists.Content()->AppendToTop(&list);
    2160                 :   }
    2161                 :   // We delay placing the positioned descendants of positioned frames to here,
    2162                 :   // because in the absence of z-index this is the correct order for them.
    2163                 :   // This doesn't affect correctness because the positioned descendants list
    2164                 :   // is sorted by z-order and content in BuildDisplayListForStackingContext,
    2165                 :   // but it means that sort routine needs to do less work.
    2166               0 :   aLists.PositionedDescendants()->AppendToTop(&extraPositionedDescendants);
    2167               0 :   return NS_OK;
    2168                 : }
    2169                 : 
    2170                 : void
    2171               0 : nsIFrame::MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder,
    2172                 :                                            const nsRect& aDirtyRect)
    2173                 : {
    2174               0 :   if (IsAbsoluteContainer()) {
    2175               0 :     aBuilder->MarkFramesForDisplayList(this, GetAbsoluteContainingBlock()->GetChildList(), aDirtyRect);
    2176                 :   }
    2177               0 : }
    2178                 : 
    2179                 : void
    2180               0 : nsIFrame::WrapReplacedContentForBorderRadius(nsDisplayListBuilder* aBuilder,
    2181                 :                                              nsDisplayList* aFromList,
    2182                 :                                              const nsDisplayListSet& aToLists)
    2183                 : {
    2184                 :   nscoord radii[8];
    2185               0 :   if (GetContentBoxBorderRadii(radii)) {
    2186                 :     // If we have a border-radius, we have to clip our content to that
    2187                 :     // radius.
    2188               0 :     nsDisplayListCollection set;
    2189               0 :     set.Content()->AppendToTop(aFromList);
    2190               0 :     nsRect clipRect = GetContentRect() - GetPosition() +
    2191               0 :                       aBuilder->ToReferenceFrame(this);
    2192               0 :     OverflowClip(aBuilder, set, aToLists, clipRect, radii, false, true);
    2193                 : 
    2194                 :     return;
    2195                 :   }
    2196                 : 
    2197               0 :   aToLists.Content()->AppendToTop(aFromList);
    2198                 : }
    2199                 : 
    2200                 : NS_IMETHODIMP  
    2201               0 : nsFrame::GetContentForEvent(nsEvent* aEvent,
    2202                 :                             nsIContent** aContent)
    2203                 : {
    2204               0 :   nsIFrame* f = nsLayoutUtils::GetNonGeneratedAncestor(this);
    2205               0 :   *aContent = f->GetContent();
    2206               0 :   NS_IF_ADDREF(*aContent);
    2207               0 :   return NS_OK;
    2208                 : }
    2209                 : 
    2210                 : void
    2211               0 : nsFrame::FireDOMEvent(const nsAString& aDOMEventName, nsIContent *aContent)
    2212                 : {
    2213               0 :   nsIContent* target = aContent ? aContent : mContent;
    2214                 : 
    2215               0 :   if (target) {
    2216                 :     nsRefPtr<nsAsyncDOMEvent> event =
    2217               0 :       new nsAsyncDOMEvent(target, aDOMEventName, true, false);
    2218               0 :     if (NS_FAILED(event->PostDOMEvent()))
    2219               0 :       NS_WARNING("Failed to dispatch nsAsyncDOMEvent");
    2220                 :   }
    2221               0 : }
    2222                 : 
    2223                 : NS_IMETHODIMP
    2224               0 : nsFrame::HandleEvent(nsPresContext* aPresContext, 
    2225                 :                      nsGUIEvent*     aEvent,
    2226                 :                      nsEventStatus*  aEventStatus)
    2227                 : {
    2228                 : 
    2229               0 :   if (aEvent->message == NS_MOUSE_MOVE) {
    2230               0 :     return HandleDrag(aPresContext, aEvent, aEventStatus);
    2231                 :   }
    2232                 : 
    2233               0 :   if (aEvent->eventStructType == NS_MOUSE_EVENT &&
    2234                 :       static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton) {
    2235               0 :     if (aEvent->message == NS_MOUSE_BUTTON_DOWN) {
    2236               0 :       HandlePress(aPresContext, aEvent, aEventStatus);
    2237               0 :     } else if (aEvent->message == NS_MOUSE_BUTTON_UP) {
    2238               0 :       HandleRelease(aPresContext, aEvent, aEventStatus);
    2239                 :     }
    2240                 :   }
    2241               0 :   return NS_OK;
    2242                 : }
    2243                 : 
    2244                 : NS_IMETHODIMP
    2245               0 : nsFrame::GetDataForTableSelection(const nsFrameSelection *aFrameSelection,
    2246                 :                                   nsIPresShell *aPresShell, nsMouseEvent *aMouseEvent, 
    2247                 :                                   nsIContent **aParentContent, PRInt32 *aContentOffset, PRInt32 *aTarget)
    2248                 : {
    2249               0 :   if (!aFrameSelection || !aPresShell || !aMouseEvent || !aParentContent || !aContentOffset || !aTarget)
    2250               0 :     return NS_ERROR_NULL_POINTER;
    2251                 : 
    2252               0 :   *aParentContent = nsnull;
    2253               0 :   *aContentOffset = 0;
    2254               0 :   *aTarget = 0;
    2255                 : 
    2256               0 :   PRInt16 displaySelection = aPresShell->GetSelectionFlags();
    2257                 : 
    2258               0 :   bool selectingTableCells = aFrameSelection->GetTableCellSelection();
    2259                 : 
    2260                 :   // DISPLAY_ALL means we're in an editor.
    2261                 :   // If already in cell selection mode, 
    2262                 :   //  continue selecting with mouse drag or end on mouse up,
    2263                 :   //  or when using shift key to extend block of cells
    2264                 :   //  (Mouse down does normal selection unless Ctrl/Cmd is pressed)
    2265                 :   bool doTableSelection =
    2266                 :      displaySelection == nsISelectionDisplay::DISPLAY_ALL && selectingTableCells &&
    2267                 :      (aMouseEvent->message == NS_MOUSE_MOVE ||
    2268                 :       (aMouseEvent->message == NS_MOUSE_BUTTON_UP &&
    2269                 :        aMouseEvent->button == nsMouseEvent::eLeftButton) ||
    2270               0 :       aMouseEvent->isShift);
    2271                 : 
    2272               0 :   if (!doTableSelection)
    2273                 :   {  
    2274                 :     // In Browser, special 'table selection' key must be pressed for table selection
    2275                 :     // or when just Shift is pressed and we're already in table/cell selection mode
    2276                 : #ifdef XP_MACOSX
    2277                 :     doTableSelection = aMouseEvent->isMeta || (aMouseEvent->isShift && selectingTableCells);
    2278                 : #else
    2279               0 :     doTableSelection = aMouseEvent->isControl || (aMouseEvent->isShift && selectingTableCells);
    2280                 : #endif
    2281                 :   }
    2282               0 :   if (!doTableSelection) 
    2283               0 :     return NS_OK;
    2284                 : 
    2285                 :   // Get the cell frame or table frame (or parent) of the current content node
    2286               0 :   nsIFrame *frame = this;
    2287               0 :   bool foundCell = false;
    2288               0 :   bool foundTable = false;
    2289                 : 
    2290                 :   // Get the limiting node to stop parent frame search
    2291               0 :   nsIContent* limiter = aFrameSelection->GetLimiter();
    2292                 : 
    2293                 :   // If our content node is an ancestor of the limiting node,
    2294                 :   // we should stop the search right now.
    2295               0 :   if (limiter && nsContentUtils::ContentIsDescendantOf(limiter, GetContent()))
    2296               0 :     return NS_OK;
    2297                 : 
    2298                 :   //We don't initiate row/col selection from here now,
    2299                 :   //  but we may in future
    2300                 :   //bool selectColumn = false;
    2301                 :   //bool selectRow = false;
    2302                 :   
    2303               0 :   while (frame)
    2304                 :   {
    2305                 :     // Check for a table cell by querying to a known CellFrame interface
    2306               0 :     nsITableCellLayout *cellElement = do_QueryFrame(frame);
    2307               0 :     if (cellElement)
    2308                 :     {
    2309               0 :       foundCell = true;
    2310                 :       //TODO: If we want to use proximity to top or left border
    2311                 :       //      for row and column selection, this is the place to do it
    2312               0 :       break;
    2313                 :     }
    2314                 :     else
    2315                 :     {
    2316                 :       // If not a cell, check for table
    2317                 :       // This will happen when starting frame is the table or child of a table,
    2318                 :       //  such as a row (we were inbetween cells or in table border)
    2319               0 :       nsITableLayout *tableElement = do_QueryFrame(frame);
    2320               0 :       if (tableElement)
    2321                 :       {
    2322               0 :         foundTable = true;
    2323                 :         //TODO: How can we select row when along left table edge
    2324                 :         //  or select column when along top edge?
    2325               0 :         break;
    2326                 :       } else {
    2327               0 :         frame = frame->GetParent();
    2328                 :         // Stop if we have hit the selection's limiting content node
    2329               0 :         if (frame && frame->GetContent() == limiter)
    2330               0 :           break;
    2331                 :       }
    2332                 :     }
    2333                 :   }
    2334                 :   // We aren't in a cell or table
    2335               0 :   if (!foundCell && !foundTable) return NS_OK;
    2336                 : 
    2337               0 :   nsIContent* tableOrCellContent = frame->GetContent();
    2338               0 :   if (!tableOrCellContent) return NS_ERROR_FAILURE;
    2339                 : 
    2340               0 :   nsCOMPtr<nsIContent> parentContent = tableOrCellContent->GetParent();
    2341               0 :   if (!parentContent) return NS_ERROR_FAILURE;
    2342                 : 
    2343               0 :   PRInt32 offset = parentContent->IndexOf(tableOrCellContent);
    2344                 :   // Not likely?
    2345               0 :   if (offset < 0) return NS_ERROR_FAILURE;
    2346                 : 
    2347                 :   // Everything is OK -- set the return values
    2348               0 :   *aParentContent = parentContent;
    2349               0 :   NS_ADDREF(*aParentContent);
    2350                 : 
    2351               0 :   *aContentOffset = offset;
    2352                 : 
    2353                 : #if 0
    2354                 :   if (selectRow)
    2355                 :     *aTarget = nsISelectionPrivate::TABLESELECTION_ROW;
    2356                 :   else if (selectColumn)
    2357                 :     *aTarget = nsISelectionPrivate::TABLESELECTION_COLUMN;
    2358                 :   else 
    2359                 : #endif
    2360               0 :   if (foundCell)
    2361               0 :     *aTarget = nsISelectionPrivate::TABLESELECTION_CELL;
    2362               0 :   else if (foundTable)
    2363               0 :     *aTarget = nsISelectionPrivate::TABLESELECTION_TABLE;
    2364                 : 
    2365               0 :   return NS_OK;
    2366                 : }
    2367                 : 
    2368                 : NS_IMETHODIMP
    2369               0 : nsFrame::IsSelectable(bool* aSelectable, PRUint8* aSelectStyle) const
    2370                 : {
    2371               0 :   if (!aSelectable) //it's ok if aSelectStyle is null
    2372               0 :     return NS_ERROR_NULL_POINTER;
    2373                 : 
    2374                 :   // Like 'visibility', we must check all the parents: if a parent
    2375                 :   // is not selectable, none of its children is selectable.
    2376                 :   //
    2377                 :   // The -moz-all value acts similarly: if a frame has 'user-select:-moz-all',
    2378                 :   // all its children are selectable, even those with 'user-select:none'.
    2379                 :   //
    2380                 :   // As a result, if 'none' and '-moz-all' are not present in the frame hierarchy,
    2381                 :   // aSelectStyle returns the first style that is not AUTO. If these values
    2382                 :   // are present in the frame hierarchy, aSelectStyle returns the style of the
    2383                 :   // topmost parent that has either 'none' or '-moz-all'.
    2384                 :   //
    2385                 :   // For instance, if the frame hierarchy is:
    2386                 :   //    AUTO     -> _MOZ_ALL -> NONE -> TEXT,     the returned value is _MOZ_ALL
    2387                 :   //    TEXT     -> NONE     -> AUTO -> _MOZ_ALL, the returned value is NONE
    2388                 :   //    _MOZ_ALL -> TEXT     -> AUTO -> AUTO,     the returned value is _MOZ_ALL
    2389                 :   //    AUTO     -> CELL     -> TEXT -> AUTO,     the returned value is TEXT
    2390                 :   //
    2391               0 :   PRUint8 selectStyle  = NS_STYLE_USER_SELECT_AUTO;
    2392               0 :   nsIFrame* frame      = (nsIFrame*)this;
    2393                 : 
    2394               0 :   while (frame) {
    2395               0 :     const nsStyleUIReset* userinterface = frame->GetStyleUIReset();
    2396               0 :     switch (userinterface->mUserSelect) {
    2397                 :       case NS_STYLE_USER_SELECT_ALL:
    2398                 :       case NS_STYLE_USER_SELECT_NONE:
    2399                 :       case NS_STYLE_USER_SELECT_MOZ_ALL:
    2400                 :         // override the previous values
    2401               0 :         selectStyle = userinterface->mUserSelect;
    2402               0 :         break;
    2403                 :       default:
    2404                 :         // otherwise return the first value which is not 'auto'
    2405               0 :         if (selectStyle == NS_STYLE_USER_SELECT_AUTO) {
    2406               0 :           selectStyle = userinterface->mUserSelect;
    2407                 :         }
    2408               0 :         break;
    2409                 :     }
    2410               0 :     frame = frame->GetParent();
    2411                 :   }
    2412                 : 
    2413                 :   // convert internal values to standard values
    2414               0 :   if (selectStyle == NS_STYLE_USER_SELECT_AUTO)
    2415               0 :     selectStyle = NS_STYLE_USER_SELECT_TEXT;
    2416                 :   else
    2417               0 :   if (selectStyle == NS_STYLE_USER_SELECT_MOZ_ALL)
    2418               0 :     selectStyle = NS_STYLE_USER_SELECT_ALL;
    2419                 :   else
    2420               0 :   if (selectStyle == NS_STYLE_USER_SELECT_MOZ_NONE)
    2421               0 :     selectStyle = NS_STYLE_USER_SELECT_NONE;
    2422                 : 
    2423                 :   // return stuff
    2424               0 :   if (aSelectStyle)
    2425               0 :     *aSelectStyle = selectStyle;
    2426               0 :   if (mState & NS_FRAME_GENERATED_CONTENT)
    2427               0 :     *aSelectable = false;
    2428                 :   else
    2429               0 :     *aSelectable = (selectStyle != NS_STYLE_USER_SELECT_NONE);
    2430               0 :   return NS_OK;
    2431                 : }
    2432                 : 
    2433                 : /**
    2434                 :   * Handles the Mouse Press Event for the frame
    2435                 :  */
    2436                 : NS_IMETHODIMP
    2437               0 : nsFrame::HandlePress(nsPresContext* aPresContext, 
    2438                 :                      nsGUIEvent*     aEvent,
    2439                 :                      nsEventStatus*  aEventStatus)
    2440                 : {
    2441               0 :   NS_ENSURE_ARG_POINTER(aEventStatus);
    2442               0 :   if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
    2443               0 :     return NS_OK;
    2444                 :   }
    2445                 : 
    2446                 :   //We often get out of sync state issues with mousedown events that
    2447                 :   //get interrupted by alerts/dialogs.
    2448                 :   //Check with the ESM to see if we should process this one
    2449               0 :   if (!aPresContext->EventStateManager()->EventStatusOK(aEvent)) 
    2450               0 :     return NS_OK;
    2451                 : 
    2452                 :   nsresult rv;
    2453               0 :   nsIPresShell *shell = aPresContext->GetPresShell();
    2454               0 :   if (!shell)
    2455               0 :     return NS_ERROR_FAILURE;
    2456                 : 
    2457                 :   // if we are in Navigator and the click is in a draggable node, we don't want
    2458                 :   // to start selection because we don't want to interfere with a potential
    2459                 :   // drag of said node and steal all its glory.
    2460               0 :   PRInt16 isEditor = shell->GetSelectionFlags();
    2461                 :   //weaaak. only the editor can display frame selection not just text and images
    2462               0 :   isEditor = isEditor == nsISelectionDisplay::DISPLAY_ALL;
    2463                 : 
    2464               0 :   nsInputEvent* keyEvent = (nsInputEvent*)aEvent;
    2465               0 :   if (!keyEvent->isAlt) {
    2466                 :     
    2467               0 :     for (nsIContent* content = mContent; content;
    2468               0 :          content = content->GetParent()) {
    2469               0 :       if (nsContentUtils::ContentIsDraggable(content) &&
    2470               0 :           !content->IsEditable()) {
    2471                 :         // coordinate stuff is the fix for bug #55921
    2472               0 :         if ((mRect - GetPosition()).Contains(
    2473               0 :                nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this)))
    2474               0 :           return NS_OK;
    2475                 :       }
    2476                 :     }
    2477                 :   }
    2478                 : 
    2479                 :   // check whether style allows selection
    2480                 :   // if not, don't tell selection the mouse event even occurred.  
    2481                 :   bool    selectable;
    2482                 :   PRUint8 selectStyle;
    2483               0 :   rv = IsSelectable(&selectable, &selectStyle);
    2484               0 :   if (NS_FAILED(rv)) return rv;
    2485                 :   
    2486                 :   // check for select: none
    2487               0 :   if (!selectable)
    2488               0 :     return NS_OK;
    2489                 : 
    2490                 :   // When implementing NS_STYLE_USER_SELECT_ELEMENT, NS_STYLE_USER_SELECT_ELEMENTS and
    2491                 :   // NS_STYLE_USER_SELECT_TOGGLE, need to change this logic
    2492               0 :   bool useFrameSelection = (selectStyle == NS_STYLE_USER_SELECT_TEXT);
    2493                 : 
    2494                 :   // If the mouse is dragged outside the nearest enclosing scrollable area
    2495                 :   // while making a selection, the area will be scrolled. To do this, capture
    2496                 :   // the mouse on the nearest scrollable frame. If there isn't a scrollable
    2497                 :   // frame, or something else is already capturing the mouse, there's no
    2498                 :   // reason to capture.
    2499               0 :   if (!nsIPresShell::GetCapturingContent()) {
    2500               0 :     nsIFrame* checkFrame = this;
    2501               0 :     nsIScrollableFrame *scrollFrame = nsnull;
    2502               0 :     while (checkFrame) {
    2503               0 :       scrollFrame = do_QueryFrame(checkFrame);
    2504               0 :       if (scrollFrame) {
    2505               0 :         nsIPresShell::SetCapturingContent(checkFrame->GetContent(), CAPTURE_IGNOREALLOWED);
    2506               0 :         break;
    2507                 :       }
    2508               0 :       checkFrame = checkFrame->GetParent();
    2509                 :     }
    2510                 :   }
    2511                 : 
    2512                 :   // XXX This is screwy; it really should use the selection frame, not the
    2513                 :   // event frame
    2514               0 :   const nsFrameSelection* frameselection = nsnull;
    2515               0 :   if (useFrameSelection)
    2516               0 :     frameselection = GetConstFrameSelection();
    2517                 :   else
    2518               0 :     frameselection = shell->ConstFrameSelection();
    2519                 : 
    2520               0 :   if (!frameselection || frameselection->GetDisplaySelection() == nsISelectionController::SELECTION_OFF)
    2521               0 :     return NS_OK;//nothing to do we cannot affect selection from here
    2522                 : 
    2523               0 :   nsMouseEvent *me = (nsMouseEvent *)aEvent;
    2524                 : 
    2525                 : #ifdef XP_MACOSX
    2526                 :   if (me->isControl)
    2527                 :     return NS_OK;//short circuit. hard coded for mac due to time restraints.
    2528                 :   bool control = me->isMeta;
    2529                 : #else
    2530               0 :   bool control = me->isControl;
    2531                 : #endif
    2532                 : 
    2533               0 :   nsRefPtr<nsFrameSelection> fc = const_cast<nsFrameSelection*>(frameselection);
    2534               0 :   if (me->clickCount > 1)
    2535                 :   {
    2536                 :     // These methods aren't const but can't actually delete anything,
    2537                 :     // so no need for nsWeakFrame.
    2538               0 :     fc->SetMouseDownState(true);
    2539               0 :     fc->SetMouseDoubleDown(true);
    2540               0 :     return HandleMultiplePress(aPresContext, aEvent, aEventStatus, control);
    2541                 :   }
    2542                 : 
    2543               0 :   nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
    2544               0 :   ContentOffsets offsets = GetContentOffsetsFromPoint(pt);
    2545                 : 
    2546               0 :   if (!offsets.content)
    2547               0 :     return NS_ERROR_FAILURE;
    2548                 : 
    2549                 :   // On touchables devices, touch the screen is usually a pan action,
    2550                 :   // so let reposition the caret if needed but do not select text
    2551               0 :   if (Preferences::GetBool("browser.ignoreNativeFrameTextSelection", false)) {
    2552               0 :     return fc->HandleClick(offsets.content, offsets.StartOffset(),
    2553               0 :                            offsets.EndOffset(), false, false,
    2554               0 :                            offsets.associateWithNext);
    2555                 :   }
    2556                 : 
    2557                 :   // Let Ctrl/Cmd+mouse down do table selection instead of drag initiation
    2558               0 :   nsCOMPtr<nsIContent>parentContent;
    2559                 :   PRInt32  contentOffset;
    2560                 :   PRInt32 target;
    2561               0 :   rv = GetDataForTableSelection(frameselection, shell, me, getter_AddRefs(parentContent), &contentOffset, &target);
    2562               0 :   if (NS_SUCCEEDED(rv) && parentContent)
    2563                 :   {
    2564               0 :     fc->SetMouseDownState(true);
    2565               0 :     return fc->HandleTableSelection(parentContent, contentOffset, target, me);
    2566                 :   }
    2567                 : 
    2568               0 :   fc->SetDelayedCaretData(0);
    2569                 : 
    2570                 :   // Check if any part of this frame is selected, and if the
    2571                 :   // user clicked inside the selected region. If so, we delay
    2572                 :   // starting a new selection since the user may be trying to
    2573                 :   // drag the selected region to some other app.
    2574                 : 
    2575               0 :   SelectionDetails *details = 0;
    2576               0 :   if (GetContent()->IsSelectionDescendant())
    2577                 :   {
    2578               0 :     bool inSelection = false;
    2579                 :     details = frameselection->LookUpSelection(offsets.content, 0,
    2580               0 :         offsets.EndOffset(), false);
    2581                 : 
    2582                 :     //
    2583                 :     // If there are any details, check to see if the user clicked
    2584                 :     // within any selected region of the frame.
    2585                 :     //
    2586                 : 
    2587               0 :     SelectionDetails *curDetail = details;
    2588                 : 
    2589               0 :     while (curDetail)
    2590                 :     {
    2591                 :       //
    2592                 :       // If the user clicked inside a selection, then just
    2593                 :       // return without doing anything. We will handle placing
    2594                 :       // the caret later on when the mouse is released. We ignore
    2595                 :       // the spellcheck, find and url formatting selections.
    2596                 :       //
    2597               0 :       if (curDetail->mType != nsISelectionController::SELECTION_SPELLCHECK &&
    2598                 :           curDetail->mType != nsISelectionController::SELECTION_FIND &&
    2599                 :           curDetail->mType != nsISelectionController::SELECTION_URLSECONDARY &&
    2600               0 :           curDetail->mStart <= offsets.StartOffset() &&
    2601               0 :           offsets.EndOffset() <= curDetail->mEnd)
    2602                 :       {
    2603               0 :         inSelection = true;
    2604                 :       }
    2605                 : 
    2606               0 :       SelectionDetails *nextDetail = curDetail->mNext;
    2607               0 :       delete curDetail;
    2608               0 :       curDetail = nextDetail;
    2609                 :     }
    2610                 : 
    2611               0 :     if (inSelection) {
    2612               0 :       fc->SetMouseDownState(false);
    2613               0 :       fc->SetDelayedCaretData(me);
    2614               0 :       return NS_OK;
    2615                 :     }
    2616                 :   }
    2617                 : 
    2618               0 :   fc->SetMouseDownState(true);
    2619                 : 
    2620                 :   // Do not touch any nsFrame members after this point without adding
    2621                 :   // weakFrame checks.
    2622               0 :   rv = fc->HandleClick(offsets.content, offsets.StartOffset(),
    2623               0 :                        offsets.EndOffset(), me->isShift, control,
    2624               0 :                        offsets.associateWithNext);
    2625                 : 
    2626               0 :   if (NS_FAILED(rv))
    2627               0 :     return rv;
    2628                 : 
    2629               0 :   if (offsets.offset != offsets.secondaryOffset)
    2630               0 :     fc->MaintainSelection();
    2631                 : 
    2632               0 :   if (isEditor && !me->isShift &&
    2633               0 :       (offsets.EndOffset() - offsets.StartOffset()) == 1)
    2634                 :   {
    2635                 :     // A single node is selected and we aren't extending an existing
    2636                 :     // selection, which means the user clicked directly on an object (either
    2637                 :     // -moz-user-select: all or a non-text node without children).
    2638                 :     // Therefore, disable selection extension during mouse moves.
    2639                 :     // XXX This is a bit hacky; shouldn't editor be able to deal with this?
    2640               0 :     fc->SetMouseDownState(false);
    2641                 :   }
    2642                 : 
    2643               0 :   return rv;
    2644                 : }
    2645                 : 
    2646                 : /**
    2647                 :   * Multiple Mouse Press -- line or paragraph selection -- for the frame.
    2648                 :   * Wouldn't it be nice if this didn't have to be hardwired into Frame code?
    2649                 :  */
    2650                 : NS_IMETHODIMP
    2651               0 : nsFrame::HandleMultiplePress(nsPresContext* aPresContext, 
    2652                 :                              nsGUIEvent*    aEvent,
    2653                 :                              nsEventStatus* aEventStatus,
    2654                 :                              bool           aControlHeld)
    2655                 : {
    2656               0 :   NS_ENSURE_ARG_POINTER(aEventStatus);
    2657               0 :   if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
    2658               0 :     return NS_OK;
    2659                 :   }
    2660                 : 
    2661               0 :   if (DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF) {
    2662               0 :     return NS_OK;
    2663                 :   }
    2664                 : 
    2665                 :   // Find out whether we're doing line or paragraph selection.
    2666                 :   // If browser.triple_click_selects_paragraph is true, triple-click selects paragraph.
    2667                 :   // Otherwise, triple-click selects line, and quadruple-click selects paragraph
    2668                 :   // (on platforms that support quadruple-click).
    2669                 :   nsSelectionAmount beginAmount, endAmount;
    2670               0 :   nsMouseEvent *me = (nsMouseEvent *)aEvent;
    2671               0 :   if (!me) return NS_OK;
    2672                 : 
    2673               0 :   if (me->clickCount == 4) {
    2674               0 :     beginAmount = endAmount = eSelectParagraph;
    2675               0 :   } else if (me->clickCount == 3) {
    2676               0 :     if (Preferences::GetBool("browser.triple_click_selects_paragraph")) {
    2677               0 :       beginAmount = endAmount = eSelectParagraph;
    2678                 :     } else {
    2679               0 :       beginAmount = eSelectBeginLine;
    2680               0 :       endAmount = eSelectEndLine;
    2681                 :     }
    2682               0 :   } else if (me->clickCount == 2) {
    2683                 :     // We only want inline frames; PeekBackwardAndForward dislikes blocks
    2684               0 :     beginAmount = endAmount = eSelectWord;
    2685                 :   } else {
    2686               0 :     return NS_OK;
    2687                 :   }
    2688                 : 
    2689               0 :   nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
    2690               0 :   ContentOffsets offsets = GetContentOffsetsFromPoint(pt);
    2691               0 :   if (!offsets.content) return NS_ERROR_FAILURE;
    2692                 : 
    2693                 :   nsIFrame* theFrame;
    2694                 :   PRInt32 offset;
    2695                 :   // Maybe make this a static helper?
    2696                 :   const nsFrameSelection* frameSelection =
    2697               0 :     PresContext()->GetPresShell()->ConstFrameSelection();
    2698                 :   theFrame = frameSelection->
    2699                 :     GetFrameForNodeOffset(offsets.content, offsets.offset,
    2700                 :                           nsFrameSelection::HINT(offsets.associateWithNext),
    2701               0 :                           &offset);
    2702               0 :   if (!theFrame)
    2703               0 :     return NS_ERROR_FAILURE;
    2704                 : 
    2705               0 :   nsFrame* frame = static_cast<nsFrame*>(theFrame);
    2706                 : 
    2707                 :   return frame->PeekBackwardAndForward(beginAmount, endAmount,
    2708                 :                                        offsets.offset, aPresContext,
    2709                 :                                        beginAmount != eSelectWord,
    2710               0 :                                        aControlHeld);
    2711                 : }
    2712                 : 
    2713                 : NS_IMETHODIMP
    2714               0 : nsFrame::PeekBackwardAndForward(nsSelectionAmount aAmountBack,
    2715                 :                                 nsSelectionAmount aAmountForward,
    2716                 :                                 PRInt32 aStartPos,
    2717                 :                                 nsPresContext* aPresContext,
    2718                 :                                 bool aJumpLines,
    2719                 :                                 bool aMultipleSelection)
    2720                 : {
    2721               0 :   nsIFrame* baseFrame = this;
    2722               0 :   PRInt32 baseOffset = aStartPos;
    2723                 :   nsresult rv;
    2724                 : 
    2725               0 :   if (aAmountBack == eSelectWord) {
    2726                 :     // To avoid selecting the previous word when at start of word,
    2727                 :     // first move one character forward.
    2728               0 :     nsPeekOffsetStruct pos;
    2729                 :     pos.SetData(eSelectCharacter,
    2730                 :                 eDirNext,
    2731                 :                 aStartPos,
    2732                 :                 0,
    2733                 :                 aJumpLines,
    2734                 :                 true,  //limit on scrolled views
    2735                 :                 false,
    2736               0 :                 false);
    2737               0 :     rv = PeekOffset(&pos);
    2738               0 :     if (NS_SUCCEEDED(rv)) {
    2739               0 :       baseFrame = pos.mResultFrame;
    2740               0 :       baseOffset = pos.mContentOffset;
    2741                 :     }
    2742                 :   }
    2743                 : 
    2744                 :   // Use peek offset one way then the other:  
    2745               0 :   nsPeekOffsetStruct startpos;
    2746                 :   startpos.SetData(aAmountBack,
    2747                 :                    eDirPrevious,
    2748                 :                    baseOffset, 
    2749                 :                    0,
    2750                 :                    aJumpLines,
    2751                 :                    true,  //limit on scrolled views
    2752                 :                    false,
    2753               0 :                    false);
    2754               0 :   rv = baseFrame->PeekOffset(&startpos);
    2755               0 :   if (NS_FAILED(rv))
    2756               0 :     return rv;
    2757                 : 
    2758               0 :   nsPeekOffsetStruct endpos;
    2759                 :   endpos.SetData(aAmountForward,
    2760                 :                  eDirNext,
    2761                 :                  aStartPos, 
    2762                 :                  0,
    2763                 :                  aJumpLines,
    2764                 :                  true,  //limit on scrolled views
    2765                 :                  false,
    2766               0 :                  false);
    2767               0 :   rv = PeekOffset(&endpos);
    2768               0 :   if (NS_FAILED(rv))
    2769               0 :     return rv;
    2770                 : 
    2771                 :   // Keep frameSelection alive.
    2772               0 :   nsRefPtr<nsFrameSelection> frameSelection = GetFrameSelection();
    2773                 : 
    2774                 :   rv = frameSelection->HandleClick(startpos.mResultContent,
    2775                 :                                    startpos.mContentOffset, startpos.mContentOffset,
    2776                 :                                    false, aMultipleSelection,
    2777               0 :                                    nsFrameSelection::HINTRIGHT);
    2778               0 :   if (NS_FAILED(rv))
    2779               0 :     return rv;
    2780                 : 
    2781                 :   rv = frameSelection->HandleClick(endpos.mResultContent,
    2782                 :                                    endpos.mContentOffset, endpos.mContentOffset,
    2783                 :                                    true, false,
    2784               0 :                                    nsFrameSelection::HINTLEFT);
    2785               0 :   if (NS_FAILED(rv))
    2786               0 :     return rv;
    2787                 : 
    2788                 :   // maintain selection
    2789               0 :   return frameSelection->MaintainSelection(aAmountBack);
    2790                 : }
    2791                 : 
    2792               0 : NS_IMETHODIMP nsFrame::HandleDrag(nsPresContext* aPresContext, 
    2793                 :                                   nsGUIEvent*     aEvent,
    2794                 :                                   nsEventStatus*  aEventStatus)
    2795                 : {
    2796                 :   bool    selectable;
    2797                 :   PRUint8 selectStyle;
    2798               0 :   IsSelectable(&selectable, &selectStyle);
    2799                 :   // XXX Do we really need to exclude non-selectable content here?
    2800                 :   // GetContentOffsetsFromPoint can handle it just fine, although some
    2801                 :   // other stuff might not like it.
    2802               0 :   if (!selectable)
    2803               0 :     return NS_OK;
    2804               0 :   if (DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF) {
    2805               0 :     return NS_OK;
    2806                 :   }
    2807               0 :   nsIPresShell *presShell = aPresContext->PresShell();
    2808                 : 
    2809               0 :   nsRefPtr<nsFrameSelection> frameselection = GetFrameSelection();
    2810               0 :   bool mouseDown = frameselection->GetMouseDownState();
    2811               0 :   if (!mouseDown)
    2812               0 :     return NS_OK;
    2813                 : 
    2814               0 :   frameselection->StopAutoScrollTimer();
    2815                 : 
    2816                 :   // Check if we are dragging in a table cell
    2817               0 :   nsCOMPtr<nsIContent> parentContent;
    2818                 :   PRInt32 contentOffset;
    2819                 :   PRInt32 target;
    2820               0 :   nsMouseEvent *me = (nsMouseEvent *)aEvent;
    2821                 :   nsresult result;
    2822                 :   result = GetDataForTableSelection(frameselection, presShell, me,
    2823               0 :                                     getter_AddRefs(parentContent),
    2824               0 :                                     &contentOffset, &target);      
    2825                 : 
    2826               0 :   nsWeakFrame weakThis = this;
    2827               0 :   if (NS_SUCCEEDED(result) && parentContent) {
    2828               0 :     frameselection->HandleTableSelection(parentContent, contentOffset, target, me);
    2829                 :   } else {
    2830               0 :     nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
    2831               0 :     frameselection->HandleDrag(this, pt);
    2832                 :   }
    2833                 : 
    2834                 :   // The frameselection object notifies selection listeners synchronously above
    2835                 :   // which might have killed us.
    2836               0 :   if (!weakThis.IsAlive()) {
    2837               0 :     return NS_OK;
    2838                 :   }
    2839                 : 
    2840                 :   // get the nearest scrollframe
    2841               0 :   nsIFrame* checkFrame = this;
    2842               0 :   nsIScrollableFrame *scrollFrame = nsnull;
    2843               0 :   while (checkFrame) {
    2844               0 :     scrollFrame = do_QueryFrame(checkFrame);
    2845               0 :     if (scrollFrame) {
    2846               0 :       break;
    2847                 :     }
    2848               0 :     checkFrame = checkFrame->GetParent();
    2849                 :   }
    2850                 : 
    2851               0 :   if (scrollFrame) {
    2852               0 :     nsIFrame* capturingFrame = scrollFrame->GetScrolledFrame();
    2853               0 :     if (capturingFrame) {
    2854                 :       nsPoint pt =
    2855               0 :         nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, capturingFrame);
    2856               0 :       frameselection->StartAutoScrollTimer(capturingFrame, pt, 30);
    2857                 :     }
    2858                 :   }
    2859                 : 
    2860               0 :   return NS_OK;
    2861                 : }
    2862                 : 
    2863                 : /**
    2864                 :  * This static method handles part of the nsFrame::HandleRelease in a way
    2865                 :  * which doesn't rely on the nsFrame object to stay alive.
    2866                 :  */
    2867                 : static nsresult
    2868               0 : HandleFrameSelection(nsFrameSelection*         aFrameSelection,
    2869                 :                      nsIFrame::ContentOffsets& aOffsets,
    2870                 :                      bool                      aHandleTableSel,
    2871                 :                      PRInt32                   aContentOffsetForTableSel,
    2872                 :                      PRInt32                   aTargetForTableSel,
    2873                 :                      nsIContent*               aParentContentForTableSel,
    2874                 :                      nsGUIEvent*               aEvent,
    2875                 :                      nsEventStatus*            aEventStatus)
    2876                 : {
    2877               0 :   if (!aFrameSelection) {
    2878               0 :     return NS_OK;
    2879                 :   }
    2880                 : 
    2881               0 :   nsresult rv = NS_OK;
    2882                 : 
    2883               0 :   if (nsEventStatus_eConsumeNoDefault != *aEventStatus) {
    2884               0 :     if (!aHandleTableSel) {
    2885               0 :       nsMouseEvent *me = aFrameSelection->GetDelayedCaretData();
    2886               0 :       if (!aOffsets.content || !me) {
    2887               0 :         return NS_ERROR_FAILURE;
    2888                 :       }
    2889                 : 
    2890                 :       // We are doing this to simulate what we would have done on HandlePress.
    2891                 :       // We didn't do it there to give the user an opportunity to drag
    2892                 :       // the text, but since they didn't drag, we want to place the
    2893                 :       // caret.
    2894                 :       // However, we'll use the mouse position from the release, since:
    2895                 :       //  * it's easier
    2896                 :       //  * that's the normal click position to use (although really, in
    2897                 :       //    the normal case, small movements that don't count as a drag
    2898                 :       //    can do selection)
    2899               0 :       aFrameSelection->SetMouseDownState(true);
    2900                 : 
    2901                 :       rv = aFrameSelection->HandleClick(aOffsets.content,
    2902               0 :                                         aOffsets.StartOffset(),
    2903               0 :                                         aOffsets.EndOffset(),
    2904                 :                                         me->isShift, false,
    2905               0 :                                         aOffsets.associateWithNext);
    2906               0 :       if (NS_FAILED(rv)) {
    2907               0 :         return rv;
    2908                 :       }
    2909               0 :     } else if (aParentContentForTableSel) {
    2910               0 :       aFrameSelection->SetMouseDownState(false);
    2911                 :       rv = aFrameSelection->HandleTableSelection(aParentContentForTableSel,
    2912                 :                                                  aContentOffsetForTableSel,
    2913                 :                                                  aTargetForTableSel,
    2914               0 :                                                  (nsMouseEvent *)aEvent);
    2915               0 :       if (NS_FAILED(rv)) {
    2916               0 :         return rv;
    2917                 :       }
    2918                 :     }
    2919               0 :     aFrameSelection->SetDelayedCaretData(0);
    2920                 :   }
    2921                 : 
    2922               0 :   aFrameSelection->SetMouseDownState(false);
    2923               0 :   aFrameSelection->StopAutoScrollTimer();
    2924                 : 
    2925               0 :   return NS_OK;
    2926                 : }
    2927                 : 
    2928               0 : NS_IMETHODIMP nsFrame::HandleRelease(nsPresContext* aPresContext,
    2929                 :                                      nsGUIEvent*    aEvent,
    2930                 :                                      nsEventStatus* aEventStatus)
    2931                 : {
    2932               0 :   nsIFrame* activeFrame = GetActiveSelectionFrame(aPresContext, this);
    2933                 : 
    2934               0 :   nsCOMPtr<nsIContent> captureContent = nsIPresShell::GetCapturingContent();
    2935                 : 
    2936                 :   // We can unconditionally stop capturing because
    2937                 :   // we should never be capturing when the mouse button is up
    2938               0 :   nsIPresShell::SetCapturingContent(nsnull, 0);
    2939                 : 
    2940                 :   bool selectionOff =
    2941               0 :     (DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF);
    2942                 : 
    2943               0 :   nsRefPtr<nsFrameSelection> frameselection;
    2944               0 :   ContentOffsets offsets;
    2945               0 :   nsCOMPtr<nsIContent> parentContent;
    2946               0 :   PRInt32 contentOffsetForTableSel = 0;
    2947               0 :   PRInt32 targetForTableSel = 0;
    2948               0 :   bool handleTableSelection = true;
    2949                 : 
    2950               0 :   if (!selectionOff) {
    2951               0 :     frameselection = GetFrameSelection();
    2952               0 :     if (nsEventStatus_eConsumeNoDefault != *aEventStatus && frameselection) {
    2953                 :       // Check if the frameselection recorded the mouse going down.
    2954                 :       // If not, the user must have clicked in a part of the selection.
    2955                 :       // Place the caret before continuing!
    2956                 : 
    2957               0 :       bool mouseDown = frameselection->GetMouseDownState();
    2958               0 :       nsMouseEvent *me = frameselection->GetDelayedCaretData();
    2959                 : 
    2960               0 :       if (!mouseDown && me && me->clickCount < 2) {
    2961               0 :         nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
    2962               0 :         offsets = GetContentOffsetsFromPoint(pt);
    2963               0 :         handleTableSelection = false;
    2964                 :       } else {
    2965                 :         GetDataForTableSelection(frameselection, PresContext()->PresShell(),
    2966                 :                                  (nsMouseEvent *)aEvent,
    2967               0 :                                  getter_AddRefs(parentContent),
    2968                 :                                  &contentOffsetForTableSel,
    2969               0 :                                  &targetForTableSel);
    2970                 :       }
    2971                 :     }
    2972                 :   }
    2973                 : 
    2974                 :   // We might be capturing in some other document and the event just happened to
    2975                 :   // trickle down here. Make sure that document's frame selection is notified.
    2976                 :   // Note, this may cause the current nsFrame object to be deleted, bug 336592.
    2977               0 :   nsRefPtr<nsFrameSelection> frameSelection;
    2978               0 :   if (activeFrame != this &&
    2979               0 :       static_cast<nsFrame*>(activeFrame)->DisplaySelection(activeFrame->PresContext())
    2980                 :         != nsISelectionController::SELECTION_OFF) {
    2981               0 :       frameSelection = activeFrame->GetFrameSelection();
    2982                 :   }
    2983                 : 
    2984                 :   // Also check the selection of the capturing content which might be in a
    2985                 :   // different document.
    2986               0 :   if (!frameSelection && captureContent) {
    2987               0 :     nsIDocument* doc = captureContent->GetCurrentDoc();
    2988               0 :     if (doc) {
    2989               0 :       nsIPresShell* capturingShell = doc->GetShell();
    2990               0 :       if (capturingShell && capturingShell != PresContext()->GetPresShell()) {
    2991               0 :         frameSelection = capturingShell->FrameSelection();
    2992                 :       }
    2993                 :     }
    2994                 :   }
    2995                 : 
    2996               0 :   if (frameSelection) {
    2997               0 :     frameSelection->SetMouseDownState(false);
    2998               0 :     frameSelection->StopAutoScrollTimer();
    2999                 :   }
    3000                 : 
    3001                 :   // Do not call any methods of the current object after this point!!!
    3002                 :   // The object is perhaps dead!
    3003                 : 
    3004                 :   return selectionOff
    3005                 :     ? NS_OK
    3006                 :     : HandleFrameSelection(frameselection, offsets, handleTableSelection,
    3007                 :                            contentOffsetForTableSel, targetForTableSel,
    3008               0 :                            parentContent, aEvent, aEventStatus);
    3009                 : }
    3010                 : 
    3011               0 : struct NS_STACK_CLASS FrameContentRange {
    3012               0 :   FrameContentRange(nsIContent* aContent, PRInt32 aStart, PRInt32 aEnd) :
    3013               0 :     content(aContent), start(aStart), end(aEnd) { }
    3014                 :   nsCOMPtr<nsIContent> content;
    3015                 :   PRInt32 start;
    3016                 :   PRInt32 end;
    3017                 : };
    3018                 : 
    3019                 : // Retrieve the content offsets of a frame
    3020               0 : static FrameContentRange GetRangeForFrame(nsIFrame* aFrame) {
    3021               0 :   nsCOMPtr<nsIContent> content, parent;
    3022               0 :   content = aFrame->GetContent();
    3023               0 :   if (!content) {
    3024               0 :     NS_WARNING("Frame has no content");
    3025               0 :     return FrameContentRange(nsnull, -1, -1);
    3026                 :   }
    3027               0 :   nsIAtom* type = aFrame->GetType();
    3028               0 :   if (type == nsGkAtoms::textFrame) {
    3029                 :     PRInt32 offset, offsetEnd;
    3030               0 :     aFrame->GetOffsets(offset, offsetEnd);
    3031               0 :     return FrameContentRange(content, offset, offsetEnd);
    3032                 :   }
    3033               0 :   if (type == nsGkAtoms::brFrame) {
    3034               0 :     parent = content->GetParent();
    3035               0 :     PRInt32 beginOffset = parent->IndexOf(content);
    3036               0 :     return FrameContentRange(parent, beginOffset, beginOffset);
    3037                 :   }
    3038                 :   // Loop to deal with anonymous content, which has no index; this loop
    3039                 :   // probably won't run more than twice under normal conditions
    3040               0 :   do {
    3041               0 :     parent  = content->GetParent();
    3042               0 :     if (parent) {
    3043               0 :       PRInt32 beginOffset = parent->IndexOf(content);
    3044               0 :       if (beginOffset >= 0)
    3045               0 :         return FrameContentRange(parent, beginOffset, beginOffset + 1);
    3046               0 :       content = parent;
    3047                 :     }
    3048               0 :   } while (parent);
    3049                 : 
    3050                 :   // The root content node must act differently
    3051               0 :   return FrameContentRange(content, 0, content->GetChildCount());
    3052                 : }
    3053                 : 
    3054                 : // The FrameTarget represents the closest frame to a point that can be selected
    3055                 : // The frame is the frame represented, frameEdge says whether one end of the
    3056                 : // frame is the result (in which case different handling is needed), and
    3057                 : // afterFrame says which end is repersented if frameEdge is true
    3058                 : struct FrameTarget {
    3059               0 :   FrameTarget(nsIFrame* aFrame, bool aFrameEdge, bool aAfterFrame,
    3060                 :               bool aEmptyBlock = false) :
    3061                 :     frame(aFrame), frameEdge(aFrameEdge), afterFrame(aAfterFrame),
    3062               0 :     emptyBlock(aEmptyBlock) { }
    3063               0 :   static FrameTarget Null() {
    3064               0 :     return FrameTarget(nsnull, false, false);
    3065                 :   }
    3066               0 :   bool IsNull() {
    3067               0 :     return !frame;
    3068                 :   }
    3069                 :   nsIFrame* frame;
    3070                 :   bool frameEdge;
    3071                 :   bool afterFrame;
    3072                 :   bool emptyBlock;
    3073                 : };
    3074                 : 
    3075                 : // See function implementation for information
    3076                 : static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame, nsPoint aPoint);
    3077                 : 
    3078               0 : static bool SelfIsSelectable(nsIFrame* aFrame)
    3079                 : {
    3080               0 :   return !(aFrame->IsGeneratedContentFrame() ||
    3081               0 :            aFrame->GetStyleUIReset()->mUserSelect == NS_STYLE_USER_SELECT_NONE);
    3082                 : }
    3083                 : 
    3084               0 : static bool SelectionDescendToKids(nsIFrame* aFrame) {
    3085               0 :   PRUint8 style = aFrame->GetStyleUIReset()->mUserSelect;
    3086               0 :   nsIFrame* parent = aFrame->GetParent();
    3087                 :   // If we are only near (not directly over) then don't traverse
    3088                 :   // frames with independent selection (e.g. text and list controls)
    3089                 :   // unless we're already inside such a frame (see bug 268497).  Note that this
    3090                 :   // prevents any of the users of this method from entering form controls.
    3091                 :   // XXX We might want some way to allow using the up-arrow to go into a form
    3092                 :   // control, but the focus didn't work right anyway; it'd probably be enough
    3093                 :   // if the left and right arrows could enter textboxes (which I don't believe
    3094                 :   // they can at the moment)
    3095               0 :   return !aFrame->IsGeneratedContentFrame() &&
    3096                 :          style != NS_STYLE_USER_SELECT_ALL  &&
    3097                 :          style != NS_STYLE_USER_SELECT_NONE &&
    3098               0 :          ((parent->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION) ||
    3099               0 :           !(aFrame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION));
    3100                 : }
    3101                 : 
    3102               0 : static FrameTarget GetSelectionClosestFrameForChild(nsIFrame* aChild,
    3103                 :                                                     nsPoint aPoint)
    3104                 : {
    3105               0 :   nsIFrame* parent = aChild->GetParent();
    3106               0 :   if (SelectionDescendToKids(aChild)) {
    3107               0 :     nsPoint pt = aPoint - aChild->GetOffsetTo(parent);
    3108               0 :     return GetSelectionClosestFrame(aChild, pt);
    3109                 :   }
    3110               0 :   return FrameTarget(aChild, false, false);
    3111                 : }
    3112                 : 
    3113                 : // When the cursor needs to be at the beginning of a block, it shouldn't be
    3114                 : // before the first child.  A click on a block whose first child is a block
    3115                 : // should put the cursor in the child.  The cursor shouldn't be between the
    3116                 : // blocks, because that's not where it's expected.
    3117                 : // Note that this method is guaranteed to succeed.
    3118               0 : static FrameTarget DrillDownToSelectionFrame(nsIFrame* aFrame,
    3119                 :                                              bool aEndFrame) {
    3120               0 :   if (SelectionDescendToKids(aFrame)) {
    3121               0 :     nsIFrame* result = nsnull;
    3122               0 :     nsIFrame *frame = aFrame->GetFirstPrincipalChild();
    3123               0 :     if (!aEndFrame) {
    3124               0 :       while (frame && (!SelfIsSelectable(frame) ||
    3125               0 :                         frame->IsEmpty()))
    3126               0 :         frame = frame->GetNextSibling();
    3127               0 :       if (frame)
    3128               0 :         result = frame;
    3129                 :     } else {
    3130                 :       // Because the frame tree is singly linked, to find the last frame,
    3131                 :       // we have to iterate through all the frames
    3132                 :       // XXX I have a feeling this could be slow for long blocks, although
    3133                 :       //     I can't find any slowdowns
    3134               0 :       while (frame) {
    3135               0 :         if (!frame->IsEmpty() && SelfIsSelectable(frame))
    3136               0 :           result = frame;
    3137               0 :         frame = frame->GetNextSibling();
    3138                 :       }
    3139                 :     }
    3140               0 :     if (result)
    3141               0 :       return DrillDownToSelectionFrame(result, aEndFrame);
    3142                 :   }
    3143                 :   // If the current frame has no targetable children, target the current frame
    3144               0 :   return FrameTarget(aFrame, true, aEndFrame);
    3145                 : }
    3146                 : 
    3147                 : // This method finds the closest valid FrameTarget on a given line; if there is
    3148                 : // no valid FrameTarget on the line, it returns a null FrameTarget
    3149               0 : static FrameTarget GetSelectionClosestFrameForLine(
    3150                 :                       nsBlockFrame* aParent,
    3151                 :                       nsBlockFrame::line_iterator aLine,
    3152                 :                       nsPoint aPoint)
    3153                 : {
    3154               0 :   nsIFrame *frame = aLine->mFirstChild;
    3155                 :   // Account for end of lines (any iterator from the block is valid)
    3156               0 :   if (aLine == aParent->end_lines())
    3157               0 :     return DrillDownToSelectionFrame(aParent, true);
    3158               0 :   nsIFrame *closestFromLeft = nsnull, *closestFromRight = nsnull;
    3159               0 :   nsRect rect = aLine->mBounds;
    3160               0 :   nscoord closestLeft = rect.x, closestRight = rect.XMost();
    3161               0 :   for (PRInt32 n = aLine->GetChildCount(); n;
    3162                 :        --n, frame = frame->GetNextSibling()) {
    3163               0 :     if (!SelfIsSelectable(frame) || frame->IsEmpty())
    3164               0 :       continue;
    3165               0 :     nsRect frameRect = frame->GetRect();
    3166               0 :     if (aPoint.x >= frameRect.x) {
    3167               0 :       if (aPoint.x < frameRect.XMost()) {
    3168               0 :         return GetSelectionClosestFrameForChild(frame, aPoint);
    3169                 :       }
    3170               0 :       if (frameRect.XMost() >= closestLeft) {
    3171               0 :         closestFromLeft = frame;
    3172               0 :         closestLeft = frameRect.XMost();
    3173                 :       }
    3174                 :     } else {
    3175               0 :       if (frameRect.x <= closestRight) {
    3176               0 :         closestFromRight = frame;
    3177               0 :         closestRight = frameRect.x;
    3178                 :       }
    3179                 :     }
    3180                 :   }
    3181               0 :   if (!closestFromLeft && !closestFromRight) {
    3182                 :     // We should only get here if there are no selectable frames on a line
    3183                 :     // XXX Do we need more elaborate handling here?
    3184               0 :     return FrameTarget::Null();
    3185                 :   }
    3186               0 :   if (closestFromLeft &&
    3187                 :       (!closestFromRight ||
    3188               0 :        (abs(aPoint.x - closestLeft) <= abs(aPoint.x - closestRight)))) {
    3189               0 :     return GetSelectionClosestFrameForChild(closestFromLeft, aPoint);
    3190                 :   }
    3191               0 :   return GetSelectionClosestFrameForChild(closestFromRight, aPoint);
    3192                 : }
    3193                 : 
    3194                 : // This method is for the special handling we do for block frames; they're
    3195                 : // special because they represent paragraphs and because they are organized
    3196                 : // into lines, which have bounds that are not stored elsewhere in the
    3197                 : // frame tree.  Returns a null FrameTarget for frames which are not
    3198                 : // blocks or blocks with no lines except editable one.
    3199               0 : static FrameTarget GetSelectionClosestFrameForBlock(nsIFrame* aFrame,
    3200                 :                                                     nsPoint aPoint)
    3201                 : {
    3202               0 :   nsBlockFrame* bf = nsLayoutUtils::GetAsBlock(aFrame); // used only for QI
    3203               0 :   if (!bf)
    3204               0 :     return FrameTarget::Null();
    3205                 : 
    3206                 :   // This code searches for the correct line
    3207               0 :   nsBlockFrame::line_iterator firstLine = bf->begin_lines();
    3208               0 :   nsBlockFrame::line_iterator end = bf->end_lines();
    3209               0 :   if (firstLine == end) {
    3210               0 :     nsIContent *blockContent = aFrame->GetContent();
    3211               0 :     if (blockContent && blockContent->IsEditable()) {
    3212                 :       // If the frame is ediable empty block, we should return it with empty
    3213                 :       // flag.
    3214               0 :       return FrameTarget(aFrame, false, false, true);
    3215                 :     }
    3216               0 :     return FrameTarget::Null();
    3217                 :   }
    3218               0 :   nsBlockFrame::line_iterator curLine = firstLine;
    3219               0 :   nsBlockFrame::line_iterator closestLine = end;
    3220               0 :   while (curLine != end) {
    3221                 :     // Check to see if our point lies with the line's Y bounds
    3222               0 :     nscoord y = aPoint.y - curLine->mBounds.y;
    3223               0 :     nscoord height = curLine->mBounds.height;
    3224               0 :     if (y >= 0 && y < height) {
    3225               0 :       closestLine = curLine;
    3226               0 :       break; // We found the line; stop looking
    3227                 :     }
    3228               0 :     if (y < 0)
    3229               0 :       break;
    3230               0 :     ++curLine;
    3231                 :   }
    3232                 : 
    3233               0 :   if (closestLine == end) {
    3234               0 :     nsBlockFrame::line_iterator prevLine = curLine.prev();
    3235               0 :     nsBlockFrame::line_iterator nextLine = curLine;
    3236                 :     // Avoid empty lines
    3237               0 :     while (nextLine != end && nextLine->IsEmpty())
    3238               0 :       ++nextLine;
    3239               0 :     while (prevLine != end && prevLine->IsEmpty())
    3240               0 :       --prevLine;
    3241                 : 
    3242                 :     // This hidden pref dictates whether a point above or below all lines comes
    3243                 :     // up with a line or the beginning or end of the frame; 0 on Windows,
    3244                 :     // 1 on other platforms by default at the writing of this code
    3245                 :     PRInt32 dragOutOfFrame =
    3246               0 :       Preferences::GetInt("browser.drag_out_of_frame_style");
    3247                 : 
    3248               0 :     if (prevLine == end) {
    3249               0 :       if (dragOutOfFrame == 1 || nextLine == end)
    3250               0 :         return DrillDownToSelectionFrame(aFrame, false);
    3251               0 :       closestLine = nextLine;
    3252               0 :     } else if (nextLine == end) {
    3253               0 :       if (dragOutOfFrame == 1)
    3254               0 :         return DrillDownToSelectionFrame(aFrame, true);
    3255               0 :       closestLine = prevLine;
    3256                 :     } else { // Figure out which line is closer
    3257               0 :       if (aPoint.y - prevLine->mBounds.YMost() < nextLine->mBounds.y - aPoint.y)
    3258               0 :         closestLine = prevLine;
    3259                 :       else
    3260               0 :         closestLine = nextLine;
    3261                 :     }
    3262                 :   }
    3263                 : 
    3264               0 :   do {
    3265                 :     FrameTarget target = GetSelectionClosestFrameForLine(bf, closestLine,
    3266               0 :                                                          aPoint);
    3267               0 :     if (!target.IsNull())
    3268               0 :       return target;
    3269               0 :     ++closestLine;
    3270                 :   } while (closestLine != end);
    3271                 :   // Fall back to just targeting the last targetable place
    3272               0 :   return DrillDownToSelectionFrame(aFrame, true);
    3273                 : }
    3274                 : 
    3275                 : // GetSelectionClosestFrame is the helper function that calculates the closest
    3276                 : // frame to the given point.
    3277                 : // It doesn't completely account for offset styles, so needs to be used in
    3278                 : // restricted environments.
    3279                 : // Cannot handle overlapping frames correctly, so it should receive the output
    3280                 : // of GetFrameForPoint
    3281                 : // Guaranteed to return a valid FrameTarget
    3282               0 : static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame, nsPoint aPoint)
    3283                 : {
    3284                 :   {
    3285                 :     // Handle blocks; if the frame isn't a block, the method fails
    3286               0 :     FrameTarget target = GetSelectionClosestFrameForBlock(aFrame, aPoint);
    3287               0 :     if (!target.IsNull())
    3288               0 :       return target;
    3289                 :   }
    3290                 : 
    3291               0 :   nsIFrame *kid = aFrame->GetFirstPrincipalChild();
    3292                 : 
    3293               0 :   if (kid) {
    3294                 :     // Go through all the child frames to find the closest one
    3295                 : 
    3296                 :     // Large number to force the comparison to succeed
    3297               0 :     const nscoord HUGE_DISTANCE = nscoord_MAX;
    3298               0 :     nscoord closestXDistance = HUGE_DISTANCE;
    3299               0 :     nscoord closestYDistance = HUGE_DISTANCE;
    3300               0 :     nsIFrame *closestFrame = nsnull;
    3301                 : 
    3302               0 :     for (; kid; kid = kid->GetNextSibling()) {
    3303               0 :       if (!SelfIsSelectable(kid) || kid->IsEmpty())
    3304               0 :         continue;
    3305                 : 
    3306               0 :       nsRect rect = kid->GetRect();
    3307                 : 
    3308               0 :       nscoord fromLeft = aPoint.x - rect.x;
    3309               0 :       nscoord fromRight = aPoint.x - rect.XMost();
    3310                 : 
    3311                 :       nscoord xDistance;
    3312               0 :       if (fromLeft >= 0 && fromRight <= 0) {
    3313               0 :         xDistance = 0;
    3314                 :       } else {
    3315               0 :         xDistance = NS_MIN(abs(fromLeft), abs(fromRight));
    3316                 :       }
    3317                 : 
    3318               0 :       if (xDistance <= closestXDistance)
    3319                 :       {
    3320               0 :         if (xDistance < closestXDistance)
    3321               0 :           closestYDistance = HUGE_DISTANCE;
    3322                 : 
    3323               0 :         nscoord fromTop = aPoint.y - rect.y;
    3324               0 :         nscoord fromBottom = aPoint.y - rect.YMost();
    3325                 : 
    3326                 :         nscoord yDistance;
    3327               0 :         if (fromTop >= 0 && fromBottom <= 0)
    3328               0 :           yDistance = 0;
    3329                 :         else
    3330               0 :           yDistance = NS_MIN(abs(fromTop), abs(fromBottom));
    3331                 : 
    3332               0 :         if (yDistance < closestYDistance)
    3333                 :         {
    3334               0 :           closestXDistance = xDistance;
    3335               0 :           closestYDistance = yDistance;
    3336               0 :           closestFrame = kid;
    3337                 :         }
    3338                 :       }
    3339                 :     }
    3340               0 :     if (closestFrame)
    3341               0 :       return GetSelectionClosestFrameForChild(closestFrame, aPoint);
    3342                 :   }
    3343               0 :   return FrameTarget(aFrame, false, false);
    3344                 : }
    3345                 : 
    3346               0 : nsIFrame::ContentOffsets OffsetsForSingleFrame(nsIFrame* aFrame, nsPoint aPoint)
    3347                 : {
    3348               0 :   nsIFrame::ContentOffsets offsets;
    3349               0 :   FrameContentRange range = GetRangeForFrame(aFrame);
    3350               0 :   offsets.content = range.content;
    3351                 :   // If there are continuations (meaning it's not one rectangle), this is the
    3352                 :   // best this function can do
    3353               0 :   if (aFrame->GetNextContinuation() || aFrame->GetPrevContinuation()) {
    3354               0 :     offsets.offset = range.start;
    3355               0 :     offsets.secondaryOffset = range.end;
    3356               0 :     offsets.associateWithNext = true;
    3357                 :     return offsets;
    3358                 :   }
    3359                 : 
    3360                 :   // Figure out whether the offsets should be over, after, or before the frame
    3361               0 :   nsRect rect(nsPoint(0, 0), aFrame->GetSize());
    3362                 : 
    3363               0 :   bool isBlock = (aFrame->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_INLINE);
    3364               0 :   bool isRtl = (aFrame->GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL);
    3365               0 :   if ((isBlock && rect.y < aPoint.y) ||
    3366               0 :       (!isBlock && ((isRtl  && rect.x + rect.width / 2 > aPoint.x) || 
    3367               0 :                     (!isRtl && rect.x + rect.width / 2 < aPoint.x)))) {
    3368               0 :     offsets.offset = range.end;
    3369               0 :     if (rect.Contains(aPoint))
    3370               0 :       offsets.secondaryOffset = range.start;
    3371                 :     else
    3372               0 :       offsets.secondaryOffset = range.end;
    3373                 :   } else {
    3374               0 :     offsets.offset = range.start;
    3375               0 :     if (rect.Contains(aPoint))
    3376               0 :       offsets.secondaryOffset = range.end;
    3377                 :     else
    3378               0 :       offsets.secondaryOffset = range.start;
    3379                 :   }
    3380               0 :   offsets.associateWithNext = (offsets.offset == range.start);
    3381                 :   return offsets;
    3382                 : }
    3383                 : 
    3384               0 : static nsIFrame* AdjustFrameForSelectionStyles(nsIFrame* aFrame) {
    3385               0 :   nsIFrame* adjustedFrame = aFrame;
    3386               0 :   for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent())
    3387                 :   {
    3388                 :     // These are the conditions that make all children not able to handle
    3389                 :     // a cursor.
    3390               0 :     if (frame->GetStyleUIReset()->mUserSelect == NS_STYLE_USER_SELECT_NONE || 
    3391               0 :         frame->GetStyleUIReset()->mUserSelect == NS_STYLE_USER_SELECT_ALL || 
    3392               0 :         frame->IsGeneratedContentFrame()) {
    3393               0 :       adjustedFrame = frame;
    3394                 :     }
    3395                 :   }
    3396               0 :   return adjustedFrame;
    3397                 : }
    3398                 :   
    3399                 : 
    3400               0 : nsIFrame::ContentOffsets nsIFrame::GetContentOffsetsFromPoint(nsPoint aPoint,
    3401                 :                                                               bool aIgnoreSelectionStyle)
    3402                 : {
    3403                 :   nsIFrame *adjustedFrame;
    3404               0 :   if (aIgnoreSelectionStyle) {
    3405               0 :     adjustedFrame = this;
    3406                 :   }
    3407                 :   else {
    3408                 :     // This section of code deals with special selection styles.  Note that
    3409                 :     // -moz-none and -moz-all exist, even though they don't need to be explicitly
    3410                 :     // handled.
    3411                 :     // The offset is forced not to end up in generated content; content offsets
    3412                 :     // cannot represent content outside of the document's content tree.
    3413                 : 
    3414               0 :     adjustedFrame = AdjustFrameForSelectionStyles(this);
    3415                 : 
    3416                 :     // -moz-user-select: all needs special handling, because clicking on it
    3417                 :     // should lead to the whole frame being selected
    3418               0 :     if (adjustedFrame && adjustedFrame->GetStyleUIReset()->mUserSelect ==
    3419                 :         NS_STYLE_USER_SELECT_ALL) {
    3420                 :       return OffsetsForSingleFrame(adjustedFrame, aPoint +
    3421               0 :                                    this->GetOffsetTo(adjustedFrame));
    3422                 :     }
    3423                 : 
    3424                 :     // For other cases, try to find a closest frame starting from the parent of
    3425                 :     // the unselectable frame
    3426               0 :     if (adjustedFrame != this)
    3427               0 :       adjustedFrame = adjustedFrame->GetParent();
    3428                 :   }
    3429                 : 
    3430               0 :   nsPoint adjustedPoint = aPoint + this->GetOffsetTo(adjustedFrame);
    3431                 : 
    3432               0 :   FrameTarget closest = GetSelectionClosestFrame(adjustedFrame, adjustedPoint);
    3433                 : 
    3434               0 :   if (closest.emptyBlock) {
    3435               0 :     ContentOffsets offsets;
    3436               0 :     NS_ASSERTION(closest.frame,
    3437                 :                  "closest.frame must not be null when it's empty");
    3438               0 :     offsets.content = closest.frame->GetContent();
    3439               0 :     offsets.offset = 0;
    3440               0 :     offsets.secondaryOffset = 0;
    3441               0 :     offsets.associateWithNext = true;
    3442               0 :     return offsets;
    3443                 :   }
    3444                 : 
    3445                 :   // If the correct offset is at one end of a frame, use offset-based
    3446                 :   // calculation method
    3447               0 :   if (closest.frameEdge) {
    3448               0 :     ContentOffsets offsets;
    3449               0 :     FrameContentRange range = GetRangeForFrame(closest.frame);
    3450               0 :     offsets.content = range.content;
    3451               0 :     if (closest.afterFrame)
    3452               0 :       offsets.offset = range.end;
    3453                 :     else
    3454               0 :       offsets.offset = range.start;
    3455               0 :     offsets.secondaryOffset = offsets.offset;
    3456               0 :     offsets.associateWithNext = (offsets.offset == range.start);
    3457               0 :     return offsets;
    3458                 :   }
    3459               0 :   nsPoint pt = aPoint - closest.frame->GetOffsetTo(this);
    3460               0 :   return static_cast<nsFrame*>(closest.frame)->CalcContentOffsetsFromFramePoint(pt);
    3461                 : 
    3462                 :   // XXX should I add some kind of offset standardization?
    3463                 :   // consider <b>xxxxx</b><i>zzzzz</i>; should any click between the last
    3464                 :   // x and first z put the cursor in the same logical position in addition
    3465                 :   // to the same visual position?
    3466                 : }
    3467                 : 
    3468               0 : nsIFrame::ContentOffsets nsFrame::CalcContentOffsetsFromFramePoint(nsPoint aPoint)
    3469                 : {
    3470               0 :   return OffsetsForSingleFrame(this, aPoint);
    3471                 : }
    3472                 : 
    3473                 : NS_IMETHODIMP
    3474               0 : nsFrame::GetCursor(const nsPoint& aPoint,
    3475                 :                    nsIFrame::Cursor& aCursor)
    3476                 : {
    3477               0 :   FillCursorInformationFromStyle(GetStyleUserInterface(), aCursor);
    3478               0 :   if (NS_STYLE_CURSOR_AUTO == aCursor.mCursor) {
    3479               0 :     aCursor.mCursor = NS_STYLE_CURSOR_DEFAULT;
    3480                 :   }
    3481                 : 
    3482                 : 
    3483               0 :   return NS_OK;
    3484                 : }
    3485                 : 
    3486                 : // Resize and incremental reflow
    3487                 : 
    3488                 : /* virtual */ void
    3489               0 : nsFrame::MarkIntrinsicWidthsDirty()
    3490                 : {
    3491                 :   // This version is meant only for what used to be box-to-block adaptors.
    3492                 :   // It should not be called by other derived classes.
    3493               0 :   if (IsBoxWrapped()) {
    3494               0 :     nsBoxLayoutMetrics *metrics = BoxMetrics();
    3495                 : 
    3496               0 :     SizeNeedsRecalc(metrics->mPrefSize);
    3497               0 :     SizeNeedsRecalc(metrics->mMinSize);
    3498               0 :     SizeNeedsRecalc(metrics->mMaxSize);
    3499               0 :     SizeNeedsRecalc(metrics->mBlockPrefSize);
    3500               0 :     SizeNeedsRecalc(metrics->mBlockMinSize);
    3501               0 :     CoordNeedsRecalc(metrics->mFlex);
    3502               0 :     CoordNeedsRecalc(metrics->mAscent);
    3503                 :   }
    3504               0 : }
    3505                 : 
    3506                 : /* virtual */ nscoord
    3507               0 : nsFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
    3508                 : {
    3509               0 :   nscoord result = 0;
    3510               0 :   DISPLAY_MIN_WIDTH(this, result);
    3511               0 :   return result;
    3512                 : }
    3513                 : 
    3514                 : /* virtual */ nscoord
    3515               0 : nsFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
    3516                 : {
    3517               0 :   nscoord result = 0;
    3518               0 :   DISPLAY_PREF_WIDTH(this, result);
    3519               0 :   return result;
    3520                 : }
    3521                 : 
    3522                 : /* virtual */ void
    3523               0 : nsFrame::AddInlineMinWidth(nsRenderingContext *aRenderingContext,
    3524                 :                            nsIFrame::InlineMinWidthData *aData)
    3525                 : {
    3526               0 :   NS_ASSERTION(GetParent(), "Must have a parent if we get here!");
    3527               0 :   bool canBreak = !CanContinueTextRun() &&
    3528               0 :     GetParent()->GetStyleText()->WhiteSpaceCanWrap();
    3529                 :   
    3530               0 :   if (canBreak)
    3531               0 :     aData->OptionallyBreak(aRenderingContext);
    3532               0 :   aData->trailingWhitespace = 0;
    3533               0 :   aData->skipWhitespace = false;
    3534               0 :   aData->trailingTextFrame = nsnull;
    3535                 :   aData->currentLine += nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
    3536               0 :                             this, nsLayoutUtils::MIN_WIDTH);
    3537               0 :   aData->atStartOfLine = false;
    3538               0 :   if (canBreak)
    3539               0 :     aData->OptionallyBreak(aRenderingContext);
    3540               0 : }
    3541                 : 
    3542                 : /* virtual */ void
    3543               0 : nsFrame::AddInlinePrefWidth(nsRenderingContext *aRenderingContext,
    3544                 :                             nsIFrame::InlinePrefWidthData *aData)
    3545                 : {
    3546               0 :   aData->trailingWhitespace = 0;
    3547               0 :   aData->skipWhitespace = false;
    3548                 :   nscoord myPref = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, 
    3549               0 :                        this, nsLayoutUtils::PREF_WIDTH);
    3550               0 :   aData->currentLine = NSCoordSaturatingAdd(aData->currentLine, myPref);
    3551               0 : }
    3552                 : 
    3553                 : void
    3554               0 : nsIFrame::InlineMinWidthData::ForceBreak(nsRenderingContext *aRenderingContext)
    3555                 : {
    3556               0 :   currentLine -= trailingWhitespace;
    3557               0 :   prevLines = NS_MAX(prevLines, currentLine);
    3558               0 :   currentLine = trailingWhitespace = 0;
    3559                 : 
    3560               0 :   for (PRUint32 i = 0, i_end = floats.Length(); i != i_end; ++i) {
    3561               0 :     nsIFrame *floatFrame = floats[i];
    3562                 :     nscoord float_min =
    3563                 :       nsLayoutUtils::IntrinsicForContainer(aRenderingContext, floatFrame,
    3564               0 :                                            nsLayoutUtils::MIN_WIDTH);
    3565               0 :     if (float_min > prevLines)
    3566               0 :       prevLines = float_min;
    3567                 :   }
    3568               0 :   floats.Clear();
    3569               0 :   trailingTextFrame = nsnull;
    3570               0 :   skipWhitespace = true;
    3571               0 : }
    3572                 : 
    3573                 : void
    3574               0 : nsIFrame::InlineMinWidthData::OptionallyBreak(nsRenderingContext *aRenderingContext,
    3575                 :                                               nscoord aHyphenWidth)
    3576                 : {
    3577               0 :   trailingTextFrame = nsnull;
    3578                 : 
    3579                 :   // If we can fit more content into a smaller width by staying on this
    3580                 :   // line (because we're still at a negative offset due to negative
    3581                 :   // text-indent or negative margin), don't break.  Otherwise, do the
    3582                 :   // same as ForceBreak.  it doesn't really matter when we accumulate
    3583                 :   // floats.
    3584               0 :   if (currentLine + aHyphenWidth < 0 || atStartOfLine)
    3585               0 :     return;
    3586               0 :   currentLine += aHyphenWidth;
    3587               0 :   ForceBreak(aRenderingContext);
    3588                 : }
    3589                 : 
    3590                 : void
    3591               0 : nsIFrame::InlinePrefWidthData::ForceBreak(nsRenderingContext *aRenderingContext)
    3592                 : {
    3593               0 :   if (floats.Length() != 0) {
    3594                 :             // preferred widths accumulated for floats that have already
    3595                 :             // been cleared past
    3596               0 :     nscoord floats_done = 0,
    3597                 :             // preferred widths accumulated for floats that have not yet
    3598                 :             // been cleared past
    3599               0 :             floats_cur_left = 0,
    3600               0 :             floats_cur_right = 0;
    3601                 : 
    3602               0 :     for (PRUint32 i = 0, i_end = floats.Length(); i != i_end; ++i) {
    3603               0 :       nsIFrame *floatFrame = floats[i];
    3604               0 :       const nsStyleDisplay *floatDisp = floatFrame->GetStyleDisplay();
    3605               0 :       if (floatDisp->mBreakType == NS_STYLE_CLEAR_LEFT ||
    3606                 :           floatDisp->mBreakType == NS_STYLE_CLEAR_RIGHT ||
    3607                 :           floatDisp->mBreakType == NS_STYLE_CLEAR_LEFT_AND_RIGHT) {
    3608                 :         nscoord floats_cur = NSCoordSaturatingAdd(floats_cur_left,
    3609               0 :                                                   floats_cur_right);
    3610               0 :         if (floats_cur > floats_done)
    3611               0 :           floats_done = floats_cur;
    3612               0 :         if (floatDisp->mBreakType != NS_STYLE_CLEAR_RIGHT)
    3613               0 :           floats_cur_left = 0;
    3614               0 :         if (floatDisp->mBreakType != NS_STYLE_CLEAR_LEFT)
    3615               0 :           floats_cur_right = 0;
    3616                 :       }
    3617                 : 
    3618                 :       nscoord &floats_cur = floatDisp->mFloats == NS_STYLE_FLOAT_LEFT
    3619               0 :                               ? floats_cur_left : floats_cur_right;
    3620                 :       nscoord floatWidth =
    3621                 :           nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
    3622                 :                                                floatFrame,
    3623               0 :                                                nsLayoutUtils::PREF_WIDTH);
    3624                 :       // Negative-width floats don't change the available space so they
    3625                 :       // shouldn't change our intrinsic line width either.
    3626                 :       floats_cur =
    3627               0 :         NSCoordSaturatingAdd(floats_cur, NS_MAX(0, floatWidth));
    3628                 :     }
    3629                 : 
    3630                 :     nscoord floats_cur =
    3631               0 :       NSCoordSaturatingAdd(floats_cur_left, floats_cur_right);
    3632               0 :     if (floats_cur > floats_done)
    3633               0 :       floats_done = floats_cur;
    3634                 : 
    3635               0 :     currentLine = NSCoordSaturatingAdd(currentLine, floats_done);
    3636                 : 
    3637               0 :     floats.Clear();
    3638                 :   }
    3639                 : 
    3640                 :   currentLine =
    3641               0 :     NSCoordSaturatingSubtract(currentLine, trailingWhitespace, nscoord_MAX);
    3642               0 :   prevLines = NS_MAX(prevLines, currentLine);
    3643               0 :   currentLine = trailingWhitespace = 0;
    3644               0 :   skipWhitespace = true;
    3645               0 : }
    3646                 : 
    3647                 : static void
    3648               0 : AddCoord(const nsStyleCoord& aStyle,
    3649                 :          nsRenderingContext* aRenderingContext,
    3650                 :          nsIFrame* aFrame,
    3651                 :          nscoord* aCoord, float* aPercent,
    3652                 :          bool aClampNegativeToZero)
    3653                 : {
    3654               0 :   switch (aStyle.GetUnit()) {
    3655                 :     case eStyleUnit_Coord: {
    3656               0 :       NS_ASSERTION(!aClampNegativeToZero || aStyle.GetCoordValue() >= 0,
    3657                 :                    "unexpected negative value");
    3658               0 :       *aCoord += aStyle.GetCoordValue();
    3659               0 :       return;
    3660                 :     }
    3661                 :     case eStyleUnit_Percent: {
    3662               0 :       NS_ASSERTION(!aClampNegativeToZero || aStyle.GetPercentValue() >= 0.0f,
    3663                 :                    "unexpected negative value");
    3664               0 :       *aPercent += aStyle.GetPercentValue();
    3665               0 :       return;
    3666                 :     }
    3667                 :     case eStyleUnit_Calc: {
    3668               0 :       const nsStyleCoord::Calc *calc = aStyle.GetCalcValue();
    3669               0 :       if (aClampNegativeToZero) {
    3670                 :         // This is far from ideal when one is negative and one is positive.
    3671               0 :         *aCoord += NS_MAX(calc->mLength, 0);
    3672               0 :         *aPercent += NS_MAX(calc->mPercent, 0.0f);
    3673                 :       } else {
    3674               0 :         *aCoord += calc->mLength;
    3675               0 :         *aPercent += calc->mPercent;
    3676                 :       }
    3677               0 :       return;
    3678                 :     }
    3679                 :     default: {
    3680               0 :       return;
    3681                 :     }
    3682                 :   }
    3683                 : }
    3684                 : 
    3685                 : /* virtual */ nsIFrame::IntrinsicWidthOffsetData
    3686               0 : nsFrame::IntrinsicWidthOffsets(nsRenderingContext* aRenderingContext)
    3687                 : {
    3688               0 :   IntrinsicWidthOffsetData result;
    3689                 : 
    3690               0 :   const nsStyleMargin *styleMargin = GetStyleMargin();
    3691                 :   AddCoord(styleMargin->mMargin.GetLeft(), aRenderingContext, this,
    3692               0 :            &result.hMargin, &result.hPctMargin, false);
    3693                 :   AddCoord(styleMargin->mMargin.GetRight(), aRenderingContext, this,
    3694               0 :            &result.hMargin, &result.hPctMargin, false);
    3695                 : 
    3696               0 :   const nsStylePadding *stylePadding = GetStylePadding();
    3697                 :   AddCoord(stylePadding->mPadding.GetLeft(), aRenderingContext, this,
    3698               0 :            &result.hPadding, &result.hPctPadding, true);
    3699                 :   AddCoord(stylePadding->mPadding.GetRight(), aRenderingContext, this,
    3700               0 :            &result.hPadding, &result.hPctPadding, true);
    3701                 : 
    3702               0 :   const nsStyleBorder *styleBorder = GetStyleBorder();
    3703               0 :   result.hBorder += styleBorder->GetActualBorderWidth(NS_SIDE_LEFT);
    3704               0 :   result.hBorder += styleBorder->GetActualBorderWidth(NS_SIDE_RIGHT);
    3705                 : 
    3706               0 :   const nsStyleDisplay *disp = GetStyleDisplay();
    3707               0 :   if (IsThemed(disp)) {
    3708               0 :     nsPresContext *presContext = PresContext();
    3709                 : 
    3710               0 :     nsIntMargin border;
    3711               0 :     presContext->GetTheme()->GetWidgetBorder(presContext->DeviceContext(),
    3712                 :                                              this, disp->mAppearance,
    3713               0 :                                              &border);
    3714               0 :     result.hBorder = presContext->DevPixelsToAppUnits(border.LeftRight());
    3715                 : 
    3716               0 :     nsIntMargin padding;
    3717               0 :     if (presContext->GetTheme()->GetWidgetPadding(presContext->DeviceContext(),
    3718                 :                                                   this, disp->mAppearance,
    3719               0 :                                                   &padding)) {
    3720               0 :       result.hPadding = presContext->DevPixelsToAppUnits(padding.LeftRight());
    3721               0 :       result.hPctPadding = 0;
    3722                 :     }
    3723                 :   }
    3724                 : 
    3725                 :   return result;
    3726                 : }
    3727                 : 
    3728                 : /* virtual */ nsIFrame::IntrinsicSize
    3729               0 : nsFrame::GetIntrinsicSize()
    3730                 : {
    3731               0 :   return IntrinsicSize(); // default is width/height set to eStyleUnit_None
    3732                 : }
    3733                 : 
    3734                 : /* virtual */ nsSize
    3735               0 : nsFrame::GetIntrinsicRatio()
    3736                 : {
    3737               0 :   return nsSize(0, 0);
    3738                 : }
    3739                 : 
    3740                 : /* virtual */ nsSize
    3741               0 : nsFrame::ComputeSize(nsRenderingContext *aRenderingContext,
    3742                 :                      nsSize aCBSize, nscoord aAvailableWidth,
    3743                 :                      nsSize aMargin, nsSize aBorder, nsSize aPadding,
    3744                 :                      bool aShrinkWrap)
    3745                 : {
    3746                 :   nsSize result = ComputeAutoSize(aRenderingContext, aCBSize, aAvailableWidth,
    3747               0 :                                   aMargin, aBorder, aPadding, aShrinkWrap);
    3748               0 :   nsSize boxSizingAdjust(0,0);
    3749               0 :   const nsStylePosition *stylePos = GetStylePosition();
    3750                 : 
    3751               0 :   switch (stylePos->mBoxSizing) {
    3752                 :     case NS_STYLE_BOX_SIZING_BORDER:
    3753               0 :       boxSizingAdjust += aBorder;
    3754                 :       // fall through
    3755                 :     case NS_STYLE_BOX_SIZING_PADDING:
    3756               0 :       boxSizingAdjust += aPadding;
    3757                 :   }
    3758                 :   nscoord boxSizingToMarginEdgeWidth =
    3759               0 :     aMargin.width + aBorder.width + aPadding.width - boxSizingAdjust.width;
    3760                 : 
    3761                 :   // Compute width
    3762                 : 
    3763               0 :   if (stylePos->mWidth.GetUnit() != eStyleUnit_Auto) {
    3764                 :     result.width =
    3765                 :       nsLayoutUtils::ComputeWidthValue(aRenderingContext, this,
    3766                 :         aCBSize.width, boxSizingAdjust.width, boxSizingToMarginEdgeWidth,
    3767               0 :         stylePos->mWidth);
    3768                 :   }
    3769                 : 
    3770               0 :   if (stylePos->mMaxWidth.GetUnit() != eStyleUnit_None) {
    3771                 :     nscoord maxWidth =
    3772                 :       nsLayoutUtils::ComputeWidthValue(aRenderingContext, this,
    3773                 :         aCBSize.width, boxSizingAdjust.width, boxSizingToMarginEdgeWidth,
    3774               0 :         stylePos->mMaxWidth);
    3775               0 :     if (maxWidth < result.width)
    3776               0 :       result.width = maxWidth;
    3777                 :   }
    3778                 : 
    3779                 :   nscoord minWidth =
    3780                 :     nsLayoutUtils::ComputeWidthValue(aRenderingContext, this,
    3781                 :       aCBSize.width, boxSizingAdjust.width, boxSizingToMarginEdgeWidth,
    3782               0 :       stylePos->mMinWidth);
    3783               0 :   if (minWidth > result.width)
    3784               0 :     result.width = minWidth;
    3785                 : 
    3786                 :   // Compute height
    3787                 : 
    3788               0 :   if (!nsLayoutUtils::IsAutoHeight(stylePos->mHeight, aCBSize.height)) {
    3789                 :     result.height =
    3790               0 :       nsLayoutUtils::ComputeHeightValue(aCBSize.height, stylePos->mHeight) -
    3791               0 :       boxSizingAdjust.height;
    3792                 :   }
    3793                 : 
    3794               0 :   if (result.height != NS_UNCONSTRAINEDSIZE) {
    3795               0 :     if (!nsLayoutUtils::IsAutoHeight(stylePos->mMaxHeight, aCBSize.height)) {
    3796                 :       nscoord maxHeight =
    3797               0 :         nsLayoutUtils::ComputeHeightValue(aCBSize.height, stylePos->mMaxHeight) -
    3798               0 :         boxSizingAdjust.height;
    3799               0 :       if (maxHeight < result.height)
    3800               0 :         result.height = maxHeight;
    3801                 :     }
    3802                 : 
    3803               0 :     if (!nsLayoutUtils::IsAutoHeight(stylePos->mMinHeight, aCBSize.height)) {
    3804                 :       nscoord minHeight =
    3805               0 :         nsLayoutUtils::ComputeHeightValue(aCBSize.height, stylePos->mMinHeight) -
    3806               0 :         boxSizingAdjust.height;
    3807               0 :       if (minHeight > result.height)
    3808               0 :         result.height = minHeight;
    3809                 :     }
    3810                 :   }
    3811                 : 
    3812               0 :   const nsStyleDisplay *disp = GetStyleDisplay();
    3813               0 :   if (IsThemed(disp)) {
    3814               0 :     nsIntSize widget(0, 0);
    3815               0 :     bool canOverride = true;
    3816               0 :     nsPresContext *presContext = PresContext();
    3817               0 :     presContext->GetTheme()->
    3818                 :       GetMinimumWidgetSize(aRenderingContext, this, disp->mAppearance,
    3819               0 :                            &widget, &canOverride);
    3820                 : 
    3821               0 :     nsSize size;
    3822               0 :     size.width = presContext->DevPixelsToAppUnits(widget.width);
    3823               0 :     size.height = presContext->DevPixelsToAppUnits(widget.height);
    3824                 : 
    3825                 :     // GMWS() returns border-box; we need content-box
    3826               0 :     size.width -= aBorder.width + aPadding.width;
    3827               0 :     size.height -= aBorder.height + aPadding.height;
    3828                 : 
    3829               0 :     if (size.height > result.height || !canOverride)
    3830               0 :       result.height = size.height;
    3831               0 :     if (size.width > result.width || !canOverride)
    3832               0 :       result.width = size.width;
    3833                 :   }
    3834                 : 
    3835               0 :   if (result.width < 0)
    3836               0 :     result.width = 0;
    3837                 : 
    3838               0 :   if (result.height < 0)
    3839               0 :     result.height = 0;
    3840                 : 
    3841                 :   return result;
    3842                 : }
    3843                 : 
    3844                 : nsRect
    3845               0 : nsIFrame::ComputeTightBounds(gfxContext* aContext) const
    3846                 : {
    3847               0 :   return GetVisualOverflowRect();
    3848                 : }
    3849                 : 
    3850                 : nsRect
    3851               0 : nsFrame::ComputeSimpleTightBounds(gfxContext* aContext) const
    3852                 : {
    3853               0 :   if (GetStyleOutline()->GetOutlineStyle() != NS_STYLE_BORDER_STYLE_NONE ||
    3854               0 :       HasBorder() || !GetStyleBackground()->IsTransparent() ||
    3855               0 :       GetStyleDisplay()->mAppearance) {
    3856                 :     // Not necessarily tight, due to clipping, negative
    3857                 :     // outline-offset, and lots of other issues, but that's OK
    3858               0 :     return GetVisualOverflowRect();
    3859                 :   }
    3860                 : 
    3861               0 :   nsRect r(0, 0, 0, 0);
    3862               0 :   ChildListIterator lists(this);
    3863               0 :   for (; !lists.IsDone(); lists.Next()) {
    3864               0 :     nsFrameList::Enumerator childFrames(lists.CurrentList());
    3865               0 :     for (; !childFrames.AtEnd(); childFrames.Next()) {
    3866               0 :       nsIFrame* child = childFrames.get();
    3867               0 :       r.UnionRect(r, child->ComputeTightBounds(aContext) + child->GetPosition());
    3868                 :     }
    3869                 :   }
    3870               0 :   return r;
    3871                 : }
    3872                 : 
    3873                 : /* virtual */ nsSize
    3874               0 : nsFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
    3875                 :                          nsSize aCBSize, nscoord aAvailableWidth,
    3876                 :                          nsSize aMargin, nsSize aBorder, nsSize aPadding,
    3877                 :                          bool aShrinkWrap)
    3878                 : {
    3879                 :   // Use basic shrink-wrapping as a default implementation.
    3880               0 :   nsSize result(0xdeadbeef, NS_UNCONSTRAINEDSIZE);
    3881                 : 
    3882                 :   // don't bother setting it if the result won't be used
    3883               0 :   if (GetStylePosition()->mWidth.GetUnit() == eStyleUnit_Auto) {
    3884                 :     nscoord availBased = aAvailableWidth - aMargin.width - aBorder.width -
    3885               0 :                          aPadding.width;
    3886               0 :     result.width = ShrinkWidthToFit(aRenderingContext, availBased);
    3887                 :   }
    3888                 :   return result;
    3889                 : }
    3890                 : 
    3891                 : nscoord
    3892               0 : nsFrame::ShrinkWidthToFit(nsRenderingContext *aRenderingContext,
    3893                 :                           nscoord aWidthInCB)
    3894                 : {
    3895                 :   // If we're a container for font size inflation, then shrink
    3896                 :   // wrapping inside of us should not apply font size inflation.
    3897               0 :   AutoMaybeNullInflationContainer an(this);
    3898                 : 
    3899                 :   nscoord result;
    3900               0 :   nscoord minWidth = GetMinWidth(aRenderingContext);
    3901               0 :   if (minWidth > aWidthInCB) {
    3902               0 :     result = minWidth;
    3903                 :   } else {
    3904               0 :     nscoord prefWidth = GetPrefWidth(aRenderingContext);
    3905               0 :     if (prefWidth > aWidthInCB) {
    3906               0 :       result = aWidthInCB;
    3907                 :     } else {
    3908               0 :       result = prefWidth;
    3909                 :     }
    3910                 :   }
    3911               0 :   return result;
    3912                 : }
    3913                 : 
    3914                 : NS_IMETHODIMP
    3915               0 : nsFrame::WillReflow(nsPresContext* aPresContext)
    3916                 : {
    3917                 : #ifdef DEBUG_dbaron_off
    3918                 :   // bug 81268
    3919                 :   NS_ASSERTION(!(mState & NS_FRAME_IN_REFLOW),
    3920                 :                "nsFrame::WillReflow: frame is already in reflow");
    3921                 : #endif
    3922                 : 
    3923               0 :   NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
    3924                 :                      ("WillReflow: oldState=%x", mState));
    3925               0 :   mState |= NS_FRAME_IN_REFLOW;
    3926               0 :   return NS_OK;
    3927                 : }
    3928                 : 
    3929                 : NS_IMETHODIMP
    3930               0 : nsFrame::DidReflow(nsPresContext*           aPresContext,
    3931                 :                    const nsHTMLReflowState*  aReflowState,
    3932                 :                    nsDidReflowStatus         aStatus)
    3933                 : {
    3934               0 :   NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
    3935                 :                      ("nsFrame::DidReflow: aStatus=%d", aStatus));
    3936                 : 
    3937               0 :   if (NS_FRAME_REFLOW_FINISHED == aStatus) {
    3938                 :     mState &= ~(NS_FRAME_IN_REFLOW | NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY |
    3939               0 :                 NS_FRAME_HAS_DIRTY_CHILDREN);
    3940                 :   }
    3941                 : 
    3942                 :   // Notify the percent height observer if there is a percent height.
    3943                 :   // The observer may be able to initiate another reflow with a computed
    3944                 :   // height. This happens in the case where a table cell has no computed
    3945                 :   // height but can fabricate one when the cell height is known.
    3946               0 :   if (aReflowState && aReflowState->mPercentHeightObserver &&
    3947               0 :       !GetPrevInFlow()) {
    3948               0 :     const nsStyleCoord &height = aReflowState->mStylePosition->mHeight;
    3949               0 :     if (height.HasPercent()) {
    3950               0 :       aReflowState->mPercentHeightObserver->NotifyPercentHeight(*aReflowState);
    3951                 :     }
    3952                 :   }
    3953                 : 
    3954               0 :   return NS_OK;
    3955                 : }
    3956                 : 
    3957                 : void
    3958               0 : nsFrame::FinishReflowWithAbsoluteFrames(nsPresContext*           aPresContext,
    3959                 :                                         nsHTMLReflowMetrics&     aDesiredSize,
    3960                 :                                         const nsHTMLReflowState& aReflowState,
    3961                 :                                         nsReflowStatus&          aStatus,
    3962                 :                                         bool                     aConstrainHeight)
    3963                 : {
    3964               0 :   ReflowAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus, aConstrainHeight);
    3965                 : 
    3966               0 :   FinishAndStoreOverflow(&aDesiredSize);
    3967               0 : }
    3968                 : 
    3969                 : void
    3970               0 : nsFrame::DestroyAbsoluteFrames(nsIFrame* aDestructRoot)
    3971                 : {
    3972               0 :   if (IsAbsoluteContainer()) {
    3973               0 :     GetAbsoluteContainingBlock()->DestroyFrames(this, aDestructRoot);
    3974                 :   }
    3975               0 : }
    3976                 : 
    3977                 : void
    3978               0 : nsFrame::ReflowAbsoluteFrames(nsPresContext*           aPresContext,
    3979                 :                               nsHTMLReflowMetrics&     aDesiredSize,
    3980                 :                               const nsHTMLReflowState& aReflowState,
    3981                 :                               nsReflowStatus&          aStatus,
    3982                 :                               bool                     aConstrainHeight)
    3983                 : {
    3984               0 :   if (HasAbsolutelyPositionedChildren()) {
    3985               0 :     nsAbsoluteContainingBlock* absoluteContainer = GetAbsoluteContainingBlock();
    3986                 : 
    3987                 :     // Let the absolutely positioned container reflow any absolutely positioned
    3988                 :     // child frames that need to be reflowed
    3989                 : 
    3990                 :     // The containing block for the abs pos kids is formed by our padding edge.
    3991                 :     nsMargin computedBorder =
    3992               0 :       aReflowState.mComputedBorderPadding - aReflowState.mComputedPadding;
    3993                 :     nscoord containingBlockWidth =
    3994               0 :       aDesiredSize.width - computedBorder.LeftRight();
    3995                 :     nscoord containingBlockHeight =
    3996               0 :       aDesiredSize.height - computedBorder.TopBottom();
    3997                 : 
    3998               0 :     nsContainerFrame* container = do_QueryFrame(this);
    3999               0 :     NS_ASSERTION(container, "Abs-pos children only supported on container frames for now");
    4000                 : 
    4001                 :     absoluteContainer->Reflow(container, aPresContext, aReflowState, aStatus,
    4002                 :                               containingBlockWidth, containingBlockHeight,
    4003                 :                               aConstrainHeight, true, true, // XXX could be optimized
    4004               0 :                               &aDesiredSize.mOverflowAreas);
    4005                 :   }
    4006               0 : }
    4007                 : 
    4008                 : /* virtual */ bool
    4009               0 : nsFrame::CanContinueTextRun() const
    4010                 : {
    4011                 :   // By default, a frame will *not* allow a text run to be continued
    4012                 :   // through it.
    4013               0 :   return false;
    4014                 : }
    4015                 : 
    4016                 : NS_IMETHODIMP
    4017               0 : nsFrame::Reflow(nsPresContext*          aPresContext,
    4018                 :                 nsHTMLReflowMetrics&     aDesiredSize,
    4019                 :                 const nsHTMLReflowState& aReflowState,
    4020                 :                 nsReflowStatus&          aStatus)
    4021                 : {
    4022               0 :   DO_GLOBAL_REFLOW_COUNT("nsFrame");
    4023               0 :   aDesiredSize.width = 0;
    4024               0 :   aDesiredSize.height = 0;
    4025               0 :   aStatus = NS_FRAME_COMPLETE;
    4026               0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
    4027               0 :   return NS_OK;
    4028                 : }
    4029                 : 
    4030                 : NS_IMETHODIMP
    4031               0 : nsFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo)
    4032                 : {
    4033               0 :   NS_NOTREACHED("should only be called for text frames");
    4034               0 :   return NS_OK;
    4035                 : }
    4036                 : 
    4037                 : NS_IMETHODIMP
    4038               0 : nsFrame::AttributeChanged(PRInt32         aNameSpaceID,
    4039                 :                           nsIAtom*        aAttribute,
    4040                 :                           PRInt32         aModType)
    4041                 : {
    4042               0 :   return NS_OK;
    4043                 : }
    4044                 : 
    4045                 : // Flow member functions
    4046                 : 
    4047                 : nsSplittableType
    4048               0 : nsFrame::GetSplittableType() const
    4049                 : {
    4050               0 :   return NS_FRAME_NOT_SPLITTABLE;
    4051                 : }
    4052                 : 
    4053               0 : nsIFrame* nsFrame::GetPrevContinuation() const
    4054                 : {
    4055               0 :   return nsnull;
    4056                 : }
    4057                 : 
    4058               0 : NS_IMETHODIMP nsFrame::SetPrevContinuation(nsIFrame* aPrevContinuation)
    4059                 : {
    4060                 :   // Ignore harmless requests to set it to NULL
    4061               0 :   if (aPrevContinuation) {
    4062               0 :     NS_ERROR("not splittable");
    4063               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    4064                 :   }
    4065                 :   
    4066               0 :   return NS_OK;
    4067                 : }
    4068                 : 
    4069               0 : nsIFrame* nsFrame::GetNextContinuation() const
    4070                 : {
    4071               0 :   return nsnull;
    4072                 : }
    4073                 : 
    4074               0 : NS_IMETHODIMP nsFrame::SetNextContinuation(nsIFrame*)
    4075                 : {
    4076               0 :   NS_ERROR("not splittable");
    4077               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    4078                 : }
    4079                 : 
    4080               0 : nsIFrame* nsFrame::GetPrevInFlowVirtual() const
    4081                 : {
    4082               0 :   return nsnull;
    4083                 : }
    4084                 : 
    4085               0 : NS_IMETHODIMP nsFrame::SetPrevInFlow(nsIFrame* aPrevInFlow)
    4086                 : {
    4087                 :   // Ignore harmless requests to set it to NULL
    4088               0 :   if (aPrevInFlow) {
    4089               0 :     NS_ERROR("not splittable");
    4090               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    4091                 :   }
    4092                 : 
    4093               0 :   return NS_OK;
    4094                 : }
    4095                 : 
    4096               0 : nsIFrame* nsFrame::GetNextInFlowVirtual() const
    4097                 : {
    4098               0 :   return nsnull;
    4099                 : }
    4100                 : 
    4101               0 : NS_IMETHODIMP nsFrame::SetNextInFlow(nsIFrame*)
    4102                 : {
    4103               0 :   NS_ERROR("not splittable");
    4104               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    4105                 : }
    4106                 : 
    4107               0 : nsIFrame* nsIFrame::GetTailContinuation()
    4108                 : {
    4109               0 :   nsIFrame* frame = this;
    4110               0 :   while (frame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
    4111               0 :     frame = frame->GetPrevContinuation();
    4112               0 :     NS_ASSERTION(frame, "first continuation can't be overflow container");
    4113                 :   }
    4114               0 :   for (nsIFrame* next = frame->GetNextContinuation();
    4115               0 :        next && !(next->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER);
    4116               0 :        next = frame->GetNextContinuation())  {
    4117               0 :     frame = next;
    4118                 :   }
    4119               0 :   NS_POSTCONDITION(frame, "illegal state in continuation chain.");
    4120               0 :   return frame;
    4121                 : }
    4122                 : 
    4123               0 : NS_DECLARE_FRAME_PROPERTY(ViewProperty, nsnull)
    4124                 : 
    4125                 : // Associated view object
    4126                 : nsIView*
    4127               0 : nsIFrame::GetView() const
    4128                 : {
    4129                 :   // Check the frame state bit and see if the frame has a view
    4130               0 :   if (!(GetStateBits() & NS_FRAME_HAS_VIEW))
    4131               0 :     return nsnull;
    4132                 : 
    4133                 :   // Check for a property on the frame
    4134               0 :   void* value = Properties().Get(ViewProperty());
    4135               0 :   NS_ASSERTION(value, "frame state bit was set but frame has no view");
    4136               0 :   return static_cast<nsIView*>(value);
    4137                 : }
    4138                 : 
    4139                 : /* virtual */ nsIView*
    4140               0 : nsIFrame::GetViewExternal() const
    4141                 : {
    4142               0 :   return GetView();
    4143                 : }
    4144                 : 
    4145                 : nsresult
    4146               0 : nsIFrame::SetView(nsIView* aView)
    4147                 : {
    4148               0 :   if (aView) {
    4149               0 :     aView->SetFrame(this);
    4150                 : 
    4151                 :     // Set a property on the frame
    4152               0 :     Properties().Set(ViewProperty(), aView);
    4153                 : 
    4154                 :     // Set the frame state bit that says the frame has a view
    4155               0 :     AddStateBits(NS_FRAME_HAS_VIEW);
    4156                 : 
    4157                 :     // Let all of the ancestors know they have a descendant with a view.
    4158               0 :     for (nsIFrame* f = GetParent();
    4159               0 :          f && !(f->GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW);
    4160                 :          f = f->GetParent())
    4161               0 :       f->AddStateBits(NS_FRAME_HAS_CHILD_WITH_VIEW);
    4162                 :   }
    4163                 : 
    4164               0 :   return NS_OK;
    4165                 : }
    4166                 : 
    4167               0 : nsIFrame* nsIFrame::GetAncestorWithViewExternal() const
    4168                 : {
    4169               0 :   return GetAncestorWithView();
    4170                 : }
    4171                 : 
    4172                 : // Find the first geometric parent that has a view
    4173               0 : nsIFrame* nsIFrame::GetAncestorWithView() const
    4174                 : {
    4175               0 :   for (nsIFrame* f = mParent; nsnull != f; f = f->GetParent()) {
    4176               0 :     if (f->HasView()) {
    4177               0 :       return f;
    4178                 :     }
    4179                 :   }
    4180               0 :   return nsnull;
    4181                 : }
    4182                 : 
    4183                 : // virtual
    4184               0 : nsPoint nsIFrame::GetOffsetToExternal(const nsIFrame* aOther) const
    4185                 : {
    4186               0 :   return GetOffsetTo(aOther);
    4187                 : }
    4188                 : 
    4189               0 : nsPoint nsIFrame::GetOffsetTo(const nsIFrame* aOther) const
    4190                 : {
    4191               0 :   NS_PRECONDITION(aOther,
    4192                 :                   "Must have frame for destination coordinate system!");
    4193                 : 
    4194               0 :   NS_ASSERTION(PresContext() == aOther->PresContext(),
    4195                 :                "GetOffsetTo called on frames in different documents");
    4196                 : 
    4197               0 :   nsPoint offset(0, 0);
    4198                 :   const nsIFrame* f;
    4199               0 :   for (f = this; f != aOther && f; f = f->GetParent()) {
    4200               0 :     offset += f->GetPosition();
    4201                 :   }
    4202                 : 
    4203               0 :   if (f != aOther) {
    4204                 :     // Looks like aOther wasn't an ancestor of |this|.  So now we have
    4205                 :     // the root-frame-relative position of |this| in |offset|.  Convert back
    4206                 :     // to the coordinates of aOther
    4207               0 :     while (aOther) {
    4208               0 :       offset -= aOther->GetPosition();
    4209               0 :       aOther = aOther->GetParent();
    4210                 :     }
    4211                 :   }
    4212                 : 
    4213                 :   return offset;
    4214                 : }
    4215                 : 
    4216               0 : nsPoint nsIFrame::GetOffsetToCrossDoc(const nsIFrame* aOther) const
    4217                 : {
    4218               0 :   return GetOffsetToCrossDoc(aOther, PresContext()->AppUnitsPerDevPixel());
    4219                 : }
    4220                 : 
    4221                 : nsPoint
    4222               0 : nsIFrame::GetOffsetToCrossDoc(const nsIFrame* aOther, const PRInt32 aAPD) const
    4223                 : {
    4224               0 :   NS_PRECONDITION(aOther,
    4225                 :                   "Must have frame for destination coordinate system!");
    4226               0 :   NS_ASSERTION(PresContext()->GetRootPresContext() ==
    4227                 :                  aOther->PresContext()->GetRootPresContext(),
    4228                 :                "trying to get the offset between frames in different document "
    4229                 :                "hierarchies?");
    4230               0 :   if (PresContext()->GetRootPresContext() !=
    4231               0 :         aOther->PresContext()->GetRootPresContext()) {
    4232                 :     // crash right away, we are almost certainly going to crash anyway.
    4233                 :     NS_RUNTIMEABORT("trying to get the offset between frames in different "
    4234               0 :                     "document hierarchies?");
    4235                 :   }
    4236                 : 
    4237               0 :   const nsIFrame* root = nsnull;
    4238                 :   // offset will hold the final offset
    4239                 :   // docOffset holds the currently accumulated offset at the current APD, it
    4240                 :   // will be converted and added to offset when the current APD changes.
    4241               0 :   nsPoint offset(0, 0), docOffset(0, 0);
    4242               0 :   const nsIFrame* f = this;
    4243               0 :   PRInt32 currAPD = PresContext()->AppUnitsPerDevPixel();
    4244               0 :   while (f && f != aOther) {
    4245               0 :     docOffset += f->GetPosition();
    4246               0 :     nsIFrame* parent = f->GetParent();
    4247               0 :     if (parent) {
    4248               0 :       f = parent;
    4249                 :     } else {
    4250               0 :       nsPoint newOffset(0, 0);
    4251               0 :       root = f;
    4252               0 :       f = nsLayoutUtils::GetCrossDocParentFrame(f, &newOffset);
    4253               0 :       PRInt32 newAPD = f ? f->PresContext()->AppUnitsPerDevPixel() : 0;
    4254               0 :       if (!f || newAPD != currAPD) {
    4255                 :         // Convert docOffset to the right APD and add it to offset.
    4256               0 :         offset += docOffset.ConvertAppUnits(currAPD, aAPD);
    4257               0 :         docOffset.x = docOffset.y = 0;
    4258                 :       }
    4259               0 :       currAPD = newAPD;
    4260               0 :       docOffset += newOffset;
    4261                 :     }
    4262                 :   }
    4263               0 :   if (f == aOther) {
    4264               0 :     offset += docOffset.ConvertAppUnits(currAPD, aAPD);
    4265                 :   } else {
    4266                 :     // Looks like aOther wasn't an ancestor of |this|.  So now we have
    4267                 :     // the root-document-relative position of |this| in |offset|. Subtract the
    4268                 :     // root-document-relative position of |aOther| from |offset|.
    4269                 :     // This call won't try to recurse again because root is an ancestor of
    4270                 :     // aOther.
    4271               0 :     nsPoint negOffset = aOther->GetOffsetToCrossDoc(root, aAPD);
    4272               0 :     offset -= negOffset;
    4273                 :   }
    4274                 : 
    4275                 :   return offset;
    4276                 : }
    4277                 : 
    4278                 : // virtual
    4279               0 : nsIntRect nsIFrame::GetScreenRectExternal() const
    4280                 : {
    4281               0 :   return GetScreenRect();
    4282                 : }
    4283                 : 
    4284               0 : nsIntRect nsIFrame::GetScreenRect() const
    4285                 : {
    4286               0 :   return GetScreenRectInAppUnits().ToNearestPixels(PresContext()->AppUnitsPerCSSPixel());
    4287                 : }
    4288                 : 
    4289                 : // virtual
    4290               0 : nsRect nsIFrame::GetScreenRectInAppUnitsExternal() const
    4291                 : {
    4292               0 :   return GetScreenRectInAppUnits();
    4293                 : }
    4294                 : 
    4295               0 : nsRect nsIFrame::GetScreenRectInAppUnits() const
    4296                 : {
    4297               0 :   nsPresContext* presContext = PresContext();
    4298                 :   nsIFrame* rootFrame =
    4299               0 :     presContext->PresShell()->FrameManager()->GetRootFrame();
    4300               0 :   nsPoint rootScreenPos(0, 0);
    4301               0 :   nsPoint rootFrameOffsetInParent(0, 0);
    4302                 :   nsIFrame* rootFrameParent =
    4303               0 :     nsLayoutUtils::GetCrossDocParentFrame(rootFrame, &rootFrameOffsetInParent);
    4304               0 :   if (rootFrameParent) {
    4305               0 :     nsRect parentScreenRectAppUnits = rootFrameParent->GetScreenRectInAppUnits();
    4306               0 :     nsPresContext* parentPresContext = rootFrameParent->PresContext();
    4307               0 :     double parentScale = double(presContext->AppUnitsPerDevPixel())/
    4308               0 :         parentPresContext->AppUnitsPerDevPixel();
    4309               0 :     nsPoint rootPt = parentScreenRectAppUnits.TopLeft() + rootFrameOffsetInParent;
    4310               0 :     rootScreenPos.x = NS_round(parentScale*rootPt.x);
    4311               0 :     rootScreenPos.y = NS_round(parentScale*rootPt.y);
    4312                 :   } else {
    4313               0 :     nsCOMPtr<nsIWidget> rootWidget;
    4314               0 :     presContext->PresShell()->GetViewManager()->GetRootWidget(getter_AddRefs(rootWidget));
    4315               0 :     if (rootWidget) {
    4316               0 :       nsIntPoint rootDevPx = rootWidget->WidgetToScreenOffset();
    4317               0 :       rootScreenPos.x = presContext->DevPixelsToAppUnits(rootDevPx.x);
    4318               0 :       rootScreenPos.y = presContext->DevPixelsToAppUnits(rootDevPx.y);
    4319                 :     }
    4320                 :   }
    4321                 : 
    4322               0 :   return nsRect(rootScreenPos + GetOffsetTo(rootFrame), GetSize());
    4323                 : }
    4324                 : 
    4325                 : // Returns the offset from this frame to the closest geometric parent that
    4326                 : // has a view. Also returns the containing view or null in case of error
    4327               0 : NS_IMETHODIMP nsFrame::GetOffsetFromView(nsPoint&  aOffset,
    4328                 :                                          nsIView** aView) const
    4329                 : {
    4330               0 :   NS_PRECONDITION(nsnull != aView, "null OUT parameter pointer");
    4331               0 :   nsIFrame* frame = (nsIFrame*)this;
    4332                 : 
    4333               0 :   *aView = nsnull;
    4334               0 :   aOffset.MoveTo(0, 0);
    4335               0 :   do {
    4336               0 :     aOffset += frame->GetPosition();
    4337               0 :     frame = frame->GetParent();
    4338               0 :   } while (frame && !frame->HasView());
    4339               0 :   if (frame)
    4340               0 :     *aView = frame->GetView();
    4341               0 :   return NS_OK;
    4342                 : }
    4343                 : 
    4344                 : nsIWidget*
    4345               0 : nsIFrame::GetNearestWidget() const
    4346                 : {
    4347               0 :   return GetClosestView()->GetNearestWidget(nsnull);
    4348                 : }
    4349                 : 
    4350                 : nsIWidget*
    4351               0 : nsIFrame::GetNearestWidget(nsPoint& aOffset) const
    4352                 : {
    4353               0 :   nsPoint offsetToView;
    4354               0 :   nsPoint offsetToWidget;
    4355                 :   nsIWidget* widget =
    4356               0 :     GetClosestView(&offsetToView)->GetNearestWidget(&offsetToWidget);
    4357               0 :   aOffset = offsetToView + offsetToWidget;
    4358               0 :   return widget;
    4359                 : }
    4360                 : 
    4361                 : nsIAtom*
    4362               0 : nsFrame::GetType() const
    4363                 : {
    4364               0 :   return nsnull;
    4365                 : }
    4366                 : 
    4367                 : bool
    4368               0 : nsIFrame::IsLeaf() const
    4369                 : {
    4370               0 :   return true;
    4371                 : }
    4372                 : 
    4373                 : Layer*
    4374               0 : nsIFrame::InvalidateLayer(const nsRect& aDamageRect, PRUint32 aDisplayItemKey)
    4375                 : {
    4376               0 :   NS_ASSERTION(aDisplayItemKey > 0, "Need a key");
    4377                 : 
    4378               0 :   Layer* layer = FrameLayerBuilder::GetDedicatedLayer(this, aDisplayItemKey);
    4379               0 :   if (!layer) {
    4380               0 :     Invalidate(aDamageRect);
    4381               0 :     return nsnull;
    4382                 :   }
    4383                 : 
    4384               0 :   PRUint32 flags = INVALIDATE_NO_THEBES_LAYERS;
    4385               0 :   if (aDisplayItemKey == nsDisplayItem::TYPE_VIDEO ||
    4386                 :       aDisplayItemKey == nsDisplayItem::TYPE_PLUGIN ||
    4387                 :       aDisplayItemKey == nsDisplayItem::TYPE_CANVAS) {
    4388               0 :     flags |= INVALIDATE_NO_UPDATE_LAYER_TREE;
    4389                 :   }
    4390                 : 
    4391               0 :   InvalidateWithFlags(aDamageRect, flags);
    4392               0 :   return layer;
    4393                 : }
    4394                 : 
    4395                 : void
    4396               0 : nsIFrame::InvalidateTransformLayer()
    4397                 : {
    4398               0 :   NS_ASSERTION(mParent, "How can a viewport frame have a transform?");
    4399                 : 
    4400                 :   bool hasLayer =
    4401               0 :       FrameLayerBuilder::GetDedicatedLayer(this, nsDisplayItem::TYPE_TRANSFORM) != nsnull;
    4402                 :   // Invalidate post-transform area in the parent. We have to invalidate
    4403                 :   // in the parent because our transform style may have changed from what was
    4404                 :   // used to paint this frame.
    4405                 :   // It's OK to bypass the SVG effects processing and other processing
    4406                 :   // performed if we called this->InvalidateWithFlags, because those effects
    4407                 :   // are performed before applying transforms.
    4408               0 :   mParent->InvalidateInternal(GetVisualOverflowRect() + GetPosition(),
    4409                 :                               0, 0, this,
    4410               0 :                               hasLayer ? INVALIDATE_NO_THEBES_LAYERS : 0);
    4411               0 : }
    4412                 : 
    4413                 : class LayerActivity {
    4414                 : public:
    4415               0 :   LayerActivity(nsIFrame* aFrame) : mFrame(aFrame), mChangeHint(nsChangeHint(0)) {}
    4416                 :   ~LayerActivity();
    4417               0 :   nsExpirationState* GetExpirationState() { return &mState; }
    4418                 : 
    4419                 :   nsIFrame* mFrame;
    4420                 :   nsExpirationState mState;
    4421                 :   // mChangeHint can be some combination of nsChangeHint_UpdateOpacityLayer and
    4422                 :   // nsChangeHint_UpdateTransformLayer (or neither)
    4423                 :   // The presence of those bits indicates whether opacity or transform
    4424                 :   // changes have been detected.
    4425                 :   nsChangeHint mChangeHint;
    4426                 : };
    4427                 : 
    4428                 : class LayerActivityTracker MOZ_FINAL : public nsExpirationTracker<LayerActivity,4> {
    4429                 : public:
    4430                 :   // 75-100ms is a good timeout period. We use 4 generations of 25ms each.
    4431                 :   enum { GENERATION_MS = 100 };
    4432               0 :   LayerActivityTracker()
    4433               0 :     : nsExpirationTracker<LayerActivity,4>(GENERATION_MS) {}
    4434               0 :   ~LayerActivityTracker() {
    4435               0 :     AgeAllGenerations();
    4436               0 :   }
    4437                 : 
    4438                 :   virtual void NotifyExpired(LayerActivity* aObject);
    4439                 : };
    4440                 : 
    4441                 : static LayerActivityTracker* gLayerActivityTracker = nsnull;
    4442                 : 
    4443               0 : LayerActivity::~LayerActivity()
    4444                 : {
    4445               0 :   if (mFrame) {
    4446               0 :     NS_ASSERTION(gLayerActivityTracker, "Should still have a tracker");
    4447               0 :     gLayerActivityTracker->RemoveObject(this);
    4448                 :   }
    4449               0 : }
    4450                 : 
    4451               0 : static void DestroyLayerActivity(void* aPropertyValue)
    4452                 : {
    4453               0 :   delete static_cast<LayerActivity*>(aPropertyValue);
    4454               0 : }
    4455                 : 
    4456               0 : NS_DECLARE_FRAME_PROPERTY(LayerActivityProperty, DestroyLayerActivity)
    4457                 : 
    4458                 : void
    4459               0 : LayerActivityTracker::NotifyExpired(LayerActivity* aObject)
    4460                 : {
    4461               0 :   RemoveObject(aObject);
    4462                 : 
    4463               0 :   nsIFrame* f = aObject->mFrame;
    4464               0 :   aObject->mFrame = nsnull;
    4465               0 :   f->Properties().Delete(LayerActivityProperty());
    4466               0 :   f->InvalidateFrameSubtree();
    4467               0 : }
    4468                 : 
    4469                 : void
    4470               0 : nsIFrame::MarkLayersActive(nsChangeHint aChangeHint)
    4471                 : {
    4472               0 :   FrameProperties properties = Properties();
    4473                 :   LayerActivity* layerActivity =
    4474               0 :     static_cast<LayerActivity*>(properties.Get(LayerActivityProperty()));
    4475               0 :   if (layerActivity) {
    4476               0 :     gLayerActivityTracker->MarkUsed(layerActivity);
    4477                 :   } else {
    4478               0 :     if (!gLayerActivityTracker) {
    4479               0 :       gLayerActivityTracker = new LayerActivityTracker();
    4480                 :     }
    4481               0 :     layerActivity = new LayerActivity(this);
    4482               0 :     gLayerActivityTracker->AddObject(layerActivity);
    4483               0 :     properties.Set(LayerActivityProperty(), layerActivity);
    4484                 :   }
    4485               0 :   NS_UpdateHint(layerActivity->mChangeHint, aChangeHint);
    4486               0 : }
    4487                 : 
    4488                 : bool
    4489               0 : nsIFrame::AreLayersMarkedActive()
    4490                 : {
    4491               0 :   return Properties().Get(LayerActivityProperty()) != nsnull;
    4492                 : }
    4493                 : 
    4494                 : bool
    4495               0 : nsIFrame::AreLayersMarkedActive(nsChangeHint aChangeHint)
    4496                 : {
    4497                 :   LayerActivity* layerActivity =
    4498               0 :     static_cast<LayerActivity*>(Properties().Get(LayerActivityProperty()));
    4499               0 :   return layerActivity && (layerActivity->mChangeHint & aChangeHint);
    4500                 : }
    4501                 : 
    4502                 : /* static */ void
    4503            1403 : nsFrame::ShutdownLayerActivityTimer()
    4504                 : {
    4505            1403 :   delete gLayerActivityTracker;
    4506            1403 :   gLayerActivityTracker = nsnull;
    4507            1403 : }
    4508                 : 
    4509                 : void
    4510               0 : nsIFrame::InvalidateWithFlags(const nsRect& aDamageRect, PRUint32 aFlags)
    4511                 : {
    4512               0 :   if (aDamageRect.IsEmpty()) {
    4513               0 :     return;
    4514                 :   }
    4515                 : 
    4516                 :   // Don't allow invalidates to do anything when
    4517                 :   // painting is suppressed.
    4518               0 :   nsIPresShell *shell = PresContext()->GetPresShell();
    4519               0 :   if (shell) {
    4520               0 :     if (shell->IsPaintingSuppressed())
    4521               0 :       return;
    4522                 :   }
    4523                 : 
    4524               0 :   InvalidateInternal(aDamageRect, 0, 0, nsnull, aFlags);
    4525                 : }
    4526                 : 
    4527                 : /**
    4528                 :  * Helper function that funnels an InvalidateInternal request up to the
    4529                 :  * parent.  This function is used so that if MOZ_SVG is not defined, we still
    4530                 :  * have unified control paths in the InvalidateInternal chain.
    4531                 :  *
    4532                 :  * @param aDamageRect The rect to invalidate.
    4533                 :  * @param aX The x offset from the origin of this frame to the rectangle.
    4534                 :  * @param aY The y offset from the origin of this frame to the rectangle.
    4535                 :  * @param aImmediate Whether to redraw immediately.
    4536                 :  * @return None, though this funnels the request up to the parent frame.
    4537                 :  */
    4538                 : void
    4539               0 : nsIFrame::InvalidateInternalAfterResize(const nsRect& aDamageRect, nscoord aX,
    4540                 :                                         nscoord aY, PRUint32 aFlags)
    4541                 : {
    4542                 :   /* If we're a transformed frame, then we need to apply our transform to the
    4543                 :    * damage rectangle so that the redraw correctly redraws the transformed
    4544                 :    * region.  We're moved over aX and aY from our origin, but since this aX
    4545                 :    * and aY is contained within our border, we need to scoot back by -aX and
    4546                 :    * -aY to get back to the origin of the transform.
    4547                 :    *
    4548                 :    * There's one more problem, though, and that's that we don't know what
    4549                 :    * coordinate space this rectangle is in.  Sometimes it's in the local
    4550                 :    * coordinate space for the frame, and sometimes its in the transformed
    4551                 :    * coordinate space.  If we get it wrong, we'll display incorrectly.  Until I
    4552                 :    * find a better fix for this problem, we'll invalidate the union of the two
    4553                 :    * rectangles (original rectangle and transformed rectangle).  At least one of
    4554                 :    * these will be correct.
    4555                 :    *
    4556                 :    * When we are preserving-3d, we can have arbitrary hierarchies of preserved 3d
    4557                 :    * children. The computed transform on these children is relative to the root
    4558                 :    * transform object in the hierarchy, not necessarily their direct ancestor.
    4559                 :    * In this case we transform by the child's transform, and mark the rectangle
    4560                 :    * as being transformed until it is passed up to the root of the hierarchy.
    4561                 :    *
    4562                 :    * See bug #452496 for more details.
    4563                 :    */
    4564                 : 
    4565                 :   // Check the transformed flags and remove it
    4566               0 :   bool rectIsTransformed = (aFlags & INVALIDATE_ALREADY_TRANSFORMED);
    4567               0 :   if (!Preserves3D()) {
    4568                 :     // We only want to remove the flag if we aren't preserving 3d. Otherwise
    4569                 :     // the rect will already have been transformed into the root preserve-3d
    4570                 :     // frame coordinate space, and we should continue passing it up without
    4571                 :     // further transforms.
    4572               0 :     aFlags &= ~INVALIDATE_ALREADY_TRANSFORMED;
    4573                 :   }
    4574                 : 
    4575               0 :   if ((mState & NS_FRAME_HAS_CONTAINER_LAYER) &&
    4576               0 :       !(aFlags & INVALIDATE_NO_THEBES_LAYERS)) {
    4577                 :     // XXX for now I'm going to assume this is in the local coordinate space
    4578                 :     // This only matters for frames with transforms and retained layers,
    4579                 :     // which can't happen right now since transforms trigger fallback
    4580                 :     // rendering and the display items that trigger layers are nested inside
    4581                 :     // the nsDisplayTransform
    4582                 :     // XXX need to set INVALIDATE_NO_THEBES_LAYERS for certain kinds of
    4583                 :     // invalidation, e.g. video update, 'opacity' change
    4584                 :     FrameLayerBuilder::InvalidateThebesLayerContents(this,
    4585               0 :         aDamageRect + nsPoint(aX, aY));
    4586                 :     // Don't need to invalidate any more Thebes layers
    4587               0 :     aFlags |= INVALIDATE_NO_THEBES_LAYERS;
    4588               0 :     if (aFlags & INVALIDATE_ONLY_THEBES_LAYERS) {
    4589               0 :       return;
    4590                 :     }
    4591                 :   }
    4592               0 :   if (IsTransformed() && !rectIsTransformed) {
    4593               0 :     nsRect newDamageRect;
    4594                 :     newDamageRect.UnionRect(nsDisplayTransform::TransformRectOut
    4595               0 :                             (aDamageRect, this, nsPoint(-aX, -aY)), aDamageRect);
    4596                 : 
    4597                 :     // If we are preserving 3d, then our computed transform includes that of any
    4598                 :     // ancestor frames that also preserve 3d. Mark the rectangle as already being
    4599                 :     // transformed into the parent's coordinate space.
    4600               0 :     if (Preserves3D()) {
    4601               0 :       aFlags |= INVALIDATE_ALREADY_TRANSFORMED;
    4602                 :     }
    4603                 : 
    4604               0 :     GetParent()->
    4605                 :       InvalidateInternal(newDamageRect, aX + mRect.x, aY + mRect.y, this,
    4606               0 :                          aFlags);
    4607                 :   }
    4608                 :   else 
    4609               0 :     GetParent()->
    4610               0 :       InvalidateInternal(aDamageRect, aX + mRect.x, aY + mRect.y, this, aFlags);
    4611                 : }
    4612                 : 
    4613                 : void
    4614               0 : nsIFrame::InvalidateInternal(const nsRect& aDamageRect, nscoord aX, nscoord aY,
    4615                 :                              nsIFrame* aForChild, PRUint32 aFlags)
    4616                 : {
    4617               0 :   nsSVGEffects::InvalidateDirectRenderingObservers(this);
    4618               0 :   if (nsSVGIntegrationUtils::UsingEffectsForFrame(this)) {
    4619                 :     nsRect r = nsSVGIntegrationUtils::GetInvalidAreaForChangedSource(this,
    4620               0 :             aDamageRect + nsPoint(aX, aY));
    4621                 :     /* Rectangle is now in our own local space, so aX and aY are effectively
    4622                 :      * zero.  Thus we'll pretend that the entire time this was in our own
    4623                 :      * local coordinate space and do any remaining processing.
    4624                 :      */
    4625               0 :     InvalidateInternalAfterResize(r, 0, 0, aFlags);
    4626                 :     return;
    4627                 :   }
    4628                 :   
    4629               0 :   InvalidateInternalAfterResize(aDamageRect, aX, aY, aFlags);
    4630                 : }
    4631                 : 
    4632                 : gfx3DMatrix
    4633               0 : nsIFrame::GetTransformMatrix(nsIFrame* aStopAtAncestor,
    4634                 :                              nsIFrame** aOutAncestor)
    4635                 : {
    4636               0 :   NS_PRECONDITION(aOutAncestor, "Need a place to put the ancestor!");
    4637                 : 
    4638                 :   /* If we're transformed, we want to hand back the combination
    4639                 :    * transform/translate matrix that will apply our current transform, then
    4640                 :    * shift us to our parent.
    4641                 :    */
    4642               0 :   if (IsTransformed()) {
    4643                 :     /* Compute the delta to the parent, which we need because we are converting
    4644                 :      * coordinates to our parent.
    4645                 :      */
    4646               0 :     NS_ASSERTION(nsLayoutUtils::GetCrossDocParentFrame(this),
    4647                 :                      "Cannot transform the viewport frame!");
    4648               0 :     PRInt32 scaleFactor = PresContext()->AppUnitsPerDevPixel();
    4649                 : 
    4650                 :     gfx3DMatrix result =
    4651                 :       nsDisplayTransform::GetResultingTransformMatrix(this, nsPoint(0, 0),
    4652               0 :                                                       scaleFactor, nsnull, aOutAncestor);
    4653               0 :     nsPoint delta = GetOffsetToCrossDoc(*aOutAncestor);
    4654                 :     /* Combine the raw transform with a translation to our parent. */
    4655                 :     result *= gfx3DMatrix::Translation
    4656                 :       (NSAppUnitsToFloatPixels(delta.x, scaleFactor),
    4657                 :        NSAppUnitsToFloatPixels(delta.y, scaleFactor),
    4658               0 :        0.0f);
    4659               0 :     return result;
    4660                 :   }
    4661                 :   
    4662               0 :   *aOutAncestor = nsLayoutUtils::GetCrossDocParentFrame(this);
    4663                 :   
    4664                 :   /* Otherwise, we're not transformed.  In that case, we'll walk up the frame
    4665                 :    * tree until we either hit the root frame or something that may be
    4666                 :    * transformed.  We'll then change coordinates into that frame, since we're
    4667                 :    * guaranteed that nothing in-between can be transformed.  First, however,
    4668                 :    * we have to check to see if we have a parent.  If not, we'll set the
    4669                 :    * outparam to null (indicating that there's nothing left) and will hand back
    4670                 :    * the identity matrix.
    4671                 :    */
    4672               0 :   if (!*aOutAncestor)
    4673               0 :     return gfx3DMatrix();
    4674                 :   
    4675                 :   /* Keep iterating while the frame can't possibly be transformed. */
    4676               0 :   while (!(*aOutAncestor)->IsTransformed() && *aOutAncestor != aStopAtAncestor) {
    4677                 :     /* If no parent, stop iterating.  Otherwise, update the ancestor. */
    4678               0 :     nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(*aOutAncestor);
    4679               0 :     if (!parent)
    4680               0 :       break;
    4681                 : 
    4682               0 :     *aOutAncestor = parent;
    4683                 :   }
    4684                 : 
    4685               0 :   NS_ASSERTION(*aOutAncestor, "Somehow ended up with a null ancestor...?");
    4686                 : 
    4687                 :   /* Translate from this frame to our ancestor, if it exists.  That's the
    4688                 :    * entire transform, so we're done.
    4689                 :    */
    4690               0 :   nsPoint delta = GetOffsetToCrossDoc(*aOutAncestor);
    4691               0 :   PRInt32 scaleFactor = PresContext()->AppUnitsPerDevPixel();
    4692                 :   return gfx3DMatrix().Translation
    4693                 :     (NSAppUnitsToFloatPixels(delta.x, scaleFactor),
    4694                 :      NSAppUnitsToFloatPixels(delta.y, scaleFactor),
    4695               0 :      0.0f);
    4696                 : }
    4697                 : 
    4698                 : void
    4699               0 : nsIFrame::InvalidateRectDifference(const nsRect& aR1, const nsRect& aR2)
    4700                 : {
    4701               0 :   nsRect sizeHStrip, sizeVStrip;
    4702               0 :   nsLayoutUtils::GetRectDifferenceStrips(aR1, aR2, &sizeHStrip, &sizeVStrip);
    4703               0 :   Invalidate(sizeVStrip);
    4704               0 :   Invalidate(sizeHStrip);
    4705               0 : }
    4706                 : 
    4707                 : void
    4708               0 : nsIFrame::InvalidateFrameSubtree()
    4709                 : {
    4710               0 :   Invalidate(GetVisualOverflowRectRelativeToSelf());
    4711               0 :   FrameLayerBuilder::InvalidateThebesLayersInSubtree(this);
    4712               0 : }
    4713                 : 
    4714                 : void
    4715               0 : nsIFrame::InvalidateOverflowRect()
    4716                 : {
    4717               0 :   Invalidate(GetVisualOverflowRectRelativeToSelf());
    4718               0 : }
    4719                 : 
    4720               0 : NS_DECLARE_FRAME_PROPERTY(DeferInvalidatesProperty, nsIFrame::DestroyRegion)
    4721                 : 
    4722                 : void
    4723               0 : nsIFrame::InvalidateRoot(const nsRect& aDamageRect, PRUint32 aFlags)
    4724                 : {
    4725               0 :   NS_ASSERTION(nsLayoutUtils::GetDisplayRootFrame(this) == this,
    4726                 :                "Can only call this on display roots");
    4727                 : 
    4728               0 :   if ((mState & NS_FRAME_HAS_CONTAINER_LAYER) &&
    4729               0 :       !(aFlags & INVALIDATE_NO_THEBES_LAYERS)) {
    4730               0 :     FrameLayerBuilder::InvalidateThebesLayerContents(this, aDamageRect);
    4731               0 :     if (aFlags & INVALIDATE_ONLY_THEBES_LAYERS) {
    4732               0 :       return;
    4733                 :     }
    4734                 :   }
    4735                 : 
    4736               0 :   nsRect rect = aDamageRect;
    4737                 :   nsRegion* excludeRegion = static_cast<nsRegion*>
    4738               0 :     (Properties().Get(DeferInvalidatesProperty()));
    4739               0 :   if (excludeRegion && (aFlags & INVALIDATE_EXCLUDE_CURRENT_PAINT)) {
    4740               0 :     nsRegion r;
    4741               0 :     r.Sub(rect, *excludeRegion);
    4742               0 :     if (r.IsEmpty())
    4743                 :       return;
    4744               0 :     rect = r.GetBounds();
    4745                 :   }
    4746                 : 
    4747               0 :   if (!(aFlags & INVALIDATE_NO_UPDATE_LAYER_TREE)) {
    4748               0 :     AddStateBits(NS_FRAME_UPDATE_LAYER_TREE);
    4749                 :   }
    4750                 : 
    4751               0 :   nsIView* view = GetView();
    4752               0 :   NS_ASSERTION(view, "This can only be called on frames with views");
    4753               0 :   view->GetViewManager()->InvalidateViewNoSuppression(view, rect);
    4754                 : }
    4755                 : 
    4756                 : void
    4757               0 : nsIFrame::BeginDeferringInvalidatesForDisplayRoot(const nsRegion& aExcludeRegion)
    4758                 : {
    4759               0 :   NS_ASSERTION(nsLayoutUtils::GetDisplayRootFrame(this) == this,
    4760                 :                "Can only call this on display roots");
    4761               0 :   Properties().Set(DeferInvalidatesProperty(), new nsRegion(aExcludeRegion));
    4762               0 : }
    4763                 : 
    4764                 : void
    4765               0 : nsIFrame::EndDeferringInvalidatesForDisplayRoot()
    4766                 : {
    4767               0 :   NS_ASSERTION(nsLayoutUtils::GetDisplayRootFrame(this) == this,
    4768                 :                "Can only call this on display roots");
    4769               0 :   Properties().Delete(DeferInvalidatesProperty());
    4770               0 : }
    4771                 : 
    4772                 : /**
    4773                 :  * @param aAnyOutlineOrEffects set to true if this frame has any
    4774                 :  * outline, SVG effects or box shadows that mean we need to invalidate
    4775                 :  * the whole overflow area if the frame's size changes.
    4776                 :  */
    4777                 : static nsRect
    4778               0 : ComputeOutlineAndEffectsRect(nsIFrame* aFrame, bool* aAnyOutlineOrEffects,
    4779                 :                              const nsRect& aOverflowRect,
    4780                 :                              const nsSize& aNewSize,
    4781                 :                              bool aStoreRectProperties) {
    4782               0 :   nsRect r = aOverflowRect;
    4783               0 :   *aAnyOutlineOrEffects = false;
    4784                 : 
    4785                 :   // box-shadow
    4786               0 :   nsCSSShadowArray* boxShadows = aFrame->GetStyleBorder()->mBoxShadow;
    4787               0 :   if (boxShadows) {
    4788               0 :     nsRect shadows;
    4789               0 :     PRInt32 A2D = aFrame->PresContext()->AppUnitsPerDevPixel();
    4790               0 :     for (PRUint32 i = 0; i < boxShadows->Length(); ++i) {
    4791               0 :       nsRect tmpRect(nsPoint(0, 0), aNewSize);
    4792               0 :       nsCSSShadowItem* shadow = boxShadows->ShadowAt(i);
    4793                 : 
    4794                 :       // inset shadows are never painted outside the frame
    4795               0 :       if (shadow->mInset)
    4796               0 :         continue;
    4797                 : 
    4798               0 :       tmpRect.MoveBy(nsPoint(shadow->mXOffset, shadow->mYOffset));
    4799               0 :       tmpRect.Inflate(shadow->mSpread, shadow->mSpread);
    4800                 :       tmpRect.Inflate(
    4801               0 :         nsContextBoxBlur::GetBlurRadiusMargin(shadow->mRadius, A2D));
    4802                 : 
    4803               0 :       shadows.UnionRect(shadows, tmpRect);
    4804                 :     }
    4805               0 :     r.UnionRect(r, shadows);
    4806               0 :     *aAnyOutlineOrEffects = true;
    4807                 :   }
    4808                 : 
    4809               0 :   const nsStyleOutline* outline = aFrame->GetStyleOutline();
    4810               0 :   PRUint8 outlineStyle = outline->GetOutlineStyle();
    4811               0 :   if (outlineStyle != NS_STYLE_BORDER_STYLE_NONE) {
    4812                 :     nscoord width;
    4813                 : #ifdef DEBUG
    4814                 :     bool result = 
    4815                 : #endif
    4816               0 :       outline->GetOutlineWidth(width);
    4817               0 :     NS_ASSERTION(result, "GetOutlineWidth had no cached outline width");
    4818               0 :     if (width > 0) {
    4819               0 :       if (aStoreRectProperties) {
    4820                 :         aFrame->Properties().
    4821               0 :           Set(nsIFrame::OutlineInnerRectProperty(), new nsRect(r));
    4822                 :       }
    4823                 : 
    4824               0 :       nscoord offset = outline->mOutlineOffset;
    4825               0 :       nscoord inflateBy = NS_MAX(width + offset, 0);
    4826                 :       // FIXME (bug 599652): We probably want outline to be drawn around
    4827                 :       // something smaller than the visual overflow rect (perhaps the
    4828                 :       // scrollable overflow rect is correct).  When we change that, we
    4829                 :       // need to keep this code (and the storing of properties just
    4830                 :       // above) in sync with GetOutlineInnerRect in nsCSSRendering.cpp.
    4831               0 :       r.Inflate(inflateBy, inflateBy);
    4832               0 :       *aAnyOutlineOrEffects = true;
    4833                 :     }
    4834                 :   }
    4835                 :   
    4836                 :   // Note that we don't remove the outlineInnerRect if a frame loses outline
    4837                 :   // style. That would require an extra property lookup for every frame,
    4838                 :   // or a new frame state bit to track whether a property had been stored,
    4839                 :   // or something like that. It's not worth doing that here. At most it's
    4840                 :   // only one heap-allocated rect per frame and it will be cleaned up when
    4841                 :   // the frame dies.
    4842                 : 
    4843               0 :   if (nsSVGIntegrationUtils::UsingEffectsForFrame(aFrame)) {
    4844               0 :     *aAnyOutlineOrEffects = true;
    4845               0 :     if (aStoreRectProperties) {
    4846                 :       aFrame->Properties().
    4847               0 :         Set(nsIFrame::PreEffectsBBoxProperty(), new nsRect(r));
    4848                 :     }
    4849               0 :     r = nsSVGIntegrationUtils::ComputeFrameEffectsRect(aFrame, r);
    4850                 :   }
    4851                 : 
    4852                 :   return r;
    4853                 : }
    4854                 : 
    4855                 : nsPoint
    4856               0 : nsIFrame::GetRelativeOffset(const nsStyleDisplay* aDisplay) const
    4857                 : {
    4858               0 :   if (!aDisplay || NS_STYLE_POSITION_RELATIVE == aDisplay->mPosition) {
    4859                 :     nsPoint *offsets = static_cast<nsPoint*>
    4860               0 :       (Properties().Get(ComputedOffsetProperty()));
    4861               0 :     if (offsets) {
    4862               0 :       return *offsets;
    4863                 :     }
    4864                 :   }
    4865               0 :   return nsPoint(0,0);
    4866                 : }
    4867                 : 
    4868                 : nsRect
    4869               0 : nsIFrame::GetOverflowRect(nsOverflowType aType) const
    4870                 : {
    4871               0 :   NS_ABORT_IF_FALSE(aType == eVisualOverflow || aType == eScrollableOverflow,
    4872                 :                     "unexpected type");
    4873                 : 
    4874                 :   // Note that in some cases the overflow area might not have been
    4875                 :   // updated (yet) to reflect any outline set on the frame or the area
    4876                 :   // of child frames. That's OK because any reflow that updates these
    4877                 :   // areas will invalidate the appropriate area, so any (mis)uses of
    4878                 :   // this method will be fixed up.
    4879                 : 
    4880               0 :   if (mOverflow.mType == NS_FRAME_OVERFLOW_LARGE) {
    4881                 :     // there is an overflow rect, and it's not stored as deltas but as
    4882                 :     // a separately-allocated rect
    4883                 :     return static_cast<nsOverflowAreas*>(const_cast<nsIFrame*>(this)->
    4884               0 :              GetOverflowAreasProperty())->Overflow(aType);
    4885                 :   }
    4886                 : 
    4887               0 :   if (aType == eVisualOverflow &&
    4888                 :       mOverflow.mType != NS_FRAME_OVERFLOW_NONE) {
    4889               0 :     return GetVisualOverflowFromDeltas();
    4890                 :   }
    4891                 : 
    4892               0 :   return nsRect(nsPoint(0, 0), GetSize());
    4893                 : }
    4894                 : 
    4895                 : nsOverflowAreas
    4896               0 : nsIFrame::GetOverflowAreas() const
    4897                 : {
    4898               0 :   if (mOverflow.mType == NS_FRAME_OVERFLOW_LARGE) {
    4899                 :     // there is an overflow rect, and it's not stored as deltas but as
    4900                 :     // a separately-allocated rect
    4901               0 :     return *const_cast<nsIFrame*>(this)->GetOverflowAreasProperty();
    4902                 :   }
    4903                 : 
    4904               0 :   return nsOverflowAreas(GetVisualOverflowFromDeltas(),
    4905               0 :                          nsRect(nsPoint(0, 0), GetSize()));
    4906                 : }
    4907                 : 
    4908                 : nsRect
    4909               0 : nsIFrame::GetScrollableOverflowRectRelativeToParent() const
    4910                 : {
    4911               0 :   return GetScrollableOverflowRect() + mRect.TopLeft();
    4912                 : }
    4913                 : 
    4914                 : nsRect
    4915               0 : nsIFrame::GetVisualOverflowRectRelativeToSelf() const
    4916                 : {
    4917               0 :   if (IsTransformed()) {
    4918                 :     nsOverflowAreas* preTransformOverflows = static_cast<nsOverflowAreas*>
    4919               0 :       (Properties().Get(PreTransformOverflowAreasProperty()));
    4920               0 :     if (preTransformOverflows)
    4921               0 :       return preTransformOverflows->VisualOverflow();
    4922                 :   }
    4923               0 :   return GetVisualOverflowRect();
    4924                 : }
    4925                 : 
    4926                 : /* virtual */ bool
    4927               0 : nsFrame::UpdateOverflow()
    4928                 : {
    4929               0 :   nsRect rect(nsPoint(0, 0), GetSize());
    4930               0 :   nsOverflowAreas overflowAreas(rect, rect);
    4931                 : 
    4932               0 :   bool isBox = IsBoxFrame() || IsBoxWrapped();
    4933               0 :   if (!isBox || (!IsCollapsed() && !DoesClipChildren())) {
    4934               0 :     nsLayoutUtils::UnionChildOverflow(this, overflowAreas);
    4935                 :   }
    4936                 : 
    4937               0 :   if (FinishAndStoreOverflow(overflowAreas, GetSize())) {
    4938               0 :     nsIView* view = GetView();
    4939               0 :     if (view) {
    4940               0 :       PRUint32 flags = 0;
    4941               0 :       GetLayoutFlags(flags);
    4942                 : 
    4943               0 :       if ((flags & NS_FRAME_NO_SIZE_VIEW) == 0) {
    4944                 :         // Make sure the frame's view is properly sized.
    4945               0 :         nsIViewManager* vm = view->GetViewManager();
    4946               0 :         vm->ResizeView(view, overflowAreas.VisualOverflow(), true);
    4947                 :       }
    4948                 :     }
    4949                 : 
    4950               0 :     return true;
    4951                 :   }
    4952                 : 
    4953               0 :   return false;
    4954                 : }
    4955                 : 
    4956                 : void
    4957               0 : nsFrame::CheckInvalidateSizeChange(nsHTMLReflowMetrics& aNewDesiredSize)
    4958                 : {
    4959               0 :   nsIFrame::CheckInvalidateSizeChange(mRect, GetVisualOverflowRect(),
    4960               0 :       nsSize(aNewDesiredSize.width, aNewDesiredSize.height));
    4961               0 : }
    4962                 : 
    4963                 : static void
    4964               0 : InvalidateRectForFrameSizeChange(nsIFrame* aFrame, const nsRect& aRect)
    4965                 : {
    4966                 :   nsStyleContext *bgSC;
    4967               0 :   if (!nsCSSRendering::FindBackground(aFrame->PresContext(), aFrame, &bgSC)) {
    4968                 :     nsIFrame* rootFrame =
    4969               0 :       aFrame->PresContext()->PresShell()->FrameManager()->GetRootFrame();
    4970               0 :     rootFrame->Invalidate(nsRect(nsPoint(0, 0), rootFrame->GetSize()));
    4971                 :   }
    4972                 : 
    4973               0 :   aFrame->Invalidate(aRect);
    4974               0 : }
    4975                 : 
    4976                 : void
    4977               0 : nsIFrame::CheckInvalidateSizeChange(const nsRect& aOldRect,
    4978                 :                                     const nsRect& aOldVisualOverflowRect,
    4979                 :                                     const nsSize& aNewDesiredSize)
    4980                 : {
    4981               0 :   if (aNewDesiredSize == aOldRect.Size())
    4982               0 :     return;
    4983                 : 
    4984                 :   // Below, we invalidate the old frame area (or, in the case of
    4985                 :   // outline, combined area) if the outline, border or background
    4986                 :   // settings indicate that something other than the difference
    4987                 :   // between the old and new areas needs to be painted. We are
    4988                 :   // assuming that the difference between the old and new areas will
    4989                 :   // be invalidated by some other means. That also means invalidating
    4990                 :   // the old frame area is the same as invalidating the new frame area
    4991                 :   // (since in either case the UNION of old and new areas will be
    4992                 :   // invalidated)
    4993                 : 
    4994                 :   // We use InvalidateRectForFrameSizeChange throughout this method, even
    4995                 :   // though root-invalidation is technically only needed in the case where
    4996                 :   // layer.RenderingMightDependOnFrameSize().  This allows us to simplify the
    4997                 :   // code somewhat and return immediately after invalidation in the earlier
    4998                 :   // cases.
    4999                 : 
    5000                 :   // Invalidate the entire old frame+outline if the frame has an outline
    5001                 :   bool anyOutlineOrEffects;
    5002                 :   nsRect r = ComputeOutlineAndEffectsRect(this, &anyOutlineOrEffects,
    5003                 :                                           aOldVisualOverflowRect,
    5004                 :                                           aNewDesiredSize,
    5005               0 :                                           false);
    5006               0 :   if (anyOutlineOrEffects) {
    5007               0 :     r.UnionRect(aOldVisualOverflowRect, r);
    5008               0 :     InvalidateRectForFrameSizeChange(this, r);
    5009                 :     return;
    5010                 :   }
    5011                 : 
    5012                 :   // Invalidate the old frame border box if the frame has borders. Those
    5013                 :   // borders may be moving.
    5014               0 :   const nsStyleBorder* border = GetStyleBorder();
    5015               0 :   NS_FOR_CSS_SIDES(side) {
    5016               0 :     if (border->GetActualBorderWidth(side) != 0) {
    5017               0 :       if ((side == NS_SIDE_LEFT || side == NS_SIDE_TOP) &&
    5018               0 :           !nsLayoutUtils::HasNonZeroCornerOnSide(border->mBorderRadius, side) &&
    5019               0 :           !border->GetBorderImage() &&
    5020               0 :           border->GetBorderStyle(side) == NS_STYLE_BORDER_STYLE_SOLID) {
    5021                 :         // We also need to be sure that the bottom-left or top-right
    5022                 :         // corner is simple. For example, if the bottom or right border
    5023                 :         // has a different color, we would need to invalidate the corner
    5024                 :         // area. But that's OK because if there is a right or bottom border,
    5025                 :         // we'll invalidate the entire border-box here anyway.
    5026               0 :         continue;
    5027                 :       }
    5028               0 :       InvalidateRectForFrameSizeChange(this, nsRect(0, 0, aOldRect.width, aOldRect.height));
    5029                 :       return;
    5030                 :     }
    5031                 :   }
    5032                 : 
    5033               0 :   const nsStyleBackground *bg = GetStyleBackground();
    5034               0 :   if (!bg->IsTransparent()) {
    5035                 :     // Invalidate the old frame background if the frame has a background
    5036                 :     // whose position depends on the size of the frame
    5037               0 :     NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
    5038               0 :       const nsStyleBackground::Layer &layer = bg->mLayers[i];
    5039               0 :       if (layer.RenderingMightDependOnFrameSize()) {
    5040               0 :         InvalidateRectForFrameSizeChange(this, nsRect(0, 0, aOldRect.width, aOldRect.height));
    5041                 :         return;
    5042                 :       }
    5043                 :     }
    5044                 : 
    5045                 :     // Invalidate the old frame background if the frame has a background
    5046                 :     // that is being clipped by border-radius, since the old or new area
    5047                 :     // clipped off by the radius is not necessarily in the area that has
    5048                 :     // already been invalidated (even if only the top-left corner has a
    5049                 :     // border radius).
    5050               0 :     if (nsLayoutUtils::HasNonZeroCorner(border->mBorderRadius)) {
    5051               0 :       InvalidateRectForFrameSizeChange(this, nsRect(0, 0, aOldRect.width, aOldRect.height));
    5052                 :       return;
    5053                 :     }
    5054                 :   }
    5055                 : }
    5056                 : 
    5057                 : // Define the MAX_FRAME_DEPTH to be the ContentSink's MAX_REFLOW_DEPTH plus
    5058                 : // 4 for the frames above the document's frames: 
    5059                 : //  the Viewport, GFXScroll, ScrollPort, and Canvas
    5060                 : #define MAX_FRAME_DEPTH (MAX_REFLOW_DEPTH+4)
    5061                 : 
    5062                 : bool
    5063               0 : nsFrame::IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
    5064                 :                             nsHTMLReflowMetrics& aMetrics,
    5065                 :                             nsReflowStatus& aStatus)
    5066                 : {
    5067               0 :   if (aReflowState.mReflowDepth >  MAX_FRAME_DEPTH) {
    5068               0 :     NS_WARNING("frame tree too deep; setting zero size and returning");
    5069               0 :     mState |= NS_FRAME_TOO_DEEP_IN_FRAME_TREE;
    5070               0 :     ClearOverflowRects();
    5071               0 :     aMetrics.width = 0;
    5072               0 :     aMetrics.height = 0;
    5073               0 :     aMetrics.ascent = 0;
    5074               0 :     aMetrics.mCarriedOutBottomMargin.Zero();
    5075               0 :     aMetrics.mOverflowAreas.Clear();
    5076                 : 
    5077               0 :     if (GetNextInFlow()) {
    5078                 :       // Reflow depth might vary between reflows, so we might have
    5079                 :       // successfully reflowed and split this frame before.  If so, we
    5080                 :       // shouldn't delete its continuations.
    5081               0 :       aStatus = NS_FRAME_NOT_COMPLETE;
    5082                 :     } else {
    5083               0 :       aStatus = NS_FRAME_COMPLETE;
    5084                 :     }
    5085                 : 
    5086               0 :     return true;
    5087                 :   }
    5088               0 :   mState &= ~NS_FRAME_TOO_DEEP_IN_FRAME_TREE;
    5089               0 :   return false;
    5090                 : }
    5091                 : 
    5092                 : bool
    5093               0 : nsIFrame::IsBlockWrapper() const
    5094                 : {
    5095               0 :   nsIAtom *pseudoType = GetStyleContext()->GetPseudo();
    5096                 :   return (pseudoType == nsCSSAnonBoxes::mozAnonymousBlock ||
    5097                 :           pseudoType == nsCSSAnonBoxes::mozAnonymousPositionedBlock ||
    5098               0 :           pseudoType == nsCSSAnonBoxes::cellContent);
    5099                 : }
    5100                 : 
    5101                 : static nsIFrame*
    5102               0 : GetNearestBlockContainer(nsIFrame* frame)
    5103                 : {
    5104                 :   // The block wrappers we use to wrap blocks inside inlines aren't
    5105                 :   // described in the CSS spec.  We need to make them not be containing
    5106                 :   // blocks.
    5107                 :   // Since the parent of such a block is either a normal block or
    5108                 :   // another such pseudo, this shouldn't cause anything bad to happen.
    5109                 :   // Also the anonymous blocks inside table cells are not containing blocks.
    5110               0 :   while (frame->IsFrameOfType(nsIFrame::eLineParticipant) ||
    5111               0 :          frame->IsBlockWrapper() ||
    5112                 :          // Table rows are not containing blocks either
    5113               0 :          frame->GetType() == nsGkAtoms::tableRowFrame) {
    5114               0 :     frame = frame->GetParent();
    5115               0 :     NS_ASSERTION(frame, "How come we got to the root frame without seeing a containing block?");
    5116                 :   }
    5117               0 :   return frame;
    5118                 : }
    5119                 : 
    5120                 : nsIFrame*
    5121               0 : nsIFrame::GetContainingBlock() const
    5122                 : {
    5123                 :   // MathML frames might have absolute positioning style, but they would
    5124                 :   // still be in-flow.  So we have to check to make sure that the frame
    5125                 :   // is really out-of-flow too.
    5126               0 :   if (GetStyleDisplay()->IsAbsolutelyPositioned() &&
    5127               0 :       (GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
    5128               0 :     return GetParent(); // the parent is always the containing block
    5129                 :   }
    5130               0 :   return GetNearestBlockContainer(GetParent());
    5131                 : }
    5132                 : 
    5133                 : #ifdef NS_DEBUG
    5134                 : 
    5135               0 : PRInt32 nsFrame::ContentIndexInContainer(const nsIFrame* aFrame)
    5136                 : {
    5137               0 :   PRInt32 result = -1;
    5138                 : 
    5139               0 :   nsIContent* content = aFrame->GetContent();
    5140               0 :   if (content) {
    5141               0 :     nsIContent* parentContent = content->GetParent();
    5142               0 :     if (parentContent) {
    5143               0 :       result = parentContent->IndexOf(content);
    5144                 :     }
    5145                 :   }
    5146                 : 
    5147               0 :   return result;
    5148                 : }
    5149                 : 
    5150                 : /**
    5151                 :  * List a frame tree to stdout. Meant to be called from gdb.
    5152                 :  */
    5153                 : void
    5154               0 : DebugListFrameTree(nsIFrame* aFrame)
    5155                 : {
    5156               0 :   ((nsFrame*)aFrame)->List(stdout, 0);
    5157               0 : }
    5158                 : 
    5159                 : 
    5160                 : // Debugging
    5161                 : NS_IMETHODIMP
    5162               0 : nsFrame::List(FILE* out, PRInt32 aIndent) const
    5163                 : {
    5164               0 :   IndentBy(out, aIndent);
    5165               0 :   ListTag(out);
    5166                 : #ifdef DEBUG_waterson
    5167                 :   fprintf(out, " [parent=%p]", static_cast<void*>(mParent));
    5168                 : #endif
    5169               0 :   if (HasView()) {
    5170               0 :     fprintf(out, " [view=%p]", static_cast<void*>(GetView()));
    5171                 :   }
    5172               0 :   fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height);
    5173               0 :   if (0 != mState) {
    5174               0 :     fprintf(out, " [state=%016llx]", (unsigned long long)mState);
    5175                 :   }
    5176               0 :   nsIFrame* prevInFlow = GetPrevInFlow();
    5177               0 :   nsIFrame* nextInFlow = GetNextInFlow();
    5178               0 :   if (nsnull != prevInFlow) {
    5179               0 :     fprintf(out, " prev-in-flow=%p", static_cast<void*>(prevInFlow));
    5180                 :   }
    5181               0 :   if (nsnull != nextInFlow) {
    5182               0 :     fprintf(out, " next-in-flow=%p", static_cast<void*>(nextInFlow));
    5183                 :   }
    5184               0 :   fprintf(out, " [content=%p]", static_cast<void*>(mContent));
    5185               0 :   nsFrame* f = const_cast<nsFrame*>(this);
    5186               0 :   if (f->HasOverflowAreas()) {
    5187               0 :     nsRect overflowArea = f->GetVisualOverflowRect();
    5188                 :     fprintf(out, " [vis-overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
    5189               0 :             overflowArea.width, overflowArea.height);
    5190               0 :     overflowArea = f->GetScrollableOverflowRect();
    5191                 :     fprintf(out, " [scr-overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
    5192               0 :             overflowArea.width, overflowArea.height);
    5193                 :   }
    5194               0 :   fprintf(out, " [sc=%p]", static_cast<void*>(mStyleContext));
    5195               0 :   fputs("\n", out);
    5196               0 :   return NS_OK;
    5197                 : }
    5198                 : 
    5199                 : NS_IMETHODIMP
    5200               0 : nsFrame::GetFrameName(nsAString& aResult) const
    5201                 : {
    5202               0 :   return MakeFrameName(NS_LITERAL_STRING("Frame"), aResult);
    5203                 : }
    5204                 : 
    5205                 : NS_IMETHODIMP_(nsFrameState)
    5206               0 : nsFrame::GetDebugStateBits() const
    5207                 : {
    5208                 :   // We'll ignore these flags for the purposes of comparing frame state:
    5209                 :   //
    5210                 :   //   NS_FRAME_EXTERNAL_REFERENCE
    5211                 :   //     because this is set by the event state manager or the
    5212                 :   //     caret code when a frame is focused. Depending on whether
    5213                 :   //     or not the regression tests are run as the focused window
    5214                 :   //     will make this value vary randomly.
    5215                 : #define IRRELEVANT_FRAME_STATE_FLAGS NS_FRAME_EXTERNAL_REFERENCE
    5216                 : 
    5217                 : #define FRAME_STATE_MASK (~(IRRELEVANT_FRAME_STATE_FLAGS))
    5218                 : 
    5219               0 :   return GetStateBits() & FRAME_STATE_MASK;
    5220                 : }
    5221                 : 
    5222                 : nsresult
    5223               0 : nsFrame::MakeFrameName(const nsAString& aType, nsAString& aResult) const
    5224                 : {
    5225               0 :   aResult = aType;
    5226               0 :   if (mContent && !mContent->IsNodeOfType(nsINode::eTEXT)) {
    5227               0 :     nsAutoString buf;
    5228               0 :     mContent->Tag()->ToString(buf);
    5229               0 :     aResult.Append(NS_LITERAL_STRING("(") + buf + NS_LITERAL_STRING(")"));
    5230                 :   }
    5231                 :   char buf[40];
    5232               0 :   PR_snprintf(buf, sizeof(buf), "(%d)", ContentIndexInContainer(this));
    5233               0 :   AppendASCIItoUTF16(buf, aResult);
    5234               0 :   return NS_OK;
    5235                 : }
    5236                 : 
    5237                 : void
    5238               0 : nsFrame::XMLQuote(nsString& aString)
    5239                 : {
    5240               0 :   PRInt32 i, len = aString.Length();
    5241               0 :   for (i = 0; i < len; i++) {
    5242               0 :     PRUnichar ch = aString.CharAt(i);
    5243               0 :     if (ch == '<') {
    5244               0 :       nsAutoString tmp(NS_LITERAL_STRING("&lt;"));
    5245               0 :       aString.Cut(i, 1);
    5246               0 :       aString.Insert(tmp, i);
    5247               0 :       len += 3;
    5248               0 :       i += 3;
    5249                 :     }
    5250               0 :     else if (ch == '>') {
    5251               0 :       nsAutoString tmp(NS_LITERAL_STRING("&gt;"));
    5252               0 :       aString.Cut(i, 1);
    5253               0 :       aString.Insert(tmp, i);
    5254               0 :       len += 3;
    5255               0 :       i += 3;
    5256                 :     }
    5257               0 :     else if (ch == '\"') {
    5258               0 :       nsAutoString tmp(NS_LITERAL_STRING("&quot;"));
    5259               0 :       aString.Cut(i, 1);
    5260               0 :       aString.Insert(tmp, i);
    5261               0 :       len += 5;
    5262               0 :       i += 5;
    5263                 :     }
    5264                 :   }
    5265               0 : }
    5266                 : #endif
    5267                 : 
    5268                 : bool
    5269               0 : nsIFrame::IsVisibleForPainting(nsDisplayListBuilder* aBuilder) {
    5270               0 :   if (!GetStyleVisibility()->IsVisible())
    5271               0 :     return false;
    5272               0 :   nsISelection* sel = aBuilder->GetBoundingSelection();
    5273               0 :   return !sel || IsVisibleInSelection(sel);
    5274                 : }
    5275                 : 
    5276                 : bool
    5277               0 : nsIFrame::IsVisibleForPainting() {
    5278               0 :   if (!GetStyleVisibility()->IsVisible())
    5279               0 :     return false;
    5280                 : 
    5281               0 :   nsPresContext* pc = PresContext();
    5282               0 :   if (!pc->IsRenderingOnlySelection())
    5283               0 :     return true;
    5284                 : 
    5285               0 :   nsCOMPtr<nsISelectionController> selcon(do_QueryInterface(pc->PresShell()));
    5286               0 :   if (selcon) {
    5287               0 :     nsCOMPtr<nsISelection> sel;
    5288               0 :     selcon->GetSelection(nsISelectionController::SELECTION_NORMAL,
    5289               0 :                          getter_AddRefs(sel));
    5290               0 :     if (sel)
    5291               0 :       return IsVisibleInSelection(sel);
    5292                 :   }
    5293               0 :   return true;
    5294                 : }
    5295                 : 
    5296                 : bool
    5297               0 : nsIFrame::IsVisibleInSelection(nsDisplayListBuilder* aBuilder) {
    5298               0 :   nsISelection* sel = aBuilder->GetBoundingSelection();
    5299               0 :   return !sel || IsVisibleInSelection(sel);
    5300                 : }
    5301                 : 
    5302                 : bool
    5303               0 : nsIFrame::IsVisibleOrCollapsedForPainting(nsDisplayListBuilder* aBuilder) {
    5304               0 :   if (!GetStyleVisibility()->IsVisibleOrCollapsed())
    5305               0 :     return false;
    5306               0 :   nsISelection* sel = aBuilder->GetBoundingSelection();
    5307               0 :   return !sel || IsVisibleInSelection(sel);
    5308                 : }
    5309                 : 
    5310                 : bool
    5311               0 : nsIFrame::IsVisibleInSelection(nsISelection* aSelection)
    5312                 : {
    5313               0 :   if (!GetContent() || !GetContent()->IsSelectionDescendant()) {
    5314               0 :     return false;
    5315                 :   }
    5316                 :   
    5317               0 :   nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mContent));
    5318                 :   bool vis;
    5319               0 :   nsresult rv = aSelection->ContainsNode(node, true, &vis);
    5320               0 :   return NS_FAILED(rv) || vis;
    5321                 : }
    5322                 : 
    5323                 : /* virtual */ bool
    5324               0 : nsFrame::IsEmpty()
    5325                 : {
    5326               0 :   return false;
    5327                 : }
    5328                 : 
    5329                 : bool
    5330               0 : nsIFrame::CachedIsEmpty()
    5331                 : {
    5332               0 :   NS_PRECONDITION(!(GetStateBits() & NS_FRAME_IS_DIRTY),
    5333                 :                   "Must only be called on reflowed lines");
    5334               0 :   return IsEmpty();
    5335                 : }
    5336                 : 
    5337                 : /* virtual */ bool
    5338               0 : nsFrame::IsSelfEmpty()
    5339                 : {
    5340               0 :   return false;
    5341                 : }
    5342                 : 
    5343                 : NS_IMETHODIMP
    5344               0 : nsFrame::GetSelectionController(nsPresContext *aPresContext, nsISelectionController **aSelCon)
    5345                 : {
    5346               0 :   if (!aPresContext || !aSelCon)
    5347               0 :     return NS_ERROR_INVALID_ARG;
    5348                 : 
    5349               0 :   nsIFrame *frame = this;
    5350               0 :   while (frame && (frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION)) {
    5351               0 :     nsITextControlFrame *tcf = do_QueryFrame(frame);
    5352               0 :     if (tcf) {
    5353               0 :       return tcf->GetOwnedSelectionController(aSelCon);
    5354                 :     }
    5355               0 :     frame = frame->GetParent();
    5356                 :   }
    5357                 : 
    5358               0 :   return CallQueryInterface(aPresContext->GetPresShell(), aSelCon);
    5359                 : }
    5360                 : 
    5361                 : already_AddRefed<nsFrameSelection>
    5362               0 : nsIFrame::GetFrameSelection()
    5363                 : {
    5364                 :   nsFrameSelection* fs =
    5365               0 :     const_cast<nsFrameSelection*>(GetConstFrameSelection());
    5366               0 :   NS_IF_ADDREF(fs);
    5367               0 :   return fs;
    5368                 : }
    5369                 : 
    5370                 : const nsFrameSelection*
    5371               0 : nsIFrame::GetConstFrameSelection() const
    5372                 : {
    5373               0 :   nsIFrame* frame = const_cast<nsIFrame*>(this);
    5374               0 :   while (frame && (frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION)) {
    5375               0 :     nsITextControlFrame* tcf = do_QueryFrame(frame);
    5376               0 :     if (tcf) {
    5377               0 :       return tcf->GetOwnedFrameSelection();
    5378                 :     }
    5379               0 :     frame = frame->GetParent();
    5380                 :   }
    5381                 : 
    5382               0 :   return PresContext()->PresShell()->ConstFrameSelection();
    5383                 : }
    5384                 : 
    5385                 : #ifdef NS_DEBUG
    5386                 : NS_IMETHODIMP
    5387               0 : nsFrame::DumpRegressionData(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent)
    5388                 : {
    5389               0 :   IndentBy(out, aIndent);
    5390               0 :   fprintf(out, "<frame va=\"%ld\" type=\"", PRUptrdiff(this));
    5391               0 :   nsAutoString name;
    5392               0 :   GetFrameName(name);
    5393               0 :   XMLQuote(name);
    5394               0 :   fputs(NS_LossyConvertUTF16toASCII(name).get(), out);
    5395                 :   fprintf(out, "\" state=\"%016llx\" parent=\"%ld\">\n",
    5396               0 :           (unsigned long long)GetDebugStateBits(), PRUptrdiff(mParent));
    5397                 : 
    5398               0 :   aIndent++;
    5399               0 :   DumpBaseRegressionData(aPresContext, out, aIndent);
    5400               0 :   aIndent--;
    5401                 : 
    5402               0 :   IndentBy(out, aIndent);
    5403               0 :   fprintf(out, "</frame>\n");
    5404                 : 
    5405               0 :   return NS_OK;
    5406                 : }
    5407                 : 
    5408                 : void
    5409               0 : nsFrame::DumpBaseRegressionData(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent)
    5410                 : {
    5411               0 :   if (GetNextSibling()) {
    5412               0 :     IndentBy(out, aIndent);
    5413               0 :     fprintf(out, "<next-sibling va=\"%ld\"/>\n", PRUptrdiff(GetNextSibling()));
    5414                 :   }
    5415                 : 
    5416               0 :   if (HasView()) {
    5417               0 :     IndentBy(out, aIndent);
    5418               0 :     fprintf(out, "<view va=\"%ld\">\n", PRUptrdiff(GetView()));
    5419               0 :     aIndent++;
    5420                 :     // XXX add in code to dump out view state too...
    5421               0 :     aIndent--;
    5422               0 :     IndentBy(out, aIndent);
    5423               0 :     fprintf(out, "</view>\n");
    5424                 :   }
    5425                 : 
    5426               0 :   IndentBy(out, aIndent);
    5427                 :   fprintf(out, "<bbox x=\"%d\" y=\"%d\" w=\"%d\" h=\"%d\"/>\n",
    5428               0 :           mRect.x, mRect.y, mRect.width, mRect.height);
    5429                 : 
    5430                 :   // Now dump all of the children on all of the child lists
    5431               0 :   ChildListIterator lists(this);
    5432               0 :   for (; !lists.IsDone(); lists.Next()) {
    5433               0 :     IndentBy(out, aIndent);
    5434               0 :     if (lists.CurrentID() != kPrincipalList) {
    5435               0 :       fprintf(out, "<child-list name=\"%s\">\n", mozilla::layout::ChildListName(lists.CurrentID()));
    5436                 :     }
    5437                 :     else {
    5438               0 :       fprintf(out, "<child-list>\n");
    5439                 :     }
    5440               0 :     aIndent++;
    5441               0 :     nsFrameList::Enumerator childFrames(lists.CurrentList());
    5442               0 :     for (; !childFrames.AtEnd(); childFrames.Next()) {
    5443               0 :       nsIFrame* kid = childFrames.get();
    5444               0 :       kid->DumpRegressionData(aPresContext, out, aIndent);
    5445                 :     }
    5446               0 :     aIndent--;
    5447               0 :     IndentBy(out, aIndent);
    5448               0 :     fprintf(out, "</child-list>\n");
    5449                 :   }
    5450               0 : }
    5451                 : #endif
    5452                 : 
    5453                 : bool
    5454               0 : nsIFrame::IsFrameSelected() const
    5455                 : {
    5456               0 :   NS_ASSERTION(!GetContent() || GetContent()->IsSelectionDescendant(),
    5457                 :                "use the public IsSelected() instead");
    5458               0 :   return nsRange::IsNodeSelected(GetContent(), 0,
    5459               0 :                                  GetContent()->GetChildCount());
    5460                 : }
    5461                 : 
    5462                 : NS_IMETHODIMP
    5463               0 : nsFrame::GetPointFromOffset(PRInt32 inOffset, nsPoint* outPoint)
    5464                 : {
    5465               0 :   NS_PRECONDITION(outPoint != nsnull, "Null parameter");
    5466               0 :   nsRect contentRect = GetContentRect() - GetPosition();
    5467               0 :   nsPoint pt = contentRect.TopLeft();
    5468               0 :   if (mContent)
    5469                 :   {
    5470               0 :     nsIContent* newContent = mContent->GetParent();
    5471               0 :     if (newContent){
    5472               0 :       PRInt32 newOffset = newContent->IndexOf(mContent);
    5473                 : 
    5474               0 :       bool isRTL = (NS_GET_EMBEDDING_LEVEL(this) & 1) == 1;
    5475               0 :       if ((!isRTL && inOffset > newOffset) ||
    5476                 :           (isRTL && inOffset <= newOffset)) {
    5477               0 :         pt = contentRect.TopRight();
    5478                 :       }
    5479                 :     }
    5480                 :   }
    5481               0 :   *outPoint = pt;
    5482               0 :   return NS_OK;
    5483                 : }
    5484                 : 
    5485                 : NS_IMETHODIMP
    5486               0 : nsFrame::GetChildFrameContainingOffset(PRInt32 inContentOffset, bool inHint, PRInt32* outFrameContentOffset, nsIFrame **outChildFrame)
    5487                 : {
    5488               0 :   NS_PRECONDITION(outChildFrame && outFrameContentOffset, "Null parameter");
    5489               0 :   *outFrameContentOffset = (PRInt32)inHint;
    5490                 :   //the best frame to reflect any given offset would be a visible frame if possible
    5491                 :   //i.e. we are looking for a valid frame to place the blinking caret 
    5492               0 :   nsRect rect = GetRect();
    5493               0 :   if (!rect.width || !rect.height)
    5494                 :   {
    5495                 :     //if we have a 0 width or height then lets look for another frame that possibly has
    5496                 :     //the same content.  If we have no frames in flow then just let us return 'this' frame
    5497               0 :     nsIFrame* nextFlow = GetNextInFlow();
    5498               0 :     if (nextFlow)
    5499               0 :       return nextFlow->GetChildFrameContainingOffset(inContentOffset, inHint, outFrameContentOffset, outChildFrame);
    5500                 :   }
    5501               0 :   *outChildFrame = this;
    5502               0 :   return NS_OK;
    5503                 : }
    5504                 : 
    5505                 : //
    5506                 : // What I've pieced together about this routine:
    5507                 : // Starting with a block frame (from which a line frame can be gotten)
    5508                 : // and a line number, drill down and get the first/last selectable
    5509                 : // frame on that line, depending on aPos->mDirection.
    5510                 : // aOutSideLimit != 0 means ignore aLineStart, instead work from
    5511                 : // the end (if > 0) or beginning (if < 0).
    5512                 : //
    5513                 : nsresult
    5514               0 : nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext,
    5515                 :                                         nsPeekOffsetStruct *aPos,
    5516                 :                                         nsIFrame *aBlockFrame, 
    5517                 :                                         PRInt32 aLineStart, 
    5518                 :                                         PRInt8 aOutSideLimit
    5519                 :                                         )
    5520                 : {
    5521                 :   //magic numbers aLineStart will be -1 for end of block 0 will be start of block
    5522               0 :   if (!aBlockFrame || !aPos)
    5523               0 :     return NS_ERROR_NULL_POINTER;
    5524                 : 
    5525               0 :   aPos->mResultFrame = nsnull;
    5526               0 :   aPos->mResultContent = nsnull;
    5527               0 :   aPos->mAttachForward = (aPos->mDirection == eDirNext);
    5528                 : 
    5529               0 :   nsAutoLineIterator it = aBlockFrame->GetLineIterator();
    5530               0 :   if (!it)
    5531               0 :     return NS_ERROR_FAILURE;
    5532               0 :   PRInt32 searchingLine = aLineStart;
    5533               0 :   PRInt32 countLines = it->GetNumLines();
    5534               0 :   if (aOutSideLimit > 0) //start at end
    5535               0 :     searchingLine = countLines;
    5536               0 :   else if (aOutSideLimit <0)//start at beginning
    5537               0 :     searchingLine = -1;//"next" will be 0  
    5538                 :   else 
    5539               0 :     if ((aPos->mDirection == eDirPrevious && searchingLine == 0) || 
    5540                 :        (aPos->mDirection == eDirNext && searchingLine >= (countLines -1) )){
    5541                 :       //we need to jump to new block frame.
    5542               0 :            return NS_ERROR_FAILURE;
    5543                 :     }
    5544                 :   PRInt32 lineFrameCount;
    5545               0 :   nsIFrame *resultFrame = nsnull;
    5546               0 :   nsIFrame *farStoppingFrame = nsnull; //we keep searching until we find a "this" frame then we go to next line
    5547               0 :   nsIFrame *nearStoppingFrame = nsnull; //if we are backing up from edge, stop here
    5548                 :   nsIFrame *firstFrame;
    5549                 :   nsIFrame *lastFrame;
    5550               0 :   nsRect  rect;
    5551                 :   bool isBeforeFirstFrame, isAfterLastFrame;
    5552               0 :   bool found = false;
    5553                 : 
    5554               0 :   nsresult result = NS_OK;
    5555               0 :   while (!found)
    5556                 :   {
    5557               0 :     if (aPos->mDirection == eDirPrevious)
    5558               0 :       searchingLine --;
    5559                 :     else
    5560               0 :       searchingLine ++;
    5561               0 :     if ((aPos->mDirection == eDirPrevious && searchingLine < 0) || 
    5562                 :        (aPos->mDirection == eDirNext && searchingLine >= countLines ))
    5563                 :     {
    5564                 :       //we need to jump to new block frame.
    5565               0 :       return NS_ERROR_FAILURE;
    5566                 :     }
    5567                 :     PRUint32 lineFlags;
    5568               0 :     result = it->GetLine(searchingLine, &firstFrame, &lineFrameCount,
    5569               0 :                          rect, &lineFlags);
    5570               0 :     if (!lineFrameCount) 
    5571               0 :       continue;
    5572               0 :     if (NS_SUCCEEDED(result)){
    5573               0 :       lastFrame = firstFrame;
    5574               0 :       for (;lineFrameCount > 1;lineFrameCount --){
    5575                 :         //result = lastFrame->GetNextSibling(&lastFrame, searchingLine);
    5576               0 :         result = it->GetNextSiblingOnLine(lastFrame, searchingLine);
    5577               0 :         if (NS_FAILED(result) || !lastFrame){
    5578               0 :           NS_ERROR("GetLine promised more frames than could be found");
    5579               0 :           return NS_ERROR_FAILURE;
    5580                 :         }
    5581                 :       }
    5582               0 :       GetLastLeaf(aPresContext, &lastFrame);
    5583                 : 
    5584               0 :       if (aPos->mDirection == eDirNext){
    5585               0 :         nearStoppingFrame = firstFrame;
    5586               0 :         farStoppingFrame = lastFrame;
    5587                 :       }
    5588                 :       else{
    5589               0 :         nearStoppingFrame = lastFrame;
    5590               0 :         farStoppingFrame = firstFrame;
    5591                 :       }
    5592               0 :       nsPoint offset;
    5593                 :       nsIView * view; //used for call of get offset from view
    5594               0 :       aBlockFrame->GetOffsetFromView(offset,&view);
    5595               0 :       nscoord newDesiredX  = aPos->mDesiredX - offset.x;//get desired x into blockframe coordinates!
    5596               0 :       result = it->FindFrameAt(searchingLine, newDesiredX, &resultFrame, &isBeforeFirstFrame, &isAfterLastFrame);
    5597               0 :       if(NS_FAILED(result))
    5598               0 :         continue;
    5599                 :     }
    5600                 : 
    5601               0 :     if (NS_SUCCEEDED(result) && resultFrame)
    5602                 :     {
    5603                 :       //check to see if this is ANOTHER blockframe inside the other one if so then call into its lines
    5604               0 :       nsAutoLineIterator newIt = resultFrame->GetLineIterator();
    5605               0 :       if (newIt)
    5606                 :       {
    5607               0 :         aPos->mResultFrame = resultFrame;
    5608               0 :         return NS_OK;
    5609                 :       }
    5610                 :       //resultFrame is not a block frame
    5611               0 :       result = NS_ERROR_FAILURE;
    5612                 : 
    5613               0 :       nsCOMPtr<nsIFrameEnumerator> frameTraversal;
    5614               0 :       result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
    5615                 :                                     aPresContext, resultFrame,
    5616                 :                                     ePostOrder,
    5617                 :                                     false, // aVisual
    5618                 :                                     aPos->mScrollViewStop,
    5619                 :                                     false     // aFollowOOFs
    5620               0 :                                     );
    5621               0 :       if (NS_FAILED(result))
    5622               0 :         return result;
    5623               0 :       nsIFrame *storeOldResultFrame = resultFrame;
    5624               0 :       while ( !found ){
    5625               0 :         nsPoint point;
    5626               0 :         point.x = aPos->mDesiredX;
    5627                 : 
    5628               0 :         nsRect tempRect = resultFrame->GetRect();
    5629               0 :         nsPoint offset;
    5630                 :         nsIView * view; //used for call of get offset from view
    5631               0 :         result = resultFrame->GetOffsetFromView(offset, &view);
    5632               0 :         if (NS_FAILED(result))
    5633               0 :           return result;
    5634               0 :         point.y = tempRect.height + offset.y;
    5635                 : 
    5636                 :         //special check. if we allow non-text selection then we can allow a hit location to fall before a table. 
    5637                 :         //otherwise there is no way to get and click signal to fall before a table (it being a line iterator itself)
    5638               0 :         nsIPresShell *shell = aPresContext->GetPresShell();
    5639               0 :         if (!shell)
    5640               0 :           return NS_ERROR_FAILURE;
    5641               0 :         PRInt16 isEditor = shell->GetSelectionFlags();
    5642               0 :         isEditor = isEditor == nsISelectionDisplay::DISPLAY_ALL;
    5643               0 :         if ( isEditor )
    5644                 :         {
    5645               0 :           if (resultFrame->GetType() == nsGkAtoms::tableOuterFrame)
    5646                 :           {
    5647               0 :             if (((point.x - offset.x + tempRect.x)<0) ||  ((point.x - offset.x+ tempRect.x)>tempRect.width))//off left/right side
    5648                 :             {
    5649               0 :               nsIContent* content = resultFrame->GetContent();
    5650               0 :               if (content)
    5651                 :               {
    5652               0 :                 nsIContent* parent = content->GetParent();
    5653               0 :                 if (parent)
    5654                 :                 {
    5655               0 :                   aPos->mResultContent = parent;
    5656               0 :                   aPos->mContentOffset = parent->IndexOf(content);
    5657               0 :                   aPos->mAttachForward = false;
    5658               0 :                   if ((point.x - offset.x+ tempRect.x)>tempRect.width)
    5659                 :                   {
    5660               0 :                     aPos->mContentOffset++;//go to end of this frame
    5661               0 :                     aPos->mAttachForward = true;
    5662                 :                   }
    5663                 :                   //result frame is the result frames parent.
    5664               0 :                   aPos->mResultFrame = resultFrame->GetParent();
    5665               0 :                   return NS_POSITION_BEFORE_TABLE;
    5666                 :                 }
    5667                 :               }
    5668                 :             }
    5669                 :           }
    5670                 :         }
    5671                 : 
    5672               0 :         if (!resultFrame->HasView())
    5673                 :         {
    5674                 :           nsIView* view;
    5675               0 :           nsPoint offset;
    5676               0 :           resultFrame->GetOffsetFromView(offset, &view);
    5677                 :           ContentOffsets offsets =
    5678               0 :               resultFrame->GetContentOffsetsFromPoint(point - offset);
    5679               0 :           aPos->mResultContent = offsets.content;
    5680               0 :           aPos->mContentOffset = offsets.offset;
    5681               0 :           aPos->mAttachForward = offsets.associateWithNext;
    5682               0 :           if (offsets.content)
    5683                 :           {
    5684                 :             bool selectable;
    5685               0 :             resultFrame->IsSelectable(&selectable, nsnull);
    5686               0 :             if (selectable)
    5687                 :             {
    5688               0 :               found = true;
    5689                 :               break;
    5690                 :             }
    5691                 :           }
    5692                 :         }
    5693                 : 
    5694               0 :         if (aPos->mDirection == eDirPrevious && (resultFrame == farStoppingFrame))
    5695                 :           break;
    5696               0 :         if (aPos->mDirection == eDirNext && (resultFrame == nearStoppingFrame))
    5697                 :           break;
    5698                 :         //always try previous on THAT line if that fails go the other way
    5699               0 :         frameTraversal->Prev();
    5700               0 :         resultFrame = frameTraversal->CurrentItem();
    5701               0 :         if (!resultFrame)
    5702               0 :           return NS_ERROR_FAILURE;
    5703                 :       }
    5704                 : 
    5705               0 :       if (!found){
    5706               0 :         resultFrame = storeOldResultFrame;
    5707               0 :         result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
    5708                 :                                       aPresContext, resultFrame,
    5709                 :                                       eLeaf,
    5710                 :                                       false, // aVisual
    5711                 :                                       aPos->mScrollViewStop,
    5712                 :                                       false     // aFollowOOFs
    5713               0 :                                       );
    5714                 :       }
    5715               0 :       while ( !found ){
    5716               0 :         nsPoint point(aPos->mDesiredX, 0);
    5717                 :         nsIView* view;
    5718               0 :         nsPoint offset;
    5719               0 :         resultFrame->GetOffsetFromView(offset, &view);
    5720                 :         ContentOffsets offsets =
    5721               0 :             resultFrame->GetContentOffsetsFromPoint(point - offset);
    5722               0 :         aPos->mResultContent = offsets.content;
    5723               0 :         aPos->mContentOffset = offsets.offset;
    5724               0 :         aPos->mAttachForward = offsets.associateWithNext;
    5725               0 :         if (offsets.content)
    5726                 :         {
    5727                 :           bool selectable;
    5728               0 :           resultFrame->IsSelectable(&selectable, nsnull);
    5729               0 :           if (selectable)
    5730                 :           {
    5731               0 :             found = true;
    5732               0 :             if (resultFrame == farStoppingFrame)
    5733               0 :               aPos->mAttachForward = false;
    5734                 :             else
    5735               0 :               aPos->mAttachForward = true;
    5736                 :             break;
    5737                 :           }
    5738                 :         }
    5739               0 :         if (aPos->mDirection == eDirPrevious && (resultFrame == nearStoppingFrame))
    5740                 :           break;
    5741               0 :         if (aPos->mDirection == eDirNext && (resultFrame == farStoppingFrame))
    5742                 :           break;
    5743                 :         //previous didnt work now we try "next"
    5744               0 :         frameTraversal->Next();
    5745               0 :         nsIFrame *tempFrame = frameTraversal->CurrentItem();
    5746               0 :         if (!tempFrame)
    5747                 :           break;
    5748               0 :         resultFrame = tempFrame;
    5749                 :       }
    5750               0 :       aPos->mResultFrame = resultFrame;
    5751                 :     }
    5752                 :     else {
    5753                 :         //we need to jump to new block frame.
    5754               0 :       aPos->mAmount = eSelectLine;
    5755               0 :       aPos->mStartOffset = 0;
    5756               0 :       aPos->mAttachForward = !(aPos->mDirection == eDirNext);
    5757               0 :       if (aPos->mDirection == eDirPrevious)
    5758               0 :         aPos->mStartOffset = -1;//start from end
    5759               0 :      return aBlockFrame->PeekOffset(aPos);
    5760                 :     }
    5761                 :   }
    5762               0 :   return NS_OK;
    5763                 : }
    5764                 : 
    5765               0 : nsPeekOffsetStruct nsIFrame::GetExtremeCaretPosition(bool aStart)
    5766                 : {
    5767               0 :   nsPeekOffsetStruct result;
    5768                 : 
    5769               0 :   FrameTarget targetFrame = DrillDownToSelectionFrame(this, !aStart);
    5770               0 :   FrameContentRange range = GetRangeForFrame(targetFrame.frame);
    5771               0 :   result.mResultContent = range.content;
    5772               0 :   result.mContentOffset = aStart ? range.start : range.end;
    5773               0 :   result.mAttachForward = (result.mContentOffset == range.start);
    5774                 :   return result;
    5775                 : }
    5776                 : 
    5777                 : // Find the first (or last) descendant of the given frame
    5778                 : // which is either a block frame or a BRFrame.
    5779                 : static nsContentAndOffset
    5780               0 : FindBlockFrameOrBR(nsIFrame* aFrame, nsDirection aDirection)
    5781                 : {
    5782                 :   nsContentAndOffset result;
    5783               0 :   result.mContent =  nsnull;
    5784               0 :   result.mOffset = 0;
    5785                 : 
    5786               0 :   if (aFrame->IsGeneratedContentFrame())
    5787               0 :     return result;
    5788                 : 
    5789                 :   // Treat form controls as inline leaves
    5790                 :   // XXX we really need a way to determine whether a frame is inline-level
    5791               0 :   nsIFormControlFrame* fcf = do_QueryFrame(aFrame);
    5792               0 :   if (fcf)
    5793               0 :     return result;
    5794                 :   
    5795                 :   // Check the frame itself
    5796                 :   // Fall through "special" block frames because their mContent is the content
    5797                 :   // of the inline frames they were created from. The first/last child of
    5798                 :   // such frames is the real block frame we're looking for.
    5799               0 :   if ((nsLayoutUtils::GetAsBlock(aFrame) && !(aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL)) ||
    5800               0 :       aFrame->GetType() == nsGkAtoms::brFrame) {
    5801               0 :     nsIContent* content = aFrame->GetContent();
    5802               0 :     result.mContent = content->GetParent();
    5803                 :     // In some cases (bug 310589, bug 370174) we end up here with a null content.
    5804                 :     // This probably shouldn't ever happen, but since it sometimes does, we want
    5805                 :     // to avoid crashing here.
    5806               0 :     NS_ASSERTION(result.mContent, "Unexpected orphan content");
    5807               0 :     if (result.mContent)
    5808               0 :       result.mOffset = result.mContent->IndexOf(content) + 
    5809               0 :         (aDirection == eDirPrevious ? 1 : 0);
    5810               0 :     return result;
    5811                 :   }
    5812                 : 
    5813                 :   // If this is a preformatted text frame, see if it ends with a newline
    5814               0 :   if (aFrame->HasTerminalNewline() &&
    5815               0 :       aFrame->GetStyleContext()->GetStyleText()->NewlineIsSignificant()) {
    5816                 :     PRInt32 startOffset, endOffset;
    5817               0 :     aFrame->GetOffsets(startOffset, endOffset);
    5818               0 :     result.mContent = aFrame->GetContent();
    5819               0 :     result.mOffset = endOffset - (aDirection == eDirPrevious ? 0 : 1);
    5820               0 :     return result;
    5821                 :   }
    5822                 : 
    5823                 :   // Iterate over children and call ourselves recursively
    5824               0 :   if (aDirection == eDirPrevious) {
    5825               0 :     nsIFrame* child = aFrame->GetLastChild(nsIFrame::kPrincipalList);
    5826               0 :     while(child && !result.mContent) {
    5827               0 :       result = FindBlockFrameOrBR(child, aDirection);
    5828               0 :       child = child->GetPrevSibling();
    5829                 :     }
    5830                 :   } else { // eDirNext
    5831               0 :     nsIFrame* child = aFrame->GetFirstPrincipalChild();
    5832               0 :     while(child && !result.mContent) {
    5833               0 :       result = FindBlockFrameOrBR(child, aDirection);
    5834               0 :       child = child->GetNextSibling();
    5835                 :     }
    5836                 :   }
    5837               0 :   return result;
    5838                 : }
    5839                 : 
    5840                 : nsresult
    5841               0 : nsIFrame::PeekOffsetParagraph(nsPeekOffsetStruct *aPos)
    5842                 : {
    5843               0 :   nsIFrame* frame = this;
    5844                 :   nsContentAndOffset blockFrameOrBR;
    5845               0 :   blockFrameOrBR.mContent = nsnull;
    5846               0 :   bool reachedBlockAncestor = false;
    5847                 : 
    5848                 :   // Go through containing frames until reaching a block frame.
    5849                 :   // In each step, search the previous (or next) siblings for the closest
    5850                 :   // "stop frame" (a block frame or a BRFrame).
    5851                 :   // If found, set it to be the selection boundray and abort.
    5852                 :   
    5853               0 :   if (aPos->mDirection == eDirPrevious) {
    5854               0 :     while (!reachedBlockAncestor) {
    5855               0 :       nsIFrame* parent = frame->GetParent();
    5856                 :       // Treat a frame associated with the root content as if it were a block frame.
    5857               0 :       if (!frame->mContent || !frame->mContent->GetParent()) {
    5858               0 :         reachedBlockAncestor = true;
    5859               0 :         break;
    5860                 :       }
    5861               0 :       nsIFrame* sibling = frame->GetPrevSibling();
    5862               0 :       while (sibling && !blockFrameOrBR.mContent) {
    5863               0 :         blockFrameOrBR = FindBlockFrameOrBR(sibling, eDirPrevious);
    5864               0 :         sibling = sibling->GetPrevSibling();
    5865                 :       }
    5866               0 :       if (blockFrameOrBR.mContent) {
    5867               0 :         aPos->mResultContent = blockFrameOrBR.mContent;
    5868               0 :         aPos->mContentOffset = blockFrameOrBR.mOffset;
    5869               0 :         break;
    5870                 :       }
    5871               0 :       frame = parent;
    5872               0 :       reachedBlockAncestor = (nsLayoutUtils::GetAsBlock(frame) != nsnull);
    5873                 :     }
    5874               0 :     if (reachedBlockAncestor) { // no "stop frame" found
    5875               0 :       aPos->mResultContent = frame->GetContent();
    5876               0 :       aPos->mContentOffset = 0;
    5877                 :     }
    5878                 :   } else { // eDirNext
    5879               0 :     while (!reachedBlockAncestor) {
    5880               0 :       nsIFrame* parent = frame->GetParent();
    5881                 :       // Treat a frame associated with the root content as if it were a block frame.
    5882               0 :       if (!frame->mContent || !frame->mContent->GetParent()) {
    5883               0 :         reachedBlockAncestor = true;
    5884               0 :         break;
    5885                 :       }
    5886               0 :       nsIFrame* sibling = frame;
    5887               0 :       while (sibling && !blockFrameOrBR.mContent) {
    5888               0 :         blockFrameOrBR = FindBlockFrameOrBR(sibling, eDirNext);
    5889               0 :         sibling = sibling->GetNextSibling();
    5890                 :       }
    5891               0 :       if (blockFrameOrBR.mContent) {
    5892               0 :         aPos->mResultContent = blockFrameOrBR.mContent;
    5893               0 :         aPos->mContentOffset = blockFrameOrBR.mOffset;
    5894               0 :         break;
    5895                 :       }
    5896               0 :       frame = parent;
    5897               0 :       reachedBlockAncestor = (nsLayoutUtils::GetAsBlock(frame) != nsnull);
    5898                 :     }
    5899               0 :     if (reachedBlockAncestor) { // no "stop frame" found
    5900               0 :       aPos->mResultContent = frame->GetContent();
    5901               0 :       if (aPos->mResultContent)
    5902               0 :         aPos->mContentOffset = aPos->mResultContent->GetChildCount();
    5903                 :     }
    5904                 :   }
    5905               0 :   return NS_OK;
    5906                 : }
    5907                 : 
    5908                 : // Determine movement direction relative to frame
    5909               0 : static bool IsMovingInFrameDirection(nsIFrame* frame, nsDirection aDirection, bool aVisual)
    5910                 : {
    5911                 :   bool isReverseDirection = aVisual ?
    5912               0 :     (NS_GET_EMBEDDING_LEVEL(frame) & 1) != (NS_GET_BASE_LEVEL(frame) & 1) : false;
    5913               0 :   return aDirection == (isReverseDirection ? eDirPrevious : eDirNext);
    5914                 : }
    5915                 : 
    5916                 : NS_IMETHODIMP
    5917               0 : nsIFrame::PeekOffset(nsPeekOffsetStruct* aPos)
    5918                 : {
    5919               0 :   if (!aPos)
    5920               0 :     return NS_ERROR_NULL_POINTER;
    5921               0 :   nsresult result = NS_ERROR_FAILURE;
    5922                 : 
    5923               0 :   if (mState & NS_FRAME_IS_DIRTY)
    5924               0 :     return NS_ERROR_UNEXPECTED;
    5925                 : 
    5926                 :   // Translate content offset to be relative to frame
    5927               0 :   FrameContentRange range = GetRangeForFrame(this);
    5928               0 :   PRInt32 offset = aPos->mStartOffset - range.start;
    5929               0 :   nsIFrame* current = this;
    5930                 :   
    5931               0 :   switch (aPos->mAmount) {
    5932                 :     case eSelectCharacter:
    5933                 :     case eSelectCluster:
    5934                 :     {
    5935               0 :       bool eatingNonRenderableWS = false;
    5936               0 :       bool done = false;
    5937               0 :       bool jumpedLine = false;
    5938                 :       
    5939               0 :       while (!done) {
    5940                 :         bool movingInFrameDirection =
    5941               0 :           IsMovingInFrameDirection(current, aPos->mDirection, aPos->mVisual);
    5942                 : 
    5943               0 :         if (eatingNonRenderableWS)
    5944               0 :           done = current->PeekOffsetNoAmount(movingInFrameDirection, &offset); 
    5945                 :         else
    5946                 :           done = current->PeekOffsetCharacter(movingInFrameDirection, &offset,
    5947               0 :                                               aPos->mAmount == eSelectCluster);
    5948                 : 
    5949               0 :         if (!done) {
    5950                 :           result =
    5951                 :             current->GetFrameFromDirection(aPos->mDirection, aPos->mVisual,
    5952                 :                                            aPos->mJumpLines, aPos->mScrollViewStop,
    5953               0 :                                            &current, &offset, &jumpedLine);
    5954               0 :           if (NS_FAILED(result))
    5955               0 :             return result;
    5956                 : 
    5957                 :           // If we jumped lines, it's as if we found a character, but we still need
    5958                 :           // to eat non-renderable content on the new line.
    5959               0 :           if (jumpedLine)
    5960               0 :             eatingNonRenderableWS = true;
    5961                 :         }
    5962                 :       }
    5963                 : 
    5964                 :       // Set outputs
    5965               0 :       range = GetRangeForFrame(current);
    5966               0 :       aPos->mResultFrame = current;
    5967               0 :       aPos->mResultContent = range.content;
    5968                 :       // Output offset is relative to content, not frame
    5969               0 :       aPos->mContentOffset = offset < 0 ? range.end : range.start + offset;
    5970                 :       // If we're dealing with a text frame and moving backward positions us at
    5971                 :       // the end of that line, decrease the offset by one to make sure that
    5972                 :       // we're placed before the linefeed character on the previous line.
    5973               0 :       if (offset < 0 && jumpedLine &&
    5974                 :           aPos->mDirection == eDirPrevious &&
    5975               0 :           current->GetStyleText()->NewlineIsSignificant() &&
    5976               0 :           current->HasTerminalNewline()) {
    5977               0 :         --aPos->mContentOffset;
    5978                 :       }
    5979                 :       
    5980               0 :       break;
    5981                 :     }
    5982                 :     case eSelectWordNoSpace:
    5983                 :       // eSelectWordNoSpace means that we should not be eating any whitespace when
    5984                 :       // moving to the adjacent word.  This means that we should set aPos->
    5985                 :       // mWordMovementType to eEndWord if we're moving forwards, and to eStartWord
    5986                 :       // if we're moving backwards.
    5987               0 :       if (aPos->mDirection == eDirPrevious) {
    5988               0 :         aPos->mWordMovementType = eStartWord;
    5989                 :       } else {
    5990               0 :         aPos->mWordMovementType = eEndWord;
    5991                 :       }
    5992                 :       // Intentionally fall through the eSelectWord case.
    5993                 :     case eSelectWord:
    5994                 :     {
    5995                 :       // wordSelectEatSpace means "are we looking for a boundary between whitespace
    5996                 :       // and non-whitespace (in the direction we're moving in)".
    5997                 :       // It is true when moving forward and looking for a beginning of a word, or
    5998                 :       // when moving backwards and looking for an end of a word.
    5999                 :       bool wordSelectEatSpace;
    6000               0 :       if (aPos->mWordMovementType != eDefaultBehavior) {
    6001                 :         // aPos->mWordMovementType possible values:
    6002                 :         //       eEndWord: eat the space if we're moving backwards
    6003                 :         //       eStartWord: eat the space if we're moving forwards
    6004               0 :         wordSelectEatSpace = ((aPos->mWordMovementType == eEndWord) == (aPos->mDirection == eDirPrevious));
    6005                 :       }
    6006                 :       else {
    6007                 :         // Use the hidden preference which is based on operating system behavior.
    6008                 :         // This pref only affects whether moving forward by word should go to the end of this word or start of the next word.
    6009                 :         // When going backwards, the start of the word is always used, on every operating system.
    6010                 :         wordSelectEatSpace = aPos->mDirection == eDirNext &&
    6011               0 :           Preferences::GetBool("layout.word_select.eat_space_to_next_word");
    6012                 :       }
    6013                 :       
    6014                 :       // mSawBeforeType means "we already saw characters of the type
    6015                 :       // before the boundary we're looking for". Examples:
    6016                 :       // 1. If we're moving forward, looking for a word beginning (i.e. a boundary
    6017                 :       //    between whitespace and non-whitespace), then eatingWS==true means
    6018                 :       //    "we already saw some whitespace".
    6019                 :       // 2. If we're moving backward, looking for a word beginning (i.e. a boundary
    6020                 :       //    between non-whitespace and whitespace), then eatingWS==true means
    6021                 :       //    "we already saw some non-whitespace".
    6022               0 :       PeekWordState state;
    6023               0 :       PRInt32 offsetAdjustment = 0;
    6024               0 :       bool done = false;
    6025               0 :       while (!done) {
    6026                 :         bool movingInFrameDirection =
    6027               0 :           IsMovingInFrameDirection(current, aPos->mDirection, aPos->mVisual);
    6028                 :         
    6029                 :         done = current->PeekOffsetWord(movingInFrameDirection, wordSelectEatSpace,
    6030               0 :                                        aPos->mIsKeyboardSelect, &offset, &state);
    6031                 :         
    6032               0 :         if (!done) {
    6033                 :           nsIFrame* nextFrame;
    6034                 :           PRInt32 nextFrameOffset;
    6035                 :           bool jumpedLine;
    6036                 :           result =
    6037                 :             current->GetFrameFromDirection(aPos->mDirection, aPos->mVisual,
    6038                 :                                            aPos->mJumpLines, aPos->mScrollViewStop,
    6039               0 :                                            &nextFrame, &nextFrameOffset, &jumpedLine);
    6040                 :           // We can't jump lines if we're looking for whitespace following
    6041                 :           // non-whitespace, and we already encountered non-whitespace.
    6042               0 :           if (NS_FAILED(result) ||
    6043               0 :               (jumpedLine && !wordSelectEatSpace && state.mSawBeforeType)) {
    6044               0 :             done = true;
    6045                 :             // If we've crossed the line boundary, check to make sure that we
    6046                 :             // have not consumed a trailing newline as whitesapce if it's significant.
    6047               0 :             if (jumpedLine && wordSelectEatSpace &&
    6048               0 :                 current->HasTerminalNewline() &&
    6049               0 :                 current->GetStyleText()->NewlineIsSignificant()) {
    6050               0 :               offsetAdjustment = -1;
    6051                 :             }
    6052                 :           } else {
    6053               0 :             if (jumpedLine) {
    6054               0 :               state.mContext.Truncate();
    6055                 :             }
    6056               0 :             current = nextFrame;
    6057               0 :             offset = nextFrameOffset;
    6058                 :             // Jumping a line is equivalent to encountering whitespace
    6059               0 :             if (wordSelectEatSpace && jumpedLine)
    6060               0 :               state.SetSawBeforeType();
    6061                 :           }
    6062                 :         }
    6063                 :       }
    6064                 :       
    6065                 :       // Set outputs
    6066               0 :       range = GetRangeForFrame(current);
    6067               0 :       aPos->mResultFrame = current;
    6068               0 :       aPos->mResultContent = range.content;
    6069                 :       // Output offset is relative to content, not frame
    6070               0 :       aPos->mContentOffset = (offset < 0 ? range.end : range.start + offset) + offsetAdjustment;
    6071                 :       break;
    6072                 :     }
    6073                 :     case eSelectLine :
    6074                 :     {
    6075               0 :       nsAutoLineIterator iter;
    6076               0 :       nsIFrame *blockFrame = this;
    6077                 : 
    6078               0 :       while (NS_FAILED(result)){
    6079               0 :         PRInt32 thisLine = nsFrame::GetLineNumber(blockFrame, aPos->mScrollViewStop, &blockFrame);
    6080               0 :         if (thisLine < 0) 
    6081               0 :           return  NS_ERROR_FAILURE;
    6082               0 :         iter = blockFrame->GetLineIterator();
    6083               0 :         NS_ASSERTION(iter, "GetLineNumber() succeeded but no block frame?");
    6084               0 :         result = NS_OK;
    6085                 : 
    6086               0 :         int edgeCase = 0;//no edge case. this should look at thisLine
    6087                 :         
    6088               0 :         bool doneLooping = false;//tells us when no more block frames hit.
    6089                 :         //this part will find a frame or a block frame. if it's a block frame
    6090                 :         //it will "drill down" to find a viable frame or it will return an error.
    6091               0 :         nsIFrame *lastFrame = this;
    6092               0 :         do {
    6093                 :           result = nsFrame::GetNextPrevLineFromeBlockFrame(PresContext(),
    6094                 :                                                            aPos, 
    6095                 :                                                            blockFrame, 
    6096                 :                                                            thisLine, 
    6097                 :                                                            edgeCase //start from thisLine
    6098               0 :             );
    6099               0 :           if (NS_SUCCEEDED(result) && (!aPos->mResultFrame || aPos->mResultFrame == lastFrame))//we came back to same spot! keep going
    6100                 :           {
    6101               0 :             aPos->mResultFrame = nsnull;
    6102               0 :             if (aPos->mDirection == eDirPrevious)
    6103               0 :               thisLine--;
    6104                 :             else
    6105               0 :               thisLine++;
    6106                 :           }
    6107                 :           else //if failure or success with different frame.
    6108               0 :             doneLooping = true; //do not continue with while loop
    6109                 : 
    6110               0 :           lastFrame = aPos->mResultFrame; //set last frame 
    6111                 : 
    6112               0 :           if (NS_SUCCEEDED(result) && aPos->mResultFrame 
    6113                 :             && blockFrame != aPos->mResultFrame)// make sure block element is not the same as the one we had before
    6114                 :           {
    6115                 : /* SPECIAL CHECK FOR TABLE NAVIGATION
    6116                 :   tables need to navigate also and the frame that supports it is nsTableRowGroupFrame which is INSIDE
    6117                 :   nsTableOuterFrame.  if we have stumbled onto an nsTableOuter we need to drill into nsTableRowGroup
    6118                 :   if we hit a header or footer that's ok just go into them,
    6119                 : */
    6120               0 :             bool searchTableBool = false;
    6121               0 :             if (aPos->mResultFrame->GetType() == nsGkAtoms::tableOuterFrame ||
    6122               0 :                 aPos->mResultFrame->GetType() == nsGkAtoms::tableCellFrame)
    6123                 :             {
    6124               0 :               nsIFrame *frame = aPos->mResultFrame->GetFirstPrincipalChild();
    6125                 :               //got the table frame now
    6126               0 :               while(frame) //ok time to drill down to find iterator
    6127                 :               {
    6128               0 :                 iter = frame->GetLineIterator();
    6129               0 :                 if (iter)
    6130                 :                 {
    6131               0 :                   aPos->mResultFrame = frame;
    6132               0 :                   searchTableBool = true;
    6133               0 :                   result = NS_OK;
    6134               0 :                   break; //while(frame)
    6135                 :                 }
    6136               0 :                 result = NS_ERROR_FAILURE;
    6137               0 :                 frame = frame->GetFirstPrincipalChild();
    6138                 :               }
    6139                 :             }
    6140                 : 
    6141               0 :             if (!searchTableBool) {
    6142               0 :               iter = aPos->mResultFrame->GetLineIterator();
    6143               0 :               result = iter ? NS_OK : NS_ERROR_FAILURE;
    6144                 :             }
    6145               0 :             if (NS_SUCCEEDED(result) && iter)//we've struck another block element!
    6146                 :             {
    6147               0 :               doneLooping = false;
    6148               0 :               if (aPos->mDirection == eDirPrevious)
    6149               0 :                 edgeCase = 1;//far edge, search from end backwards
    6150                 :               else
    6151               0 :                 edgeCase = -1;//near edge search from beginning onwards
    6152               0 :               thisLine=0;//this line means nothing now.
    6153                 :               //everything else means something so keep looking "inside" the block
    6154               0 :               blockFrame = aPos->mResultFrame;
    6155                 : 
    6156                 :             }
    6157                 :             else
    6158                 :             {
    6159               0 :               result = NS_OK;//THIS is to mean that everything is ok to the containing while loop
    6160               0 :               break;
    6161                 :             }
    6162                 :           }
    6163               0 :         } while (!doneLooping);
    6164                 :       }
    6165               0 :       return result;
    6166                 :     }
    6167                 : 
    6168                 :     case eSelectParagraph:
    6169               0 :       return PeekOffsetParagraph(aPos);
    6170                 : 
    6171                 :     case eSelectBeginLine:
    6172                 :     case eSelectEndLine:
    6173                 :     {
    6174                 :       // Adjusted so that the caret can't get confused when content changes
    6175               0 :       nsIFrame* blockFrame = AdjustFrameForSelectionStyles(this);
    6176               0 :       PRInt32 thisLine = nsFrame::GetLineNumber(blockFrame, aPos->mScrollViewStop, &blockFrame);
    6177               0 :       if (thisLine < 0)
    6178               0 :         return NS_ERROR_FAILURE;
    6179               0 :       nsAutoLineIterator it = blockFrame->GetLineIterator();
    6180               0 :       NS_ASSERTION(it, "GetLineNumber() succeeded but no block frame?");
    6181                 : 
    6182                 :       PRInt32 lineFrameCount;
    6183                 :       nsIFrame *firstFrame;
    6184               0 :       nsRect usedRect;
    6185                 :       PRUint32 lineFlags;
    6186               0 :       nsIFrame* baseFrame = nsnull;
    6187               0 :       bool endOfLine = (eSelectEndLine == aPos->mAmount);
    6188                 :       
    6189                 : #ifdef IBMBIDI
    6190               0 :       if (aPos->mVisual && PresContext()->BidiEnabled()) {
    6191               0 :         bool lineIsRTL = it->GetDirection();
    6192                 :         bool isReordered;
    6193                 :         nsIFrame *lastFrame;
    6194               0 :         result = it->CheckLineOrder(thisLine, &isReordered, &firstFrame, &lastFrame);
    6195               0 :         baseFrame = endOfLine ? lastFrame : firstFrame;
    6196               0 :         if (baseFrame) {
    6197               0 :           nsBidiLevel embeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(baseFrame);
    6198                 :           // If the direction of the frame on the edge is opposite to that of the line,
    6199                 :           // we'll need to drill down to its opposite end, so reverse endOfLine.
    6200               0 :           if ((embeddingLevel & 1) == !lineIsRTL)
    6201               0 :             endOfLine = !endOfLine;
    6202                 :         }
    6203                 :       } else
    6204                 : #endif
    6205                 :       {
    6206               0 :         it->GetLine(thisLine, &firstFrame, &lineFrameCount, usedRect, &lineFlags);
    6207                 : 
    6208               0 :         nsIFrame* frame = firstFrame;
    6209               0 :         for (PRInt32 count = lineFrameCount; count;
    6210                 :              --count, frame = frame->GetNextSibling()) {
    6211               0 :           if (!frame->IsGeneratedContentFrame()) {
    6212               0 :             baseFrame = frame;
    6213               0 :             if (!endOfLine)
    6214               0 :               break;
    6215                 :           }
    6216                 :         }
    6217                 :       }
    6218               0 :       if (!baseFrame)
    6219               0 :         return NS_ERROR_FAILURE;
    6220                 :       FrameTarget targetFrame = DrillDownToSelectionFrame(baseFrame,
    6221               0 :                                                           endOfLine);
    6222               0 :       FrameContentRange range = GetRangeForFrame(targetFrame.frame);
    6223               0 :       aPos->mResultContent = range.content;
    6224               0 :       aPos->mContentOffset = endOfLine ? range.end : range.start;
    6225               0 :       if (endOfLine && targetFrame.frame->HasTerminalNewline()) {
    6226                 :         // Do not position the caret after the terminating newline if we're
    6227                 :         // trying to move to the end of line (see bug 596506)
    6228               0 :         --aPos->mContentOffset;
    6229                 :       }
    6230               0 :       aPos->mResultFrame = targetFrame.frame;
    6231               0 :       aPos->mAttachForward = (aPos->mContentOffset == range.start);
    6232               0 :       if (!range.content)
    6233               0 :         return NS_ERROR_FAILURE;
    6234               0 :       return NS_OK;
    6235                 :     }
    6236                 : 
    6237                 :     default: 
    6238                 :     {
    6239               0 :       NS_ASSERTION(false, "Invalid amount");
    6240               0 :       return NS_ERROR_FAILURE;
    6241                 :     }
    6242                 :   }
    6243               0 :   return NS_OK;
    6244                 : }
    6245                 : 
    6246                 : bool
    6247               0 : nsFrame::PeekOffsetNoAmount(bool aForward, PRInt32* aOffset)
    6248                 : {
    6249               0 :   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
    6250                 :   // Sure, we can stop right here.
    6251               0 :   return true;
    6252                 : }
    6253                 : 
    6254                 : bool
    6255               0 : nsFrame::PeekOffsetCharacter(bool aForward, PRInt32* aOffset,
    6256                 :                              bool aRespectClusters)
    6257                 : {
    6258               0 :   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
    6259               0 :   PRInt32 startOffset = *aOffset;
    6260                 :   // A negative offset means "end of frame", which in our case means offset 1.
    6261               0 :   if (startOffset < 0)
    6262               0 :     startOffset = 1;
    6263               0 :   if (aForward == (startOffset == 0)) {
    6264                 :     // We're before the frame and moving forward, or after it and moving backwards:
    6265                 :     // skip to the other side and we're done.
    6266               0 :     *aOffset = 1 - startOffset;
    6267               0 :     return true;
    6268                 :   }
    6269               0 :   return false;
    6270                 : }
    6271                 : 
    6272                 : bool
    6273               0 : nsFrame::PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
    6274                 :                         PRInt32* aOffset, PeekWordState* aState)
    6275                 : {
    6276               0 :   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
    6277               0 :   PRInt32 startOffset = *aOffset;
    6278                 :   // This isn't text, so truncate the context
    6279               0 :   aState->mContext.Truncate();
    6280               0 :   if (startOffset < 0)
    6281               0 :     startOffset = 1;
    6282               0 :   if (aForward == (startOffset == 0)) {
    6283                 :     // We're before the frame and moving forward, or after it and moving backwards.
    6284                 :     // If we're looking for non-whitespace, we found it (without skipping this frame).
    6285               0 :     if (!aState->mAtStart) {
    6286               0 :       if (aState->mLastCharWasPunctuation) {
    6287                 :         // We're not punctuation, so this is a punctuation boundary.
    6288               0 :         if (BreakWordBetweenPunctuation(aState, aForward, false, false, aIsKeyboardSelect))
    6289               0 :           return true;
    6290                 :       } else {
    6291                 :         // This is not a punctuation boundary.
    6292               0 :         if (aWordSelectEatSpace && aState->mSawBeforeType)
    6293               0 :           return true;
    6294                 :       }
    6295                 :     }
    6296                 :     // Otherwise skip to the other side and note that we encountered non-whitespace.
    6297               0 :     *aOffset = 1 - startOffset;
    6298                 :     aState->Update(false, // not punctuation
    6299                 :                    false     // not whitespace
    6300               0 :                    );
    6301               0 :     if (!aWordSelectEatSpace)
    6302               0 :       aState->SetSawBeforeType();
    6303                 :   }
    6304               0 :   return false;
    6305                 : }
    6306                 : 
    6307                 : bool
    6308               0 : nsFrame::BreakWordBetweenPunctuation(const PeekWordState* aState,
    6309                 :                                      bool aForward,
    6310                 :                                      bool aPunctAfter, bool aWhitespaceAfter,
    6311                 :                                      bool aIsKeyboardSelect)
    6312                 : {
    6313               0 :   NS_ASSERTION(aPunctAfter != aState->mLastCharWasPunctuation,
    6314                 :                "Call this only at punctuation boundaries");
    6315               0 :   if (aState->mLastCharWasWhitespace) {
    6316                 :     // We always stop between whitespace and punctuation
    6317               0 :     return true;
    6318                 :   }
    6319               0 :   if (!Preferences::GetBool("layout.word_select.stop_at_punctuation")) {
    6320                 :     // When this pref is false, we never stop at a punctuation boundary unless
    6321                 :     // it's after whitespace
    6322               0 :     return false;
    6323                 :   }
    6324               0 :   if (!aIsKeyboardSelect) {
    6325                 :     // mouse caret movement (e.g. word selection) always stops at every punctuation boundary
    6326               0 :     return true;
    6327                 :   }
    6328               0 :   bool afterPunct = aForward ? aState->mLastCharWasPunctuation : aPunctAfter;
    6329               0 :   if (!afterPunct) {
    6330                 :     // keyboard caret movement only stops after punctuation (in content order)
    6331               0 :     return false;
    6332                 :   }
    6333                 :   // Stop only if we've seen some non-punctuation since the last whitespace;
    6334                 :   // don't stop after punctuation that follows whitespace.
    6335               0 :   return aState->mSeenNonPunctuationSinceWhitespace;
    6336                 : }
    6337                 : 
    6338                 : NS_IMETHODIMP
    6339               0 : nsFrame::CheckVisibility(nsPresContext* , PRInt32 , PRInt32 , bool , bool *, bool *)
    6340                 : {
    6341               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    6342                 : }
    6343                 : 
    6344                 : 
    6345                 : PRInt32
    6346               0 : nsFrame::GetLineNumber(nsIFrame *aFrame, bool aLockScroll, nsIFrame** aContainingBlock)
    6347                 : {
    6348               0 :   NS_ASSERTION(aFrame, "null aFrame");
    6349               0 :   nsFrameManager* frameManager = aFrame->PresContext()->FrameManager();
    6350               0 :   nsIFrame *blockFrame = aFrame;
    6351                 :   nsIFrame *thisBlock;
    6352               0 :   nsAutoLineIterator it;
    6353               0 :   nsresult result = NS_ERROR_FAILURE;
    6354               0 :   while (NS_FAILED(result) && blockFrame)
    6355                 :   {
    6356               0 :     thisBlock = blockFrame;
    6357               0 :     if (thisBlock->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    6358                 :       //if we are searching for a frame that is not in flow we will not find it. 
    6359                 :       //we must instead look for its placeholder
    6360               0 :       if (thisBlock->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
    6361                 :         // abspos continuations don't have placeholders, get the fif
    6362               0 :         thisBlock = thisBlock->GetFirstInFlow();
    6363                 :       }
    6364               0 :       thisBlock = frameManager->GetPlaceholderFrameFor(thisBlock);
    6365               0 :       if (!thisBlock)
    6366               0 :         return -1;
    6367                 :     }  
    6368               0 :     blockFrame = thisBlock->GetParent();
    6369               0 :     result = NS_OK;
    6370               0 :     if (blockFrame) {
    6371               0 :       if (aLockScroll && blockFrame->GetType() == nsGkAtoms::scrollFrame)
    6372               0 :         return -1;
    6373               0 :       it = blockFrame->GetLineIterator();
    6374               0 :       if (!it)
    6375               0 :         result = NS_ERROR_FAILURE;
    6376                 :     }
    6377                 :   }
    6378               0 :   if (!blockFrame || !it)
    6379               0 :     return -1;
    6380                 : 
    6381               0 :   if (aContainingBlock)
    6382               0 :     *aContainingBlock = blockFrame;
    6383               0 :   return it->FindLineContaining(thisBlock);
    6384                 : }
    6385                 : 
    6386                 : nsresult
    6387               0 : nsIFrame::GetFrameFromDirection(nsDirection aDirection, bool aVisual,
    6388                 :                                 bool aJumpLines, bool aScrollViewStop, 
    6389                 :                                 nsIFrame** aOutFrame, PRInt32* aOutOffset, bool* aOutJumpedLine)
    6390                 : {
    6391                 :   nsresult result;
    6392                 : 
    6393               0 :   if (!aOutFrame || !aOutOffset || !aOutJumpedLine)
    6394               0 :     return NS_ERROR_NULL_POINTER;
    6395                 :   
    6396               0 :   nsPresContext* presContext = PresContext();
    6397               0 :   *aOutFrame = nsnull;
    6398               0 :   *aOutOffset = 0;
    6399               0 :   *aOutJumpedLine = false;
    6400                 : 
    6401                 :   // Find the prev/next selectable frame
    6402               0 :   bool selectable = false;
    6403               0 :   nsIFrame *traversedFrame = this;
    6404               0 :   while (!selectable) {
    6405                 :     nsIFrame *blockFrame;
    6406                 :     
    6407               0 :     PRInt32 thisLine = nsFrame::GetLineNumber(traversedFrame, aScrollViewStop, &blockFrame);
    6408               0 :     if (thisLine < 0)
    6409               0 :       return NS_ERROR_FAILURE;
    6410                 : 
    6411               0 :     nsAutoLineIterator it = blockFrame->GetLineIterator();
    6412               0 :     NS_ASSERTION(it, "GetLineNumber() succeeded but no block frame?");
    6413                 : 
    6414                 :     bool atLineEdge;
    6415                 :     nsIFrame *firstFrame;
    6416                 :     nsIFrame *lastFrame;
    6417                 : #ifdef IBMBIDI
    6418               0 :     if (aVisual && presContext->BidiEnabled()) {
    6419               0 :       bool lineIsRTL = it->GetDirection();
    6420                 :       bool isReordered;
    6421               0 :       result = it->CheckLineOrder(thisLine, &isReordered, &firstFrame, &lastFrame);
    6422               0 :       nsIFrame** framePtr = aDirection == eDirPrevious ? &firstFrame : &lastFrame;
    6423               0 :       if (*framePtr) {
    6424               0 :         nsBidiLevel embeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(*framePtr);
    6425               0 :         if ((((embeddingLevel & 1) && lineIsRTL) || (!(embeddingLevel & 1) && !lineIsRTL)) ==
    6426                 :             (aDirection == eDirPrevious)) {
    6427               0 :           nsFrame::GetFirstLeaf(presContext, framePtr);
    6428                 :         } else {
    6429               0 :           nsFrame::GetLastLeaf(presContext, framePtr);
    6430                 :         }
    6431               0 :         atLineEdge = *framePtr == traversedFrame;
    6432                 :       } else {
    6433               0 :         atLineEdge = true;
    6434                 :       }
    6435                 :     } else
    6436                 : #endif
    6437                 :     {
    6438               0 :       nsRect  nonUsedRect;
    6439                 :       PRInt32 lineFrameCount;
    6440                 :       PRUint32 lineFlags;
    6441               0 :       result = it->GetLine(thisLine, &firstFrame, &lineFrameCount,nonUsedRect,
    6442               0 :                            &lineFlags);
    6443               0 :       if (NS_FAILED(result))
    6444               0 :         return result;
    6445                 : 
    6446               0 :       if (aDirection == eDirPrevious) {
    6447               0 :         nsFrame::GetFirstLeaf(presContext, &firstFrame);
    6448               0 :         atLineEdge = firstFrame == traversedFrame;
    6449                 :       } else { // eDirNext
    6450               0 :         lastFrame = firstFrame;
    6451               0 :         for (;lineFrameCount > 1;lineFrameCount --){
    6452               0 :           result = it->GetNextSiblingOnLine(lastFrame, thisLine);
    6453               0 :           if (NS_FAILED(result) || !lastFrame){
    6454               0 :             NS_ERROR("should not be reached nsFrame");
    6455               0 :             return NS_ERROR_FAILURE;
    6456                 :           }
    6457                 :         }
    6458               0 :         nsFrame::GetLastLeaf(presContext, &lastFrame);
    6459               0 :         atLineEdge = lastFrame == traversedFrame;
    6460                 :       }
    6461                 :     }
    6462                 : 
    6463               0 :     if (atLineEdge) {
    6464               0 :       *aOutJumpedLine = true;
    6465               0 :       if (!aJumpLines)
    6466               0 :         return NS_ERROR_FAILURE; //we are done. cannot jump lines
    6467                 :     }
    6468                 : 
    6469               0 :     nsCOMPtr<nsIFrameEnumerator> frameTraversal;
    6470               0 :     result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
    6471                 :                                   presContext, traversedFrame,
    6472                 :                                   eLeaf,
    6473               0 :                                   aVisual && presContext->BidiEnabled(),
    6474                 :                                   aScrollViewStop,
    6475                 :                                   true     // aFollowOOFs
    6476               0 :                                   );
    6477               0 :     if (NS_FAILED(result))
    6478               0 :       return result;
    6479                 : 
    6480               0 :     if (aDirection == eDirNext)
    6481               0 :       frameTraversal->Next();
    6482                 :     else
    6483               0 :       frameTraversal->Prev();
    6484                 : 
    6485               0 :     traversedFrame = frameTraversal->CurrentItem();
    6486               0 :     if (!traversedFrame)
    6487               0 :       return NS_ERROR_FAILURE;
    6488               0 :     traversedFrame->IsSelectable(&selectable, nsnull);
    6489                 :   } // while (!selectable)
    6490                 : 
    6491               0 :   *aOutOffset = (aDirection == eDirNext) ? 0 : -1;
    6492                 : 
    6493                 : #ifdef IBMBIDI
    6494               0 :   if (aVisual) {
    6495               0 :     PRUint8 newLevel = NS_GET_EMBEDDING_LEVEL(traversedFrame);
    6496               0 :     PRUint8 newBaseLevel = NS_GET_BASE_LEVEL(traversedFrame);
    6497               0 :     if ((newLevel & 1) != (newBaseLevel & 1)) // The new frame is reverse-direction, go to the other end
    6498               0 :       *aOutOffset = -1 - *aOutOffset;
    6499                 :   }
    6500                 : #endif
    6501               0 :   *aOutFrame = traversedFrame;
    6502               0 :   return NS_OK;
    6503                 : }
    6504                 : 
    6505               0 : nsIView* nsIFrame::GetClosestView(nsPoint* aOffset) const
    6506                 : {
    6507               0 :   nsPoint offset(0,0);
    6508               0 :   for (const nsIFrame *f = this; f; f = f->GetParent()) {
    6509               0 :     if (f->HasView()) {
    6510               0 :       if (aOffset)
    6511               0 :         *aOffset = offset;
    6512               0 :       return f->GetView();
    6513                 :     }
    6514               0 :     offset += f->GetPosition();
    6515                 :   }
    6516                 : 
    6517               0 :   NS_NOTREACHED("No view on any parent?  How did that happen?");
    6518               0 :   return nsnull;
    6519                 : }
    6520                 : 
    6521                 : 
    6522                 : /* virtual */ void
    6523               0 : nsFrame::ChildIsDirty(nsIFrame* aChild)
    6524                 : {
    6525                 :   NS_NOTREACHED("should never be called on a frame that doesn't inherit from "
    6526               0 :                 "nsContainerFrame");
    6527               0 : }
    6528                 : 
    6529                 : 
    6530                 : #ifdef ACCESSIBILITY
    6531                 : already_AddRefed<nsAccessible>
    6532               0 : nsFrame::CreateAccessible()
    6533                 : {
    6534               0 :   return nsnull;
    6535                 : }
    6536                 : #endif
    6537                 : 
    6538               0 : NS_DECLARE_FRAME_PROPERTY(OverflowAreasProperty,
    6539                 :                           nsIFrame::DestroyOverflowAreas)
    6540                 : 
    6541                 : bool
    6542               0 : nsIFrame::ClearOverflowRects()
    6543                 : {
    6544               0 :   if (mOverflow.mType == NS_FRAME_OVERFLOW_NONE) {
    6545               0 :     return false;
    6546                 :   }
    6547               0 :   if (mOverflow.mType == NS_FRAME_OVERFLOW_LARGE) {
    6548               0 :     Properties().Delete(OverflowAreasProperty());
    6549                 :   }
    6550               0 :   mOverflow.mType = NS_FRAME_OVERFLOW_NONE;
    6551               0 :   return true;
    6552                 : }
    6553                 : 
    6554                 : /** Create or retrieve the previously stored overflow area, if the frame does 
    6555                 :  * not overflow and no creation is required return nsnull.
    6556                 :  * @return pointer to the overflow area rectangle 
    6557                 :  */
    6558                 : nsOverflowAreas*
    6559               0 : nsIFrame::GetOverflowAreasProperty()
    6560                 : {
    6561               0 :   FrameProperties props = Properties();
    6562                 :   nsOverflowAreas *overflow =
    6563               0 :     static_cast<nsOverflowAreas*>(props.Get(OverflowAreasProperty()));
    6564                 : 
    6565               0 :   if (overflow) {
    6566               0 :     return overflow; // the property already exists
    6567                 :   }
    6568                 : 
    6569                 :   // The property isn't set yet, so allocate a new rect, set the property,
    6570                 :   // and return the newly allocated rect
    6571               0 :   overflow = new nsOverflowAreas;
    6572               0 :   props.Set(OverflowAreasProperty(), overflow);
    6573               0 :   return overflow;
    6574                 : }
    6575                 : 
    6576                 : /** Set the overflowArea rect, storing it as deltas or a separate rect
    6577                 :  * depending on its size in relation to the primary frame rect.
    6578                 :  */
    6579                 : bool
    6580               0 : nsIFrame::SetOverflowAreas(const nsOverflowAreas& aOverflowAreas)
    6581                 : {
    6582               0 :   if (mOverflow.mType == NS_FRAME_OVERFLOW_LARGE) {
    6583                 :     nsOverflowAreas *overflow =
    6584               0 :       static_cast<nsOverflowAreas*>(Properties().Get(OverflowAreasProperty()));
    6585               0 :     bool changed = *overflow != aOverflowAreas;
    6586               0 :     *overflow = aOverflowAreas;
    6587                 : 
    6588                 :     // Don't bother with converting to the deltas form if we already
    6589                 :     // have a property.
    6590               0 :     return changed;
    6591                 :   }
    6592                 : 
    6593               0 :   const nsRect& vis = aOverflowAreas.VisualOverflow();
    6594               0 :   PRUint32 l = -vis.x, // left edge: positive delta is leftwards
    6595               0 :            t = -vis.y, // top: positive is upwards
    6596               0 :            r = vis.XMost() - mRect.width, // right: positive is rightwards
    6597               0 :            b = vis.YMost() - mRect.height; // bottom: positive is downwards
    6598               0 :   if (aOverflowAreas.ScrollableOverflow().IsEqualEdges(nsRect(nsPoint(0, 0), GetSize())) &&
    6599                 :       l <= NS_FRAME_OVERFLOW_DELTA_MAX &&
    6600                 :       t <= NS_FRAME_OVERFLOW_DELTA_MAX &&
    6601                 :       r <= NS_FRAME_OVERFLOW_DELTA_MAX &&
    6602                 :       b <= NS_FRAME_OVERFLOW_DELTA_MAX &&
    6603                 :       // we have to check these against zero because we *never* want to
    6604                 :       // set a frame as having no overflow in this function.  This is
    6605                 :       // because FinishAndStoreOverflow calls this function prior to
    6606                 :       // SetRect based on whether the overflow areas match aNewSize.
    6607                 :       // In the case where the overflow areas exactly match mRect but
    6608                 :       // do not match aNewSize, we need to store overflow in a property
    6609                 :       // so that our eventual SetRect/SetSize will know that it has to
    6610                 :       // reset our overflow areas.
    6611                 :       (l | t | r | b) != 0) {
    6612               0 :     VisualDeltas oldDeltas = mOverflow.mVisualDeltas;
    6613                 :     // It's a "small" overflow area so we store the deltas for each edge
    6614                 :     // directly in the frame, rather than allocating a separate rect.
    6615                 :     // If they're all zero, that's fine; we're setting things to
    6616                 :     // no-overflow.
    6617               0 :     mOverflow.mVisualDeltas.mLeft   = l;
    6618               0 :     mOverflow.mVisualDeltas.mTop    = t;
    6619               0 :     mOverflow.mVisualDeltas.mRight  = r;
    6620               0 :     mOverflow.mVisualDeltas.mBottom = b;
    6621                 :     // There was no scrollable overflow before, and there isn't now.
    6622               0 :     return oldDeltas != mOverflow.mVisualDeltas;
    6623                 :   } else {
    6624               0 :     bool changed = !aOverflowAreas.ScrollableOverflow().IsEqualEdges(nsRect(nsPoint(0, 0), GetSize())) ||
    6625               0 :       !aOverflowAreas.VisualOverflow().IsEqualEdges(GetVisualOverflowFromDeltas());
    6626                 : 
    6627                 :     // it's a large overflow area that we need to store as a property
    6628               0 :     mOverflow.mType = NS_FRAME_OVERFLOW_LARGE;
    6629               0 :     nsOverflowAreas* overflow = GetOverflowAreasProperty();
    6630               0 :     NS_ASSERTION(overflow, "should have created areas");
    6631               0 :     *overflow = aOverflowAreas;
    6632               0 :     return changed;
    6633                 :   }
    6634                 : }
    6635                 : 
    6636                 : inline bool
    6637               0 : IsInlineFrame(nsIFrame *aFrame)
    6638                 : {
    6639               0 :   nsIAtom *type = aFrame->GetType();
    6640               0 :   return type == nsGkAtoms::inlineFrame;
    6641                 : }
    6642                 : 
    6643                 : bool
    6644               0 : nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
    6645                 :                                  nsSize aNewSize)
    6646                 : {
    6647               0 :   nsRect bounds(nsPoint(0, 0), aNewSize);
    6648                 :   // Store the passed in overflow area if we are a preserve-3d frame,
    6649                 :   // and it's not just the frame bounds.
    6650               0 :   if ((Preserves3D() || HasPerspective()) && (!aOverflowAreas.VisualOverflow().IsEqualEdges(bounds) ||
    6651               0 :                         !aOverflowAreas.ScrollableOverflow().IsEqualEdges(bounds))) {
    6652                 :     nsOverflowAreas* initial =
    6653               0 :       static_cast<nsOverflowAreas*>(Properties().Get(nsIFrame::InitialOverflowProperty()));
    6654               0 :     if (!initial) {
    6655                 :       Properties().Set(nsIFrame::InitialOverflowProperty(),
    6656               0 :                        new nsOverflowAreas(aOverflowAreas));
    6657               0 :     } else if (initial != &aOverflowAreas) {
    6658               0 :       *initial = aOverflowAreas;
    6659                 :     }
    6660                 :   }
    6661                 : 
    6662                 :   // This is now called FinishAndStoreOverflow() instead of 
    6663                 :   // StoreOverflow() because frame-generic ways of adding overflow
    6664                 :   // can happen here, e.g. CSS2 outline and native theme.
    6665                 :   // If the overflow area width or height is nscoord_MAX, then a
    6666                 :   // saturating union may have encounted an overflow, so the overflow may not
    6667                 :   // contain the frame border-box. Don't warn in that case.
    6668               0 :   NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
    6669               0 :     DebugOnly<nsRect*> r = &aOverflowAreas.Overflow(otype);
    6670               0 :     NS_ASSERTION(aNewSize.width == 0 || aNewSize.height == 0 ||
    6671                 :                  r->width == nscoord_MAX || r->height == nscoord_MAX ||
    6672                 :                  r->Contains(nsRect(nsPoint(0,0), aNewSize)),
    6673                 :                  "Computed overflow area must contain frame bounds");
    6674                 :   }
    6675                 : 
    6676                 :   // If we clip our children, clear accumulated overflow area. The
    6677                 :   // children are actually clipped to the padding-box, but since the
    6678                 :   // overflow area should include the entire border-box, just set it to
    6679                 :   // the border-box here.
    6680               0 :   const nsStyleDisplay* disp = GetStyleDisplay();
    6681               0 :   NS_ASSERTION((disp->mOverflowY == NS_STYLE_OVERFLOW_CLIP) ==
    6682                 :                (disp->mOverflowX == NS_STYLE_OVERFLOW_CLIP),
    6683                 :                "If one overflow is clip, the other should be too");
    6684               0 :   if (nsFrame::ApplyOverflowClipping(this, disp)) {
    6685                 :     // The contents are actually clipped to the padding area 
    6686               0 :     aOverflowAreas.SetAllTo(bounds);
    6687                 :   }
    6688                 : 
    6689                 :   // Overflow area must always include the frame's top-left and bottom-right,
    6690                 :   // even if the frame rect is empty.
    6691                 :   // Pending a real fix for bug 426879, don't do this for inline frames
    6692                 :   // with zero width.
    6693               0 :   if (aNewSize.width != 0 || !IsInlineFrame(this)) {
    6694               0 :     NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
    6695               0 :       nsRect& o = aOverflowAreas.Overflow(otype);
    6696               0 :       o.UnionRectEdges(o, bounds);
    6697                 :     }
    6698                 :   }
    6699                 : 
    6700                 :   // Note that NS_STYLE_OVERFLOW_CLIP doesn't clip the frame background,
    6701                 :   // so we add theme background overflow here so it's not clipped.
    6702               0 :   if (!IsBoxWrapped() && IsThemed(disp)) {
    6703               0 :     nsRect r(bounds);
    6704               0 :     nsPresContext *presContext = PresContext();
    6705               0 :     if (presContext->GetTheme()->
    6706                 :           GetWidgetOverflow(presContext->DeviceContext(), this,
    6707               0 :                             disp->mAppearance, &r)) {
    6708               0 :       nsRect& vo = aOverflowAreas.VisualOverflow();
    6709               0 :       vo.UnionRectEdges(vo, r);
    6710                 :     }
    6711                 :   }
    6712                 : 
    6713                 :   // Nothing in here should affect scrollable overflow.
    6714                 :   bool hasOutlineOrEffects;
    6715               0 :   aOverflowAreas.VisualOverflow() =
    6716                 :     ComputeOutlineAndEffectsRect(this, &hasOutlineOrEffects,
    6717               0 :                                  aOverflowAreas.VisualOverflow(), aNewSize,
    6718               0 :                                  true);
    6719                 : 
    6720                 :   // Absolute position clipping
    6721               0 :   bool didHaveClipPropClip = (GetStateBits() & NS_FRAME_HAS_CLIP) != 0;
    6722               0 :   nsRect clipPropClipRect;
    6723               0 :   bool hasClipPropClip = GetClipPropClipRect(disp, &clipPropClipRect, aNewSize);
    6724               0 :   if (hasClipPropClip) {
    6725               0 :     NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
    6726               0 :       nsRect& o = aOverflowAreas.Overflow(otype);
    6727               0 :       o.IntersectRect(o, clipPropClipRect);
    6728                 :     }
    6729               0 :     AddStateBits(NS_FRAME_HAS_CLIP);
    6730                 :   } else {
    6731               0 :     RemoveStateBits(NS_FRAME_HAS_CLIP);
    6732                 :   }
    6733                 : 
    6734                 :   bool preTransformVisualOverflowChanged =
    6735               0 :     !GetVisualOverflowRectRelativeToSelf().IsEqualInterior(aOverflowAreas.VisualOverflow());
    6736                 : 
    6737                 :   /* If we're transformed, transform the overflow rect by the current transformation. */
    6738               0 :   bool hasTransform = IsTransformed();
    6739               0 :   if (hasTransform) {
    6740                 :     Properties().Set(nsIFrame::PreTransformOverflowAreasProperty(),
    6741               0 :                      new nsOverflowAreas(aOverflowAreas));
    6742                 :     /* Since our size might not actually have been computed yet, we need to make sure that we use the
    6743                 :      * correct dimensions by overriding the stored bounding rectangle with the value the caller has
    6744                 :      * ensured us we'll use.
    6745                 :      */
    6746               0 :     nsRect newBounds(nsPoint(0, 0), aNewSize);
    6747                 :     // Transform affects both overflow areas.
    6748               0 :     NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
    6749               0 :       nsRect& o = aOverflowAreas.Overflow(otype);
    6750               0 :       o = nsDisplayTransform::TransformRect(o, this, nsPoint(0, 0), &newBounds);
    6751                 :     }
    6752               0 :     if (Preserves3DChildren()) {
    6753               0 :       ComputePreserve3DChildrenOverflow(aOverflowAreas, newBounds);
    6754               0 :     } else if (ChildrenHavePerspective()) {
    6755               0 :       RecomputePerspectiveChildrenOverflow(this->GetStyleContext(), &newBounds);
    6756                 :     }
    6757                 :   } else {
    6758               0 :     Properties().Delete(nsIFrame::PreTransformOverflowAreasProperty());
    6759               0 :     if (ChildrenHavePerspective()) {
    6760               0 :       nsRect newBounds(nsPoint(0, 0), aNewSize);
    6761               0 :       RecomputePerspectiveChildrenOverflow(this->GetStyleContext(), &newBounds);
    6762                 :     }
    6763                 :   }
    6764                 :     
    6765                 : 
    6766                 :   bool anyOverflowChanged;
    6767               0 :   if (aOverflowAreas != nsOverflowAreas(bounds, bounds)) {
    6768               0 :     anyOverflowChanged = SetOverflowAreas(aOverflowAreas);
    6769                 :   } else {
    6770               0 :     anyOverflowChanged = ClearOverflowRects();
    6771                 :   }
    6772                 : 
    6773               0 :   if (preTransformVisualOverflowChanged) {
    6774               0 :     if (hasOutlineOrEffects) {
    6775                 :       // When there's an outline or box-shadow or SVG effects,
    6776                 :       // changes to those styles might require repainting of the old and new
    6777                 :       // overflow areas. Repainting of the old overflow area is handled in
    6778                 :       // nsCSSFrameConstructor::DoApplyRenderingChangeToTree in response
    6779                 :       // to nsChangeHint_RepaintFrame. Since the new overflow area is not
    6780                 :       // known at that time, we have to handle it here.
    6781                 :       // If the overflow area hasn't changed, then we don't have to do
    6782                 :       // anything here since repainting the old overflow area was enough.
    6783                 :       // If there is no outline or other effects now, then we don't have
    6784                 :       // to do anything here since removing those styles can't require
    6785                 :       // repainting of areas that weren't in the old overflow area.
    6786               0 :       Invalidate(aOverflowAreas.VisualOverflow());
    6787               0 :     } else if (hasClipPropClip || didHaveClipPropClip) {
    6788                 :       // If we are (or were) clipped by the 'clip' property, and our
    6789                 :       // overflow area changes, it might be because the clipping changed.
    6790                 :       // The nsChangeHint_RepaintFrame for the style change will only
    6791                 :       // repaint the old overflow area, so if the overflow area has
    6792                 :       // changed (in particular, if it grows), we have to repaint the
    6793                 :       // new area here.
    6794               0 :       Invalidate(aOverflowAreas.VisualOverflow());
    6795                 :     }
    6796                 :   }
    6797               0 :   if (anyOverflowChanged && hasTransform) {
    6798                 :     // When there's a transform, changes to that style might require
    6799                 :     // repainting of the old and new overflow areas in the widget.
    6800                 :     // Repainting of the frame itself will not be required if there's
    6801                 :     // a retained layer, so we can call InvalidateLayer here
    6802                 :     // which will avoid repainting ThebesLayers if possible.
    6803                 :     // nsCSSFrameConstructor::DoApplyRenderingChangeToTree repaints
    6804                 :     // the old overflow area in the widget in response to
    6805                 :     // nsChangeHint_UpdateTransformLayer. But since the new overflow
    6806                 :     // area is not known at that time, we have to handle it here.
    6807                 :     // If the overflow area hasn't changed, then it doesn't matter that
    6808                 :     // we didn't reach here since repainting the old overflow area was enough.
    6809                 :     // If there is no transform now, then the container layer for
    6810                 :     // the transform will go away and the frame contents will change
    6811                 :     // ThebesLayers, forcing it to be invalidated, so it doesn't matter
    6812                 :     // that we didn't reach here.
    6813               0 :     InvalidateLayer(aOverflowAreas.VisualOverflow(),
    6814               0 :                     nsDisplayItem::TYPE_TRANSFORM);
    6815                 :   }
    6816                 : 
    6817               0 :   return anyOverflowChanged;
    6818                 : }
    6819                 : 
    6820                 : void
    6821               0 : nsIFrame::RecomputePerspectiveChildrenOverflow(const nsStyleContext* aStartStyle, const nsRect* aBounds)
    6822                 : {
    6823                 :   // Children may check our size when getting our transform, make sure it's valid.
    6824               0 :   nsSize oldSize = GetSize();
    6825               0 :   if (aBounds) {
    6826               0 :     SetSize(aBounds->Size());
    6827                 :   }
    6828               0 :   nsIFrame::ChildListIterator lists(this);
    6829               0 :   for (; !lists.IsDone(); lists.Next()) {
    6830               0 :     nsFrameList::Enumerator childFrames(lists.CurrentList());
    6831               0 :     for (; !childFrames.AtEnd(); childFrames.Next()) {
    6832               0 :       nsIFrame* child = childFrames.get();
    6833               0 :       if (child->HasPerspective()) {
    6834                 :         nsOverflowAreas* overflow = 
    6835               0 :           static_cast<nsOverflowAreas*>(child->Properties().Get(nsIFrame::InitialOverflowProperty()));
    6836               0 :         nsRect bounds(nsPoint(0, 0), child->GetSize());
    6837               0 :         if (overflow) {
    6838               0 :           child->FinishAndStoreOverflow(*overflow, bounds.Size());
    6839                 :         } else {
    6840               0 :           nsOverflowAreas boundsOverflow;
    6841               0 :           boundsOverflow.SetAllTo(bounds);
    6842               0 :           child->FinishAndStoreOverflow(boundsOverflow, bounds.Size());
    6843                 :         }
    6844               0 :       } else if (child->GetStyleContext()->GetParent() == aStartStyle ||
    6845               0 :                  child->GetStyleContext() == aStartStyle) {
    6846                 :         // Recurse into frames with the same style context, or a direct
    6847                 :         // child style context.
    6848               0 :         child->RecomputePerspectiveChildrenOverflow(aStartStyle, nsnull);
    6849                 :       }
    6850                 :     }
    6851                 :   }
    6852                 :   // Restore our old size just in case something depends on this elesewhere.
    6853               0 :   SetSize(oldSize);
    6854               0 : }
    6855                 : 
    6856                 : /* The overflow rects for leaf nodes in a preserve-3d hierarchy depends on
    6857                 :  * the mRect value for their parents (since we use their transform, and transform
    6858                 :  * depends on this for transform-origin etc). These weren't necessarily correct
    6859                 :  * when we reflowed initially, so walk over all preserve-3d children and repeat the
    6860                 :  * overflow calculation.
    6861                 :  */
    6862                 : static void
    6863               0 : RecomputePreserve3DChildrenOverflow(nsIFrame* aFrame, const nsRect* aBounds)
    6864                 : {
    6865                 :   // Children may check our size when getting our transform, make sure it's valid.
    6866               0 :   nsSize oldSize = aFrame->GetSize();
    6867               0 :   if (aBounds) {
    6868               0 :     aFrame->SetSize(aBounds->Size());
    6869                 :   }
    6870               0 :   nsIFrame::ChildListIterator lists(aFrame);
    6871               0 :   for (; !lists.IsDone(); lists.Next()) {
    6872               0 :     nsFrameList::Enumerator childFrames(lists.CurrentList());
    6873               0 :     for (; !childFrames.AtEnd(); childFrames.Next()) {
    6874               0 :       nsIFrame* child = childFrames.get();
    6875               0 :       if (child->Preserves3DChildren()) {
    6876               0 :         RecomputePreserve3DChildrenOverflow(child, NULL);
    6877               0 :       } else if (child->Preserves3D()) {
    6878                 :         nsOverflowAreas* overflow = 
    6879               0 :           static_cast<nsOverflowAreas*>(child->Properties().Get(nsIFrame::InitialOverflowProperty()));
    6880               0 :         nsRect bounds(nsPoint(0, 0), child->GetSize());
    6881               0 :         if (overflow) {
    6882               0 :           child->FinishAndStoreOverflow(*overflow, bounds.Size());
    6883                 :         } else {
    6884               0 :           nsOverflowAreas boundsOverflow;
    6885               0 :           boundsOverflow.SetAllTo(bounds);
    6886               0 :           child->FinishAndStoreOverflow(boundsOverflow, bounds.Size());
    6887                 :         }
    6888                 :       }
    6889                 :     }
    6890                 :   }
    6891                 :   // Restore our old size just in case something depends on this elesewhere.
    6892               0 :   aFrame->SetSize(oldSize);
    6893                 :  
    6894                 :   // Only repeat computing our overflow in recursive calls since the initial caller is still
    6895                 :   // in the middle of doing this and we don't want an infinite loop.
    6896               0 :   if (!aBounds) {
    6897                 :     nsOverflowAreas* overflow = 
    6898               0 :       static_cast<nsOverflowAreas*>(aFrame->Properties().Get(nsIFrame::InitialOverflowProperty()));
    6899               0 :     nsRect bounds(nsPoint(0, 0), aFrame->GetSize());
    6900               0 :     if (overflow) {
    6901               0 :       overflow->UnionAllWith(bounds); 
    6902               0 :       aFrame->FinishAndStoreOverflow(*overflow, bounds.Size());
    6903                 :     } else {
    6904               0 :       nsOverflowAreas boundsOverflow;
    6905               0 :       boundsOverflow.SetAllTo(bounds);
    6906               0 :       aFrame->FinishAndStoreOverflow(boundsOverflow, bounds.Size());
    6907                 :     }
    6908                 :   }
    6909               0 : }
    6910                 : 
    6911                 : void
    6912               0 : nsIFrame::ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas, const nsRect& aBounds)
    6913                 : {
    6914                 :   // When we are preserving 3d we need to iterate over all children separately.
    6915                 :   // If the child also preserves 3d then their overflow will already been in our
    6916                 :   // coordinate space, otherwise we need to transform.
    6917                 : 
    6918                 :   // If we're the top frame in a preserve 3d chain then we need to recalculate the overflow
    6919                 :   // areas of all our children since they will have used our size/offset which was invalid at
    6920                 :   // the time.
    6921               0 :   if (!Preserves3D()) {
    6922               0 :     RecomputePreserve3DChildrenOverflow(this, &aBounds);
    6923                 :   }
    6924                 : 
    6925               0 :   nsRect childVisual;
    6926               0 :   nsRect childScrollable;
    6927               0 :   nsIFrame::ChildListIterator lists(this);
    6928               0 :   for (; !lists.IsDone(); lists.Next()) {
    6929               0 :     nsFrameList::Enumerator childFrames(lists.CurrentList());
    6930               0 :     for (; !childFrames.AtEnd(); childFrames.Next()) {
    6931               0 :       nsIFrame* child = childFrames.get();
    6932               0 :       nsPoint offset = child->GetPosition();
    6933               0 :       nsRect visual = child->GetVisualOverflowRect();
    6934               0 :       nsRect scrollable = child->GetScrollableOverflowRect();
    6935               0 :       visual.MoveBy(offset);
    6936               0 :       scrollable.MoveBy(offset);
    6937               0 :       if (child->Preserves3D()) {
    6938               0 :         childVisual = childVisual.Union(visual);
    6939               0 :         childScrollable = childScrollable.Union(scrollable);
    6940                 :       } else {
    6941                 :         childVisual = 
    6942                 :           childVisual.Union(nsDisplayTransform::TransformRect(visual, 
    6943               0 :                             this, nsPoint(0,0), &aBounds));
    6944                 :         childScrollable = 
    6945                 :           childScrollable.Union(nsDisplayTransform::TransformRect(scrollable,
    6946               0 :                                 this, nsPoint(0,0), &aBounds));
    6947                 :       }
    6948                 :     }
    6949                 :   }
    6950                 : 
    6951               0 :   aOverflowAreas.Overflow(eVisualOverflow) = aOverflowAreas.Overflow(eVisualOverflow).Union(childVisual);
    6952               0 :   aOverflowAreas.Overflow(eScrollableOverflow) = aOverflowAreas.Overflow(eScrollableOverflow).Union(childScrollable);
    6953               0 : }
    6954                 : 
    6955                 : void
    6956               0 : nsFrame::ConsiderChildOverflow(nsOverflowAreas& aOverflowAreas,
    6957                 :                                nsIFrame* aChildFrame)
    6958                 : {
    6959               0 :   aOverflowAreas.UnionWith(aChildFrame->GetOverflowAreas() +
    6960               0 :                            aChildFrame->GetPosition());
    6961               0 : }
    6962                 : 
    6963                 : /**
    6964                 :  * This function takes a "special" frame and _if_ that frame is an anonymous
    6965                 :  * block created by an ib split it returns the block's preceding inline.  This
    6966                 :  * is needed because the split inline's style context is the parent of the
    6967                 :  * anonymous block's style context.
    6968                 :  *
    6969                 :  * If aFrame is not an anonymous block, null is returned.
    6970                 :  */
    6971                 : static nsIFrame*
    6972               0 : GetIBSpecialSiblingForAnonymousBlock(const nsIFrame* aFrame)
    6973                 : {
    6974               0 :   NS_PRECONDITION(aFrame, "Must have a non-null frame!");
    6975               0 :   NS_ASSERTION(aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL,
    6976                 :                "GetIBSpecialSibling should not be called on a non-special frame");
    6977                 : 
    6978               0 :   nsIAtom* type = aFrame->GetStyleContext()->GetPseudo();
    6979               0 :   if (type != nsCSSAnonBoxes::mozAnonymousBlock &&
    6980                 :       type != nsCSSAnonBoxes::mozAnonymousPositionedBlock) {
    6981                 :     // it's not an anonymous block
    6982               0 :     return nsnull;
    6983                 :   }
    6984                 : 
    6985                 :   // Find the first continuation of the frame.  (Ugh.  This ends up
    6986                 :   // being O(N^2) when it is called O(N) times.)
    6987               0 :   aFrame = aFrame->GetFirstContinuation();
    6988                 : 
    6989                 :   /*
    6990                 :    * Now look up the nsGkAtoms::IBSplitSpecialPrevSibling
    6991                 :    * property.
    6992                 :    */
    6993                 :   nsIFrame *specialSibling = static_cast<nsIFrame*>
    6994               0 :     (aFrame->Properties().Get(nsIFrame::IBSplitSpecialPrevSibling()));
    6995               0 :   NS_ASSERTION(specialSibling, "Broken frame tree?");
    6996               0 :   return specialSibling;
    6997                 : }
    6998                 : 
    6999                 : /**
    7000                 :  * Get the parent, corrected for the mangled frame tree resulting from
    7001                 :  * having a block within an inline.  The result only differs from the
    7002                 :  * result of |GetParent| when |GetParent| returns an anonymous block
    7003                 :  * that was created for an element that was 'display: inline' because
    7004                 :  * that element contained a block.
    7005                 :  *
    7006                 :  * Also skip anonymous scrolled-content parents; inherit directly from the
    7007                 :  * outer scroll frame.
    7008                 :  */
    7009                 : static nsIFrame*
    7010               0 : GetCorrectedParent(const nsIFrame* aFrame)
    7011                 : {
    7012               0 :   nsIFrame *parent = aFrame->GetParent();
    7013               0 :   if (!parent) {
    7014               0 :     return nsnull;
    7015                 :   }
    7016                 : 
    7017                 :   // Outer tables are always anon boxes; if we're in here for an outer
    7018                 :   // table, that actually means its the _inner_ table that wants to
    7019                 :   // know its parent.  So get the pseudo of the inner in that case.
    7020               0 :   nsIAtom* pseudo = aFrame->GetStyleContext()->GetPseudo();
    7021               0 :   if (pseudo == nsCSSAnonBoxes::tableOuter) {
    7022               0 :     pseudo = aFrame->GetFirstPrincipalChild()->GetStyleContext()->GetPseudo();
    7023                 :   }
    7024               0 :   return nsFrame::CorrectStyleParentFrame(parent, pseudo);
    7025                 : }
    7026                 : 
    7027                 : /* static */
    7028                 : nsIFrame*
    7029               0 : nsFrame::CorrectStyleParentFrame(nsIFrame* aProspectiveParent,
    7030                 :                                  nsIAtom* aChildPseudo)
    7031                 : {
    7032               0 :   NS_PRECONDITION(aProspectiveParent, "Must have a prospective parent");
    7033                 : 
    7034                 :   // Anon boxes are parented to their actual parent already, except
    7035                 :   // for non-elements.  Those should not be treated as an anon box.
    7036               0 :   if (aChildPseudo && aChildPseudo != nsCSSAnonBoxes::mozNonElement &&
    7037               0 :       nsCSSAnonBoxes::IsAnonBox(aChildPseudo)) {
    7038               0 :     NS_ASSERTION(aChildPseudo != nsCSSAnonBoxes::mozAnonymousBlock &&
    7039                 :                  aChildPseudo != nsCSSAnonBoxes::mozAnonymousPositionedBlock,
    7040                 :                  "Should have dealt with kids that have NS_FRAME_IS_SPECIAL "
    7041                 :                  "elsewhere");
    7042               0 :     return aProspectiveParent;
    7043                 :   }
    7044                 : 
    7045                 :   // Otherwise, walk up out of all anon boxes.  For placeholder frames, walk out
    7046                 :   // of all pseudo-elements as well.  Otherwise ReparentStyleContext could cause
    7047                 :   // style data to be out of sync with the frame tree.
    7048               0 :   nsIFrame* parent = aProspectiveParent;
    7049               0 :   do {
    7050               0 :     if (parent->GetStateBits() & NS_FRAME_IS_SPECIAL) {
    7051               0 :       nsIFrame* sibling = GetIBSpecialSiblingForAnonymousBlock(parent);
    7052                 : 
    7053               0 :       if (sibling) {
    7054                 :         // |parent| was a block in an {ib} split; use the inline as
    7055                 :         // |the style parent.
    7056               0 :         parent = sibling;
    7057                 :       }
    7058                 :     }
    7059                 :       
    7060               0 :     nsIAtom* parentPseudo = parent->GetStyleContext()->GetPseudo();
    7061               0 :     if (!parentPseudo ||
    7062               0 :         (!nsCSSAnonBoxes::IsAnonBox(parentPseudo) &&
    7063                 :          // nsPlaceholderFrame pases in nsGkAtoms::placeholderFrame for
    7064                 :          // aChildPseudo (even though that's not a valid pseudo-type) just to
    7065                 :          // trigger this behavior of walking up to the nearest non-pseudo
    7066                 :          // ancestor.
    7067                 :          aChildPseudo != nsGkAtoms::placeholderFrame)) {
    7068               0 :       return parent;
    7069                 :     }
    7070                 : 
    7071               0 :     parent = parent->GetParent();
    7072                 :   } while (parent);
    7073                 : 
    7074               0 :   if (aProspectiveParent->GetStyleContext()->GetPseudo() ==
    7075                 :       nsCSSAnonBoxes::viewportScroll) {
    7076                 :     // aProspectiveParent is the scrollframe for a viewport
    7077                 :     // and the kids are the anonymous scrollbars
    7078               0 :     return aProspectiveParent;
    7079                 :   }
    7080                 : 
    7081                 :   // We can get here if the root element is absolutely positioned.
    7082                 :   // We can't test for this very accurately, but it can only happen
    7083                 :   // when the prospective parent is a canvas frame.
    7084               0 :   NS_ASSERTION(aProspectiveParent->GetType() == nsGkAtoms::canvasFrame,
    7085                 :                "Should have found a parent before this");
    7086               0 :   return nsnull;
    7087                 : }
    7088                 : 
    7089                 : nsIFrame*
    7090               0 : nsFrame::DoGetParentStyleContextFrame() const
    7091                 : {
    7092               0 :   if (mContent && !mContent->GetParent() &&
    7093               0 :       !GetStyleContext()->GetPseudo()) {
    7094                 :     // we're a frame for the root.  We have no style context parent.
    7095               0 :     return nsnull;
    7096                 :   }
    7097                 :   
    7098               0 :   if (!(mState & NS_FRAME_OUT_OF_FLOW)) {
    7099                 :     /*
    7100                 :      * If this frame is an anonymous block created when an inline with a block
    7101                 :      * inside it got split, then the parent style context is on its preceding
    7102                 :      * inline. We can get to it using GetIBSpecialSiblingForAnonymousBlock.
    7103                 :      */
    7104               0 :     if (mState & NS_FRAME_IS_SPECIAL) {
    7105               0 :       nsIFrame* specialSibling = GetIBSpecialSiblingForAnonymousBlock(this);
    7106               0 :       if (specialSibling) {
    7107               0 :         return specialSibling;
    7108                 :       }
    7109                 :     }
    7110                 : 
    7111                 :     // If this frame is one of the blocks that split an inline, we must
    7112                 :     // return the "special" inline parent, i.e., the parent that this
    7113                 :     // frame would have if we didn't mangle the frame structure.
    7114               0 :     return GetCorrectedParent(this);
    7115                 :   }
    7116                 : 
    7117                 :   // For out-of-flow frames, we must resolve underneath the
    7118                 :   // placeholder's parent.
    7119               0 :   const nsIFrame* oofFrame = this;
    7120               0 :   if ((oofFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
    7121               0 :       GetPrevInFlow()) {
    7122                 :     // Out of flows that are continuations do not
    7123                 :     // have placeholders. Use their first-in-flow's placeholder.
    7124               0 :     oofFrame = oofFrame->GetFirstInFlow();
    7125                 :   }
    7126                 :   nsIFrame* placeholder = oofFrame->PresContext()->FrameManager()->
    7127               0 :                             GetPlaceholderFrameFor(oofFrame);
    7128               0 :   if (!placeholder) {
    7129               0 :     NS_NOTREACHED("no placeholder frame for out-of-flow frame");
    7130               0 :     return GetCorrectedParent(this);
    7131                 :   }
    7132               0 :   return placeholder->GetParentStyleContextFrame();
    7133                 : }
    7134                 : 
    7135                 : void
    7136               0 : nsFrame::GetLastLeaf(nsPresContext* aPresContext, nsIFrame **aFrame)
    7137                 : {
    7138               0 :   if (!aFrame || !*aFrame)
    7139               0 :     return;
    7140               0 :   nsIFrame *child = *aFrame;
    7141                 :   //if we are a block frame then go for the last line of 'this'
    7142               0 :   while (1){
    7143               0 :     child = child->GetFirstPrincipalChild();
    7144               0 :     if (!child)
    7145               0 :       return;//nothing to do
    7146                 :     nsIFrame* siblingFrame;
    7147                 :     nsIContent* content;
    7148                 :     //ignore anonymous elements, e.g. mozTableAdd* mozTableRemove*
    7149                 :     //see bug 278197 comment #12 #13 for details
    7150               0 :     while ((siblingFrame = child->GetNextSibling()) &&
    7151                 :            (content = siblingFrame->GetContent()) &&
    7152               0 :            !content->IsRootOfNativeAnonymousSubtree())
    7153               0 :       child = siblingFrame;
    7154               0 :     *aFrame = child;
    7155                 :   }
    7156                 : }
    7157                 : 
    7158                 : void
    7159               0 : nsFrame::GetFirstLeaf(nsPresContext* aPresContext, nsIFrame **aFrame)
    7160                 : {
    7161               0 :   if (!aFrame || !*aFrame)
    7162               0 :     return;
    7163               0 :   nsIFrame *child = *aFrame;
    7164               0 :   while (1){
    7165               0 :     child = child->GetFirstPrincipalChild();
    7166               0 :     if (!child)
    7167               0 :       return;//nothing to do
    7168               0 :     *aFrame = child;
    7169                 :   }
    7170                 : }
    7171                 : 
    7172                 : /* virtual */ const void*
    7173               0 : nsFrame::GetStyleDataExternal(nsStyleStructID aSID) const
    7174                 : {
    7175               0 :   NS_ASSERTION(mStyleContext, "unexpected null pointer");
    7176               0 :   return mStyleContext->GetStyleData(aSID);
    7177                 : }
    7178                 : 
    7179                 : /* virtual */ bool
    7180               0 : nsIFrame::IsFocusable(PRInt32 *aTabIndex, bool aWithMouse)
    7181                 : {
    7182               0 :   PRInt32 tabIndex = -1;
    7183               0 :   if (aTabIndex) {
    7184               0 :     *aTabIndex = -1; // Default for early return is not focusable
    7185                 :   }
    7186               0 :   bool isFocusable = false;
    7187                 : 
    7188               0 :   if (mContent && mContent->IsElement() && IsVisibleConsideringAncestors()) {
    7189               0 :     const nsStyleUserInterface* ui = GetStyleUserInterface();
    7190               0 :     if (ui->mUserFocus != NS_STYLE_USER_FOCUS_IGNORE &&
    7191                 :         ui->mUserFocus != NS_STYLE_USER_FOCUS_NONE) {
    7192                 :       // Pass in default tabindex of -1 for nonfocusable and 0 for focusable
    7193               0 :       tabIndex = 0;
    7194                 :     }
    7195               0 :     isFocusable = mContent->IsFocusable(&tabIndex, aWithMouse);
    7196               0 :     if (!isFocusable && !aWithMouse &&
    7197               0 :         GetType() == nsGkAtoms::scrollFrame &&
    7198               0 :         mContent->IsHTML() &&
    7199               0 :         !mContent->IsRootOfNativeAnonymousSubtree() &&
    7200               0 :         mContent->GetParent() &&
    7201               0 :         !mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
    7202                 :       // Elements with scrollable view are focusable with script & tabbable
    7203                 :       // Otherwise you couldn't scroll them with keyboard, which is
    7204                 :       // an accessibility issue (e.g. Section 508 rules)
    7205                 :       // However, we don't make them to be focusable with the mouse,
    7206                 :       // because the extra focus outlines are considered unnecessarily ugly.
    7207                 :       // When clicked on, the selection position within the element 
    7208                 :       // will be enough to make them keyboard scrollable.
    7209               0 :       nsIScrollableFrame *scrollFrame = do_QueryFrame(this);
    7210               0 :       if (scrollFrame &&
    7211               0 :           scrollFrame->GetScrollbarStyles() != nsIScrollableFrame::ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_HIDDEN) &&
    7212               0 :           !scrollFrame->GetScrollRange().IsEqualEdges(nsRect(0, 0, 0, 0))) {
    7213                 :           // Scroll bars will be used for overflow
    7214               0 :           isFocusable = true;
    7215               0 :           tabIndex = 0;
    7216                 :       }
    7217                 :     }
    7218                 :   }
    7219                 : 
    7220               0 :   if (aTabIndex) {
    7221               0 :     *aTabIndex = tabIndex;
    7222                 :   }
    7223               0 :   return isFocusable;
    7224                 : }
    7225                 : 
    7226                 : /**
    7227                 :  * @return true if this text frame ends with a newline character.  It
    7228                 :  * should return false if this is not a text frame.
    7229                 :  */
    7230                 : bool
    7231               0 : nsIFrame::HasTerminalNewline() const
    7232                 : {
    7233               0 :   return false;
    7234                 : }
    7235                 : 
    7236                 : /* static */
    7237               0 : void nsFrame::FillCursorInformationFromStyle(const nsStyleUserInterface* ui,
    7238                 :                                              nsIFrame::Cursor& aCursor)
    7239                 : {
    7240               0 :   aCursor.mCursor = ui->mCursor;
    7241               0 :   aCursor.mHaveHotspot = false;
    7242               0 :   aCursor.mHotspotX = aCursor.mHotspotY = 0.0f;
    7243                 : 
    7244               0 :   for (nsCursorImage *item = ui->mCursorArray,
    7245               0 :                  *item_end = ui->mCursorArray + ui->mCursorArrayLength;
    7246                 :        item < item_end; ++item) {
    7247                 :     PRUint32 status;
    7248               0 :     nsresult rv = item->GetImage()->GetImageStatus(&status);
    7249               0 :     if (NS_SUCCEEDED(rv) && (status & imgIRequest::STATUS_LOAD_COMPLETE)) {
    7250                 :       // This is the one we want
    7251               0 :       item->GetImage()->GetImage(getter_AddRefs(aCursor.mContainer));
    7252               0 :       aCursor.mHaveHotspot = item->mHaveHotspot;
    7253               0 :       aCursor.mHotspotX = item->mHotspotX;
    7254               0 :       aCursor.mHotspotY = item->mHotspotY;
    7255               0 :       break;
    7256                 :     }
    7257                 :   }
    7258               0 : }
    7259                 : 
    7260                 : NS_IMETHODIMP
    7261               0 : nsFrame::RefreshSizeCache(nsBoxLayoutState& aState)
    7262                 : {
    7263                 :   // XXXbz this comment needs some rewriting to make sense in the
    7264                 :   // post-reflow-branch world.
    7265                 :   
    7266                 :   // Ok we need to compute our minimum, preferred, and maximum sizes.
    7267                 :   // 1) Maximum size. This is easy. Its infinite unless it is overloaded by CSS.
    7268                 :   // 2) Preferred size. This is a little harder. This is the size the block would be 
    7269                 :   //      if it were laid out on an infinite canvas. So we can get this by reflowing
    7270                 :   //      the block with and INTRINSIC width and height. We can also do a nice optimization
    7271                 :   //      for incremental reflow. If the reflow is incremental then we can pass a flag to 
    7272                 :   //      have the block compute the preferred width for us! Preferred height can just be
    7273                 :   //      the minimum height;
    7274                 :   // 3) Minimum size. This is a toughy. We can pass the block a flag asking for the max element
    7275                 :   //    size. That would give us the width. Unfortunately you can only ask for a maxElementSize
    7276                 :   //    during an incremental reflow. So on other reflows we will just have to use 0.
    7277                 :   //    The min height on the other hand is fairly easy we need to get the largest
    7278                 :   //    line height. This can be done with the line iterator.
    7279                 : 
    7280                 :   // if we do have a rendering context
    7281               0 :   nsresult rv = NS_OK;
    7282               0 :   nsRenderingContext* rendContext = aState.GetRenderingContext();
    7283               0 :   if (rendContext) {
    7284               0 :     nsPresContext* presContext = aState.PresContext();
    7285                 : 
    7286                 :     // If we don't have any HTML constraints and it's a resize, then nothing in the block
    7287                 :     // could have changed, so no refresh is necessary.
    7288               0 :     nsBoxLayoutMetrics* metrics = BoxMetrics();
    7289               0 :     if (!DoesNeedRecalc(metrics->mBlockPrefSize))
    7290               0 :       return NS_OK;
    7291                 : 
    7292                 :     // get the old rect.
    7293               0 :     nsRect oldRect = GetRect();
    7294                 : 
    7295                 :     // the rect we plan to size to.
    7296               0 :     nsRect rect(oldRect);
    7297                 : 
    7298               0 :     nsMargin bp(0,0,0,0);
    7299               0 :     GetBorderAndPadding(bp);
    7300                 : 
    7301                 :     {
    7302                 :       // If we're a container for font size inflation, then shrink
    7303                 :       // wrapping inside of us should not apply font size inflation.
    7304               0 :       AutoMaybeNullInflationContainer an(this);
    7305                 : 
    7306                 :       metrics->mBlockPrefSize.width =
    7307               0 :         GetPrefWidth(rendContext) + bp.LeftRight();
    7308                 :       metrics->mBlockMinSize.width =
    7309               0 :         GetMinWidth(rendContext) + bp.LeftRight();
    7310                 :     }
    7311                 : 
    7312                 :     // do the nasty.
    7313               0 :     nsHTMLReflowMetrics desiredSize;
    7314                 :     rv = BoxReflow(aState, presContext, desiredSize, rendContext,
    7315                 :                    rect.x, rect.y,
    7316               0 :                    metrics->mBlockPrefSize.width, NS_UNCONSTRAINEDSIZE);
    7317                 : 
    7318               0 :     nsRect newRect = GetRect();
    7319                 : 
    7320                 :     // make sure we draw any size change
    7321               0 :     if (oldRect.width != newRect.width || oldRect.height != newRect.height) {
    7322               0 :       newRect.x = 0;
    7323               0 :       newRect.y = 0;
    7324               0 :       Redraw(aState, &newRect);
    7325                 :     }
    7326                 : 
    7327               0 :     metrics->mBlockMinSize.height = 0;
    7328                 :     // ok we need the max ascent of the items on the line. So to do this
    7329                 :     // ask the block for its line iterator. Get the max ascent.
    7330               0 :     nsAutoLineIterator lines = GetLineIterator();
    7331               0 :     if (lines) 
    7332                 :     {
    7333               0 :       metrics->mBlockMinSize.height = 0;
    7334               0 :       int count = 0;
    7335               0 :       nsIFrame* firstFrame = nsnull;
    7336                 :       PRInt32 framesOnLine;
    7337               0 :       nsRect lineBounds;
    7338                 :       PRUint32 lineFlags;
    7339                 : 
    7340               0 :       do {
    7341               0 :          lines->GetLine(count, &firstFrame, &framesOnLine, lineBounds, &lineFlags);
    7342                 : 
    7343               0 :          if (lineBounds.height > metrics->mBlockMinSize.height)
    7344               0 :            metrics->mBlockMinSize.height = lineBounds.height;
    7345                 : 
    7346               0 :          count++;
    7347                 :       } while(firstFrame);
    7348                 :     } else {
    7349               0 :       metrics->mBlockMinSize.height = desiredSize.height;
    7350                 :     }
    7351                 : 
    7352               0 :     metrics->mBlockPrefSize.height = metrics->mBlockMinSize.height;
    7353                 : 
    7354               0 :     if (desiredSize.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
    7355               0 :       if (!nsLayoutUtils::GetFirstLineBaseline(this, &metrics->mBlockAscent))
    7356               0 :         metrics->mBlockAscent = GetBaseline();
    7357                 :     } else {
    7358               0 :       metrics->mBlockAscent = desiredSize.ascent;
    7359                 :     }
    7360                 : 
    7361                 : #ifdef DEBUG_adaptor
    7362                 :     printf("min=(%d,%d), pref=(%d,%d), ascent=%d\n", metrics->mBlockMinSize.width,
    7363                 :                                                      metrics->mBlockMinSize.height,
    7364                 :                                                      metrics->mBlockPrefSize.width,
    7365                 :                                                      metrics->mBlockPrefSize.height,
    7366                 :                                                      metrics->mBlockAscent);
    7367                 : #endif
    7368                 :   }
    7369                 : 
    7370               0 :   return rv;
    7371                 : }
    7372                 : 
    7373                 : /* virtual */ nsILineIterator*
    7374               0 : nsFrame::GetLineIterator()
    7375                 : {
    7376               0 :   return nsnull;
    7377                 : }
    7378                 : 
    7379                 : nsSize
    7380               0 : nsFrame::GetPrefSize(nsBoxLayoutState& aState)
    7381                 : {
    7382               0 :   nsSize size(0,0);
    7383               0 :   DISPLAY_PREF_SIZE(this, size);
    7384                 :   // If the size is cached, and there are no HTML constraints that we might
    7385                 :   // be depending on, then we just return the cached size.
    7386               0 :   nsBoxLayoutMetrics *metrics = BoxMetrics();
    7387               0 :   if (!DoesNeedRecalc(metrics->mPrefSize)) {
    7388               0 :     return metrics->mPrefSize;
    7389                 :   }
    7390                 : 
    7391               0 :   if (IsCollapsed())
    7392               0 :     return size;
    7393                 : 
    7394                 :   // get our size in CSS.
    7395                 :   bool widthSet, heightSet;
    7396               0 :   bool completelyRedefined = nsIBox::AddCSSPrefSize(this, size, widthSet, heightSet);
    7397                 : 
    7398                 :   // Refresh our caches with new sizes.
    7399               0 :   if (!completelyRedefined) {
    7400               0 :     RefreshSizeCache(aState);
    7401               0 :     nsSize blockSize = metrics->mBlockPrefSize;
    7402                 : 
    7403                 :     // notice we don't need to add our borders or padding
    7404                 :     // in. That's because the block did it for us.
    7405               0 :     if (!widthSet)
    7406               0 :       size.width = blockSize.width;
    7407               0 :     if (!heightSet)
    7408               0 :       size.height = blockSize.height;
    7409                 :   }
    7410                 : 
    7411               0 :   metrics->mPrefSize = size;
    7412               0 :   return size;
    7413                 : }
    7414                 : 
    7415                 : nsSize
    7416               0 : nsFrame::GetMinSize(nsBoxLayoutState& aState)
    7417                 : {
    7418               0 :   nsSize size(0,0);
    7419               0 :   DISPLAY_MIN_SIZE(this, size);
    7420                 :   // Don't use the cache if we have HTMLReflowState constraints --- they might have changed
    7421               0 :   nsBoxLayoutMetrics *metrics = BoxMetrics();
    7422               0 :   if (!DoesNeedRecalc(metrics->mMinSize)) {
    7423               0 :     size = metrics->mMinSize;
    7424                 :     return size;
    7425                 :   }
    7426                 : 
    7427               0 :   if (IsCollapsed())
    7428                 :     return size;
    7429                 : 
    7430                 :   // get our size in CSS.
    7431                 :   bool widthSet, heightSet;
    7432                 :   bool completelyRedefined =
    7433               0 :     nsIBox::AddCSSMinSize(aState, this, size, widthSet, heightSet);
    7434                 : 
    7435                 :   // Refresh our caches with new sizes.
    7436               0 :   if (!completelyRedefined) {
    7437               0 :     RefreshSizeCache(aState);
    7438               0 :     nsSize blockSize = metrics->mBlockMinSize;
    7439                 : 
    7440               0 :     if (!widthSet)
    7441               0 :       size.width = blockSize.width;
    7442               0 :     if (!heightSet)
    7443               0 :       size.height = blockSize.height;
    7444                 :   }
    7445                 : 
    7446               0 :   metrics->mMinSize = size;
    7447                 :   return size;
    7448                 : }
    7449                 : 
    7450                 : nsSize
    7451               0 : nsFrame::GetMaxSize(nsBoxLayoutState& aState)
    7452                 : {
    7453               0 :   nsSize size(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
    7454               0 :   DISPLAY_MAX_SIZE(this, size);
    7455                 :   // Don't use the cache if we have HTMLReflowState constraints --- they might have changed
    7456               0 :   nsBoxLayoutMetrics *metrics = BoxMetrics();
    7457               0 :   if (!DoesNeedRecalc(metrics->mMaxSize)) {
    7458               0 :     size = metrics->mMaxSize;
    7459                 :     return size;
    7460                 :   }
    7461                 : 
    7462               0 :   if (IsCollapsed())
    7463                 :     return size;
    7464                 : 
    7465               0 :   size = nsBox::GetMaxSize(aState);
    7466               0 :   metrics->mMaxSize = size;
    7467                 : 
    7468                 :   return size;
    7469                 : }
    7470                 : 
    7471                 : nscoord
    7472               0 : nsFrame::GetFlex(nsBoxLayoutState& aState)
    7473                 : {
    7474               0 :   nsBoxLayoutMetrics *metrics = BoxMetrics();
    7475               0 :   if (!DoesNeedRecalc(metrics->mFlex))
    7476               0 :      return metrics->mFlex;
    7477                 : 
    7478               0 :   metrics->mFlex = nsBox::GetFlex(aState);
    7479                 : 
    7480               0 :   return metrics->mFlex;
    7481                 : }
    7482                 : 
    7483                 : nscoord
    7484               0 : nsFrame::GetBoxAscent(nsBoxLayoutState& aState)
    7485                 : {
    7486               0 :   nsBoxLayoutMetrics *metrics = BoxMetrics();
    7487               0 :   if (!DoesNeedRecalc(metrics->mAscent))
    7488               0 :     return metrics->mAscent;
    7489                 : 
    7490               0 :   if (IsCollapsed()) {
    7491               0 :     metrics->mAscent = 0;
    7492                 :   } else {
    7493                 :     // Refresh our caches with new sizes.
    7494               0 :     RefreshSizeCache(aState);
    7495               0 :     metrics->mAscent = metrics->mBlockAscent;
    7496                 :   }
    7497                 : 
    7498               0 :   return metrics->mAscent;
    7499                 : }
    7500                 : 
    7501                 : nsresult
    7502               0 : nsFrame::DoLayout(nsBoxLayoutState& aState)
    7503                 : {
    7504               0 :   nsRect ourRect(mRect);
    7505                 : 
    7506               0 :   nsRenderingContext* rendContext = aState.GetRenderingContext();
    7507               0 :   nsPresContext* presContext = aState.PresContext();
    7508               0 :   nsHTMLReflowMetrics desiredSize;
    7509               0 :   nsresult rv = NS_OK;
    7510                 :  
    7511               0 :   if (rendContext) {
    7512                 : 
    7513                 :     rv = BoxReflow(aState, presContext, desiredSize, rendContext,
    7514               0 :                    ourRect.x, ourRect.y, ourRect.width, ourRect.height);
    7515                 : 
    7516               0 :     if (IsCollapsed()) {
    7517               0 :       SetSize(nsSize(0, 0));
    7518                 :     } else {
    7519                 : 
    7520                 :       // if our child needs to be bigger. This might happend with
    7521                 :       // wrapping text. There is no way to predict its height until we
    7522                 :       // reflow it. Now that we know the height reshuffle upward.
    7523               0 :       if (desiredSize.width > ourRect.width ||
    7524                 :           desiredSize.height > ourRect.height) {
    7525                 : 
    7526                 : #ifdef DEBUG_GROW
    7527                 :         DumpBox(stdout);
    7528                 :         printf(" GREW from (%d,%d) -> (%d,%d)\n",
    7529                 :                ourRect.width, ourRect.height,
    7530                 :                desiredSize.width, desiredSize.height);
    7531                 : #endif
    7532                 : 
    7533               0 :         if (desiredSize.width > ourRect.width)
    7534               0 :           ourRect.width = desiredSize.width;
    7535                 : 
    7536               0 :         if (desiredSize.height > ourRect.height)
    7537               0 :           ourRect.height = desiredSize.height;
    7538                 :       }
    7539                 : 
    7540                 :       // ensure our size is what we think is should be. Someone could have
    7541                 :       // reset the frame to be smaller or something dumb like that. 
    7542               0 :       SetSize(nsSize(ourRect.width, ourRect.height));
    7543                 :     }
    7544                 :   }
    7545                 : 
    7546                 :   // Should we do this if IsCollapsed() is true?
    7547               0 :   nsSize size(GetSize());
    7548               0 :   desiredSize.width = size.width;
    7549               0 :   desiredSize.height = size.height;
    7550               0 :   desiredSize.UnionOverflowAreasWithDesiredBounds();
    7551                 : 
    7552               0 :   if (HasAbsolutelyPositionedChildren()) {
    7553                 :     // Set up a |reflowState| to pass into ReflowAbsoluteFrames
    7554                 :     nsHTMLReflowState reflowState(aState.PresContext(), this,
    7555                 :                                   aState.GetRenderingContext(),
    7556               0 :                                   nsSize(size.width, NS_UNCONSTRAINEDSIZE));
    7557                 : 
    7558                 :     // Set up a |reflowStatus| to pass into ReflowAbsoluteFrames
    7559                 :     // (just a dummy value; hopefully that's OK)
    7560               0 :     nsReflowStatus reflowStatus = NS_FRAME_COMPLETE;
    7561                 :     ReflowAbsoluteFrames(aState.PresContext(), desiredSize,
    7562               0 :                          reflowState, reflowStatus);
    7563                 :   }
    7564                 : 
    7565               0 :   FinishAndStoreOverflow(desiredSize.mOverflowAreas, size);
    7566                 : 
    7567               0 :   SyncLayout(aState);
    7568                 : 
    7569               0 :   return rv;
    7570                 : }
    7571                 : 
    7572                 : nsresult
    7573               0 : nsFrame::BoxReflow(nsBoxLayoutState&        aState,
    7574                 :                    nsPresContext*           aPresContext,
    7575                 :                    nsHTMLReflowMetrics&     aDesiredSize,
    7576                 :                    nsRenderingContext*     aRenderingContext,
    7577                 :                    nscoord                  aX,
    7578                 :                    nscoord                  aY,
    7579                 :                    nscoord                  aWidth,
    7580                 :                    nscoord                  aHeight,
    7581                 :                    bool                     aMoveFrame)
    7582                 : {
    7583               0 :   DO_GLOBAL_REFLOW_COUNT("nsBoxToBlockAdaptor");
    7584                 : 
    7585                 : #ifdef DEBUG_REFLOW
    7586                 :   nsAdaptorAddIndents();
    7587                 :   printf("Reflowing: ");
    7588                 :   nsFrame::ListTag(stdout, mFrame);
    7589                 :   printf("\n");
    7590                 :   gIndent2++;
    7591                 : #endif
    7592                 : 
    7593                 :   //printf("width=%d, height=%d\n", aWidth, aHeight);
    7594                 :   /*
    7595                 :   nsIBox* parent;
    7596                 :   GetParentBox(&parent);
    7597                 : 
    7598                 :  // if (parent->GetStateBits() & NS_STATE_CURRENTLY_IN_DEBUG)
    7599                 :   //   printf("In debug\n");
    7600                 :   */
    7601                 : 
    7602               0 :   nsBoxLayoutMetrics *metrics = BoxMetrics();
    7603               0 :   nsReflowStatus status = NS_FRAME_COMPLETE;
    7604                 : 
    7605               0 :   bool redrawAfterReflow = false;
    7606               0 :   bool redrawNow = false;
    7607                 : 
    7608               0 :   bool needsReflow = NS_SUBTREE_DIRTY(this);
    7609                 : 
    7610               0 :   if (redrawNow)
    7611               0 :      Redraw(aState);
    7612                 : 
    7613                 :   // if we don't need a reflow then 
    7614                 :   // lets see if we are already that size. Yes? then don't even reflow. We are done.
    7615               0 :   if (!needsReflow) {
    7616                 :       
    7617               0 :       if (aWidth != NS_INTRINSICSIZE && aHeight != NS_INTRINSICSIZE) {
    7618                 :       
    7619                 :           // if the new calculated size has a 0 width or a 0 height
    7620               0 :           if ((metrics->mLastSize.width == 0 || metrics->mLastSize.height == 0) && (aWidth == 0 || aHeight == 0)) {
    7621               0 :                needsReflow = false;
    7622               0 :                aDesiredSize.width = aWidth; 
    7623               0 :                aDesiredSize.height = aHeight; 
    7624               0 :                SetSize(nsSize(aDesiredSize.width, aDesiredSize.height));
    7625                 :           } else {
    7626               0 :             aDesiredSize.width = metrics->mLastSize.width;
    7627               0 :             aDesiredSize.height = metrics->mLastSize.height;
    7628                 : 
    7629                 :             // remove the margin. The rect of our child does not include it but our calculated size does.
    7630                 :             // don't reflow if we are already the right size
    7631               0 :             if (metrics->mLastSize.width == aWidth && metrics->mLastSize.height == aHeight)
    7632               0 :                   needsReflow = false;
    7633                 :             else
    7634               0 :                   needsReflow = true;
    7635                 :    
    7636                 :           }
    7637                 :       } else {
    7638                 :           // if the width or height are intrinsic alway reflow because
    7639                 :           // we don't know what it should be.
    7640               0 :          needsReflow = true;
    7641                 :       }
    7642                 :   }
    7643                 :                              
    7644                 :   // ok now reflow the child into the spacers calculated space
    7645               0 :   if (needsReflow) {
    7646                 : 
    7647               0 :     aDesiredSize.width = 0;
    7648               0 :     aDesiredSize.height = 0;
    7649                 : 
    7650                 :     // create a reflow state to tell our child to flow at the given size.
    7651                 : 
    7652                 :     // Construct a bogus parent reflow state so that there's a usable
    7653                 :     // containing block reflow state.
    7654               0 :     nsMargin margin(0,0,0,0);
    7655               0 :     GetMargin(margin);
    7656                 : 
    7657               0 :     nsSize parentSize(aWidth, aHeight);
    7658               0 :     if (parentSize.height != NS_INTRINSICSIZE)
    7659               0 :       parentSize.height += margin.TopBottom();
    7660               0 :     if (parentSize.width != NS_INTRINSICSIZE)
    7661               0 :       parentSize.width += margin.LeftRight();
    7662                 : 
    7663               0 :     nsIFrame *parentFrame = GetParent();
    7664               0 :     nsFrameState savedState = parentFrame->GetStateBits();
    7665                 :     nsHTMLReflowState parentReflowState(aPresContext, parentFrame,
    7666                 :                                         aRenderingContext,
    7667               0 :                                         parentSize);
    7668               0 :     parentFrame->RemoveStateBits(~nsFrameState(0));
    7669               0 :     parentFrame->AddStateBits(savedState);
    7670                 : 
    7671                 :     // This may not do very much useful, but it's probably worth trying.
    7672               0 :     if (parentSize.width != NS_INTRINSICSIZE)
    7673               0 :       parentReflowState.SetComputedWidth(NS_MAX(parentSize.width, 0));
    7674               0 :     if (parentSize.height != NS_INTRINSICSIZE)
    7675               0 :       parentReflowState.SetComputedHeight(NS_MAX(parentSize.height, 0));
    7676               0 :     parentReflowState.mComputedMargin.SizeTo(0, 0, 0, 0);
    7677                 :     // XXX use box methods
    7678               0 :     parentFrame->GetPadding(parentReflowState.mComputedPadding);
    7679               0 :     parentFrame->GetBorder(parentReflowState.mComputedBorderPadding);
    7680                 :     parentReflowState.mComputedBorderPadding +=
    7681               0 :       parentReflowState.mComputedPadding;
    7682                 : 
    7683                 :     // XXX Is it OK that this reflow state has no parent reflow state?
    7684                 :     // (It used to have a bogus parent, skipping all the boxes).
    7685               0 :     nsSize availSize(aWidth, NS_INTRINSICSIZE);
    7686                 :     nsHTMLReflowState reflowState(aPresContext, this, aRenderingContext,
    7687               0 :                                   availSize);
    7688                 : 
    7689                 :     // Construct the parent chain manually since constructing it normally
    7690                 :     // messes up dimensions.
    7691               0 :     const nsHTMLReflowState *outerReflowState = aState.OuterReflowState();
    7692               0 :     NS_ASSERTION(!outerReflowState || outerReflowState->frame != this,
    7693                 :                  "in and out of XUL on a single frame?");
    7694               0 :     if (outerReflowState && outerReflowState->frame == parentFrame) {
    7695                 :       // We're a frame (such as a text control frame) that jumps into
    7696                 :       // box reflow and then straight out of it on the child frame.
    7697                 :       // This means we actually have a real parent reflow state.
    7698                 :       // nsLayoutUtils::InflationMinFontSizeFor used to need this to be
    7699                 :       // linked up correctly for text control frames, so do so here).
    7700               0 :       reflowState.parentReflowState = outerReflowState;
    7701               0 :       reflowState.mCBReflowState = outerReflowState;
    7702                 :     } else {
    7703               0 :       reflowState.parentReflowState = &parentReflowState;
    7704               0 :       reflowState.mCBReflowState = &parentReflowState;
    7705                 :     }
    7706               0 :     reflowState.mReflowDepth = aState.GetReflowDepth();
    7707                 : 
    7708                 :     // mComputedWidth and mComputedHeight are content-box, not
    7709                 :     // border-box
    7710               0 :     if (aWidth != NS_INTRINSICSIZE) {
    7711                 :       nscoord computedWidth =
    7712               0 :         aWidth - reflowState.mComputedBorderPadding.LeftRight();
    7713               0 :       computedWidth = NS_MAX(computedWidth, 0);
    7714               0 :       reflowState.SetComputedWidth(computedWidth);
    7715                 :     }
    7716                 : 
    7717                 :     // Most child frames of box frames (e.g. subdocument or scroll frames)
    7718                 :     // need to be constrained to the provided size and overflow as necessary.
    7719                 :     // The one exception are block frames, because we need to know their
    7720                 :     // natural height excluding any overflow area which may be caused by
    7721                 :     // various CSS effects such as shadow or outline.
    7722               0 :     if (!IsFrameOfType(eBlockFrame)) {
    7723               0 :       if (aHeight != NS_INTRINSICSIZE) {
    7724                 :         nscoord computedHeight =
    7725               0 :           aHeight - reflowState.mComputedBorderPadding.TopBottom();
    7726               0 :         computedHeight = NS_MAX(computedHeight, 0);
    7727               0 :         reflowState.SetComputedHeight(computedHeight);
    7728                 :       } else {
    7729                 :         reflowState.SetComputedHeight(
    7730                 :           ComputeSize(aRenderingContext, availSize, availSize.width,
    7731                 :                       nsSize(reflowState.mComputedMargin.LeftRight(),
    7732                 :                              reflowState.mComputedMargin.TopBottom()),
    7733               0 :                       nsSize(reflowState.mComputedBorderPadding.LeftRight() -
    7734               0 :                                reflowState.mComputedPadding.LeftRight(),
    7735               0 :                              reflowState.mComputedBorderPadding.TopBottom() -
    7736               0 :                                reflowState.mComputedPadding.TopBottom()),
    7737                 :                       nsSize(reflowState.mComputedPadding.LeftRight(),
    7738                 :                                reflowState.mComputedPadding.TopBottom()),
    7739               0 :                       false).height
    7740               0 :           );
    7741                 :       }
    7742                 :     }
    7743                 : 
    7744                 :     // Box layout calls SetRect before Layout, whereas non-box layout
    7745                 :     // calls SetRect after Reflow.
    7746                 :     // XXX Perhaps we should be doing this by twiddling the rect back to
    7747                 :     // mLastSize before calling Reflow and then switching it back, but
    7748                 :     // However, mLastSize can also be the size passed to BoxReflow by
    7749                 :     // RefreshSizeCache, so that doesn't really make sense.
    7750               0 :     if (metrics->mLastSize.width != aWidth) {
    7751               0 :       reflowState.mFlags.mHResize = true;
    7752                 : 
    7753                 :       // When font size inflation is enabled, a horizontal resize
    7754                 :       // requires a full reflow.  See nsHTMLReflowState::InitResizeFlags
    7755                 :       // for more details.
    7756               0 :       if (nsLayoutUtils::FontSizeInflationEnabled(aPresContext)) {
    7757               0 :         AddStateBits(NS_FRAME_IS_DIRTY);
    7758                 :       }
    7759                 :     }
    7760               0 :     if (metrics->mLastSize.height != aHeight)
    7761               0 :       reflowState.mFlags.mVResize = true;
    7762                 : 
    7763                 :     #ifdef DEBUG_REFLOW
    7764                 :       nsAdaptorAddIndents();
    7765                 :       printf("Size=(%d,%d)\n",reflowState.ComputedWidth(),
    7766                 :              reflowState.ComputedHeight());
    7767                 :       nsAdaptorAddIndents();
    7768                 :       nsAdaptorPrintReason(reflowState);
    7769                 :       printf("\n");
    7770                 :     #endif
    7771                 : 
    7772                 :        // place the child and reflow
    7773               0 :     WillReflow(aPresContext);
    7774                 : 
    7775               0 :     Reflow(aPresContext, aDesiredSize, reflowState, status);
    7776                 : 
    7777               0 :     NS_ASSERTION(NS_FRAME_IS_COMPLETE(status), "bad status");
    7778                 : 
    7779               0 :     if (redrawAfterReflow) {
    7780               0 :        nsRect r = GetRect();
    7781               0 :        r.width = aDesiredSize.width;
    7782               0 :        r.height = aDesiredSize.height;
    7783               0 :        Redraw(aState, &r);
    7784                 :     }
    7785                 : 
    7786               0 :     PRUint32 layoutFlags = aState.LayoutFlags();
    7787                 :     nsContainerFrame::FinishReflowChild(this, aPresContext, &reflowState,
    7788               0 :                                         aDesiredSize, aX, aY, layoutFlags | NS_FRAME_NO_MOVE_FRAME);
    7789                 : 
    7790                 :     // Save the ascent.  (bug 103925)
    7791               0 :     if (IsCollapsed()) {
    7792               0 :       metrics->mAscent = 0;
    7793                 :     } else {
    7794               0 :       if (aDesiredSize.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
    7795               0 :         if (!nsLayoutUtils::GetFirstLineBaseline(this, &metrics->mAscent))
    7796               0 :           metrics->mAscent = GetBaseline();
    7797                 :       } else
    7798               0 :         metrics->mAscent = aDesiredSize.ascent;
    7799                 :     }
    7800                 : 
    7801                 :   } else {
    7802               0 :     aDesiredSize.ascent = metrics->mBlockAscent;
    7803                 :   }
    7804                 : 
    7805                 : #ifdef DEBUG_REFLOW
    7806                 :   if (aHeight != NS_INTRINSICSIZE && aDesiredSize.height != aHeight)
    7807                 :   {
    7808                 :           nsAdaptorAddIndents();
    7809                 :           printf("*****got taller!*****\n");
    7810                 :          
    7811                 :   }
    7812                 :   if (aWidth != NS_INTRINSICSIZE && aDesiredSize.width != aWidth)
    7813                 :   {
    7814                 :           nsAdaptorAddIndents();
    7815                 :           printf("*****got wider!******\n");
    7816                 :          
    7817                 :   }
    7818                 : #endif
    7819                 : 
    7820               0 :   if (aWidth == NS_INTRINSICSIZE)
    7821               0 :      aWidth = aDesiredSize.width;
    7822                 : 
    7823               0 :   if (aHeight == NS_INTRINSICSIZE)
    7824               0 :      aHeight = aDesiredSize.height;
    7825                 : 
    7826               0 :   metrics->mLastSize.width = aDesiredSize.width;
    7827               0 :   metrics->mLastSize.height = aDesiredSize.height;
    7828                 : 
    7829                 : #ifdef DEBUG_REFLOW
    7830                 :   gIndent2--;
    7831                 : #endif
    7832                 : 
    7833               0 :   return NS_OK;
    7834                 : }
    7835                 : 
    7836                 : static void
    7837               0 : DestroyBoxMetrics(void* aPropertyValue)
    7838                 : {
    7839                 :   delete static_cast<nsBoxLayoutMetrics*>(aPropertyValue);
    7840               0 : }
    7841                 : 
    7842               0 : NS_DECLARE_FRAME_PROPERTY(BoxMetricsProperty, DestroyBoxMetrics)
    7843                 : 
    7844                 : nsBoxLayoutMetrics*
    7845               0 : nsFrame::BoxMetrics() const
    7846                 : {
    7847                 :   nsBoxLayoutMetrics* metrics =
    7848               0 :     static_cast<nsBoxLayoutMetrics*>(Properties().Get(BoxMetricsProperty()));
    7849               0 :   NS_ASSERTION(metrics, "A box layout method was called but InitBoxMetrics was never called");
    7850               0 :   return metrics;
    7851                 : }
    7852                 : 
    7853                 : void
    7854               0 : nsFrame::SetParent(nsIFrame* aParent)
    7855                 : {
    7856               0 :   bool wasBoxWrapped = IsBoxWrapped();
    7857               0 :   mParent = aParent;
    7858               0 :   if (!wasBoxWrapped && IsBoxWrapped()) {
    7859               0 :     InitBoxMetrics(true);
    7860               0 :   } else if (wasBoxWrapped && !IsBoxWrapped()) {
    7861               0 :     Properties().Delete(BoxMetricsProperty());
    7862                 :   }
    7863                 : 
    7864               0 :   if (GetStateBits() & (NS_FRAME_HAS_VIEW | NS_FRAME_HAS_CHILD_WITH_VIEW)) {
    7865               0 :     for (nsIFrame* f = aParent;
    7866               0 :          f && !(f->GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW);
    7867                 :          f = f->GetParent()) {
    7868               0 :       f->AddStateBits(NS_FRAME_HAS_CHILD_WITH_VIEW);
    7869                 :     }
    7870                 :   }
    7871                 : 
    7872               0 :   if (GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT) {
    7873               0 :     for (nsIFrame* f = aParent;
    7874               0 :          f && !(f->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT);
    7875                 :          f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
    7876               0 :       f->AddStateBits(NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT);
    7877                 :     }
    7878                 :   }
    7879               0 : }
    7880                 : 
    7881                 : void
    7882               0 : nsFrame::InitBoxMetrics(bool aClear)
    7883                 : {
    7884               0 :   FrameProperties props = Properties();
    7885               0 :   if (aClear) {
    7886               0 :     props.Delete(BoxMetricsProperty());
    7887                 :   }
    7888                 : 
    7889               0 :   nsBoxLayoutMetrics *metrics = new nsBoxLayoutMetrics();
    7890               0 :   props.Set(BoxMetricsProperty(), metrics);
    7891                 : 
    7892               0 :   nsFrame::MarkIntrinsicWidthsDirty();
    7893               0 :   metrics->mBlockAscent = 0;
    7894               0 :   metrics->mLastSize.SizeTo(0, 0);
    7895               0 : }
    7896                 : 
    7897                 : // Box layout debugging
    7898                 : #ifdef DEBUG_REFLOW
    7899                 : PRInt32 gIndent2 = 0;
    7900                 : 
    7901                 : void
    7902                 : nsAdaptorAddIndents()
    7903                 : {
    7904                 :     for(PRInt32 i=0; i < gIndent2; i++)
    7905                 :     {
    7906                 :         printf(" ");
    7907                 :     }
    7908                 : }
    7909                 : 
    7910                 : void
    7911                 : nsAdaptorPrintReason(nsHTMLReflowState& aReflowState)
    7912                 : {
    7913                 :     char* reflowReasonString;
    7914                 : 
    7915                 :     switch(aReflowState.reason) 
    7916                 :     {
    7917                 :         case eReflowReason_Initial:
    7918                 :           reflowReasonString = "initial";
    7919                 :           break;
    7920                 : 
    7921                 :         case eReflowReason_Resize:
    7922                 :           reflowReasonString = "resize";
    7923                 :           break;
    7924                 :         case eReflowReason_Dirty:
    7925                 :           reflowReasonString = "dirty";
    7926                 :           break;
    7927                 :         case eReflowReason_StyleChange:
    7928                 :           reflowReasonString = "stylechange";
    7929                 :           break;
    7930                 :         case eReflowReason_Incremental: 
    7931                 :         {
    7932                 :             switch (aReflowState.reflowCommand->Type()) {
    7933                 :               case eReflowType_StyleChanged:
    7934                 :                  reflowReasonString = "incremental (StyleChanged)";
    7935                 :               break;
    7936                 :               case eReflowType_ReflowDirty:
    7937                 :                  reflowReasonString = "incremental (ReflowDirty)";
    7938                 :               break;
    7939                 :               default:
    7940                 :                  reflowReasonString = "incremental (Unknown)";
    7941                 :             }
    7942                 :         }                             
    7943                 :         break;
    7944                 :         default:
    7945                 :           reflowReasonString = "unknown";
    7946                 :           break;
    7947                 :     }
    7948                 : 
    7949                 :     printf("%s",reflowReasonString);
    7950                 : }
    7951                 : 
    7952                 : #endif
    7953                 : #ifdef DEBUG_LAYOUT
    7954                 : void
    7955                 : nsFrame::GetBoxName(nsAutoString& aName)
    7956                 : {
    7957                 :   GetFrameName(aName);
    7958                 : }
    7959                 : #endif
    7960                 : 
    7961                 : #ifdef NS_DEBUG
    7962                 : static void
    7963               0 : GetTagName(nsFrame* aFrame, nsIContent* aContent, PRIntn aResultSize,
    7964                 :            char* aResult)
    7965                 : {
    7966               0 :   if (aContent) {
    7967                 :     PR_snprintf(aResult, aResultSize, "%s@%p",
    7968               0 :                 nsAtomCString(aContent->Tag()).get(), aFrame);
    7969                 :   }
    7970                 :   else {
    7971               0 :     PR_snprintf(aResult, aResultSize, "@%p", aFrame);
    7972                 :   }
    7973               0 : }
    7974                 : 
    7975                 : void
    7976               0 : nsFrame::Trace(const char* aMethod, bool aEnter)
    7977                 : {
    7978               0 :   if (NS_FRAME_LOG_TEST(gLogModule, NS_FRAME_TRACE_CALLS)) {
    7979                 :     char tagbuf[40];
    7980               0 :     GetTagName(this, mContent, sizeof(tagbuf), tagbuf);
    7981               0 :     PR_LogPrint("%s: %s %s", tagbuf, aEnter ? "enter" : "exit", aMethod);
    7982                 :   }
    7983               0 : }
    7984                 : 
    7985                 : void
    7986               0 : nsFrame::Trace(const char* aMethod, bool aEnter, nsReflowStatus aStatus)
    7987                 : {
    7988               0 :   if (NS_FRAME_LOG_TEST(gLogModule, NS_FRAME_TRACE_CALLS)) {
    7989                 :     char tagbuf[40];
    7990               0 :     GetTagName(this, mContent, sizeof(tagbuf), tagbuf);
    7991                 :     PR_LogPrint("%s: %s %s, status=%scomplete%s",
    7992                 :                 tagbuf, aEnter ? "enter" : "exit", aMethod,
    7993                 :                 NS_FRAME_IS_NOT_COMPLETE(aStatus) ? "not" : "",
    7994               0 :                 (NS_FRAME_REFLOW_NEXTINFLOW & aStatus) ? "+reflow" : "");
    7995                 :   }
    7996               0 : }
    7997                 : 
    7998                 : void
    7999               0 : nsFrame::TraceMsg(const char* aFormatString, ...)
    8000                 : {
    8001               0 :   if (NS_FRAME_LOG_TEST(gLogModule, NS_FRAME_TRACE_CALLS)) {
    8002                 :     // Format arguments into a buffer
    8003                 :     char argbuf[200];
    8004                 :     va_list ap;
    8005               0 :     va_start(ap, aFormatString);
    8006               0 :     PR_vsnprintf(argbuf, sizeof(argbuf), aFormatString, ap);
    8007               0 :     va_end(ap);
    8008                 : 
    8009                 :     char tagbuf[40];
    8010               0 :     GetTagName(this, mContent, sizeof(tagbuf), tagbuf);
    8011               0 :     PR_LogPrint("%s: %s", tagbuf, argbuf);
    8012                 :   }
    8013               0 : }
    8014                 : 
    8015                 : void
    8016               0 : nsFrame::VerifyDirtyBitSet(const nsFrameList& aFrameList)
    8017                 : {
    8018               0 :   for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
    8019               0 :     NS_ASSERTION(e.get()->GetStateBits() & NS_FRAME_IS_DIRTY,
    8020                 :                  "dirty bit not set");
    8021                 :   }
    8022               0 : }
    8023                 : 
    8024                 : // Start Display Reflow
    8025                 : #ifdef DEBUG
    8026                 : 
    8027               0 : DR_cookie::DR_cookie(nsPresContext*          aPresContext,
    8028                 :                      nsIFrame*                aFrame, 
    8029                 :                      const nsHTMLReflowState& aReflowState,
    8030                 :                      nsHTMLReflowMetrics&     aMetrics,
    8031                 :                      nsReflowStatus&          aStatus)
    8032               0 :   :mPresContext(aPresContext), mFrame(aFrame), mReflowState(aReflowState), mMetrics(aMetrics), mStatus(aStatus)
    8033                 : {
    8034               0 :   MOZ_COUNT_CTOR(DR_cookie);
    8035               0 :   mValue = nsFrame::DisplayReflowEnter(aPresContext, mFrame, mReflowState);
    8036               0 : }
    8037                 : 
    8038               0 : DR_cookie::~DR_cookie()
    8039                 : {
    8040               0 :   MOZ_COUNT_DTOR(DR_cookie);
    8041               0 :   nsFrame::DisplayReflowExit(mPresContext, mFrame, mMetrics, mStatus, mValue);
    8042               0 : }
    8043                 : 
    8044               0 : DR_layout_cookie::DR_layout_cookie(nsIFrame* aFrame)
    8045               0 :   : mFrame(aFrame)
    8046                 : {
    8047               0 :   MOZ_COUNT_CTOR(DR_layout_cookie);
    8048               0 :   mValue = nsFrame::DisplayLayoutEnter(mFrame);
    8049               0 : }
    8050                 : 
    8051               0 : DR_layout_cookie::~DR_layout_cookie()
    8052                 : {
    8053               0 :   MOZ_COUNT_DTOR(DR_layout_cookie);
    8054               0 :   nsFrame::DisplayLayoutExit(mFrame, mValue);
    8055               0 : }
    8056                 : 
    8057               0 : DR_intrinsic_width_cookie::DR_intrinsic_width_cookie(
    8058                 :                      nsIFrame*                aFrame, 
    8059                 :                      const char*              aType,
    8060                 :                      nscoord&                 aResult)
    8061                 :   : mFrame(aFrame)
    8062                 :   , mType(aType)
    8063               0 :   , mResult(aResult)
    8064                 : {
    8065               0 :   MOZ_COUNT_CTOR(DR_intrinsic_width_cookie);
    8066               0 :   mValue = nsFrame::DisplayIntrinsicWidthEnter(mFrame, mType);
    8067               0 : }
    8068                 : 
    8069               0 : DR_intrinsic_width_cookie::~DR_intrinsic_width_cookie()
    8070                 : {
    8071               0 :   MOZ_COUNT_DTOR(DR_intrinsic_width_cookie);
    8072               0 :   nsFrame::DisplayIntrinsicWidthExit(mFrame, mType, mResult, mValue);
    8073               0 : }
    8074                 : 
    8075               0 : DR_intrinsic_size_cookie::DR_intrinsic_size_cookie(
    8076                 :                      nsIFrame*                aFrame, 
    8077                 :                      const char*              aType,
    8078                 :                      nsSize&                  aResult)
    8079                 :   : mFrame(aFrame)
    8080                 :   , mType(aType)
    8081               0 :   , mResult(aResult)
    8082                 : {
    8083               0 :   MOZ_COUNT_CTOR(DR_intrinsic_size_cookie);
    8084               0 :   mValue = nsFrame::DisplayIntrinsicSizeEnter(mFrame, mType);
    8085               0 : }
    8086                 : 
    8087               0 : DR_intrinsic_size_cookie::~DR_intrinsic_size_cookie()
    8088                 : {
    8089               0 :   MOZ_COUNT_DTOR(DR_intrinsic_size_cookie);
    8090               0 :   nsFrame::DisplayIntrinsicSizeExit(mFrame, mType, mResult, mValue);
    8091               0 : }
    8092                 : 
    8093               0 : DR_init_constraints_cookie::DR_init_constraints_cookie(
    8094                 :                      nsIFrame*                aFrame,
    8095                 :                      nsHTMLReflowState*       aState,
    8096                 :                      nscoord                  aCBWidth,
    8097                 :                      nscoord                  aCBHeight,
    8098                 :                      const nsMargin*          aMargin,
    8099                 :                      const nsMargin*          aPadding)
    8100                 :   : mFrame(aFrame)
    8101               0 :   , mState(aState)
    8102                 : {
    8103               0 :   MOZ_COUNT_CTOR(DR_init_constraints_cookie);
    8104                 :   mValue = nsHTMLReflowState::DisplayInitConstraintsEnter(mFrame, mState,
    8105                 :                                                           aCBWidth, aCBHeight,
    8106               0 :                                                           aMargin, aPadding);
    8107               0 : }
    8108                 : 
    8109               0 : DR_init_constraints_cookie::~DR_init_constraints_cookie()
    8110                 : {
    8111               0 :   MOZ_COUNT_DTOR(DR_init_constraints_cookie);
    8112               0 :   nsHTMLReflowState::DisplayInitConstraintsExit(mFrame, mState, mValue);
    8113               0 : }
    8114                 : 
    8115               0 : DR_init_offsets_cookie::DR_init_offsets_cookie(
    8116                 :                      nsIFrame*                aFrame,
    8117                 :                      nsCSSOffsetState*        aState,
    8118                 :                      nscoord                  aCBWidth,
    8119                 :                      const nsMargin*          aMargin,
    8120                 :                      const nsMargin*          aPadding)
    8121                 :   : mFrame(aFrame)
    8122               0 :   , mState(aState)
    8123                 : {
    8124               0 :   MOZ_COUNT_CTOR(DR_init_offsets_cookie);
    8125                 :   mValue = nsCSSOffsetState::DisplayInitOffsetsEnter(mFrame, mState, aCBWidth,
    8126               0 :                                                      aMargin, aPadding);
    8127               0 : }
    8128                 : 
    8129               0 : DR_init_offsets_cookie::~DR_init_offsets_cookie()
    8130                 : {
    8131               0 :   MOZ_COUNT_DTOR(DR_init_offsets_cookie);
    8132               0 :   nsCSSOffsetState::DisplayInitOffsetsExit(mFrame, mState, mValue);
    8133               0 : }
    8134                 : 
    8135               0 : DR_init_type_cookie::DR_init_type_cookie(
    8136                 :                      nsIFrame*                aFrame,
    8137                 :                      nsHTMLReflowState*       aState)
    8138                 :   : mFrame(aFrame)
    8139               0 :   , mState(aState)
    8140                 : {
    8141               0 :   MOZ_COUNT_CTOR(DR_init_type_cookie);
    8142               0 :   mValue = nsHTMLReflowState::DisplayInitFrameTypeEnter(mFrame, mState);
    8143               0 : }
    8144                 : 
    8145               0 : DR_init_type_cookie::~DR_init_type_cookie()
    8146                 : {
    8147               0 :   MOZ_COUNT_DTOR(DR_init_type_cookie);
    8148               0 :   nsHTMLReflowState::DisplayInitFrameTypeExit(mFrame, mState, mValue);
    8149               0 : }
    8150                 : 
    8151                 : struct DR_FrameTypeInfo;
    8152                 : struct DR_FrameTreeNode;
    8153                 : struct DR_Rule;
    8154                 : 
    8155                 : struct DR_State
    8156                 : {
    8157                 :   DR_State();
    8158                 :   ~DR_State();
    8159                 :   void Init();
    8160                 :   void AddFrameTypeInfo(nsIAtom* aFrameType,
    8161                 :                         const char* aFrameNameAbbrev,
    8162                 :                         const char* aFrameName);
    8163                 :   DR_FrameTypeInfo* GetFrameTypeInfo(nsIAtom* aFrameType);
    8164                 :   DR_FrameTypeInfo* GetFrameTypeInfo(char* aFrameName);
    8165                 :   void InitFrameTypeTable();
    8166                 :   DR_FrameTreeNode* CreateTreeNode(nsIFrame*                aFrame,
    8167                 :                                    const nsHTMLReflowState* aReflowState);
    8168                 :   void FindMatchingRule(DR_FrameTreeNode& aNode);
    8169                 :   bool RuleMatches(DR_Rule&          aRule,
    8170                 :                      DR_FrameTreeNode& aNode);
    8171                 :   bool GetToken(FILE* aFile,
    8172                 :                   char* aBuf,
    8173                 :                   size_t aBufSize);
    8174                 :   DR_Rule* ParseRule(FILE* aFile);
    8175                 :   void ParseRulesFile();
    8176                 :   void AddRule(nsTArray<DR_Rule*>& aRules,
    8177                 :                DR_Rule&            aRule);
    8178                 :   bool IsWhiteSpace(int c);
    8179                 :   bool GetNumber(char*    aBuf, 
    8180                 :                  PRInt32&  aNumber);
    8181                 :   void PrettyUC(nscoord aSize,
    8182                 :                 char*   aBuf);
    8183                 :   void PrintMargin(const char* tag, const nsMargin* aMargin);
    8184                 :   void DisplayFrameTypeInfo(nsIFrame* aFrame,
    8185                 :                             PRInt32   aIndent);
    8186                 :   void DeleteTreeNode(DR_FrameTreeNode& aNode);
    8187                 : 
    8188                 :   bool        mInited;
    8189                 :   bool        mActive;
    8190                 :   PRInt32     mCount;
    8191                 :   PRInt32     mAssert;
    8192                 :   PRInt32     mIndent;
    8193                 :   bool        mIndentUndisplayedFrames;
    8194                 :   bool        mDisplayPixelErrors;
    8195                 :   nsTArray<DR_Rule*>          mWildRules;
    8196                 :   nsTArray<DR_FrameTypeInfo>  mFrameTypeTable;
    8197                 :   // reflow specific state
    8198                 :   nsTArray<DR_FrameTreeNode*> mFrameTreeLeaves;
    8199                 : };
    8200                 : 
    8201                 : static DR_State *DR_state; // the one and only DR_State
    8202                 : 
    8203                 : struct DR_RulePart 
    8204                 : {
    8205               0 :   DR_RulePart(nsIAtom* aFrameType) : mFrameType(aFrameType), mNext(0) {}
    8206                 :   void Destroy();
    8207                 : 
    8208                 :   nsIAtom*     mFrameType;
    8209                 :   DR_RulePart* mNext;
    8210                 : };
    8211                 : 
    8212               0 : void DR_RulePart::Destroy()
    8213                 : {
    8214               0 :   if (mNext) {
    8215               0 :     mNext->Destroy();
    8216                 :   }
    8217                 :   delete this;
    8218               0 : }
    8219                 : 
    8220                 : struct DR_Rule 
    8221                 : {
    8222               0 :   DR_Rule() : mLength(0), mTarget(nsnull), mDisplay(false) {
    8223               0 :     MOZ_COUNT_CTOR(DR_Rule);
    8224               0 :   }
    8225               0 :   ~DR_Rule() {
    8226               0 :     if (mTarget) mTarget->Destroy();
    8227               0 :     MOZ_COUNT_DTOR(DR_Rule);
    8228               0 :   }
    8229                 :   void AddPart(nsIAtom* aFrameType);
    8230                 : 
    8231                 :   PRUint32      mLength;
    8232                 :   DR_RulePart*  mTarget;
    8233                 :   bool          mDisplay;
    8234                 : };
    8235                 : 
    8236               0 : void DR_Rule::AddPart(nsIAtom* aFrameType)
    8237                 : {
    8238               0 :   DR_RulePart* newPart = new DR_RulePart(aFrameType);
    8239               0 :   newPart->mNext = mTarget;
    8240               0 :   mTarget = newPart;
    8241               0 :   mLength++;
    8242               0 : }
    8243                 : 
    8244                 : struct DR_FrameTypeInfo
    8245               0 : {
    8246                 :   DR_FrameTypeInfo(nsIAtom* aFrmeType, const char* aFrameNameAbbrev, const char* aFrameName);
    8247               0 :   ~DR_FrameTypeInfo() { 
    8248                 :       PRInt32 numElements;
    8249               0 :       numElements = mRules.Length();
    8250               0 :       for (PRInt32 i = numElements - 1; i >= 0; i--) {
    8251               0 :         delete mRules.ElementAt(i);
    8252                 :       }
    8253               0 :    }
    8254                 : 
    8255                 :   nsIAtom*    mType;
    8256                 :   char        mNameAbbrev[16];
    8257                 :   char        mName[32];
    8258                 :   nsTArray<DR_Rule*> mRules;
    8259                 : private:
    8260                 :   DR_FrameTypeInfo& operator=(const DR_FrameTypeInfo&) MOZ_DELETE;
    8261                 : };
    8262                 : 
    8263               0 : DR_FrameTypeInfo::DR_FrameTypeInfo(nsIAtom* aFrameType, 
    8264                 :                                    const char* aFrameNameAbbrev, 
    8265               0 :                                    const char* aFrameName)
    8266                 : {
    8267               0 :   mType = aFrameType;
    8268               0 :   PL_strncpyz(mNameAbbrev, aFrameNameAbbrev, sizeof(mNameAbbrev));
    8269               0 :   PL_strncpyz(mName, aFrameName, sizeof(mName));
    8270               0 : }
    8271                 : 
    8272                 : struct DR_FrameTreeNode
    8273                 : {
    8274               0 :   DR_FrameTreeNode(nsIFrame* aFrame, DR_FrameTreeNode* aParent) : mFrame(aFrame), mParent(aParent), mDisplay(0), mIndent(0)
    8275                 :   {
    8276               0 :     MOZ_COUNT_CTOR(DR_FrameTreeNode);
    8277               0 :   }
    8278                 : 
    8279               0 :   ~DR_FrameTreeNode()
    8280                 :   {
    8281               0 :     MOZ_COUNT_DTOR(DR_FrameTreeNode);
    8282               0 :   }
    8283                 : 
    8284                 :   nsIFrame*         mFrame;
    8285                 :   DR_FrameTreeNode* mParent;
    8286                 :   bool              mDisplay;
    8287                 :   PRUint32          mIndent;
    8288                 : };
    8289                 : 
    8290                 : // DR_State implementation
    8291                 : 
    8292            1404 : DR_State::DR_State() 
    8293                 : : mInited(false), mActive(false), mCount(0), mAssert(-1), mIndent(0), 
    8294            1404 :   mIndentUndisplayedFrames(false), mDisplayPixelErrors(false)
    8295                 : {
    8296            1404 :   MOZ_COUNT_CTOR(DR_State);
    8297            1404 : }
    8298                 : 
    8299               0 : void DR_State::Init() 
    8300                 : {
    8301               0 :   char* env = PR_GetEnv("GECKO_DISPLAY_REFLOW_ASSERT");
    8302                 :   PRInt32 num;
    8303               0 :   if (env) {
    8304               0 :     if (GetNumber(env, num)) 
    8305               0 :       mAssert = num;
    8306                 :     else 
    8307               0 :       printf("GECKO_DISPLAY_REFLOW_ASSERT - invalid value = %s", env);
    8308                 :   }
    8309                 : 
    8310               0 :   env = PR_GetEnv("GECKO_DISPLAY_REFLOW_INDENT_START");
    8311               0 :   if (env) {
    8312               0 :     if (GetNumber(env, num)) 
    8313               0 :       mIndent = num;
    8314                 :     else 
    8315               0 :       printf("GECKO_DISPLAY_REFLOW_INDENT_START - invalid value = %s", env);
    8316                 :   }
    8317                 : 
    8318               0 :   env = PR_GetEnv("GECKO_DISPLAY_REFLOW_INDENT_UNDISPLAYED_FRAMES");
    8319               0 :   if (env) {
    8320               0 :     if (GetNumber(env, num)) 
    8321               0 :       mIndentUndisplayedFrames = num;
    8322                 :     else 
    8323               0 :       printf("GECKO_DISPLAY_REFLOW_INDENT_UNDISPLAYED_FRAMES - invalid value = %s", env);
    8324                 :   }
    8325                 : 
    8326               0 :   env = PR_GetEnv("GECKO_DISPLAY_REFLOW_FLAG_PIXEL_ERRORS");
    8327               0 :   if (env) {
    8328               0 :     if (GetNumber(env, num)) 
    8329               0 :       mDisplayPixelErrors = num;
    8330                 :     else 
    8331               0 :       printf("GECKO_DISPLAY_REFLOW_FLAG_PIXEL_ERRORS - invalid value = %s", env);
    8332                 :   }
    8333                 : 
    8334               0 :   InitFrameTypeTable();
    8335               0 :   ParseRulesFile();
    8336               0 :   mInited = true;
    8337               0 : }
    8338                 : 
    8339            2806 : DR_State::~DR_State()
    8340                 : {
    8341            1403 :   MOZ_COUNT_DTOR(DR_State);
    8342                 :   PRInt32 numElements, i;
    8343            1403 :   numElements = mWildRules.Length();
    8344            1403 :   for (i = numElements - 1; i >= 0; i--) {
    8345               0 :     delete mWildRules.ElementAt(i);
    8346                 :   }
    8347            1403 :   numElements = mFrameTreeLeaves.Length();
    8348            1403 :   for (i = numElements - 1; i >= 0; i--) {
    8349               0 :     delete mFrameTreeLeaves.ElementAt(i);
    8350                 :   }
    8351            1403 : }
    8352                 : 
    8353               0 : bool DR_State::GetNumber(char*     aBuf, 
    8354                 :                            PRInt32&  aNumber)
    8355                 : {
    8356               0 :   if (sscanf(aBuf, "%d", &aNumber) > 0) 
    8357               0 :     return true;
    8358                 :   else 
    8359               0 :     return false;
    8360                 : }
    8361                 : 
    8362               0 : bool DR_State::IsWhiteSpace(int c) {
    8363               0 :   return (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r');
    8364                 : }
    8365                 : 
    8366               0 : bool DR_State::GetToken(FILE* aFile,
    8367                 :                           char* aBuf,
    8368                 :                           size_t aBufSize)
    8369                 : {
    8370               0 :   bool haveToken = false;
    8371               0 :   aBuf[0] = 0;
    8372                 :   // get the 1st non whitespace char
    8373               0 :   int c = -1;
    8374               0 :   for (c = getc(aFile); (c > 0) && IsWhiteSpace(c); c = getc(aFile)) {
    8375                 :   }
    8376                 : 
    8377               0 :   if (c > 0) {
    8378               0 :     haveToken = true;
    8379               0 :     aBuf[0] = c;
    8380                 :     // get everything up to the next whitespace char
    8381                 :     size_t cX;
    8382               0 :     for (cX = 1; cX + 1 < aBufSize ; cX++) {
    8383               0 :       c = getc(aFile);
    8384               0 :       if (c < 0) { // EOF
    8385               0 :         ungetc(' ', aFile); 
    8386               0 :         break;
    8387                 :       }
    8388                 :       else {
    8389               0 :         if (IsWhiteSpace(c)) {
    8390               0 :           break;
    8391                 :         }
    8392                 :         else {
    8393               0 :           aBuf[cX] = c;
    8394                 :         }
    8395                 :       }
    8396                 :     }
    8397               0 :     aBuf[cX] = 0;
    8398                 :   }
    8399               0 :   return haveToken;
    8400                 : }
    8401                 : 
    8402               0 : DR_Rule* DR_State::ParseRule(FILE* aFile)
    8403                 : {
    8404                 :   char buf[128];
    8405                 :   PRInt32 doDisplay;
    8406               0 :   DR_Rule* rule = nsnull;
    8407               0 :   while (GetToken(aFile, buf, sizeof(buf))) {
    8408               0 :     if (GetNumber(buf, doDisplay)) {
    8409               0 :       if (rule) { 
    8410               0 :         rule->mDisplay = !!doDisplay;
    8411               0 :         break;
    8412                 :       }
    8413                 :       else {
    8414               0 :         printf("unexpected token - %s \n", buf);
    8415                 :       }
    8416                 :     }
    8417                 :     else {
    8418               0 :       if (!rule) {
    8419               0 :         rule = new DR_Rule;
    8420                 :       }
    8421               0 :       if (strcmp(buf, "*") == 0) {
    8422               0 :         rule->AddPart(nsnull);
    8423                 :       }
    8424                 :       else {
    8425               0 :         DR_FrameTypeInfo* info = GetFrameTypeInfo(buf);
    8426               0 :         if (info) {
    8427               0 :           rule->AddPart(info->mType);
    8428                 :         }
    8429                 :         else {
    8430               0 :           printf("invalid frame type - %s \n", buf);
    8431                 :         }
    8432                 :       }
    8433                 :     }
    8434                 :   }
    8435               0 :   return rule;
    8436                 : }
    8437                 : 
    8438               0 : void DR_State::AddRule(nsTArray<DR_Rule*>& aRules,
    8439                 :                        DR_Rule&            aRule)
    8440                 : {
    8441               0 :   PRInt32 numRules = aRules.Length();
    8442               0 :   for (PRInt32 ruleX = 0; ruleX < numRules; ruleX++) {
    8443               0 :     DR_Rule* rule = aRules.ElementAt(ruleX);
    8444               0 :     NS_ASSERTION(rule, "program error");
    8445               0 :     if (aRule.mLength > rule->mLength) {
    8446               0 :       aRules.InsertElementAt(ruleX, &aRule);
    8447               0 :       return;
    8448                 :     }
    8449                 :   }
    8450               0 :   aRules.AppendElement(&aRule);
    8451                 : }
    8452                 : 
    8453               0 : void DR_State::ParseRulesFile()
    8454                 : {
    8455               0 :   char* path = PR_GetEnv("GECKO_DISPLAY_REFLOW_RULES_FILE");
    8456               0 :   if (path) {
    8457               0 :     FILE* inFile = fopen(path, "r");
    8458               0 :     if (inFile) {
    8459               0 :       for (DR_Rule* rule = ParseRule(inFile); rule; rule = ParseRule(inFile)) {
    8460               0 :         if (rule->mTarget) {
    8461               0 :           nsIAtom* fType = rule->mTarget->mFrameType;
    8462               0 :           if (fType) {
    8463               0 :             DR_FrameTypeInfo* info = GetFrameTypeInfo(fType);
    8464               0 :             if (info) {
    8465               0 :               AddRule(info->mRules, *rule);
    8466                 :             }
    8467                 :           }
    8468                 :           else {
    8469               0 :             AddRule(mWildRules, *rule);
    8470                 :           }
    8471               0 :           mActive = true;
    8472                 :         }
    8473                 :       }
    8474                 :     }
    8475                 :   }
    8476               0 : }
    8477                 : 
    8478                 : 
    8479               0 : void DR_State::AddFrameTypeInfo(nsIAtom* aFrameType,
    8480                 :                                 const char* aFrameNameAbbrev,
    8481                 :                                 const char* aFrameName)
    8482                 : {
    8483               0 :   mFrameTypeTable.AppendElement(DR_FrameTypeInfo(aFrameType, aFrameNameAbbrev, aFrameName));
    8484               0 : }
    8485                 : 
    8486               0 : DR_FrameTypeInfo* DR_State::GetFrameTypeInfo(nsIAtom* aFrameType)
    8487                 : {
    8488               0 :   PRInt32 numEntries = mFrameTypeTable.Length();
    8489               0 :   NS_ASSERTION(numEntries != 0, "empty FrameTypeTable");
    8490               0 :   for (PRInt32 i = 0; i < numEntries; i++) {
    8491               0 :     DR_FrameTypeInfo& info = mFrameTypeTable.ElementAt(i);
    8492               0 :     if (info.mType == aFrameType) {
    8493               0 :       return &info;
    8494                 :     }
    8495                 :   }
    8496               0 :   return &mFrameTypeTable.ElementAt(numEntries - 1); // return unknown frame type
    8497                 : }
    8498                 : 
    8499               0 : DR_FrameTypeInfo* DR_State::GetFrameTypeInfo(char* aFrameName)
    8500                 : {
    8501               0 :   PRInt32 numEntries = mFrameTypeTable.Length();
    8502               0 :   NS_ASSERTION(numEntries != 0, "empty FrameTypeTable");
    8503               0 :   for (PRInt32 i = 0; i < numEntries; i++) {
    8504               0 :     DR_FrameTypeInfo& info = mFrameTypeTable.ElementAt(i);
    8505               0 :     if ((strcmp(aFrameName, info.mName) == 0) || (strcmp(aFrameName, info.mNameAbbrev) == 0)) {
    8506               0 :       return &info;
    8507                 :     }
    8508                 :   }
    8509               0 :   return &mFrameTypeTable.ElementAt(numEntries - 1); // return unknown frame type
    8510                 : }
    8511                 : 
    8512               0 : void DR_State::InitFrameTypeTable()
    8513                 : {  
    8514               0 :   AddFrameTypeInfo(nsGkAtoms::blockFrame,            "block",     "block");
    8515               0 :   AddFrameTypeInfo(nsGkAtoms::brFrame,               "br",        "br");
    8516               0 :   AddFrameTypeInfo(nsGkAtoms::bulletFrame,           "bullet",    "bullet");
    8517               0 :   AddFrameTypeInfo(nsGkAtoms::gfxButtonControlFrame, "button",    "gfxButtonControl");
    8518               0 :   AddFrameTypeInfo(nsGkAtoms::HTMLButtonControlFrame, "HTMLbutton",    "HTMLButtonControl");
    8519               0 :   AddFrameTypeInfo(nsGkAtoms::HTMLCanvasFrame,       "HTMLCanvas","HTMLCanvas");
    8520               0 :   AddFrameTypeInfo(nsGkAtoms::subDocumentFrame,      "subdoc",    "subDocument");
    8521               0 :   AddFrameTypeInfo(nsGkAtoms::imageFrame,            "img",       "image");
    8522               0 :   AddFrameTypeInfo(nsGkAtoms::inlineFrame,           "inline",    "inline");
    8523               0 :   AddFrameTypeInfo(nsGkAtoms::letterFrame,           "letter",    "letter");
    8524               0 :   AddFrameTypeInfo(nsGkAtoms::lineFrame,             "line",      "line");
    8525               0 :   AddFrameTypeInfo(nsGkAtoms::listControlFrame,      "select",    "select");
    8526               0 :   AddFrameTypeInfo(nsGkAtoms::objectFrame,           "obj",       "object");
    8527               0 :   AddFrameTypeInfo(nsGkAtoms::pageFrame,             "page",      "page");
    8528               0 :   AddFrameTypeInfo(nsGkAtoms::placeholderFrame,      "place",     "placeholder");
    8529               0 :   AddFrameTypeInfo(nsGkAtoms::canvasFrame,           "canvas",    "canvas");
    8530               0 :   AddFrameTypeInfo(nsGkAtoms::rootFrame,             "root",      "root");
    8531               0 :   AddFrameTypeInfo(nsGkAtoms::scrollFrame,           "scroll",    "scroll");
    8532               0 :   AddFrameTypeInfo(nsGkAtoms::tableCaptionFrame,     "caption",   "tableCaption");
    8533               0 :   AddFrameTypeInfo(nsGkAtoms::tableCellFrame,        "cell",      "tableCell");
    8534               0 :   AddFrameTypeInfo(nsGkAtoms::bcTableCellFrame,      "bcCell",    "bcTableCell");
    8535               0 :   AddFrameTypeInfo(nsGkAtoms::tableColFrame,         "col",       "tableCol");
    8536               0 :   AddFrameTypeInfo(nsGkAtoms::tableColGroupFrame,    "colG",      "tableColGroup");
    8537               0 :   AddFrameTypeInfo(nsGkAtoms::tableFrame,            "tbl",       "table");
    8538               0 :   AddFrameTypeInfo(nsGkAtoms::tableOuterFrame,       "tblO",      "tableOuter");
    8539               0 :   AddFrameTypeInfo(nsGkAtoms::tableRowGroupFrame,    "rowG",      "tableRowGroup");
    8540               0 :   AddFrameTypeInfo(nsGkAtoms::tableRowFrame,         "row",       "tableRow");
    8541               0 :   AddFrameTypeInfo(nsGkAtoms::textInputFrame,        "textCtl",   "textInput");
    8542               0 :   AddFrameTypeInfo(nsGkAtoms::textFrame,             "text",      "text");
    8543               0 :   AddFrameTypeInfo(nsGkAtoms::viewportFrame,         "VP",        "viewport");
    8544                 : #ifdef MOZ_XUL
    8545               0 :   AddFrameTypeInfo(nsGkAtoms::XULLabelFrame,         "XULLabel",  "XULLabel");
    8546               0 :   AddFrameTypeInfo(nsGkAtoms::boxFrame,              "Box",       "Box");
    8547               0 :   AddFrameTypeInfo(nsGkAtoms::sliderFrame,           "Slider",    "Slider");
    8548               0 :   AddFrameTypeInfo(nsGkAtoms::popupSetFrame,         "PopupSet",  "PopupSet");
    8549                 : #endif
    8550               0 :   AddFrameTypeInfo(nsnull,                               "unknown",   "unknown");
    8551               0 : }
    8552                 : 
    8553                 : 
    8554               0 : void DR_State::DisplayFrameTypeInfo(nsIFrame* aFrame,
    8555                 :                                     PRInt32   aIndent)
    8556                 : { 
    8557               0 :   DR_FrameTypeInfo* frameTypeInfo = GetFrameTypeInfo(aFrame->GetType());
    8558               0 :   if (frameTypeInfo) {
    8559               0 :     for (PRInt32 i = 0; i < aIndent; i++) {
    8560               0 :       printf(" ");
    8561                 :     }
    8562               0 :     if(!strcmp(frameTypeInfo->mNameAbbrev, "unknown")) {
    8563               0 :       if (aFrame) {
    8564               0 :        nsAutoString  name;
    8565               0 :        aFrame->GetFrameName(name);
    8566               0 :        printf("%s %p ", NS_LossyConvertUTF16toASCII(name).get(), (void*)aFrame);
    8567                 :       }
    8568                 :       else {
    8569               0 :         printf("%s %p ", frameTypeInfo->mNameAbbrev, (void*)aFrame);
    8570                 :       }
    8571                 :     }
    8572                 :     else {
    8573               0 :       printf("%s %p ", frameTypeInfo->mNameAbbrev, (void*)aFrame);
    8574                 :     }
    8575                 :   }
    8576               0 : }
    8577                 : 
    8578               0 : bool DR_State::RuleMatches(DR_Rule&          aRule,
    8579                 :                              DR_FrameTreeNode& aNode)
    8580                 : {
    8581               0 :   NS_ASSERTION(aRule.mTarget, "program error");
    8582                 : 
    8583                 :   DR_RulePart* rulePart;
    8584                 :   DR_FrameTreeNode* parentNode;
    8585               0 :   for (rulePart = aRule.mTarget->mNext, parentNode = aNode.mParent;
    8586                 :        rulePart && parentNode;
    8587                 :        rulePart = rulePart->mNext, parentNode = parentNode->mParent) {
    8588               0 :     if (rulePart->mFrameType) {
    8589               0 :       if (parentNode->mFrame) {
    8590               0 :         if (rulePart->mFrameType != parentNode->mFrame->GetType()) {
    8591               0 :           return false;
    8592                 :         }
    8593                 :       }
    8594               0 :       else NS_ASSERTION(false, "program error");
    8595                 :     }
    8596                 :     // else wild card match
    8597                 :   }
    8598               0 :   return true;
    8599                 : }
    8600                 : 
    8601               0 : void DR_State::FindMatchingRule(DR_FrameTreeNode& aNode)
    8602                 : {
    8603               0 :   if (!aNode.mFrame) {
    8604               0 :     NS_ASSERTION(false, "invalid DR_FrameTreeNode \n");
    8605               0 :     return;
    8606                 :   }
    8607                 : 
    8608               0 :   bool matchingRule = false;
    8609                 : 
    8610               0 :   DR_FrameTypeInfo* info = GetFrameTypeInfo(aNode.mFrame->GetType());
    8611               0 :   NS_ASSERTION(info, "program error");
    8612               0 :   PRInt32 numRules = info->mRules.Length();
    8613               0 :   for (PRInt32 ruleX = 0; ruleX < numRules; ruleX++) {
    8614               0 :     DR_Rule* rule = info->mRules.ElementAt(ruleX);
    8615               0 :     if (rule && RuleMatches(*rule, aNode)) {
    8616               0 :       aNode.mDisplay = rule->mDisplay;
    8617               0 :       matchingRule = true;
    8618               0 :       break;
    8619                 :     }
    8620                 :   }
    8621               0 :   if (!matchingRule) {
    8622               0 :     PRInt32 numWildRules = mWildRules.Length();
    8623               0 :     for (PRInt32 ruleX = 0; ruleX < numWildRules; ruleX++) {
    8624               0 :       DR_Rule* rule = mWildRules.ElementAt(ruleX);
    8625               0 :       if (rule && RuleMatches(*rule, aNode)) {
    8626               0 :         aNode.mDisplay = rule->mDisplay;
    8627               0 :         break;
    8628                 :       }
    8629                 :     }
    8630                 :   }
    8631                 : }
    8632                 :     
    8633               0 : DR_FrameTreeNode* DR_State::CreateTreeNode(nsIFrame*                aFrame,
    8634                 :                                            const nsHTMLReflowState* aReflowState)
    8635                 : {
    8636                 :   // find the frame of the parent reflow state (usually just the parent of aFrame)
    8637                 :   nsIFrame* parentFrame;
    8638               0 :   if (aReflowState) {
    8639               0 :     const nsHTMLReflowState* parentRS = aReflowState->parentReflowState;
    8640               0 :     parentFrame = (parentRS) ? parentRS->frame : nsnull;
    8641                 :   } else {
    8642               0 :     parentFrame = aFrame->GetParent();
    8643                 :   }
    8644                 : 
    8645                 :   // find the parent tree node leaf
    8646               0 :   DR_FrameTreeNode* parentNode = nsnull;
    8647                 :   
    8648               0 :   DR_FrameTreeNode* lastLeaf = nsnull;
    8649               0 :   if(mFrameTreeLeaves.Length())
    8650               0 :     lastLeaf = mFrameTreeLeaves.ElementAt(mFrameTreeLeaves.Length() - 1);
    8651               0 :   if (lastLeaf) {
    8652               0 :     for (parentNode = lastLeaf; parentNode && (parentNode->mFrame != parentFrame); parentNode = parentNode->mParent) {
    8653                 :     }
    8654                 :   }
    8655               0 :   DR_FrameTreeNode* newNode = new DR_FrameTreeNode(aFrame, parentNode);
    8656               0 :   FindMatchingRule(*newNode);
    8657                 : 
    8658               0 :   newNode->mIndent = mIndent;
    8659               0 :   if (newNode->mDisplay || mIndentUndisplayedFrames) {
    8660               0 :     ++mIndent;
    8661                 :   }
    8662                 : 
    8663               0 :   if (lastLeaf && (lastLeaf == parentNode)) {
    8664               0 :     mFrameTreeLeaves.RemoveElementAt(mFrameTreeLeaves.Length() - 1);
    8665                 :   }
    8666               0 :   mFrameTreeLeaves.AppendElement(newNode);
    8667               0 :   mCount++;
    8668                 : 
    8669               0 :   return newNode;
    8670                 : }
    8671                 : 
    8672               0 : void DR_State::PrettyUC(nscoord aSize,
    8673                 :                         char*   aBuf)
    8674                 : {
    8675               0 :   if (NS_UNCONSTRAINEDSIZE == aSize) {
    8676               0 :     strcpy(aBuf, "UC");
    8677                 :   }
    8678                 :   else {
    8679               0 :     if ((nscoord)0xdeadbeefU == aSize)
    8680                 :     {
    8681               0 :       strcpy(aBuf, "deadbeef");
    8682                 :     }
    8683                 :     else {
    8684               0 :       sprintf(aBuf, "%d", aSize);
    8685                 :     }
    8686                 :   }
    8687               0 : }
    8688                 : 
    8689               0 : void DR_State::PrintMargin(const char *tag, const nsMargin* aMargin)
    8690                 : {
    8691               0 :   if (aMargin) {
    8692                 :     char t[16], r[16], b[16], l[16];
    8693               0 :     PrettyUC(aMargin->top, t);
    8694               0 :     PrettyUC(aMargin->right, r);
    8695               0 :     PrettyUC(aMargin->bottom, b);
    8696               0 :     PrettyUC(aMargin->left, l);
    8697               0 :     printf(" %s=%s,%s,%s,%s", tag, t, r, b, l);
    8698                 :   } else {
    8699                 :     // use %p here for consistency with other null-pointer printouts
    8700               0 :     printf(" %s=%p", tag, (void*)aMargin);
    8701                 :   }
    8702               0 : }
    8703                 : 
    8704               0 : void DR_State::DeleteTreeNode(DR_FrameTreeNode& aNode)
    8705                 : {
    8706               0 :   mFrameTreeLeaves.RemoveElement(&aNode);
    8707               0 :   PRInt32 numLeaves = mFrameTreeLeaves.Length();
    8708               0 :   if ((0 == numLeaves) || (aNode.mParent != mFrameTreeLeaves.ElementAt(numLeaves - 1))) {
    8709               0 :     mFrameTreeLeaves.AppendElement(aNode.mParent);
    8710                 :   }
    8711                 : 
    8712               0 :   if (aNode.mDisplay || mIndentUndisplayedFrames) {
    8713               0 :     --mIndent;
    8714                 :   }
    8715                 :   // delete the tree node 
    8716               0 :   delete &aNode;
    8717               0 : }
    8718                 : 
    8719                 : static void
    8720               0 : CheckPixelError(nscoord aSize,
    8721                 :                 PRInt32 aPixelToTwips)
    8722                 : {
    8723               0 :   if (NS_UNCONSTRAINEDSIZE != aSize) {
    8724               0 :     if ((aSize % aPixelToTwips) > 0) {
    8725               0 :       printf("VALUE %d is not a whole pixel \n", aSize);
    8726                 :     }
    8727                 :   }
    8728               0 : }
    8729                 : 
    8730               0 : static void DisplayReflowEnterPrint(nsPresContext*          aPresContext,
    8731                 :                                     nsIFrame*                aFrame,
    8732                 :                                     const nsHTMLReflowState& aReflowState,
    8733                 :                                     DR_FrameTreeNode&        aTreeNode,
    8734                 :                                     bool                     aChanged)
    8735                 : {
    8736               0 :   if (aTreeNode.mDisplay) {
    8737               0 :     DR_state->DisplayFrameTypeInfo(aFrame, aTreeNode.mIndent);
    8738                 : 
    8739                 :     char width[16];
    8740                 :     char height[16];
    8741                 : 
    8742               0 :     DR_state->PrettyUC(aReflowState.availableWidth, width);
    8743               0 :     DR_state->PrettyUC(aReflowState.availableHeight, height);
    8744               0 :     printf("Reflow a=%s,%s ", width, height);
    8745                 : 
    8746               0 :     DR_state->PrettyUC(aReflowState.ComputedWidth(), width);
    8747               0 :     DR_state->PrettyUC(aReflowState.ComputedHeight(), height);
    8748               0 :     printf("c=%s,%s ", width, height);
    8749                 : 
    8750               0 :     if (aFrame->GetStateBits() & NS_FRAME_IS_DIRTY)
    8751               0 :       printf("dirty ");
    8752                 : 
    8753               0 :     if (aFrame->GetStateBits() & NS_FRAME_HAS_DIRTY_CHILDREN)
    8754               0 :       printf("dirty-children ");
    8755                 : 
    8756               0 :     if (aReflowState.mFlags.mSpecialHeightReflow)
    8757               0 :       printf("special-height ");
    8758                 : 
    8759               0 :     if (aReflowState.mFlags.mHResize)
    8760               0 :       printf("h-resize ");
    8761                 : 
    8762               0 :     if (aReflowState.mFlags.mVResize)
    8763               0 :       printf("v-resize ");
    8764                 : 
    8765               0 :     nsIFrame* inFlow = aFrame->GetPrevInFlow();
    8766               0 :     if (inFlow) {
    8767               0 :       printf("pif=%p ", (void*)inFlow);
    8768                 :     }
    8769               0 :     inFlow = aFrame->GetNextInFlow();
    8770               0 :     if (inFlow) {
    8771               0 :       printf("nif=%p ", (void*)inFlow);
    8772                 :     }
    8773               0 :     if (aChanged) 
    8774               0 :       printf("CHANGED \n");
    8775                 :     else 
    8776               0 :       printf("cnt=%d \n", DR_state->mCount);
    8777               0 :     if (DR_state->mDisplayPixelErrors) {
    8778               0 :       PRInt32 p2t = aPresContext->AppUnitsPerDevPixel();
    8779               0 :       CheckPixelError(aReflowState.availableWidth, p2t);
    8780               0 :       CheckPixelError(aReflowState.availableHeight, p2t);
    8781               0 :       CheckPixelError(aReflowState.ComputedWidth(), p2t);
    8782               0 :       CheckPixelError(aReflowState.ComputedHeight(), p2t);
    8783                 :     }
    8784                 :   }
    8785               0 : }
    8786                 : 
    8787               0 : void* nsFrame::DisplayReflowEnter(nsPresContext*          aPresContext,
    8788                 :                                   nsIFrame*                aFrame,
    8789                 :                                   const nsHTMLReflowState& aReflowState)
    8790                 : {
    8791               0 :   if (!DR_state->mInited) DR_state->Init();
    8792               0 :   if (!DR_state->mActive) return nsnull;
    8793                 : 
    8794               0 :   NS_ASSERTION(aFrame, "invalid call");
    8795                 : 
    8796               0 :   DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, &aReflowState);
    8797               0 :   if (treeNode) {
    8798               0 :     DisplayReflowEnterPrint(aPresContext, aFrame, aReflowState, *treeNode, false);
    8799                 :   }
    8800               0 :   return treeNode;
    8801                 : }
    8802                 : 
    8803               0 : void* nsFrame::DisplayLayoutEnter(nsIFrame* aFrame)
    8804                 : {
    8805               0 :   if (!DR_state->mInited) DR_state->Init();
    8806               0 :   if (!DR_state->mActive) return nsnull;
    8807                 : 
    8808               0 :   NS_ASSERTION(aFrame, "invalid call");
    8809                 : 
    8810               0 :   DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, nsnull);
    8811               0 :   if (treeNode && treeNode->mDisplay) {
    8812               0 :     DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
    8813               0 :     printf("Layout\n");
    8814                 :   }
    8815               0 :   return treeNode;
    8816                 : }
    8817                 : 
    8818               0 : void* nsFrame::DisplayIntrinsicWidthEnter(nsIFrame* aFrame,
    8819                 :                                           const char* aType)
    8820                 : {
    8821               0 :   if (!DR_state->mInited) DR_state->Init();
    8822               0 :   if (!DR_state->mActive) return nsnull;
    8823                 : 
    8824               0 :   NS_ASSERTION(aFrame, "invalid call");
    8825                 : 
    8826               0 :   DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, nsnull);
    8827               0 :   if (treeNode && treeNode->mDisplay) {
    8828               0 :     DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
    8829               0 :     printf("Get%sWidth\n", aType);
    8830                 :   }
    8831               0 :   return treeNode;
    8832                 : }
    8833                 : 
    8834               0 : void* nsFrame::DisplayIntrinsicSizeEnter(nsIFrame* aFrame,
    8835                 :                                          const char* aType)
    8836                 : {
    8837               0 :   if (!DR_state->mInited) DR_state->Init();
    8838               0 :   if (!DR_state->mActive) return nsnull;
    8839                 : 
    8840               0 :   NS_ASSERTION(aFrame, "invalid call");
    8841                 : 
    8842               0 :   DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, nsnull);
    8843               0 :   if (treeNode && treeNode->mDisplay) {
    8844               0 :     DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
    8845               0 :     printf("Get%sSize\n", aType);
    8846                 :   }
    8847               0 :   return treeNode;
    8848                 : }
    8849                 : 
    8850               0 : void nsFrame::DisplayReflowExit(nsPresContext*      aPresContext,
    8851                 :                                 nsIFrame*            aFrame,
    8852                 :                                 nsHTMLReflowMetrics& aMetrics,
    8853                 :                                 nsReflowStatus       aStatus,
    8854                 :                                 void*                aFrameTreeNode)
    8855                 : {
    8856               0 :   if (!DR_state->mActive) return;
    8857                 : 
    8858               0 :   NS_ASSERTION(aFrame, "DisplayReflowExit - invalid call");
    8859               0 :   if (!aFrameTreeNode) return;
    8860                 : 
    8861               0 :   DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aFrameTreeNode;
    8862               0 :   if (treeNode->mDisplay) {
    8863               0 :     DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
    8864                 : 
    8865                 :     char width[16];
    8866                 :     char height[16];
    8867                 :     char x[16];
    8868                 :     char y[16];
    8869               0 :     DR_state->PrettyUC(aMetrics.width, width);
    8870               0 :     DR_state->PrettyUC(aMetrics.height, height);
    8871               0 :     printf("Reflow d=%s,%s", width, height);
    8872                 : 
    8873               0 :     if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
    8874               0 :       printf(" status=0x%x", aStatus);
    8875                 :     }
    8876               0 :     if (aFrame->HasOverflowAreas()) {
    8877               0 :       DR_state->PrettyUC(aMetrics.VisualOverflow().x, x);
    8878               0 :       DR_state->PrettyUC(aMetrics.VisualOverflow().y, y);
    8879               0 :       DR_state->PrettyUC(aMetrics.VisualOverflow().width, width);
    8880               0 :       DR_state->PrettyUC(aMetrics.VisualOverflow().height, height);
    8881               0 :       printf(" vis-o=(%s,%s) %s x %s", x, y, width, height);
    8882                 : 
    8883               0 :       nsRect storedOverflow = aFrame->GetVisualOverflowRect();
    8884               0 :       DR_state->PrettyUC(storedOverflow.x, x);
    8885               0 :       DR_state->PrettyUC(storedOverflow.y, y);
    8886               0 :       DR_state->PrettyUC(storedOverflow.width, width);
    8887               0 :       DR_state->PrettyUC(storedOverflow.height, height);
    8888               0 :       printf(" vis-sto=(%s,%s) %s x %s", x, y, width, height);
    8889                 : 
    8890               0 :       DR_state->PrettyUC(aMetrics.ScrollableOverflow().x, x);
    8891               0 :       DR_state->PrettyUC(aMetrics.ScrollableOverflow().y, y);
    8892               0 :       DR_state->PrettyUC(aMetrics.ScrollableOverflow().width, width);
    8893               0 :       DR_state->PrettyUC(aMetrics.ScrollableOverflow().height, height);
    8894               0 :       printf(" scr-o=(%s,%s) %s x %s", x, y, width, height);
    8895                 : 
    8896               0 :       storedOverflow = aFrame->GetScrollableOverflowRect();
    8897               0 :       DR_state->PrettyUC(storedOverflow.x, x);
    8898               0 :       DR_state->PrettyUC(storedOverflow.y, y);
    8899               0 :       DR_state->PrettyUC(storedOverflow.width, width);
    8900               0 :       DR_state->PrettyUC(storedOverflow.height, height);
    8901               0 :       printf(" scr-sto=(%s,%s) %s x %s", x, y, width, height);
    8902                 :     }
    8903               0 :     printf("\n");
    8904               0 :     if (DR_state->mDisplayPixelErrors) {
    8905               0 :       PRInt32 p2t = aPresContext->AppUnitsPerDevPixel();
    8906               0 :       CheckPixelError(aMetrics.width, p2t);
    8907               0 :       CheckPixelError(aMetrics.height, p2t);
    8908                 :     }
    8909                 :   }
    8910               0 :   DR_state->DeleteTreeNode(*treeNode);
    8911                 : }
    8912                 : 
    8913               0 : void nsFrame::DisplayLayoutExit(nsIFrame*            aFrame,
    8914                 :                                 void*                aFrameTreeNode)
    8915                 : {
    8916               0 :   if (!DR_state->mActive) return;
    8917                 : 
    8918               0 :   NS_ASSERTION(aFrame, "non-null frame required");
    8919               0 :   if (!aFrameTreeNode) return;
    8920                 : 
    8921               0 :   DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aFrameTreeNode;
    8922               0 :   if (treeNode->mDisplay) {
    8923               0 :     DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
    8924               0 :     nsRect rect = aFrame->GetRect();
    8925               0 :     printf("Layout=%d,%d,%d,%d\n", rect.x, rect.y, rect.width, rect.height);
    8926                 :   }
    8927               0 :   DR_state->DeleteTreeNode(*treeNode);
    8928                 : }
    8929                 : 
    8930               0 : void nsFrame::DisplayIntrinsicWidthExit(nsIFrame*            aFrame,
    8931                 :                                         const char*          aType,
    8932                 :                                         nscoord              aResult,
    8933                 :                                         void*                aFrameTreeNode)
    8934                 : {
    8935               0 :   if (!DR_state->mActive) return;
    8936                 : 
    8937               0 :   NS_ASSERTION(aFrame, "non-null frame required");
    8938               0 :   if (!aFrameTreeNode) return;
    8939                 : 
    8940               0 :   DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aFrameTreeNode;
    8941               0 :   if (treeNode->mDisplay) {
    8942               0 :     DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
    8943                 :     char width[16];
    8944               0 :     DR_state->PrettyUC(aResult, width);
    8945               0 :     printf("Get%sWidth=%s\n", aType, width);
    8946                 :   }
    8947               0 :   DR_state->DeleteTreeNode(*treeNode);
    8948                 : }
    8949                 : 
    8950               0 : void nsFrame::DisplayIntrinsicSizeExit(nsIFrame*            aFrame,
    8951                 :                                        const char*          aType,
    8952                 :                                        nsSize               aResult,
    8953                 :                                        void*                aFrameTreeNode)
    8954                 : {
    8955               0 :   if (!DR_state->mActive) return;
    8956                 : 
    8957               0 :   NS_ASSERTION(aFrame, "non-null frame required");
    8958               0 :   if (!aFrameTreeNode) return;
    8959                 : 
    8960               0 :   DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aFrameTreeNode;
    8961               0 :   if (treeNode->mDisplay) {
    8962               0 :     DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
    8963                 : 
    8964                 :     char width[16];
    8965                 :     char height[16];
    8966               0 :     DR_state->PrettyUC(aResult.width, width);
    8967               0 :     DR_state->PrettyUC(aResult.height, height);
    8968               0 :     printf("Get%sSize=%s,%s\n", aType, width, height);
    8969                 :   }
    8970               0 :   DR_state->DeleteTreeNode(*treeNode);
    8971                 : }
    8972                 : 
    8973                 : /* static */ void
    8974            1404 : nsFrame::DisplayReflowStartup()
    8975                 : {
    8976            1404 :   DR_state = new DR_State();
    8977            1404 : }
    8978                 : 
    8979                 : /* static */ void
    8980            1403 : nsFrame::DisplayReflowShutdown()
    8981                 : {
    8982            1403 :   delete DR_state;
    8983            1403 :   DR_state = nsnull;
    8984            1403 : }
    8985                 : 
    8986               0 : void DR_cookie::Change() const
    8987                 : {
    8988               0 :   DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)mValue;
    8989               0 :   if (treeNode && treeNode->mDisplay) {
    8990               0 :     DisplayReflowEnterPrint(mPresContext, mFrame, mReflowState, *treeNode, true);
    8991                 :   }
    8992               0 : }
    8993                 : 
    8994                 : /* static */ void*
    8995               0 : nsHTMLReflowState::DisplayInitConstraintsEnter(nsIFrame* aFrame,
    8996                 :                                                nsHTMLReflowState* aState,
    8997                 :                                                nscoord aContainingBlockWidth,
    8998                 :                                                nscoord aContainingBlockHeight,
    8999                 :                                                const nsMargin* aBorder,
    9000                 :                                                const nsMargin* aPadding)
    9001                 : {
    9002               0 :   NS_PRECONDITION(aFrame, "non-null frame required");
    9003               0 :   NS_PRECONDITION(aState, "non-null state required");
    9004                 : 
    9005               0 :   if (!DR_state->mInited) DR_state->Init();
    9006               0 :   if (!DR_state->mActive) return nsnull;
    9007                 : 
    9008               0 :   DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, aState);
    9009               0 :   if (treeNode && treeNode->mDisplay) {
    9010               0 :     DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
    9011                 : 
    9012                 :     printf("InitConstraints parent=%p",
    9013               0 :            (void*)aState->parentReflowState);
    9014                 : 
    9015                 :     char width[16];
    9016                 :     char height[16];
    9017                 : 
    9018               0 :     DR_state->PrettyUC(aContainingBlockWidth, width);
    9019               0 :     DR_state->PrettyUC(aContainingBlockHeight, height);
    9020               0 :     printf(" cb=%s,%s", width, height);
    9021                 : 
    9022               0 :     DR_state->PrettyUC(aState->availableWidth, width);
    9023               0 :     DR_state->PrettyUC(aState->availableHeight, height);
    9024               0 :     printf(" as=%s,%s", width, height);
    9025                 : 
    9026               0 :     DR_state->PrintMargin("b", aBorder);
    9027               0 :     DR_state->PrintMargin("p", aPadding);
    9028               0 :     putchar('\n');
    9029                 :   }
    9030               0 :   return treeNode;
    9031                 : }
    9032                 : 
    9033                 : /* static */ void
    9034               0 : nsHTMLReflowState::DisplayInitConstraintsExit(nsIFrame* aFrame,
    9035                 :                                               nsHTMLReflowState* aState,
    9036                 :                                               void* aValue)
    9037                 : {
    9038               0 :   NS_PRECONDITION(aFrame, "non-null frame required");
    9039               0 :   NS_PRECONDITION(aState, "non-null state required");
    9040                 : 
    9041               0 :   if (!DR_state->mActive) return;
    9042               0 :   if (!aValue) return;
    9043                 : 
    9044               0 :   DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aValue;
    9045               0 :   if (treeNode->mDisplay) {
    9046               0 :     DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
    9047                 :     char cmiw[16], cw[16], cmxw[16], cmih[16], ch[16], cmxh[16];
    9048               0 :     DR_state->PrettyUC(aState->mComputedMinWidth, cmiw);
    9049               0 :     DR_state->PrettyUC(aState->mComputedWidth, cw);
    9050               0 :     DR_state->PrettyUC(aState->mComputedMaxWidth, cmxw);
    9051               0 :     DR_state->PrettyUC(aState->mComputedMinHeight, cmih);
    9052               0 :     DR_state->PrettyUC(aState->mComputedHeight, ch);
    9053               0 :     DR_state->PrettyUC(aState->mComputedMaxHeight, cmxh);
    9054                 :     printf("InitConstraints= cw=(%s <= %s <= %s) ch=(%s <= %s <= %s)",
    9055               0 :            cmiw, cw, cmxw, cmih, ch, cmxh);
    9056               0 :     DR_state->PrintMargin("co", &aState->mComputedOffsets);
    9057               0 :     putchar('\n');
    9058                 :   }
    9059               0 :   DR_state->DeleteTreeNode(*treeNode);
    9060                 : }
    9061                 : 
    9062                 : 
    9063                 : /* static */ void*
    9064               0 : nsCSSOffsetState::DisplayInitOffsetsEnter(nsIFrame* aFrame,
    9065                 :                                           nsCSSOffsetState* aState,
    9066                 :                                           nscoord aContainingBlockWidth,
    9067                 :                                           const nsMargin* aBorder,
    9068                 :                                           const nsMargin* aPadding)
    9069                 : {
    9070               0 :   NS_PRECONDITION(aFrame, "non-null frame required");
    9071               0 :   NS_PRECONDITION(aState, "non-null state required");
    9072                 : 
    9073               0 :   if (!DR_state->mInited) DR_state->Init();
    9074               0 :   if (!DR_state->mActive) return nsnull;
    9075                 : 
    9076                 :   // aState is not necessarily a nsHTMLReflowState
    9077               0 :   DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, nsnull);
    9078               0 :   if (treeNode && treeNode->mDisplay) {
    9079               0 :     DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
    9080                 : 
    9081                 :     char width[16];
    9082               0 :     DR_state->PrettyUC(aContainingBlockWidth, width);
    9083               0 :     printf("InitOffsets cbw=%s", width);
    9084               0 :     DR_state->PrintMargin("b", aBorder);
    9085               0 :     DR_state->PrintMargin("p", aPadding);
    9086               0 :     putchar('\n');
    9087                 :   }
    9088               0 :   return treeNode;
    9089                 : }
    9090                 : 
    9091                 : /* static */ void
    9092               0 : nsCSSOffsetState::DisplayInitOffsetsExit(nsIFrame* aFrame,
    9093                 :                                          nsCSSOffsetState* aState,
    9094                 :                                          void* aValue)
    9095                 : {
    9096               0 :   NS_PRECONDITION(aFrame, "non-null frame required");
    9097               0 :   NS_PRECONDITION(aState, "non-null state required");
    9098                 : 
    9099               0 :   if (!DR_state->mActive) return;
    9100               0 :   if (!aValue) return;
    9101                 : 
    9102               0 :   DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aValue;
    9103               0 :   if (treeNode->mDisplay) {
    9104               0 :     DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
    9105               0 :     printf("InitOffsets=");
    9106               0 :     DR_state->PrintMargin("m", &aState->mComputedMargin);
    9107               0 :     DR_state->PrintMargin("p", &aState->mComputedPadding);
    9108               0 :     DR_state->PrintMargin("p+b", &aState->mComputedBorderPadding);
    9109               0 :     putchar('\n');
    9110                 :   }
    9111               0 :   DR_state->DeleteTreeNode(*treeNode);
    9112                 : }
    9113                 : 
    9114                 : /* static */ void*
    9115               0 : nsHTMLReflowState::DisplayInitFrameTypeEnter(nsIFrame* aFrame,
    9116                 :                                              nsHTMLReflowState* aState)
    9117                 : {
    9118               0 :   NS_PRECONDITION(aFrame, "non-null frame required");
    9119               0 :   NS_PRECONDITION(aState, "non-null state required");
    9120                 : 
    9121               0 :   if (!DR_state->mInited) DR_state->Init();
    9122               0 :   if (!DR_state->mActive) return nsnull;
    9123                 : 
    9124                 :   // we don't print anything here
    9125               0 :   return DR_state->CreateTreeNode(aFrame, aState);
    9126                 : }
    9127                 : 
    9128                 : /* static */ void
    9129               0 : nsHTMLReflowState::DisplayInitFrameTypeExit(nsIFrame* aFrame,
    9130                 :                                             nsHTMLReflowState* aState,
    9131                 :                                             void* aValue)
    9132                 : {
    9133               0 :   NS_PRECONDITION(aFrame, "non-null frame required");
    9134               0 :   NS_PRECONDITION(aState, "non-null state required");
    9135                 : 
    9136               0 :   if (!DR_state->mActive) return;
    9137               0 :   if (!aValue) return;
    9138                 : 
    9139               0 :   DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aValue;
    9140               0 :   if (treeNode->mDisplay) {
    9141               0 :     DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
    9142               0 :     printf("InitFrameType");
    9143                 : 
    9144               0 :     const nsStyleDisplay *disp = aState->mStyleDisplay;
    9145                 : 
    9146               0 :     if (aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW)
    9147               0 :       printf(" out-of-flow");
    9148               0 :     if (aFrame->GetPrevInFlow())
    9149               0 :       printf(" prev-in-flow");
    9150               0 :     if (disp->IsAbsolutelyPositioned())
    9151               0 :       printf(" abspos");
    9152               0 :     if (disp->IsFloating())
    9153               0 :       printf(" float");
    9154                 : 
    9155                 :     // This array must exactly match the NS_STYLE_DISPLAY constants.
    9156                 :     const char *const displayTypes[] = {
    9157                 :       "none", "block", "inline", "inline-block", "list-item", "marker",
    9158                 :       "run-in", "compact", "table", "inline-table", "table-row-group",
    9159                 :       "table-column", "table-column-group", "table-header-group",
    9160                 :       "table-footer-group", "table-row", "table-cell", "table-caption",
    9161                 :       "box", "inline-box",
    9162                 : #ifdef MOZ_XUL
    9163                 :       "grid", "inline-grid", "grid-group", "grid-line", "stack",
    9164                 :       "inline-stack", "deck", "popup", "groupbox",
    9165                 : #endif
    9166               0 :     };
    9167               0 :     if (disp->mDisplay >= ArrayLength(displayTypes))
    9168               0 :       printf(" display=%u", disp->mDisplay);
    9169                 :     else
    9170               0 :       printf(" display=%s", displayTypes[disp->mDisplay]);
    9171                 : 
    9172                 :     // This array must exactly match the NS_CSS_FRAME_TYPE constants.
    9173                 :     const char *const cssFrameTypes[] = {
    9174                 :       "unknown", "inline", "block", "floating", "absolute", "internal-table"
    9175               0 :     };
    9176               0 :     nsCSSFrameType bareType = NS_FRAME_GET_TYPE(aState->mFrameType);
    9177               0 :     bool repNoBlock = NS_FRAME_IS_REPLACED_NOBLOCK(aState->mFrameType);
    9178               0 :     bool repBlock = NS_FRAME_IS_REPLACED_CONTAINS_BLOCK(aState->mFrameType);
    9179                 : 
    9180               0 :     if (bareType >= ArrayLength(cssFrameTypes)) {
    9181               0 :       printf(" result=type %u", bareType);
    9182                 :     } else {
    9183               0 :       printf(" result=%s", cssFrameTypes[bareType]);
    9184                 :     }
    9185               0 :     printf("%s%s\n", repNoBlock ? " +rep" : "", repBlock ? " +repBlk" : "");
    9186                 :   }
    9187               0 :   DR_state->DeleteTreeNode(*treeNode);
    9188                 : }
    9189                 : 
    9190                 : #endif
    9191                 : // End Display Reflow
    9192                 : 
    9193                 : #endif

Generated by: LCOV version 1.7