diff --git a/content/html/content/src/makefile.win b/content/html/content/src/makefile.win
index c4c932d7fb44..0b0658502757 100644
--- a/content/html/content/src/makefile.win
+++ b/content/html/content/src/makefile.win
@@ -154,7 +154,7 @@ CPP_OBJS= \
LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I$(PUBLIC)\js \
-I$(PUBLIC)\dom -I$(PUBLIC)\netlib \
- -I..\..\style\src -I..\..\..\css\layout\src \
+ -I..\..\style\src \
-I..\..\..\base\src -I..\..\base\src
LCFLAGS = \
diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp
index 9db31d5748dd..cef73f58b739 100644
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -53,8 +53,8 @@
#include "nsString.h"
#include "nsHTMLAtoms.h"
#include "nsDOMEventsIIDs.h"
-#include "nsCSSBlockFrame.h"
-#include "nsCSSInlineFrame.h"
+#include "nsBlockFrame.h"
+#include "nsInlineFrame.h"
#include "nsIEventStateManager.h"
#include "nsDOMEvent.h"
#include "nsIPrivateDOMEvent.h"
@@ -1884,11 +1884,11 @@ nsGenericHTMLElement::CreateFrame(nsIPresContext* aPresContext,
switch (styleDisplay->mDisplay) {
case NS_STYLE_DISPLAY_BLOCK:
case NS_STYLE_DISPLAY_LIST_ITEM:
- rv = NS_NewCSSBlockFrame(&frame, mContent, aParentFrame);
+ rv = NS_NewBlockFrame(&frame, mContent, aParentFrame);
break;
case NS_STYLE_DISPLAY_INLINE:
- rv = NS_NewCSSInlineFrame(&frame, mContent, aParentFrame);
+ rv = NS_NewInlineFrame(&frame, mContent, aParentFrame);
break;
default:
diff --git a/content/html/style/src/nsHTMLStyleSheet.cpp b/content/html/style/src/nsHTMLStyleSheet.cpp
index 68194e7c9663..afe16c1ea0f6 100644
--- a/content/html/style/src/nsHTMLStyleSheet.cpp
+++ b/content/html/style/src/nsHTMLStyleSheet.cpp
@@ -1089,14 +1089,14 @@ NS_IMETHODIMP HTMLStyleSheetImpl::ConstructFrame(nsIPresContext* aPresContext,
switch (styleDisplay->mDisplay) {
case NS_STYLE_DISPLAY_BLOCK:
case NS_STYLE_DISPLAY_LIST_ITEM:
- rv = NS_NewCSSBlockFrame(&frame, aContent, aParentFrame);
+ rv = NS_NewBlockFrame(&frame, aContent, aParentFrame);
// Process the child content
ProcessChildren(aPresContext, frame, aContent, childList);
break;
case NS_STYLE_DISPLAY_INLINE:
- rv = NS_NewCSSInlineFrame(&frame, aContent, aParentFrame);
+ rv = NS_NewInlineFrame(&frame, aContent, aParentFrame);
// Process the child content
ProcessChildren(aPresContext, frame, aContent, childList);
diff --git a/layout/Makefile b/layout/Makefile
index 77f2a7a3fa00..f85dc453da3a 100644
--- a/layout/Makefile
+++ b/layout/Makefile
@@ -17,7 +17,7 @@
DEPTH = ..
-DIRS = base css html events build
+DIRS = base html events build
include $(DEPTH)/config/config.mk
diff --git a/layout/build/Makefile b/layout/build/Makefile
index a399313f3950..dce0bd001f7d 100644
--- a/layout/build/Makefile
+++ b/layout/build/Makefile
@@ -43,11 +43,10 @@ EXTRA_DSO_LDOPTS = \
$(LD_ALL) \
$(DIST)/lib/libraptorhtmldoc_s.a \
$(DIST)/lib/libnglhtmlcon_s.a \
- $(DIST)/lib/libraptorhtmldoc_s.a \
+ $(DIST)/lib/libraptorhtmldoc_s.a \
$(DIST)/lib/libraptorhtmlforms_s.a \
$(DIST)/lib/libraptorhtmltable_s.a \
$(DIST)/lib/libraptorhtmlbase_s.a \
- $(DIST)/lib/libnglcsslay_s.a \
$(DIST)/lib/libraptorhtmlstyle_s.a \
$(DIST)/lib/libraptorlayout_s.a \
$(DIST)/lib/libraptorevents_s.a \
diff --git a/layout/build/makefile.win b/layout/build/makefile.win
index d602d58388e6..e41949156d1d 100644
--- a/layout/build/makefile.win
+++ b/layout/build/makefile.win
@@ -36,7 +36,6 @@ MISCDEP = \
$(DIST)\lib\raptorlayout_s.lib \
$(DIST)\lib\raptorhtmlbase_s.lib \
$(DIST)\lib\nglhtmlcon_s.lib \
- $(DIST)\lib\nglcsslay_s.lib \
$(DIST)\lib\raptorhtmldoc_s.lib \
$(DIST)\lib\raptorhtmlforms_s.lib \
$(DIST)\lib\raptorhtmlstyle_s.lib \
@@ -63,7 +62,6 @@ LLIBS= \
$(DIST)\lib\raptorlayout_s.lib \
$(DIST)\lib\raptorhtmlbase_s.lib \
$(DIST)\lib\nglhtmlcon_s.lib \
- $(DIST)\lib\nglcsslay_s.lib \
$(DIST)\lib\raptorhtmldoc_s.lib \
$(DIST)\lib\raptorhtmlforms_s.lib \
$(DIST)\lib\raptorhtmlstyle_s.lib \
diff --git a/layout/css/Makefile b/layout/css/Makefile
deleted file mode 100644
index f1e5fea7715f..000000000000
--- a/layout/css/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-#!gmake
-#
-# The contents of this file are subject to the Netscape Public License
-# Version 1.0 (the "NPL"); you may not use this file except in
-# compliance with the NPL. You may obtain a copy of the NPL at
-# http://www.mozilla.org/NPL/
-#
-# Software distributed under the NPL is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
-# for the specific language governing rights and limitations under the
-# NPL.
-#
-# The Initial Developer of this code under the NPL is Netscape
-# Communications Corporation. Portions created by Netscape are
-# Copyright (C) 1998 Netscape Communications Corporation. All Rights
-# Reserved.
-
-DEPTH = ../..
-
-DIRS = layout
-
-include $(DEPTH)/config/config.mk
-
-include $(DEPTH)/config/rules.mk
diff --git a/layout/css/layout/Makefile b/layout/css/layout/Makefile
deleted file mode 100644
index c650dc9b7ab4..000000000000
--- a/layout/css/layout/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-#!gmake
-#
-# The contents of this file are subject to the Netscape Public License
-# Version 1.0 (the "NPL"); you may not use this file except in
-# compliance with the NPL. You may obtain a copy of the NPL at
-# http://www.mozilla.org/NPL/
-#
-# Software distributed under the NPL is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
-# for the specific language governing rights and limitations under the
-# NPL.
-#
-# The Initial Developer of this code under the NPL is Netscape
-# Communications Corporation. Portions created by Netscape are
-# Copyright (C) 1998 Netscape Communications Corporation. All Rights
-# Reserved.
-
-DEPTH = ../../..
-
-DIRS = public src
-
-include $(DEPTH)/config/config.mk
-
-include $(DEPTH)/config/rules.mk
diff --git a/layout/css/layout/makefile.win b/layout/css/layout/makefile.win
deleted file mode 100644
index fc8fa3cffa16..000000000000
--- a/layout/css/layout/makefile.win
+++ /dev/null
@@ -1,22 +0,0 @@
-#!nmake
-#
-# The contents of this file are subject to the Netscape Public License
-# Version 1.0 (the "NPL"); you may not use this file except in
-# compliance with the NPL. You may obtain a copy of the NPL at
-# http://www.mozilla.org/NPL/
-#
-# Software distributed under the NPL is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
-# for the specific language governing rights and limitations under the
-# NPL.
-#
-# The Initial Developer of this code under the NPL is Netscape
-# Communications Corporation. Portions created by Netscape are
-# Copyright (C) 1998 Netscape Communications Corporation. All Rights
-# Reserved.
-
-DEPTH=..\..\..
-
-DIRS=public src
-
-include <$(DEPTH)\layout\config\rules.mak>
diff --git a/layout/css/layout/src/Makefile b/layout/css/layout/src/Makefile
deleted file mode 100644
index 9aaacbe75bbf..000000000000
--- a/layout/css/layout/src/Makefile
+++ /dev/null
@@ -1,46 +0,0 @@
-#!gmake
-#
-# The contents of this file are subject to the Netscape Public License
-# Version 1.0 (the "NPL"); you may not use this file except in
-# compliance with the NPL. You may obtain a copy of the NPL at
-# http://www.mozilla.org/NPL/
-#
-# Software distributed under the NPL is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
-# for the specific language governing rights and limitations under the
-# NPL.
-#
-# The Initial Developer of this code under the NPL is Netscape
-# Communications Corporation. Portions created by Netscape are
-# Copyright (C) 1998 Netscape Communications Corporation. All Rights
-# Reserved.
-
-DEPTH=../../../..
-
-LIBRARY_NAME = nglcsslay_s
-
-# Note the sophisticated alphabetical ordering :-|
-CPPSRCS = \
- nsCSSBlockFrame.cpp \
- nsCSSContainerFrame.cpp \
- nsCSSInlineFrame.cpp \
- nsCSSInlineLayout.cpp \
- nsCSSLineLayout.cpp \
- $(NULL)
-
-MODULE = raptor
-
-REQUIRES = xpcom raptor dom netlib
-
-include $(DEPTH)/config/config.mk
-
-LCFLAGS += -D_IMPL_NS_HTML
-
-INCLUDES += -I../../../html/style/src -I../../../html/base/src \
- -I../../../base/src
-
-MKSHLIB :=
-
-include $(DEPTH)/config/rules.mk
-
-install::
diff --git a/layout/css/layout/src/TODO b/layout/css/layout/src/TODO
deleted file mode 100644
index 2f918a409e38..000000000000
--- a/layout/css/layout/src/TODO
+++ /dev/null
@@ -1,233 +0,0 @@
-todo for AOL August 1st deadline:
----------------------------------
-
-o bug17-3.html: when dealing with incremental frame-appended reflow we
- need to know how the last clean line was ended (e.g. break, clear=all, etc.)
- otherwise we won't adjust the y coordinate properly. We can save the
- break status into the line or adjust the line height and make it tall.
-
-o entities in attributes (e.g. alt text at disney.com)
-
-o tuning ideas:
- o DidReflow N^2 [current disabled because of nested view x,y problem]
- o FindTextRuns N^2
- o LineData allocations/frees
-
-o click on gif, jpg, txt
-
-o http://www.aol.com/netfind
- o fix the size of the iframe
- o look into the parsing bug's
-
-o http://www.magicbit.com/links/travel.htm; why is the SMART-NET image
- at the bottom instead of at the baseline?
-
-o http://www.altavista.com looks wrong. why?
- why does it go into an infinite loop during a -f run?
-
-o bug2.html
-
-o UMR bug because of painting during reflow
-
-
-o fast scroll to #ref for a link targeted at the same document as is
- currently showing
-
-o force-refresh needs to get the nsIScrollableView and update that view,
- not the root view
-
-o f:/html/bug8.html (descent bug in vertically align children)
-
-o Viewer:
- o make the print-preview menu item work
- o select-all and copy menu items
- o fix link-over status
-
-o fix floating tables
- x current-line floaters need to go in previous line's bcl list; if first line
- then they go in the block-frame's pending floater list
- x ... we need a place to hang current-line floaters!!!
- x http://www.news.com
- x http://www.usatoday.com/
- o http://www.mrshowbiz.com/
- x file:/f:/html/floating-images.html
- "tucked between the woofers" isn't
- o file:/f:/html/floating-tables-inline.html
- overwrite errors
- o file:/f:/html/br-clear.html
- 3rd test case is not compatible with navigator; I think navigator
- has a bug IMHO.
-
-o block-frame: DidReflow and content-appended can be smarter; right now
- we did-reflow the whole caboodle whereas we could keep a bit in the
- line that indicates where the dirty lines were so that when the
- block's parent comes along and does a did-reflow it can propogate it
- down to only the affected lines.
-
-o fix blocks inside of inlines; need to find the block's inline-layout
- state and see where the block child is with respect to the left edge
- of the line.
-
-o mark/insert-at-mark for parser???
-
-o www.cnn.com: crash
-
-o performance:
- o people.netscape.com
-
-o slide show resize bug
-
-o fix assertion on LCIC in nscssblockframe::content-inserted when
- running rotate.html/js test
-
-o docloader needs to disconnect itself as an observer when it's done
-
-----------------------------------------------------------------------
-After august 10th
-----------------------------------------------------------------------
-
-o why is nsInlineLayout different from nsInlineReflowState (mott@nc.com)
-
-BASE TAG SUPPORT:
-o revise the way that base tags work (somehow); either make the
- content sink aware of all tags that can have url's in them, or better
- yet, add in base tag api's to the nsHTMLDocument and make the content
- set-attribute methods deal with it; or add in a method to
- nsIHTMLContent called SetBaseURL and SetTarget (which is defined to be
- ignored except for those tags that care)
-
- o implement base tag support:
- o frame, iframe, frameset
- o layer
- o Body (background), TABLE, TR, TD (background), etc.
- o Image, Anchor; look at html4.0 spec for attributes that are URI's
-
- o TEST base tag support:
- o script src=
- o style src=
-
-o NS_FRAME_FIRST_REFLOW needs to go; block code is the only consumer
- instead keep a list of new frames and when we hit one, trigger the
- initial reflow
-
-o Query-Interface day: go through and change all the QueryInterface
- implementations to put the cast into a temp variable and then cast the
- temp variable to void*
-
-o crash in: http://www-dsed.llnl.gov/documents/a_document.html
- the problem stems from a OL marked display:inline that contains LI's;
- the LI's aren't doing the right thing to find the container that
- has next ordinal number (which in this case is none!)
-
-o implement hspace, vspace; test for navigator compatability
- check for all other unimplemented tag attributes
- verify that DumpContent works; write a oneof.html test that has every
- tag with every attribute in every combination in it.
-
-o max-element-size and floaters:
- the correct value is dependent on which table pass we are in;
- for pass1 we really only need the max(floaters, child-max-element-size)
- for pass2 we need a per-line max-element-size and then we need to
- compute the sum(floaters, line-max-element-size); this is still not
- quite right; the sum should be the sum of the floaters and the line's
- first-element-size.
-
-o ebina margin bugs:
- BR tags
- line-height adjustment (sometimes; see test0.html and the large font)
- P's in LI's
- f:/html/bug3.html (yikes!)
- f:/html/bug6.html
- www.infoseek.com; see steve's mail (date july 21st)
- www.w3.org
- f:/html/image-hspace.html
-
-o rework how BR's work:
- f:/html/image-vspace.html; notice the top two lines stuck together in nav
- make clear-line a real style-const property and use it to mean "give me
- a fresh line". Then make br's zero height. Have the block code handle the
- fresh line concept directly...work this in with keeping track of pending
- vertical whitespace for table shrink wrapping.
-
-o ebina's engine provides automatic margins around floating images that
- are PROPORTIONAL to the size of the image's border (find the code
- luke)
-
-o tinderbox: add selftest to our makefile so that it will run whatever
- we want and verify the results of a build
-
-o XXX code in block frame code
-
-o rethink list-item handling again
- o f:/html/list-padding.html: bullet turns into a box
- o f:/html/list-style-image.html: bullets don't trigger a reflow properly
- when the image size finally arrives
-
-o have michael fix up the scrolling-view code so that if a document is
- scrolled and grown the relative scroll position is maintained so that
- the view doesn't jump around. Then re-enable the html content sink
- scroll-to-ref code in the incremental reflow cases.
- o scroll to #ref needs to be able to update the scrollbars when it
- finds the target frame has been reflowed.
-
-pseudo-frame whackage
-
-factories for html etc. so that viewer no longer links against the dll
-
-async style sheet loading
-async script src= loading
- need blocking model in content sink and parser
-
-o Get rid of XXX::NewFrame methods
-o ListTag(nsString& aResult) instead of FILE*
-o style attributes of BODY tag
-o style attributes of HTML tag
-o turn noisy code in nsContainerFrame into NS_FRAME_TRACE calls
-
-o implement the LINK tag including base attributes for style sheets
- and other linked objects
-
-o LINK rel=stylesheet href=... type=text/css
-
-Underlines across font/style changes look like cr*p. We should draw a
-single underline that's the same size.
-
-www.excite.com; crash
-
-people.netscape.com/paquin/temple.html; crash
-
-people.netscape.com/kipp - Hickman breaking bug
-
-block-margins.html: margin after block & before text is lost
-
-Content objects for: FORM, /FORM, MAP, AREA, SCRIPT, STYLE
-
-width/height sizing stuff into body/block/inline code
-
-image-map.html: top border is black; why?
-
-css2 cursors into raptor
-
-1 pass build on windows
-
-o write a combinatoric test case of the all the different variations on
- url parsing and compare with navigator; get nsURL.cpp to agree with it.
-
-security dialog support code using raptor
-
-nspr log module list online
-
-----------------------------------------------------------------------
-Would be nice someday
-----------------------------------------------------------------------
-
-async dns slow mode
-
-css parser keeping comments
-
-----------------------------------------------------------------------
-DONE
-----------------------------------------------------------------------
-
-x fix limited stack depth in content sink
-x missing space after ampersand on http://home.netscape.com
diff --git a/layout/css/layout/src/makefile.win b/layout/css/layout/src/makefile.win
deleted file mode 100644
index f24d0cdd99d0..000000000000
--- a/layout/css/layout/src/makefile.win
+++ /dev/null
@@ -1,57 +0,0 @@
-#!nmake
-#
-# The contents of this file are subject to the Netscape Public License
-# Version 1.0 (the "NPL"); you may not use this file except in
-# compliance with the NPL. You may obtain a copy of the NPL at
-# http://www.mozilla.org/NPL/
-#
-# Software distributed under the NPL is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
-# for the specific language governing rights and limitations under the
-# NPL.
-#
-# The Initial Developer of this code under the NPL is Netscape
-# Communications Corporation. Portions created by Netscape are
-# Copyright (C) 1998 Netscape Communications Corporation. All Rights
-# Reserved.
-
-DEPTH=..\..\..\..
-
-LIBRARY_NAME=nglcsslay_s
-MODULE=raptor
-REQUIRES=xpcom raptor
-DEFINES=-D_IMPL_NS_HTML -DWIN32_LEAN_AND_MEAN
-
-CPPSRCS= \
- nsCSSBlockFrame.cpp \
- nsCSSContainerFrame.cpp \
- nsCSSInlineFrame.cpp \
- nsCSSInlineLayout.cpp \
- nsCSSLineLayout.cpp \
- $(NULL)
-
-CPP_OBJS= \
- .\$(OBJDIR)\nsCSSBlockFrame.obj \
- .\$(OBJDIR)\nsCSSContainerFrame.obj \
- .\$(OBJDIR)\nsCSSInlineFrame.obj \
- .\$(OBJDIR)\nsCSSInlineLayout.obj \
- .\$(OBJDIR)\nsCSSLineLayout.obj \
- $(NULL)
-
-LINCS = \
- -I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I$(PUBLIC)\dom -I$(PUBLIC)\netlib \
- -I..\..\..\base\src \
- -I..\..\..\html\style\src -I..\..\..\html\base\src
-
-LCFLAGS = \
- $(LCFLAGS) \
- $(DEFINES) \
- $(NULL)
-
-include <$(DEPTH)\layout\config\rules.mak>
-
-libs:: $(LIBRARY)
- $(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
-
-clobber::
- rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
diff --git a/layout/css/layout/src/nsCSSContainerFrame.cpp b/layout/css/layout/src/nsCSSContainerFrame.cpp
deleted file mode 100644
index 6b844dc26ad1..000000000000
--- a/layout/css/layout/src/nsCSSContainerFrame.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Original Code is Mozilla Communicator client code.
- *
- * The Initial Developer of the Original Code is Netscape Communications
- * Corporation. Portions created by Netscape are Copyright (C) 1998
- * Netscape Communications Corporation. All Rights Reserved.
- */
-#include "nsCSSContainerFrame.h"
-#include "nsPlaceholderFrame.h"
-#include "nsIStyleContext.h"
-
-nsCSSContainerFrame::nsCSSContainerFrame(nsIContent* aContent,
- nsIFrame* aParent)
- : nsHTMLContainerFrame(aContent, aParent)
-{
-}
-
-nsCSSContainerFrame::~nsCSSContainerFrame()
-{
-}
-
-nsPlaceholderFrame*
-nsCSSContainerFrame::CreatePlaceholderFrame(nsIPresContext* aPresContext,
- nsIFrame* aFloatedFrame)
-{
- nsIContent* content;
- aFloatedFrame->GetContent(content);
-
- nsPlaceholderFrame* placeholder;
- nsPlaceholderFrame::NewFrame((nsIFrame**)&placeholder, content, this, aFloatedFrame);
- NS_IF_RELEASE(content);
-
- // Let the placeholder share the same style context as the floated element
- nsIStyleContext* kidSC;
- aFloatedFrame->GetStyleContext(aPresContext, kidSC);
- placeholder->SetStyleContext(aPresContext, kidSC);
- NS_RELEASE(kidSC);
-
- return placeholder;
-}
diff --git a/layout/css/layout/src/nsCSSContainerFrame.h b/layout/css/layout/src/nsCSSContainerFrame.h
deleted file mode 100644
index b69fae372860..000000000000
--- a/layout/css/layout/src/nsCSSContainerFrame.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Original Code is Mozilla Communicator client code.
- *
- * The Initial Developer of the Original Code is Netscape Communications
- * Corporation. Portions created by Netscape are Copyright (C) 1998
- * Netscape Communications Corporation. All Rights Reserved.
- */
-#ifndef nsCSSContainerFrame_h___
-#define nsCSSContainerFrame_h___
-
-#include "nsHTMLContainerFrame.h"
-
-class nsPlaceholderFrame;
-
-class nsCSSContainerFrame : public nsHTMLContainerFrame {
-public:
-
- virtual PRBool DeleteNextInFlowsFor(nsIPresContext& aPresContext, nsIFrame* aChild) = 0;
-
-protected:
- nsCSSContainerFrame(nsIContent* aContent, nsIFrame* aParent);
- ~nsCSSContainerFrame();
-
- nsPlaceholderFrame* CreatePlaceholderFrame(nsIPresContext* aPresContext,
- nsIFrame* aFloatedFrame);
-
-};
-
-#endif /* nsCSSContainerFrame_h___ */
diff --git a/layout/css/makefile.win b/layout/css/makefile.win
deleted file mode 100644
index 8a66827b3aa3..000000000000
--- a/layout/css/makefile.win
+++ /dev/null
@@ -1,22 +0,0 @@
-#!nmake
-#
-# The contents of this file are subject to the Netscape Public License
-# Version 1.0 (the "NPL"); you may not use this file except in
-# compliance with the NPL. You may obtain a copy of the NPL at
-# http://www.mozilla.org/NPL/
-#
-# Software distributed under the NPL is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
-# for the specific language governing rights and limitations under the
-# NPL.
-#
-# The Initial Developer of this code under the NPL is Netscape
-# Communications Corporation. Portions created by Netscape are
-# Copyright (C) 1998 Netscape Communications Corporation. All Rights
-# Reserved.
-
-DEPTH=..\..
-
-DIRS = layout
-
-include <$(DEPTH)\layout\config\rules.mak>
diff --git a/layout/generic/nsBRFrame.cpp b/layout/generic/nsBRFrame.cpp
index 3b595cd87d1c..1129a0e3b89d 100644
--- a/layout/generic/nsBRFrame.cpp
+++ b/layout/generic/nsBRFrame.cpp
@@ -20,7 +20,7 @@
#include "nsHTMLIIDs.h"
#include "nsIPresContext.h"
#include "nsIInlineReflow.h"
-#include "nsCSSLineLayout.h"
+#include "nsLineLayout.h"
#include "nsStyleConsts.h"
#include "nsHTMLAtoms.h"
#include "nsIStyleContext.h"
@@ -40,9 +40,9 @@ public:
const nsRect& aDirtyRect);
// nsIInlineReflow
- NS_IMETHOD FindTextRuns(nsCSSLineLayout& aLineLayout,
+ NS_IMETHOD FindTextRuns(nsLineLayout& aLineLayout,
nsIReflowCommand* aReflowCommand);
- NS_IMETHOD InlineReflow(nsCSSLineLayout& aLineLayout,
+ NS_IMETHOD InlineReflow(nsLineLayout& aLineLayout,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState);
@@ -100,7 +100,7 @@ BRFrame::Paint(nsIPresContext& aPresContext,
}
NS_IMETHODIMP
-BRFrame::FindTextRuns(nsCSSLineLayout& aLineLayout,
+BRFrame::FindTextRuns(nsLineLayout& aLineLayout,
nsIReflowCommand* aReflowCommand)
{
aLineLayout.EndTextRun();
@@ -108,7 +108,7 @@ BRFrame::FindTextRuns(nsCSSLineLayout& aLineLayout,
}
NS_IMETHODIMP
-BRFrame::InlineReflow(nsCSSLineLayout& aLineLayout,
+BRFrame::InlineReflow(nsLineLayout& aLineLayout,
nsReflowMetrics& aMetrics,
const nsReflowState& aReflowState)
{
diff --git a/layout/css/layout/src/nsCSSBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp
similarity index 92%
rename from layout/css/layout/src/nsCSSBlockFrame.cpp
rename to layout/generic/nsBlockFrame.cpp
index 6972bdeafef8..6dd718cd7d70 100644
--- a/layout/css/layout/src/nsCSSBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -16,9 +16,9 @@
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
-#include "nsCSSBlockFrame.h"
-#include "nsCSSLineLayout.h"
-#include "nsCSSInlineLayout.h"
+#include "nsBlockFrame.h"
+#include "nsLineLayout.h"
+#include "nsInlineLayout.h"
#include "nsCSSLayout.h"
#include "nsPlaceholderFrame.h"
#include "nsStyleConsts.h"
@@ -35,7 +35,7 @@
#include "nsIView.h"
#include "nsIFontMetrics.h"
-#include "nsHTMLBase.h"// XXX rename to nsCSSBase?
+#include "nsHTMLBase.h"// XXX rename to nsBase?
#include "nsHTMLParts.h"// XXX html reflow command???
#include "nsHTMLAtoms.h"// XXX list ordinal hack
#include "nsHTMLValue.h"// XXX list ordinal hack
@@ -76,7 +76,7 @@
// XXX Tuneup: if mNoWrap is true and we are given a ResizeReflow we
// can just return because there's nothing to do!; this is true in
-// nsCSSInlineFrame too!
+// nsInlineFrame too!
// Except that noWrap is ignored if the containers width is too small
// (like a table cell with a fixed width.)
@@ -100,14 +100,14 @@ struct LineData;
#define DTPF 1
// XXX temporary until PropagateContentOffsets can be written genericly
-#define nsCSSBlockFrameSuper nsCSSContainerFrame
+#define nsBlockFrameSuper nsHTMLContainerFrame
-class nsCSSBlockFrame : public nsCSSBlockFrameSuper,
- public nsIRunaround,
- public nsIFloaterContainer
+class nsBlockFrame : public nsBlockFrameSuper,
+ public nsIRunaround,
+ public nsIFloaterContainer
{
public:
- nsCSSBlockFrame(nsIContent* aContent, nsIFrame* aParent);
+ nsBlockFrame(nsIContent* aContent, nsIFrame* aParent);
// nsISupports
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
@@ -178,13 +178,13 @@ public:
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
- nsIFrame * FindHitFrame(nsCSSBlockFrame * aBlockFrame,
+ nsIFrame * FindHitFrame(nsBlockFrame * aBlockFrame,
const nscoord aX, const nscoord aY,
const nsPoint & aPoint);
#endif
protected:
- ~nsCSSBlockFrame();
+ ~nsBlockFrame();
#if 0
@@ -208,66 +208,66 @@ protected:
PRBool IsPseudoFrame() const;
- nsresult InitialReflow(nsCSSBlockReflowState& aState);
+ nsresult InitialReflow(nsBlockReflowState& aState);
- nsresult FrameAppendedReflow(nsCSSBlockReflowState& aState);
+ nsresult FrameAppendedReflow(nsBlockReflowState& aState);
- nsresult InsertNewFrame(nsCSSBlockFrame* aParentFrame,
+ nsresult InsertNewFrame(nsBlockFrame* aParentFrame,
nsIFrame* aNewFrame,
nsIFrame* aPrevSibling);
- nsresult FrameInsertedReflow(nsCSSBlockReflowState& aState);
+ nsresult FrameInsertedReflow(nsBlockReflowState& aState);
- nsresult FrameDeletedReflow(nsCSSBlockReflowState& aState);
+ nsresult FrameDeletedReflow(nsBlockReflowState& aState);
nsresult CreateNewFrames(nsIPresContext* aPresContext);
- nsresult FindTextRuns(nsCSSBlockReflowState& aState);
+ nsresult FindTextRuns(nsBlockReflowState& aState);
- nsresult ChildIncrementalReflow(nsCSSBlockReflowState& aState);
+ nsresult ChildIncrementalReflow(nsBlockReflowState& aState);
- nsresult ResizeReflow(nsCSSBlockReflowState& aState);
+ nsresult ResizeReflow(nsBlockReflowState& aState);
- void ComputeFinalSize(nsCSSBlockReflowState& aState,
+ void ComputeFinalSize(nsBlockReflowState& aState,
nsReflowMetrics& aMetrics,
nsRect& aDesiredRect);
- nsresult ReflowLinesAt(nsCSSBlockReflowState& aState, LineData* aLine);
+ nsresult ReflowLinesAt(nsBlockReflowState& aState, LineData* aLine);
- PRBool ReflowLine(nsCSSBlockReflowState& aState,
+ PRBool ReflowLine(nsBlockReflowState& aState,
LineData* aLine,
nsInlineReflowStatus& aReflowResult);
- PRBool PlaceLine(nsCSSBlockReflowState& aState,
+ PRBool PlaceLine(nsBlockReflowState& aState,
LineData* aLine,
nsInlineReflowStatus aReflowStatus);
void FindFloaters(LineData* aLine);
- PRBool ReflowInlineFrame(nsCSSBlockReflowState& aState,
+ PRBool ReflowInlineFrame(nsBlockReflowState& aState,
LineData* aLine,
nsIFrame* aFrame,
nsInlineReflowStatus& aResult);
- nsresult SplitLine(nsCSSBlockReflowState& aState,
+ nsresult SplitLine(nsBlockReflowState& aState,
LineData* aLine,
nsIFrame* aFrame,
PRBool aLineWasComplete);
- PRBool ReflowBlockFrame(nsCSSBlockReflowState& aState,
+ PRBool ReflowBlockFrame(nsBlockReflowState& aState,
LineData* aLine,
nsIFrame* aFrame,
nsInlineReflowStatus& aResult);
- PRBool PullFrame(nsCSSBlockReflowState& aState,
+ PRBool PullFrame(nsBlockReflowState& aState,
LineData* aToLine,
LineData** aFromList,
PRBool aUpdateGeometricParent,
nsInlineReflowStatus& aResult);
- void PushLines(nsCSSBlockReflowState& aState);
+ void PushLines(nsBlockReflowState& aState);
void ReflowFloater(nsIPresContext* aPresContext,
- nsCSSBlockReflowState& aState,
+ nsBlockReflowState& aState,
nsIFrame* aFloaterFrame);
void PaintChildren(nsIPresContext& aPresContext,
@@ -288,12 +288,12 @@ protected:
// nsVoidArray* mRunInFloaters;
// Text run information
- nsCSSTextRun* mTextRuns;
+ nsTextRun* mTextRuns;
// XXX TEMP
PRBool mHasBeenInitialized;
- friend struct nsCSSBlockReflowState;
+ friend struct nsBlockReflowState;
};
//----------------------------------------------------------------------
@@ -429,7 +429,7 @@ ListFloaters(FILE* out, nsVoidArray* aFloaters)
}
static void
-ListTextRuns(FILE* out, PRInt32 aIndent, nsCSSTextRun* aRuns)
+ListTextRuns(FILE* out, PRInt32 aIndent, nsTextRun* aRuns)
{
while (nsnull != aRuns) {
aRuns->List(out, aIndent);
@@ -641,7 +641,7 @@ FindLineContaining(LineData* aLine, nsIFrame* aFrame)
//----------------------------------------------------------------------
-void nsCSSBlockReflowState::BlockBandData::ComputeAvailSpaceRect()
+void nsBlockReflowState::BlockBandData::ComputeAvailSpaceRect()
{
nsBandTrapezoid* trapezoid = data;
@@ -728,9 +728,9 @@ GetParentLeftPadding(const nsReflowState* aReflowState)
return leftPadding;
}
-nsCSSBlockReflowState::nsCSSBlockReflowState(nsIPresContext* aPresContext,
+nsBlockReflowState::nsBlockReflowState(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
- nsCSSBlockFrame* aBlock,
+ nsBlockFrame* aBlock,
nsIStyleContext* aBlockSC,
const nsReflowState& aReflowState,
nsReflowMetrics& aMetrics,
@@ -902,7 +902,7 @@ nsCSSBlockReflowState::nsCSSBlockReflowState(nsIPresContext* aPresContext,
NS_RELEASE(blockContent);
}
-nsCSSBlockReflowState::~nsCSSBlockReflowState()
+nsBlockReflowState::~nsBlockReflowState()
{
// Restore the coordinate system
mSpaceManager->Translate(-mBorderPadding.left, -mBorderPadding.top);
@@ -921,7 +921,7 @@ nsCSSBlockReflowState::~nsCSSBlockReflowState()
// available space is relative to our coordinate system (0,0) is our
// upper left corner.
void
-nsCSSBlockReflowState::GetAvailableSpace()
+nsBlockReflowState::GetAvailableSpace()
{
nsISpaceManager* sm = mSpaceManager;
@@ -942,7 +942,7 @@ nsCSSBlockReflowState::GetAvailableSpace()
mCurrentBand.ComputeAvailSpaceRect();
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
- ("nsCSSBlockReflowState::GetAvailableSpace: band={%d,%d,%d,%d} count=%d",
+ ("nsBlockReflowState::GetAvailableSpace: band={%d,%d,%d,%d} count=%d",
mCurrentBand.availSpace.x, mCurrentBand.availSpace.y,
mCurrentBand.availSpace.width, mCurrentBand.availSpace.height,
mCurrentBand.count));
@@ -951,7 +951,7 @@ nsCSSBlockReflowState::GetAvailableSpace()
//----------------------------------------------------------------------
nsresult
-NS_NewCSSBlockFrame(nsIFrame** aInstancePtrResult,
+NS_NewBlockFrame(nsIFrame** aInstancePtrResult,
nsIContent* aContent,
nsIFrame* aParent)
{
@@ -959,7 +959,7 @@ NS_NewCSSBlockFrame(nsIFrame** aInstancePtrResult,
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
- nsIFrame* it = new nsCSSBlockFrame(aContent, aParent);
+ nsIFrame* it = new nsBlockFrame(aContent, aParent);
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@@ -967,22 +967,22 @@ NS_NewCSSBlockFrame(nsIFrame** aInstancePtrResult,
return NS_OK;
}
-nsCSSBlockFrame::nsCSSBlockFrame(nsIContent* aContent, nsIFrame* aParent)
- : nsCSSBlockFrameSuper(aContent, aParent)
+nsBlockFrame::nsBlockFrame(nsIContent* aContent, nsIFrame* aParent)
+ : nsBlockFrameSuper(aContent, aParent)
{
mHasBeenInitialized = PR_FALSE;
}
-nsCSSBlockFrame::~nsCSSBlockFrame()
+nsBlockFrame::~nsBlockFrame()
{
// if (nsnull != mRunInFloaters) {
// delete mRunInFloaters;
// }
- nsCSSTextRun::DeleteTextRuns(mTextRuns);
+ nsTextRun::DeleteTextRuns(mTextRuns);
}
NS_IMETHODIMP
-nsCSSBlockFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
+nsBlockFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
NS_PRECONDITION(0 != aInstancePtr, "null ptr");
if (NULL == aInstancePtr) {
@@ -1001,29 +1001,29 @@ nsCSSBlockFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
*aInstancePtr = (void*) ((nsIFloaterContainer*) this);
return NS_OK;
}
- return nsCSSBlockFrameSuper::QueryInterface(aIID, aInstancePtr);
+ return nsBlockFrameSuper::QueryInterface(aIID, aInstancePtr);
}
NS_IMETHODIMP
-nsCSSBlockFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList)
+nsBlockFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList)
{
mHasBeenInitialized = PR_TRUE;
return AppendNewFrames(&aPresContext, aChildList);
}
NS_IMETHODIMP
-nsCSSBlockFrame::DeleteFrame(nsIPresContext& aPresContext)
+nsBlockFrame::DeleteFrame(nsIPresContext& aPresContext)
{
DeleteLineList(aPresContext, mLines);
DeleteLineList(aPresContext, mOverflowLines);
- nsCSSBlockFrameSuper::DeleteFrame(aPresContext);
+ nsBlockFrameSuper::DeleteFrame(aPresContext);
return NS_OK;
}
PRBool
-nsCSSBlockFrame::IsPseudoFrame() const
+nsBlockFrame::IsPseudoFrame() const
{
PRBool result = PR_FALSE;
@@ -1041,31 +1041,31 @@ nsCSSBlockFrame::IsPseudoFrame() const
}
NS_IMETHODIMP
-nsCSSBlockFrame::IsSplittable(nsSplittableType& aIsSplittable) const
+nsBlockFrame::IsSplittable(nsSplittableType& aIsSplittable) const
{
aIsSplittable = NS_FRAME_SPLITTABLE_NON_RECTANGULAR;
return NS_OK;
}
NS_IMETHODIMP
-nsCSSBlockFrame::CreateContinuingFrame(nsIPresContext& aCX,
+nsBlockFrame::CreateContinuingFrame(nsIPresContext& aCX,
nsIFrame* aParent,
nsIStyleContext* aStyleContext,
nsIFrame*& aContinuingFrame)
{
- nsCSSBlockFrame* cf = new nsCSSBlockFrame(mContent, aParent);
+ nsBlockFrame* cf = new nsBlockFrame(mContent, aParent);
if (nsnull == cf) {
return NS_ERROR_OUT_OF_MEMORY;
}
PrepareContinuingFrame(aCX, aParent, aStyleContext, cf);
aContinuingFrame = cf;
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("nsCSSBlockFrame::CreateContinuingFrame: newFrame=%p", cf));
+ ("nsBlockFrame::CreateContinuingFrame: newFrame=%p", cf));
return NS_OK;
}
NS_IMETHODIMP
-nsCSSBlockFrame::ListTag(FILE* out) const
+nsBlockFrame::ListTag(FILE* out) const
{
if ((nsnull != mGeometricParent) && IsPseudoFrame()) {
fprintf(out, "*block<");
@@ -1080,13 +1080,13 @@ nsCSSBlockFrame::ListTag(FILE* out) const
GetContentIndex(contentIndex);
fprintf(out, ">(%d)@%p", contentIndex, this);
} else {
- nsCSSBlockFrameSuper::ListTag(out);
+ nsBlockFrameSuper::ListTag(out);
}
return NS_OK;
}
NS_METHOD
-nsCSSBlockFrame::List(FILE* out, PRInt32 aIndent, nsIListFilter *aFilter) const
+nsBlockFrame::List(FILE* out, PRInt32 aIndent, nsIListFilter *aFilter) const
{
// if a filter is present, only output this frame if the filter says we should
nsIAtom* tag;
@@ -1183,7 +1183,7 @@ nsCSSBlockFrame::List(FILE* out, PRInt32 aIndent, nsIListFilter *aFilter) const
// Child frame enumeration
NS_IMETHODIMP
-nsCSSBlockFrame::ChildCount(PRInt32& aChildCount) const
+nsBlockFrame::ChildCount(PRInt32& aChildCount) const
{
PRInt32 sum = 0;
LineData* line = mLines;
@@ -1196,7 +1196,7 @@ nsCSSBlockFrame::ChildCount(PRInt32& aChildCount) const
}
NS_IMETHODIMP
-nsCSSBlockFrame::ChildAt(PRInt32 aIndex, nsIFrame*& aFrame) const
+nsBlockFrame::ChildAt(PRInt32 aIndex, nsIFrame*& aFrame) const
{
LineData* line = mLines;
if ((aIndex >= 0) && (nsnull != line)) {
@@ -1226,7 +1226,7 @@ nsCSSBlockFrame::ChildAt(PRInt32 aIndex, nsIFrame*& aFrame) const
}
NS_IMETHODIMP
-nsCSSBlockFrame::IndexOf(const nsIFrame* aChild, PRInt32& aIndex) const
+nsBlockFrame::IndexOf(const nsIFrame* aChild, PRInt32& aIndex) const
{
aIndex = -1;
if (nsnull != mLines) {
@@ -1246,14 +1246,14 @@ nsCSSBlockFrame::IndexOf(const nsIFrame* aChild, PRInt32& aIndex) const
}
NS_IMETHODIMP
-nsCSSBlockFrame::FirstChild(nsIFrame*& aFirstChild) const
+nsBlockFrame::FirstChild(nsIFrame*& aFirstChild) const
{
aFirstChild = (nsnull != mLines) ? mLines->mFirstChild : nsnull;
return NS_OK;
}
NS_IMETHODIMP
-nsCSSBlockFrame::NextChild(const nsIFrame* aChild, nsIFrame*& aNextChild) const
+nsBlockFrame::NextChild(const nsIFrame* aChild, nsIFrame*& aNextChild) const
{
NS_PRECONDITION(aChild != nsnull, "null pointer");
aChild->GetNextSibling(aNextChild);
@@ -1261,7 +1261,7 @@ nsCSSBlockFrame::NextChild(const nsIFrame* aChild, nsIFrame*& aNextChild) const
}
NS_IMETHODIMP
-nsCSSBlockFrame::PrevChild(const nsIFrame* aChild, nsIFrame*& aPrevChild) const
+nsBlockFrame::PrevChild(const nsIFrame* aChild, nsIFrame*& aPrevChild) const
{
NS_PRECONDITION(aChild != nsnull, "null pointer");
if ((nsnull != mLines) && (mLines->mFirstChild != aChild)) {
@@ -1281,7 +1281,7 @@ nsCSSBlockFrame::PrevChild(const nsIFrame* aChild, nsIFrame*& aPrevChild) const
}
NS_IMETHODIMP
-nsCSSBlockFrame::LastChild(nsIFrame*& aLastChild) const
+nsBlockFrame::LastChild(nsIFrame*& aLastChild) const
{
LineData* line = LastLine(mLines);
if (nsnull != line) {
@@ -1297,7 +1297,7 @@ nsCSSBlockFrame::LastChild(nsIFrame*& aLastChild) const
#if XXX
PRBool
-nsCSSBlockFrame::GetLastContentIsComplete() const
+nsBlockFrame::GetLastContentIsComplete() const
{
PRBool result = PR_TRUE;
LineData* line = LastLine(mLines);
@@ -1308,7 +1308,7 @@ nsCSSBlockFrame::GetLastContentIsComplete() const
}
PRInt32
-nsCSSBlockFrame::GetFirstContentOffset() const
+nsBlockFrame::GetFirstContentOffset() const
{
PRInt32 result = 0;
LineData* line = mLines;
@@ -1319,7 +1319,7 @@ nsCSSBlockFrame::GetFirstContentOffset() const
}
PRInt32
-nsCSSBlockFrame::GetLastContentOffset() const
+nsBlockFrame::GetLastContentOffset() const
{
PRInt32 result = 0;
LineData* line = LastNonEmptyLine(mLines);
@@ -1331,7 +1331,7 @@ nsCSSBlockFrame::GetLastContentOffset() const
#endif
NS_IMETHODIMP
-nsCSSBlockFrame::ReflowAround(nsIPresContext& aPresContext,
+nsBlockFrame::ReflowAround(nsIPresContext& aPresContext,
nsISpaceManager* aSpaceManager,
nsReflowMetrics& aMetrics,
const nsReflowState& aReflowState,
@@ -1339,7 +1339,7 @@ nsCSSBlockFrame::ReflowAround(nsIPresContext& aPresContext,
nsReflowStatus& aStatus)
{
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("enter nsCSSBlockFrame::Reflow: maxSize=%d,%d reason=%d [%d,%d,%c]",
+ ("enter nsBlockFrame::Reflow: maxSize=%d,%d reason=%d [%d,%d,%c]",
aReflowState.maxSize.width,
aReflowState.maxSize.height,
aReflowState.reason,
@@ -1357,7 +1357,7 @@ nsCSSBlockFrame::ReflowAround(nsIPresContext& aPresContext,
// Replace parent provided reflow state with our own significantly
// more extensive version.
- nsCSSBlockReflowState state(&aPresContext, aSpaceManager,
+ nsBlockReflowState state(&aPresContext, aSpaceManager,
this, mStyleContext,
aReflowState, aMetrics,
PRBool(nsnull != aMetrics.maxElementSize));
@@ -1450,7 +1450,7 @@ nsCSSBlockFrame::ReflowAround(nsIPresContext& aPresContext,
#endif
aStatus = rv;
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("exit nsCSSBlockFrame::Reflow: size=%d,%d rv=%x [%d,%d,%c]",
+ ("exit nsBlockFrame::Reflow: size=%d,%d rv=%x [%d,%d,%c]",
aMetrics.width, aMetrics.height, rv,
GetFirstContentOffset(), GetLastContentOffset(),
GetLastContentIsComplete()?'T':'F'));
@@ -1458,7 +1458,7 @@ nsCSSBlockFrame::ReflowAround(nsIPresContext& aPresContext,
}
nsresult
-nsCSSBlockFrame::ProcessInitialReflow(nsIPresContext* aPresContext)
+nsBlockFrame::ProcessInitialReflow(nsIPresContext* aPresContext)
{
// XXX ick; html stuff. pfuui.
@@ -1466,7 +1466,7 @@ nsCSSBlockFrame::ProcessInitialReflow(nsIPresContext* aPresContext)
const nsStyleDisplay* display = (const nsStyleDisplay*)
mStyleContext->GetStyleData(eStyleStruct_Display);
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("nsCSSBlockFrame::ProcessInitialReflow: display=%d",
+ ("nsBlockFrame::ProcessInitialReflow: display=%d",
display->mDisplay));
if (NS_STYLE_DISPLAY_LIST_ITEM == display->mDisplay) {
// This container is a list-item container. Therefore it needs a
@@ -1521,11 +1521,11 @@ nsCSSBlockFrame::ProcessInitialReflow(nsIPresContext* aPresContext)
// methods on nsContainerFrame that we have no right using.
// XXX can't work: our parent can be an nsContainerFrame -or- an
-// nsCSSBlockFrame; we can't tell them apart and yet the need to be
+// nsBlockFrame; we can't tell them apart and yet the need to be
// updated when we are a pseudo-frame
void
-nsCSSBlockFrame::PropagateContentOffsets()
+nsBlockFrame::PropagateContentOffsets()
{
NS_PRECONDITION(IsPseudoFrame(), "not a pseudo frame");
nsIFrame* parent = mGeometricParent;
@@ -1553,7 +1553,7 @@ nsCSSBlockFrame::PropagateContentOffsets()
#endif
void
-nsCSSBlockFrame::ComputeFinalSize(nsCSSBlockReflowState& aState,
+nsBlockFrame::ComputeFinalSize(nsBlockReflowState& aState,
nsReflowMetrics& aMetrics,
nsRect& aDesiredRect)
{
@@ -1657,7 +1657,7 @@ nsCSSBlockFrame::ComputeFinalSize(nsCSSBlockReflowState& aState,
}
nsresult
-nsCSSBlockFrame::AppendNewFrames(nsIPresContext* aPresContext, nsIFrame* aNewFrame)
+nsBlockFrame::AppendNewFrames(nsIPresContext* aPresContext, nsIFrame* aNewFrame)
{
// Get our last line and then get its last child
nsIFrame* lastFrame;
@@ -1700,12 +1700,13 @@ nsCSSBlockFrame::AppendNewFrames(nsIPresContext* aPresContext, nsIFrame* aNewFra
return rv;
}
PRBool isBlock =
- nsCSSLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition);
+ nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition);
// See if the element wants to be floated
if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) {
// Create a placeholder frame that will serve as the anchor point.
- nsPlaceholderFrame* placeholder = CreatePlaceholderFrame(aPresContext, frame);
+ nsPlaceholderFrame* placeholder =
+ CreatePlaceholderFrame(aPresContext, frame);
// Remove the floated element from the flow, and replace it with the
// placeholder frame
@@ -1818,7 +1819,7 @@ nsCSSBlockFrame::AppendNewFrames(nsIPresContext* aPresContext, nsIFrame* aNewFra
}
nsresult
-nsCSSBlockFrame::InitialReflow(nsCSSBlockReflowState& aState)
+nsBlockFrame::InitialReflow(nsBlockReflowState& aState)
{
// Create synthetic content (XXX a hack)
nsresult rv = ProcessInitialReflow(aState.mPresContext);
@@ -1852,7 +1853,7 @@ nsCSSBlockFrame::InitialReflow(nsCSSBlockReflowState& aState)
}
nsresult
-nsCSSBlockFrame::FrameAppendedReflow(nsCSSBlockReflowState& aState)
+nsBlockFrame::FrameAppendedReflow(nsBlockReflowState& aState)
{
// XXX CONSTRUCTION
#if 0
@@ -1933,7 +1934,7 @@ NS_ASSERTION(xmost < 1000000, "bad line width");
aState.GetAvailableSpace();
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("nsCSSBlockReflowState::FrameAppendedReflow: y=%d firstDirtyLine=%p",
+ ("nsBlockReflowState::FrameAppendedReflow: y=%d firstDirtyLine=%p",
aState.mY, firstDirtyLine));
// Reflow lines from there forward
@@ -1942,7 +1943,7 @@ NS_ASSERTION(xmost < 1000000, "bad line width");
}
nsresult
-nsCSSBlockFrame::CreateNewFrames(nsIPresContext* aPresContext)
+nsBlockFrame::CreateNewFrames(nsIPresContext* aPresContext)
{
// If we need to be continued but aren't, we will have an overflow list
NS_ASSERTION((nsnull == mOverflowLines) && (nsnull == mNextInFlow),
@@ -1994,7 +1995,7 @@ nsCSSBlockFrame::CreateNewFrames(nsIPresContext* aPresContext)
PRInt32 lastContentIndex;
mContent->ChildCount(lastContentIndex);
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("enter nsCSSBlockFrame::CreateNewFrames: kidContentIndex=%d lastContentIndex=%d",
+ ("enter nsBlockFrame::CreateNewFrames: kidContentIndex=%d lastContentIndex=%d",
kidContentIndex, lastContentIndex));
for (; kidContentIndex < lastContentIndex; kidContentIndex++) {
nsIContent* kid;
@@ -2016,7 +2017,7 @@ nsCSSBlockFrame::CreateNewFrames(nsIPresContext* aPresContext)
lastFrame = frame;
//XXX childPrevInFlow = nsnull;
NS_FRAME_TRACE(NS_FRAME_TRACE_NEW_FRAMES,
- ("nsCSSBlockFrame::CreateNewFrames: new-frame=%p", frame));
+ ("nsBlockFrame::CreateNewFrames: new-frame=%p", frame));
// See if the child is a block or non-block
const nsStyleDisplay* kidDisplay;
@@ -2032,7 +2033,7 @@ nsCSSBlockFrame::CreateNewFrames(nsIPresContext* aPresContext)
return rv;
}
PRBool isBlock =
- nsCSSLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition);
+ nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition);
// If the child is an inline then add it to the lastLine (if it's
// an inline line, otherwise make a new line). If the child is a
@@ -2091,16 +2092,16 @@ nsCSSBlockFrame::CreateNewFrames(nsIPresContext* aPresContext)
}
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("exit nsCSSBlockFrame::CreateNewFrames"));
+ ("exit nsBlockFrame::CreateNewFrames"));
return NS_OK;
}
// XXX keep the text-run data in the first-in-flow of the block
nsresult
-nsCSSBlockFrame::FindTextRuns(nsCSSBlockReflowState& aState)
+nsBlockFrame::FindTextRuns(nsBlockReflowState& aState)
{
// Destroy old run information first
- nsCSSTextRun::DeleteTextRuns(mTextRuns);
+ nsTextRun::DeleteTextRuns(mTextRuns);
mTextRuns = nsnull;
aState.mLineLayout.ResetTextRuns();
@@ -2144,7 +2145,7 @@ nsCSSBlockFrame::FindTextRuns(nsCSSBlockReflowState& aState)
}
nsresult
-nsCSSBlockFrame::FrameInsertedReflow(nsCSSBlockReflowState& aState)
+nsBlockFrame::FrameInsertedReflow(nsBlockReflowState& aState)
{
LineData* line = mLines;
while (nsnull != line->mNext) {
@@ -2166,7 +2167,7 @@ nsCSSBlockFrame::FrameInsertedReflow(nsCSSBlockReflowState& aState)
}
nsresult
-nsCSSBlockFrame::FrameDeletedReflow(nsCSSBlockReflowState& aState)
+nsBlockFrame::FrameDeletedReflow(nsBlockReflowState& aState)
{
if (nsnull == mLines) {
return NS_OK;
@@ -2199,7 +2200,7 @@ nsCSSBlockFrame::FrameDeletedReflow(nsCSSBlockReflowState& aState)
// recover state before it, slide lines down after it.
nsresult
-nsCSSBlockFrame::ChildIncrementalReflow(nsCSSBlockReflowState& aState)
+nsBlockFrame::ChildIncrementalReflow(nsBlockReflowState& aState)
{
// Generate text-run information; this will also "fluff out" any
// inline children's frame tree.
@@ -2215,7 +2216,7 @@ nsCSSBlockFrame::ChildIncrementalReflow(nsCSSBlockReflowState& aState)
}
nsresult
-nsCSSBlockFrame::ResizeReflow(nsCSSBlockReflowState& aState)
+nsBlockFrame::ResizeReflow(nsBlockReflowState& aState)
{
// Mark everything dirty
LineData* line = mLines;
@@ -2231,7 +2232,7 @@ nsCSSBlockFrame::ResizeReflow(nsCSSBlockReflowState& aState)
}
nsresult
-nsCSSBlockFrame::ReflowLinesAt(nsCSSBlockReflowState& aState, LineData* aLine)
+nsBlockFrame::ReflowLinesAt(nsBlockReflowState& aState, LineData* aLine)
{
#if XXX
if ((nsnull != mRunInFloaters) && (aLine == mLines)) {
@@ -2258,7 +2259,7 @@ nsCSSBlockFrame::ReflowLinesAt(nsCSSBlockReflowState& aState, LineData* aLine)
// Grab first line from our next-in-flow
aLine = aState.mNextInFlow->mLines;
if (nsnull == aLine) {
- aState.mNextInFlow = (nsCSSBlockFrame*) aState.mNextInFlow->mNextInFlow;
+ aState.mNextInFlow = (nsBlockFrame*) aState.mNextInFlow->mNextInFlow;
continue;
}
// XXX See if the line is not dirty; if it's not maybe we can
@@ -2335,15 +2336,15 @@ nsCSSBlockFrame::ReflowLinesAt(nsCSSBlockReflowState& aState, LineData* aLine)
* or contain 1 or more inline frames.
*/
PRBool
-nsCSSBlockFrame::ReflowLine(nsCSSBlockReflowState& aState,
+nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
LineData* aLine,
nsInlineReflowStatus& aReflowResult)
{
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("nsCSSBlockFrame::ReflowLine: line=%p", aLine));
+ ("nsBlockFrame::ReflowLine: line=%p", aLine));
PRBool keepGoing = PR_FALSE;
- nsCSSBlockFrame* nextInFlow;
+ nsBlockFrame* nextInFlow;
aState.mCurrentLine = aLine;
aState.mInlineLayoutPrepared = PR_FALSE;
aLine->ClearDirty();
@@ -2366,7 +2367,7 @@ nsCSSBlockFrame::ReflowLine(nsCSSBlockReflowState& aState,
const nsStylePosition* position;
frame->GetStyleData(eStyleStruct_Position,
(const nsStyleStruct*&) position);
- PRBool isBlock = nsCSSLineLayout::TreatFrameAsBlock(display, position);
+ PRBool isBlock = nsLineLayout::TreatFrameAsBlock(display, position);
NS_ASSERTION(isBlock == aLine->IsBlock(), "bad line isBlock");
#endif
if (aLine->IsBlock()) {
@@ -2412,7 +2413,7 @@ nsCSSBlockFrame::ReflowLine(nsCSSBlockReflowState& aState,
while (nsnull != nextInFlow) {
LineData* line = nextInFlow->mLines;
if (nsnull == line) {
- nextInFlow = (nsCSSBlockFrame*) nextInFlow->mNextInFlow;
+ nextInFlow = (nsBlockFrame*) nextInFlow->mNextInFlow;
aState.mNextInFlow = nextInFlow;
continue;
}
@@ -2432,13 +2433,13 @@ done:;
}
PRBool
-nsCSSBlockFrame::ReflowBlockFrame(nsCSSBlockReflowState& aState,
+nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
LineData* aLine,
nsIFrame* aFrame,
nsInlineReflowStatus& aReflowResult)
{
NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockFrame::ReflowBlockFrame: line=%p frame=%p y=%d",
+ ("nsBlockFrame::ReflowBlockFrame: line=%p frame=%p y=%d",
aLine, aFrame, aState.mY));
NS_ASSERTION(nsnull != aState.mSpaceManager, "null ptr");
@@ -2563,7 +2564,7 @@ nsCSSBlockFrame::ReflowBlockFrame(nsCSSBlockReflowState& aState,
aFrame->MoveTo(x, y);
NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockFrame::ReflowBlockFrame: xy={%d,%d} availSize={%d,%d}",
+ ("nsBlockFrame::ReflowBlockFrame: xy={%d,%d} availSize={%d,%d}",
x, y, availSize.width, availSize.height));
// Determine the reason for the reflow
@@ -2633,7 +2634,7 @@ nsCSSBlockFrame::ReflowBlockFrame(nsCSSBlockReflowState& aState,
// parent is not this because we are executing pullup code)
nsIFrame* parent;
aFrame->GetGeometricParent(parent);
- ((nsCSSBlockFrame*)parent)->DeleteNextInFlowsFor(*aState.mPresContext, aFrame);
+ ((nsBlockFrame*)parent)->DeleteNextInFlowsFor(*aState.mPresContext, aFrame);
}
aLine->SetLastContentIsComplete();
aReflowResult = NS_FRAME_COMPLETE;
@@ -2676,7 +2677,7 @@ nsCSSBlockFrame::ReflowBlockFrame(nsCSSBlockReflowState& aState,
// See if it fit
newY = y + metrics.height + childBottomMargin;
NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockFrame::ReflowBlockFrame: metrics={%d,%d} newY=%d maxY=%d",
+ ("nsBlockFrame::ReflowBlockFrame: metrics={%d,%d} newY=%d maxY=%d",
metrics.width, metrics.height, newY, aState.mBottomEdge));
if ((mLines != aLine) && (newY > aState.mBottomEdge)) {
// None of the block fit. Push aLine and any other lines that follow
@@ -2769,7 +2770,7 @@ NS_ASSERTION(xmost < 1000000, "bad line width");
}
PRBool
-nsCSSBlockFrame::ReflowInlineFrame(nsCSSBlockReflowState& aState,
+nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
LineData* aLine,
nsIFrame* aFrame,
nsInlineReflowStatus& aReflowResult)
@@ -2876,14 +2877,14 @@ nsCSSBlockFrame::ReflowInlineFrame(nsCSSBlockReflowState& aState,
// XXX refactor this since the split NEVER has to deal with blocks
nsresult
-nsCSSBlockFrame::SplitLine(nsCSSBlockReflowState& aState,
+nsBlockFrame::SplitLine(nsBlockReflowState& aState,
LineData* aLine,
nsIFrame* aFrame,
PRBool aLineWasComplete)
{
PRInt32 pushCount = aLine->mChildCount - aState.mInlineLayout.mFrameNum;
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("nsCSSBlockFrame::SplitLine: pushing %d frames",
+ ("nsBlockFrame::SplitLine: pushing %d frames",
pushCount));
if (0 != pushCount) {
NS_ASSERTION(nsnull != aFrame, "whoops");
@@ -2922,7 +2923,7 @@ nsCSSBlockFrame::SplitLine(nsCSSBlockReflowState& aState,
}
PRBool
-nsCSSBlockFrame::PullFrame(nsCSSBlockReflowState& aState,
+nsBlockFrame::PullFrame(nsBlockReflowState& aState,
LineData* aLine,
LineData** aFromList,
PRBool aUpdateGeometricParent,
@@ -2960,7 +2961,7 @@ nsCSSBlockFrame::PullFrame(nsCSSBlockReflowState& aState,
const nsStylePosition* position;
frame->GetStyleData(eStyleStruct_Position,
(const nsStyleStruct*&) position);
- PRBool isBlock = nsCSSLineLayout::TreatFrameAsBlock(display, position);
+ PRBool isBlock = nsLineLayout::TreatFrameAsBlock(display, position);
NS_ASSERTION(isBlock == aLine->IsBlock(), "bad line isBlock");
#endif
}
@@ -3004,7 +3005,7 @@ nsCSSBlockFrame::PullFrame(nsCSSBlockReflowState& aState,
}
PRBool
-nsCSSBlockFrame::PlaceLine(nsCSSBlockReflowState& aState,
+nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
LineData* aLine,
nsInlineReflowStatus aReflowStatus)
{
@@ -3021,7 +3022,7 @@ nsCSSBlockFrame::PlaceLine(nsCSSBlockReflowState& aState,
// too.
nscoord newY = aState.mY + aLine->mBounds.height;
NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockFrame::PlaceLine: newY=%d limit=%d lineHeight=%d",
+ ("nsBlockFrame::PlaceLine: newY=%d limit=%d lineHeight=%d",
newY, aState.mBottomEdge, aLine->mBounds.height));
if ((mLines != aLine) && (newY > aState.mBottomEdge)) {
// Push this line and all of it's children and anything else that
@@ -3075,7 +3076,7 @@ NS_ASSERTION(xmost < 1000000, "bad line width");
case NS_STYLE_CLEAR_RIGHT:
case NS_STYLE_CLEAR_LEFT_AND_RIGHT:
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("nsCSSBlockFrame::PlaceLine: clearing floaters=%d",
+ ("nsBlockFrame::PlaceLine: clearing floaters=%d",
breakType));
aState.ClearFloaters(breakType);
break;
@@ -3122,7 +3123,7 @@ FindFloatersIn(nsIFrame* aFrame, nsVoidArray*& aArray)
}
void
-nsCSSBlockFrame::FindFloaters(LineData* aLine)
+nsBlockFrame::FindFloaters(LineData* aLine)
{
nsVoidArray* floaters = aLine->mFloaters;
if (nsnull != floaters) {
@@ -3166,7 +3167,7 @@ nsCSSBlockFrame::FindFloaters(LineData* aLine)
}
void
-nsCSSBlockFrame::PushLines(nsCSSBlockReflowState& aState)
+nsBlockFrame::PushLines(nsBlockReflowState& aState)
{
NS_ASSERTION(nsnull != aState.mPrevLine, "bad push");
@@ -3181,7 +3182,7 @@ nsCSSBlockFrame::PushLines(nsCSSBlockReflowState& aState)
lastFrame->SetNextSibling(nsnull);
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("nsCSSBlockFrame::PushLines: line=%p prevInFlow=%p nextInFlow=%p",
+ ("nsBlockFrame::PushLines: line=%p prevInFlow=%p nextInFlow=%p",
mOverflowLines, mPrevInFlow, mNextInFlow));
#ifdef NS_DEBUG
if (GetVerifyTreeEnable()) {
@@ -3192,18 +3193,18 @@ nsCSSBlockFrame::PushLines(nsCSSBlockReflowState& aState)
}
PRBool
-nsCSSBlockFrame::DrainOverflowLines()
+nsBlockFrame::DrainOverflowLines()
{
PRBool drained = PR_FALSE;
// First grab the prev-in-flows overflow lines
- nsCSSBlockFrame* prevBlock = (nsCSSBlockFrame*) mPrevInFlow;
+ nsBlockFrame* prevBlock = (nsBlockFrame*) mPrevInFlow;
if (nsnull != prevBlock) {
LineData* line = prevBlock->mOverflowLines;
if (nsnull != line) {
drained = PR_TRUE;
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("nsCSSBlockFrame::DrainOverflowLines: line=%p prevInFlow=%p",
+ ("nsBlockFrame::DrainOverflowLines: line=%p prevInFlow=%p",
line, prevBlock));
prevBlock->mOverflowLines = nsnull;
@@ -3248,7 +3249,7 @@ nsCSSBlockFrame::DrainOverflowLines()
// we are told to reflow again before a next-in-flow is created
// and reflows.
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("nsCSSBlockFrame::DrainOverflowLines: from me, line=%p",
+ ("nsBlockFrame::DrainOverflowLines: from me, line=%p",
mOverflowLines));
LineData* lastLine = LastLine(mLines);
if (nsnull == lastLine) {
@@ -3281,12 +3282,12 @@ nsCSSBlockFrame::DrainOverflowLines()
#if 0
// XXX a copy of nsHTMLContainerFrame's
NS_IMETHODIMP
-nsCSSBlockFrame::ContentAppended(nsIPresShell* aShell,
+nsBlockFrame::ContentAppended(nsIPresShell* aShell,
nsIPresContext* aPresContext,
nsIContent* aContainer)
{
// Get the last-in-flow
- nsCSSBlockFrame* lastInFlow = (nsCSSBlockFrame*)GetLastInFlow();
+ nsBlockFrame* lastInFlow = (nsBlockFrame*)GetLastInFlow();
// Generate a reflow command for the frame
nsIReflowCommand* cmd;
@@ -3304,7 +3305,7 @@ nsCSSBlockFrame::ContentAppended(nsIPresShell* aShell,
#endif
nsresult
-nsCSSBlockFrame::InsertNewFrame(nsCSSBlockFrame* aParentFrame,
+nsBlockFrame::InsertNewFrame(nsBlockFrame* aParentFrame,
nsIFrame* aNewFrame,
nsIFrame* aPrevSibling)
{
@@ -3312,7 +3313,7 @@ nsCSSBlockFrame::InsertNewFrame(nsCSSBlockFrame* aParentFrame,
aNewFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
const nsStylePosition* position;
aNewFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&) position);
- PRUint16 newFrameIsBlock = nsCSSLineLayout::TreatFrameAsBlock(display, position)
+ PRUint16 newFrameIsBlock = nsLineLayout::TreatFrameAsBlock(display, position)
? LINE_IS_BLOCK : 0;
// Insert/append the frame into flows line list at the right spot
@@ -3429,7 +3430,7 @@ nsCSSBlockFrame::InsertNewFrame(nsCSSBlockFrame* aParentFrame,
// XXX we assume that the insertion is really an assertion and never an append
// XXX what about zero lines case
NS_IMETHODIMP
-nsCSSBlockFrame::ContentInserted(nsIPresShell* aShell,
+nsBlockFrame::ContentInserted(nsIPresShell* aShell,
nsIPresContext* aPresContext,
nsIContent* aContainer,
nsIContent* aChild,
@@ -3459,7 +3460,7 @@ nsCSSBlockFrame::ContentInserted(nsIPresShell* aShell,
// Get the parent of the previous sibling (which will be the proper
// next-in-flow for the child). We expect it to be this frame or one
// of our next-in-flow(s).
- nsCSSBlockFrame* flow = this;
+ nsBlockFrame* flow = this;
if (nsnull != prevSibling) {
prevSibling->GetGeometricParent((nsIFrame*&)flow);
}
@@ -3494,7 +3495,7 @@ nsCSSBlockFrame::ContentInserted(nsIPresShell* aShell,
flow->mLastContentOffset,
flow->mLastContentIsComplete);
}
- flow = (nsCSSBlockFrame*) flow->mNextInFlow;
+ flow = (nsBlockFrame*) flow->mNextInFlow;
while (nsnull != flow) {
flow->mFirstContentOffset++;
flow->mLastContentOffset++;
@@ -3504,14 +3505,14 @@ nsCSSBlockFrame::ContentInserted(nsIPresShell* aShell,
flow->mLastContentOffset,
flow->mLastContentIsComplete);
}
- flow = (nsCSSBlockFrame*) flow->mNextInFlow;
+ flow = (nsBlockFrame*) flow->mNextInFlow;
}
return NS_OK;
}
NS_IMETHODIMP
-nsCSSBlockFrame::ContentDeleted(nsIPresShell* aShell,
+nsBlockFrame::ContentDeleted(nsIPresShell* aShell,
nsIPresContext* aPresContext,
nsIContent* aContainer,
nsIContent* aChild,
@@ -3520,7 +3521,7 @@ nsCSSBlockFrame::ContentDeleted(nsIPresShell* aShell,
// Find the frame that precedes the frame to destroy and the frame
// to destroy (the first-in-flow if the frame is continued). We also
// find which of our next-in-flows contain the dead frame.
- nsCSSBlockFrame* flow;
+ nsBlockFrame* flow;
nsIFrame* deadFrame;
nsIFrame* prevSibling;
if (aIndexInParent > 0) {
@@ -3546,7 +3547,7 @@ nsCSSBlockFrame::ContentDeleted(nsIPresShell* aShell,
if (nsnull == deadFrame) {
// The deadFrame must be prevSibling's parent's next-in-flows
// first frame. Therefore it doesn't have a prevSibling.
- flow = (nsCSSBlockFrame*) flow->mNextInFlow;
+ flow = (nsBlockFrame*) flow->mNextInFlow;
if (nsnull != flow) {
deadFrame = flow->mLines->mFirstChild;
}
@@ -3595,7 +3596,7 @@ nsCSSBlockFrame::ContentDeleted(nsIPresShell* aShell,
NS_ASSERTION(flow == parent, "messed up delete code");
#endif
NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockFrame::ContentDeleted: deadFrame=%p",
+ ("nsBlockFrame::ContentDeleted: deadFrame=%p",
deadFrame));
// Remove deadFrame from the line
@@ -3667,7 +3668,7 @@ nsCSSBlockFrame::ContentDeleted(nsIPresShell* aShell,
// Advance to next flow block if the frame has more continuations
if (nsnull != deadFrame) {
- flow = (nsCSSBlockFrame*) flow->mNextInFlow;
+ flow = (nsBlockFrame*) flow->mNextInFlow;
NS_ASSERTION(nsnull != flow, "whoops, continuation without a parent");
line = flow->mLines;
prevSibling = nsnull;
@@ -3678,11 +3679,11 @@ nsCSSBlockFrame::ContentDeleted(nsIPresShell* aShell,
// next-in-flows the follow the last flow container that contained
// one of the deadFrame's. Therefore both content offsets need
// updating (because all the children are following the deletion).
- flow = (nsCSSBlockFrame*) flow->mNextInFlow;
+ flow = (nsBlockFrame*) flow->mNextInFlow;
while (nsnull != flow) {
flow->mFirstContentOffset--;
flow->mLastContentOffset--;
- flow = (nsCSSBlockFrame*) flow->mNextInFlow;
+ flow = (nsBlockFrame*) flow->mNextInFlow;
}
#ifdef NS_DEBUG
@@ -3698,7 +3699,7 @@ nsCSSBlockFrame::ContentDeleted(nsIPresShell* aShell,
NS_RELEASE(content);
frame->GetNextSibling(frame);
}
- flow = (nsCSSBlockFrame*) flow->mNextInFlow;
+ flow = (nsBlockFrame*) flow->mNextInFlow;
}
}
#endif
@@ -3707,12 +3708,12 @@ nsCSSBlockFrame::ContentDeleted(nsIPresShell* aShell,
}
PRBool
-nsCSSBlockFrame::DeleteNextInFlowsFor(nsIPresContext& aPresContext, nsIFrame* aChild)
+nsBlockFrame::DeleteNextInFlowsFor(nsIPresContext& aPresContext, nsIFrame* aChild)
{
NS_PRECONDITION(IsChild(aChild), "bad geometric parent");
nsIFrame* nextInFlow;
- nsCSSBlockFrame* parent;
+ nsBlockFrame* parent;
aChild->GetNextInFlow(nextInFlow);
NS_PRECONDITION(nsnull != nextInFlow, "null next-in-flow");
@@ -3742,7 +3743,7 @@ nsCSSBlockFrame::DeleteNextInFlowsFor(nsIPresContext& aPresContext, nsIFrame* aC
// the sibling list.
if (RemoveChild(parent->mLines, nextInFlow)) {
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("nsCSSBlockFrame::DeleteNextInFlowsFor: frame=%p (from mLines)",
+ ("nsBlockFrame::DeleteNextInFlowsFor: frame=%p (from mLines)",
nextInFlow));
goto done;
}
@@ -3752,7 +3753,7 @@ nsCSSBlockFrame::DeleteNextInFlowsFor(nsIPresContext& aPresContext, nsIFrame* aC
if (nsnull != mOverflowLines) {
if (RemoveChild(parent->mOverflowLines, nextInFlow)) {
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("nsCSSBlockFrame::DeleteNextInFlowsFor: frame=%p (from overflow)",
+ ("nsBlockFrame::DeleteNextInFlowsFor: frame=%p (from overflow)",
nextInFlow));
goto done;
}
@@ -3781,7 +3782,7 @@ nsCSSBlockFrame::DeleteNextInFlowsFor(nsIPresContext& aPresContext, nsIFrame* aC
}
PRBool
-nsCSSBlockFrame::RemoveChild(LineData* aLines, nsIFrame* aChild)
+nsBlockFrame::RemoveChild(LineData* aLines, nsIFrame* aChild)
{
LineData* line = aLines;
nsIFrame* prevChild = nsnull;
@@ -3793,7 +3794,7 @@ nsCSSBlockFrame::RemoveChild(LineData* aLines, nsIFrame* aChild)
child->GetNextSibling(nextChild);
if (child == aChild) {
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("nsCSSBlockFrame::RemoveChild: line=%p frame=%p",
+ ("nsBlockFrame::RemoveChild: line=%p frame=%p",
line, aChild));
// Continuations HAVE to be at the start of a line
NS_ASSERTION(child == line->mFirstChild, "bad continuation");
@@ -3819,11 +3820,11 @@ nsCSSBlockFrame::RemoveChild(LineData* aLines, nsIFrame* aChild)
#if 0
NS_IMETHODIMP
-nsCSSBlockFrame::DidReflow(nsIPresContext& aPresContext,
+nsBlockFrame::DidReflow(nsIPresContext& aPresContext,
nsDidReflowStatus aStatus)
{
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("enter nsCSSBlockFrame::DidReflow: status=%d",
+ ("enter nsBlockFrame::DidReflow: status=%d",
aStatus));
if (NS_FRAME_REFLOW_FINISHED == aStatus) {
@@ -3847,7 +3848,7 @@ nsCSSBlockFrame::DidReflow(nsIPresContext& aPresContext,
}
}
- NS_FRAME_TRACE_OUT("nsCSSBlockFrame::DidReflow");
+ NS_FRAME_TRACE_OUT("nsBlockFrame::DidReflow");
// Let nsFrame position and size our view (if we have one), and clear
// the NS_FRAME_IN_REFLOW bit
@@ -3859,13 +3860,13 @@ nsCSSBlockFrame::DidReflow(nsIPresContext& aPresContext,
// Floater support
void
-nsCSSBlockFrame::ReflowFloater(nsIPresContext* aPresContext,
- nsCSSBlockReflowState& aState,
+nsBlockFrame::ReflowFloater(nsIPresContext* aPresContext,
+ nsBlockReflowState& aState,
nsIFrame* aFloaterFrame)
{
// Prepare the reflow state for the floater frame. Note that initially
// it's maxSize will be 0,0 until we compute it (we need the reflowState
- // for nsCSSLayout::GetStyleSize so we have to do this first)
+ // for nsLayout::GetStyleSize so we have to do this first)
nsSize kidAvailSize(0, 0);
nsReflowState reflowState(aFloaterFrame, aState, kidAvailSize,
eReflowReason_Initial);
@@ -3918,7 +3919,7 @@ nsCSSBlockFrame::ReflowFloater(nsIPresContext* aPresContext,
}
PRBool
-nsCSSBlockFrame::AddFloater(nsIPresContext* aPresContext,
+nsBlockFrame::AddFloater(nsIPresContext* aPresContext,
const nsReflowState& aReflowState,
nsIFrame* aFloater,
nsPlaceholderFrame* aPlaceholder)
@@ -3935,7 +3936,7 @@ nsCSSBlockFrame::AddFloater(nsIPresContext* aPresContext,
// Never mind
return PR_FALSE;
}
- nsCSSBlockReflowState* state = (nsCSSBlockReflowState*) rs;
+ nsBlockReflowState* state = (nsBlockReflowState*) rs;
// Get the frame associated with the space manager, and get its
// nsIAnchoredItems interface
@@ -3980,7 +3981,7 @@ nsCSSBlockFrame::AddFloater(nsIPresContext* aPresContext,
// then the floater is place immediately, otherwise the floater
// placement is deferred until the line has been reflowed.
void
-nsCSSBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder)
+nsBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder)
{
// Update the current line's floater array
NS_ASSERTION(nsnull != mCurrentLine, "null ptr");
@@ -3993,7 +3994,7 @@ nsCSSBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder)
// away in mPendingFloaters and place it later.
if (IsLeftMostChild(aPlaceholder)) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockReflowState::AddFloater: IsLeftMostChild, placeHolder=%p",
+ ("nsBlockReflowState::AddFloater: IsLeftMostChild, placeHolder=%p",
aPlaceholder));
// Because we are in the middle of reflowing a placeholder frame
@@ -4021,7 +4022,7 @@ nsCSSBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder)
// This floater will be placed after the line is done (it is a
// below current line floater).
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockReflowState::AddFloater: pending, placeHolder=%p",
+ ("nsBlockReflowState::AddFloater: pending, placeHolder=%p",
aPlaceholder));
mPendingFloaters.AppendElement(aPlaceholder);
}
@@ -4031,7 +4032,7 @@ nsCSSBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder)
// coordinated; IsFirstChild in the inline code is doing much the same
// thing as below; firstness should be well known.
PRBool
-nsCSSBlockReflowState::IsLeftMostChild(nsIFrame* aFrame)
+nsBlockReflowState::IsLeftMostChild(nsIFrame* aFrame)
{
for (;;) {
nsIFrame* parent;
@@ -4078,7 +4079,7 @@ nsCSSBlockReflowState::IsLeftMostChild(nsIFrame* aFrame)
}
void
-nsCSSBlockReflowState::PlaceFloater(nsPlaceholderFrame* aPlaceholder)
+nsBlockReflowState::PlaceFloater(nsPlaceholderFrame* aPlaceholder)
{
nsISpaceManager* sm = mSpaceManager;
nsIFrame* floater = aPlaceholder->GetAnchoredItem();
@@ -4144,7 +4145,7 @@ nsCSSBlockReflowState::PlaceFloater(nsPlaceholderFrame* aPlaceholder)
floater->MoveTo(region.x + worldX + floaterMargin.left,
region.y + worldY + floaterMargin.top);
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockReflowState::PlaceFloater: right, placeHolder=%p xy=%d,%d worldxy=%d,%d",
+ ("nsBlockReflowState::PlaceFloater: right, placeHolder=%p xy=%d,%d worldxy=%d,%d",
aPlaceholder, region.x + worldX + floaterMargin.left,
region.y + worldY + floaterMargin.top,
worldX, worldY));
@@ -4153,7 +4154,7 @@ nsCSSBlockReflowState::PlaceFloater(nsPlaceholderFrame* aPlaceholder)
floater->MoveTo(region.x + worldX + floaterMargin.left + mBulletPadding,
region.y + worldY + floaterMargin.top);
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockReflowState::PlaceFloater: left, placeHolder=%p xy=%d,%d worldxy=%d,%d",
+ ("nsBlockReflowState::PlaceFloater: left, placeHolder=%p xy=%d,%d worldxy=%d,%d",
aPlaceholder, region.x + worldX + floaterMargin.left + mBulletPadding,
region.y + worldY + floaterMargin.top,
worldX, worldY));
@@ -4161,7 +4162,7 @@ nsCSSBlockReflowState::PlaceFloater(nsPlaceholderFrame* aPlaceholder)
}
void
-nsCSSBlockReflowState::PlaceFloaters(nsVoidArray* aFloaters)
+nsBlockReflowState::PlaceFloaters(nsVoidArray* aFloaters)
{
NS_PRECONDITION(aFloaters->Count() > 0, "no floaters");
@@ -4184,7 +4185,7 @@ nsCSSBlockReflowState::PlaceFloaters(nsVoidArray* aFloaters)
}
void
-nsCSSBlockReflowState::ClearFloaters(PRUint8 aBreakType)
+nsBlockReflowState::ClearFloaters(PRUint8 aBreakType)
{
for (;;) {
PRBool haveFloater = PR_FALSE;
@@ -4193,7 +4194,7 @@ nsCSSBlockReflowState::ClearFloaters(PRUint8 aBreakType)
// never translate by Y before getting a band, we can use absolute
// comparisons against mY.
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockReflowState::ClearFloaters: mY=%d trapCount=%d",
+ ("nsBlockReflowState::ClearFloaters: mY=%d trapCount=%d",
mY, mCurrentBand.count));
nscoord clearYMost = mY;
nsRect tmp;
@@ -4202,7 +4203,7 @@ nsCSSBlockReflowState::ClearFloaters(PRUint8 aBreakType)
const nsStyleDisplay* display;
nsBandTrapezoid* trapezoid = &mCurrentBand.data[i];
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockReflowState::ClearFloaters: trap=%d state=%d",
+ ("nsBlockReflowState::ClearFloaters: trap=%d state=%d",
i, trapezoid->state));
if (nsBandTrapezoid::Available != trapezoid->state) {
haveFloater = PR_TRUE;
@@ -4214,7 +4215,7 @@ nsCSSBlockReflowState::ClearFloaters(PRUint8 aBreakType)
frame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&)display);
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockReflowState::ClearFloaters: frame[%d]=%p floats=%d",
+ ("nsBlockReflowState::ClearFloaters: frame[%d]=%p floats=%d",
fn, frame, display->mFloats));
switch (display->mFloats) {
case NS_STYLE_FLOAT_LEFT:
@@ -4225,7 +4226,7 @@ nsCSSBlockReflowState::ClearFloaters(PRUint8 aBreakType)
if (ym > clearYMost) {
clearYMost = ym;
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockReflowState::ClearFloaters: left clearYMost=%d",
+ ("nsBlockReflowState::ClearFloaters: left clearYMost=%d",
clearYMost));
}
}
@@ -4238,7 +4239,7 @@ nsCSSBlockReflowState::ClearFloaters(PRUint8 aBreakType)
if (ym > clearYMost) {
clearYMost = ym;
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockReflowState::ClearFloaters: right clearYMost=%d",
+ ("nsBlockReflowState::ClearFloaters: right clearYMost=%d",
clearYMost));
}
}
@@ -4250,7 +4251,7 @@ nsCSSBlockReflowState::ClearFloaters(PRUint8 aBreakType)
trapezoid->frame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&)display);
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockReflowState::ClearFloaters: frame=%p floats=%d",
+ ("nsBlockReflowState::ClearFloaters: frame=%p floats=%d",
trapezoid->frame, display->mFloats));
switch (display->mFloats) {
case NS_STYLE_FLOAT_LEFT:
@@ -4259,12 +4260,12 @@ nsCSSBlockReflowState::ClearFloaters(PRUint8 aBreakType)
trapezoid->GetRect(tmp);
nscoord ym = tmp.YMost();
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockReflowState::ClearFloaters: left? ym=%d clearYMost=%d",
+ ("nsBlockReflowState::ClearFloaters: left? ym=%d clearYMost=%d",
ym, clearYMost));
if (ym > clearYMost) {
clearYMost = ym;
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockReflowState::ClearFloaters: left clearYMost=%d",
+ ("nsBlockReflowState::ClearFloaters: left clearYMost=%d",
clearYMost));
}
}
@@ -4277,7 +4278,7 @@ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
if (ym > clearYMost) {
clearYMost = ym;
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockReflowState::ClearFloaters: right clearYMost=%d",
+ ("nsBlockReflowState::ClearFloaters: right clearYMost=%d",
clearYMost));
}
}
@@ -4296,7 +4297,7 @@ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
}
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsCSSBlockReflowState::ClearFloaters: mY=%d clearYMost=%d",
+ ("nsBlockReflowState::ClearFloaters: mY=%d clearYMost=%d",
mY, clearYMost));
mY = clearYMost + 1;
@@ -4310,7 +4311,7 @@ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
// Painting, event handling
PRIntn
-nsCSSBlockFrame::GetSkipSides() const
+nsBlockFrame::GetSkipSides() const
{
PRIntn skip = 0;
if (nsnull != mPrevInFlow) {
@@ -4323,7 +4324,7 @@ nsCSSBlockFrame::GetSkipSides() const
}
NS_IMETHODIMP
-nsCSSBlockFrame::Paint(nsIPresContext& aPresContext,
+nsBlockFrame::Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect)
{
@@ -4364,7 +4365,7 @@ nsCSSBlockFrame::Paint(nsIPresContext& aPresContext,
// aDirtyRect is in our coordinate system
// child rect's are also in our coordinate system
void
-nsCSSBlockFrame::PaintChildren(nsIPresContext& aPresContext,
+nsBlockFrame::PaintChildren(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect)
{
@@ -4490,7 +4491,7 @@ InSiblingList(LineData* aLine, nsIFrame* aFrame)
}
PRBool
-nsCSSBlockFrame::IsChild(nsIFrame* aFrame)
+nsBlockFrame::IsChild(nsIFrame* aFrame)
{
nsIFrame* parent;
aFrame->GetGeometricParent(parent);
@@ -4515,7 +4516,7 @@ nsCSSBlockFrame::IsChild(nsIFrame* aFrame)
NS_ASSERTION(_expr, _msg)
NS_IMETHODIMP
-nsCSSBlockFrame::VerifyTree() const
+nsBlockFrame::VerifyTree() const
{
#ifdef NS_DEBUG
NS_ASSERTION(0 == (mState & NS_FRAME_IN_REFLOW), "frame is in reflow");
@@ -4578,7 +4579,7 @@ nsCSSBlockFrame::VerifyTree() const
}
#ifdef DO_SELECTION
-nsIFrame * nsCSSBlockFrame::FindHitFrame(nsCSSBlockFrame * aBlockFrame,
+nsIFrame * nsBlockFrame::FindHitFrame(nsBlockFrame * aBlockFrame,
const nscoord aX,
const nscoord aY,
const nsPoint & aPoint)
@@ -4596,7 +4597,7 @@ nsIFrame * nsCSSBlockFrame::FindHitFrame(nsCSSBlockFrame * aBlockFrame,
nsRect bounds;
frame->GetRect(bounds);
if (bounds.Contains(mousePoint)) {
- nsCSSBlockFrame * blockFrame;
+ nsBlockFrame * blockFrame;
if (NS_OK == frame->QueryInterface(kBlockFrameCID, (void**)&blockFrame)) {
frame = FindHitFrame(blockFrame, bounds.x, bounds.y, aPoint);
//NS_RELEASE(blockFrame);
@@ -4613,7 +4614,7 @@ nsIFrame * nsCSSBlockFrame::FindHitFrame(nsCSSBlockFrame * aBlockFrame,
return aBlockFrame;
}
-NS_METHOD nsCSSBlockFrame::HandleEvent(nsIPresContext& aPresContext,
+NS_METHOD nsBlockFrame::HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
@@ -4677,7 +4678,7 @@ NS_METHOD nsCSSBlockFrame::HandleEvent(nsIPresContext& aPresContext,
nsIFrame * gNearByFrame = nsnull;
-NS_METHOD nsCSSBlockFrame::HandleDrag(nsIPresContext& aPresContext,
+NS_METHOD nsBlockFrame::HandleDrag(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
diff --git a/layout/css/layout/src/nsCSSBlockFrame.h b/layout/generic/nsBlockFrame.h
similarity index 76%
rename from layout/css/layout/src/nsCSSBlockFrame.h
rename to layout/generic/nsBlockFrame.h
index 4e47a95f911f..b173c3c9dc47 100644
--- a/layout/css/layout/src/nsCSSBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -16,17 +16,17 @@
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
-#ifndef nsCSSBlockFrame_h___
-#define nsCSSBlockFrame_h___
+#ifndef nsBlockFrame_h___
+#define nsBlockFrame_h___
-#include "nsCSSContainerFrame.h"
-#include "nsCSSLineLayout.h"
-#include "nsCSSInlineLayout.h"
+#include "nsHTMLContainerFrame.h"
+#include "nsLineLayout.h"
+#include "nsInlineLayout.h"
#include "nsVoidArray.h"
#include "nsISpaceManager.h"
-class nsCSSBlockFrame;
-struct nsCSSInlineLayout;
+class nsBlockFrame;
+struct nsInlineLayout;
class nsPlaceholderFrame;
struct LineData;
@@ -36,16 +36,16 @@ struct LineData;
// XXX hide this as soon as list bullet code is cleaned up
-struct nsCSSBlockReflowState : public nsReflowState {
- nsCSSBlockReflowState(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsCSSBlockFrame* aBlock,
- nsIStyleContext* aBlockSC,
- const nsReflowState& aReflowState,
- nsReflowMetrics& aMetrics,
- PRBool aComputeMaxElementSize);
+struct nsBlockReflowState : public nsReflowState {
+ nsBlockReflowState(nsIPresContext* aPresContext,
+ nsISpaceManager* aSpaceManager,
+ nsBlockFrame* aBlock,
+ nsIStyleContext* aBlockSC,
+ const nsReflowState& aReflowState,
+ nsReflowMetrics& aMetrics,
+ PRBool aComputeMaxElementSize);
- ~nsCSSBlockReflowState();
+ ~nsBlockReflowState();
/**
* Update the mCurrentBand data based on the current mY position.
@@ -64,9 +64,9 @@ struct nsCSSBlockReflowState : public nsReflowState {
nsIPresContext* mPresContext;
nsISpaceManager* mSpaceManager;
- nsCSSBlockFrame* mBlock;
+ nsBlockFrame* mBlock;
PRBool mBlockIsPseudo;
- nsCSSBlockFrame* mNextInFlow;
+ nsBlockFrame* mNextInFlow;
PRUint8 mTextAlign;
PRUint8 mDirection;
@@ -96,9 +96,9 @@ struct nsCSSBlockReflowState : public nsReflowState {
nsSize mMaxElementSize;
- nsCSSLineLayout mLineLayout;
+ nsLineLayout mLineLayout;
- nsCSSInlineLayout mInlineLayout;
+ nsInlineLayout mInlineLayout;
PRBool mInlineLayoutPrepared;
nsIFrame* mPrevChild;
@@ -140,13 +140,13 @@ struct nsCSSBlockReflowState : public nsReflowState {
};
inline void
-nsCSSLineLayout::AddFloater(nsPlaceholderFrame* aFrame)
+nsLineLayout::AddFloater(nsPlaceholderFrame* aFrame)
{
mBlockReflowState->AddFloater(aFrame);
}
-extern nsresult NS_NewCSSBlockFrame(nsIFrame** aInstancePtrResult,
- nsIContent* aContent,
- nsIFrame* aParent);
+extern nsresult NS_NewBlockFrame(nsIFrame** aInstancePtrResult,
+ nsIContent* aContent,
+ nsIFrame* aParent);
#endif /* nsCSSBlockFrame_h___ */
diff --git a/layout/generic/nsBlockReflowState.cpp b/layout/generic/nsBlockReflowState.cpp
new file mode 100644
index 000000000000..6dd718cd7d70
--- /dev/null
+++ b/layout/generic/nsBlockReflowState.cpp
@@ -0,0 +1,4735 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications
+ * Corporation. Portions created by Netscape are Copyright (C) 1998
+ * Netscape Communications Corporation. All Rights Reserved.
+ */
+#include "nsBlockFrame.h"
+#include "nsLineLayout.h"
+#include "nsInlineLayout.h"
+#include "nsCSSLayout.h"
+#include "nsPlaceholderFrame.h"
+#include "nsStyleConsts.h"
+#include "nsHTMLIIDs.h"
+#include "nsCSSRendering.h"
+
+#include "nsIAnchoredItems.h"
+#include "nsIFloaterContainer.h"
+#include "nsIPresContext.h"
+#include "nsIPresShell.h"
+#include "nsIReflowCommand.h"
+#include "nsIRunaround.h"
+#include "nsIStyleContext.h"
+#include "nsIView.h"
+#include "nsIFontMetrics.h"
+
+#include "nsHTMLBase.h"// XXX rename to nsBase?
+#include "nsHTMLParts.h"// XXX html reflow command???
+#include "nsHTMLAtoms.h"// XXX list ordinal hack
+#include "nsHTMLValue.h"// XXX list ordinal hack
+#include "nsIHTMLContent.h"// XXX list ordinal hack
+
+//#include "js/jsapi.h"
+//#include "nsDOMEvent.h"
+#define DOM_EVENT_INIT 0x0001
+
+#include "prprf.h"
+
+// XXX mLastContentOffset, mFirstContentOffset, mLastContentIsComplete
+// XXX pagination
+// XXX prev-in-flow continuations
+
+// XXX IsFirstChild
+// XXX max-element-size
+// XXX no-wrap
+// XXX margin collapsing and empty InlineFrameData's
+// XXX floaters in inlines
+// XXX Check handling of mUnconstrainedWidth
+
+// XXX MULTICOL support; note that multicol will end up using the
+// equivalent of pagination! Therefore we should probably make sure
+// the pagination code isn't completely stupid.
+
+// XXX better lists (bullet numbering)
+
+// XXX page-breaks
+
+// XXX out of memory checks are missing
+
+// XXX push code can record the y coordinate where the push occurred
+// and the width that the data was flowed against and also indicate
+// which frames were reflowed and which weren't. Then drain code can just
+// place the pulled up data directly when there are no floaters to
+// worry about. something like that...
+
+// XXX Tuneup: if mNoWrap is true and we are given a ResizeReflow we
+// can just return because there's nothing to do!; this is true in
+// nsInlineFrame too!
+// Except that noWrap is ignored if the containers width is too small
+// (like a table cell with a fixed width.)
+
+//----------------------------------------------------------------------
+// XXX It's really important that blocks strip out extra whitespace;
+// otherwise we will see ALOT of this, which will waste memory big time:
+//
+//
+//
+//
+//
+// ...
+//----------------------------------------------------------------------
+
+// XXX I don't want mFirstChild, mChildCount, mOverflowList,
+// mLastContentIsComplete in our base class!!!
+
+struct LineData;
+
+// XXX Death to pseudo-frames!!!!!
+#define DTPF 1
+
+// XXX temporary until PropagateContentOffsets can be written genericly
+#define nsBlockFrameSuper nsHTMLContainerFrame
+
+class nsBlockFrame : public nsBlockFrameSuper,
+ public nsIRunaround,
+ public nsIFloaterContainer
+{
+public:
+ nsBlockFrame(nsIContent* aContent, nsIFrame* aParent);
+
+ // nsISupports
+ NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
+
+ // nsIFrame
+ NS_IMETHOD Init(nsIPresContext& aPresContext, nsIFrame* aChildList);
+ NS_IMETHOD DeleteFrame(nsIPresContext& aPresContext);
+ NS_IMETHOD ChildCount(PRInt32& aChildCount) const;
+ NS_IMETHOD ChildAt(PRInt32 aIndex, nsIFrame*& aFrame) const;
+ NS_IMETHOD IndexOf(const nsIFrame* aChild, PRInt32& aIndex) const;
+ NS_IMETHOD FirstChild(nsIFrame*& aFirstChild) const;
+ NS_IMETHOD NextChild(const nsIFrame* aChild, nsIFrame*& aNextChild) const;
+ NS_IMETHOD PrevChild(const nsIFrame* aChild, nsIFrame*& aPrevChild) const;
+ NS_IMETHOD LastChild(nsIFrame*& aLastChild) const;
+ NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const;
+ NS_IMETHOD CreateContinuingFrame(nsIPresContext& aPresContext,
+ nsIFrame* aParent,
+ nsIStyleContext* aStyleContext,
+ nsIFrame*& aContinuingFrame);
+ NS_IMETHOD Paint(nsIPresContext& aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect);
+ // XXX CONSTRUCTION
+#if 0
+ NS_IMETHOD ContentAppended(nsIPresShell* aShell,
+ nsIPresContext* aPresContext,
+ nsIContent* aContainer);
+#endif
+ NS_IMETHOD ContentInserted(nsIPresShell* aShell,
+ nsIPresContext* aPresContext,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ PRInt32 aIndexInParent);
+ NS_IMETHOD ContentDeleted(nsIPresShell* aShell,
+ nsIPresContext* aPresContext,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ PRInt32 aIndexInParent);
+#if XXX
+ NS_IMETHOD DidReflow(nsIPresContext& aPresContext,
+ nsDidReflowStatus aStatus);
+#endif
+ NS_IMETHOD List(FILE* out, PRInt32 aIndent, nsIListFilter *aFilter = nsnull) const;
+ NS_IMETHOD ListTag(FILE* out) const;
+ NS_IMETHOD VerifyTree() const;
+ // XXX implement regular reflow method too!
+
+ // nsIRunaround
+ NS_IMETHOD ReflowAround(nsIPresContext& aPresContext,
+ nsISpaceManager* aSpaceManager,
+ nsReflowMetrics& aDesiredSize,
+ const nsReflowState& aReflowState,
+ nsRect& aDesiredRect,
+ nsReflowStatus& aStatus);
+
+ // nsIFloaterContainer
+ virtual PRBool AddFloater(nsIPresContext* aPresContext,
+ const nsReflowState& aPlaceholderReflowState,
+ nsIFrame* aFloater,
+ nsPlaceholderFrame* aPlaceholder);
+
+#ifdef DO_SELECTION
+ NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus);
+
+ NS_IMETHOD HandleDrag(nsIPresContext& aPresContext,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus);
+
+ nsIFrame * FindHitFrame(nsBlockFrame * aBlockFrame,
+ const nscoord aX, const nscoord aY,
+ const nsPoint & aPoint);
+
+#endif
+protected:
+ ~nsBlockFrame();
+
+
+#if 0
+ PRInt32 GetFirstContentOffset() const;
+
+ PRInt32 GetLastContentOffset() const;
+
+ PRBool GetLastContentIsComplete() const;
+#endif
+ virtual PRBool DeleteNextInFlowsFor(nsIPresContext& aPresContext, nsIFrame* aNextInFlow);
+
+ PRBool DrainOverflowLines();
+
+ PRBool RemoveChild(LineData* aLines, nsIFrame* aChild);
+
+ nsresult ProcessInitialReflow(nsIPresContext* aPresContext);
+
+ //XXX void PropagateContentOffsets();
+
+ PRIntn GetSkipSides() const;
+
+ PRBool IsPseudoFrame() const;
+
+ nsresult InitialReflow(nsBlockReflowState& aState);
+
+ nsresult FrameAppendedReflow(nsBlockReflowState& aState);
+
+ nsresult InsertNewFrame(nsBlockFrame* aParentFrame,
+ nsIFrame* aNewFrame,
+ nsIFrame* aPrevSibling);
+ nsresult FrameInsertedReflow(nsBlockReflowState& aState);
+
+ nsresult FrameDeletedReflow(nsBlockReflowState& aState);
+
+ nsresult CreateNewFrames(nsIPresContext* aPresContext);
+
+ nsresult FindTextRuns(nsBlockReflowState& aState);
+
+ nsresult ChildIncrementalReflow(nsBlockReflowState& aState);
+
+ nsresult ResizeReflow(nsBlockReflowState& aState);
+
+ void ComputeFinalSize(nsBlockReflowState& aState,
+ nsReflowMetrics& aMetrics,
+ nsRect& aDesiredRect);
+
+ nsresult ReflowLinesAt(nsBlockReflowState& aState, LineData* aLine);
+
+ PRBool ReflowLine(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsInlineReflowStatus& aReflowResult);
+
+ PRBool PlaceLine(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsInlineReflowStatus aReflowStatus);
+
+ void FindFloaters(LineData* aLine);
+
+ PRBool ReflowInlineFrame(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsIFrame* aFrame,
+ nsInlineReflowStatus& aResult);
+
+ nsresult SplitLine(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsIFrame* aFrame,
+ PRBool aLineWasComplete);
+
+ PRBool ReflowBlockFrame(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsIFrame* aFrame,
+ nsInlineReflowStatus& aResult);
+
+ PRBool PullFrame(nsBlockReflowState& aState,
+ LineData* aToLine,
+ LineData** aFromList,
+ PRBool aUpdateGeometricParent,
+ nsInlineReflowStatus& aResult);
+
+ void PushLines(nsBlockReflowState& aState);
+
+ void ReflowFloater(nsIPresContext* aPresContext,
+ nsBlockReflowState& aState,
+ nsIFrame* aFloaterFrame);
+
+ void PaintChildren(nsIPresContext& aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect);
+
+ nsresult AppendNewFrames(nsIPresContext* aPresContext, nsIFrame*);
+
+#ifdef NS_DEBUG
+ PRBool IsChild(nsIFrame* aFrame);
+#endif
+
+ LineData* mLines;
+
+ LineData* mOverflowLines;
+
+ // placeholder frames for floaters to display at the top line
+// nsVoidArray* mRunInFloaters;
+
+ // Text run information
+ nsTextRun* mTextRuns;
+
+ // XXX TEMP
+ PRBool mHasBeenInitialized;
+
+ friend struct nsBlockReflowState;
+};
+
+//----------------------------------------------------------------------
+
+#define LINE_IS_DIRTY 0x1
+#define LINE_IS_BLOCK 0x2
+#define LINE_LAST_CONTENT_IS_COMPLETE 0x4
+#define LINE_NEED_DID_REFLOW 0x8
+
+struct LineData {
+ LineData(nsIFrame* aFrame, PRInt32 aCount, PRUint16 flags) {
+ mFirstChild = aFrame;
+ mChildCount = aCount;
+ mState = LINE_IS_DIRTY | LINE_NEED_DID_REFLOW | flags;
+ mFloaters = nsnull;
+ mNext = nsnull;
+ mInnerBottomMargin = 0;
+ mOuterBottomMargin = 0;
+ mBounds.SetRect(0,0,0,0);
+ }
+
+ ~LineData();
+
+ void List(FILE* out, PRInt32 aIndent, nsIListFilter *aFilter = nsnull,
+ PRBool aOutputMe=PR_TRUE) const;
+
+ nsIFrame* LastChild() const;
+
+ PRBool IsLastChild(nsIFrame* aFrame) const;
+
+ void SetLastContentIsComplete() {
+ mState |= LINE_LAST_CONTENT_IS_COMPLETE;
+ }
+
+ void ClearLastContentIsComplete() {
+ mState &= ~LINE_LAST_CONTENT_IS_COMPLETE;
+ }
+
+ void SetLastContentIsComplete(PRBool aValue) {
+ if (aValue) {
+ SetLastContentIsComplete();
+ }
+ else {
+ ClearLastContentIsComplete();
+ }
+ }
+
+ PRBool GetLastContentIsComplete() {
+ return 0 != (LINE_LAST_CONTENT_IS_COMPLETE & mState);
+ }
+
+ PRBool IsBlock() const {
+ return 0 != (LINE_IS_BLOCK & mState);
+ }
+
+ void SetIsBlock() {
+ mState |= LINE_IS_BLOCK;
+ }
+
+ void ClearIsBlock() {
+ mState &= ~LINE_IS_BLOCK;
+ }
+
+ void SetIsBlock(PRBool aValue) {
+ if (aValue) {
+ SetIsBlock();
+ }
+ else {
+ ClearIsBlock();
+ }
+ }
+
+ void MarkDirty() {
+ mState |= LINE_IS_DIRTY;
+ }
+
+ void ClearDirty() {
+ mState &= ~LINE_IS_DIRTY;
+ }
+
+ void SetNeedDidReflow() {
+ mState |= LINE_NEED_DID_REFLOW;
+ }
+
+ void ClearNeedDidReflow() {
+ mState &= ~LINE_NEED_DID_REFLOW;
+ }
+
+ PRBool NeedsDidReflow() {
+ return 0 != (LINE_NEED_DID_REFLOW & mState);
+ }
+
+ PRBool IsDirty() const {
+ return 0 != (LINE_IS_DIRTY & mState);
+ }
+
+ PRUint16 GetState() const { return mState; }
+
+ char* StateToString(char* aBuf, PRInt32 aBufSize) const;
+
+ PRBool Contains(nsIFrame* aFrame) const;
+
+#ifdef NS_DEBUG
+ void Verify();
+#endif
+
+ nsIFrame* mFirstChild;
+ PRUint16 mChildCount;
+ PRUint16 mState;
+ nsRect mBounds;
+ nscoord mInnerBottomMargin;
+ nscoord mOuterBottomMargin;
+ nsVoidArray* mFloaters;
+ LineData* mNext;
+};
+
+LineData::~LineData()
+{
+ if (nsnull != mFloaters) {
+ delete mFloaters;
+ }
+}
+
+static void
+ListFloaters(FILE* out, nsVoidArray* aFloaters)
+{
+ PRInt32 i, n = aFloaters->Count();
+ for (i = 0; i < n; i++) {
+ nsIFrame* frame = (nsIFrame*) aFloaters->ElementAt(i);
+ frame->ListTag(out);
+ if (i < n - 1) fputs(" ", out);
+ }
+}
+
+static void
+ListTextRuns(FILE* out, PRInt32 aIndent, nsTextRun* aRuns)
+{
+ while (nsnull != aRuns) {
+ aRuns->List(out, aIndent);
+ aRuns = aRuns->mNext;
+ }
+}
+
+char*
+LineData::StateToString(char* aBuf, PRInt32 aBufSize) const
+{
+ PR_snprintf(aBuf, aBufSize, "%s,%s,%scomplete",
+ (mState & LINE_IS_DIRTY) ? "dirty" : "clean",
+ (mState & LINE_IS_BLOCK) ? "block" : "inline",
+ (mState & LINE_LAST_CONTENT_IS_COMPLETE) ? "" : "!");
+ return aBuf;
+}
+
+void
+LineData::List(FILE* out, PRInt32 aIndent, nsIListFilter *aFilter,
+ PRBool aOutputMe) const
+{
+ // if a filter is present, only output this frame if the filter says we should
+ PRInt32 i;
+
+ if (PR_TRUE==aOutputMe)
+ {
+ for (i = aIndent; --i >= 0; ) fputs(" ", out);
+ char cbuf[100];
+ fprintf(out, "line %p: count=%d state=%s {%d,%d,%d,%d} ibm=%d obm=%d <\n",
+ this, mChildCount, StateToString(cbuf, sizeof(cbuf)),
+ mBounds.x, mBounds.y, mBounds.width, mBounds.height,
+ mInnerBottomMargin, mOuterBottomMargin);
+ }
+
+ nsIFrame* frame = mFirstChild;
+ PRInt32 n = mChildCount;
+ while (--n >= 0) {
+ frame->List(out, aIndent + 1, aFilter);
+ frame->GetNextSibling(frame);
+ }
+
+ if (PR_TRUE==aOutputMe)
+ {
+ for (i = aIndent; --i >= 0; ) fputs(" ", out);
+
+ if (nsnull != mFloaters) {
+ fputs("> bcl-floaters=<", out);
+ ListFloaters(out, mFloaters);
+ }
+ fputs(">\n", out);
+ }
+}
+
+nsIFrame*
+LineData::LastChild() const
+{
+ nsIFrame* frame = mFirstChild;
+ PRInt32 n = mChildCount - 1;
+ while (--n >= 0) {
+ frame->GetNextSibling(frame);
+ }
+ return frame;
+}
+
+PRBool
+LineData::IsLastChild(nsIFrame* aFrame) const
+{
+ nsIFrame* lastFrame = LastChild();
+ return aFrame == lastFrame;
+}
+
+PRBool
+LineData::Contains(nsIFrame* aFrame) const
+{
+ PRInt32 n = mChildCount;
+ nsIFrame* frame = mFirstChild;
+ while (--n >= 0) {
+ if (frame == aFrame) {
+ return PR_TRUE;
+ }
+ frame->GetNextSibling(frame);
+ }
+ return PR_FALSE;
+}
+
+static PRInt32
+LengthOf(nsIFrame* aFrame)
+{
+ PRInt32 result = 0;
+ while (nsnull != aFrame) {
+ result++;
+ aFrame->GetNextSibling(aFrame);
+ }
+ return result;
+}
+
+#ifdef NS_DEBUG
+void
+LineData::Verify()
+{
+ nsIFrame* lastFrame = LastChild();
+ if (nsnull != lastFrame) {
+ nsIFrame* nextInFlow;
+ lastFrame->GetNextInFlow(nextInFlow);
+ if (GetLastContentIsComplete()) {
+ NS_ASSERTION(nsnull == nextInFlow, "bad mState");
+ }
+ if (nsnull != mNext) {
+ nsIFrame* nextSibling;
+ lastFrame->GetNextSibling(nextSibling);
+ NS_ASSERTION(mNext->mFirstChild == nextSibling, "bad line list");
+ }
+ }
+ PRInt32 len = LengthOf(mFirstChild);
+ NS_ASSERTION(len >= mChildCount, "bad mChildCount");
+}
+
+static void
+VerifyLines(LineData* aLine)
+{
+ while (nsnull != aLine) {
+ aLine->Verify();
+ aLine = aLine->mNext;
+ }
+}
+
+static void
+VerifyChildCount(LineData* aLines, PRBool aEmptyOK = PR_FALSE)
+{
+ if (nsnull != aLines) {
+ PRInt32 childCount = LengthOf(aLines->mFirstChild);
+ PRInt32 sum = 0;
+ LineData* line = aLines;
+ while (nsnull != line) {
+ if (!aEmptyOK) {
+ NS_ASSERTION(0 != line->mChildCount, "empty line left in line list");
+ }
+ sum += line->mChildCount;
+ line = line->mNext;
+ }
+ if (sum != childCount) {
+ printf("Bad sibling list/line mChildCount's\n");
+ LineData* line = aLines;
+ while (nsnull != line) {
+ line->List(stdout, 1);
+ if (nsnull != line->mNext) {
+ nsIFrame* lastFrame = line->LastChild();
+ if (nsnull != lastFrame) {
+ nsIFrame* nextSibling;
+ lastFrame->GetNextSibling(nextSibling);
+ if (line->mNext->mFirstChild != nextSibling) {
+ printf(" [list broken: nextSibling=%p mNext->mFirstChild=%p]\n",
+ nextSibling, line->mNext->mFirstChild);
+ }
+ }
+ }
+ line = line->mNext;
+ }
+ NS_ASSERTION(sum == childCount, "bad sibling list/line mChildCount's");
+ }
+ }
+}
+#endif
+
+static void
+DeleteLineList(nsIPresContext& aPresContext, LineData* aLine)
+{
+ if (nsnull != aLine) {
+ // Delete our child frames before doing anything else. In particular
+ // we do all of this before our base class releases it's hold on the
+ // view.
+ for (nsIFrame* child = aLine->mFirstChild; child; ) {
+ nsIFrame* nextChild;
+ child->GetNextSibling(nextChild);
+ child->DeleteFrame(aPresContext);
+ child = nextChild;
+ }
+
+ while (nsnull != aLine) {
+ LineData* next = aLine->mNext;
+ delete aLine;
+ aLine = next;
+ }
+ }
+}
+
+static LineData*
+LastLine(LineData* aLine)
+{
+ if (nsnull != aLine) {
+ while (nsnull != aLine->mNext) {
+ aLine = aLine->mNext;
+ }
+ }
+ return aLine;
+}
+
+static LineData*
+FindLineContaining(LineData* aLine, nsIFrame* aFrame)
+{
+ while (nsnull != aLine) {
+ if (aLine->Contains(aFrame)) {
+ return aLine;
+ }
+ aLine = aLine->mNext;
+ }
+ return nsnull;
+}
+
+//----------------------------------------------------------------------
+
+void nsBlockReflowState::BlockBandData::ComputeAvailSpaceRect()
+{
+ nsBandTrapezoid* trapezoid = data;
+
+ if (count > 1) {
+ // If there's more than one trapezoid that means there are floaters
+ PRInt32 i;
+
+ // Stop when we get to space occupied by a right floater, or when we've
+ // looked at every trapezoid and none are right floaters
+ for (i = 0; i < count; i++) {
+ nsBandTrapezoid* trapezoid = &data[i];
+ if (trapezoid->state != nsBandTrapezoid::Available) {
+ const nsStyleDisplay* display;
+ if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
+ PRInt32 j, numFrames = trapezoid->frames->Count();
+ NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
+ for (j = 0; j < numFrames; j++) {
+ nsIFrame* f = (nsIFrame*)trapezoid->frames->ElementAt(j);
+ f->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)display);
+ if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
+ goto foundRightFloater;
+ }
+ }
+ } else {
+ trapezoid->frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)display);
+ if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
+ break;
+ }
+ }
+ }
+ }
+ foundRightFloater:
+
+ if (i > 0) {
+ trapezoid = &data[i - 1];
+ }
+ }
+
+ if (nsBandTrapezoid::Available == trapezoid->state) {
+ // The trapezoid is available
+ trapezoid->GetRect(availSpace);
+ } else {
+ const nsStyleDisplay* display;
+
+ // The trapezoid is occupied. That means there's no available space
+ trapezoid->GetRect(availSpace);
+
+ // XXX Better handle the case of multiple frames
+ if (nsBandTrapezoid::Occupied == trapezoid->state) {
+ trapezoid->frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)display);
+ if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
+ availSpace.x = availSpace.XMost();
+ }
+ }
+ availSpace.width = 0;
+ }
+}
+
+//----------------------------------------------------------------------
+
+static nscoord
+GetParentLeftPadding(const nsReflowState* aReflowState)
+{
+ nscoord leftPadding = 0;
+ while (nsnull != aReflowState) {
+ nsIFrame* frame = aReflowState->frame;
+ const nsStyleDisplay* styleDisplay;
+ frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&) styleDisplay);
+ if (NS_STYLE_DISPLAY_BLOCK == styleDisplay->mDisplay) {
+ const nsStyleSpacing* styleSpacing;
+ frame->GetStyleData(eStyleStruct_Spacing,
+ (const nsStyleStruct*&) styleSpacing);
+ nsMargin padding;
+ styleSpacing->CalcPaddingFor(frame, padding);
+ leftPadding = padding.left;
+ break;
+ }
+ aReflowState = aReflowState->parentReflowState;
+ }
+ return leftPadding;
+}
+
+nsBlockReflowState::nsBlockReflowState(nsIPresContext* aPresContext,
+ nsISpaceManager* aSpaceManager,
+ nsBlockFrame* aBlock,
+ nsIStyleContext* aBlockSC,
+ const nsReflowState& aReflowState,
+ nsReflowMetrics& aMetrics,
+ PRBool aComputeMaxElementSize)
+ : nsReflowState(aReflowState),
+ mLineLayout(aPresContext, aSpaceManager),
+ mInlineLayout(mLineLayout, aBlock, aBlockSC)
+{
+ mLineLayout.Init(this);
+ mInlineLayout.Init(this);
+
+ mSpaceManager = aSpaceManager;
+
+ // Save away the outer coordinate system origin for later
+ mSpaceManager->GetTranslation(mSpaceManagerX, mSpaceManagerY);
+
+ mPresContext = aPresContext;
+ mBlock = aBlock;
+ mBlockIsPseudo = aBlock->IsPseudoFrame();
+ aBlock->GetNextInFlow((nsIFrame*&)mNextInFlow);
+ mPrevBottomMargin = 0;
+ mOuterTopMargin = aMetrics.posTopMargin;
+ mKidXMost = 0;
+
+ mX = 0;
+ mY = 0;
+ mUnconstrainedWidth = maxSize.width == NS_UNCONSTRAINEDSIZE;
+ mUnconstrainedHeight = maxSize.height == NS_UNCONSTRAINEDSIZE;
+#ifdef NS_DEBUG
+ if (!mUnconstrainedWidth && (maxSize.width > 100000)) {
+ mBlock->ListTag(stdout);
+ printf(": bad parent: maxSize WAS %d,%d\n",
+ maxSize.width, maxSize.height);
+ maxSize.width = NS_UNCONSTRAINEDSIZE;
+ mUnconstrainedWidth = PR_TRUE;
+ }
+ if (!mUnconstrainedHeight && (maxSize.height > 100000)) {
+ mBlock->ListTag(stdout);
+ printf(": bad parent: maxSize WAS %d,%d\n",
+ maxSize.width, maxSize.height);
+ maxSize.height = NS_UNCONSTRAINEDSIZE;
+ mUnconstrainedHeight = PR_TRUE;
+ }
+#endif
+ mComputeMaxElementSize = aComputeMaxElementSize;
+ if (mComputeMaxElementSize) {
+ mMaxElementSize.width = 0;
+ mMaxElementSize.height = 0;
+ }
+ mHaveBlockMaxWidth = PR_FALSE;
+
+ // Set mNoWrap flag
+ const nsStyleText* blockText = (const nsStyleText*)
+ aBlockSC->GetStyleData(eStyleStruct_Text);
+ switch (blockText->mWhiteSpace) {
+ case NS_STYLE_WHITESPACE_PRE:
+ case NS_STYLE_WHITESPACE_NOWRAP:
+ mNoWrap = PR_TRUE;
+ break;
+ default:
+ mNoWrap = PR_FALSE;
+ break;
+ }
+ mTextAlign = blockText->mTextAlign;
+ const nsStyleDisplay* styleDisplay = (const nsStyleDisplay*)
+ aBlockSC->GetStyleData(eStyleStruct_Display);
+ mDirection = styleDisplay->mDirection;
+
+ mBulletPadding = 0;
+ if (NS_STYLE_DISPLAY_LIST_ITEM == styleDisplay->mDisplay) {
+ const nsStyleList* sl = (const nsStyleList*)
+ aBlockSC->GetStyleData(eStyleStruct_List);
+ if (NS_STYLE_LIST_STYLE_POSITION_OUTSIDE == sl->mListStylePosition) {
+ mLineLayout.mListPositionOutside = PR_TRUE;
+ mBulletPadding = GetParentLeftPadding(aReflowState.parentReflowState);
+ }
+ }
+ const nsStyleSpacing* blockSpacing = (const nsStyleSpacing*)
+ aBlockSC->GetStyleData(eStyleStruct_Spacing);
+ nsMargin padding;
+ blockSpacing->CalcPaddingFor(mBlock, padding);
+ mLeftPadding = padding.left;
+
+ // Apply border and padding adjustments for regular frames only
+ nsRect blockRect;
+ mBlock->GetRect(blockRect);
+ mStyleSizeFlags = 0;
+ if (!mBlockIsPseudo) {
+ blockSpacing->CalcBorderPaddingFor(mBlock, mBorderPadding);
+ mY = mBorderPadding.top;
+ mX = mBorderPadding.left;
+
+ if (mUnconstrainedWidth) {
+ // If our width is unconstrained don't bother futzing with the
+ // available width/height because they don't matter - we are
+ // going to get reflowed again.
+ mDeltaWidth = NS_UNCONSTRAINEDSIZE;
+ mInnerSize.width = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ // When we are constrained we need to apply the width/height
+ // style properties. When we have a width/height it applies to
+ // the content width/height of our box. The content width/height
+ // doesn't include the border+padding so we have to add that in
+ // instead of subtracting it out of our maxsize.
+ nscoord lr = mBorderPadding.left + mBorderPadding.right;
+
+ // Get and apply the stylistic size. Note: do not limit the
+ // height until we are done reflowing.
+ PRIntn ss = nsCSSLayout::GetStyleSize(aPresContext, aReflowState,
+ mStyleSize);
+ mStyleSizeFlags = ss;
+ if (0 != (ss & NS_SIZE_HAS_WIDTH)) {
+ // CSS2 spec says that the width attribute defines the width
+ // of the "content area" which does not include the border
+ // padding. So we add those back in.
+ mInnerSize.width = mStyleSize.width + lr;
+ }
+ else {
+ mInnerSize.width = maxSize.width - lr;
+ }
+ mDeltaWidth = maxSize.width - blockRect.width;
+ }
+ if (mUnconstrainedHeight) {
+ mInnerSize.height = maxSize.height;
+ mBottomEdge = maxSize.height;
+ }
+ else {
+ nscoord tb = mBorderPadding.top + mBorderPadding.bottom;
+ mInnerSize.height = maxSize.height - tb;
+ mBottomEdge = maxSize.height - mBorderPadding.bottom;
+ }
+ }
+ else {
+ mBorderPadding.SizeTo(0, 0, 0, 0);
+ mDeltaWidth = maxSize.width - blockRect.width;
+ mInnerSize = maxSize;
+ mBottomEdge = maxSize.height;
+ }
+
+ // Now translate in by our border and padding
+ mSpaceManager->Translate(mBorderPadding.left, mBorderPadding.top);
+
+ mPrevChild = nsnull;
+ mFreeList = nsnull;
+ mPrevLine = nsnull;
+
+ // Setup initial list ordinal value
+
+ // XXX translate the starting value to a css style type and stop
+ // doing this!
+ mNextListOrdinal = -1;
+ nsIContent* blockContent;
+ mBlock->GetContent(blockContent);
+ nsIAtom* tag;
+ blockContent->GetTag(tag);
+ if ((tag == nsHTMLAtoms::ul) || (tag == nsHTMLAtoms::ol) ||
+ (tag == nsHTMLAtoms::menu) || (tag == nsHTMLAtoms::dir)) {
+ nsHTMLValue value;
+ if (NS_CONTENT_ATTR_HAS_VALUE ==
+ ((nsIHTMLContent*)blockContent)->GetAttribute(nsHTMLAtoms::start,
+ value)) {
+ if (eHTMLUnit_Integer == value.GetUnit()) {
+ mNextListOrdinal = value.GetIntValue();
+ }
+ }
+ }
+ NS_IF_RELEASE(tag);
+ NS_RELEASE(blockContent);
+}
+
+nsBlockReflowState::~nsBlockReflowState()
+{
+ // Restore the coordinate system
+ mSpaceManager->Translate(-mBorderPadding.left, -mBorderPadding.top);
+
+ LineData* line = mFreeList;
+ while (nsnull != line) {
+ NS_ASSERTION((0 == line->mChildCount) && (nsnull == line->mFirstChild),
+ "bad free line");
+ LineData* next = line->mNext;
+ delete line;
+ line = next;
+ }
+}
+
+// Get the available reflow space for the current y coordinate. The
+// available space is relative to our coordinate system (0,0) is our
+// upper left corner.
+void
+nsBlockReflowState::GetAvailableSpace()
+{
+ nsISpaceManager* sm = mSpaceManager;
+
+#ifdef NS_DEBUG
+ // Verify that the caller setup the coordinate system properly
+ nscoord wx, wy;
+ sm->GetTranslation(wx, wy);
+ nscoord cx = mSpaceManagerX + mBorderPadding.left;
+ nscoord cy = mSpaceManagerY + mBorderPadding.top;
+ NS_ASSERTION((wx == cx) && (wy == cy), "bad coord system");
+#endif
+
+ // Fill in band data for the specific Y coordinate
+ sm->GetBandData(mY, mInnerSize, mCurrentBand);
+
+ // Compute the bounding rect of the available space, i.e. space
+ // between any left and right floaters.
+ mCurrentBand.ComputeAvailSpaceRect();
+
+ NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
+ ("nsBlockReflowState::GetAvailableSpace: band={%d,%d,%d,%d} count=%d",
+ mCurrentBand.availSpace.x, mCurrentBand.availSpace.y,
+ mCurrentBand.availSpace.width, mCurrentBand.availSpace.height,
+ mCurrentBand.count));
+}
+
+//----------------------------------------------------------------------
+
+nsresult
+NS_NewBlockFrame(nsIFrame** aInstancePtrResult,
+ nsIContent* aContent,
+ nsIFrame* aParent)
+{
+ NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
+ if (nsnull == aInstancePtrResult) {
+ return NS_ERROR_NULL_POINTER;
+ }
+ nsIFrame* it = new nsBlockFrame(aContent, aParent);
+ if (nsnull == it) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ *aInstancePtrResult = it;
+ return NS_OK;
+}
+
+nsBlockFrame::nsBlockFrame(nsIContent* aContent, nsIFrame* aParent)
+ : nsBlockFrameSuper(aContent, aParent)
+{
+ mHasBeenInitialized = PR_FALSE;
+}
+
+nsBlockFrame::~nsBlockFrame()
+{
+// if (nsnull != mRunInFloaters) {
+// delete mRunInFloaters;
+// }
+ nsTextRun::DeleteTextRuns(mTextRuns);
+}
+
+NS_IMETHODIMP
+nsBlockFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
+{
+ NS_PRECONDITION(0 != aInstancePtr, "null ptr");
+ if (NULL == aInstancePtr) {
+ return NS_ERROR_NULL_POINTER;
+ }
+ // XXX temporary
+ if (aIID.Equals(kBlockFrameCID)) {
+ *aInstancePtr = (void*) (this);
+ return NS_OK;
+ }
+ if (aIID.Equals(kIRunaroundIID)) {
+ *aInstancePtr = (void*) ((nsIRunaround*) this);
+ return NS_OK;
+ }
+ if (aIID.Equals(kIFloaterContainerIID)) {
+ *aInstancePtr = (void*) ((nsIFloaterContainer*) this);
+ return NS_OK;
+ }
+ return nsBlockFrameSuper::QueryInterface(aIID, aInstancePtr);
+}
+
+NS_IMETHODIMP
+nsBlockFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList)
+{
+ mHasBeenInitialized = PR_TRUE;
+ return AppendNewFrames(&aPresContext, aChildList);
+}
+
+NS_IMETHODIMP
+nsBlockFrame::DeleteFrame(nsIPresContext& aPresContext)
+{
+ DeleteLineList(aPresContext, mLines);
+ DeleteLineList(aPresContext, mOverflowLines);
+
+ nsBlockFrameSuper::DeleteFrame(aPresContext);
+
+ return NS_OK;
+}
+
+PRBool
+nsBlockFrame::IsPseudoFrame() const
+{
+ PRBool result = PR_FALSE;
+
+ if (nsnull != mGeometricParent) {
+ nsIContent* parentContent;
+
+ mGeometricParent->GetContent(parentContent);
+ if (parentContent == mContent) {
+ result = PR_TRUE;
+ }
+ NS_RELEASE(parentContent);
+ }
+
+ return result;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::IsSplittable(nsSplittableType& aIsSplittable) const
+{
+ aIsSplittable = NS_FRAME_SPLITTABLE_NON_RECTANGULAR;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::CreateContinuingFrame(nsIPresContext& aCX,
+ nsIFrame* aParent,
+ nsIStyleContext* aStyleContext,
+ nsIFrame*& aContinuingFrame)
+{
+ nsBlockFrame* cf = new nsBlockFrame(mContent, aParent);
+ if (nsnull == cf) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ PrepareContinuingFrame(aCX, aParent, aStyleContext, cf);
+ aContinuingFrame = cf;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::CreateContinuingFrame: newFrame=%p", cf));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::ListTag(FILE* out) const
+{
+ if ((nsnull != mGeometricParent) && IsPseudoFrame()) {
+ fprintf(out, "*block<");
+ nsIAtom* atom;
+ mContent->GetTag(atom);
+ if (nsnull != atom) {
+ nsAutoString tmp;
+ atom->ToString(tmp);
+ fputs(tmp, out);
+ }
+ PRInt32 contentIndex;
+ GetContentIndex(contentIndex);
+ fprintf(out, ">(%d)@%p", contentIndex, this);
+ } else {
+ nsBlockFrameSuper::ListTag(out);
+ }
+ return NS_OK;
+}
+
+NS_METHOD
+nsBlockFrame::List(FILE* out, PRInt32 aIndent, nsIListFilter *aFilter) const
+{
+ // if a filter is present, only output this frame if the filter says we should
+ nsIAtom* tag;
+ nsAutoString tagString;
+ mContent->GetTag(tag);
+ if (tag != nsnull)
+ {
+ tag->ToString(tagString);
+ NS_RELEASE(tag);
+ }
+
+ PRInt32 i;
+ PRBool outputMe = (PRBool)((nsnull==aFilter) || ((PR_TRUE==aFilter->OutputTag(&tagString)) && (!IsPseudoFrame())));
+ if (PR_TRUE==outputMe)
+ {
+ // Indent
+ for (i = aIndent; --i >= 0; ) fputs(" ", out);
+
+ // Output the tag
+ ListTag(out);
+ nsIView* view;
+ GetView(view);
+ if (nsnull != view) {
+ fprintf(out, " [view=%p]", view);
+ }
+
+ // Output the first/last content offset
+ fprintf(out, "[%d,%d,%c] ",
+ GetFirstContentOffset(), GetLastContentOffset(),
+ (GetLastContentIsComplete() ? 'T' : 'F'));
+ if (nsnull != mPrevInFlow) {
+ fprintf(out, "prev-in-flow=%p ", mPrevInFlow);
+ }
+ if (nsnull != mNextInFlow) {
+ fprintf(out, "next-in-flow=%p ", mNextInFlow);
+ }
+
+ // Output the rect and state
+ out << mRect;
+ if (0 != mState) {
+ fprintf(out, " [state=%08x]", mState);
+ }
+
+ #if XXX
+ // Dump run-in floaters
+ if (nsnull != mRunInFloaters) {
+ fputs(" run-in-floaters=<", out);
+ ListFloaters(out, mRunInFloaters);
+ for (i = aIndent; --i >= 0; ) fputs(" ", out);
+ fputs(">", out);
+ }
+ #endif
+ }
+
+
+ // Output the children, one line at a time
+ if (nsnull != mLines) {
+ if (PR_TRUE==outputMe)
+ fputs("<\n", out);
+ aIndent++;
+ LineData* line = mLines;
+ while (nsnull != line) {
+ line->List(out, aIndent, aFilter, outputMe);
+ line = line->mNext;
+ }
+ aIndent--;
+ if (PR_TRUE==outputMe)
+ {
+ for (i = aIndent; --i >= 0; ) fputs(" ", out);
+ fputs(">", out);
+ }
+ }
+ else {
+ if (PR_TRUE==outputMe)
+ fputs("<>", out);
+ }
+
+ if (PR_TRUE==outputMe)
+ {
+ // Output the text-runs
+ if (nsnull != mTextRuns) {
+ fputs(" text-runs=<\n", out);
+ ListTextRuns(out, aIndent + 1, mTextRuns);
+ for (i = aIndent; --i >= 0; ) fputs(" ", out);
+ fputs(">", out);
+ }
+ fputs("\n", out);
+ }
+
+ return NS_OK;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Child frame enumeration
+
+NS_IMETHODIMP
+nsBlockFrame::ChildCount(PRInt32& aChildCount) const
+{
+ PRInt32 sum = 0;
+ LineData* line = mLines;
+ while (nsnull != line) {
+ sum += line->mChildCount;
+ line = line->mNext;
+ }
+ aChildCount = sum;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::ChildAt(PRInt32 aIndex, nsIFrame*& aFrame) const
+{
+ LineData* line = mLines;
+ if ((aIndex >= 0) && (nsnull != line)) {
+ // First find the line that contains the aIndex
+ while (nsnull != line) {
+ PRInt32 n = line->mChildCount;
+ if (aIndex < n) {
+ // Then find the frame in the line
+ nsIFrame* frame = mLines->mFirstChild;
+ while (--n >= 0) {
+ if (0 == aIndex) {
+ aFrame = frame;
+ return NS_OK;
+ }
+ aIndex--;
+ frame->GetNextSibling(frame);
+ }
+ NS_NOTREACHED("line mChildCount wrong");
+ }
+ aIndex -= line->mChildCount;
+ line = line->mNext;
+ }
+ }
+
+ aFrame = nsnull;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::IndexOf(const nsIFrame* aChild, PRInt32& aIndex) const
+{
+ aIndex = -1;
+ if (nsnull != mLines) {
+ PRInt32 index = 0;
+ nsIFrame* frame = mLines->mFirstChild;
+ NS_ASSERTION(nsnull != frame, "bad mLines");
+ while (nsnull != frame) {
+ if (frame == aChild) {
+ aIndex = index;
+ break;
+ }
+ index++;
+ frame->GetNextSibling(frame);
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::FirstChild(nsIFrame*& aFirstChild) const
+{
+ aFirstChild = (nsnull != mLines) ? mLines->mFirstChild : nsnull;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::NextChild(const nsIFrame* aChild, nsIFrame*& aNextChild) const
+{
+ NS_PRECONDITION(aChild != nsnull, "null pointer");
+ aChild->GetNextSibling(aNextChild);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::PrevChild(const nsIFrame* aChild, nsIFrame*& aPrevChild) const
+{
+ NS_PRECONDITION(aChild != nsnull, "null pointer");
+ if ((nsnull != mLines) && (mLines->mFirstChild != aChild)) {
+ nsIFrame* frame = mLines->mFirstChild;
+ while (nsnull != frame) {
+ nsIFrame* nextFrame;
+ frame->GetNextSibling(nextFrame);
+ if (nextFrame == aChild) {
+ aPrevChild = frame;
+ return NS_OK;
+ }
+ frame = nextFrame;
+ }
+ }
+ aPrevChild = nsnull;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::LastChild(nsIFrame*& aLastChild) const
+{
+ LineData* line = LastLine(mLines);
+ if (nsnull != line) {
+ aLastChild = line->LastChild();
+ return NS_OK;
+ }
+ aLastChild = nsnull;
+ return NS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////
+// Reflow methods
+
+#if XXX
+PRBool
+nsBlockFrame::GetLastContentIsComplete() const
+{
+ PRBool result = PR_TRUE;
+ LineData* line = LastLine(mLines);
+ if (nsnull != line) {
+ return line->GetLastContentIsComplete();
+ }
+ return result;
+}
+
+PRInt32
+nsBlockFrame::GetFirstContentOffset() const
+{
+ PRInt32 result = 0;
+ LineData* line = mLines;
+ if (nsnull != line) {
+ line->mFirstChild->GetContentIndex(result);
+ }
+ return result;
+}
+
+PRInt32
+nsBlockFrame::GetLastContentOffset() const
+{
+ PRInt32 result = 0;
+ LineData* line = LastNonEmptyLine(mLines);
+ if (nsnull != line) {
+ line->LastChild()->GetContentIndex(result);
+ }
+ return result;
+}
+#endif
+
+NS_IMETHODIMP
+nsBlockFrame::ReflowAround(nsIPresContext& aPresContext,
+ nsISpaceManager* aSpaceManager,
+ nsReflowMetrics& aMetrics,
+ const nsReflowState& aReflowState,
+ nsRect& aDesiredRect,
+ nsReflowStatus& aStatus)
+{
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("enter nsBlockFrame::Reflow: maxSize=%d,%d reason=%d [%d,%d,%c]",
+ aReflowState.maxSize.width,
+ aReflowState.maxSize.height,
+ aReflowState.reason,
+ GetFirstContentOffset(), GetLastContentOffset(),
+ GetLastContentIsComplete()?'T':'F'));
+
+ // If this is the initial reflow, generate any synthetic content
+ // that needs generating.
+ if (eReflowReason_Initial == aReflowState.reason) {
+ NS_ASSERTION(0 != (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
+ }
+ else {
+ NS_ASSERTION(0 == (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
+ }
+
+ // Replace parent provided reflow state with our own significantly
+ // more extensive version.
+ nsBlockReflowState state(&aPresContext, aSpaceManager,
+ this, mStyleContext,
+ aReflowState, aMetrics,
+ PRBool(nsnull != aMetrics.maxElementSize));
+
+ nsresult rv = NS_OK;
+ if (eReflowReason_Initial == state.reason) {
+ if (!DrainOverflowLines()) {
+ rv = InitialReflow(state);
+ }
+ else {
+ rv = ResizeReflow(state);
+ }
+ mState &= ~NS_FRAME_FIRST_REFLOW;
+ }
+ else if (eReflowReason_Incremental == state.reason) {
+#if XXX
+ // We can have an overflow here if our parent doesn't bother to
+ // continue us
+ DrainOverflowLines();
+#endif
+ nsIFrame* target;
+ state.reflowCommand->GetTarget(target);
+ if (this == target) {
+ nsIReflowCommand::ReflowType type;
+ state.reflowCommand->GetType(type);
+ switch (type) {
+ case nsIReflowCommand::FrameAppended:
+ rv = FrameAppendedReflow(state);
+ break;
+
+ case nsIReflowCommand::FrameInserted:
+ rv = FrameInsertedReflow(state);
+ break;
+
+ case nsIReflowCommand::FrameDeleted:
+ rv = FrameDeletedReflow(state);
+ break;
+
+ default:
+ NS_NOTYETIMPLEMENTED("XXX");
+ }
+ }
+ else {
+ // Get next frame in reflow command chain
+ state.reflowCommand->GetNext(state.mInlineLayout.mNextRCFrame);
+
+ // Now do the reflow
+ rv = ChildIncrementalReflow(state);
+ }
+ }
+ else if (eReflowReason_Resize == state.reason) {
+ DrainOverflowLines();
+ rv = ResizeReflow(state);
+ }
+
+#ifdef DTPF
+ // Update content offsets; we don't track them normally but we do
+ // need them because we are a pseudo-frame
+ if (nsnull != mLines) {
+ nsIFrame* firstChild = mLines->mFirstChild;
+ if (nsnull != firstChild) {
+ firstChild->GetContentIndex(mFirstContentOffset);
+ }
+ LineData* line = mLines;
+ while (nsnull != line->mNext) {
+ NS_ASSERTION(line->mChildCount > 0, "empty line left on list");
+ line = line->mNext;
+ }
+ line->LastChild()->GetContentIndex(mLastContentOffset);
+ mLastContentIsComplete = line->GetLastContentIsComplete();
+ }
+ if (state.mBlockIsPseudo) {
+ // Tell our parent to update it's offsets because our offsets have
+ // changed.
+ nsContainerFrame* parent = (nsContainerFrame*) mGeometricParent;
+ parent->PropagateContentOffsets(this, mFirstContentOffset,
+ mLastContentOffset,
+ mLastContentIsComplete);
+ }
+#endif
+
+ // Compute our final size
+ ComputeFinalSize(state, aMetrics, aDesiredRect);
+
+#ifdef NS_DEBUG
+ if (GetVerifyTreeEnable()) {
+ VerifyChildCount(mLines);
+ VerifyLines(mLines);
+ }
+#endif
+ aStatus = rv;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("exit nsBlockFrame::Reflow: size=%d,%d rv=%x [%d,%d,%c]",
+ aMetrics.width, aMetrics.height, rv,
+ GetFirstContentOffset(), GetLastContentOffset(),
+ GetLastContentIsComplete()?'T':'F'));
+ return NS_OK;
+}
+
+nsresult
+nsBlockFrame::ProcessInitialReflow(nsIPresContext* aPresContext)
+{
+ // XXX ick; html stuff. pfuui.
+
+ if (nsnull == mPrevInFlow) {
+ const nsStyleDisplay* display = (const nsStyleDisplay*)
+ mStyleContext->GetStyleData(eStyleStruct_Display);
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::ProcessInitialReflow: display=%d",
+ display->mDisplay));
+ if (NS_STYLE_DISPLAY_LIST_ITEM == display->mDisplay) {
+ // This container is a list-item container. Therefore it needs a
+ // bullet content object. However, it might have already had the
+ // bullet crated. Check to see if the first child of the
+ // container is a synthetic object; if it is, then don't make a
+ // bullet (XXX what a hack!).
+ nsIContent* firstContent;
+ mContent->ChildAt(0, firstContent);
+ if (nsnull != firstContent) {
+ PRBool is;
+ firstContent->IsSynthetic(is);
+ NS_RELEASE(firstContent);
+ if (is) {
+ return NS_OK;
+ }
+ }
+
+ nsIHTMLContent* bullet;
+ nsresult rv = NS_NewHTMLBullet(&bullet);
+ if (NS_OK != rv) {
+ return rv;
+ }
+
+ // Insert the bullet. Do not allow an incremental reflow operation
+ // to occur.
+ mContent->InsertChildAt(bullet, 0, PR_FALSE);
+
+ // If the frame has already been initialized, then we need to create a frame
+ // for the bullet and insert it into the line list
+ if (mHasBeenInitialized) {
+ nsIStyleContext* kidSC = aPresContext->ResolveStyleContextFor(bullet, this);
+
+ nsIFrame* bulletFrame;
+ NS_NewBulletFrame(bullet, this, bulletFrame);
+ bulletFrame->SetStyleContext(aPresContext, kidSC);
+ NS_RELEASE(kidSC);
+
+ // Insert the bullet frame
+ InsertNewFrame(this, bulletFrame, nsnull);
+ }
+
+ NS_RELEASE(bullet);
+ }
+ }
+
+ return NS_OK;
+}
+
+#if XXX
+// XXX It should be impossible to write this code because we use
+// methods on nsContainerFrame that we have no right using.
+
+// XXX can't work: our parent can be an nsContainerFrame -or- an
+// nsBlockFrame; we can't tell them apart and yet the need to be
+// updated when we are a pseudo-frame
+
+void
+nsBlockFrame::PropagateContentOffsets()
+{
+ NS_PRECONDITION(IsPseudoFrame(), "not a pseudo frame");
+ nsIFrame* parent = mGeometricParent;
+ if (nsnull != parent) {
+ // If we're the first child frame then update our parent's content offset
+ nsIFrame* firstChild;
+ parent->FirstChild(firstChild);
+ if (firstChild == this) {
+ parent->SetFirstContentOffset(GetFirstContentOffset());
+ }
+
+ // If we're the last child frame then update our parent's content offset
+ if (nsnull == mNextSibling) {
+ parent->SetLastContentOffset(GetLastContentOffset());
+ parent->SetLastContentIsComplete(GetLastContentIsComplete());
+ }
+
+ // If the parent is being used as a pseudo frame then we need to propagate
+ // the content offsets upwards to its parent frame
+ if (parent->IsPseudoFrame()) {
+ parent->PropagateContentOffsets();
+ }
+ }
+}
+#endif
+
+void
+nsBlockFrame::ComputeFinalSize(nsBlockReflowState& aState,
+ nsReflowMetrics& aMetrics,
+ nsRect& aDesiredRect)
+{
+ aDesiredRect.x = 0;
+ aDesiredRect.y = 0;
+
+ // Special check for zero sized content: If our content is zero
+ // sized then we collapse into nothingness.
+ if ((0 == aState.mKidXMost - aState.mBorderPadding.left) &&
+ (0 == aState.mY - aState.mBorderPadding.top)) {
+ aDesiredRect.width = 0;
+ aDesiredRect.height = 0;
+ aMetrics.posBottomMargin = 0;
+ }
+ else {
+ aDesiredRect.width = aState.mKidXMost + aState.mBorderPadding.right;
+ if (!aState.mUnconstrainedWidth) {
+ // Make sure we're at least as wide as the max size we were given
+ nscoord mw = aState.maxSize.width/* + aState.mBulletPaddingXXX*/;
+ if (aDesiredRect.width < mw) {
+ aDesiredRect.width = mw;
+ }
+ }
+ if (0 != aState.mBorderPadding.bottom) {
+ aState.mY += aState.mBorderPadding.bottom;
+ aMetrics.posBottomMargin = 0;
+ }
+ else {
+ aMetrics.posBottomMargin = aState.mPrevBottomMargin;
+ }
+ aDesiredRect.height = aState.mY;
+
+ if (!aState.mBlockIsPseudo) {
+ // Clamp the desired rect height when style height applies
+ PRIntn ss = aState.mStyleSizeFlags;
+ if (0 != (ss & NS_SIZE_HAS_HEIGHT)) {
+ aDesiredRect.height = aState.mBorderPadding.top +
+ aState.mStyleSize.height + aState.mBorderPadding.bottom;
+ }
+ }
+ }
+
+ aMetrics.width = aDesiredRect.width;
+ aMetrics.height = aDesiredRect.height;
+ aMetrics.ascent = aMetrics.height;
+ aMetrics.descent = 0;
+ if (aState.mComputeMaxElementSize) {
+ *aMetrics.maxElementSize = aState.mMaxElementSize;
+
+ // Add in our border and padding to the max-element-size so that
+ // we don't shrink too far.
+ aMetrics.maxElementSize->width += aState.mBorderPadding.left +
+ aState.mBorderPadding.right;
+ aMetrics.maxElementSize->height += aState.mBorderPadding.top +
+ aState.mBorderPadding.bottom;
+
+ // Factor in any left and right floaters as well
+ LineData* line = mLines;
+ PRInt32 maxLeft = 0, maxRight = 0;
+ while (nsnull != line) {
+ if (nsnull != line->mFloaters) {
+ nsRect r;
+ nsMargin floaterMargin;
+ PRInt32 leftSum = 0, rightSum = 0;
+ PRInt32 n = line->mFloaters->Count();
+ for (PRInt32 i = 0; i < n; i++) {
+ nsPlaceholderFrame* placeholder = (nsPlaceholderFrame*)
+ line->mFloaters->ElementAt(i);
+ nsIFrame* floater = placeholder->GetAnchoredItem();
+ floater->GetRect(r);
+ const nsStyleDisplay* floaterDisplay;
+ const nsStyleSpacing* floaterSpacing;
+ floater->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)floaterDisplay);
+ floater->GetStyleData(eStyleStruct_Spacing,
+ (const nsStyleStruct*&)floaterSpacing);
+ floaterSpacing->CalcMarginFor(floater, floaterMargin);
+ nscoord width = r.width + floaterMargin.left + floaterMargin.right;
+ switch (floaterDisplay->mFloats) {
+ default:
+ NS_NOTYETIMPLEMENTED("Unsupported floater type");
+ // FALL THROUGH
+
+ case NS_STYLE_FLOAT_LEFT:
+ leftSum += width;
+ break;
+
+ case NS_STYLE_FLOAT_RIGHT:
+ rightSum += width;
+ break;
+ }
+ }
+ if (leftSum > maxLeft) maxLeft = leftSum;
+ if (rightSum > maxRight) maxRight = rightSum;
+ }
+ line = line->mNext;
+ }
+ aMetrics.maxElementSize->width += maxLeft + maxRight;
+ }
+ NS_ASSERTION(aDesiredRect.width < 1000000, "whoops");
+}
+
+nsresult
+nsBlockFrame::AppendNewFrames(nsIPresContext* aPresContext, nsIFrame* aNewFrame)
+{
+ // Get our last line and then get its last child
+ nsIFrame* lastFrame;
+ LineData* lastLine = LastLine(mLines);
+ if (nsnull != lastLine) {
+ lastFrame = lastLine->LastChild();
+ } else {
+ lastFrame = nsnull;
+ }
+
+ // Add the new frames to the sibling list
+ if (nsnull != lastFrame) {
+ lastFrame->SetNextSibling(aNewFrame);
+ }
+
+ // Make sure that new inlines go onto the end of the lastLine when
+ // the lastLine is mapping inline frames.
+ PRInt32 pendingInlines = 0;
+ if (nsnull != lastLine) {
+ if (!lastLine->IsBlock()) {
+ pendingInlines = 1;
+ }
+ }
+
+ // Now create some lines for the new frames
+ nsIFrame* prevFrame = lastFrame;
+ nsresult rv;
+ for (nsIFrame* frame = aNewFrame; nsnull != frame; frame->GetNextSibling(frame)) {
+ // See if the child is a block or non-block
+ const nsStyleDisplay* kidDisplay;
+ rv = frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&) kidDisplay);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ const nsStylePosition* kidPosition;
+ rv = frame->GetStyleData(eStyleStruct_Position,
+ (const nsStyleStruct*&) kidPosition);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ PRBool isBlock =
+ nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition);
+
+ // See if the element wants to be floated
+ if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) {
+ // Create a placeholder frame that will serve as the anchor point.
+ nsPlaceholderFrame* placeholder =
+ CreatePlaceholderFrame(aPresContext, frame);
+
+ // Remove the floated element from the flow, and replace it with the
+ // placeholder frame
+ if (nsnull != prevFrame) {
+ prevFrame->SetNextSibling(placeholder);
+ }
+ nsIFrame* nextSibling;
+ frame->GetNextSibling(nextSibling);
+ placeholder->SetNextSibling(nextSibling);
+ frame->SetNextSibling(nsnull);
+
+ // If the floated element can contain children then wrap it in a
+ // BODY frame before floating it
+ nsIContent* content;
+ PRBool isContainer;
+
+ frame->GetContent(content);
+ content->CanContainChildren(isContainer);
+ if (isContainer) {
+ // Wrap the floated element in a BODY frame.
+ nsIFrame* wrapperFrame;
+ NS_NewBodyFrame(content, this, wrapperFrame);
+
+ // The body wrapper frame gets the original style context, and the floated
+ // frame gets a pseudo style context
+ nsIStyleContext* kidStyle;
+ frame->GetStyleContext(aPresContext, kidStyle);
+ wrapperFrame->SetStyleContext(aPresContext, kidStyle);
+ NS_RELEASE(kidStyle);
+
+ nsIStyleContext* pseudoStyle;
+ pseudoStyle = aPresContext->ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo,
+ wrapperFrame);
+ frame->SetStyleContext(aPresContext, pseudoStyle);
+ NS_RELEASE(pseudoStyle);
+
+ // Init the body frame
+ wrapperFrame->Init(*aPresContext, frame);
+
+ // Bind the wrapper frame to the placeholder
+ placeholder->SetAnchoredItem(wrapperFrame);
+ }
+ NS_RELEASE(content);
+
+ // The placeholder frame is always inline
+ frame = placeholder;
+ isBlock = PR_FALSE;
+ }
+
+ // If the child is an inline then add it to the lastLine (if it's
+ // an inline line, otherwise make a new line). If the child is a
+ // block then make a new line and put the child in that line.
+ if (isBlock) {
+ // If the previous line has pending inline data to be reflowed,
+ // do so now.
+ if (0 != pendingInlines) {
+ // Set this to true in case we don't end up reflowing all of the
+ // frames on the line (because they end up being pushed).
+ lastLine->SetLastContentIsComplete();
+ lastLine->MarkDirty();
+ pendingInlines = 0;
+ }
+
+ // Create a line for the block
+ LineData* line = new LineData(frame, 1,
+ (LINE_IS_BLOCK |
+ LINE_LAST_CONTENT_IS_COMPLETE));
+ if (nsnull == line) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ if (nsnull == lastLine) {
+ mLines = line;
+ }
+ else {
+ lastLine->mNext = line;
+ }
+ lastLine = line;
+ }
+ else {
+ // Queue up the inlines for reflow later on
+ if (0 == pendingInlines) {
+ LineData* line = new LineData(frame, 0, 0);
+ if (nsnull == line) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ if (nsnull == lastLine) {
+ mLines = line;
+ }
+ else {
+ lastLine->mNext = line;
+ }
+ lastLine = line;
+ }
+ lastLine->mChildCount++;
+ pendingInlines++;
+ }
+
+ // Remember the previous frame
+ prevFrame = frame;
+ }
+
+ if (0 != pendingInlines) {
+ // Set this to true in case we don't end up reflowing all of the
+ // frames on the line (because they end up being pushed).
+ lastLine->SetLastContentIsComplete();
+ lastLine->MarkDirty();
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsBlockFrame::InitialReflow(nsBlockReflowState& aState)
+{
+ // Create synthetic content (XXX a hack)
+ nsresult rv = ProcessInitialReflow(aState.mPresContext);
+ if (NS_OK != rv) {
+ return rv;
+ }
+
+ // XXX CONSTRUCTION
+ // Temporary hack. If we haven't had Init() called then go ahead and create
+ // frames the old way. This is needed until tables get converted...
+
+ // Create new frames
+ if (!mHasBeenInitialized) {
+ if (nsnull == mNextInFlow) {
+ rv = CreateNewFrames(aState.mPresContext);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ }
+ }
+
+ // Generate text-run information
+ rv = FindTextRuns(aState);
+ if (NS_OK != rv) {
+ return rv;
+ }
+
+ // Reflow everything
+ aState.GetAvailableSpace();
+ return ResizeReflow(aState);
+}
+
+nsresult
+nsBlockFrame::FrameAppendedReflow(nsBlockReflowState& aState)
+{
+ // XXX CONSTRUCTION
+#if 0
+ // Create new frames for the appended content. Each line that is
+ // impacted by this will be marked dirty.
+ nsresult rv = CreateNewFrames(aState.mPresContext);
+ if (NS_OK != rv) {
+ return rv;
+ }
+#else
+ nsresult rv = NS_OK;
+
+ // Get the first of the newly appended frames
+ nsIFrame* firstAppendedFrame;
+ aState.reflowCommand->GetChildFrame(firstAppendedFrame);
+
+ // Add the new frames to the child list, and create new lines. Each
+ // impacted line will be marked dirty
+ AppendNewFrames(aState.mPresContext, firstAppendedFrame);
+#endif
+
+ // Generate text-run information
+ rv = FindTextRuns(aState);
+ if (NS_OK != rv) {
+ return rv;
+ }
+
+ // Recover our reflow state. First find the lastCleanLine and the
+ // firstDirtyLine which follows it. While we are looking, compute
+ // the maximum xmost of each line.
+ LineData* firstDirtyLine = mLines;
+ LineData* lastCleanLine = nsnull;
+ LineData* lastYLine = nsnull;
+ while (nsnull != firstDirtyLine) {
+ if (firstDirtyLine->IsDirty()) {
+ break;
+ }
+ nscoord xmost = firstDirtyLine->mBounds.XMost();
+NS_ASSERTION(xmost < 1000000, "bad line width");
+ if (xmost > aState.mKidXMost) {
+ aState.mKidXMost = xmost;
+ }
+ if (firstDirtyLine->mBounds.height > 0) {
+ lastYLine = firstDirtyLine;
+ }
+ lastCleanLine = firstDirtyLine;
+ firstDirtyLine = firstDirtyLine->mNext;
+ }
+
+ // Recover the starting Y coordinate and the previous bottom margin
+ // value.
+ if (nsnull != lastCleanLine) {
+ // If the lastCleanLine is not a block but instead is a zero
+ // height inline line then we need to backup to either a non-zero
+ // height line.
+ aState.mPrevBottomMargin = 0;
+ if (nsnull != lastYLine) {
+ aState.mPrevBottomMargin = lastYLine->mInnerBottomMargin +
+ lastYLine->mOuterBottomMargin;
+ }
+
+ // Start the Y coordinate after the last clean line.
+ aState.mY = lastCleanLine->mBounds.YMost();
+
+ // Add in the outer margin to the Y coordinate (the inner margin
+ // will be present in the lastCleanLine's YMost so don't add it
+ // in again)
+ aState.mY += lastCleanLine->mOuterBottomMargin;
+
+ // XXX I'm not sure about the previous statement and floaters!!!
+
+ // Place any floaters the line has
+ if (nsnull != lastCleanLine->mFloaters) {
+ aState.mCurrentLine = lastCleanLine;
+ aState.PlaceFloaters(lastCleanLine->mFloaters);
+ }
+ }
+
+ aState.GetAvailableSpace();
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockReflowState::FrameAppendedReflow: y=%d firstDirtyLine=%p",
+ aState.mY, firstDirtyLine));
+
+ // Reflow lines from there forward
+ aState.mPrevLine = lastCleanLine;
+ return ReflowLinesAt(aState, firstDirtyLine);
+}
+
+nsresult
+nsBlockFrame::CreateNewFrames(nsIPresContext* aPresContext)
+{
+ // If we need to be continued but aren't, we will have an overflow list
+ NS_ASSERTION((nsnull == mOverflowLines) && (nsnull == mNextInFlow),
+ "bad call to CreateNewFrames");
+
+ // Get our last line and then get its last child. Use that
+ // information to determine our kidContentIndex.
+ LineData* lastLine = LastLine(mLines);
+ nsIFrame* lastFrame;
+ PRInt32 kidContentIndex;
+ if (nsnull != lastLine) {
+ lastFrame = lastLine->LastChild();
+ lastFrame->GetContentIndex(kidContentIndex);
+ if (lastLine->GetLastContentIsComplete()) {
+ kidContentIndex++;
+ }
+ else {
+#ifdef NS_DEBUG
+ // Because we always create continuations as we find them (XXX
+ // sigh) instead of when we need them, we can assert that if the
+ // last child is not complete then it already has a continuation.
+ nsIFrame* kidNextInFlow;
+ lastFrame->GetNextInFlow(kidNextInFlow);
+ NS_ASSERTION(nsnull != kidNextInFlow, "whoops");
+#endif
+ }
+ }
+ else {
+ // We can't have an empty line list and have a prev-in-flow. If we
+ // have a prev-in-flow then we are its continuation which means it
+ // must have pushed some lines into its overflow list; therefore
+ // we must have some lines.
+ NS_ASSERTION(nsnull == mPrevInFlow, "prev-in-flow without overflow lines");
+ lastFrame = nsnull;
+ kidContentIndex = 0;
+ }
+
+ // Make sure that new inlines go onto the end of the lastLine when
+ // the lastLine is mapping inline frames.
+ PRInt32 pendingInlines = 0;
+ if (nsnull != lastLine) {
+ if (!lastLine->IsBlock()) {
+ pendingInlines = 1;
+ }
+ }
+
+ // Now create frames for all of the new content.
+ nsresult rv;
+ PRInt32 lastContentIndex;
+ mContent->ChildCount(lastContentIndex);
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("enter nsBlockFrame::CreateNewFrames: kidContentIndex=%d lastContentIndex=%d",
+ kidContentIndex, lastContentIndex));
+ for (; kidContentIndex < lastContentIndex; kidContentIndex++) {
+ nsIContent* kid;
+ mContent->ChildAt(kidContentIndex, kid);
+ if (nsnull == kid) {
+ break;
+ }
+
+ // Create frame for our new child and add it to the sibling list
+ nsIFrame* frame;
+ rv = nsHTMLBase::CreateFrame(aPresContext, this, kid, nsnull, frame);
+ NS_RELEASE(kid);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ if (nsnull != lastFrame) {
+ lastFrame->SetNextSibling(frame);
+ }
+ lastFrame = frame;
+//XXX childPrevInFlow = nsnull;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_NEW_FRAMES,
+ ("nsBlockFrame::CreateNewFrames: new-frame=%p", frame));
+
+ // See if the child is a block or non-block
+ const nsStyleDisplay* kidDisplay;
+ rv = frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&) kidDisplay);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ const nsStylePosition* kidPosition;
+ rv = frame->GetStyleData(eStyleStruct_Position,
+ (const nsStyleStruct*&) kidPosition);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ PRBool isBlock =
+ nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition);
+
+ // If the child is an inline then add it to the lastLine (if it's
+ // an inline line, otherwise make a new line). If the child is a
+ // block then make a new line and put the child in that line.
+ if (isBlock) {
+ // If the previous line has pending inline data to be reflowed,
+ // do so now.
+ if (0 != pendingInlines) {
+ // Set this to true in case we don't end up reflowing all of the
+ // frames on the line (because they end up being pushed).
+ lastLine->SetLastContentIsComplete();
+ lastLine->MarkDirty();
+ pendingInlines = 0;
+ }
+
+ // Create a line for the block
+ LineData* line = new LineData(frame, 1,
+ (LINE_IS_BLOCK |
+ LINE_LAST_CONTENT_IS_COMPLETE));
+ if (nsnull == line) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ if (nsnull == lastLine) {
+ mLines = line;
+ }
+ else {
+ lastLine->mNext = line;
+ }
+ lastLine = line;
+ }
+ else {
+ // Queue up the inlines for reflow later on
+ if (0 == pendingInlines) {
+ LineData* line = new LineData(frame, 0, 0);
+ if (nsnull == line) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ if (nsnull == lastLine) {
+ mLines = line;
+ }
+ else {
+ lastLine->mNext = line;
+ }
+ lastLine = line;
+ }
+ lastLine->mChildCount++;
+ pendingInlines++;
+ }
+ }
+
+ if (0 != pendingInlines) {
+ // Set this to true in case we don't end up reflowing all of the
+ // frames on the line (because they end up being pushed).
+ lastLine->SetLastContentIsComplete();
+ lastLine->MarkDirty();
+ }
+
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("exit nsBlockFrame::CreateNewFrames"));
+ return NS_OK;
+}
+
+// XXX keep the text-run data in the first-in-flow of the block
+nsresult
+nsBlockFrame::FindTextRuns(nsBlockReflowState& aState)
+{
+ // Destroy old run information first
+ nsTextRun::DeleteTextRuns(mTextRuns);
+ mTextRuns = nsnull;
+ aState.mLineLayout.ResetTextRuns();
+
+ // Ask each child that implements nsIInlineReflow to find its text runs
+ LineData* line = mLines;
+ while (nsnull != line) {
+ if (!line->IsBlock()) {
+ nsIFrame* frame = line->mFirstChild;
+ PRInt32 n = line->mChildCount;
+ while (--n >= 0) {
+ nsIInlineReflow* inlineReflow;
+ if (NS_OK == frame->QueryInterface(kIInlineReflowIID,
+ (void**)&inlineReflow)) {
+ nsresult rv = inlineReflow->FindTextRuns(aState.mLineLayout,
+ aState.reflowCommand);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ }
+ else {
+ // A frame that doesn't implement nsIInlineReflow isn't text
+ // therefore it will end an open text run.
+ aState.mLineLayout.EndTextRun();
+ }
+ frame->GetNextSibling(frame);
+ }
+ }
+ else {
+ // A frame that doesn't implement nsIInlineReflow isn't text
+ // therefore it will end an open text run.
+ aState.mLineLayout.EndTextRun();
+ }
+ line = line->mNext;
+ }
+ aState.mLineLayout.EndTextRun();
+
+ // Now take the text-runs away from the line layout engine.
+ mTextRuns = aState.mLineLayout.TakeTextRuns();
+
+ return NS_OK;
+}
+
+nsresult
+nsBlockFrame::FrameInsertedReflow(nsBlockReflowState& aState)
+{
+ LineData* line = mLines;
+ while (nsnull != line->mNext) {
+ if (line->IsDirty()) {
+ break;
+ }
+ line = line->mNext;
+ }
+ NS_ASSERTION(nsnull != line, "bad inserted reflow");
+ //XXX return ReflowDirtyLines(aState, line);
+
+ // XXX Correct implementation: reflow the dirty lines only; all
+ // other lines can be moved; recover state before first dirty line.
+
+ // XXX temporary
+ aState.GetAvailableSpace();
+ aState.mPrevLine = nsnull;
+ return ReflowLinesAt(aState, mLines);
+}
+
+nsresult
+nsBlockFrame::FrameDeletedReflow(nsBlockReflowState& aState)
+{
+ if (nsnull == mLines) {
+ return NS_OK;
+ }
+ LineData* line = mLines;
+ while (nsnull != line->mNext) {
+ if (line->IsDirty()) {
+ break;
+ }
+ line = line->mNext;
+ }
+ NS_ASSERTION(nsnull != line, "bad inserted reflow");
+ //XXX return ReflowDirtyLines(aState, line);
+
+ // XXX Correct implementation: reflow the dirty lines only; all
+ // other lines can be moved; recover state before first dirty line.
+
+ // XXX temporary
+ aState.GetAvailableSpace();
+ aState.mPrevLine = nsnull;
+ return ReflowLinesAt(aState, mLines);
+}
+
+// XXX Todo: some incremental reflows are passing through this block
+// and into a child block; those cannot impact our text-runs. In that
+// case skip the FindTextRuns work.
+
+// XXX easy optimizations: find the line that contains the next child
+// in the reflow-command path and mark it dirty and only reflow it;
+// recover state before it, slide lines down after it.
+
+nsresult
+nsBlockFrame::ChildIncrementalReflow(nsBlockReflowState& aState)
+{
+ // Generate text-run information; this will also "fluff out" any
+ // inline children's frame tree.
+ nsresult rv = FindTextRuns(aState);
+ if (NS_OK != rv) {
+ return rv;
+ }
+
+ // XXX temporary
+ aState.GetAvailableSpace();
+ aState.mPrevLine = nsnull;
+ return ReflowLinesAt(aState, mLines);
+}
+
+nsresult
+nsBlockFrame::ResizeReflow(nsBlockReflowState& aState)
+{
+ // Mark everything dirty
+ LineData* line = mLines;
+ while (nsnull != line) {
+ line->MarkDirty();
+ line = line->mNext;
+ }
+
+ // Reflow all of our lines
+ aState.GetAvailableSpace();
+ aState.mPrevLine = nsnull;
+ return ReflowLinesAt(aState, mLines);
+}
+
+nsresult
+nsBlockFrame::ReflowLinesAt(nsBlockReflowState& aState, LineData* aLine)
+{
+#if XXX
+ if ((nsnull != mRunInFloaters) && (aLine == mLines)) {
+ aState.PlaceBelowCurrentLineFloaters(mRunInFloaters);
+ }
+#endif
+
+ // Reflow the lines that are already ours
+ while (nsnull != aLine) {
+ nsInlineReflowStatus rs;
+ if (!ReflowLine(aState, aLine, rs)) {
+ if (NS_IS_REFLOW_ERROR(rs)) {
+ return nsresult(rs);
+ }
+ return NS_FRAME_NOT_COMPLETE;
+ }
+ aState.mLineLayout.NextLine();
+ aState.mPrevLine = aLine;
+ aLine = aLine->mNext;
+ }
+
+ // Pull data from a next-in-flow if we can
+ while (nsnull != aState.mNextInFlow) {
+ // Grab first line from our next-in-flow
+ aLine = aState.mNextInFlow->mLines;
+ if (nsnull == aLine) {
+ aState.mNextInFlow = (nsBlockFrame*) aState.mNextInFlow->mNextInFlow;
+ continue;
+ }
+ // XXX See if the line is not dirty; if it's not maybe we can
+ // avoid the pullup if it can't fit?
+ aState.mNextInFlow->mLines = aLine->mNext;
+ aLine->mNext = nsnull;
+ if (0 == aLine->mChildCount) {
+ // The line is empty. Try the next one.
+ NS_ASSERTION(nsnull == aLine->mChildCount, "bad empty line");
+ aLine->mNext = aState.mFreeList;
+ aState.mFreeList = aLine;
+ continue;
+ }
+
+ // Make the children in the line ours.
+ nsIFrame* frame = aLine->mFirstChild;
+ nsIFrame* lastFrame = nsnull;
+ PRInt32 n = aLine->mChildCount;
+ while (--n >= 0) {
+ nsIFrame* geometricParent;
+ nsIFrame* contentParent;
+ frame->GetGeometricParent(geometricParent);
+ frame->GetContentParent(contentParent);
+ if (contentParent == geometricParent) {
+ frame->SetContentParent(this);
+ }
+ frame->SetGeometricParent(this);
+ lastFrame = frame;
+ frame->GetNextSibling(frame);
+ }
+ lastFrame->SetNextSibling(nsnull);
+
+#ifdef NS_DEBUG
+ LastChild(lastFrame);
+ NS_ASSERTION(lastFrame == aState.mPrevChild, "bad aState.mPrevChild");
+#endif
+
+ // Add line to our line list
+ if (nsnull == aState.mPrevLine) {
+ NS_ASSERTION(nsnull == mLines, "bad aState.mPrevLine");
+ mLines = aLine;
+ }
+ else {
+ NS_ASSERTION(nsnull == aState.mPrevLine->mNext, "bad aState.mPrevLine");
+ aState.mPrevLine->mNext = aLine;
+ aState.mPrevChild->SetNextSibling(aLine->mFirstChild);
+ }
+#ifdef NS_DEBUG
+ if (GetVerifyTreeEnable()) {
+ VerifyChildCount(mLines);
+ }
+#endif
+
+ // Now reflow it and any lines that it makes during it's reflow.
+ while (nsnull != aLine) {
+ nsInlineReflowStatus rs;
+ if (!ReflowLine(aState, aLine, rs)) {
+ if (NS_IS_REFLOW_ERROR(rs)) {
+ return nsresult(rs);
+ }
+ return NS_FRAME_NOT_COMPLETE;
+ }
+ aState.mLineLayout.NextLine();
+ aState.mPrevLine = aLine;
+ aLine = aLine->mNext;
+ }
+ }
+
+ return NS_FRAME_COMPLETE;
+}
+
+/**
+ * Reflow a line. The line will either contain a single block frame
+ * or contain 1 or more inline frames.
+ */
+PRBool
+nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsInlineReflowStatus& aReflowResult)
+{
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::ReflowLine: line=%p", aLine));
+
+ PRBool keepGoing = PR_FALSE;
+ nsBlockFrame* nextInFlow;
+ aState.mCurrentLine = aLine;
+ aState.mInlineLayoutPrepared = PR_FALSE;
+ aLine->ClearDirty();
+ aLine->SetNeedDidReflow();
+
+ // XXX temporary SLOW code
+ if (nsnull != aLine->mFloaters) {
+ delete aLine->mFloaters;
+ aLine->mFloaters = nsnull;
+ }
+
+ // Reflow mapped frames in the line
+ PRInt32 n = aLine->mChildCount;
+ if (0 != n) {
+ nsIFrame* frame = aLine->mFirstChild;
+#ifdef NS_DEBUG
+ const nsStyleDisplay* display;
+ frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&) display);
+ const nsStylePosition* position;
+ frame->GetStyleData(eStyleStruct_Position,
+ (const nsStyleStruct*&) position);
+ PRBool isBlock = nsLineLayout::TreatFrameAsBlock(display, position);
+ NS_ASSERTION(isBlock == aLine->IsBlock(), "bad line isBlock");
+#endif
+ if (aLine->IsBlock()) {
+ keepGoing = ReflowBlockFrame(aState, aLine, frame, aReflowResult);
+ return keepGoing;
+ }
+ else {
+ while (--n >= 0) {
+ keepGoing = ReflowInlineFrame(aState, aLine, frame, aReflowResult);
+ if (!keepGoing) {
+ // It is possible that one or more of next lines are empty
+ // (because of DeleteNextInFlowsFor). If so, delete them now
+ // in case we are finished.
+ LineData* nextLine = aLine->mNext;
+ while ((nsnull != nextLine) && (0 == nextLine->mChildCount)) {
+ // Discard empty lines immediately. Empty lines can happen
+ // here because of DeleteNextInFlowsFor not being able to
+ // delete lines.
+ aLine->mNext = nextLine->mNext;
+ NS_ASSERTION(nsnull == nextLine->mFirstChild, "bad empty line");
+ nextLine->mNext = aState.mFreeList;
+ aState.mFreeList = nextLine;
+ nextLine = aLine->mNext;
+ }
+ goto done;
+ }
+ frame->GetNextSibling(frame);
+ }
+ }
+ }
+
+ // Pull frames from the next line until we can't
+ while (nsnull != aLine->mNext) {
+ keepGoing = PullFrame(aState, aLine, &aLine->mNext,
+ PR_FALSE, aReflowResult);
+ if (!keepGoing) {
+ goto done;
+ }
+ }
+
+ // Pull frames from the next-in-flow(s) until we can't
+ nextInFlow = aState.mNextInFlow;
+ while (nsnull != nextInFlow) {
+ LineData* line = nextInFlow->mLines;
+ if (nsnull == line) {
+ nextInFlow = (nsBlockFrame*) nextInFlow->mNextInFlow;
+ aState.mNextInFlow = nextInFlow;
+ continue;
+ }
+ keepGoing = PullFrame(aState, aLine, &nextInFlow->mLines,
+ PR_TRUE, aReflowResult);
+ if (!keepGoing) {
+ goto done;
+ }
+ }
+ keepGoing = PR_TRUE;
+
+done:;
+ if (!aLine->IsBlock()) {
+ return PlaceLine(aState, aLine, aReflowResult);
+ }
+ return keepGoing;
+}
+
+PRBool
+nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsIFrame* aFrame,
+ nsInlineReflowStatus& aReflowResult)
+{
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockFrame::ReflowBlockFrame: line=%p frame=%p y=%d",
+ aLine, aFrame, aState.mY));
+
+ NS_ASSERTION(nsnull != aState.mSpaceManager, "null ptr");
+
+ // Get run-around interface if frame supports it
+ nsIRunaround* runAround = nsnull;
+ aFrame->QueryInterface(kIRunaroundIID, (void**)&runAround);
+
+ // Get the child margins
+ nsMargin childMargin;
+ const nsStyleSpacing* childSpacing;
+ aFrame->GetStyleData(eStyleStruct_Spacing,
+ (const nsStyleStruct*&)childSpacing);
+ childSpacing->CalcMarginFor(aFrame, childMargin);
+ const nsStyleDisplay* childDisplay;
+ aFrame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)childDisplay);
+
+ // XXX Negative margins are set to zero; we could do better SOMEDAY
+ // Compute the top margin to apply to the child block
+ nscoord totalTopMargin = 0;
+ nscoord topMargin = 0;
+ nscoord childTopMargin = 0;
+ nscoord childBottomMargin = 0;
+ if (childSpacing->mMargin.GetTopUnit() <= eStyleUnit_Auto) {
+ // Provide an ebina style margin of 1 blank line before this block
+ // for most block elements.
+ // XXX need a complete list of the ones that he does this for
+ if (NS_STYLE_DISPLAY_LIST_ITEM != childDisplay->mDisplay) {
+ if (IsPseudoFrame() && (aState.mY == aState.mBorderPadding.top)) {
+ childTopMargin = 0;
+ }
+ else {
+ const nsFont& defaultFont = aState.mPresContext->GetDefaultFont();
+ nsIFontMetrics* fm = aState.mPresContext->GetMetricsFor(defaultFont);
+ fm->GetHeight(childTopMargin);
+ NS_RELEASE(fm);
+ }
+ }
+ }
+ else {
+ childTopMargin = childMargin.top;
+ if (childTopMargin < 0) childTopMargin = 0;
+ }
+ if (aState.mY == aState.mBorderPadding.top) {
+ // Since this is our first child we need to collapse its top
+ // margin with our top margin.
+ if (0 != aState.mBorderPadding.top) {
+ // Since we have a border/padding value the childs top margin
+ // does not collapse with our top margin.
+ topMargin = childTopMargin;
+ }
+ else {
+ nscoord outerTopMargin = aState.mOuterTopMargin;
+ if (childTopMargin > outerTopMargin) {
+ topMargin = childTopMargin - outerTopMargin;
+ totalTopMargin = childTopMargin;
+ }
+ else {
+ totalTopMargin = outerTopMargin;
+ }
+ }
+ }
+ else {
+ // For other children we collapse the margins between them.
+ if (childTopMargin > aState.mPrevBottomMargin) {
+ topMargin = childTopMargin - aState.mPrevBottomMargin;
+ totalTopMargin = childTopMargin;
+ }
+ else {
+ totalTopMargin = aState.mPrevBottomMargin;
+ }
+ }
+ if (childSpacing->mMargin.GetBottomUnit() > eStyleUnit_Auto) {
+ childBottomMargin = childMargin.bottom;
+ if (childBottomMargin < 0) childBottomMargin = 0;
+ }
+
+ // Compute the available space that the child block can reflow into
+ // and the starting x,y coordinate.
+ nscoord x;
+ if (nsnull == runAround) {
+ // When there is no run-around API the coordinates must include
+ // any impact by floaters.
+ x = aState.mCurrentBand.availSpace.x;
+ }
+ else {
+ // When the child does implement the run-around API it will deal
+ // with any floater impact itself.
+ x = aState.mX;
+ }
+ x += childMargin.left + aState.mBulletPadding;
+ nscoord y = aState.mY + topMargin;
+ nsSize availSize;
+ if (aState.mUnconstrainedWidth) {
+ availSize.width = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ availSize.width = aState.mInnerSize.width -
+ (childMargin.left + childMargin.right + aState.mBulletPadding);
+ }
+ if (aState.mUnconstrainedHeight) {
+ availSize.height = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ availSize.height = aState.mBottomEdge - (y + childBottomMargin);
+ }
+ if (NS_STYLE_DISPLAY_LIST_ITEM == childDisplay->mDisplay) {
+ // Special handling for list-item children that have outside
+ // bullets.
+ const nsStyleList* sl;
+ aFrame->GetStyleData(eStyleStruct_List,
+ (const nsStyleStruct*&) sl);
+ if (NS_STYLE_LIST_STYLE_POSITION_OUTSIDE == sl->mListStylePosition) {
+ // Slide child list item so that it's just past our border; it
+ // will use our padding area to place its bullet.
+ x -= aState.mLeftPadding;
+ availSize.width += aState.mLeftPadding;
+ }
+ }
+ aFrame->WillReflow(*aState.mPresContext);
+ aFrame->MoveTo(x, y);
+
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockFrame::ReflowBlockFrame: xy={%d,%d} availSize={%d,%d}",
+ x, y, availSize.width, availSize.height));
+
+ // Determine the reason for the reflow
+ nsReflowReason reason = eReflowReason_Resize;
+ nsFrameState state;
+ aFrame->GetFrameState(state);
+ if (NS_FRAME_FIRST_REFLOW & state) {
+ reason = eReflowReason_Initial;
+ }
+ else if (aState.mInlineLayout.mNextRCFrame == aFrame) {
+ reason = eReflowReason_Incremental;
+ // Make sure we only incrementally reflow once
+ aState.mInlineLayout.mNextRCFrame = nsnull;
+ }
+
+ // Reflow the block frame. Use the run-around API if possible;
+ // otherwise treat it as a rectangular lump and place it.
+ nsresult rv;
+ nsSize kidMaxElementSize;
+ nsReflowMetrics metrics(aState.mComputeMaxElementSize
+ ? &kidMaxElementSize
+ : nsnull);
+ metrics.posTopMargin = totalTopMargin;
+ nsReflowStatus reflowStatus;
+
+ if (nsnull != runAround) {
+ // Reflow the block
+ nsReflowState reflowState(aFrame, aState, availSize);
+ reflowState.reason = reason;
+ nsRect r;
+ aState.mSpaceManager->Translate(x, y);
+ rv = runAround->ReflowAround(*aState.mPresContext, aState.mSpaceManager,
+ metrics, reflowState, r, reflowStatus);
+ aState.mSpaceManager->Translate(-x, -y);
+ metrics.width = r.width;
+ metrics.height = r.height;
+ metrics.ascent = r.height;
+ metrics.descent = 0;
+ }
+ else {
+ nsReflowState reflowState(aFrame, aState, availSize);
+ reflowState.reason = reason;
+ aState.mSpaceManager->Translate(x, y);
+ rv = aFrame->Reflow(*aState.mPresContext, metrics, reflowState,
+ reflowStatus);
+ aState.mSpaceManager->Translate(-x, -y);
+ }
+
+// XXX we need to do this because blocks depend on it; we shouldn't expect
+// the child frame to deal with it.
+ if (eReflowReason_Initial == reason) {
+ aFrame->GetFrameState(state);
+ aFrame->SetFrameState(state & ~NS_FRAME_FIRST_REFLOW);
+ }
+
+ if (NS_IS_REFLOW_ERROR(rv)) {
+ aReflowResult = nsInlineReflowStatus(rv);
+ return PR_FALSE;
+ }
+
+ if (NS_FRAME_IS_COMPLETE(reflowStatus)) {
+ nsIFrame* kidNextInFlow;
+ aFrame->GetNextInFlow(kidNextInFlow);
+ if (nsnull != kidNextInFlow) {
+ // Remove all of the childs next-in-flows. Make sure that we ask
+ // the right parent to do the removal (it's possible that the
+ // parent is not this because we are executing pullup code)
+ nsIFrame* parent;
+ aFrame->GetGeometricParent(parent);
+ ((nsBlockFrame*)parent)->DeleteNextInFlowsFor(*aState.mPresContext, aFrame);
+ }
+ aLine->SetLastContentIsComplete();
+ aReflowResult = NS_FRAME_COMPLETE;
+ }
+ else {
+ aLine->ClearLastContentIsComplete();
+ aReflowResult = NS_FRAME_NOT_COMPLETE;
+ }
+
+ // If the block we just reflowed happens to end up being zero height
+ // then we do not let its margins take effect.
+ nscoord newY;
+ if (0 == metrics.height) {
+ // Leave aState.mPrevBottomMargin alone in this case so that it
+ // can carry forward to the next non-empty block.
+ newY = y = aState.mY;
+ aLine->mInnerBottomMargin = 0;
+ aLine->mOuterBottomMargin = 0;
+ }
+ else {
+ // Collapse the childs bottom margin with the grandchilds bottom
+ // margin.
+ if (childSpacing->mMargin.GetBottomUnit() <= eStyleUnit_Auto) {
+ // list-item's don't get bottom margins in ebina land
+ const nsStyleDisplay* childDisplay;
+ aFrame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)childDisplay);
+ if (NS_STYLE_DISPLAY_LIST_ITEM != childDisplay->mDisplay) {
+ const nsFont& defaultFont = aState.mPresContext->GetDefaultFont();
+ nsIFontMetrics* fm = aState.mPresContext->GetMetricsFor(defaultFont);
+ fm->GetHeight(childBottomMargin);
+ NS_RELEASE(fm);
+ }
+ }
+ else {
+ childBottomMargin -= metrics.posBottomMargin;
+ if (childBottomMargin < 0) childBottomMargin = 0;
+ }
+
+ // See if it fit
+ newY = y + metrics.height + childBottomMargin;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockFrame::ReflowBlockFrame: metrics={%d,%d} newY=%d maxY=%d",
+ metrics.width, metrics.height, newY, aState.mBottomEdge));
+ if ((mLines != aLine) && (newY > aState.mBottomEdge)) {
+ // None of the block fit. Push aLine and any other lines that follow
+ PushLines(aState);
+ aReflowResult = NS_INLINE_LINE_BREAK_BEFORE(reflowStatus);
+ return PR_FALSE;
+ }
+ aState.mPrevBottomMargin = metrics.posBottomMargin + childBottomMargin;
+ aLine->mInnerBottomMargin = metrics.posBottomMargin;
+ aLine->mOuterBottomMargin = childBottomMargin;
+ }
+
+ // Update max-element-size
+ if (aState.mComputeMaxElementSize) {
+ if (kidMaxElementSize.width > aState.mMaxElementSize.width) {
+ aState.mMaxElementSize.width = kidMaxElementSize.width;
+ }
+ if (kidMaxElementSize.height > aState.mMaxElementSize.height) {
+ aState.mMaxElementSize.height = kidMaxElementSize.height;
+ }
+ }
+
+ // Save away bounds before other adjustments
+ aLine->mBounds.x = x;
+ aLine->mBounds.y = y;
+ aLine->mBounds.width = metrics.width;
+ aLine->mBounds.height = metrics.height;
+ nscoord xmost = aLine->mBounds.XMost();
+NS_ASSERTION(xmost < 1000000, "bad line width");
+ if (xmost > aState.mKidXMost) {
+ aState.mKidXMost = xmost;
+ }
+
+ // Place child then align it and relatively position it
+ aFrame->SetRect(aLine->mBounds);
+ aState.mY = newY;
+ if (!aState.mUnconstrainedWidth) {
+ nsCSSLayout::HorizontallyPlaceChildren(aState.mPresContext,
+ aState.mBlock,
+ aState.mTextAlign,
+ aState.mDirection,
+ aFrame, 1,
+ metrics.width,
+ availSize.width);
+ }
+ nsCSSLayout::RelativePositionChildren(aState.mPresContext,
+ aState.mBlock,
+ aFrame, 1);
+ aState.mPrevChild = aFrame;
+
+ // Refresh our available space in case a floater was placed by our
+ // child.
+ // XXX expensive!
+ aState.GetAvailableSpace();
+
+ if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus)) {
+ // Some of the block fit. We need to have the block frame
+ // continued, so we make sure that it has a next-in-flow now.
+ nsIFrame* nextInFlow;
+ rv = aState.mInlineLayout.MaybeCreateNextInFlow(aFrame, nextInFlow);
+ if (NS_OK != rv) {
+ aReflowResult = nsInlineReflowStatus(rv);
+ return PR_FALSE;
+ }
+ if (nsnull != nextInFlow) {
+ // We made a next-in-flow for the block child frame. Create a
+ // line to map the block childs next-in-flow.
+ LineData* line = new LineData(nextInFlow, 1,
+ (LINE_IS_BLOCK |
+ LINE_LAST_CONTENT_IS_COMPLETE));
+ if (nsnull == line) {
+ aReflowResult = nsInlineReflowStatus(NS_ERROR_OUT_OF_MEMORY);
+ return PR_FALSE;
+ }
+ line->mNext = aLine->mNext;
+ aLine->mNext = line;
+ }
+
+ // Advance mPrevLine because we are keeping aLine (since some of
+ // the child block frame fit). Then push any remaining lines to
+ // our next-in-flow
+ aState.mPrevLine = aLine;
+ if (nsnull != aLine->mNext) {
+ PushLines(aState);
+ }
+ aReflowResult = NS_INLINE_LINE_BREAK_AFTER(reflowStatus);
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
+PRBool
+nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsIFrame* aFrame,
+ nsInlineReflowStatus& aReflowResult)
+{
+ if (!aState.mInlineLayoutPrepared) {
+ nscoord x = aState.mCurrentBand.availSpace.x;
+ nscoord width = aState.mCurrentBand.availSpace.width;
+ if (0 != aState.mBulletPadding) {
+ if (x == aState.mX) {
+ x += aState.mBulletPadding;
+ width -= aState.mBulletPadding;
+ }
+ }
+
+ aState.mLineLayout.Prepare(x);
+ aState.mInlineLayout.Prepare(aState.mUnconstrainedWidth, aState.mNoWrap,
+ aState.mComputeMaxElementSize);
+ aState.mInlineLayout.SetReflowSpace(x, aState.mY,
+ width,
+ aState.mCurrentBand.availSpace.height);
+ // If we we are a list-item container and we are positioning the
+ // first child on the line (which is true when !mInlineLayoutPrepared)
+ // and it's the first line, and we are not a continuation, then
+ // set the mIsBullet flag for the line layout code.
+ if (aState.mLineLayout.mListPositionOutside &&
+ (0 == aState.mLineLayout.mLineNumber) &&
+ (nsnull == mPrevInFlow)) {
+ aState.mInlineLayout.mIsBullet = PR_TRUE;
+ aState.mInlineLayout.mHaveBullet = PR_TRUE;
+ }
+ aState.mInlineLayoutPrepared = PR_TRUE;
+ }
+
+ nsresult rv;
+ nsIFrame* nextInFlow;
+ aReflowResult = aState.mInlineLayout.ReflowAndPlaceFrame(aFrame);
+ aState.mInlineLayout.mIsBullet = PR_FALSE;
+ if (NS_IS_REFLOW_ERROR(aReflowResult)) {
+ return PR_FALSE;
+ }
+
+ PRBool lineWasComplete = aLine->GetLastContentIsComplete();
+ if (!NS_INLINE_IS_BREAK(aReflowResult)) {
+ aState.mPrevChild = aFrame;
+ if (NS_FRAME_IS_COMPLETE(aReflowResult)) {
+ aFrame->GetNextSibling(aFrame);
+ aLine->SetLastContentIsComplete();
+ return PR_TRUE;
+ }
+
+ // Create continuation frame (if necessary); add it to the end of
+ // the current line so that it can be pushed to the next line
+ // properly.
+ aLine->ClearLastContentIsComplete();
+ rv = aState.mInlineLayout.MaybeCreateNextInFlow(aFrame, nextInFlow);
+ if (NS_OK != rv) {
+ aReflowResult = nsInlineReflowStatus(rv);
+ return PR_FALSE;
+ }
+ if (nsnull != nextInFlow) {
+ // Add new child to the line
+ aLine->mChildCount++;
+ }
+ aFrame->GetNextSibling(aFrame);
+ }
+ else {
+ if (NS_INLINE_IS_BREAK_AFTER(aReflowResult)) {
+ aState.mPrevChild = aFrame;
+ if (NS_FRAME_IS_COMPLETE(aReflowResult)) {
+ aLine->SetLastContentIsComplete();
+ }
+ else {
+ // Create continuation frame (if necessary); add it to the end of
+ // the current line so that it can be pushed to the next line
+ // properly.
+ aLine->ClearLastContentIsComplete();
+ rv = aState.mInlineLayout.MaybeCreateNextInFlow(aFrame, nextInFlow);
+ if (NS_OK != rv) {
+ aReflowResult = nsInlineReflowStatus(rv);
+ return PR_FALSE;
+ }
+ if (nsnull != nextInFlow) {
+ // Add new child to the line
+ aLine->mChildCount++;
+ }
+ }
+ aFrame->GetNextSibling(aFrame);
+ }
+ else {
+ NS_ASSERTION(aLine->GetLastContentIsComplete(), "bad mState");
+ }
+ }
+
+ // Split line since we aren't going to keep going
+ rv = SplitLine(aState, aLine, aFrame, lineWasComplete);
+ if (NS_IS_REFLOW_ERROR(rv)) {
+ aReflowResult = nsInlineReflowStatus(rv);
+ }
+ return PR_FALSE;
+}
+
+// XXX alloc lines using free-list in aState
+
+// XXX refactor this since the split NEVER has to deal with blocks
+
+nsresult
+nsBlockFrame::SplitLine(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsIFrame* aFrame,
+ PRBool aLineWasComplete)
+{
+ PRInt32 pushCount = aLine->mChildCount - aState.mInlineLayout.mFrameNum;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::SplitLine: pushing %d frames",
+ pushCount));
+ if (0 != pushCount) {
+ NS_ASSERTION(nsnull != aFrame, "whoops");
+ LineData* to = aLine->mNext;
+ if (nsnull != to) {
+ // Only push into the next line if it's empty; otherwise we can
+ // end up pushing a frame which is continued into the same frame
+ // as it's continuation. This causes all sorts of bad side
+ // effects so we don't allow it.
+ if (to->mChildCount != 0) {
+ LineData* insertedLine = new LineData(aFrame, pushCount, 0);
+ aLine->mNext = insertedLine;
+ insertedLine->mNext = to;
+ to = insertedLine;
+ } else {
+ to->mFirstChild = aFrame;
+ to->mChildCount += pushCount;
+ }
+ } else {
+ to = new LineData(aFrame, pushCount, 0);
+ aLine->mNext = to;
+ }
+ if (nsnull == to) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ to->SetLastContentIsComplete(aLineWasComplete);
+ aLine->mChildCount -= pushCount;
+#ifdef NS_DEBUG
+ if (GetVerifyTreeEnable()) {
+ aLine->Verify();
+ }
+#endif
+ NS_ASSERTION(0 != aLine->mChildCount, "bad push");
+ }
+ return NS_OK;
+}
+
+PRBool
+nsBlockFrame::PullFrame(nsBlockReflowState& aState,
+ LineData* aLine,
+ LineData** aFromList,
+ PRBool aUpdateGeometricParent,
+ nsInlineReflowStatus& aReflowResult)
+{
+ LineData* fromLine = *aFromList;
+ NS_ASSERTION(nsnull != fromLine, "bad line to pull from");
+ if (0 == fromLine->mChildCount) {
+ // Discard empty lines immediately. Empty lines can happen here
+ // because of DeleteChildsNextInFlow not being able to delete
+ // lines.
+ *aFromList = fromLine->mNext;
+ NS_ASSERTION(nsnull == fromLine->mFirstChild, "bad empty line");
+ fromLine->mNext = aState.mFreeList;
+ aState.mFreeList = fromLine;
+ return PR_TRUE;
+ }
+
+ // If our line is not empty and the child in aFromLine is a block
+ // then we cannot pull up the frame into this line.
+ if ((0 != aLine->mChildCount) && fromLine->IsBlock()) {
+ aReflowResult = NS_INLINE_LINE_BREAK_BEFORE(0);
+ return PR_FALSE;
+ }
+
+ // Take frame from fromLine
+ nsIFrame* frame = fromLine->mFirstChild;
+ if (0 == aLine->mChildCount++) {
+ aLine->mFirstChild = frame;
+ aLine->SetIsBlock(fromLine->IsBlock());
+#ifdef NS_DEBUG
+ const nsStyleDisplay* display;
+ frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&) display);
+ const nsStylePosition* position;
+ frame->GetStyleData(eStyleStruct_Position,
+ (const nsStyleStruct*&) position);
+ PRBool isBlock = nsLineLayout::TreatFrameAsBlock(display, position);
+ NS_ASSERTION(isBlock == aLine->IsBlock(), "bad line isBlock");
+#endif
+ }
+ if (0 != --fromLine->mChildCount) {
+ frame->GetNextSibling(fromLine->mFirstChild);
+ }
+ else {
+ // Free up the fromLine now that it's empty
+ *aFromList = fromLine->mNext;
+ fromLine->mFirstChild = nsnull;
+ fromLine->mNext = aState.mFreeList;
+ aState.mFreeList = fromLine;
+ }
+
+ // Change geometric parents
+ if (aUpdateGeometricParent) {
+ nsIFrame* geometricParent;
+ nsIFrame* contentParent;
+ frame->GetGeometricParent(geometricParent);
+ frame->GetContentParent(contentParent);
+ if (contentParent == geometricParent) {
+ frame->SetContentParent(this);
+ }
+ frame->SetGeometricParent(this);
+
+ // The frame is being pulled from a next-in-flow; therefore we
+ // need to add it to our sibling list.
+ if (nsnull != aState.mPrevChild) {
+ aState.mPrevChild->SetNextSibling(frame);
+ }
+ frame->SetNextSibling(nsnull);
+ }
+
+ // Reflow the frame
+ if (aLine->IsBlock()) {
+ return ReflowBlockFrame(aState, aLine, frame, aReflowResult);
+ }
+ else {
+ return ReflowInlineFrame(aState, aLine, frame, aReflowResult);
+ }
+}
+
+PRBool
+nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsInlineReflowStatus aReflowStatus)
+{
+ // Align the children. This also determines the actual height and
+ // width of the line.
+ aState.mInlineLayout.AlignFrames(aLine->mFirstChild, aLine->mChildCount,
+ aLine->mBounds);
+
+ // See if the line fit. If it doesn't we need to push it. Our first
+ // line will always fit.
+
+ // XXX This is a good place to check and see if we have
+ // below-current-line floaters, and if we do make sure that they fit
+ // too.
+ nscoord newY = aState.mY + aLine->mBounds.height;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockFrame::PlaceLine: newY=%d limit=%d lineHeight=%d",
+ newY, aState.mBottomEdge, aLine->mBounds.height));
+ if ((mLines != aLine) && (newY > aState.mBottomEdge)) {
+ // Push this line and all of it's children and anything else that
+ // follows to our next-in-flow
+ PushLines(aState);
+ return PR_FALSE;
+ }
+
+ if (aLine->mBounds.height > 0) {
+ aState.mPrevBottomMargin = 0;
+ }
+
+ // Update max-element-size
+ if (aState.mComputeMaxElementSize) {
+ nsSize& lineMaxElementSize = aState.mInlineLayout.mMaxElementSize;
+ if (lineMaxElementSize.width > aState.mMaxElementSize.width) {
+ aState.mMaxElementSize.width = lineMaxElementSize.width;
+ }
+ if (lineMaxElementSize.height > aState.mMaxElementSize.height) {
+ aState.mMaxElementSize.height = lineMaxElementSize.height;
+ }
+ }
+
+ nscoord xmost = aLine->mBounds.XMost();
+NS_ASSERTION(xmost < 1000000, "bad line width");
+ if (xmost > aState.mKidXMost) {
+ aState.mKidXMost = xmost;
+ }
+ aState.mY = newY;
+
+ // Any below current line floaters to place?
+ if (0 != aState.mPendingFloaters.Count()) {
+ aState.PlaceFloaters(&aState.mPendingFloaters);
+ aState.mPendingFloaters.Clear();
+
+ // XXX Factor in the height of the floaters as well when considering
+ // whether the line fits.
+ // The default policy is that if there isn't room for the floaters then
+ // both the line and the floaters are pushed to the next-in-flow...
+ }
+
+ // Based on the last child we reflowed reflow status, we may need to
+ // clear past any floaters.
+ if (NS_INLINE_IS_BREAK_AFTER(aReflowStatus)) {
+ // Apply break to the line
+ PRUint8 breakType = NS_INLINE_GET_BREAK_TYPE(aReflowStatus);
+ switch (breakType) {
+ default:
+ break;
+ case NS_STYLE_CLEAR_LEFT:
+ case NS_STYLE_CLEAR_RIGHT:
+ case NS_STYLE_CLEAR_LEFT_AND_RIGHT:
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::PlaceLine: clearing floaters=%d",
+ breakType));
+ aState.ClearFloaters(breakType);
+ break;
+ }
+ // XXX page breaks, etc, need to be passed upwards too!
+ }
+
+// if (aState.mY >= aState.mCurrentBand.availSpace.YMost()) {
+ // The current y coordinate is now past our available space
+ // rectangle. Get a new band of space.
+ aState.GetAvailableSpace();
+// }
+ return PR_TRUE;
+}
+
+static nsresult
+FindFloatersIn(nsIFrame* aFrame, nsVoidArray*& aArray)
+{
+ const nsStyleDisplay* display;
+ aFrame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&) display);
+ if (NS_STYLE_FLOAT_NONE != display->mFloats) {
+ if (nsnull == aArray) {
+ aArray = new nsVoidArray();
+ if (nsnull == aArray) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ aArray->AppendElement(aFrame);
+ }
+
+ if (NS_STYLE_DISPLAY_INLINE == display->mDisplay) {
+ nsIFrame* kid;
+ aFrame->FirstChild(kid);
+ while (nsnull != kid) {
+ nsresult rv = FindFloatersIn(kid, aArray);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ kid->GetNextSibling(kid);
+ }
+ }
+ return NS_OK;
+}
+
+void
+nsBlockFrame::FindFloaters(LineData* aLine)
+{
+ nsVoidArray* floaters = aLine->mFloaters;
+ if (nsnull != floaters) {
+ // Empty floater array before proceeding
+ floaters->Clear();
+ }
+
+ nsIFrame* frame = aLine->mFirstChild;
+ PRInt32 n = aLine->mChildCount;
+ while (--n >= 0) {
+ FindFloatersIn(frame, floaters);
+ frame->GetNextSibling(frame);
+ }
+
+ aLine->mFloaters = floaters;
+
+#if XXX
+ if ((mLines == aLine) && (nsnull != mRunInFloaters) &&
+ (nsnull != floaters)) {
+ // Special check for the first line: remove any floaters that are
+ // "current line" floaters (they musn't show up in the lines
+ // floater array)
+ PRInt32 i;
+ n = mRunInFloaters->Count();
+ for (i = 0; i < n; i++) {
+ PRInt32 ix = floaters->IndexOf(mRunInFloaters->ElementAt(i));
+ if (ix >= 0) {
+ floaters->RemoveElementAt(ix);
+ }
+ }
+ }
+#endif
+
+ // Get rid of floater array if we don't need it
+ if (nsnull != floaters) {
+ if (0 == floaters->Count()) {
+ delete floaters;
+ aLine->mFloaters = nsnull;
+ }
+ }
+}
+
+void
+nsBlockFrame::PushLines(nsBlockReflowState& aState)
+{
+ NS_ASSERTION(nsnull != aState.mPrevLine, "bad push");
+
+ LineData* lastLine = aState.mPrevLine;
+ LineData* nextLine = lastLine->mNext;
+
+ lastLine->mNext = nsnull;
+ mOverflowLines = nextLine;
+
+ // Break frame sibling list
+ nsIFrame* lastFrame = lastLine->LastChild();
+ lastFrame->SetNextSibling(nsnull);
+
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::PushLines: line=%p prevInFlow=%p nextInFlow=%p",
+ mOverflowLines, mPrevInFlow, mNextInFlow));
+#ifdef NS_DEBUG
+ if (GetVerifyTreeEnable()) {
+ VerifyChildCount(mLines);
+ VerifyChildCount(mOverflowLines, PR_TRUE);
+ }
+#endif
+}
+
+PRBool
+nsBlockFrame::DrainOverflowLines()
+{
+ PRBool drained = PR_FALSE;
+
+ // First grab the prev-in-flows overflow lines
+ nsBlockFrame* prevBlock = (nsBlockFrame*) mPrevInFlow;
+ if (nsnull != prevBlock) {
+ LineData* line = prevBlock->mOverflowLines;
+ if (nsnull != line) {
+ drained = PR_TRUE;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::DrainOverflowLines: line=%p prevInFlow=%p",
+ line, prevBlock));
+ prevBlock->mOverflowLines = nsnull;
+
+ // Make all the frames on the mOverflowLines list mine
+ nsIFrame* lastFrame = nsnull;
+ nsIFrame* frame = line->mFirstChild;
+ while (nsnull != frame) {
+ nsIFrame* geometricParent;
+ nsIFrame* contentParent;
+ frame->GetGeometricParent(geometricParent);
+ frame->GetContentParent(contentParent);
+ if (contentParent == geometricParent) {
+ frame->SetContentParent(this);
+ }
+ frame->SetGeometricParent(this);
+ lastFrame = frame;
+ frame->GetNextSibling(frame);
+ }
+
+ // Join the line lists
+ if (nsnull == mLines) {
+ mLines = line;
+ }
+ else {
+ // Join the sibling lists together
+ lastFrame->SetNextSibling(mLines->mFirstChild);
+
+ // Place overflow lines at the front of our line list
+ LineData* lastLine = LastLine(line);
+ lastLine->mNext = mLines;
+ mLines = line;
+ }
+
+ // Update our first-content-index now that we have a new first child
+ mLines->mFirstChild->GetContentIndex(mFirstContentOffset);
+ }
+ }
+
+ // Now grab our own overflow lines
+ if (nsnull != mOverflowLines) {
+ // This can happen when we reflow and not everything fits and then
+ // we are told to reflow again before a next-in-flow is created
+ // and reflows.
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::DrainOverflowLines: from me, line=%p",
+ mOverflowLines));
+ LineData* lastLine = LastLine(mLines);
+ if (nsnull == lastLine) {
+ mLines = mOverflowLines;
+ // Update our first-content-index now that we have a new first child
+ mLines->mFirstChild->GetContentIndex(mFirstContentOffset);
+ }
+ else {
+ lastLine->mNext = mOverflowLines;
+ nsIFrame* lastFrame = lastLine->LastChild();
+ lastFrame->SetNextSibling(mOverflowLines->mFirstChild);
+
+ // Update our last-content-index now that we have a new last child
+ lastLine = LastLine(mOverflowLines);
+ lastLine->LastChild()->GetContentIndex(mLastContentOffset);
+ }
+ mOverflowLines = nsnull;
+ drained = PR_TRUE;
+ }
+
+#ifdef NS_DEBUG
+ if (GetVerifyTreeEnable()) {
+ VerifyChildCount(mLines, PR_TRUE);
+ }
+#endif
+ return drained;
+}
+
+// XXX CONSTRUCTION
+#if 0
+// XXX a copy of nsHTMLContainerFrame's
+NS_IMETHODIMP
+nsBlockFrame::ContentAppended(nsIPresShell* aShell,
+ nsIPresContext* aPresContext,
+ nsIContent* aContainer)
+{
+ // Get the last-in-flow
+ nsBlockFrame* lastInFlow = (nsBlockFrame*)GetLastInFlow();
+
+ // Generate a reflow command for the frame
+ nsIReflowCommand* cmd;
+ nsresult result;
+
+ result = NS_NewHTMLReflowCommand(&cmd, lastInFlow,
+ nsIReflowCommand::FrameAppended);
+ if (NS_OK == result) {
+ aShell->AppendReflowCommand(cmd);
+ NS_RELEASE(cmd);
+ }
+
+ return NS_OK;
+}
+#endif
+
+nsresult
+nsBlockFrame::InsertNewFrame(nsBlockFrame* aParentFrame,
+ nsIFrame* aNewFrame,
+ nsIFrame* aPrevSibling)
+{
+ const nsStyleDisplay* display;
+ aNewFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
+ const nsStylePosition* position;
+ aNewFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&) position);
+ PRUint16 newFrameIsBlock = nsLineLayout::TreatFrameAsBlock(display, position)
+ ? LINE_IS_BLOCK : 0;
+
+ // Insert/append the frame into flows line list at the right spot
+ LineData* newLine;
+ LineData* line = aParentFrame->mLines;
+ if (nsnull == aPrevSibling) {
+ // Insert new frame into the sibling list
+ aNewFrame->SetNextSibling(line->mFirstChild);
+
+ if (line->IsBlock() || newFrameIsBlock) {
+ // Create a new line
+ newLine = new LineData(aNewFrame, 1, LINE_LAST_CONTENT_IS_COMPLETE |
+ newFrameIsBlock);
+ if (nsnull == newLine) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ newLine->mNext = aParentFrame->mLines;
+ aParentFrame->mLines = newLine;
+ } else {
+ // Insert frame at the front of the line
+ line->mFirstChild = aNewFrame;
+ line->mChildCount++;
+ line->MarkDirty();
+ }
+ }
+ else {
+ // Find line containing the previous sibling to the new frame
+ line = FindLineContaining(line, aPrevSibling);
+ NS_ASSERTION(nsnull != line, "no line contains the previous sibling");
+ if (nsnull != line) {
+ if (line->IsBlock()) {
+ // Create a new line just after line
+ newLine = new LineData(aNewFrame, 1, LINE_LAST_CONTENT_IS_COMPLETE |
+ newFrameIsBlock);
+ if (nsnull == newLine) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ newLine->mNext = line->mNext;
+ line->mNext = newLine;
+ }
+ else if (newFrameIsBlock) {
+ // Split line in two, if necessary. We can't allow a block to
+ // end up in an inline line.
+ if (line->IsLastChild(aPrevSibling)) {
+ // The new frame goes after prevSibling and prevSibling is
+ // the last frame on the line. Therefore we don't need to
+ // split the line, just create a new line.
+ newLine = new LineData(aNewFrame, 1, LINE_LAST_CONTENT_IS_COMPLETE |
+ newFrameIsBlock);
+ if (nsnull == newLine) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ newLine->mNext = line->mNext;
+ line->mNext = newLine;
+ }
+ else {
+ // The new frame goes after prevSibling and prevSibling is
+ // somewhere in the line, but not at the end. Split the line
+ // just after prevSibling.
+ PRInt32 i, n = line->mChildCount;
+ nsIFrame* frame = line->mFirstChild;
+ for (i = 0; i < n; i++) {
+ if (frame == aPrevSibling) {
+ nsIFrame* nextSibling;
+ aPrevSibling->GetNextSibling(nextSibling);
+
+ // Create new line to hold the remaining frames
+ NS_ASSERTION(n - i - 1 > 0, "bad line count");
+ newLine = new LineData(nextSibling, n - i - 1,
+ line->mState & LINE_LAST_CONTENT_IS_COMPLETE);
+ if (nsnull == newLine) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ newLine->mNext = line->mNext;
+ line->mNext = newLine;
+ line->MarkDirty();
+ line->SetLastContentIsComplete();
+ line->mChildCount = i + 1;
+ break;
+ }
+ frame->GetNextSibling(frame);
+ }
+
+ // Now create a new line to hold the block
+ newLine = new LineData(aNewFrame, 1,
+ newFrameIsBlock | LINE_LAST_CONTENT_IS_COMPLETE);
+ if (nsnull == newLine) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ newLine->mNext = line->mNext;
+ line->mNext = newLine;
+ }
+ }
+ else {
+ // Insert frame into the line.
+ // NS_ASSERTION(line->GetLastContentIsComplete(), "bad line LCIC");
+ line->mChildCount++;
+ line->MarkDirty();
+ }
+ }
+
+ // Insert new frame into the sibling list; note: this must be done
+ // after the above logic because the above logic depends on the
+ // sibling list being in the "before insertion" state.
+ nsIFrame* nextSibling;
+ aPrevSibling->GetNextSibling(nextSibling);
+ aNewFrame->SetNextSibling(nextSibling);
+ aPrevSibling->SetNextSibling(aNewFrame);
+ }
+
+ return NS_OK;
+}
+
+// XXX we assume that the insertion is really an assertion and never an append
+// XXX what about zero lines case
+NS_IMETHODIMP
+nsBlockFrame::ContentInserted(nsIPresShell* aShell,
+ nsIPresContext* aPresContext,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ PRInt32 aIndexInParent)
+{
+ // Find the frame that precedes this frame
+ nsIFrame* prevSibling = nsnull;
+ if (aIndexInParent > 0) {
+ nsIContent* precedingContent;
+ aContainer->ChildAt(aIndexInParent - 1, precedingContent);
+ prevSibling = aShell->FindFrameWithContent(precedingContent);
+ NS_ASSERTION(nsnull != prevSibling, "no frame for preceding content");
+ NS_RELEASE(precedingContent);
+
+ // The frame may have a next-in-flow. Get the last-in-flow; we do
+ // it the hard way because we can't assume that prevSibling is a
+ // subclass of nsSplittableFrame.
+ nsIFrame* nextInFlow;
+ do {
+ prevSibling->GetNextInFlow(nextInFlow);
+ if (nsnull != nextInFlow) {
+ prevSibling = nextInFlow;
+ }
+ } while (nsnull != nextInFlow);
+ }
+
+ // Get the parent of the previous sibling (which will be the proper
+ // next-in-flow for the child). We expect it to be this frame or one
+ // of our next-in-flow(s).
+ nsBlockFrame* flow = this;
+ if (nsnull != prevSibling) {
+ prevSibling->GetGeometricParent((nsIFrame*&)flow);
+ }
+
+ // Now that we have the right flow block we can create the new
+ // frame; test and see if the inserted frame is a block or not.
+ // XXX create-frame could return that fact
+ nsIFrame* newFrame;
+ nsresult rv = nsHTMLBase::CreateFrame(aPresContext, flow, aChild,
+ nsnull, newFrame);
+ if (NS_OK != rv) {
+ return rv;
+ }
+
+ InsertNewFrame(flow, newFrame, prevSibling);
+
+ // Generate a reflow command
+ nsIReflowCommand* cmd;
+ rv = NS_NewHTMLReflowCommand(&cmd, flow, nsIReflowCommand::FrameInserted);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ aShell->AppendReflowCommand(cmd);
+ NS_RELEASE(cmd);
+
+ // Update the content offsets of the flow block and all that follow
+ PRBool pseudos = flow->IsPseudoFrame();
+ flow->mLastContentOffset++;
+ if (pseudos) {
+ nsContainerFrame* flowParent = (nsContainerFrame*)flow->mGeometricParent;
+ flowParent->PropagateContentOffsets(flow, flow->mFirstContentOffset,
+ flow->mLastContentOffset,
+ flow->mLastContentIsComplete);
+ }
+ flow = (nsBlockFrame*) flow->mNextInFlow;
+ while (nsnull != flow) {
+ flow->mFirstContentOffset++;
+ flow->mLastContentOffset++;
+ if (pseudos) {
+ nsContainerFrame* flowParent = (nsContainerFrame*)flow->mGeometricParent;
+ flowParent->PropagateContentOffsets(flow, flow->mFirstContentOffset,
+ flow->mLastContentOffset,
+ flow->mLastContentIsComplete);
+ }
+ flow = (nsBlockFrame*) flow->mNextInFlow;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::ContentDeleted(nsIPresShell* aShell,
+ nsIPresContext* aPresContext,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ PRInt32 aIndexInParent)
+{
+ // Find the frame that precedes the frame to destroy and the frame
+ // to destroy (the first-in-flow if the frame is continued). We also
+ // find which of our next-in-flows contain the dead frame.
+ nsBlockFrame* flow;
+ nsIFrame* deadFrame;
+ nsIFrame* prevSibling;
+ if (aIndexInParent > 0) {
+ nsIContent* precedingContent;
+ aContainer->ChildAt(aIndexInParent - 1, precedingContent);
+ prevSibling = aShell->FindFrameWithContent(precedingContent);
+ NS_RELEASE(precedingContent);
+
+ // The frame may have a next-in-flow. Get the last-in-flow; we do
+ // it the hard way because we can't assume that prevSibling is a
+ // subclass of nsSplittableFrame.
+ nsIFrame* nextInFlow;
+ do {
+ prevSibling->GetNextInFlow(nextInFlow);
+ if (nsnull != nextInFlow) {
+ prevSibling = nextInFlow;
+ }
+ } while (nsnull != nextInFlow);
+
+ // Get the dead frame (maybe)
+ prevSibling->GetGeometricParent((nsIFrame*&)flow);
+ prevSibling->GetNextSibling(deadFrame);
+ if (nsnull == deadFrame) {
+ // The deadFrame must be prevSibling's parent's next-in-flows
+ // first frame. Therefore it doesn't have a prevSibling.
+ flow = (nsBlockFrame*) flow->mNextInFlow;
+ if (nsnull != flow) {
+ deadFrame = flow->mLines->mFirstChild;
+ }
+ prevSibling = nsnull;
+ }
+ }
+ else {
+ prevSibling = nsnull;
+ flow = this;
+ deadFrame = mLines->mFirstChild;
+ }
+ NS_ASSERTION(nsnull != deadFrame, "yikes! couldn't find frame");
+ if (nsnull == deadFrame) {
+ return NS_OK;
+ }
+
+ // Generate a reflow command for the appropriate flow frame
+ nsIReflowCommand* cmd;
+ nsresult rv = NS_NewHTMLReflowCommand(&cmd, flow,
+ nsIReflowCommand::FrameDeleted);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ aShell->AppendReflowCommand(cmd);
+ NS_RELEASE(cmd);
+
+ // Find line that contains deadFrame; we also find the pointer to
+ // the line.
+ LineData** linep = &flow->mLines;
+ LineData* line = flow->mLines;
+ while (nsnull != line) {
+ if (line->Contains(deadFrame)) {
+ break;
+ }
+ linep = &line->mNext;
+ line = line->mNext;
+ }
+
+ // Remove frame and its continuations
+ PRBool pseudos = flow->IsPseudoFrame();
+ while (nsnull != deadFrame) {
+ while ((nsnull != line) && (nsnull != deadFrame)) {
+#ifdef NS_DEBUG
+ nsIFrame* parent;
+ deadFrame->GetGeometricParent(parent);
+ NS_ASSERTION(flow == parent, "messed up delete code");
+#endif
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockFrame::ContentDeleted: deadFrame=%p",
+ deadFrame));
+
+ // Remove deadFrame from the line
+ if (line->mFirstChild == deadFrame) {
+ nsIFrame* nextFrame;
+ deadFrame->GetNextSibling(nextFrame);
+ line->mFirstChild = nextFrame;
+ }
+ else {
+ nsIFrame* lastFrame = line->LastChild();
+ if (lastFrame == deadFrame) {
+ line->SetLastContentIsComplete();
+ }
+ }
+
+ // Take deadFrame out of the sibling list
+ if (nsnull != prevSibling) {
+ nsIFrame* nextFrame;
+ deadFrame->GetNextSibling(nextFrame);
+ prevSibling->SetNextSibling(nextFrame);
+ }
+
+ // Destroy frame; capture its next-in-flow first in case we need
+ // to destroy that too.
+ nsIFrame* nextInFlow;
+ deadFrame->GetNextInFlow(nextInFlow);
+ if (nsnull != nextInFlow) {
+ deadFrame->BreakFromNextFlow();
+ }
+ deadFrame->DeleteFrame(*aPresContext);
+ deadFrame = nextInFlow;
+
+ // If line is empty, remove it now
+ LineData* next = line->mNext;
+ if (0 == --line->mChildCount) {
+ *linep = next;
+ line->mNext = nsnull;
+ delete line;
+ }
+ else {
+ linep = &line->mNext;
+ }
+ line = next;
+ }
+
+ // Update flows last-content-offset. Note that only the last
+ // content needs updating when a deadFrame is removed from flow
+ // (because only the children that follow the deletion need
+ // renumbering).
+ flow->mLastContentOffset--;
+ if (pseudos) {
+ nsContainerFrame* parent = (nsContainerFrame*)flow->mGeometricParent;
+ parent->PropagateContentOffsets(flow, flow->mFirstContentOffset,
+ flow->mLastContentOffset,
+ flow->mLastContentIsComplete);
+#if XXX
+ if (parent != flowParent) {
+ nsIReflowCommand* cmd;
+ rv = NS_NewHTMLReflowCommand(&cmd, flow,
+ nsIReflowCommand::FrameDeleted);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ aShell->AppendReflowCommand(cmd);
+ NS_RELEASE(cmd);
+ }
+#endif
+ }
+
+ // Advance to next flow block if the frame has more continuations
+ if (nsnull != deadFrame) {
+ flow = (nsBlockFrame*) flow->mNextInFlow;
+ NS_ASSERTION(nsnull != flow, "whoops, continuation without a parent");
+ line = flow->mLines;
+ prevSibling = nsnull;
+ }
+ }
+
+ // Repair any remaining next-in-flows content offsets; these are the
+ // next-in-flows the follow the last flow container that contained
+ // one of the deadFrame's. Therefore both content offsets need
+ // updating (because all the children are following the deletion).
+ flow = (nsBlockFrame*) flow->mNextInFlow;
+ while (nsnull != flow) {
+ flow->mFirstContentOffset--;
+ flow->mLastContentOffset--;
+ flow = (nsBlockFrame*) flow->mNextInFlow;
+ }
+
+#ifdef NS_DEBUG
+ if (GetVerifyTreeEnable()) {
+ // Verify that the above delete code actually deleted the frames!
+ flow = this;
+ while (nsnull != flow) {
+ nsIFrame* frame = flow->mLines->mFirstChild;
+ while (nsnull != frame) {
+ nsIContent* content;
+ frame->GetContent(content);
+ NS_ASSERTION(content != aChild, "delete failed");
+ NS_RELEASE(content);
+ frame->GetNextSibling(frame);
+ }
+ flow = (nsBlockFrame*) flow->mNextInFlow;
+ }
+ }
+#endif
+
+ return rv;
+}
+
+PRBool
+nsBlockFrame::DeleteNextInFlowsFor(nsIPresContext& aPresContext, nsIFrame* aChild)
+{
+ NS_PRECONDITION(IsChild(aChild), "bad geometric parent");
+
+ nsIFrame* nextInFlow;
+ nsBlockFrame* parent;
+
+ aChild->GetNextInFlow(nextInFlow);
+ NS_PRECONDITION(nsnull != nextInFlow, "null next-in-flow");
+ nextInFlow->GetGeometricParent((nsIFrame*&)parent);
+
+ // If the next-in-flow has a next-in-flow then delete it, too (and
+ // delete it first).
+ nsIFrame* nextNextInFlow;
+ nextInFlow->GetNextInFlow(nextNextInFlow);
+ if (nsnull != nextNextInFlow) {
+ parent->DeleteNextInFlowsFor(aPresContext, nextInFlow);
+ }
+
+#ifdef NS_DEBUG
+ PRInt32 childCount;
+ nsIFrame* firstChild;
+ nextInFlow->ChildCount(childCount);
+ nextInFlow->FirstChild(firstChild);
+ NS_ASSERTION((0 == childCount) && (nsnull == firstChild),
+ "deleting !empty next-in-flow");
+#endif
+
+ // Disconnect the next-in-flow from the flow list
+ nextInFlow->BreakFromPrevFlow();
+
+ // Remove nextInFlow from the parents line list. Also remove it from
+ // the sibling list.
+ if (RemoveChild(parent->mLines, nextInFlow)) {
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::DeleteNextInFlowsFor: frame=%p (from mLines)",
+ nextInFlow));
+ goto done;
+ }
+
+ // If we get here then we didn't find the child on the line list. If
+ // it's not there then it has to be on the overflow lines list.
+ if (nsnull != mOverflowLines) {
+ if (RemoveChild(parent->mOverflowLines, nextInFlow)) {
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::DeleteNextInFlowsFor: frame=%p (from overflow)",
+ nextInFlow));
+ goto done;
+ }
+ }
+ NS_NOTREACHED("can't find next-in-flow in overflow list");
+
+ done:;
+ // If the parent is us then we will finish reflowing and update the
+ // content offsets of our parents when we are a pseudo-frame; if the
+ // parent is not us then it's a next-in-flow which means it will get
+ // reflowed by our parent and fix its content offsets. So there.
+#if XXX
+ if (parent->IsPseudoFrame()) {
+ parent->PropagateContentOffsets();
+ }
+#endif
+
+ // Delete the next-in-flow frame and adjust its parents child count
+ nextInFlow->DeleteFrame(aPresContext);
+
+#ifdef NS_DEBUG
+ aChild->GetNextInFlow(nextInFlow);
+ NS_POSTCONDITION(nsnull == nextInFlow, "non null next-in-flow");
+#endif
+ return PR_TRUE;
+}
+
+PRBool
+nsBlockFrame::RemoveChild(LineData* aLines, nsIFrame* aChild)
+{
+ LineData* line = aLines;
+ nsIFrame* prevChild = nsnull;
+ while (nsnull != line) {
+ nsIFrame* child = line->mFirstChild;
+ PRInt32 n = line->mChildCount;
+ while (--n >= 0) {
+ nsIFrame* nextChild;
+ child->GetNextSibling(nextChild);
+ if (child == aChild) {
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::RemoveChild: line=%p frame=%p",
+ line, aChild));
+ // Continuations HAVE to be at the start of a line
+ NS_ASSERTION(child == line->mFirstChild, "bad continuation");
+ line->mFirstChild = nextChild;
+ if (0 == --line->mChildCount) {
+ line->mFirstChild = nsnull;
+ }
+ if (nsnull != prevChild) {
+ // When nextInFlow and it's continuation are in the same
+ // container then we remove the nextInFlow from the sibling
+ // list.
+ prevChild->SetNextSibling(nextChild);
+ }
+ return PR_TRUE;
+ }
+ prevChild = child;
+ child = nextChild;
+ }
+ line = line->mNext;
+ }
+ return PR_FALSE;
+}
+
+#if 0
+NS_IMETHODIMP
+nsBlockFrame::DidReflow(nsIPresContext& aPresContext,
+ nsDidReflowStatus aStatus)
+{
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("enter nsBlockFrame::DidReflow: status=%d",
+ aStatus));
+
+ if (NS_FRAME_REFLOW_FINISHED == aStatus) {
+ LineData* line = mLines;
+ while (nsnull != line) {
+ // XXX This can't be done because we need to pass on DidReflow's
+ // to things that weren't touched but are moving (like an
+ // embedded view that needs to update its view coordinate)
+
+ // XXX We need a better solution!
+ if (line->NeedsDidReflow()) {
+ line->ClearNeedDidReflow();
+ nsIFrame* kid = line->mFirstChild;
+ PRInt32 n = line->mChildCount;
+ while (--n >= 0) {
+ kid->DidReflow(aPresContext, aStatus);
+ kid->GetNextSibling(kid);
+ }
+ }
+ line = line->mNext;
+ }
+ }
+
+ NS_FRAME_TRACE_OUT("nsBlockFrame::DidReflow");
+
+ // Let nsFrame position and size our view (if we have one), and clear
+ // the NS_FRAME_IN_REFLOW bit
+ return nsFrame::DidReflow(aPresContext, aStatus);
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////
+// Floater support
+
+void
+nsBlockFrame::ReflowFloater(nsIPresContext* aPresContext,
+ nsBlockReflowState& aState,
+ nsIFrame* aFloaterFrame)
+{
+ // Prepare the reflow state for the floater frame. Note that initially
+ // it's maxSize will be 0,0 until we compute it (we need the reflowState
+ // for nsLayout::GetStyleSize so we have to do this first)
+ nsSize kidAvailSize(0, 0);
+ nsReflowState reflowState(aFloaterFrame, aState, kidAvailSize,
+ eReflowReason_Initial);
+
+ // Compute the available space for the floater. Use the default
+ // 'auto' width and height values
+ nsSize styleSize;
+ PRIntn styleSizeFlags =
+ nsCSSLayout::GetStyleSize(aPresContext, reflowState, styleSize);
+
+ // XXX The width and height are for the content area only. Add in space for
+ // border and padding
+ if (styleSizeFlags & NS_SIZE_HAS_WIDTH) {
+ kidAvailSize.width = styleSize.width;
+ }
+ else {
+ // If we are floating something and we don't know the width then
+ // find a maximum width for it to reflow into.
+
+ // XXX if the child is a block (instead of a table, say) then this
+ // will do the wrong thing. A better choice would be
+ // NS_UNCONSTRAINEDSIZE, but that has special meaning to tables.
+ const nsReflowState* rsp = &aState;
+ kidAvailSize.width = 0;
+ while (nsnull != rsp) {
+ if ((0 != rsp->maxSize.width) &&
+ (NS_UNCONSTRAINEDSIZE != rsp->maxSize.width)) {
+ kidAvailSize.width = rsp->maxSize.width;
+ break;
+ }
+ rsp = rsp->parentReflowState;
+ }
+ NS_ASSERTION(0 != kidAvailSize.width, "no width for block found");
+ }
+ if (styleSizeFlags & NS_SIZE_HAS_HEIGHT) {
+ kidAvailSize.height = styleSize.height;
+ }
+ else {
+ kidAvailSize.height = NS_UNCONSTRAINEDSIZE;
+ }
+ reflowState.maxSize = kidAvailSize;
+
+ // Resize reflow the anchored item into the available space
+ // XXX Check for complete?
+ nsReflowMetrics desiredSize(nsnull);
+ nsReflowStatus status;
+ aFloaterFrame->WillReflow(*aPresContext);
+ aFloaterFrame->Reflow(*aPresContext, desiredSize, reflowState, status);
+ aFloaterFrame->SizeTo(desiredSize.width, desiredSize.height);
+}
+
+PRBool
+nsBlockFrame::AddFloater(nsIPresContext* aPresContext,
+ const nsReflowState& aReflowState,
+ nsIFrame* aFloater,
+ nsPlaceholderFrame* aPlaceholder)
+{
+ // Walk up reflow state chain, looking for ourself
+ const nsReflowState* rs = &aReflowState;
+ while (nsnull != rs) {
+ if (rs->frame == this) {
+ break;
+ }
+ rs = rs->parentReflowState;
+ }
+ if (nsnull == rs) {
+ // Never mind
+ return PR_FALSE;
+ }
+ nsBlockReflowState* state = (nsBlockReflowState*) rs;
+
+ // Get the frame associated with the space manager, and get its
+ // nsIAnchoredItems interface
+ nsIFrame* frame = state->mSpaceManager->GetFrame();
+ nsIAnchoredItems* anchoredItems = nsnull;
+
+ frame->QueryInterface(kIAnchoredItemsIID, (void**)&anchoredItems);
+ NS_ASSERTION(nsnull != anchoredItems, "no anchored items interface");
+ if (nsnull != anchoredItems) {
+ anchoredItems->AddAnchoredItem(aFloater,
+ nsIAnchoredItems::anHTMLFloater,
+ this);
+
+ // Reflow the floater (the first time we do it here; later on it's
+ // done during the reflow of the line that contains the floater)
+ ReflowFloater(aPresContext, *state, aFloater);
+
+#if XXX_remove_me
+ // Determine whether we place it at the top or we place it below the
+ // current line
+// if (IsLeftMostChild(aPlaceholder)) {
+// if (nsnull == mRunInFloaters) {
+// mRunInFloaters = new nsVoidArray;
+// }
+// mRunInFloaters->AppendElement(aPlaceholder);
+// state->PlaceCurrentLineFloater(aFloater);
+// }
+ else {
+ // Add the placeholder to our to-do list
+ state->mPendingFloaters.AppendElement(aPlaceholder);
+ }
+#endif
+ return PR_TRUE;
+ }
+
+ return PR_FALSE;
+}
+
+// This is called by the line layout's AddFloater method when a
+// place-holder frame is reflowed in a line. If the floater is a
+// left-most child (it's x coordinate is at the line's left margin)
+// then the floater is place immediately, otherwise the floater
+// placement is deferred until the line has been reflowed.
+void
+nsBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder)
+{
+ // Update the current line's floater array
+ NS_ASSERTION(nsnull != mCurrentLine, "null ptr");
+ if (nsnull == mCurrentLine->mFloaters) {
+ mCurrentLine->mFloaters = new nsVoidArray();
+ }
+ mCurrentLine->mFloaters->AppendElement(aPlaceholder);
+
+ // Now place the floater immediately if possible. Otherwise stash it
+ // away in mPendingFloaters and place it later.
+ if (IsLeftMostChild(aPlaceholder)) {
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::AddFloater: IsLeftMostChild, placeHolder=%p",
+ aPlaceholder));
+
+ // Because we are in the middle of reflowing a placeholder frame
+ // within a line (and possibly nested in an inline frame or two
+ // that's a child of our block) we need to restore the space
+ // manager's translation to the space that the block resides in
+ // before placing the floater.
+ nscoord ox, oy;
+ mSpaceManager->GetTranslation(ox, oy);
+ nscoord dx = ox - mSpaceManagerX;
+ nscoord dy = oy - mSpaceManagerY;
+ mSpaceManager->Translate(-dx, -dy);
+ PlaceFloater(aPlaceholder);
+
+ // Pass on updated available space to the current line
+ GetAvailableSpace();
+ mInlineLayout.SetReflowSpace(mCurrentBand.availSpace.x, mY,
+ mCurrentBand.availSpace.width,
+ mCurrentBand.availSpace.height);
+
+ // Restore coordinate system
+ mSpaceManager->Translate(dx, dy);
+ }
+ else {
+ // This floater will be placed after the line is done (it is a
+ // below current line floater).
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::AddFloater: pending, placeHolder=%p",
+ aPlaceholder));
+ mPendingFloaters.AppendElement(aPlaceholder);
+ }
+}
+
+// XXX Inline frame layout and block layout need to be more
+// coordinated; IsFirstChild in the inline code is doing much the same
+// thing as below; firstness should be well known.
+PRBool
+nsBlockReflowState::IsLeftMostChild(nsIFrame* aFrame)
+{
+ for (;;) {
+ nsIFrame* parent;
+ aFrame->GetGeometricParent(parent);
+ if (parent == mBlock) {
+ nsIFrame* child = mCurrentLine->mFirstChild;
+ PRInt32 n = mCurrentLine->mChildCount;
+ while ((nsnull != child) && (aFrame != child) && (--n >= 0)) {
+ nsSize size;
+
+ // Is the child zero-sized?
+ child->GetSize(size);
+ if (size.width > 0) {
+ // We found a non-zero sized child frame that precedes aFrame
+ return PR_FALSE;
+ }
+ child->GetNextSibling(child);
+ }
+ break;
+ }
+ else {
+ // See if there are any non-zero sized child frames that precede
+ // aFrame in the child list
+ nsIFrame* child;
+ parent->FirstChild(child);
+ while ((nsnull != child) && (aFrame != child)) {
+ nsSize size;
+
+ // Is the child zero-sized?
+ child->GetSize(size);
+ if (size.width > 0) {
+ // We found a non-zero sized child frame that precedes aFrame
+ return PR_FALSE;
+ }
+ child->GetNextSibling(child);
+ }
+ }
+
+ // aFrame is the left-most non-zero sized frame in its geometric parent.
+ // Walk up one level and check that its parent is left-most as well
+ aFrame = parent;
+ }
+ return PR_TRUE;
+}
+
+void
+nsBlockReflowState::PlaceFloater(nsPlaceholderFrame* aPlaceholder)
+{
+ nsISpaceManager* sm = mSpaceManager;
+ nsIFrame* floater = aPlaceholder->GetAnchoredItem();
+
+ // Remove floaters old placement from the space manager
+ sm->RemoveRegion(floater);
+
+ // Reflow the floater if it's targetted for a reflow
+ if (nsnull != reflowCommand) {
+ nsIFrame* target;
+ reflowCommand->GetTarget(target);
+ if (floater == target) {
+ mBlock->ReflowFloater(mPresContext, *this, floater);
+ }
+ }
+
+ // Get the band of available space
+ GetAvailableSpace();
+
+ // Get the type of floater
+ const nsStyleDisplay* floaterDisplay;
+ const nsStyleSpacing* floaterSpacing;
+ floater->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)floaterDisplay);
+ floater->GetStyleData(eStyleStruct_Spacing,
+ (const nsStyleStruct*&)floaterSpacing);
+
+ // Get the floaters bounding box and margin information
+ nsRect region;
+ floater->GetRect(region);
+ nsMargin floaterMargin;
+ floaterSpacing->CalcMarginFor(floater, floaterMargin);
+
+ // Compute the size of the region that will impact the space manager
+ region.y = mY;
+ switch (floaterDisplay->mFloats) {
+ default:
+ NS_NOTYETIMPLEMENTED("Unsupported floater type");
+ // FALL THROUGH
+
+ case NS_STYLE_FLOAT_LEFT:
+ region.x = mCurrentBand.availSpace.x;
+ region.width += mBulletPadding;
+ break;
+
+ case NS_STYLE_FLOAT_RIGHT:
+ region.x = mCurrentBand.availSpace.XMost() - region.width;
+ region.x -= floaterMargin.right;
+ if (region.x < 0) {
+ region.x = 0;
+ }
+ }
+
+ // Factor in the floaters margins
+ region.width += floaterMargin.left + floaterMargin.right;
+ region.height += floaterMargin.top + floaterMargin.bottom;
+ sm->AddRectRegion(floater, region);
+
+ // Set the origin of the floater in world coordinates
+ nscoord worldX = mSpaceManagerX;
+ nscoord worldY = mSpaceManagerY;
+ if (NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats) {
+ floater->MoveTo(region.x + worldX + floaterMargin.left,
+ region.y + worldY + floaterMargin.top);
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::PlaceFloater: right, placeHolder=%p xy=%d,%d worldxy=%d,%d",
+ aPlaceholder, region.x + worldX + floaterMargin.left,
+ region.y + worldY + floaterMargin.top,
+ worldX, worldY));
+ }
+ else {
+ floater->MoveTo(region.x + worldX + floaterMargin.left + mBulletPadding,
+ region.y + worldY + floaterMargin.top);
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::PlaceFloater: left, placeHolder=%p xy=%d,%d worldxy=%d,%d",
+ aPlaceholder, region.x + worldX + floaterMargin.left + mBulletPadding,
+ region.y + worldY + floaterMargin.top,
+ worldX, worldY));
+ }
+}
+
+void
+nsBlockReflowState::PlaceFloaters(nsVoidArray* aFloaters)
+{
+ NS_PRECONDITION(aFloaters->Count() > 0, "no floaters");
+
+ PRInt32 numFloaters = aFloaters->Count();
+ for (PRInt32 i = 0; i < numFloaters; i++) {
+ nsPlaceholderFrame* placeholderFrame = (nsPlaceholderFrame*)
+ aFloaters->ElementAt(i);
+ if (IsLeftMostChild(placeholderFrame)) {
+ // Left-most children are placed during the line's reflow
+ continue;
+ }
+ PlaceFloater(placeholderFrame);
+ }
+
+ // Pass on updated available space to the current line
+ GetAvailableSpace();
+ mInlineLayout.SetReflowSpace(mCurrentBand.availSpace.x, mY,
+ mCurrentBand.availSpace.width,
+ mCurrentBand.availSpace.height);
+}
+
+void
+nsBlockReflowState::ClearFloaters(PRUint8 aBreakType)
+{
+ for (;;) {
+ PRBool haveFloater = PR_FALSE;
+ // Find the Y coordinate to clear to. Note that the band trapezoid
+ // coordinates are relative to the last translation. Since we
+ // never translate by Y before getting a band, we can use absolute
+ // comparisons against mY.
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: mY=%d trapCount=%d",
+ mY, mCurrentBand.count));
+ nscoord clearYMost = mY;
+ nsRect tmp;
+ PRInt32 i;
+ for (i = 0; i < mCurrentBand.count; i++) {
+ const nsStyleDisplay* display;
+ nsBandTrapezoid* trapezoid = &mCurrentBand.data[i];
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: trap=%d state=%d",
+ i, trapezoid->state));
+ if (nsBandTrapezoid::Available != trapezoid->state) {
+ haveFloater = PR_TRUE;
+ if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
+ PRInt32 fn, numFrames = trapezoid->frames->Count();
+ NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
+ for (fn = 0; fn < numFrames; fn++) {
+ nsIFrame* frame = (nsIFrame*) trapezoid->frames->ElementAt(fn);
+ frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)display);
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: frame[%d]=%p floats=%d",
+ fn, frame, display->mFloats));
+ switch (display->mFloats) {
+ case NS_STYLE_FLOAT_LEFT:
+ if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
+ (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
+ trapezoid->GetRect(tmp);
+ nscoord ym = tmp.YMost();
+ if (ym > clearYMost) {
+ clearYMost = ym;
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: left clearYMost=%d",
+ clearYMost));
+ }
+ }
+ break;
+ case NS_STYLE_FLOAT_RIGHT:
+ if ((NS_STYLE_CLEAR_RIGHT == aBreakType) ||
+ (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
+ trapezoid->GetRect(tmp);
+ nscoord ym = tmp.YMost();
+ if (ym > clearYMost) {
+ clearYMost = ym;
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: right clearYMost=%d",
+ clearYMost));
+ }
+ }
+ break;
+ }
+ }
+ }
+ else {
+ trapezoid->frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)display);
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: frame=%p floats=%d",
+ trapezoid->frame, display->mFloats));
+ switch (display->mFloats) {
+ case NS_STYLE_FLOAT_LEFT:
+ if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
+ (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
+ trapezoid->GetRect(tmp);
+ nscoord ym = tmp.YMost();
+NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: left? ym=%d clearYMost=%d",
+ ym, clearYMost));
+ if (ym > clearYMost) {
+ clearYMost = ym;
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: left clearYMost=%d",
+ clearYMost));
+ }
+ }
+ break;
+ case NS_STYLE_FLOAT_RIGHT:
+ if ((NS_STYLE_CLEAR_RIGHT == aBreakType) ||
+ (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
+ trapezoid->GetRect(tmp);
+ nscoord ym = tmp.YMost();
+ if (ym > clearYMost) {
+ clearYMost = ym;
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: right clearYMost=%d",
+ clearYMost));
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ if (!haveFloater) {
+ break;
+ }
+
+ if (clearYMost == mY) {
+ // Nothing to clear
+ break;
+ }
+
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: mY=%d clearYMost=%d",
+ mY, clearYMost));
+
+ mY = clearYMost + 1;
+
+ // Get a new band
+ GetAvailableSpace();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+// Painting, event handling
+
+PRIntn
+nsBlockFrame::GetSkipSides() const
+{
+ PRIntn skip = 0;
+ if (nsnull != mPrevInFlow) {
+ skip |= 1 << NS_SIDE_TOP;
+ }
+ if (nsnull != mNextInFlow) {
+ skip |= 1 << NS_SIDE_BOTTOM;
+ }
+ return skip;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::Paint(nsIPresContext& aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect)
+{
+ // Paint our background and border
+ const nsStyleDisplay* disp =
+ (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display);
+
+ if (disp->mVisible && mRect.width && mRect.height) {
+ PRIntn skipSides = GetSkipSides();
+ const nsStyleColor* color =
+ (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color);
+ const nsStyleSpacing* spacing =
+ (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
+
+ nsRect rect(0, 0, mRect.width, mRect.height);
+ nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
+ aDirtyRect, rect, *color);
+ nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
+ aDirtyRect, rect, *spacing, skipSides);
+ }
+
+ PaintChildren(aPresContext, aRenderingContext, aDirtyRect);
+
+ if (nsIFrame::GetShowFrameBorders()) {
+ nsIView* view;
+ GetView(view);
+ if (nsnull != view) {
+ aRenderingContext.SetColor(NS_RGB(0,0,255));
+ }
+ else {
+ aRenderingContext.SetColor(NS_RGB(255,0,0));
+ }
+ aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height);
+ }
+ return NS_OK;
+}
+
+// aDirtyRect is in our coordinate system
+// child rect's are also in our coordinate system
+void
+nsBlockFrame::PaintChildren(nsIPresContext& aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect)
+{
+ // Set clip rect so that children don't leak out of us
+ const nsStyleDisplay* disp =
+ (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display);
+ PRBool hidden = PR_FALSE;
+ if (NS_STYLE_OVERFLOW_HIDDEN == disp->mOverflow) {
+ aRenderingContext.PushState();
+ aRenderingContext.SetClipRect(nsRect(0, 0, mRect.width, mRect.height),
+ nsClipCombine_kIntersect);
+ hidden = PR_TRUE;
+ }
+
+ // Iterate the lines looking for lines that intersect the dirty rect
+ for (LineData* line = mLines; nsnull != line; line = line->mNext) {
+ // Stop when we get to a line that's below the dirty rect
+ if (line->mBounds.y >= aDirtyRect.YMost()) {
+ break;
+ }
+
+ // If the line overlaps the dirty rect then iterate the child frames
+ // and paint those frames that intersect the dirty rect
+ if (line->mBounds.YMost() > aDirtyRect.y) {
+ nsIFrame* kid = line->mFirstChild;
+ for (PRUint16 i = 0; i < line->mChildCount; i++) {
+
+ nsIView *pView;
+
+ kid->GetView(pView);
+ if (nsnull == pView) {
+ nsRect kidRect;
+ kid->GetRect(kidRect);
+ nsRect damageArea;
+#ifdef NS_DEBUG
+ PRBool overlap = PR_FALSE;
+ if (nsIFrame::GetShowFrameBorders() &&
+ ((kidRect.width == 0) || (kidRect.height == 0))) {
+ nscoord xmost = aDirtyRect.XMost();
+ nscoord ymost = aDirtyRect.YMost();
+ if ((aDirtyRect.x <= kidRect.x) && (kidRect.x < xmost) &&
+ (aDirtyRect.y <= kidRect.y) && (kidRect.y < ymost)) {
+ overlap = PR_TRUE;
+ }
+ }
+ else {
+ overlap = damageArea.IntersectRect(aDirtyRect, kidRect);
+ }
+#else
+ PRBool overlap = damageArea.IntersectRect(aDirtyRect, kidRect);
+#endif
+ if (overlap) {
+ // Translate damage area into kid's coordinate system
+ nsRect kidDamageArea(damageArea.x - kidRect.x,
+ damageArea.y - kidRect.y,
+ damageArea.width, damageArea.height);
+ aRenderingContext.PushState();
+ aRenderingContext.Translate(kidRect.x, kidRect.y);
+ kid->Paint(aPresContext, aRenderingContext, kidDamageArea);
+#ifdef NS_DEBUG
+ if (nsIFrame::GetShowFrameBorders() &&
+ (0 != kidRect.width) && (0 != kidRect.height)) {
+ nsIView* view;
+ GetView(view);
+ if (nsnull != view) {
+ aRenderingContext.SetColor(NS_RGB(0,0,255));
+ }
+ else {
+ aRenderingContext.SetColor(NS_RGB(255,0,0));
+ }
+ aRenderingContext.DrawRect(0, 0, kidRect.width, kidRect.height);
+ }
+#endif
+ aRenderingContext.PopState();
+ }
+ }
+
+ // Get the next frame on this line
+ kid->GetNextSibling(kid);
+ }
+ }
+ }
+
+ if (hidden) {
+ aRenderingContext.PopState();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+// Debugging
+
+#ifdef NS_DEBUG
+static PRBool
+InLineList(LineData* aLines, nsIFrame* aFrame)
+{
+ while (nsnull != aLines) {
+ nsIFrame* frame = aLines->mFirstChild;
+ PRInt32 n = aLines->mChildCount;
+ while (--n >= 0) {
+ if (frame == aFrame) {
+ return PR_TRUE;
+ }
+ frame->GetNextSibling(frame);
+ }
+ aLines = aLines->mNext;
+ }
+ return PR_FALSE;
+}
+
+static PRBool
+InSiblingList(LineData* aLine, nsIFrame* aFrame)
+{
+ if (nsnull != aLine) {
+ nsIFrame* frame = aLine->mFirstChild;
+ while (nsnull != frame) {
+ if (frame == aFrame) {
+ return PR_TRUE;
+ }
+ frame->GetNextSibling(frame);
+ }
+ }
+ return PR_FALSE;
+}
+
+PRBool
+nsBlockFrame::IsChild(nsIFrame* aFrame)
+{
+ nsIFrame* parent;
+ aFrame->GetGeometricParent(parent);
+ if (parent != (nsIFrame*)this) {
+ return PR_FALSE;
+ }
+ if (InLineList(mLines, aFrame) && InSiblingList(mLines, aFrame)) {
+ return PR_TRUE;
+ }
+ if (InLineList(mOverflowLines, aFrame) &&
+ InSiblingList(mOverflowLines, aFrame)) {
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+#endif
+
+#define VERIFY_ASSERT(_expr, _msg) \
+ if (!(_expr)) { \
+ DumpTree(); \
+ } \
+ NS_ASSERTION(_expr, _msg)
+
+NS_IMETHODIMP
+nsBlockFrame::VerifyTree() const
+{
+#ifdef NS_DEBUG
+ NS_ASSERTION(0 == (mState & NS_FRAME_IN_REFLOW), "frame is in reflow");
+
+ VERIFY_ASSERT(nsnull == mOverflowLines, "bad overflow list");
+
+ // Verify that child count is the same as the line's mChildCount's
+ VerifyChildCount(mLines);
+
+ // Verify child content offsets and index-in-parents
+ PRInt32 offset = GetFirstContentOffset();
+ nsIFrame* child = (nsnull == mLines) ? nsnull : mLines->mFirstChild;
+ while (nsnull != child) {
+ // Make sure child is ours
+ nsIFrame* parent;
+ child->GetGeometricParent(parent);
+ VERIFY_ASSERT(parent == (nsIFrame*)this, "bad parent");
+
+ // Make sure that the child's tree is valid
+ child->VerifyTree();
+
+ // Make sure child's index-in-parent is correct
+ PRInt32 indexInParent;
+ child->GetContentIndex(indexInParent);
+ VERIFY_ASSERT(offset == indexInParent, "bad child offset");
+
+ nsIFrame* nextInFlow;
+ child->GetNextInFlow(nextInFlow);
+ if (nsnull == nextInFlow) {
+ offset++;
+ }
+ child->GetNextSibling(child);
+ }
+
+ // Verify that our last content offset is correct
+ if (0 != mChildCount) {
+ if (GetLastContentIsComplete()) {
+ VERIFY_ASSERT(offset == GetLastContentOffset() + 1, "bad last offset");
+ } else {
+ VERIFY_ASSERT(offset == GetLastContentOffset(), "bad last offset");
+ }
+ }
+
+#if XXX
+ // Make sure that our flow blocks offsets are all correct
+ if (nsnull == mPrevInFlow) {
+ PRInt32 nextOffset = NextChildOffset();
+ nsContainerFrame* nextInFlow = (nsContainerFrame*) mNextInFlow;
+ while (nsnull != nextInFlow) {
+ VERIFY_ASSERT(0 != nextInFlow->mChildCount, "empty next-in-flow");
+ VERIFY_ASSERT(nextInFlow->GetFirstContentOffset() == nextOffset,
+ "bad next-in-flow first offset");
+ nextOffset = nextInFlow->NextChildOffset();
+ nextInFlow = (nsContainerFrame*) nextInFlow->mNextInFlow;
+ }
+ }
+#endif
+#endif
+ return NS_OK;
+}
+
+#ifdef DO_SELECTION
+nsIFrame * nsBlockFrame::FindHitFrame(nsBlockFrame * aBlockFrame,
+ const nscoord aX,
+ const nscoord aY,
+ const nsPoint & aPoint)
+{
+ nsPoint mousePoint(aPoint.x-aX, aPoint.y-aY);
+
+ nsIFrame * contentFrame = nsnull;
+ LineData * line = aBlockFrame->mLines;
+ if (nsnull != line) {
+ // First find the line that contains the aIndex
+ while (nsnull != line && contentFrame == nsnull) {
+ nsIFrame* frame = line->mFirstChild;
+ PRInt32 n = line->mChildCount;
+ while (--n >= 0) {
+ nsRect bounds;
+ frame->GetRect(bounds);
+ if (bounds.Contains(mousePoint)) {
+ nsBlockFrame * blockFrame;
+ if (NS_OK == frame->QueryInterface(kBlockFrameCID, (void**)&blockFrame)) {
+ frame = FindHitFrame(blockFrame, bounds.x, bounds.y, aPoint);
+ //NS_RELEASE(blockFrame);
+ return frame;
+ } else {
+ return frame;
+ }
+ }
+ frame->GetNextSibling(frame);
+ }
+ line = line->mNext;
+ }
+ }
+ return aBlockFrame;
+}
+
+NS_METHOD nsBlockFrame::HandleEvent(nsIPresContext& aPresContext,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus)
+{
+ if (0) {
+ nsHTMLContainerFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
+ }
+
+ //return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
+ aEventStatus = nsEventStatus_eIgnore;
+
+ //if (nsnull != mContent && (aEvent->message != NS_MOUSE_LEFT_BUTTON_UP ||
+ // (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP && !mDoingSelection))) {
+ if (nsnull != mContent) {
+ mContent->HandleDOMEvent(aPresContext, (nsEvent*)aEvent, nsnull, DOM_EVENT_INIT, aEventStatus);
+ }
+
+ if (DisplaySelection(aPresContext) == PR_FALSE) {
+ if (aEvent->message != NS_MOUSE_LEFT_BUTTON_DOWN) {
+ return NS_OK;
+ }
+ }
+
+ if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) {
+ int x = 0;
+ }
+
+ //nsRect bounds;
+ //GetRect(bounds);
+ //nsIFrame * contentFrame = FindHitFrame(this, bounds.x, bounds.y, aEvent->point);
+ nsIFrame * contentFrame = FindHitFrame(this, 0,0, aEvent->point);
+
+ if (contentFrame == nsnull) {
+ return NS_OK;
+ }
+
+ if(nsEventStatus_eConsumeNoDefault != aEventStatus) {
+ if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) {
+ } else if (aEvent->message == NS_MOUSE_MOVE && mDoingSelection ||
+ aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) {
+ // no-op
+ } else {
+ return NS_OK;
+ }
+
+
+ if (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) {
+ if (mDoingSelection) {
+ contentFrame->HandleRelease(aPresContext, aEvent, aEventStatus);
+ }
+ } else if (aEvent->message == NS_MOUSE_MOVE) {
+ mDidDrag = PR_TRUE;
+ contentFrame->HandleDrag(aPresContext, aEvent, aEventStatus);
+ } else if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) {
+ contentFrame->HandlePress(aPresContext, aEvent, aEventStatus);
+ }
+ }
+
+ return NS_OK;
+
+}
+
+nsIFrame * gNearByFrame = nsnull;
+
+NS_METHOD nsBlockFrame::HandleDrag(nsIPresContext& aPresContext,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus)
+{
+ if (DisplaySelection(aPresContext) == PR_FALSE)
+ {
+ aEventStatus = nsEventStatus_eIgnore;
+ return NS_OK;
+ }
+
+ // Keep old start and end
+ //nsIContent * startContent = mSelectionRange->GetStartContent(); // ref counted
+ //nsIContent * endContent = mSelectionRange->GetEndContent(); // ref counted
+
+ mDidDrag = PR_TRUE;
+
+
+ nsIFrame * contentFrame = nsnull;
+ LineData* line = mLines;
+ if (nsnull != line) {
+ // First find the line that contains the aIndex
+ while (nsnull != line && contentFrame == nsnull) {
+ nsIFrame* frame = line->mFirstChild;
+ PRInt32 n = line->mChildCount;
+ while (--n >= 0) {
+ nsRect bounds;
+ frame->GetRect(bounds);
+ if (aEvent->point.y >= bounds.y && aEvent->point.y < bounds.y+bounds.height) {
+ contentFrame = frame;
+ if (frame != gNearByFrame) {
+ if (gNearByFrame != nsnull) {
+ int x = 0;
+ }
+ aEvent->point.x = bounds.x+bounds.width-50;
+ gNearByFrame = frame;
+ return contentFrame->HandleDrag(aPresContext, aEvent, aEventStatus);
+ } else {
+ return NS_OK;
+ }
+ //break;
+ }
+ frame->GetNextSibling(frame);
+ }
+ line = line->mNext;
+ }
+ }
+
+
+
+ return NS_OK;
+
+}
+
+
+#endif
diff --git a/layout/generic/nsBlockReflowState.h b/layout/generic/nsBlockReflowState.h
new file mode 100644
index 000000000000..6dd718cd7d70
--- /dev/null
+++ b/layout/generic/nsBlockReflowState.h
@@ -0,0 +1,4735 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications
+ * Corporation. Portions created by Netscape are Copyright (C) 1998
+ * Netscape Communications Corporation. All Rights Reserved.
+ */
+#include "nsBlockFrame.h"
+#include "nsLineLayout.h"
+#include "nsInlineLayout.h"
+#include "nsCSSLayout.h"
+#include "nsPlaceholderFrame.h"
+#include "nsStyleConsts.h"
+#include "nsHTMLIIDs.h"
+#include "nsCSSRendering.h"
+
+#include "nsIAnchoredItems.h"
+#include "nsIFloaterContainer.h"
+#include "nsIPresContext.h"
+#include "nsIPresShell.h"
+#include "nsIReflowCommand.h"
+#include "nsIRunaround.h"
+#include "nsIStyleContext.h"
+#include "nsIView.h"
+#include "nsIFontMetrics.h"
+
+#include "nsHTMLBase.h"// XXX rename to nsBase?
+#include "nsHTMLParts.h"// XXX html reflow command???
+#include "nsHTMLAtoms.h"// XXX list ordinal hack
+#include "nsHTMLValue.h"// XXX list ordinal hack
+#include "nsIHTMLContent.h"// XXX list ordinal hack
+
+//#include "js/jsapi.h"
+//#include "nsDOMEvent.h"
+#define DOM_EVENT_INIT 0x0001
+
+#include "prprf.h"
+
+// XXX mLastContentOffset, mFirstContentOffset, mLastContentIsComplete
+// XXX pagination
+// XXX prev-in-flow continuations
+
+// XXX IsFirstChild
+// XXX max-element-size
+// XXX no-wrap
+// XXX margin collapsing and empty InlineFrameData's
+// XXX floaters in inlines
+// XXX Check handling of mUnconstrainedWidth
+
+// XXX MULTICOL support; note that multicol will end up using the
+// equivalent of pagination! Therefore we should probably make sure
+// the pagination code isn't completely stupid.
+
+// XXX better lists (bullet numbering)
+
+// XXX page-breaks
+
+// XXX out of memory checks are missing
+
+// XXX push code can record the y coordinate where the push occurred
+// and the width that the data was flowed against and also indicate
+// which frames were reflowed and which weren't. Then drain code can just
+// place the pulled up data directly when there are no floaters to
+// worry about. something like that...
+
+// XXX Tuneup: if mNoWrap is true and we are given a ResizeReflow we
+// can just return because there's nothing to do!; this is true in
+// nsInlineFrame too!
+// Except that noWrap is ignored if the containers width is too small
+// (like a table cell with a fixed width.)
+
+//----------------------------------------------------------------------
+// XXX It's really important that blocks strip out extra whitespace;
+// otherwise we will see ALOT of this, which will waste memory big time:
+//
+//
+//
+//
+//
+// ...
+//----------------------------------------------------------------------
+
+// XXX I don't want mFirstChild, mChildCount, mOverflowList,
+// mLastContentIsComplete in our base class!!!
+
+struct LineData;
+
+// XXX Death to pseudo-frames!!!!!
+#define DTPF 1
+
+// XXX temporary until PropagateContentOffsets can be written genericly
+#define nsBlockFrameSuper nsHTMLContainerFrame
+
+class nsBlockFrame : public nsBlockFrameSuper,
+ public nsIRunaround,
+ public nsIFloaterContainer
+{
+public:
+ nsBlockFrame(nsIContent* aContent, nsIFrame* aParent);
+
+ // nsISupports
+ NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
+
+ // nsIFrame
+ NS_IMETHOD Init(nsIPresContext& aPresContext, nsIFrame* aChildList);
+ NS_IMETHOD DeleteFrame(nsIPresContext& aPresContext);
+ NS_IMETHOD ChildCount(PRInt32& aChildCount) const;
+ NS_IMETHOD ChildAt(PRInt32 aIndex, nsIFrame*& aFrame) const;
+ NS_IMETHOD IndexOf(const nsIFrame* aChild, PRInt32& aIndex) const;
+ NS_IMETHOD FirstChild(nsIFrame*& aFirstChild) const;
+ NS_IMETHOD NextChild(const nsIFrame* aChild, nsIFrame*& aNextChild) const;
+ NS_IMETHOD PrevChild(const nsIFrame* aChild, nsIFrame*& aPrevChild) const;
+ NS_IMETHOD LastChild(nsIFrame*& aLastChild) const;
+ NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const;
+ NS_IMETHOD CreateContinuingFrame(nsIPresContext& aPresContext,
+ nsIFrame* aParent,
+ nsIStyleContext* aStyleContext,
+ nsIFrame*& aContinuingFrame);
+ NS_IMETHOD Paint(nsIPresContext& aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect);
+ // XXX CONSTRUCTION
+#if 0
+ NS_IMETHOD ContentAppended(nsIPresShell* aShell,
+ nsIPresContext* aPresContext,
+ nsIContent* aContainer);
+#endif
+ NS_IMETHOD ContentInserted(nsIPresShell* aShell,
+ nsIPresContext* aPresContext,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ PRInt32 aIndexInParent);
+ NS_IMETHOD ContentDeleted(nsIPresShell* aShell,
+ nsIPresContext* aPresContext,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ PRInt32 aIndexInParent);
+#if XXX
+ NS_IMETHOD DidReflow(nsIPresContext& aPresContext,
+ nsDidReflowStatus aStatus);
+#endif
+ NS_IMETHOD List(FILE* out, PRInt32 aIndent, nsIListFilter *aFilter = nsnull) const;
+ NS_IMETHOD ListTag(FILE* out) const;
+ NS_IMETHOD VerifyTree() const;
+ // XXX implement regular reflow method too!
+
+ // nsIRunaround
+ NS_IMETHOD ReflowAround(nsIPresContext& aPresContext,
+ nsISpaceManager* aSpaceManager,
+ nsReflowMetrics& aDesiredSize,
+ const nsReflowState& aReflowState,
+ nsRect& aDesiredRect,
+ nsReflowStatus& aStatus);
+
+ // nsIFloaterContainer
+ virtual PRBool AddFloater(nsIPresContext* aPresContext,
+ const nsReflowState& aPlaceholderReflowState,
+ nsIFrame* aFloater,
+ nsPlaceholderFrame* aPlaceholder);
+
+#ifdef DO_SELECTION
+ NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus);
+
+ NS_IMETHOD HandleDrag(nsIPresContext& aPresContext,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus);
+
+ nsIFrame * FindHitFrame(nsBlockFrame * aBlockFrame,
+ const nscoord aX, const nscoord aY,
+ const nsPoint & aPoint);
+
+#endif
+protected:
+ ~nsBlockFrame();
+
+
+#if 0
+ PRInt32 GetFirstContentOffset() const;
+
+ PRInt32 GetLastContentOffset() const;
+
+ PRBool GetLastContentIsComplete() const;
+#endif
+ virtual PRBool DeleteNextInFlowsFor(nsIPresContext& aPresContext, nsIFrame* aNextInFlow);
+
+ PRBool DrainOverflowLines();
+
+ PRBool RemoveChild(LineData* aLines, nsIFrame* aChild);
+
+ nsresult ProcessInitialReflow(nsIPresContext* aPresContext);
+
+ //XXX void PropagateContentOffsets();
+
+ PRIntn GetSkipSides() const;
+
+ PRBool IsPseudoFrame() const;
+
+ nsresult InitialReflow(nsBlockReflowState& aState);
+
+ nsresult FrameAppendedReflow(nsBlockReflowState& aState);
+
+ nsresult InsertNewFrame(nsBlockFrame* aParentFrame,
+ nsIFrame* aNewFrame,
+ nsIFrame* aPrevSibling);
+ nsresult FrameInsertedReflow(nsBlockReflowState& aState);
+
+ nsresult FrameDeletedReflow(nsBlockReflowState& aState);
+
+ nsresult CreateNewFrames(nsIPresContext* aPresContext);
+
+ nsresult FindTextRuns(nsBlockReflowState& aState);
+
+ nsresult ChildIncrementalReflow(nsBlockReflowState& aState);
+
+ nsresult ResizeReflow(nsBlockReflowState& aState);
+
+ void ComputeFinalSize(nsBlockReflowState& aState,
+ nsReflowMetrics& aMetrics,
+ nsRect& aDesiredRect);
+
+ nsresult ReflowLinesAt(nsBlockReflowState& aState, LineData* aLine);
+
+ PRBool ReflowLine(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsInlineReflowStatus& aReflowResult);
+
+ PRBool PlaceLine(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsInlineReflowStatus aReflowStatus);
+
+ void FindFloaters(LineData* aLine);
+
+ PRBool ReflowInlineFrame(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsIFrame* aFrame,
+ nsInlineReflowStatus& aResult);
+
+ nsresult SplitLine(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsIFrame* aFrame,
+ PRBool aLineWasComplete);
+
+ PRBool ReflowBlockFrame(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsIFrame* aFrame,
+ nsInlineReflowStatus& aResult);
+
+ PRBool PullFrame(nsBlockReflowState& aState,
+ LineData* aToLine,
+ LineData** aFromList,
+ PRBool aUpdateGeometricParent,
+ nsInlineReflowStatus& aResult);
+
+ void PushLines(nsBlockReflowState& aState);
+
+ void ReflowFloater(nsIPresContext* aPresContext,
+ nsBlockReflowState& aState,
+ nsIFrame* aFloaterFrame);
+
+ void PaintChildren(nsIPresContext& aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect);
+
+ nsresult AppendNewFrames(nsIPresContext* aPresContext, nsIFrame*);
+
+#ifdef NS_DEBUG
+ PRBool IsChild(nsIFrame* aFrame);
+#endif
+
+ LineData* mLines;
+
+ LineData* mOverflowLines;
+
+ // placeholder frames for floaters to display at the top line
+// nsVoidArray* mRunInFloaters;
+
+ // Text run information
+ nsTextRun* mTextRuns;
+
+ // XXX TEMP
+ PRBool mHasBeenInitialized;
+
+ friend struct nsBlockReflowState;
+};
+
+//----------------------------------------------------------------------
+
+#define LINE_IS_DIRTY 0x1
+#define LINE_IS_BLOCK 0x2
+#define LINE_LAST_CONTENT_IS_COMPLETE 0x4
+#define LINE_NEED_DID_REFLOW 0x8
+
+struct LineData {
+ LineData(nsIFrame* aFrame, PRInt32 aCount, PRUint16 flags) {
+ mFirstChild = aFrame;
+ mChildCount = aCount;
+ mState = LINE_IS_DIRTY | LINE_NEED_DID_REFLOW | flags;
+ mFloaters = nsnull;
+ mNext = nsnull;
+ mInnerBottomMargin = 0;
+ mOuterBottomMargin = 0;
+ mBounds.SetRect(0,0,0,0);
+ }
+
+ ~LineData();
+
+ void List(FILE* out, PRInt32 aIndent, nsIListFilter *aFilter = nsnull,
+ PRBool aOutputMe=PR_TRUE) const;
+
+ nsIFrame* LastChild() const;
+
+ PRBool IsLastChild(nsIFrame* aFrame) const;
+
+ void SetLastContentIsComplete() {
+ mState |= LINE_LAST_CONTENT_IS_COMPLETE;
+ }
+
+ void ClearLastContentIsComplete() {
+ mState &= ~LINE_LAST_CONTENT_IS_COMPLETE;
+ }
+
+ void SetLastContentIsComplete(PRBool aValue) {
+ if (aValue) {
+ SetLastContentIsComplete();
+ }
+ else {
+ ClearLastContentIsComplete();
+ }
+ }
+
+ PRBool GetLastContentIsComplete() {
+ return 0 != (LINE_LAST_CONTENT_IS_COMPLETE & mState);
+ }
+
+ PRBool IsBlock() const {
+ return 0 != (LINE_IS_BLOCK & mState);
+ }
+
+ void SetIsBlock() {
+ mState |= LINE_IS_BLOCK;
+ }
+
+ void ClearIsBlock() {
+ mState &= ~LINE_IS_BLOCK;
+ }
+
+ void SetIsBlock(PRBool aValue) {
+ if (aValue) {
+ SetIsBlock();
+ }
+ else {
+ ClearIsBlock();
+ }
+ }
+
+ void MarkDirty() {
+ mState |= LINE_IS_DIRTY;
+ }
+
+ void ClearDirty() {
+ mState &= ~LINE_IS_DIRTY;
+ }
+
+ void SetNeedDidReflow() {
+ mState |= LINE_NEED_DID_REFLOW;
+ }
+
+ void ClearNeedDidReflow() {
+ mState &= ~LINE_NEED_DID_REFLOW;
+ }
+
+ PRBool NeedsDidReflow() {
+ return 0 != (LINE_NEED_DID_REFLOW & mState);
+ }
+
+ PRBool IsDirty() const {
+ return 0 != (LINE_IS_DIRTY & mState);
+ }
+
+ PRUint16 GetState() const { return mState; }
+
+ char* StateToString(char* aBuf, PRInt32 aBufSize) const;
+
+ PRBool Contains(nsIFrame* aFrame) const;
+
+#ifdef NS_DEBUG
+ void Verify();
+#endif
+
+ nsIFrame* mFirstChild;
+ PRUint16 mChildCount;
+ PRUint16 mState;
+ nsRect mBounds;
+ nscoord mInnerBottomMargin;
+ nscoord mOuterBottomMargin;
+ nsVoidArray* mFloaters;
+ LineData* mNext;
+};
+
+LineData::~LineData()
+{
+ if (nsnull != mFloaters) {
+ delete mFloaters;
+ }
+}
+
+static void
+ListFloaters(FILE* out, nsVoidArray* aFloaters)
+{
+ PRInt32 i, n = aFloaters->Count();
+ for (i = 0; i < n; i++) {
+ nsIFrame* frame = (nsIFrame*) aFloaters->ElementAt(i);
+ frame->ListTag(out);
+ if (i < n - 1) fputs(" ", out);
+ }
+}
+
+static void
+ListTextRuns(FILE* out, PRInt32 aIndent, nsTextRun* aRuns)
+{
+ while (nsnull != aRuns) {
+ aRuns->List(out, aIndent);
+ aRuns = aRuns->mNext;
+ }
+}
+
+char*
+LineData::StateToString(char* aBuf, PRInt32 aBufSize) const
+{
+ PR_snprintf(aBuf, aBufSize, "%s,%s,%scomplete",
+ (mState & LINE_IS_DIRTY) ? "dirty" : "clean",
+ (mState & LINE_IS_BLOCK) ? "block" : "inline",
+ (mState & LINE_LAST_CONTENT_IS_COMPLETE) ? "" : "!");
+ return aBuf;
+}
+
+void
+LineData::List(FILE* out, PRInt32 aIndent, nsIListFilter *aFilter,
+ PRBool aOutputMe) const
+{
+ // if a filter is present, only output this frame if the filter says we should
+ PRInt32 i;
+
+ if (PR_TRUE==aOutputMe)
+ {
+ for (i = aIndent; --i >= 0; ) fputs(" ", out);
+ char cbuf[100];
+ fprintf(out, "line %p: count=%d state=%s {%d,%d,%d,%d} ibm=%d obm=%d <\n",
+ this, mChildCount, StateToString(cbuf, sizeof(cbuf)),
+ mBounds.x, mBounds.y, mBounds.width, mBounds.height,
+ mInnerBottomMargin, mOuterBottomMargin);
+ }
+
+ nsIFrame* frame = mFirstChild;
+ PRInt32 n = mChildCount;
+ while (--n >= 0) {
+ frame->List(out, aIndent + 1, aFilter);
+ frame->GetNextSibling(frame);
+ }
+
+ if (PR_TRUE==aOutputMe)
+ {
+ for (i = aIndent; --i >= 0; ) fputs(" ", out);
+
+ if (nsnull != mFloaters) {
+ fputs("> bcl-floaters=<", out);
+ ListFloaters(out, mFloaters);
+ }
+ fputs(">\n", out);
+ }
+}
+
+nsIFrame*
+LineData::LastChild() const
+{
+ nsIFrame* frame = mFirstChild;
+ PRInt32 n = mChildCount - 1;
+ while (--n >= 0) {
+ frame->GetNextSibling(frame);
+ }
+ return frame;
+}
+
+PRBool
+LineData::IsLastChild(nsIFrame* aFrame) const
+{
+ nsIFrame* lastFrame = LastChild();
+ return aFrame == lastFrame;
+}
+
+PRBool
+LineData::Contains(nsIFrame* aFrame) const
+{
+ PRInt32 n = mChildCount;
+ nsIFrame* frame = mFirstChild;
+ while (--n >= 0) {
+ if (frame == aFrame) {
+ return PR_TRUE;
+ }
+ frame->GetNextSibling(frame);
+ }
+ return PR_FALSE;
+}
+
+static PRInt32
+LengthOf(nsIFrame* aFrame)
+{
+ PRInt32 result = 0;
+ while (nsnull != aFrame) {
+ result++;
+ aFrame->GetNextSibling(aFrame);
+ }
+ return result;
+}
+
+#ifdef NS_DEBUG
+void
+LineData::Verify()
+{
+ nsIFrame* lastFrame = LastChild();
+ if (nsnull != lastFrame) {
+ nsIFrame* nextInFlow;
+ lastFrame->GetNextInFlow(nextInFlow);
+ if (GetLastContentIsComplete()) {
+ NS_ASSERTION(nsnull == nextInFlow, "bad mState");
+ }
+ if (nsnull != mNext) {
+ nsIFrame* nextSibling;
+ lastFrame->GetNextSibling(nextSibling);
+ NS_ASSERTION(mNext->mFirstChild == nextSibling, "bad line list");
+ }
+ }
+ PRInt32 len = LengthOf(mFirstChild);
+ NS_ASSERTION(len >= mChildCount, "bad mChildCount");
+}
+
+static void
+VerifyLines(LineData* aLine)
+{
+ while (nsnull != aLine) {
+ aLine->Verify();
+ aLine = aLine->mNext;
+ }
+}
+
+static void
+VerifyChildCount(LineData* aLines, PRBool aEmptyOK = PR_FALSE)
+{
+ if (nsnull != aLines) {
+ PRInt32 childCount = LengthOf(aLines->mFirstChild);
+ PRInt32 sum = 0;
+ LineData* line = aLines;
+ while (nsnull != line) {
+ if (!aEmptyOK) {
+ NS_ASSERTION(0 != line->mChildCount, "empty line left in line list");
+ }
+ sum += line->mChildCount;
+ line = line->mNext;
+ }
+ if (sum != childCount) {
+ printf("Bad sibling list/line mChildCount's\n");
+ LineData* line = aLines;
+ while (nsnull != line) {
+ line->List(stdout, 1);
+ if (nsnull != line->mNext) {
+ nsIFrame* lastFrame = line->LastChild();
+ if (nsnull != lastFrame) {
+ nsIFrame* nextSibling;
+ lastFrame->GetNextSibling(nextSibling);
+ if (line->mNext->mFirstChild != nextSibling) {
+ printf(" [list broken: nextSibling=%p mNext->mFirstChild=%p]\n",
+ nextSibling, line->mNext->mFirstChild);
+ }
+ }
+ }
+ line = line->mNext;
+ }
+ NS_ASSERTION(sum == childCount, "bad sibling list/line mChildCount's");
+ }
+ }
+}
+#endif
+
+static void
+DeleteLineList(nsIPresContext& aPresContext, LineData* aLine)
+{
+ if (nsnull != aLine) {
+ // Delete our child frames before doing anything else. In particular
+ // we do all of this before our base class releases it's hold on the
+ // view.
+ for (nsIFrame* child = aLine->mFirstChild; child; ) {
+ nsIFrame* nextChild;
+ child->GetNextSibling(nextChild);
+ child->DeleteFrame(aPresContext);
+ child = nextChild;
+ }
+
+ while (nsnull != aLine) {
+ LineData* next = aLine->mNext;
+ delete aLine;
+ aLine = next;
+ }
+ }
+}
+
+static LineData*
+LastLine(LineData* aLine)
+{
+ if (nsnull != aLine) {
+ while (nsnull != aLine->mNext) {
+ aLine = aLine->mNext;
+ }
+ }
+ return aLine;
+}
+
+static LineData*
+FindLineContaining(LineData* aLine, nsIFrame* aFrame)
+{
+ while (nsnull != aLine) {
+ if (aLine->Contains(aFrame)) {
+ return aLine;
+ }
+ aLine = aLine->mNext;
+ }
+ return nsnull;
+}
+
+//----------------------------------------------------------------------
+
+void nsBlockReflowState::BlockBandData::ComputeAvailSpaceRect()
+{
+ nsBandTrapezoid* trapezoid = data;
+
+ if (count > 1) {
+ // If there's more than one trapezoid that means there are floaters
+ PRInt32 i;
+
+ // Stop when we get to space occupied by a right floater, or when we've
+ // looked at every trapezoid and none are right floaters
+ for (i = 0; i < count; i++) {
+ nsBandTrapezoid* trapezoid = &data[i];
+ if (trapezoid->state != nsBandTrapezoid::Available) {
+ const nsStyleDisplay* display;
+ if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
+ PRInt32 j, numFrames = trapezoid->frames->Count();
+ NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
+ for (j = 0; j < numFrames; j++) {
+ nsIFrame* f = (nsIFrame*)trapezoid->frames->ElementAt(j);
+ f->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)display);
+ if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
+ goto foundRightFloater;
+ }
+ }
+ } else {
+ trapezoid->frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)display);
+ if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
+ break;
+ }
+ }
+ }
+ }
+ foundRightFloater:
+
+ if (i > 0) {
+ trapezoid = &data[i - 1];
+ }
+ }
+
+ if (nsBandTrapezoid::Available == trapezoid->state) {
+ // The trapezoid is available
+ trapezoid->GetRect(availSpace);
+ } else {
+ const nsStyleDisplay* display;
+
+ // The trapezoid is occupied. That means there's no available space
+ trapezoid->GetRect(availSpace);
+
+ // XXX Better handle the case of multiple frames
+ if (nsBandTrapezoid::Occupied == trapezoid->state) {
+ trapezoid->frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)display);
+ if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
+ availSpace.x = availSpace.XMost();
+ }
+ }
+ availSpace.width = 0;
+ }
+}
+
+//----------------------------------------------------------------------
+
+static nscoord
+GetParentLeftPadding(const nsReflowState* aReflowState)
+{
+ nscoord leftPadding = 0;
+ while (nsnull != aReflowState) {
+ nsIFrame* frame = aReflowState->frame;
+ const nsStyleDisplay* styleDisplay;
+ frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&) styleDisplay);
+ if (NS_STYLE_DISPLAY_BLOCK == styleDisplay->mDisplay) {
+ const nsStyleSpacing* styleSpacing;
+ frame->GetStyleData(eStyleStruct_Spacing,
+ (const nsStyleStruct*&) styleSpacing);
+ nsMargin padding;
+ styleSpacing->CalcPaddingFor(frame, padding);
+ leftPadding = padding.left;
+ break;
+ }
+ aReflowState = aReflowState->parentReflowState;
+ }
+ return leftPadding;
+}
+
+nsBlockReflowState::nsBlockReflowState(nsIPresContext* aPresContext,
+ nsISpaceManager* aSpaceManager,
+ nsBlockFrame* aBlock,
+ nsIStyleContext* aBlockSC,
+ const nsReflowState& aReflowState,
+ nsReflowMetrics& aMetrics,
+ PRBool aComputeMaxElementSize)
+ : nsReflowState(aReflowState),
+ mLineLayout(aPresContext, aSpaceManager),
+ mInlineLayout(mLineLayout, aBlock, aBlockSC)
+{
+ mLineLayout.Init(this);
+ mInlineLayout.Init(this);
+
+ mSpaceManager = aSpaceManager;
+
+ // Save away the outer coordinate system origin for later
+ mSpaceManager->GetTranslation(mSpaceManagerX, mSpaceManagerY);
+
+ mPresContext = aPresContext;
+ mBlock = aBlock;
+ mBlockIsPseudo = aBlock->IsPseudoFrame();
+ aBlock->GetNextInFlow((nsIFrame*&)mNextInFlow);
+ mPrevBottomMargin = 0;
+ mOuterTopMargin = aMetrics.posTopMargin;
+ mKidXMost = 0;
+
+ mX = 0;
+ mY = 0;
+ mUnconstrainedWidth = maxSize.width == NS_UNCONSTRAINEDSIZE;
+ mUnconstrainedHeight = maxSize.height == NS_UNCONSTRAINEDSIZE;
+#ifdef NS_DEBUG
+ if (!mUnconstrainedWidth && (maxSize.width > 100000)) {
+ mBlock->ListTag(stdout);
+ printf(": bad parent: maxSize WAS %d,%d\n",
+ maxSize.width, maxSize.height);
+ maxSize.width = NS_UNCONSTRAINEDSIZE;
+ mUnconstrainedWidth = PR_TRUE;
+ }
+ if (!mUnconstrainedHeight && (maxSize.height > 100000)) {
+ mBlock->ListTag(stdout);
+ printf(": bad parent: maxSize WAS %d,%d\n",
+ maxSize.width, maxSize.height);
+ maxSize.height = NS_UNCONSTRAINEDSIZE;
+ mUnconstrainedHeight = PR_TRUE;
+ }
+#endif
+ mComputeMaxElementSize = aComputeMaxElementSize;
+ if (mComputeMaxElementSize) {
+ mMaxElementSize.width = 0;
+ mMaxElementSize.height = 0;
+ }
+ mHaveBlockMaxWidth = PR_FALSE;
+
+ // Set mNoWrap flag
+ const nsStyleText* blockText = (const nsStyleText*)
+ aBlockSC->GetStyleData(eStyleStruct_Text);
+ switch (blockText->mWhiteSpace) {
+ case NS_STYLE_WHITESPACE_PRE:
+ case NS_STYLE_WHITESPACE_NOWRAP:
+ mNoWrap = PR_TRUE;
+ break;
+ default:
+ mNoWrap = PR_FALSE;
+ break;
+ }
+ mTextAlign = blockText->mTextAlign;
+ const nsStyleDisplay* styleDisplay = (const nsStyleDisplay*)
+ aBlockSC->GetStyleData(eStyleStruct_Display);
+ mDirection = styleDisplay->mDirection;
+
+ mBulletPadding = 0;
+ if (NS_STYLE_DISPLAY_LIST_ITEM == styleDisplay->mDisplay) {
+ const nsStyleList* sl = (const nsStyleList*)
+ aBlockSC->GetStyleData(eStyleStruct_List);
+ if (NS_STYLE_LIST_STYLE_POSITION_OUTSIDE == sl->mListStylePosition) {
+ mLineLayout.mListPositionOutside = PR_TRUE;
+ mBulletPadding = GetParentLeftPadding(aReflowState.parentReflowState);
+ }
+ }
+ const nsStyleSpacing* blockSpacing = (const nsStyleSpacing*)
+ aBlockSC->GetStyleData(eStyleStruct_Spacing);
+ nsMargin padding;
+ blockSpacing->CalcPaddingFor(mBlock, padding);
+ mLeftPadding = padding.left;
+
+ // Apply border and padding adjustments for regular frames only
+ nsRect blockRect;
+ mBlock->GetRect(blockRect);
+ mStyleSizeFlags = 0;
+ if (!mBlockIsPseudo) {
+ blockSpacing->CalcBorderPaddingFor(mBlock, mBorderPadding);
+ mY = mBorderPadding.top;
+ mX = mBorderPadding.left;
+
+ if (mUnconstrainedWidth) {
+ // If our width is unconstrained don't bother futzing with the
+ // available width/height because they don't matter - we are
+ // going to get reflowed again.
+ mDeltaWidth = NS_UNCONSTRAINEDSIZE;
+ mInnerSize.width = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ // When we are constrained we need to apply the width/height
+ // style properties. When we have a width/height it applies to
+ // the content width/height of our box. The content width/height
+ // doesn't include the border+padding so we have to add that in
+ // instead of subtracting it out of our maxsize.
+ nscoord lr = mBorderPadding.left + mBorderPadding.right;
+
+ // Get and apply the stylistic size. Note: do not limit the
+ // height until we are done reflowing.
+ PRIntn ss = nsCSSLayout::GetStyleSize(aPresContext, aReflowState,
+ mStyleSize);
+ mStyleSizeFlags = ss;
+ if (0 != (ss & NS_SIZE_HAS_WIDTH)) {
+ // CSS2 spec says that the width attribute defines the width
+ // of the "content area" which does not include the border
+ // padding. So we add those back in.
+ mInnerSize.width = mStyleSize.width + lr;
+ }
+ else {
+ mInnerSize.width = maxSize.width - lr;
+ }
+ mDeltaWidth = maxSize.width - blockRect.width;
+ }
+ if (mUnconstrainedHeight) {
+ mInnerSize.height = maxSize.height;
+ mBottomEdge = maxSize.height;
+ }
+ else {
+ nscoord tb = mBorderPadding.top + mBorderPadding.bottom;
+ mInnerSize.height = maxSize.height - tb;
+ mBottomEdge = maxSize.height - mBorderPadding.bottom;
+ }
+ }
+ else {
+ mBorderPadding.SizeTo(0, 0, 0, 0);
+ mDeltaWidth = maxSize.width - blockRect.width;
+ mInnerSize = maxSize;
+ mBottomEdge = maxSize.height;
+ }
+
+ // Now translate in by our border and padding
+ mSpaceManager->Translate(mBorderPadding.left, mBorderPadding.top);
+
+ mPrevChild = nsnull;
+ mFreeList = nsnull;
+ mPrevLine = nsnull;
+
+ // Setup initial list ordinal value
+
+ // XXX translate the starting value to a css style type and stop
+ // doing this!
+ mNextListOrdinal = -1;
+ nsIContent* blockContent;
+ mBlock->GetContent(blockContent);
+ nsIAtom* tag;
+ blockContent->GetTag(tag);
+ if ((tag == nsHTMLAtoms::ul) || (tag == nsHTMLAtoms::ol) ||
+ (tag == nsHTMLAtoms::menu) || (tag == nsHTMLAtoms::dir)) {
+ nsHTMLValue value;
+ if (NS_CONTENT_ATTR_HAS_VALUE ==
+ ((nsIHTMLContent*)blockContent)->GetAttribute(nsHTMLAtoms::start,
+ value)) {
+ if (eHTMLUnit_Integer == value.GetUnit()) {
+ mNextListOrdinal = value.GetIntValue();
+ }
+ }
+ }
+ NS_IF_RELEASE(tag);
+ NS_RELEASE(blockContent);
+}
+
+nsBlockReflowState::~nsBlockReflowState()
+{
+ // Restore the coordinate system
+ mSpaceManager->Translate(-mBorderPadding.left, -mBorderPadding.top);
+
+ LineData* line = mFreeList;
+ while (nsnull != line) {
+ NS_ASSERTION((0 == line->mChildCount) && (nsnull == line->mFirstChild),
+ "bad free line");
+ LineData* next = line->mNext;
+ delete line;
+ line = next;
+ }
+}
+
+// Get the available reflow space for the current y coordinate. The
+// available space is relative to our coordinate system (0,0) is our
+// upper left corner.
+void
+nsBlockReflowState::GetAvailableSpace()
+{
+ nsISpaceManager* sm = mSpaceManager;
+
+#ifdef NS_DEBUG
+ // Verify that the caller setup the coordinate system properly
+ nscoord wx, wy;
+ sm->GetTranslation(wx, wy);
+ nscoord cx = mSpaceManagerX + mBorderPadding.left;
+ nscoord cy = mSpaceManagerY + mBorderPadding.top;
+ NS_ASSERTION((wx == cx) && (wy == cy), "bad coord system");
+#endif
+
+ // Fill in band data for the specific Y coordinate
+ sm->GetBandData(mY, mInnerSize, mCurrentBand);
+
+ // Compute the bounding rect of the available space, i.e. space
+ // between any left and right floaters.
+ mCurrentBand.ComputeAvailSpaceRect();
+
+ NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
+ ("nsBlockReflowState::GetAvailableSpace: band={%d,%d,%d,%d} count=%d",
+ mCurrentBand.availSpace.x, mCurrentBand.availSpace.y,
+ mCurrentBand.availSpace.width, mCurrentBand.availSpace.height,
+ mCurrentBand.count));
+}
+
+//----------------------------------------------------------------------
+
+nsresult
+NS_NewBlockFrame(nsIFrame** aInstancePtrResult,
+ nsIContent* aContent,
+ nsIFrame* aParent)
+{
+ NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
+ if (nsnull == aInstancePtrResult) {
+ return NS_ERROR_NULL_POINTER;
+ }
+ nsIFrame* it = new nsBlockFrame(aContent, aParent);
+ if (nsnull == it) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ *aInstancePtrResult = it;
+ return NS_OK;
+}
+
+nsBlockFrame::nsBlockFrame(nsIContent* aContent, nsIFrame* aParent)
+ : nsBlockFrameSuper(aContent, aParent)
+{
+ mHasBeenInitialized = PR_FALSE;
+}
+
+nsBlockFrame::~nsBlockFrame()
+{
+// if (nsnull != mRunInFloaters) {
+// delete mRunInFloaters;
+// }
+ nsTextRun::DeleteTextRuns(mTextRuns);
+}
+
+NS_IMETHODIMP
+nsBlockFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
+{
+ NS_PRECONDITION(0 != aInstancePtr, "null ptr");
+ if (NULL == aInstancePtr) {
+ return NS_ERROR_NULL_POINTER;
+ }
+ // XXX temporary
+ if (aIID.Equals(kBlockFrameCID)) {
+ *aInstancePtr = (void*) (this);
+ return NS_OK;
+ }
+ if (aIID.Equals(kIRunaroundIID)) {
+ *aInstancePtr = (void*) ((nsIRunaround*) this);
+ return NS_OK;
+ }
+ if (aIID.Equals(kIFloaterContainerIID)) {
+ *aInstancePtr = (void*) ((nsIFloaterContainer*) this);
+ return NS_OK;
+ }
+ return nsBlockFrameSuper::QueryInterface(aIID, aInstancePtr);
+}
+
+NS_IMETHODIMP
+nsBlockFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList)
+{
+ mHasBeenInitialized = PR_TRUE;
+ return AppendNewFrames(&aPresContext, aChildList);
+}
+
+NS_IMETHODIMP
+nsBlockFrame::DeleteFrame(nsIPresContext& aPresContext)
+{
+ DeleteLineList(aPresContext, mLines);
+ DeleteLineList(aPresContext, mOverflowLines);
+
+ nsBlockFrameSuper::DeleteFrame(aPresContext);
+
+ return NS_OK;
+}
+
+PRBool
+nsBlockFrame::IsPseudoFrame() const
+{
+ PRBool result = PR_FALSE;
+
+ if (nsnull != mGeometricParent) {
+ nsIContent* parentContent;
+
+ mGeometricParent->GetContent(parentContent);
+ if (parentContent == mContent) {
+ result = PR_TRUE;
+ }
+ NS_RELEASE(parentContent);
+ }
+
+ return result;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::IsSplittable(nsSplittableType& aIsSplittable) const
+{
+ aIsSplittable = NS_FRAME_SPLITTABLE_NON_RECTANGULAR;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::CreateContinuingFrame(nsIPresContext& aCX,
+ nsIFrame* aParent,
+ nsIStyleContext* aStyleContext,
+ nsIFrame*& aContinuingFrame)
+{
+ nsBlockFrame* cf = new nsBlockFrame(mContent, aParent);
+ if (nsnull == cf) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ PrepareContinuingFrame(aCX, aParent, aStyleContext, cf);
+ aContinuingFrame = cf;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::CreateContinuingFrame: newFrame=%p", cf));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::ListTag(FILE* out) const
+{
+ if ((nsnull != mGeometricParent) && IsPseudoFrame()) {
+ fprintf(out, "*block<");
+ nsIAtom* atom;
+ mContent->GetTag(atom);
+ if (nsnull != atom) {
+ nsAutoString tmp;
+ atom->ToString(tmp);
+ fputs(tmp, out);
+ }
+ PRInt32 contentIndex;
+ GetContentIndex(contentIndex);
+ fprintf(out, ">(%d)@%p", contentIndex, this);
+ } else {
+ nsBlockFrameSuper::ListTag(out);
+ }
+ return NS_OK;
+}
+
+NS_METHOD
+nsBlockFrame::List(FILE* out, PRInt32 aIndent, nsIListFilter *aFilter) const
+{
+ // if a filter is present, only output this frame if the filter says we should
+ nsIAtom* tag;
+ nsAutoString tagString;
+ mContent->GetTag(tag);
+ if (tag != nsnull)
+ {
+ tag->ToString(tagString);
+ NS_RELEASE(tag);
+ }
+
+ PRInt32 i;
+ PRBool outputMe = (PRBool)((nsnull==aFilter) || ((PR_TRUE==aFilter->OutputTag(&tagString)) && (!IsPseudoFrame())));
+ if (PR_TRUE==outputMe)
+ {
+ // Indent
+ for (i = aIndent; --i >= 0; ) fputs(" ", out);
+
+ // Output the tag
+ ListTag(out);
+ nsIView* view;
+ GetView(view);
+ if (nsnull != view) {
+ fprintf(out, " [view=%p]", view);
+ }
+
+ // Output the first/last content offset
+ fprintf(out, "[%d,%d,%c] ",
+ GetFirstContentOffset(), GetLastContentOffset(),
+ (GetLastContentIsComplete() ? 'T' : 'F'));
+ if (nsnull != mPrevInFlow) {
+ fprintf(out, "prev-in-flow=%p ", mPrevInFlow);
+ }
+ if (nsnull != mNextInFlow) {
+ fprintf(out, "next-in-flow=%p ", mNextInFlow);
+ }
+
+ // Output the rect and state
+ out << mRect;
+ if (0 != mState) {
+ fprintf(out, " [state=%08x]", mState);
+ }
+
+ #if XXX
+ // Dump run-in floaters
+ if (nsnull != mRunInFloaters) {
+ fputs(" run-in-floaters=<", out);
+ ListFloaters(out, mRunInFloaters);
+ for (i = aIndent; --i >= 0; ) fputs(" ", out);
+ fputs(">", out);
+ }
+ #endif
+ }
+
+
+ // Output the children, one line at a time
+ if (nsnull != mLines) {
+ if (PR_TRUE==outputMe)
+ fputs("<\n", out);
+ aIndent++;
+ LineData* line = mLines;
+ while (nsnull != line) {
+ line->List(out, aIndent, aFilter, outputMe);
+ line = line->mNext;
+ }
+ aIndent--;
+ if (PR_TRUE==outputMe)
+ {
+ for (i = aIndent; --i >= 0; ) fputs(" ", out);
+ fputs(">", out);
+ }
+ }
+ else {
+ if (PR_TRUE==outputMe)
+ fputs("<>", out);
+ }
+
+ if (PR_TRUE==outputMe)
+ {
+ // Output the text-runs
+ if (nsnull != mTextRuns) {
+ fputs(" text-runs=<\n", out);
+ ListTextRuns(out, aIndent + 1, mTextRuns);
+ for (i = aIndent; --i >= 0; ) fputs(" ", out);
+ fputs(">", out);
+ }
+ fputs("\n", out);
+ }
+
+ return NS_OK;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Child frame enumeration
+
+NS_IMETHODIMP
+nsBlockFrame::ChildCount(PRInt32& aChildCount) const
+{
+ PRInt32 sum = 0;
+ LineData* line = mLines;
+ while (nsnull != line) {
+ sum += line->mChildCount;
+ line = line->mNext;
+ }
+ aChildCount = sum;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::ChildAt(PRInt32 aIndex, nsIFrame*& aFrame) const
+{
+ LineData* line = mLines;
+ if ((aIndex >= 0) && (nsnull != line)) {
+ // First find the line that contains the aIndex
+ while (nsnull != line) {
+ PRInt32 n = line->mChildCount;
+ if (aIndex < n) {
+ // Then find the frame in the line
+ nsIFrame* frame = mLines->mFirstChild;
+ while (--n >= 0) {
+ if (0 == aIndex) {
+ aFrame = frame;
+ return NS_OK;
+ }
+ aIndex--;
+ frame->GetNextSibling(frame);
+ }
+ NS_NOTREACHED("line mChildCount wrong");
+ }
+ aIndex -= line->mChildCount;
+ line = line->mNext;
+ }
+ }
+
+ aFrame = nsnull;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::IndexOf(const nsIFrame* aChild, PRInt32& aIndex) const
+{
+ aIndex = -1;
+ if (nsnull != mLines) {
+ PRInt32 index = 0;
+ nsIFrame* frame = mLines->mFirstChild;
+ NS_ASSERTION(nsnull != frame, "bad mLines");
+ while (nsnull != frame) {
+ if (frame == aChild) {
+ aIndex = index;
+ break;
+ }
+ index++;
+ frame->GetNextSibling(frame);
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::FirstChild(nsIFrame*& aFirstChild) const
+{
+ aFirstChild = (nsnull != mLines) ? mLines->mFirstChild : nsnull;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::NextChild(const nsIFrame* aChild, nsIFrame*& aNextChild) const
+{
+ NS_PRECONDITION(aChild != nsnull, "null pointer");
+ aChild->GetNextSibling(aNextChild);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::PrevChild(const nsIFrame* aChild, nsIFrame*& aPrevChild) const
+{
+ NS_PRECONDITION(aChild != nsnull, "null pointer");
+ if ((nsnull != mLines) && (mLines->mFirstChild != aChild)) {
+ nsIFrame* frame = mLines->mFirstChild;
+ while (nsnull != frame) {
+ nsIFrame* nextFrame;
+ frame->GetNextSibling(nextFrame);
+ if (nextFrame == aChild) {
+ aPrevChild = frame;
+ return NS_OK;
+ }
+ frame = nextFrame;
+ }
+ }
+ aPrevChild = nsnull;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::LastChild(nsIFrame*& aLastChild) const
+{
+ LineData* line = LastLine(mLines);
+ if (nsnull != line) {
+ aLastChild = line->LastChild();
+ return NS_OK;
+ }
+ aLastChild = nsnull;
+ return NS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////
+// Reflow methods
+
+#if XXX
+PRBool
+nsBlockFrame::GetLastContentIsComplete() const
+{
+ PRBool result = PR_TRUE;
+ LineData* line = LastLine(mLines);
+ if (nsnull != line) {
+ return line->GetLastContentIsComplete();
+ }
+ return result;
+}
+
+PRInt32
+nsBlockFrame::GetFirstContentOffset() const
+{
+ PRInt32 result = 0;
+ LineData* line = mLines;
+ if (nsnull != line) {
+ line->mFirstChild->GetContentIndex(result);
+ }
+ return result;
+}
+
+PRInt32
+nsBlockFrame::GetLastContentOffset() const
+{
+ PRInt32 result = 0;
+ LineData* line = LastNonEmptyLine(mLines);
+ if (nsnull != line) {
+ line->LastChild()->GetContentIndex(result);
+ }
+ return result;
+}
+#endif
+
+NS_IMETHODIMP
+nsBlockFrame::ReflowAround(nsIPresContext& aPresContext,
+ nsISpaceManager* aSpaceManager,
+ nsReflowMetrics& aMetrics,
+ const nsReflowState& aReflowState,
+ nsRect& aDesiredRect,
+ nsReflowStatus& aStatus)
+{
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("enter nsBlockFrame::Reflow: maxSize=%d,%d reason=%d [%d,%d,%c]",
+ aReflowState.maxSize.width,
+ aReflowState.maxSize.height,
+ aReflowState.reason,
+ GetFirstContentOffset(), GetLastContentOffset(),
+ GetLastContentIsComplete()?'T':'F'));
+
+ // If this is the initial reflow, generate any synthetic content
+ // that needs generating.
+ if (eReflowReason_Initial == aReflowState.reason) {
+ NS_ASSERTION(0 != (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
+ }
+ else {
+ NS_ASSERTION(0 == (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
+ }
+
+ // Replace parent provided reflow state with our own significantly
+ // more extensive version.
+ nsBlockReflowState state(&aPresContext, aSpaceManager,
+ this, mStyleContext,
+ aReflowState, aMetrics,
+ PRBool(nsnull != aMetrics.maxElementSize));
+
+ nsresult rv = NS_OK;
+ if (eReflowReason_Initial == state.reason) {
+ if (!DrainOverflowLines()) {
+ rv = InitialReflow(state);
+ }
+ else {
+ rv = ResizeReflow(state);
+ }
+ mState &= ~NS_FRAME_FIRST_REFLOW;
+ }
+ else if (eReflowReason_Incremental == state.reason) {
+#if XXX
+ // We can have an overflow here if our parent doesn't bother to
+ // continue us
+ DrainOverflowLines();
+#endif
+ nsIFrame* target;
+ state.reflowCommand->GetTarget(target);
+ if (this == target) {
+ nsIReflowCommand::ReflowType type;
+ state.reflowCommand->GetType(type);
+ switch (type) {
+ case nsIReflowCommand::FrameAppended:
+ rv = FrameAppendedReflow(state);
+ break;
+
+ case nsIReflowCommand::FrameInserted:
+ rv = FrameInsertedReflow(state);
+ break;
+
+ case nsIReflowCommand::FrameDeleted:
+ rv = FrameDeletedReflow(state);
+ break;
+
+ default:
+ NS_NOTYETIMPLEMENTED("XXX");
+ }
+ }
+ else {
+ // Get next frame in reflow command chain
+ state.reflowCommand->GetNext(state.mInlineLayout.mNextRCFrame);
+
+ // Now do the reflow
+ rv = ChildIncrementalReflow(state);
+ }
+ }
+ else if (eReflowReason_Resize == state.reason) {
+ DrainOverflowLines();
+ rv = ResizeReflow(state);
+ }
+
+#ifdef DTPF
+ // Update content offsets; we don't track them normally but we do
+ // need them because we are a pseudo-frame
+ if (nsnull != mLines) {
+ nsIFrame* firstChild = mLines->mFirstChild;
+ if (nsnull != firstChild) {
+ firstChild->GetContentIndex(mFirstContentOffset);
+ }
+ LineData* line = mLines;
+ while (nsnull != line->mNext) {
+ NS_ASSERTION(line->mChildCount > 0, "empty line left on list");
+ line = line->mNext;
+ }
+ line->LastChild()->GetContentIndex(mLastContentOffset);
+ mLastContentIsComplete = line->GetLastContentIsComplete();
+ }
+ if (state.mBlockIsPseudo) {
+ // Tell our parent to update it's offsets because our offsets have
+ // changed.
+ nsContainerFrame* parent = (nsContainerFrame*) mGeometricParent;
+ parent->PropagateContentOffsets(this, mFirstContentOffset,
+ mLastContentOffset,
+ mLastContentIsComplete);
+ }
+#endif
+
+ // Compute our final size
+ ComputeFinalSize(state, aMetrics, aDesiredRect);
+
+#ifdef NS_DEBUG
+ if (GetVerifyTreeEnable()) {
+ VerifyChildCount(mLines);
+ VerifyLines(mLines);
+ }
+#endif
+ aStatus = rv;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("exit nsBlockFrame::Reflow: size=%d,%d rv=%x [%d,%d,%c]",
+ aMetrics.width, aMetrics.height, rv,
+ GetFirstContentOffset(), GetLastContentOffset(),
+ GetLastContentIsComplete()?'T':'F'));
+ return NS_OK;
+}
+
+nsresult
+nsBlockFrame::ProcessInitialReflow(nsIPresContext* aPresContext)
+{
+ // XXX ick; html stuff. pfuui.
+
+ if (nsnull == mPrevInFlow) {
+ const nsStyleDisplay* display = (const nsStyleDisplay*)
+ mStyleContext->GetStyleData(eStyleStruct_Display);
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::ProcessInitialReflow: display=%d",
+ display->mDisplay));
+ if (NS_STYLE_DISPLAY_LIST_ITEM == display->mDisplay) {
+ // This container is a list-item container. Therefore it needs a
+ // bullet content object. However, it might have already had the
+ // bullet crated. Check to see if the first child of the
+ // container is a synthetic object; if it is, then don't make a
+ // bullet (XXX what a hack!).
+ nsIContent* firstContent;
+ mContent->ChildAt(0, firstContent);
+ if (nsnull != firstContent) {
+ PRBool is;
+ firstContent->IsSynthetic(is);
+ NS_RELEASE(firstContent);
+ if (is) {
+ return NS_OK;
+ }
+ }
+
+ nsIHTMLContent* bullet;
+ nsresult rv = NS_NewHTMLBullet(&bullet);
+ if (NS_OK != rv) {
+ return rv;
+ }
+
+ // Insert the bullet. Do not allow an incremental reflow operation
+ // to occur.
+ mContent->InsertChildAt(bullet, 0, PR_FALSE);
+
+ // If the frame has already been initialized, then we need to create a frame
+ // for the bullet and insert it into the line list
+ if (mHasBeenInitialized) {
+ nsIStyleContext* kidSC = aPresContext->ResolveStyleContextFor(bullet, this);
+
+ nsIFrame* bulletFrame;
+ NS_NewBulletFrame(bullet, this, bulletFrame);
+ bulletFrame->SetStyleContext(aPresContext, kidSC);
+ NS_RELEASE(kidSC);
+
+ // Insert the bullet frame
+ InsertNewFrame(this, bulletFrame, nsnull);
+ }
+
+ NS_RELEASE(bullet);
+ }
+ }
+
+ return NS_OK;
+}
+
+#if XXX
+// XXX It should be impossible to write this code because we use
+// methods on nsContainerFrame that we have no right using.
+
+// XXX can't work: our parent can be an nsContainerFrame -or- an
+// nsBlockFrame; we can't tell them apart and yet the need to be
+// updated when we are a pseudo-frame
+
+void
+nsBlockFrame::PropagateContentOffsets()
+{
+ NS_PRECONDITION(IsPseudoFrame(), "not a pseudo frame");
+ nsIFrame* parent = mGeometricParent;
+ if (nsnull != parent) {
+ // If we're the first child frame then update our parent's content offset
+ nsIFrame* firstChild;
+ parent->FirstChild(firstChild);
+ if (firstChild == this) {
+ parent->SetFirstContentOffset(GetFirstContentOffset());
+ }
+
+ // If we're the last child frame then update our parent's content offset
+ if (nsnull == mNextSibling) {
+ parent->SetLastContentOffset(GetLastContentOffset());
+ parent->SetLastContentIsComplete(GetLastContentIsComplete());
+ }
+
+ // If the parent is being used as a pseudo frame then we need to propagate
+ // the content offsets upwards to its parent frame
+ if (parent->IsPseudoFrame()) {
+ parent->PropagateContentOffsets();
+ }
+ }
+}
+#endif
+
+void
+nsBlockFrame::ComputeFinalSize(nsBlockReflowState& aState,
+ nsReflowMetrics& aMetrics,
+ nsRect& aDesiredRect)
+{
+ aDesiredRect.x = 0;
+ aDesiredRect.y = 0;
+
+ // Special check for zero sized content: If our content is zero
+ // sized then we collapse into nothingness.
+ if ((0 == aState.mKidXMost - aState.mBorderPadding.left) &&
+ (0 == aState.mY - aState.mBorderPadding.top)) {
+ aDesiredRect.width = 0;
+ aDesiredRect.height = 0;
+ aMetrics.posBottomMargin = 0;
+ }
+ else {
+ aDesiredRect.width = aState.mKidXMost + aState.mBorderPadding.right;
+ if (!aState.mUnconstrainedWidth) {
+ // Make sure we're at least as wide as the max size we were given
+ nscoord mw = aState.maxSize.width/* + aState.mBulletPaddingXXX*/;
+ if (aDesiredRect.width < mw) {
+ aDesiredRect.width = mw;
+ }
+ }
+ if (0 != aState.mBorderPadding.bottom) {
+ aState.mY += aState.mBorderPadding.bottom;
+ aMetrics.posBottomMargin = 0;
+ }
+ else {
+ aMetrics.posBottomMargin = aState.mPrevBottomMargin;
+ }
+ aDesiredRect.height = aState.mY;
+
+ if (!aState.mBlockIsPseudo) {
+ // Clamp the desired rect height when style height applies
+ PRIntn ss = aState.mStyleSizeFlags;
+ if (0 != (ss & NS_SIZE_HAS_HEIGHT)) {
+ aDesiredRect.height = aState.mBorderPadding.top +
+ aState.mStyleSize.height + aState.mBorderPadding.bottom;
+ }
+ }
+ }
+
+ aMetrics.width = aDesiredRect.width;
+ aMetrics.height = aDesiredRect.height;
+ aMetrics.ascent = aMetrics.height;
+ aMetrics.descent = 0;
+ if (aState.mComputeMaxElementSize) {
+ *aMetrics.maxElementSize = aState.mMaxElementSize;
+
+ // Add in our border and padding to the max-element-size so that
+ // we don't shrink too far.
+ aMetrics.maxElementSize->width += aState.mBorderPadding.left +
+ aState.mBorderPadding.right;
+ aMetrics.maxElementSize->height += aState.mBorderPadding.top +
+ aState.mBorderPadding.bottom;
+
+ // Factor in any left and right floaters as well
+ LineData* line = mLines;
+ PRInt32 maxLeft = 0, maxRight = 0;
+ while (nsnull != line) {
+ if (nsnull != line->mFloaters) {
+ nsRect r;
+ nsMargin floaterMargin;
+ PRInt32 leftSum = 0, rightSum = 0;
+ PRInt32 n = line->mFloaters->Count();
+ for (PRInt32 i = 0; i < n; i++) {
+ nsPlaceholderFrame* placeholder = (nsPlaceholderFrame*)
+ line->mFloaters->ElementAt(i);
+ nsIFrame* floater = placeholder->GetAnchoredItem();
+ floater->GetRect(r);
+ const nsStyleDisplay* floaterDisplay;
+ const nsStyleSpacing* floaterSpacing;
+ floater->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)floaterDisplay);
+ floater->GetStyleData(eStyleStruct_Spacing,
+ (const nsStyleStruct*&)floaterSpacing);
+ floaterSpacing->CalcMarginFor(floater, floaterMargin);
+ nscoord width = r.width + floaterMargin.left + floaterMargin.right;
+ switch (floaterDisplay->mFloats) {
+ default:
+ NS_NOTYETIMPLEMENTED("Unsupported floater type");
+ // FALL THROUGH
+
+ case NS_STYLE_FLOAT_LEFT:
+ leftSum += width;
+ break;
+
+ case NS_STYLE_FLOAT_RIGHT:
+ rightSum += width;
+ break;
+ }
+ }
+ if (leftSum > maxLeft) maxLeft = leftSum;
+ if (rightSum > maxRight) maxRight = rightSum;
+ }
+ line = line->mNext;
+ }
+ aMetrics.maxElementSize->width += maxLeft + maxRight;
+ }
+ NS_ASSERTION(aDesiredRect.width < 1000000, "whoops");
+}
+
+nsresult
+nsBlockFrame::AppendNewFrames(nsIPresContext* aPresContext, nsIFrame* aNewFrame)
+{
+ // Get our last line and then get its last child
+ nsIFrame* lastFrame;
+ LineData* lastLine = LastLine(mLines);
+ if (nsnull != lastLine) {
+ lastFrame = lastLine->LastChild();
+ } else {
+ lastFrame = nsnull;
+ }
+
+ // Add the new frames to the sibling list
+ if (nsnull != lastFrame) {
+ lastFrame->SetNextSibling(aNewFrame);
+ }
+
+ // Make sure that new inlines go onto the end of the lastLine when
+ // the lastLine is mapping inline frames.
+ PRInt32 pendingInlines = 0;
+ if (nsnull != lastLine) {
+ if (!lastLine->IsBlock()) {
+ pendingInlines = 1;
+ }
+ }
+
+ // Now create some lines for the new frames
+ nsIFrame* prevFrame = lastFrame;
+ nsresult rv;
+ for (nsIFrame* frame = aNewFrame; nsnull != frame; frame->GetNextSibling(frame)) {
+ // See if the child is a block or non-block
+ const nsStyleDisplay* kidDisplay;
+ rv = frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&) kidDisplay);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ const nsStylePosition* kidPosition;
+ rv = frame->GetStyleData(eStyleStruct_Position,
+ (const nsStyleStruct*&) kidPosition);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ PRBool isBlock =
+ nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition);
+
+ // See if the element wants to be floated
+ if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) {
+ // Create a placeholder frame that will serve as the anchor point.
+ nsPlaceholderFrame* placeholder =
+ CreatePlaceholderFrame(aPresContext, frame);
+
+ // Remove the floated element from the flow, and replace it with the
+ // placeholder frame
+ if (nsnull != prevFrame) {
+ prevFrame->SetNextSibling(placeholder);
+ }
+ nsIFrame* nextSibling;
+ frame->GetNextSibling(nextSibling);
+ placeholder->SetNextSibling(nextSibling);
+ frame->SetNextSibling(nsnull);
+
+ // If the floated element can contain children then wrap it in a
+ // BODY frame before floating it
+ nsIContent* content;
+ PRBool isContainer;
+
+ frame->GetContent(content);
+ content->CanContainChildren(isContainer);
+ if (isContainer) {
+ // Wrap the floated element in a BODY frame.
+ nsIFrame* wrapperFrame;
+ NS_NewBodyFrame(content, this, wrapperFrame);
+
+ // The body wrapper frame gets the original style context, and the floated
+ // frame gets a pseudo style context
+ nsIStyleContext* kidStyle;
+ frame->GetStyleContext(aPresContext, kidStyle);
+ wrapperFrame->SetStyleContext(aPresContext, kidStyle);
+ NS_RELEASE(kidStyle);
+
+ nsIStyleContext* pseudoStyle;
+ pseudoStyle = aPresContext->ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo,
+ wrapperFrame);
+ frame->SetStyleContext(aPresContext, pseudoStyle);
+ NS_RELEASE(pseudoStyle);
+
+ // Init the body frame
+ wrapperFrame->Init(*aPresContext, frame);
+
+ // Bind the wrapper frame to the placeholder
+ placeholder->SetAnchoredItem(wrapperFrame);
+ }
+ NS_RELEASE(content);
+
+ // The placeholder frame is always inline
+ frame = placeholder;
+ isBlock = PR_FALSE;
+ }
+
+ // If the child is an inline then add it to the lastLine (if it's
+ // an inline line, otherwise make a new line). If the child is a
+ // block then make a new line and put the child in that line.
+ if (isBlock) {
+ // If the previous line has pending inline data to be reflowed,
+ // do so now.
+ if (0 != pendingInlines) {
+ // Set this to true in case we don't end up reflowing all of the
+ // frames on the line (because they end up being pushed).
+ lastLine->SetLastContentIsComplete();
+ lastLine->MarkDirty();
+ pendingInlines = 0;
+ }
+
+ // Create a line for the block
+ LineData* line = new LineData(frame, 1,
+ (LINE_IS_BLOCK |
+ LINE_LAST_CONTENT_IS_COMPLETE));
+ if (nsnull == line) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ if (nsnull == lastLine) {
+ mLines = line;
+ }
+ else {
+ lastLine->mNext = line;
+ }
+ lastLine = line;
+ }
+ else {
+ // Queue up the inlines for reflow later on
+ if (0 == pendingInlines) {
+ LineData* line = new LineData(frame, 0, 0);
+ if (nsnull == line) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ if (nsnull == lastLine) {
+ mLines = line;
+ }
+ else {
+ lastLine->mNext = line;
+ }
+ lastLine = line;
+ }
+ lastLine->mChildCount++;
+ pendingInlines++;
+ }
+
+ // Remember the previous frame
+ prevFrame = frame;
+ }
+
+ if (0 != pendingInlines) {
+ // Set this to true in case we don't end up reflowing all of the
+ // frames on the line (because they end up being pushed).
+ lastLine->SetLastContentIsComplete();
+ lastLine->MarkDirty();
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsBlockFrame::InitialReflow(nsBlockReflowState& aState)
+{
+ // Create synthetic content (XXX a hack)
+ nsresult rv = ProcessInitialReflow(aState.mPresContext);
+ if (NS_OK != rv) {
+ return rv;
+ }
+
+ // XXX CONSTRUCTION
+ // Temporary hack. If we haven't had Init() called then go ahead and create
+ // frames the old way. This is needed until tables get converted...
+
+ // Create new frames
+ if (!mHasBeenInitialized) {
+ if (nsnull == mNextInFlow) {
+ rv = CreateNewFrames(aState.mPresContext);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ }
+ }
+
+ // Generate text-run information
+ rv = FindTextRuns(aState);
+ if (NS_OK != rv) {
+ return rv;
+ }
+
+ // Reflow everything
+ aState.GetAvailableSpace();
+ return ResizeReflow(aState);
+}
+
+nsresult
+nsBlockFrame::FrameAppendedReflow(nsBlockReflowState& aState)
+{
+ // XXX CONSTRUCTION
+#if 0
+ // Create new frames for the appended content. Each line that is
+ // impacted by this will be marked dirty.
+ nsresult rv = CreateNewFrames(aState.mPresContext);
+ if (NS_OK != rv) {
+ return rv;
+ }
+#else
+ nsresult rv = NS_OK;
+
+ // Get the first of the newly appended frames
+ nsIFrame* firstAppendedFrame;
+ aState.reflowCommand->GetChildFrame(firstAppendedFrame);
+
+ // Add the new frames to the child list, and create new lines. Each
+ // impacted line will be marked dirty
+ AppendNewFrames(aState.mPresContext, firstAppendedFrame);
+#endif
+
+ // Generate text-run information
+ rv = FindTextRuns(aState);
+ if (NS_OK != rv) {
+ return rv;
+ }
+
+ // Recover our reflow state. First find the lastCleanLine and the
+ // firstDirtyLine which follows it. While we are looking, compute
+ // the maximum xmost of each line.
+ LineData* firstDirtyLine = mLines;
+ LineData* lastCleanLine = nsnull;
+ LineData* lastYLine = nsnull;
+ while (nsnull != firstDirtyLine) {
+ if (firstDirtyLine->IsDirty()) {
+ break;
+ }
+ nscoord xmost = firstDirtyLine->mBounds.XMost();
+NS_ASSERTION(xmost < 1000000, "bad line width");
+ if (xmost > aState.mKidXMost) {
+ aState.mKidXMost = xmost;
+ }
+ if (firstDirtyLine->mBounds.height > 0) {
+ lastYLine = firstDirtyLine;
+ }
+ lastCleanLine = firstDirtyLine;
+ firstDirtyLine = firstDirtyLine->mNext;
+ }
+
+ // Recover the starting Y coordinate and the previous bottom margin
+ // value.
+ if (nsnull != lastCleanLine) {
+ // If the lastCleanLine is not a block but instead is a zero
+ // height inline line then we need to backup to either a non-zero
+ // height line.
+ aState.mPrevBottomMargin = 0;
+ if (nsnull != lastYLine) {
+ aState.mPrevBottomMargin = lastYLine->mInnerBottomMargin +
+ lastYLine->mOuterBottomMargin;
+ }
+
+ // Start the Y coordinate after the last clean line.
+ aState.mY = lastCleanLine->mBounds.YMost();
+
+ // Add in the outer margin to the Y coordinate (the inner margin
+ // will be present in the lastCleanLine's YMost so don't add it
+ // in again)
+ aState.mY += lastCleanLine->mOuterBottomMargin;
+
+ // XXX I'm not sure about the previous statement and floaters!!!
+
+ // Place any floaters the line has
+ if (nsnull != lastCleanLine->mFloaters) {
+ aState.mCurrentLine = lastCleanLine;
+ aState.PlaceFloaters(lastCleanLine->mFloaters);
+ }
+ }
+
+ aState.GetAvailableSpace();
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockReflowState::FrameAppendedReflow: y=%d firstDirtyLine=%p",
+ aState.mY, firstDirtyLine));
+
+ // Reflow lines from there forward
+ aState.mPrevLine = lastCleanLine;
+ return ReflowLinesAt(aState, firstDirtyLine);
+}
+
+nsresult
+nsBlockFrame::CreateNewFrames(nsIPresContext* aPresContext)
+{
+ // If we need to be continued but aren't, we will have an overflow list
+ NS_ASSERTION((nsnull == mOverflowLines) && (nsnull == mNextInFlow),
+ "bad call to CreateNewFrames");
+
+ // Get our last line and then get its last child. Use that
+ // information to determine our kidContentIndex.
+ LineData* lastLine = LastLine(mLines);
+ nsIFrame* lastFrame;
+ PRInt32 kidContentIndex;
+ if (nsnull != lastLine) {
+ lastFrame = lastLine->LastChild();
+ lastFrame->GetContentIndex(kidContentIndex);
+ if (lastLine->GetLastContentIsComplete()) {
+ kidContentIndex++;
+ }
+ else {
+#ifdef NS_DEBUG
+ // Because we always create continuations as we find them (XXX
+ // sigh) instead of when we need them, we can assert that if the
+ // last child is not complete then it already has a continuation.
+ nsIFrame* kidNextInFlow;
+ lastFrame->GetNextInFlow(kidNextInFlow);
+ NS_ASSERTION(nsnull != kidNextInFlow, "whoops");
+#endif
+ }
+ }
+ else {
+ // We can't have an empty line list and have a prev-in-flow. If we
+ // have a prev-in-flow then we are its continuation which means it
+ // must have pushed some lines into its overflow list; therefore
+ // we must have some lines.
+ NS_ASSERTION(nsnull == mPrevInFlow, "prev-in-flow without overflow lines");
+ lastFrame = nsnull;
+ kidContentIndex = 0;
+ }
+
+ // Make sure that new inlines go onto the end of the lastLine when
+ // the lastLine is mapping inline frames.
+ PRInt32 pendingInlines = 0;
+ if (nsnull != lastLine) {
+ if (!lastLine->IsBlock()) {
+ pendingInlines = 1;
+ }
+ }
+
+ // Now create frames for all of the new content.
+ nsresult rv;
+ PRInt32 lastContentIndex;
+ mContent->ChildCount(lastContentIndex);
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("enter nsBlockFrame::CreateNewFrames: kidContentIndex=%d lastContentIndex=%d",
+ kidContentIndex, lastContentIndex));
+ for (; kidContentIndex < lastContentIndex; kidContentIndex++) {
+ nsIContent* kid;
+ mContent->ChildAt(kidContentIndex, kid);
+ if (nsnull == kid) {
+ break;
+ }
+
+ // Create frame for our new child and add it to the sibling list
+ nsIFrame* frame;
+ rv = nsHTMLBase::CreateFrame(aPresContext, this, kid, nsnull, frame);
+ NS_RELEASE(kid);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ if (nsnull != lastFrame) {
+ lastFrame->SetNextSibling(frame);
+ }
+ lastFrame = frame;
+//XXX childPrevInFlow = nsnull;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_NEW_FRAMES,
+ ("nsBlockFrame::CreateNewFrames: new-frame=%p", frame));
+
+ // See if the child is a block or non-block
+ const nsStyleDisplay* kidDisplay;
+ rv = frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&) kidDisplay);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ const nsStylePosition* kidPosition;
+ rv = frame->GetStyleData(eStyleStruct_Position,
+ (const nsStyleStruct*&) kidPosition);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ PRBool isBlock =
+ nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition);
+
+ // If the child is an inline then add it to the lastLine (if it's
+ // an inline line, otherwise make a new line). If the child is a
+ // block then make a new line and put the child in that line.
+ if (isBlock) {
+ // If the previous line has pending inline data to be reflowed,
+ // do so now.
+ if (0 != pendingInlines) {
+ // Set this to true in case we don't end up reflowing all of the
+ // frames on the line (because they end up being pushed).
+ lastLine->SetLastContentIsComplete();
+ lastLine->MarkDirty();
+ pendingInlines = 0;
+ }
+
+ // Create a line for the block
+ LineData* line = new LineData(frame, 1,
+ (LINE_IS_BLOCK |
+ LINE_LAST_CONTENT_IS_COMPLETE));
+ if (nsnull == line) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ if (nsnull == lastLine) {
+ mLines = line;
+ }
+ else {
+ lastLine->mNext = line;
+ }
+ lastLine = line;
+ }
+ else {
+ // Queue up the inlines for reflow later on
+ if (0 == pendingInlines) {
+ LineData* line = new LineData(frame, 0, 0);
+ if (nsnull == line) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ if (nsnull == lastLine) {
+ mLines = line;
+ }
+ else {
+ lastLine->mNext = line;
+ }
+ lastLine = line;
+ }
+ lastLine->mChildCount++;
+ pendingInlines++;
+ }
+ }
+
+ if (0 != pendingInlines) {
+ // Set this to true in case we don't end up reflowing all of the
+ // frames on the line (because they end up being pushed).
+ lastLine->SetLastContentIsComplete();
+ lastLine->MarkDirty();
+ }
+
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("exit nsBlockFrame::CreateNewFrames"));
+ return NS_OK;
+}
+
+// XXX keep the text-run data in the first-in-flow of the block
+nsresult
+nsBlockFrame::FindTextRuns(nsBlockReflowState& aState)
+{
+ // Destroy old run information first
+ nsTextRun::DeleteTextRuns(mTextRuns);
+ mTextRuns = nsnull;
+ aState.mLineLayout.ResetTextRuns();
+
+ // Ask each child that implements nsIInlineReflow to find its text runs
+ LineData* line = mLines;
+ while (nsnull != line) {
+ if (!line->IsBlock()) {
+ nsIFrame* frame = line->mFirstChild;
+ PRInt32 n = line->mChildCount;
+ while (--n >= 0) {
+ nsIInlineReflow* inlineReflow;
+ if (NS_OK == frame->QueryInterface(kIInlineReflowIID,
+ (void**)&inlineReflow)) {
+ nsresult rv = inlineReflow->FindTextRuns(aState.mLineLayout,
+ aState.reflowCommand);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ }
+ else {
+ // A frame that doesn't implement nsIInlineReflow isn't text
+ // therefore it will end an open text run.
+ aState.mLineLayout.EndTextRun();
+ }
+ frame->GetNextSibling(frame);
+ }
+ }
+ else {
+ // A frame that doesn't implement nsIInlineReflow isn't text
+ // therefore it will end an open text run.
+ aState.mLineLayout.EndTextRun();
+ }
+ line = line->mNext;
+ }
+ aState.mLineLayout.EndTextRun();
+
+ // Now take the text-runs away from the line layout engine.
+ mTextRuns = aState.mLineLayout.TakeTextRuns();
+
+ return NS_OK;
+}
+
+nsresult
+nsBlockFrame::FrameInsertedReflow(nsBlockReflowState& aState)
+{
+ LineData* line = mLines;
+ while (nsnull != line->mNext) {
+ if (line->IsDirty()) {
+ break;
+ }
+ line = line->mNext;
+ }
+ NS_ASSERTION(nsnull != line, "bad inserted reflow");
+ //XXX return ReflowDirtyLines(aState, line);
+
+ // XXX Correct implementation: reflow the dirty lines only; all
+ // other lines can be moved; recover state before first dirty line.
+
+ // XXX temporary
+ aState.GetAvailableSpace();
+ aState.mPrevLine = nsnull;
+ return ReflowLinesAt(aState, mLines);
+}
+
+nsresult
+nsBlockFrame::FrameDeletedReflow(nsBlockReflowState& aState)
+{
+ if (nsnull == mLines) {
+ return NS_OK;
+ }
+ LineData* line = mLines;
+ while (nsnull != line->mNext) {
+ if (line->IsDirty()) {
+ break;
+ }
+ line = line->mNext;
+ }
+ NS_ASSERTION(nsnull != line, "bad inserted reflow");
+ //XXX return ReflowDirtyLines(aState, line);
+
+ // XXX Correct implementation: reflow the dirty lines only; all
+ // other lines can be moved; recover state before first dirty line.
+
+ // XXX temporary
+ aState.GetAvailableSpace();
+ aState.mPrevLine = nsnull;
+ return ReflowLinesAt(aState, mLines);
+}
+
+// XXX Todo: some incremental reflows are passing through this block
+// and into a child block; those cannot impact our text-runs. In that
+// case skip the FindTextRuns work.
+
+// XXX easy optimizations: find the line that contains the next child
+// in the reflow-command path and mark it dirty and only reflow it;
+// recover state before it, slide lines down after it.
+
+nsresult
+nsBlockFrame::ChildIncrementalReflow(nsBlockReflowState& aState)
+{
+ // Generate text-run information; this will also "fluff out" any
+ // inline children's frame tree.
+ nsresult rv = FindTextRuns(aState);
+ if (NS_OK != rv) {
+ return rv;
+ }
+
+ // XXX temporary
+ aState.GetAvailableSpace();
+ aState.mPrevLine = nsnull;
+ return ReflowLinesAt(aState, mLines);
+}
+
+nsresult
+nsBlockFrame::ResizeReflow(nsBlockReflowState& aState)
+{
+ // Mark everything dirty
+ LineData* line = mLines;
+ while (nsnull != line) {
+ line->MarkDirty();
+ line = line->mNext;
+ }
+
+ // Reflow all of our lines
+ aState.GetAvailableSpace();
+ aState.mPrevLine = nsnull;
+ return ReflowLinesAt(aState, mLines);
+}
+
+nsresult
+nsBlockFrame::ReflowLinesAt(nsBlockReflowState& aState, LineData* aLine)
+{
+#if XXX
+ if ((nsnull != mRunInFloaters) && (aLine == mLines)) {
+ aState.PlaceBelowCurrentLineFloaters(mRunInFloaters);
+ }
+#endif
+
+ // Reflow the lines that are already ours
+ while (nsnull != aLine) {
+ nsInlineReflowStatus rs;
+ if (!ReflowLine(aState, aLine, rs)) {
+ if (NS_IS_REFLOW_ERROR(rs)) {
+ return nsresult(rs);
+ }
+ return NS_FRAME_NOT_COMPLETE;
+ }
+ aState.mLineLayout.NextLine();
+ aState.mPrevLine = aLine;
+ aLine = aLine->mNext;
+ }
+
+ // Pull data from a next-in-flow if we can
+ while (nsnull != aState.mNextInFlow) {
+ // Grab first line from our next-in-flow
+ aLine = aState.mNextInFlow->mLines;
+ if (nsnull == aLine) {
+ aState.mNextInFlow = (nsBlockFrame*) aState.mNextInFlow->mNextInFlow;
+ continue;
+ }
+ // XXX See if the line is not dirty; if it's not maybe we can
+ // avoid the pullup if it can't fit?
+ aState.mNextInFlow->mLines = aLine->mNext;
+ aLine->mNext = nsnull;
+ if (0 == aLine->mChildCount) {
+ // The line is empty. Try the next one.
+ NS_ASSERTION(nsnull == aLine->mChildCount, "bad empty line");
+ aLine->mNext = aState.mFreeList;
+ aState.mFreeList = aLine;
+ continue;
+ }
+
+ // Make the children in the line ours.
+ nsIFrame* frame = aLine->mFirstChild;
+ nsIFrame* lastFrame = nsnull;
+ PRInt32 n = aLine->mChildCount;
+ while (--n >= 0) {
+ nsIFrame* geometricParent;
+ nsIFrame* contentParent;
+ frame->GetGeometricParent(geometricParent);
+ frame->GetContentParent(contentParent);
+ if (contentParent == geometricParent) {
+ frame->SetContentParent(this);
+ }
+ frame->SetGeometricParent(this);
+ lastFrame = frame;
+ frame->GetNextSibling(frame);
+ }
+ lastFrame->SetNextSibling(nsnull);
+
+#ifdef NS_DEBUG
+ LastChild(lastFrame);
+ NS_ASSERTION(lastFrame == aState.mPrevChild, "bad aState.mPrevChild");
+#endif
+
+ // Add line to our line list
+ if (nsnull == aState.mPrevLine) {
+ NS_ASSERTION(nsnull == mLines, "bad aState.mPrevLine");
+ mLines = aLine;
+ }
+ else {
+ NS_ASSERTION(nsnull == aState.mPrevLine->mNext, "bad aState.mPrevLine");
+ aState.mPrevLine->mNext = aLine;
+ aState.mPrevChild->SetNextSibling(aLine->mFirstChild);
+ }
+#ifdef NS_DEBUG
+ if (GetVerifyTreeEnable()) {
+ VerifyChildCount(mLines);
+ }
+#endif
+
+ // Now reflow it and any lines that it makes during it's reflow.
+ while (nsnull != aLine) {
+ nsInlineReflowStatus rs;
+ if (!ReflowLine(aState, aLine, rs)) {
+ if (NS_IS_REFLOW_ERROR(rs)) {
+ return nsresult(rs);
+ }
+ return NS_FRAME_NOT_COMPLETE;
+ }
+ aState.mLineLayout.NextLine();
+ aState.mPrevLine = aLine;
+ aLine = aLine->mNext;
+ }
+ }
+
+ return NS_FRAME_COMPLETE;
+}
+
+/**
+ * Reflow a line. The line will either contain a single block frame
+ * or contain 1 or more inline frames.
+ */
+PRBool
+nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsInlineReflowStatus& aReflowResult)
+{
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::ReflowLine: line=%p", aLine));
+
+ PRBool keepGoing = PR_FALSE;
+ nsBlockFrame* nextInFlow;
+ aState.mCurrentLine = aLine;
+ aState.mInlineLayoutPrepared = PR_FALSE;
+ aLine->ClearDirty();
+ aLine->SetNeedDidReflow();
+
+ // XXX temporary SLOW code
+ if (nsnull != aLine->mFloaters) {
+ delete aLine->mFloaters;
+ aLine->mFloaters = nsnull;
+ }
+
+ // Reflow mapped frames in the line
+ PRInt32 n = aLine->mChildCount;
+ if (0 != n) {
+ nsIFrame* frame = aLine->mFirstChild;
+#ifdef NS_DEBUG
+ const nsStyleDisplay* display;
+ frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&) display);
+ const nsStylePosition* position;
+ frame->GetStyleData(eStyleStruct_Position,
+ (const nsStyleStruct*&) position);
+ PRBool isBlock = nsLineLayout::TreatFrameAsBlock(display, position);
+ NS_ASSERTION(isBlock == aLine->IsBlock(), "bad line isBlock");
+#endif
+ if (aLine->IsBlock()) {
+ keepGoing = ReflowBlockFrame(aState, aLine, frame, aReflowResult);
+ return keepGoing;
+ }
+ else {
+ while (--n >= 0) {
+ keepGoing = ReflowInlineFrame(aState, aLine, frame, aReflowResult);
+ if (!keepGoing) {
+ // It is possible that one or more of next lines are empty
+ // (because of DeleteNextInFlowsFor). If so, delete them now
+ // in case we are finished.
+ LineData* nextLine = aLine->mNext;
+ while ((nsnull != nextLine) && (0 == nextLine->mChildCount)) {
+ // Discard empty lines immediately. Empty lines can happen
+ // here because of DeleteNextInFlowsFor not being able to
+ // delete lines.
+ aLine->mNext = nextLine->mNext;
+ NS_ASSERTION(nsnull == nextLine->mFirstChild, "bad empty line");
+ nextLine->mNext = aState.mFreeList;
+ aState.mFreeList = nextLine;
+ nextLine = aLine->mNext;
+ }
+ goto done;
+ }
+ frame->GetNextSibling(frame);
+ }
+ }
+ }
+
+ // Pull frames from the next line until we can't
+ while (nsnull != aLine->mNext) {
+ keepGoing = PullFrame(aState, aLine, &aLine->mNext,
+ PR_FALSE, aReflowResult);
+ if (!keepGoing) {
+ goto done;
+ }
+ }
+
+ // Pull frames from the next-in-flow(s) until we can't
+ nextInFlow = aState.mNextInFlow;
+ while (nsnull != nextInFlow) {
+ LineData* line = nextInFlow->mLines;
+ if (nsnull == line) {
+ nextInFlow = (nsBlockFrame*) nextInFlow->mNextInFlow;
+ aState.mNextInFlow = nextInFlow;
+ continue;
+ }
+ keepGoing = PullFrame(aState, aLine, &nextInFlow->mLines,
+ PR_TRUE, aReflowResult);
+ if (!keepGoing) {
+ goto done;
+ }
+ }
+ keepGoing = PR_TRUE;
+
+done:;
+ if (!aLine->IsBlock()) {
+ return PlaceLine(aState, aLine, aReflowResult);
+ }
+ return keepGoing;
+}
+
+PRBool
+nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsIFrame* aFrame,
+ nsInlineReflowStatus& aReflowResult)
+{
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockFrame::ReflowBlockFrame: line=%p frame=%p y=%d",
+ aLine, aFrame, aState.mY));
+
+ NS_ASSERTION(nsnull != aState.mSpaceManager, "null ptr");
+
+ // Get run-around interface if frame supports it
+ nsIRunaround* runAround = nsnull;
+ aFrame->QueryInterface(kIRunaroundIID, (void**)&runAround);
+
+ // Get the child margins
+ nsMargin childMargin;
+ const nsStyleSpacing* childSpacing;
+ aFrame->GetStyleData(eStyleStruct_Spacing,
+ (const nsStyleStruct*&)childSpacing);
+ childSpacing->CalcMarginFor(aFrame, childMargin);
+ const nsStyleDisplay* childDisplay;
+ aFrame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)childDisplay);
+
+ // XXX Negative margins are set to zero; we could do better SOMEDAY
+ // Compute the top margin to apply to the child block
+ nscoord totalTopMargin = 0;
+ nscoord topMargin = 0;
+ nscoord childTopMargin = 0;
+ nscoord childBottomMargin = 0;
+ if (childSpacing->mMargin.GetTopUnit() <= eStyleUnit_Auto) {
+ // Provide an ebina style margin of 1 blank line before this block
+ // for most block elements.
+ // XXX need a complete list of the ones that he does this for
+ if (NS_STYLE_DISPLAY_LIST_ITEM != childDisplay->mDisplay) {
+ if (IsPseudoFrame() && (aState.mY == aState.mBorderPadding.top)) {
+ childTopMargin = 0;
+ }
+ else {
+ const nsFont& defaultFont = aState.mPresContext->GetDefaultFont();
+ nsIFontMetrics* fm = aState.mPresContext->GetMetricsFor(defaultFont);
+ fm->GetHeight(childTopMargin);
+ NS_RELEASE(fm);
+ }
+ }
+ }
+ else {
+ childTopMargin = childMargin.top;
+ if (childTopMargin < 0) childTopMargin = 0;
+ }
+ if (aState.mY == aState.mBorderPadding.top) {
+ // Since this is our first child we need to collapse its top
+ // margin with our top margin.
+ if (0 != aState.mBorderPadding.top) {
+ // Since we have a border/padding value the childs top margin
+ // does not collapse with our top margin.
+ topMargin = childTopMargin;
+ }
+ else {
+ nscoord outerTopMargin = aState.mOuterTopMargin;
+ if (childTopMargin > outerTopMargin) {
+ topMargin = childTopMargin - outerTopMargin;
+ totalTopMargin = childTopMargin;
+ }
+ else {
+ totalTopMargin = outerTopMargin;
+ }
+ }
+ }
+ else {
+ // For other children we collapse the margins between them.
+ if (childTopMargin > aState.mPrevBottomMargin) {
+ topMargin = childTopMargin - aState.mPrevBottomMargin;
+ totalTopMargin = childTopMargin;
+ }
+ else {
+ totalTopMargin = aState.mPrevBottomMargin;
+ }
+ }
+ if (childSpacing->mMargin.GetBottomUnit() > eStyleUnit_Auto) {
+ childBottomMargin = childMargin.bottom;
+ if (childBottomMargin < 0) childBottomMargin = 0;
+ }
+
+ // Compute the available space that the child block can reflow into
+ // and the starting x,y coordinate.
+ nscoord x;
+ if (nsnull == runAround) {
+ // When there is no run-around API the coordinates must include
+ // any impact by floaters.
+ x = aState.mCurrentBand.availSpace.x;
+ }
+ else {
+ // When the child does implement the run-around API it will deal
+ // with any floater impact itself.
+ x = aState.mX;
+ }
+ x += childMargin.left + aState.mBulletPadding;
+ nscoord y = aState.mY + topMargin;
+ nsSize availSize;
+ if (aState.mUnconstrainedWidth) {
+ availSize.width = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ availSize.width = aState.mInnerSize.width -
+ (childMargin.left + childMargin.right + aState.mBulletPadding);
+ }
+ if (aState.mUnconstrainedHeight) {
+ availSize.height = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ availSize.height = aState.mBottomEdge - (y + childBottomMargin);
+ }
+ if (NS_STYLE_DISPLAY_LIST_ITEM == childDisplay->mDisplay) {
+ // Special handling for list-item children that have outside
+ // bullets.
+ const nsStyleList* sl;
+ aFrame->GetStyleData(eStyleStruct_List,
+ (const nsStyleStruct*&) sl);
+ if (NS_STYLE_LIST_STYLE_POSITION_OUTSIDE == sl->mListStylePosition) {
+ // Slide child list item so that it's just past our border; it
+ // will use our padding area to place its bullet.
+ x -= aState.mLeftPadding;
+ availSize.width += aState.mLeftPadding;
+ }
+ }
+ aFrame->WillReflow(*aState.mPresContext);
+ aFrame->MoveTo(x, y);
+
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockFrame::ReflowBlockFrame: xy={%d,%d} availSize={%d,%d}",
+ x, y, availSize.width, availSize.height));
+
+ // Determine the reason for the reflow
+ nsReflowReason reason = eReflowReason_Resize;
+ nsFrameState state;
+ aFrame->GetFrameState(state);
+ if (NS_FRAME_FIRST_REFLOW & state) {
+ reason = eReflowReason_Initial;
+ }
+ else if (aState.mInlineLayout.mNextRCFrame == aFrame) {
+ reason = eReflowReason_Incremental;
+ // Make sure we only incrementally reflow once
+ aState.mInlineLayout.mNextRCFrame = nsnull;
+ }
+
+ // Reflow the block frame. Use the run-around API if possible;
+ // otherwise treat it as a rectangular lump and place it.
+ nsresult rv;
+ nsSize kidMaxElementSize;
+ nsReflowMetrics metrics(aState.mComputeMaxElementSize
+ ? &kidMaxElementSize
+ : nsnull);
+ metrics.posTopMargin = totalTopMargin;
+ nsReflowStatus reflowStatus;
+
+ if (nsnull != runAround) {
+ // Reflow the block
+ nsReflowState reflowState(aFrame, aState, availSize);
+ reflowState.reason = reason;
+ nsRect r;
+ aState.mSpaceManager->Translate(x, y);
+ rv = runAround->ReflowAround(*aState.mPresContext, aState.mSpaceManager,
+ metrics, reflowState, r, reflowStatus);
+ aState.mSpaceManager->Translate(-x, -y);
+ metrics.width = r.width;
+ metrics.height = r.height;
+ metrics.ascent = r.height;
+ metrics.descent = 0;
+ }
+ else {
+ nsReflowState reflowState(aFrame, aState, availSize);
+ reflowState.reason = reason;
+ aState.mSpaceManager->Translate(x, y);
+ rv = aFrame->Reflow(*aState.mPresContext, metrics, reflowState,
+ reflowStatus);
+ aState.mSpaceManager->Translate(-x, -y);
+ }
+
+// XXX we need to do this because blocks depend on it; we shouldn't expect
+// the child frame to deal with it.
+ if (eReflowReason_Initial == reason) {
+ aFrame->GetFrameState(state);
+ aFrame->SetFrameState(state & ~NS_FRAME_FIRST_REFLOW);
+ }
+
+ if (NS_IS_REFLOW_ERROR(rv)) {
+ aReflowResult = nsInlineReflowStatus(rv);
+ return PR_FALSE;
+ }
+
+ if (NS_FRAME_IS_COMPLETE(reflowStatus)) {
+ nsIFrame* kidNextInFlow;
+ aFrame->GetNextInFlow(kidNextInFlow);
+ if (nsnull != kidNextInFlow) {
+ // Remove all of the childs next-in-flows. Make sure that we ask
+ // the right parent to do the removal (it's possible that the
+ // parent is not this because we are executing pullup code)
+ nsIFrame* parent;
+ aFrame->GetGeometricParent(parent);
+ ((nsBlockFrame*)parent)->DeleteNextInFlowsFor(*aState.mPresContext, aFrame);
+ }
+ aLine->SetLastContentIsComplete();
+ aReflowResult = NS_FRAME_COMPLETE;
+ }
+ else {
+ aLine->ClearLastContentIsComplete();
+ aReflowResult = NS_FRAME_NOT_COMPLETE;
+ }
+
+ // If the block we just reflowed happens to end up being zero height
+ // then we do not let its margins take effect.
+ nscoord newY;
+ if (0 == metrics.height) {
+ // Leave aState.mPrevBottomMargin alone in this case so that it
+ // can carry forward to the next non-empty block.
+ newY = y = aState.mY;
+ aLine->mInnerBottomMargin = 0;
+ aLine->mOuterBottomMargin = 0;
+ }
+ else {
+ // Collapse the childs bottom margin with the grandchilds bottom
+ // margin.
+ if (childSpacing->mMargin.GetBottomUnit() <= eStyleUnit_Auto) {
+ // list-item's don't get bottom margins in ebina land
+ const nsStyleDisplay* childDisplay;
+ aFrame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)childDisplay);
+ if (NS_STYLE_DISPLAY_LIST_ITEM != childDisplay->mDisplay) {
+ const nsFont& defaultFont = aState.mPresContext->GetDefaultFont();
+ nsIFontMetrics* fm = aState.mPresContext->GetMetricsFor(defaultFont);
+ fm->GetHeight(childBottomMargin);
+ NS_RELEASE(fm);
+ }
+ }
+ else {
+ childBottomMargin -= metrics.posBottomMargin;
+ if (childBottomMargin < 0) childBottomMargin = 0;
+ }
+
+ // See if it fit
+ newY = y + metrics.height + childBottomMargin;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockFrame::ReflowBlockFrame: metrics={%d,%d} newY=%d maxY=%d",
+ metrics.width, metrics.height, newY, aState.mBottomEdge));
+ if ((mLines != aLine) && (newY > aState.mBottomEdge)) {
+ // None of the block fit. Push aLine and any other lines that follow
+ PushLines(aState);
+ aReflowResult = NS_INLINE_LINE_BREAK_BEFORE(reflowStatus);
+ return PR_FALSE;
+ }
+ aState.mPrevBottomMargin = metrics.posBottomMargin + childBottomMargin;
+ aLine->mInnerBottomMargin = metrics.posBottomMargin;
+ aLine->mOuterBottomMargin = childBottomMargin;
+ }
+
+ // Update max-element-size
+ if (aState.mComputeMaxElementSize) {
+ if (kidMaxElementSize.width > aState.mMaxElementSize.width) {
+ aState.mMaxElementSize.width = kidMaxElementSize.width;
+ }
+ if (kidMaxElementSize.height > aState.mMaxElementSize.height) {
+ aState.mMaxElementSize.height = kidMaxElementSize.height;
+ }
+ }
+
+ // Save away bounds before other adjustments
+ aLine->mBounds.x = x;
+ aLine->mBounds.y = y;
+ aLine->mBounds.width = metrics.width;
+ aLine->mBounds.height = metrics.height;
+ nscoord xmost = aLine->mBounds.XMost();
+NS_ASSERTION(xmost < 1000000, "bad line width");
+ if (xmost > aState.mKidXMost) {
+ aState.mKidXMost = xmost;
+ }
+
+ // Place child then align it and relatively position it
+ aFrame->SetRect(aLine->mBounds);
+ aState.mY = newY;
+ if (!aState.mUnconstrainedWidth) {
+ nsCSSLayout::HorizontallyPlaceChildren(aState.mPresContext,
+ aState.mBlock,
+ aState.mTextAlign,
+ aState.mDirection,
+ aFrame, 1,
+ metrics.width,
+ availSize.width);
+ }
+ nsCSSLayout::RelativePositionChildren(aState.mPresContext,
+ aState.mBlock,
+ aFrame, 1);
+ aState.mPrevChild = aFrame;
+
+ // Refresh our available space in case a floater was placed by our
+ // child.
+ // XXX expensive!
+ aState.GetAvailableSpace();
+
+ if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus)) {
+ // Some of the block fit. We need to have the block frame
+ // continued, so we make sure that it has a next-in-flow now.
+ nsIFrame* nextInFlow;
+ rv = aState.mInlineLayout.MaybeCreateNextInFlow(aFrame, nextInFlow);
+ if (NS_OK != rv) {
+ aReflowResult = nsInlineReflowStatus(rv);
+ return PR_FALSE;
+ }
+ if (nsnull != nextInFlow) {
+ // We made a next-in-flow for the block child frame. Create a
+ // line to map the block childs next-in-flow.
+ LineData* line = new LineData(nextInFlow, 1,
+ (LINE_IS_BLOCK |
+ LINE_LAST_CONTENT_IS_COMPLETE));
+ if (nsnull == line) {
+ aReflowResult = nsInlineReflowStatus(NS_ERROR_OUT_OF_MEMORY);
+ return PR_FALSE;
+ }
+ line->mNext = aLine->mNext;
+ aLine->mNext = line;
+ }
+
+ // Advance mPrevLine because we are keeping aLine (since some of
+ // the child block frame fit). Then push any remaining lines to
+ // our next-in-flow
+ aState.mPrevLine = aLine;
+ if (nsnull != aLine->mNext) {
+ PushLines(aState);
+ }
+ aReflowResult = NS_INLINE_LINE_BREAK_AFTER(reflowStatus);
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
+PRBool
+nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsIFrame* aFrame,
+ nsInlineReflowStatus& aReflowResult)
+{
+ if (!aState.mInlineLayoutPrepared) {
+ nscoord x = aState.mCurrentBand.availSpace.x;
+ nscoord width = aState.mCurrentBand.availSpace.width;
+ if (0 != aState.mBulletPadding) {
+ if (x == aState.mX) {
+ x += aState.mBulletPadding;
+ width -= aState.mBulletPadding;
+ }
+ }
+
+ aState.mLineLayout.Prepare(x);
+ aState.mInlineLayout.Prepare(aState.mUnconstrainedWidth, aState.mNoWrap,
+ aState.mComputeMaxElementSize);
+ aState.mInlineLayout.SetReflowSpace(x, aState.mY,
+ width,
+ aState.mCurrentBand.availSpace.height);
+ // If we we are a list-item container and we are positioning the
+ // first child on the line (which is true when !mInlineLayoutPrepared)
+ // and it's the first line, and we are not a continuation, then
+ // set the mIsBullet flag for the line layout code.
+ if (aState.mLineLayout.mListPositionOutside &&
+ (0 == aState.mLineLayout.mLineNumber) &&
+ (nsnull == mPrevInFlow)) {
+ aState.mInlineLayout.mIsBullet = PR_TRUE;
+ aState.mInlineLayout.mHaveBullet = PR_TRUE;
+ }
+ aState.mInlineLayoutPrepared = PR_TRUE;
+ }
+
+ nsresult rv;
+ nsIFrame* nextInFlow;
+ aReflowResult = aState.mInlineLayout.ReflowAndPlaceFrame(aFrame);
+ aState.mInlineLayout.mIsBullet = PR_FALSE;
+ if (NS_IS_REFLOW_ERROR(aReflowResult)) {
+ return PR_FALSE;
+ }
+
+ PRBool lineWasComplete = aLine->GetLastContentIsComplete();
+ if (!NS_INLINE_IS_BREAK(aReflowResult)) {
+ aState.mPrevChild = aFrame;
+ if (NS_FRAME_IS_COMPLETE(aReflowResult)) {
+ aFrame->GetNextSibling(aFrame);
+ aLine->SetLastContentIsComplete();
+ return PR_TRUE;
+ }
+
+ // Create continuation frame (if necessary); add it to the end of
+ // the current line so that it can be pushed to the next line
+ // properly.
+ aLine->ClearLastContentIsComplete();
+ rv = aState.mInlineLayout.MaybeCreateNextInFlow(aFrame, nextInFlow);
+ if (NS_OK != rv) {
+ aReflowResult = nsInlineReflowStatus(rv);
+ return PR_FALSE;
+ }
+ if (nsnull != nextInFlow) {
+ // Add new child to the line
+ aLine->mChildCount++;
+ }
+ aFrame->GetNextSibling(aFrame);
+ }
+ else {
+ if (NS_INLINE_IS_BREAK_AFTER(aReflowResult)) {
+ aState.mPrevChild = aFrame;
+ if (NS_FRAME_IS_COMPLETE(aReflowResult)) {
+ aLine->SetLastContentIsComplete();
+ }
+ else {
+ // Create continuation frame (if necessary); add it to the end of
+ // the current line so that it can be pushed to the next line
+ // properly.
+ aLine->ClearLastContentIsComplete();
+ rv = aState.mInlineLayout.MaybeCreateNextInFlow(aFrame, nextInFlow);
+ if (NS_OK != rv) {
+ aReflowResult = nsInlineReflowStatus(rv);
+ return PR_FALSE;
+ }
+ if (nsnull != nextInFlow) {
+ // Add new child to the line
+ aLine->mChildCount++;
+ }
+ }
+ aFrame->GetNextSibling(aFrame);
+ }
+ else {
+ NS_ASSERTION(aLine->GetLastContentIsComplete(), "bad mState");
+ }
+ }
+
+ // Split line since we aren't going to keep going
+ rv = SplitLine(aState, aLine, aFrame, lineWasComplete);
+ if (NS_IS_REFLOW_ERROR(rv)) {
+ aReflowResult = nsInlineReflowStatus(rv);
+ }
+ return PR_FALSE;
+}
+
+// XXX alloc lines using free-list in aState
+
+// XXX refactor this since the split NEVER has to deal with blocks
+
+nsresult
+nsBlockFrame::SplitLine(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsIFrame* aFrame,
+ PRBool aLineWasComplete)
+{
+ PRInt32 pushCount = aLine->mChildCount - aState.mInlineLayout.mFrameNum;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::SplitLine: pushing %d frames",
+ pushCount));
+ if (0 != pushCount) {
+ NS_ASSERTION(nsnull != aFrame, "whoops");
+ LineData* to = aLine->mNext;
+ if (nsnull != to) {
+ // Only push into the next line if it's empty; otherwise we can
+ // end up pushing a frame which is continued into the same frame
+ // as it's continuation. This causes all sorts of bad side
+ // effects so we don't allow it.
+ if (to->mChildCount != 0) {
+ LineData* insertedLine = new LineData(aFrame, pushCount, 0);
+ aLine->mNext = insertedLine;
+ insertedLine->mNext = to;
+ to = insertedLine;
+ } else {
+ to->mFirstChild = aFrame;
+ to->mChildCount += pushCount;
+ }
+ } else {
+ to = new LineData(aFrame, pushCount, 0);
+ aLine->mNext = to;
+ }
+ if (nsnull == to) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ to->SetLastContentIsComplete(aLineWasComplete);
+ aLine->mChildCount -= pushCount;
+#ifdef NS_DEBUG
+ if (GetVerifyTreeEnable()) {
+ aLine->Verify();
+ }
+#endif
+ NS_ASSERTION(0 != aLine->mChildCount, "bad push");
+ }
+ return NS_OK;
+}
+
+PRBool
+nsBlockFrame::PullFrame(nsBlockReflowState& aState,
+ LineData* aLine,
+ LineData** aFromList,
+ PRBool aUpdateGeometricParent,
+ nsInlineReflowStatus& aReflowResult)
+{
+ LineData* fromLine = *aFromList;
+ NS_ASSERTION(nsnull != fromLine, "bad line to pull from");
+ if (0 == fromLine->mChildCount) {
+ // Discard empty lines immediately. Empty lines can happen here
+ // because of DeleteChildsNextInFlow not being able to delete
+ // lines.
+ *aFromList = fromLine->mNext;
+ NS_ASSERTION(nsnull == fromLine->mFirstChild, "bad empty line");
+ fromLine->mNext = aState.mFreeList;
+ aState.mFreeList = fromLine;
+ return PR_TRUE;
+ }
+
+ // If our line is not empty and the child in aFromLine is a block
+ // then we cannot pull up the frame into this line.
+ if ((0 != aLine->mChildCount) && fromLine->IsBlock()) {
+ aReflowResult = NS_INLINE_LINE_BREAK_BEFORE(0);
+ return PR_FALSE;
+ }
+
+ // Take frame from fromLine
+ nsIFrame* frame = fromLine->mFirstChild;
+ if (0 == aLine->mChildCount++) {
+ aLine->mFirstChild = frame;
+ aLine->SetIsBlock(fromLine->IsBlock());
+#ifdef NS_DEBUG
+ const nsStyleDisplay* display;
+ frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&) display);
+ const nsStylePosition* position;
+ frame->GetStyleData(eStyleStruct_Position,
+ (const nsStyleStruct*&) position);
+ PRBool isBlock = nsLineLayout::TreatFrameAsBlock(display, position);
+ NS_ASSERTION(isBlock == aLine->IsBlock(), "bad line isBlock");
+#endif
+ }
+ if (0 != --fromLine->mChildCount) {
+ frame->GetNextSibling(fromLine->mFirstChild);
+ }
+ else {
+ // Free up the fromLine now that it's empty
+ *aFromList = fromLine->mNext;
+ fromLine->mFirstChild = nsnull;
+ fromLine->mNext = aState.mFreeList;
+ aState.mFreeList = fromLine;
+ }
+
+ // Change geometric parents
+ if (aUpdateGeometricParent) {
+ nsIFrame* geometricParent;
+ nsIFrame* contentParent;
+ frame->GetGeometricParent(geometricParent);
+ frame->GetContentParent(contentParent);
+ if (contentParent == geometricParent) {
+ frame->SetContentParent(this);
+ }
+ frame->SetGeometricParent(this);
+
+ // The frame is being pulled from a next-in-flow; therefore we
+ // need to add it to our sibling list.
+ if (nsnull != aState.mPrevChild) {
+ aState.mPrevChild->SetNextSibling(frame);
+ }
+ frame->SetNextSibling(nsnull);
+ }
+
+ // Reflow the frame
+ if (aLine->IsBlock()) {
+ return ReflowBlockFrame(aState, aLine, frame, aReflowResult);
+ }
+ else {
+ return ReflowInlineFrame(aState, aLine, frame, aReflowResult);
+ }
+}
+
+PRBool
+nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
+ LineData* aLine,
+ nsInlineReflowStatus aReflowStatus)
+{
+ // Align the children. This also determines the actual height and
+ // width of the line.
+ aState.mInlineLayout.AlignFrames(aLine->mFirstChild, aLine->mChildCount,
+ aLine->mBounds);
+
+ // See if the line fit. If it doesn't we need to push it. Our first
+ // line will always fit.
+
+ // XXX This is a good place to check and see if we have
+ // below-current-line floaters, and if we do make sure that they fit
+ // too.
+ nscoord newY = aState.mY + aLine->mBounds.height;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockFrame::PlaceLine: newY=%d limit=%d lineHeight=%d",
+ newY, aState.mBottomEdge, aLine->mBounds.height));
+ if ((mLines != aLine) && (newY > aState.mBottomEdge)) {
+ // Push this line and all of it's children and anything else that
+ // follows to our next-in-flow
+ PushLines(aState);
+ return PR_FALSE;
+ }
+
+ if (aLine->mBounds.height > 0) {
+ aState.mPrevBottomMargin = 0;
+ }
+
+ // Update max-element-size
+ if (aState.mComputeMaxElementSize) {
+ nsSize& lineMaxElementSize = aState.mInlineLayout.mMaxElementSize;
+ if (lineMaxElementSize.width > aState.mMaxElementSize.width) {
+ aState.mMaxElementSize.width = lineMaxElementSize.width;
+ }
+ if (lineMaxElementSize.height > aState.mMaxElementSize.height) {
+ aState.mMaxElementSize.height = lineMaxElementSize.height;
+ }
+ }
+
+ nscoord xmost = aLine->mBounds.XMost();
+NS_ASSERTION(xmost < 1000000, "bad line width");
+ if (xmost > aState.mKidXMost) {
+ aState.mKidXMost = xmost;
+ }
+ aState.mY = newY;
+
+ // Any below current line floaters to place?
+ if (0 != aState.mPendingFloaters.Count()) {
+ aState.PlaceFloaters(&aState.mPendingFloaters);
+ aState.mPendingFloaters.Clear();
+
+ // XXX Factor in the height of the floaters as well when considering
+ // whether the line fits.
+ // The default policy is that if there isn't room for the floaters then
+ // both the line and the floaters are pushed to the next-in-flow...
+ }
+
+ // Based on the last child we reflowed reflow status, we may need to
+ // clear past any floaters.
+ if (NS_INLINE_IS_BREAK_AFTER(aReflowStatus)) {
+ // Apply break to the line
+ PRUint8 breakType = NS_INLINE_GET_BREAK_TYPE(aReflowStatus);
+ switch (breakType) {
+ default:
+ break;
+ case NS_STYLE_CLEAR_LEFT:
+ case NS_STYLE_CLEAR_RIGHT:
+ case NS_STYLE_CLEAR_LEFT_AND_RIGHT:
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::PlaceLine: clearing floaters=%d",
+ breakType));
+ aState.ClearFloaters(breakType);
+ break;
+ }
+ // XXX page breaks, etc, need to be passed upwards too!
+ }
+
+// if (aState.mY >= aState.mCurrentBand.availSpace.YMost()) {
+ // The current y coordinate is now past our available space
+ // rectangle. Get a new band of space.
+ aState.GetAvailableSpace();
+// }
+ return PR_TRUE;
+}
+
+static nsresult
+FindFloatersIn(nsIFrame* aFrame, nsVoidArray*& aArray)
+{
+ const nsStyleDisplay* display;
+ aFrame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&) display);
+ if (NS_STYLE_FLOAT_NONE != display->mFloats) {
+ if (nsnull == aArray) {
+ aArray = new nsVoidArray();
+ if (nsnull == aArray) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ aArray->AppendElement(aFrame);
+ }
+
+ if (NS_STYLE_DISPLAY_INLINE == display->mDisplay) {
+ nsIFrame* kid;
+ aFrame->FirstChild(kid);
+ while (nsnull != kid) {
+ nsresult rv = FindFloatersIn(kid, aArray);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ kid->GetNextSibling(kid);
+ }
+ }
+ return NS_OK;
+}
+
+void
+nsBlockFrame::FindFloaters(LineData* aLine)
+{
+ nsVoidArray* floaters = aLine->mFloaters;
+ if (nsnull != floaters) {
+ // Empty floater array before proceeding
+ floaters->Clear();
+ }
+
+ nsIFrame* frame = aLine->mFirstChild;
+ PRInt32 n = aLine->mChildCount;
+ while (--n >= 0) {
+ FindFloatersIn(frame, floaters);
+ frame->GetNextSibling(frame);
+ }
+
+ aLine->mFloaters = floaters;
+
+#if XXX
+ if ((mLines == aLine) && (nsnull != mRunInFloaters) &&
+ (nsnull != floaters)) {
+ // Special check for the first line: remove any floaters that are
+ // "current line" floaters (they musn't show up in the lines
+ // floater array)
+ PRInt32 i;
+ n = mRunInFloaters->Count();
+ for (i = 0; i < n; i++) {
+ PRInt32 ix = floaters->IndexOf(mRunInFloaters->ElementAt(i));
+ if (ix >= 0) {
+ floaters->RemoveElementAt(ix);
+ }
+ }
+ }
+#endif
+
+ // Get rid of floater array if we don't need it
+ if (nsnull != floaters) {
+ if (0 == floaters->Count()) {
+ delete floaters;
+ aLine->mFloaters = nsnull;
+ }
+ }
+}
+
+void
+nsBlockFrame::PushLines(nsBlockReflowState& aState)
+{
+ NS_ASSERTION(nsnull != aState.mPrevLine, "bad push");
+
+ LineData* lastLine = aState.mPrevLine;
+ LineData* nextLine = lastLine->mNext;
+
+ lastLine->mNext = nsnull;
+ mOverflowLines = nextLine;
+
+ // Break frame sibling list
+ nsIFrame* lastFrame = lastLine->LastChild();
+ lastFrame->SetNextSibling(nsnull);
+
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::PushLines: line=%p prevInFlow=%p nextInFlow=%p",
+ mOverflowLines, mPrevInFlow, mNextInFlow));
+#ifdef NS_DEBUG
+ if (GetVerifyTreeEnable()) {
+ VerifyChildCount(mLines);
+ VerifyChildCount(mOverflowLines, PR_TRUE);
+ }
+#endif
+}
+
+PRBool
+nsBlockFrame::DrainOverflowLines()
+{
+ PRBool drained = PR_FALSE;
+
+ // First grab the prev-in-flows overflow lines
+ nsBlockFrame* prevBlock = (nsBlockFrame*) mPrevInFlow;
+ if (nsnull != prevBlock) {
+ LineData* line = prevBlock->mOverflowLines;
+ if (nsnull != line) {
+ drained = PR_TRUE;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::DrainOverflowLines: line=%p prevInFlow=%p",
+ line, prevBlock));
+ prevBlock->mOverflowLines = nsnull;
+
+ // Make all the frames on the mOverflowLines list mine
+ nsIFrame* lastFrame = nsnull;
+ nsIFrame* frame = line->mFirstChild;
+ while (nsnull != frame) {
+ nsIFrame* geometricParent;
+ nsIFrame* contentParent;
+ frame->GetGeometricParent(geometricParent);
+ frame->GetContentParent(contentParent);
+ if (contentParent == geometricParent) {
+ frame->SetContentParent(this);
+ }
+ frame->SetGeometricParent(this);
+ lastFrame = frame;
+ frame->GetNextSibling(frame);
+ }
+
+ // Join the line lists
+ if (nsnull == mLines) {
+ mLines = line;
+ }
+ else {
+ // Join the sibling lists together
+ lastFrame->SetNextSibling(mLines->mFirstChild);
+
+ // Place overflow lines at the front of our line list
+ LineData* lastLine = LastLine(line);
+ lastLine->mNext = mLines;
+ mLines = line;
+ }
+
+ // Update our first-content-index now that we have a new first child
+ mLines->mFirstChild->GetContentIndex(mFirstContentOffset);
+ }
+ }
+
+ // Now grab our own overflow lines
+ if (nsnull != mOverflowLines) {
+ // This can happen when we reflow and not everything fits and then
+ // we are told to reflow again before a next-in-flow is created
+ // and reflows.
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::DrainOverflowLines: from me, line=%p",
+ mOverflowLines));
+ LineData* lastLine = LastLine(mLines);
+ if (nsnull == lastLine) {
+ mLines = mOverflowLines;
+ // Update our first-content-index now that we have a new first child
+ mLines->mFirstChild->GetContentIndex(mFirstContentOffset);
+ }
+ else {
+ lastLine->mNext = mOverflowLines;
+ nsIFrame* lastFrame = lastLine->LastChild();
+ lastFrame->SetNextSibling(mOverflowLines->mFirstChild);
+
+ // Update our last-content-index now that we have a new last child
+ lastLine = LastLine(mOverflowLines);
+ lastLine->LastChild()->GetContentIndex(mLastContentOffset);
+ }
+ mOverflowLines = nsnull;
+ drained = PR_TRUE;
+ }
+
+#ifdef NS_DEBUG
+ if (GetVerifyTreeEnable()) {
+ VerifyChildCount(mLines, PR_TRUE);
+ }
+#endif
+ return drained;
+}
+
+// XXX CONSTRUCTION
+#if 0
+// XXX a copy of nsHTMLContainerFrame's
+NS_IMETHODIMP
+nsBlockFrame::ContentAppended(nsIPresShell* aShell,
+ nsIPresContext* aPresContext,
+ nsIContent* aContainer)
+{
+ // Get the last-in-flow
+ nsBlockFrame* lastInFlow = (nsBlockFrame*)GetLastInFlow();
+
+ // Generate a reflow command for the frame
+ nsIReflowCommand* cmd;
+ nsresult result;
+
+ result = NS_NewHTMLReflowCommand(&cmd, lastInFlow,
+ nsIReflowCommand::FrameAppended);
+ if (NS_OK == result) {
+ aShell->AppendReflowCommand(cmd);
+ NS_RELEASE(cmd);
+ }
+
+ return NS_OK;
+}
+#endif
+
+nsresult
+nsBlockFrame::InsertNewFrame(nsBlockFrame* aParentFrame,
+ nsIFrame* aNewFrame,
+ nsIFrame* aPrevSibling)
+{
+ const nsStyleDisplay* display;
+ aNewFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
+ const nsStylePosition* position;
+ aNewFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&) position);
+ PRUint16 newFrameIsBlock = nsLineLayout::TreatFrameAsBlock(display, position)
+ ? LINE_IS_BLOCK : 0;
+
+ // Insert/append the frame into flows line list at the right spot
+ LineData* newLine;
+ LineData* line = aParentFrame->mLines;
+ if (nsnull == aPrevSibling) {
+ // Insert new frame into the sibling list
+ aNewFrame->SetNextSibling(line->mFirstChild);
+
+ if (line->IsBlock() || newFrameIsBlock) {
+ // Create a new line
+ newLine = new LineData(aNewFrame, 1, LINE_LAST_CONTENT_IS_COMPLETE |
+ newFrameIsBlock);
+ if (nsnull == newLine) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ newLine->mNext = aParentFrame->mLines;
+ aParentFrame->mLines = newLine;
+ } else {
+ // Insert frame at the front of the line
+ line->mFirstChild = aNewFrame;
+ line->mChildCount++;
+ line->MarkDirty();
+ }
+ }
+ else {
+ // Find line containing the previous sibling to the new frame
+ line = FindLineContaining(line, aPrevSibling);
+ NS_ASSERTION(nsnull != line, "no line contains the previous sibling");
+ if (nsnull != line) {
+ if (line->IsBlock()) {
+ // Create a new line just after line
+ newLine = new LineData(aNewFrame, 1, LINE_LAST_CONTENT_IS_COMPLETE |
+ newFrameIsBlock);
+ if (nsnull == newLine) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ newLine->mNext = line->mNext;
+ line->mNext = newLine;
+ }
+ else if (newFrameIsBlock) {
+ // Split line in two, if necessary. We can't allow a block to
+ // end up in an inline line.
+ if (line->IsLastChild(aPrevSibling)) {
+ // The new frame goes after prevSibling and prevSibling is
+ // the last frame on the line. Therefore we don't need to
+ // split the line, just create a new line.
+ newLine = new LineData(aNewFrame, 1, LINE_LAST_CONTENT_IS_COMPLETE |
+ newFrameIsBlock);
+ if (nsnull == newLine) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ newLine->mNext = line->mNext;
+ line->mNext = newLine;
+ }
+ else {
+ // The new frame goes after prevSibling and prevSibling is
+ // somewhere in the line, but not at the end. Split the line
+ // just after prevSibling.
+ PRInt32 i, n = line->mChildCount;
+ nsIFrame* frame = line->mFirstChild;
+ for (i = 0; i < n; i++) {
+ if (frame == aPrevSibling) {
+ nsIFrame* nextSibling;
+ aPrevSibling->GetNextSibling(nextSibling);
+
+ // Create new line to hold the remaining frames
+ NS_ASSERTION(n - i - 1 > 0, "bad line count");
+ newLine = new LineData(nextSibling, n - i - 1,
+ line->mState & LINE_LAST_CONTENT_IS_COMPLETE);
+ if (nsnull == newLine) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ newLine->mNext = line->mNext;
+ line->mNext = newLine;
+ line->MarkDirty();
+ line->SetLastContentIsComplete();
+ line->mChildCount = i + 1;
+ break;
+ }
+ frame->GetNextSibling(frame);
+ }
+
+ // Now create a new line to hold the block
+ newLine = new LineData(aNewFrame, 1,
+ newFrameIsBlock | LINE_LAST_CONTENT_IS_COMPLETE);
+ if (nsnull == newLine) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ newLine->mNext = line->mNext;
+ line->mNext = newLine;
+ }
+ }
+ else {
+ // Insert frame into the line.
+ // NS_ASSERTION(line->GetLastContentIsComplete(), "bad line LCIC");
+ line->mChildCount++;
+ line->MarkDirty();
+ }
+ }
+
+ // Insert new frame into the sibling list; note: this must be done
+ // after the above logic because the above logic depends on the
+ // sibling list being in the "before insertion" state.
+ nsIFrame* nextSibling;
+ aPrevSibling->GetNextSibling(nextSibling);
+ aNewFrame->SetNextSibling(nextSibling);
+ aPrevSibling->SetNextSibling(aNewFrame);
+ }
+
+ return NS_OK;
+}
+
+// XXX we assume that the insertion is really an assertion and never an append
+// XXX what about zero lines case
+NS_IMETHODIMP
+nsBlockFrame::ContentInserted(nsIPresShell* aShell,
+ nsIPresContext* aPresContext,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ PRInt32 aIndexInParent)
+{
+ // Find the frame that precedes this frame
+ nsIFrame* prevSibling = nsnull;
+ if (aIndexInParent > 0) {
+ nsIContent* precedingContent;
+ aContainer->ChildAt(aIndexInParent - 1, precedingContent);
+ prevSibling = aShell->FindFrameWithContent(precedingContent);
+ NS_ASSERTION(nsnull != prevSibling, "no frame for preceding content");
+ NS_RELEASE(precedingContent);
+
+ // The frame may have a next-in-flow. Get the last-in-flow; we do
+ // it the hard way because we can't assume that prevSibling is a
+ // subclass of nsSplittableFrame.
+ nsIFrame* nextInFlow;
+ do {
+ prevSibling->GetNextInFlow(nextInFlow);
+ if (nsnull != nextInFlow) {
+ prevSibling = nextInFlow;
+ }
+ } while (nsnull != nextInFlow);
+ }
+
+ // Get the parent of the previous sibling (which will be the proper
+ // next-in-flow for the child). We expect it to be this frame or one
+ // of our next-in-flow(s).
+ nsBlockFrame* flow = this;
+ if (nsnull != prevSibling) {
+ prevSibling->GetGeometricParent((nsIFrame*&)flow);
+ }
+
+ // Now that we have the right flow block we can create the new
+ // frame; test and see if the inserted frame is a block or not.
+ // XXX create-frame could return that fact
+ nsIFrame* newFrame;
+ nsresult rv = nsHTMLBase::CreateFrame(aPresContext, flow, aChild,
+ nsnull, newFrame);
+ if (NS_OK != rv) {
+ return rv;
+ }
+
+ InsertNewFrame(flow, newFrame, prevSibling);
+
+ // Generate a reflow command
+ nsIReflowCommand* cmd;
+ rv = NS_NewHTMLReflowCommand(&cmd, flow, nsIReflowCommand::FrameInserted);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ aShell->AppendReflowCommand(cmd);
+ NS_RELEASE(cmd);
+
+ // Update the content offsets of the flow block and all that follow
+ PRBool pseudos = flow->IsPseudoFrame();
+ flow->mLastContentOffset++;
+ if (pseudos) {
+ nsContainerFrame* flowParent = (nsContainerFrame*)flow->mGeometricParent;
+ flowParent->PropagateContentOffsets(flow, flow->mFirstContentOffset,
+ flow->mLastContentOffset,
+ flow->mLastContentIsComplete);
+ }
+ flow = (nsBlockFrame*) flow->mNextInFlow;
+ while (nsnull != flow) {
+ flow->mFirstContentOffset++;
+ flow->mLastContentOffset++;
+ if (pseudos) {
+ nsContainerFrame* flowParent = (nsContainerFrame*)flow->mGeometricParent;
+ flowParent->PropagateContentOffsets(flow, flow->mFirstContentOffset,
+ flow->mLastContentOffset,
+ flow->mLastContentIsComplete);
+ }
+ flow = (nsBlockFrame*) flow->mNextInFlow;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::ContentDeleted(nsIPresShell* aShell,
+ nsIPresContext* aPresContext,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ PRInt32 aIndexInParent)
+{
+ // Find the frame that precedes the frame to destroy and the frame
+ // to destroy (the first-in-flow if the frame is continued). We also
+ // find which of our next-in-flows contain the dead frame.
+ nsBlockFrame* flow;
+ nsIFrame* deadFrame;
+ nsIFrame* prevSibling;
+ if (aIndexInParent > 0) {
+ nsIContent* precedingContent;
+ aContainer->ChildAt(aIndexInParent - 1, precedingContent);
+ prevSibling = aShell->FindFrameWithContent(precedingContent);
+ NS_RELEASE(precedingContent);
+
+ // The frame may have a next-in-flow. Get the last-in-flow; we do
+ // it the hard way because we can't assume that prevSibling is a
+ // subclass of nsSplittableFrame.
+ nsIFrame* nextInFlow;
+ do {
+ prevSibling->GetNextInFlow(nextInFlow);
+ if (nsnull != nextInFlow) {
+ prevSibling = nextInFlow;
+ }
+ } while (nsnull != nextInFlow);
+
+ // Get the dead frame (maybe)
+ prevSibling->GetGeometricParent((nsIFrame*&)flow);
+ prevSibling->GetNextSibling(deadFrame);
+ if (nsnull == deadFrame) {
+ // The deadFrame must be prevSibling's parent's next-in-flows
+ // first frame. Therefore it doesn't have a prevSibling.
+ flow = (nsBlockFrame*) flow->mNextInFlow;
+ if (nsnull != flow) {
+ deadFrame = flow->mLines->mFirstChild;
+ }
+ prevSibling = nsnull;
+ }
+ }
+ else {
+ prevSibling = nsnull;
+ flow = this;
+ deadFrame = mLines->mFirstChild;
+ }
+ NS_ASSERTION(nsnull != deadFrame, "yikes! couldn't find frame");
+ if (nsnull == deadFrame) {
+ return NS_OK;
+ }
+
+ // Generate a reflow command for the appropriate flow frame
+ nsIReflowCommand* cmd;
+ nsresult rv = NS_NewHTMLReflowCommand(&cmd, flow,
+ nsIReflowCommand::FrameDeleted);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ aShell->AppendReflowCommand(cmd);
+ NS_RELEASE(cmd);
+
+ // Find line that contains deadFrame; we also find the pointer to
+ // the line.
+ LineData** linep = &flow->mLines;
+ LineData* line = flow->mLines;
+ while (nsnull != line) {
+ if (line->Contains(deadFrame)) {
+ break;
+ }
+ linep = &line->mNext;
+ line = line->mNext;
+ }
+
+ // Remove frame and its continuations
+ PRBool pseudos = flow->IsPseudoFrame();
+ while (nsnull != deadFrame) {
+ while ((nsnull != line) && (nsnull != deadFrame)) {
+#ifdef NS_DEBUG
+ nsIFrame* parent;
+ deadFrame->GetGeometricParent(parent);
+ NS_ASSERTION(flow == parent, "messed up delete code");
+#endif
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockFrame::ContentDeleted: deadFrame=%p",
+ deadFrame));
+
+ // Remove deadFrame from the line
+ if (line->mFirstChild == deadFrame) {
+ nsIFrame* nextFrame;
+ deadFrame->GetNextSibling(nextFrame);
+ line->mFirstChild = nextFrame;
+ }
+ else {
+ nsIFrame* lastFrame = line->LastChild();
+ if (lastFrame == deadFrame) {
+ line->SetLastContentIsComplete();
+ }
+ }
+
+ // Take deadFrame out of the sibling list
+ if (nsnull != prevSibling) {
+ nsIFrame* nextFrame;
+ deadFrame->GetNextSibling(nextFrame);
+ prevSibling->SetNextSibling(nextFrame);
+ }
+
+ // Destroy frame; capture its next-in-flow first in case we need
+ // to destroy that too.
+ nsIFrame* nextInFlow;
+ deadFrame->GetNextInFlow(nextInFlow);
+ if (nsnull != nextInFlow) {
+ deadFrame->BreakFromNextFlow();
+ }
+ deadFrame->DeleteFrame(*aPresContext);
+ deadFrame = nextInFlow;
+
+ // If line is empty, remove it now
+ LineData* next = line->mNext;
+ if (0 == --line->mChildCount) {
+ *linep = next;
+ line->mNext = nsnull;
+ delete line;
+ }
+ else {
+ linep = &line->mNext;
+ }
+ line = next;
+ }
+
+ // Update flows last-content-offset. Note that only the last
+ // content needs updating when a deadFrame is removed from flow
+ // (because only the children that follow the deletion need
+ // renumbering).
+ flow->mLastContentOffset--;
+ if (pseudos) {
+ nsContainerFrame* parent = (nsContainerFrame*)flow->mGeometricParent;
+ parent->PropagateContentOffsets(flow, flow->mFirstContentOffset,
+ flow->mLastContentOffset,
+ flow->mLastContentIsComplete);
+#if XXX
+ if (parent != flowParent) {
+ nsIReflowCommand* cmd;
+ rv = NS_NewHTMLReflowCommand(&cmd, flow,
+ nsIReflowCommand::FrameDeleted);
+ if (NS_OK != rv) {
+ return rv;
+ }
+ aShell->AppendReflowCommand(cmd);
+ NS_RELEASE(cmd);
+ }
+#endif
+ }
+
+ // Advance to next flow block if the frame has more continuations
+ if (nsnull != deadFrame) {
+ flow = (nsBlockFrame*) flow->mNextInFlow;
+ NS_ASSERTION(nsnull != flow, "whoops, continuation without a parent");
+ line = flow->mLines;
+ prevSibling = nsnull;
+ }
+ }
+
+ // Repair any remaining next-in-flows content offsets; these are the
+ // next-in-flows the follow the last flow container that contained
+ // one of the deadFrame's. Therefore both content offsets need
+ // updating (because all the children are following the deletion).
+ flow = (nsBlockFrame*) flow->mNextInFlow;
+ while (nsnull != flow) {
+ flow->mFirstContentOffset--;
+ flow->mLastContentOffset--;
+ flow = (nsBlockFrame*) flow->mNextInFlow;
+ }
+
+#ifdef NS_DEBUG
+ if (GetVerifyTreeEnable()) {
+ // Verify that the above delete code actually deleted the frames!
+ flow = this;
+ while (nsnull != flow) {
+ nsIFrame* frame = flow->mLines->mFirstChild;
+ while (nsnull != frame) {
+ nsIContent* content;
+ frame->GetContent(content);
+ NS_ASSERTION(content != aChild, "delete failed");
+ NS_RELEASE(content);
+ frame->GetNextSibling(frame);
+ }
+ flow = (nsBlockFrame*) flow->mNextInFlow;
+ }
+ }
+#endif
+
+ return rv;
+}
+
+PRBool
+nsBlockFrame::DeleteNextInFlowsFor(nsIPresContext& aPresContext, nsIFrame* aChild)
+{
+ NS_PRECONDITION(IsChild(aChild), "bad geometric parent");
+
+ nsIFrame* nextInFlow;
+ nsBlockFrame* parent;
+
+ aChild->GetNextInFlow(nextInFlow);
+ NS_PRECONDITION(nsnull != nextInFlow, "null next-in-flow");
+ nextInFlow->GetGeometricParent((nsIFrame*&)parent);
+
+ // If the next-in-flow has a next-in-flow then delete it, too (and
+ // delete it first).
+ nsIFrame* nextNextInFlow;
+ nextInFlow->GetNextInFlow(nextNextInFlow);
+ if (nsnull != nextNextInFlow) {
+ parent->DeleteNextInFlowsFor(aPresContext, nextInFlow);
+ }
+
+#ifdef NS_DEBUG
+ PRInt32 childCount;
+ nsIFrame* firstChild;
+ nextInFlow->ChildCount(childCount);
+ nextInFlow->FirstChild(firstChild);
+ NS_ASSERTION((0 == childCount) && (nsnull == firstChild),
+ "deleting !empty next-in-flow");
+#endif
+
+ // Disconnect the next-in-flow from the flow list
+ nextInFlow->BreakFromPrevFlow();
+
+ // Remove nextInFlow from the parents line list. Also remove it from
+ // the sibling list.
+ if (RemoveChild(parent->mLines, nextInFlow)) {
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::DeleteNextInFlowsFor: frame=%p (from mLines)",
+ nextInFlow));
+ goto done;
+ }
+
+ // If we get here then we didn't find the child on the line list. If
+ // it's not there then it has to be on the overflow lines list.
+ if (nsnull != mOverflowLines) {
+ if (RemoveChild(parent->mOverflowLines, nextInFlow)) {
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::DeleteNextInFlowsFor: frame=%p (from overflow)",
+ nextInFlow));
+ goto done;
+ }
+ }
+ NS_NOTREACHED("can't find next-in-flow in overflow list");
+
+ done:;
+ // If the parent is us then we will finish reflowing and update the
+ // content offsets of our parents when we are a pseudo-frame; if the
+ // parent is not us then it's a next-in-flow which means it will get
+ // reflowed by our parent and fix its content offsets. So there.
+#if XXX
+ if (parent->IsPseudoFrame()) {
+ parent->PropagateContentOffsets();
+ }
+#endif
+
+ // Delete the next-in-flow frame and adjust its parents child count
+ nextInFlow->DeleteFrame(aPresContext);
+
+#ifdef NS_DEBUG
+ aChild->GetNextInFlow(nextInFlow);
+ NS_POSTCONDITION(nsnull == nextInFlow, "non null next-in-flow");
+#endif
+ return PR_TRUE;
+}
+
+PRBool
+nsBlockFrame::RemoveChild(LineData* aLines, nsIFrame* aChild)
+{
+ LineData* line = aLines;
+ nsIFrame* prevChild = nsnull;
+ while (nsnull != line) {
+ nsIFrame* child = line->mFirstChild;
+ PRInt32 n = line->mChildCount;
+ while (--n >= 0) {
+ nsIFrame* nextChild;
+ child->GetNextSibling(nextChild);
+ if (child == aChild) {
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsBlockFrame::RemoveChild: line=%p frame=%p",
+ line, aChild));
+ // Continuations HAVE to be at the start of a line
+ NS_ASSERTION(child == line->mFirstChild, "bad continuation");
+ line->mFirstChild = nextChild;
+ if (0 == --line->mChildCount) {
+ line->mFirstChild = nsnull;
+ }
+ if (nsnull != prevChild) {
+ // When nextInFlow and it's continuation are in the same
+ // container then we remove the nextInFlow from the sibling
+ // list.
+ prevChild->SetNextSibling(nextChild);
+ }
+ return PR_TRUE;
+ }
+ prevChild = child;
+ child = nextChild;
+ }
+ line = line->mNext;
+ }
+ return PR_FALSE;
+}
+
+#if 0
+NS_IMETHODIMP
+nsBlockFrame::DidReflow(nsIPresContext& aPresContext,
+ nsDidReflowStatus aStatus)
+{
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("enter nsBlockFrame::DidReflow: status=%d",
+ aStatus));
+
+ if (NS_FRAME_REFLOW_FINISHED == aStatus) {
+ LineData* line = mLines;
+ while (nsnull != line) {
+ // XXX This can't be done because we need to pass on DidReflow's
+ // to things that weren't touched but are moving (like an
+ // embedded view that needs to update its view coordinate)
+
+ // XXX We need a better solution!
+ if (line->NeedsDidReflow()) {
+ line->ClearNeedDidReflow();
+ nsIFrame* kid = line->mFirstChild;
+ PRInt32 n = line->mChildCount;
+ while (--n >= 0) {
+ kid->DidReflow(aPresContext, aStatus);
+ kid->GetNextSibling(kid);
+ }
+ }
+ line = line->mNext;
+ }
+ }
+
+ NS_FRAME_TRACE_OUT("nsBlockFrame::DidReflow");
+
+ // Let nsFrame position and size our view (if we have one), and clear
+ // the NS_FRAME_IN_REFLOW bit
+ return nsFrame::DidReflow(aPresContext, aStatus);
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////
+// Floater support
+
+void
+nsBlockFrame::ReflowFloater(nsIPresContext* aPresContext,
+ nsBlockReflowState& aState,
+ nsIFrame* aFloaterFrame)
+{
+ // Prepare the reflow state for the floater frame. Note that initially
+ // it's maxSize will be 0,0 until we compute it (we need the reflowState
+ // for nsLayout::GetStyleSize so we have to do this first)
+ nsSize kidAvailSize(0, 0);
+ nsReflowState reflowState(aFloaterFrame, aState, kidAvailSize,
+ eReflowReason_Initial);
+
+ // Compute the available space for the floater. Use the default
+ // 'auto' width and height values
+ nsSize styleSize;
+ PRIntn styleSizeFlags =
+ nsCSSLayout::GetStyleSize(aPresContext, reflowState, styleSize);
+
+ // XXX The width and height are for the content area only. Add in space for
+ // border and padding
+ if (styleSizeFlags & NS_SIZE_HAS_WIDTH) {
+ kidAvailSize.width = styleSize.width;
+ }
+ else {
+ // If we are floating something and we don't know the width then
+ // find a maximum width for it to reflow into.
+
+ // XXX if the child is a block (instead of a table, say) then this
+ // will do the wrong thing. A better choice would be
+ // NS_UNCONSTRAINEDSIZE, but that has special meaning to tables.
+ const nsReflowState* rsp = &aState;
+ kidAvailSize.width = 0;
+ while (nsnull != rsp) {
+ if ((0 != rsp->maxSize.width) &&
+ (NS_UNCONSTRAINEDSIZE != rsp->maxSize.width)) {
+ kidAvailSize.width = rsp->maxSize.width;
+ break;
+ }
+ rsp = rsp->parentReflowState;
+ }
+ NS_ASSERTION(0 != kidAvailSize.width, "no width for block found");
+ }
+ if (styleSizeFlags & NS_SIZE_HAS_HEIGHT) {
+ kidAvailSize.height = styleSize.height;
+ }
+ else {
+ kidAvailSize.height = NS_UNCONSTRAINEDSIZE;
+ }
+ reflowState.maxSize = kidAvailSize;
+
+ // Resize reflow the anchored item into the available space
+ // XXX Check for complete?
+ nsReflowMetrics desiredSize(nsnull);
+ nsReflowStatus status;
+ aFloaterFrame->WillReflow(*aPresContext);
+ aFloaterFrame->Reflow(*aPresContext, desiredSize, reflowState, status);
+ aFloaterFrame->SizeTo(desiredSize.width, desiredSize.height);
+}
+
+PRBool
+nsBlockFrame::AddFloater(nsIPresContext* aPresContext,
+ const nsReflowState& aReflowState,
+ nsIFrame* aFloater,
+ nsPlaceholderFrame* aPlaceholder)
+{
+ // Walk up reflow state chain, looking for ourself
+ const nsReflowState* rs = &aReflowState;
+ while (nsnull != rs) {
+ if (rs->frame == this) {
+ break;
+ }
+ rs = rs->parentReflowState;
+ }
+ if (nsnull == rs) {
+ // Never mind
+ return PR_FALSE;
+ }
+ nsBlockReflowState* state = (nsBlockReflowState*) rs;
+
+ // Get the frame associated with the space manager, and get its
+ // nsIAnchoredItems interface
+ nsIFrame* frame = state->mSpaceManager->GetFrame();
+ nsIAnchoredItems* anchoredItems = nsnull;
+
+ frame->QueryInterface(kIAnchoredItemsIID, (void**)&anchoredItems);
+ NS_ASSERTION(nsnull != anchoredItems, "no anchored items interface");
+ if (nsnull != anchoredItems) {
+ anchoredItems->AddAnchoredItem(aFloater,
+ nsIAnchoredItems::anHTMLFloater,
+ this);
+
+ // Reflow the floater (the first time we do it here; later on it's
+ // done during the reflow of the line that contains the floater)
+ ReflowFloater(aPresContext, *state, aFloater);
+
+#if XXX_remove_me
+ // Determine whether we place it at the top or we place it below the
+ // current line
+// if (IsLeftMostChild(aPlaceholder)) {
+// if (nsnull == mRunInFloaters) {
+// mRunInFloaters = new nsVoidArray;
+// }
+// mRunInFloaters->AppendElement(aPlaceholder);
+// state->PlaceCurrentLineFloater(aFloater);
+// }
+ else {
+ // Add the placeholder to our to-do list
+ state->mPendingFloaters.AppendElement(aPlaceholder);
+ }
+#endif
+ return PR_TRUE;
+ }
+
+ return PR_FALSE;
+}
+
+// This is called by the line layout's AddFloater method when a
+// place-holder frame is reflowed in a line. If the floater is a
+// left-most child (it's x coordinate is at the line's left margin)
+// then the floater is place immediately, otherwise the floater
+// placement is deferred until the line has been reflowed.
+void
+nsBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder)
+{
+ // Update the current line's floater array
+ NS_ASSERTION(nsnull != mCurrentLine, "null ptr");
+ if (nsnull == mCurrentLine->mFloaters) {
+ mCurrentLine->mFloaters = new nsVoidArray();
+ }
+ mCurrentLine->mFloaters->AppendElement(aPlaceholder);
+
+ // Now place the floater immediately if possible. Otherwise stash it
+ // away in mPendingFloaters and place it later.
+ if (IsLeftMostChild(aPlaceholder)) {
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::AddFloater: IsLeftMostChild, placeHolder=%p",
+ aPlaceholder));
+
+ // Because we are in the middle of reflowing a placeholder frame
+ // within a line (and possibly nested in an inline frame or two
+ // that's a child of our block) we need to restore the space
+ // manager's translation to the space that the block resides in
+ // before placing the floater.
+ nscoord ox, oy;
+ mSpaceManager->GetTranslation(ox, oy);
+ nscoord dx = ox - mSpaceManagerX;
+ nscoord dy = oy - mSpaceManagerY;
+ mSpaceManager->Translate(-dx, -dy);
+ PlaceFloater(aPlaceholder);
+
+ // Pass on updated available space to the current line
+ GetAvailableSpace();
+ mInlineLayout.SetReflowSpace(mCurrentBand.availSpace.x, mY,
+ mCurrentBand.availSpace.width,
+ mCurrentBand.availSpace.height);
+
+ // Restore coordinate system
+ mSpaceManager->Translate(dx, dy);
+ }
+ else {
+ // This floater will be placed after the line is done (it is a
+ // below current line floater).
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::AddFloater: pending, placeHolder=%p",
+ aPlaceholder));
+ mPendingFloaters.AppendElement(aPlaceholder);
+ }
+}
+
+// XXX Inline frame layout and block layout need to be more
+// coordinated; IsFirstChild in the inline code is doing much the same
+// thing as below; firstness should be well known.
+PRBool
+nsBlockReflowState::IsLeftMostChild(nsIFrame* aFrame)
+{
+ for (;;) {
+ nsIFrame* parent;
+ aFrame->GetGeometricParent(parent);
+ if (parent == mBlock) {
+ nsIFrame* child = mCurrentLine->mFirstChild;
+ PRInt32 n = mCurrentLine->mChildCount;
+ while ((nsnull != child) && (aFrame != child) && (--n >= 0)) {
+ nsSize size;
+
+ // Is the child zero-sized?
+ child->GetSize(size);
+ if (size.width > 0) {
+ // We found a non-zero sized child frame that precedes aFrame
+ return PR_FALSE;
+ }
+ child->GetNextSibling(child);
+ }
+ break;
+ }
+ else {
+ // See if there are any non-zero sized child frames that precede
+ // aFrame in the child list
+ nsIFrame* child;
+ parent->FirstChild(child);
+ while ((nsnull != child) && (aFrame != child)) {
+ nsSize size;
+
+ // Is the child zero-sized?
+ child->GetSize(size);
+ if (size.width > 0) {
+ // We found a non-zero sized child frame that precedes aFrame
+ return PR_FALSE;
+ }
+ child->GetNextSibling(child);
+ }
+ }
+
+ // aFrame is the left-most non-zero sized frame in its geometric parent.
+ // Walk up one level and check that its parent is left-most as well
+ aFrame = parent;
+ }
+ return PR_TRUE;
+}
+
+void
+nsBlockReflowState::PlaceFloater(nsPlaceholderFrame* aPlaceholder)
+{
+ nsISpaceManager* sm = mSpaceManager;
+ nsIFrame* floater = aPlaceholder->GetAnchoredItem();
+
+ // Remove floaters old placement from the space manager
+ sm->RemoveRegion(floater);
+
+ // Reflow the floater if it's targetted for a reflow
+ if (nsnull != reflowCommand) {
+ nsIFrame* target;
+ reflowCommand->GetTarget(target);
+ if (floater == target) {
+ mBlock->ReflowFloater(mPresContext, *this, floater);
+ }
+ }
+
+ // Get the band of available space
+ GetAvailableSpace();
+
+ // Get the type of floater
+ const nsStyleDisplay* floaterDisplay;
+ const nsStyleSpacing* floaterSpacing;
+ floater->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)floaterDisplay);
+ floater->GetStyleData(eStyleStruct_Spacing,
+ (const nsStyleStruct*&)floaterSpacing);
+
+ // Get the floaters bounding box and margin information
+ nsRect region;
+ floater->GetRect(region);
+ nsMargin floaterMargin;
+ floaterSpacing->CalcMarginFor(floater, floaterMargin);
+
+ // Compute the size of the region that will impact the space manager
+ region.y = mY;
+ switch (floaterDisplay->mFloats) {
+ default:
+ NS_NOTYETIMPLEMENTED("Unsupported floater type");
+ // FALL THROUGH
+
+ case NS_STYLE_FLOAT_LEFT:
+ region.x = mCurrentBand.availSpace.x;
+ region.width += mBulletPadding;
+ break;
+
+ case NS_STYLE_FLOAT_RIGHT:
+ region.x = mCurrentBand.availSpace.XMost() - region.width;
+ region.x -= floaterMargin.right;
+ if (region.x < 0) {
+ region.x = 0;
+ }
+ }
+
+ // Factor in the floaters margins
+ region.width += floaterMargin.left + floaterMargin.right;
+ region.height += floaterMargin.top + floaterMargin.bottom;
+ sm->AddRectRegion(floater, region);
+
+ // Set the origin of the floater in world coordinates
+ nscoord worldX = mSpaceManagerX;
+ nscoord worldY = mSpaceManagerY;
+ if (NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats) {
+ floater->MoveTo(region.x + worldX + floaterMargin.left,
+ region.y + worldY + floaterMargin.top);
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::PlaceFloater: right, placeHolder=%p xy=%d,%d worldxy=%d,%d",
+ aPlaceholder, region.x + worldX + floaterMargin.left,
+ region.y + worldY + floaterMargin.top,
+ worldX, worldY));
+ }
+ else {
+ floater->MoveTo(region.x + worldX + floaterMargin.left + mBulletPadding,
+ region.y + worldY + floaterMargin.top);
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::PlaceFloater: left, placeHolder=%p xy=%d,%d worldxy=%d,%d",
+ aPlaceholder, region.x + worldX + floaterMargin.left + mBulletPadding,
+ region.y + worldY + floaterMargin.top,
+ worldX, worldY));
+ }
+}
+
+void
+nsBlockReflowState::PlaceFloaters(nsVoidArray* aFloaters)
+{
+ NS_PRECONDITION(aFloaters->Count() > 0, "no floaters");
+
+ PRInt32 numFloaters = aFloaters->Count();
+ for (PRInt32 i = 0; i < numFloaters; i++) {
+ nsPlaceholderFrame* placeholderFrame = (nsPlaceholderFrame*)
+ aFloaters->ElementAt(i);
+ if (IsLeftMostChild(placeholderFrame)) {
+ // Left-most children are placed during the line's reflow
+ continue;
+ }
+ PlaceFloater(placeholderFrame);
+ }
+
+ // Pass on updated available space to the current line
+ GetAvailableSpace();
+ mInlineLayout.SetReflowSpace(mCurrentBand.availSpace.x, mY,
+ mCurrentBand.availSpace.width,
+ mCurrentBand.availSpace.height);
+}
+
+void
+nsBlockReflowState::ClearFloaters(PRUint8 aBreakType)
+{
+ for (;;) {
+ PRBool haveFloater = PR_FALSE;
+ // Find the Y coordinate to clear to. Note that the band trapezoid
+ // coordinates are relative to the last translation. Since we
+ // never translate by Y before getting a band, we can use absolute
+ // comparisons against mY.
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: mY=%d trapCount=%d",
+ mY, mCurrentBand.count));
+ nscoord clearYMost = mY;
+ nsRect tmp;
+ PRInt32 i;
+ for (i = 0; i < mCurrentBand.count; i++) {
+ const nsStyleDisplay* display;
+ nsBandTrapezoid* trapezoid = &mCurrentBand.data[i];
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: trap=%d state=%d",
+ i, trapezoid->state));
+ if (nsBandTrapezoid::Available != trapezoid->state) {
+ haveFloater = PR_TRUE;
+ if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
+ PRInt32 fn, numFrames = trapezoid->frames->Count();
+ NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
+ for (fn = 0; fn < numFrames; fn++) {
+ nsIFrame* frame = (nsIFrame*) trapezoid->frames->ElementAt(fn);
+ frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)display);
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: frame[%d]=%p floats=%d",
+ fn, frame, display->mFloats));
+ switch (display->mFloats) {
+ case NS_STYLE_FLOAT_LEFT:
+ if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
+ (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
+ trapezoid->GetRect(tmp);
+ nscoord ym = tmp.YMost();
+ if (ym > clearYMost) {
+ clearYMost = ym;
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: left clearYMost=%d",
+ clearYMost));
+ }
+ }
+ break;
+ case NS_STYLE_FLOAT_RIGHT:
+ if ((NS_STYLE_CLEAR_RIGHT == aBreakType) ||
+ (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
+ trapezoid->GetRect(tmp);
+ nscoord ym = tmp.YMost();
+ if (ym > clearYMost) {
+ clearYMost = ym;
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: right clearYMost=%d",
+ clearYMost));
+ }
+ }
+ break;
+ }
+ }
+ }
+ else {
+ trapezoid->frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)display);
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: frame=%p floats=%d",
+ trapezoid->frame, display->mFloats));
+ switch (display->mFloats) {
+ case NS_STYLE_FLOAT_LEFT:
+ if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
+ (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
+ trapezoid->GetRect(tmp);
+ nscoord ym = tmp.YMost();
+NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: left? ym=%d clearYMost=%d",
+ ym, clearYMost));
+ if (ym > clearYMost) {
+ clearYMost = ym;
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: left clearYMost=%d",
+ clearYMost));
+ }
+ }
+ break;
+ case NS_STYLE_FLOAT_RIGHT:
+ if ((NS_STYLE_CLEAR_RIGHT == aBreakType) ||
+ (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
+ trapezoid->GetRect(tmp);
+ nscoord ym = tmp.YMost();
+ if (ym > clearYMost) {
+ clearYMost = ym;
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: right clearYMost=%d",
+ clearYMost));
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ if (!haveFloater) {
+ break;
+ }
+
+ if (clearYMost == mY) {
+ // Nothing to clear
+ break;
+ }
+
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsBlockReflowState::ClearFloaters: mY=%d clearYMost=%d",
+ mY, clearYMost));
+
+ mY = clearYMost + 1;
+
+ // Get a new band
+ GetAvailableSpace();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+// Painting, event handling
+
+PRIntn
+nsBlockFrame::GetSkipSides() const
+{
+ PRIntn skip = 0;
+ if (nsnull != mPrevInFlow) {
+ skip |= 1 << NS_SIDE_TOP;
+ }
+ if (nsnull != mNextInFlow) {
+ skip |= 1 << NS_SIDE_BOTTOM;
+ }
+ return skip;
+}
+
+NS_IMETHODIMP
+nsBlockFrame::Paint(nsIPresContext& aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect)
+{
+ // Paint our background and border
+ const nsStyleDisplay* disp =
+ (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display);
+
+ if (disp->mVisible && mRect.width && mRect.height) {
+ PRIntn skipSides = GetSkipSides();
+ const nsStyleColor* color =
+ (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color);
+ const nsStyleSpacing* spacing =
+ (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
+
+ nsRect rect(0, 0, mRect.width, mRect.height);
+ nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
+ aDirtyRect, rect, *color);
+ nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
+ aDirtyRect, rect, *spacing, skipSides);
+ }
+
+ PaintChildren(aPresContext, aRenderingContext, aDirtyRect);
+
+ if (nsIFrame::GetShowFrameBorders()) {
+ nsIView* view;
+ GetView(view);
+ if (nsnull != view) {
+ aRenderingContext.SetColor(NS_RGB(0,0,255));
+ }
+ else {
+ aRenderingContext.SetColor(NS_RGB(255,0,0));
+ }
+ aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height);
+ }
+ return NS_OK;
+}
+
+// aDirtyRect is in our coordinate system
+// child rect's are also in our coordinate system
+void
+nsBlockFrame::PaintChildren(nsIPresContext& aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect)
+{
+ // Set clip rect so that children don't leak out of us
+ const nsStyleDisplay* disp =
+ (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display);
+ PRBool hidden = PR_FALSE;
+ if (NS_STYLE_OVERFLOW_HIDDEN == disp->mOverflow) {
+ aRenderingContext.PushState();
+ aRenderingContext.SetClipRect(nsRect(0, 0, mRect.width, mRect.height),
+ nsClipCombine_kIntersect);
+ hidden = PR_TRUE;
+ }
+
+ // Iterate the lines looking for lines that intersect the dirty rect
+ for (LineData* line = mLines; nsnull != line; line = line->mNext) {
+ // Stop when we get to a line that's below the dirty rect
+ if (line->mBounds.y >= aDirtyRect.YMost()) {
+ break;
+ }
+
+ // If the line overlaps the dirty rect then iterate the child frames
+ // and paint those frames that intersect the dirty rect
+ if (line->mBounds.YMost() > aDirtyRect.y) {
+ nsIFrame* kid = line->mFirstChild;
+ for (PRUint16 i = 0; i < line->mChildCount; i++) {
+
+ nsIView *pView;
+
+ kid->GetView(pView);
+ if (nsnull == pView) {
+ nsRect kidRect;
+ kid->GetRect(kidRect);
+ nsRect damageArea;
+#ifdef NS_DEBUG
+ PRBool overlap = PR_FALSE;
+ if (nsIFrame::GetShowFrameBorders() &&
+ ((kidRect.width == 0) || (kidRect.height == 0))) {
+ nscoord xmost = aDirtyRect.XMost();
+ nscoord ymost = aDirtyRect.YMost();
+ if ((aDirtyRect.x <= kidRect.x) && (kidRect.x < xmost) &&
+ (aDirtyRect.y <= kidRect.y) && (kidRect.y < ymost)) {
+ overlap = PR_TRUE;
+ }
+ }
+ else {
+ overlap = damageArea.IntersectRect(aDirtyRect, kidRect);
+ }
+#else
+ PRBool overlap = damageArea.IntersectRect(aDirtyRect, kidRect);
+#endif
+ if (overlap) {
+ // Translate damage area into kid's coordinate system
+ nsRect kidDamageArea(damageArea.x - kidRect.x,
+ damageArea.y - kidRect.y,
+ damageArea.width, damageArea.height);
+ aRenderingContext.PushState();
+ aRenderingContext.Translate(kidRect.x, kidRect.y);
+ kid->Paint(aPresContext, aRenderingContext, kidDamageArea);
+#ifdef NS_DEBUG
+ if (nsIFrame::GetShowFrameBorders() &&
+ (0 != kidRect.width) && (0 != kidRect.height)) {
+ nsIView* view;
+ GetView(view);
+ if (nsnull != view) {
+ aRenderingContext.SetColor(NS_RGB(0,0,255));
+ }
+ else {
+ aRenderingContext.SetColor(NS_RGB(255,0,0));
+ }
+ aRenderingContext.DrawRect(0, 0, kidRect.width, kidRect.height);
+ }
+#endif
+ aRenderingContext.PopState();
+ }
+ }
+
+ // Get the next frame on this line
+ kid->GetNextSibling(kid);
+ }
+ }
+ }
+
+ if (hidden) {
+ aRenderingContext.PopState();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+// Debugging
+
+#ifdef NS_DEBUG
+static PRBool
+InLineList(LineData* aLines, nsIFrame* aFrame)
+{
+ while (nsnull != aLines) {
+ nsIFrame* frame = aLines->mFirstChild;
+ PRInt32 n = aLines->mChildCount;
+ while (--n >= 0) {
+ if (frame == aFrame) {
+ return PR_TRUE;
+ }
+ frame->GetNextSibling(frame);
+ }
+ aLines = aLines->mNext;
+ }
+ return PR_FALSE;
+}
+
+static PRBool
+InSiblingList(LineData* aLine, nsIFrame* aFrame)
+{
+ if (nsnull != aLine) {
+ nsIFrame* frame = aLine->mFirstChild;
+ while (nsnull != frame) {
+ if (frame == aFrame) {
+ return PR_TRUE;
+ }
+ frame->GetNextSibling(frame);
+ }
+ }
+ return PR_FALSE;
+}
+
+PRBool
+nsBlockFrame::IsChild(nsIFrame* aFrame)
+{
+ nsIFrame* parent;
+ aFrame->GetGeometricParent(parent);
+ if (parent != (nsIFrame*)this) {
+ return PR_FALSE;
+ }
+ if (InLineList(mLines, aFrame) && InSiblingList(mLines, aFrame)) {
+ return PR_TRUE;
+ }
+ if (InLineList(mOverflowLines, aFrame) &&
+ InSiblingList(mOverflowLines, aFrame)) {
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+#endif
+
+#define VERIFY_ASSERT(_expr, _msg) \
+ if (!(_expr)) { \
+ DumpTree(); \
+ } \
+ NS_ASSERTION(_expr, _msg)
+
+NS_IMETHODIMP
+nsBlockFrame::VerifyTree() const
+{
+#ifdef NS_DEBUG
+ NS_ASSERTION(0 == (mState & NS_FRAME_IN_REFLOW), "frame is in reflow");
+
+ VERIFY_ASSERT(nsnull == mOverflowLines, "bad overflow list");
+
+ // Verify that child count is the same as the line's mChildCount's
+ VerifyChildCount(mLines);
+
+ // Verify child content offsets and index-in-parents
+ PRInt32 offset = GetFirstContentOffset();
+ nsIFrame* child = (nsnull == mLines) ? nsnull : mLines->mFirstChild;
+ while (nsnull != child) {
+ // Make sure child is ours
+ nsIFrame* parent;
+ child->GetGeometricParent(parent);
+ VERIFY_ASSERT(parent == (nsIFrame*)this, "bad parent");
+
+ // Make sure that the child's tree is valid
+ child->VerifyTree();
+
+ // Make sure child's index-in-parent is correct
+ PRInt32 indexInParent;
+ child->GetContentIndex(indexInParent);
+ VERIFY_ASSERT(offset == indexInParent, "bad child offset");
+
+ nsIFrame* nextInFlow;
+ child->GetNextInFlow(nextInFlow);
+ if (nsnull == nextInFlow) {
+ offset++;
+ }
+ child->GetNextSibling(child);
+ }
+
+ // Verify that our last content offset is correct
+ if (0 != mChildCount) {
+ if (GetLastContentIsComplete()) {
+ VERIFY_ASSERT(offset == GetLastContentOffset() + 1, "bad last offset");
+ } else {
+ VERIFY_ASSERT(offset == GetLastContentOffset(), "bad last offset");
+ }
+ }
+
+#if XXX
+ // Make sure that our flow blocks offsets are all correct
+ if (nsnull == mPrevInFlow) {
+ PRInt32 nextOffset = NextChildOffset();
+ nsContainerFrame* nextInFlow = (nsContainerFrame*) mNextInFlow;
+ while (nsnull != nextInFlow) {
+ VERIFY_ASSERT(0 != nextInFlow->mChildCount, "empty next-in-flow");
+ VERIFY_ASSERT(nextInFlow->GetFirstContentOffset() == nextOffset,
+ "bad next-in-flow first offset");
+ nextOffset = nextInFlow->NextChildOffset();
+ nextInFlow = (nsContainerFrame*) nextInFlow->mNextInFlow;
+ }
+ }
+#endif
+#endif
+ return NS_OK;
+}
+
+#ifdef DO_SELECTION
+nsIFrame * nsBlockFrame::FindHitFrame(nsBlockFrame * aBlockFrame,
+ const nscoord aX,
+ const nscoord aY,
+ const nsPoint & aPoint)
+{
+ nsPoint mousePoint(aPoint.x-aX, aPoint.y-aY);
+
+ nsIFrame * contentFrame = nsnull;
+ LineData * line = aBlockFrame->mLines;
+ if (nsnull != line) {
+ // First find the line that contains the aIndex
+ while (nsnull != line && contentFrame == nsnull) {
+ nsIFrame* frame = line->mFirstChild;
+ PRInt32 n = line->mChildCount;
+ while (--n >= 0) {
+ nsRect bounds;
+ frame->GetRect(bounds);
+ if (bounds.Contains(mousePoint)) {
+ nsBlockFrame * blockFrame;
+ if (NS_OK == frame->QueryInterface(kBlockFrameCID, (void**)&blockFrame)) {
+ frame = FindHitFrame(blockFrame, bounds.x, bounds.y, aPoint);
+ //NS_RELEASE(blockFrame);
+ return frame;
+ } else {
+ return frame;
+ }
+ }
+ frame->GetNextSibling(frame);
+ }
+ line = line->mNext;
+ }
+ }
+ return aBlockFrame;
+}
+
+NS_METHOD nsBlockFrame::HandleEvent(nsIPresContext& aPresContext,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus)
+{
+ if (0) {
+ nsHTMLContainerFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
+ }
+
+ //return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
+ aEventStatus = nsEventStatus_eIgnore;
+
+ //if (nsnull != mContent && (aEvent->message != NS_MOUSE_LEFT_BUTTON_UP ||
+ // (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP && !mDoingSelection))) {
+ if (nsnull != mContent) {
+ mContent->HandleDOMEvent(aPresContext, (nsEvent*)aEvent, nsnull, DOM_EVENT_INIT, aEventStatus);
+ }
+
+ if (DisplaySelection(aPresContext) == PR_FALSE) {
+ if (aEvent->message != NS_MOUSE_LEFT_BUTTON_DOWN) {
+ return NS_OK;
+ }
+ }
+
+ if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) {
+ int x = 0;
+ }
+
+ //nsRect bounds;
+ //GetRect(bounds);
+ //nsIFrame * contentFrame = FindHitFrame(this, bounds.x, bounds.y, aEvent->point);
+ nsIFrame * contentFrame = FindHitFrame(this, 0,0, aEvent->point);
+
+ if (contentFrame == nsnull) {
+ return NS_OK;
+ }
+
+ if(nsEventStatus_eConsumeNoDefault != aEventStatus) {
+ if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) {
+ } else if (aEvent->message == NS_MOUSE_MOVE && mDoingSelection ||
+ aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) {
+ // no-op
+ } else {
+ return NS_OK;
+ }
+
+
+ if (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) {
+ if (mDoingSelection) {
+ contentFrame->HandleRelease(aPresContext, aEvent, aEventStatus);
+ }
+ } else if (aEvent->message == NS_MOUSE_MOVE) {
+ mDidDrag = PR_TRUE;
+ contentFrame->HandleDrag(aPresContext, aEvent, aEventStatus);
+ } else if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) {
+ contentFrame->HandlePress(aPresContext, aEvent, aEventStatus);
+ }
+ }
+
+ return NS_OK;
+
+}
+
+nsIFrame * gNearByFrame = nsnull;
+
+NS_METHOD nsBlockFrame::HandleDrag(nsIPresContext& aPresContext,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus)
+{
+ if (DisplaySelection(aPresContext) == PR_FALSE)
+ {
+ aEventStatus = nsEventStatus_eIgnore;
+ return NS_OK;
+ }
+
+ // Keep old start and end
+ //nsIContent * startContent = mSelectionRange->GetStartContent(); // ref counted
+ //nsIContent * endContent = mSelectionRange->GetEndContent(); // ref counted
+
+ mDidDrag = PR_TRUE;
+
+
+ nsIFrame * contentFrame = nsnull;
+ LineData* line = mLines;
+ if (nsnull != line) {
+ // First find the line that contains the aIndex
+ while (nsnull != line && contentFrame == nsnull) {
+ nsIFrame* frame = line->mFirstChild;
+ PRInt32 n = line->mChildCount;
+ while (--n >= 0) {
+ nsRect bounds;
+ frame->GetRect(bounds);
+ if (aEvent->point.y >= bounds.y && aEvent->point.y < bounds.y+bounds.height) {
+ contentFrame = frame;
+ if (frame != gNearByFrame) {
+ if (gNearByFrame != nsnull) {
+ int x = 0;
+ }
+ aEvent->point.x = bounds.x+bounds.width-50;
+ gNearByFrame = frame;
+ return contentFrame->HandleDrag(aPresContext, aEvent, aEventStatus);
+ } else {
+ return NS_OK;
+ }
+ //break;
+ }
+ frame->GetNextSibling(frame);
+ }
+ line = line->mNext;
+ }
+ }
+
+
+
+ return NS_OK;
+
+}
+
+
+#endif
diff --git a/layout/generic/nsHTMLContainerFrame.cpp b/layout/generic/nsHTMLContainerFrame.cpp
index b8731fefbe01..9b18bf45b751 100644
--- a/layout/generic/nsHTMLContainerFrame.cpp
+++ b/layout/generic/nsHTMLContainerFrame.cpp
@@ -389,3 +389,32 @@ nsHTMLContainerFrame::ProcessInitialReflow(nsIPresContext* aPresContext)
return NS_OK;
}
+
+PRBool
+nsHTMLContainerFrame::DeleteNextInFlowsFor(nsIPresContext& aPresContext,
+ nsIFrame* aChild)
+{
+ // XXX get rid of this sillyness
+ NS_NOTREACHED("subclass should've overriden this!");
+ return PR_TRUE;
+}
+
+nsPlaceholderFrame*
+nsHTMLContainerFrame::CreatePlaceholderFrame(nsIPresContext* aPresContext,
+ nsIFrame* aFloatedFrame)
+{
+ nsIContent* content;
+ aFloatedFrame->GetContent(content);
+
+ nsPlaceholderFrame* placeholder;
+ nsPlaceholderFrame::NewFrame((nsIFrame**)&placeholder, content, this, aFloatedFrame);
+ NS_IF_RELEASE(content);
+
+ // Let the placeholder share the same style context as the floated element
+ nsIStyleContext* kidSC;
+ aFloatedFrame->GetStyleContext(aPresContext, kidSC);
+ placeholder->SetStyleContext(aPresContext, kidSC);
+ NS_RELEASE(kidSC);
+
+ return placeholder;
+}
diff --git a/layout/generic/nsHTMLContainerFrame.h b/layout/generic/nsHTMLContainerFrame.h
index eacc819002ed..a01d12cafab6 100644
--- a/layout/generic/nsHTMLContainerFrame.h
+++ b/layout/generic/nsHTMLContainerFrame.h
@@ -20,6 +20,7 @@
#include "nsContainerFrame.h"
class nsString;
+class nsPlaceholderFrame;
// Base class for html container frames that provides common
// functionality.
@@ -53,6 +54,12 @@ public:
nsIContent* aChild,
PRInt32 aIndexInParent);
+ virtual PRBool DeleteNextInFlowsFor(nsIPresContext& aPresContext,
+ nsIFrame* aChild);
+
+ nsPlaceholderFrame* CreatePlaceholderFrame(nsIPresContext* aPresContext,
+ nsIFrame* aFloatedFrame);
+
protected:
virtual ~nsHTMLContainerFrame();
diff --git a/layout/generic/nsHTMLParts.h b/layout/generic/nsHTMLParts.h
index 06006f7a9e17..cec33e442952 100644
--- a/layout/generic/nsHTMLParts.h
+++ b/layout/generic/nsHTMLParts.h
@@ -235,13 +235,18 @@ NS_CreateHTMLElement(nsIHTMLContent** aResult,
// Factory methods for creating html layout objects
+extern nsresult
+NS_NewBRFrame(nsIContent* aContent, nsIFrame* aParentFrame,
+ nsIFrame*& aNewFrame);
+
extern nsresult
NS_NewBodyFrame(nsIContent* aContent, nsIFrame* aParentFrame,
nsIFrame*& aNewFrame);
extern nsresult
-NS_NewBRFrame(nsIContent* aContent, nsIFrame* aParentFrame,
- nsIFrame*& aNewFrame);
+NS_NewBlockFrame(nsIFrame** aInstancePtrResult,
+ nsIContent* aContent,
+ nsIFrame* aParent);
extern nsresult
NS_NewCommentFrame(nsIContent* aContent, nsIFrame* aParentFrame,
@@ -252,11 +257,13 @@ NS_NewHRFrame(nsIContent* aContent, nsIFrame* aParentFrame,
nsIFrame*& aNewFrame);
// and