diff --git a/layout/base/src/nsPresShell.cpp b/layout/base/nsPresShell.cpp
similarity index 100%
rename from layout/base/src/nsPresShell.cpp
rename to layout/base/nsPresShell.cpp
diff --git a/layout/base/src/makefile.win b/layout/base/src/makefile.win
index b24596e3c25c..ddde4d1bae5f 100644
--- a/layout/base/src/makefile.win
+++ b/layout/base/src/makefile.win
@@ -21,20 +21,16 @@ LIBRARY_NAME=raptorlayout_s
DEFINES=-D_IMPL_NS_LAYOUT -DWIN32_LEAN_AND_MEAN
CPPSRCS = \
- nsContainerFrame.cpp \
nsContentList.cpp \
nsDocument.cpp \
- nsFrame.cpp \
nsFrameImageLoader.cpp \
nsGalleyContext.cpp \
nsPresContext.cpp \
- nsPresShell.cpp \
nsPrintPreviewContext.cpp \
nsSelection.cpp \
nsSelectionPoint.cpp \
nsSelectionRange.cpp \
nsSpaceManager.cpp \
- nsSplittableFrame.cpp \
nsStyleContext.cpp \
nsStyleCoord.cpp \
nsStyleSet.cpp \
@@ -46,20 +42,16 @@ REQUIRES=xpcom raptor dom
EXPORTS=nsSelectionRange.h nsSelectionPoint.h
CPP_OBJS= \
- .\$(OBJDIR)\nsContainerFrame.obj \
.\$(OBJDIR)\nsContentList.obj \
.\$(OBJDIR)\nsDocument.obj \
- .\$(OBJDIR)\nsFrame.obj \
.\$(OBJDIR)\nsFrameImageLoader.obj \
.\$(OBJDIR)\nsGalleyContext.obj \
.\$(OBJDIR)\nsPresContext.obj \
- .\$(OBJDIR)\nsPresShell.obj \
.\$(OBJDIR)\nsPrintPreviewContext.obj \
.\$(OBJDIR)\nsSelection.obj \
.\$(OBJDIR)\nsSelectionPoint.obj \
.\$(OBJDIR)\nsSelectionRange.obj \
.\$(OBJDIR)\nsSpaceManager.obj \
- .\$(OBJDIR)\nsSplittableFrame.obj \
.\$(OBJDIR)\nsStyleContext.obj \
.\$(OBJDIR)\nsStyleCoord.obj \
.\$(OBJDIR)\nsStyleSet.obj \
diff --git a/layout/base/src/nsContainerFrame.cpp b/layout/base/src/nsContainerFrame.cpp
deleted file mode 100644
index f89b29ce1fdc..000000000000
--- a/layout/base/src/nsContainerFrame.cpp
+++ /dev/null
@@ -1,700 +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 "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.
- */
-#include "nsContainerFrame.h"
-#include "nsIContent.h"
-#include "nsIPresContext.h"
-#include "nsIRenderingContext.h"
-#include "nsIRunaround.h"
-#include "nsISpaceManager.h"
-#include "nsIStyleContext.h"
-#include "nsRect.h"
-#include "nsPoint.h"
-#include "nsGUIEvent.h"
-#include "nsStyleConsts.h"
-#include "nsIView.h"
-#include "nsVoidArray.h"
-#include "nsISizeOfHandler.h"
-
-#ifdef NS_DEBUG
-#undef NOISY
-#else
-#undef NOISY
-#endif
-
-nsContainerFrame::nsContainerFrame(nsIContent* aContent, nsIFrame* aParent)
- : nsSplittableFrame(aContent, aParent)
-{
-}
-
-nsContainerFrame::~nsContainerFrame()
-{
-}
-
-NS_IMETHODIMP
-nsContainerFrame::SizeOf(nsISizeOfHandler* aHandler) const
-{
- aHandler->Add(sizeof(*this));
- nsContainerFrame::SizeOfWithoutThis(aHandler);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsContainerFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList)
-{
- NS_PRECONDITION(nsnull == mFirstChild, "already initialized");
-
- mFirstChild = aChildList;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsContainerFrame::DeleteFrame(nsIPresContext& aPresContext)
-{
- // 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 = mFirstChild; child; ) {
- mFirstChild = nsnull; // XXX hack until HandleEvent is not called until after destruction
- nsIFrame* nextChild;
-
- child->GetNextSibling(nextChild);
- child->DeleteFrame(aPresContext);
- child = nextChild;
- }
-
- nsFrame::DeleteFrame(aPresContext);
-
- return NS_OK;
-}
-
-void
-nsContainerFrame::SizeOfWithoutThis(nsISizeOfHandler* aHandler) const
-{
- nsSplittableFrame::SizeOfWithoutThis(aHandler);
- for (nsIFrame* child = mFirstChild; child; ) {
- child->SizeOf(aHandler);
- child->GetNextSibling(child);
- }
-}
-
-void
-nsContainerFrame::PrepareContinuingFrame(nsIPresContext& aPresContext,
- nsIFrame* aParent,
- nsIStyleContext* aStyleContext,
- nsContainerFrame* aContFrame)
-{
- // Append the continuing frame to the flow
- aContFrame->AppendToFlow(this);
- aContFrame->SetStyleContext(&aPresContext, aStyleContext);
-}
-
-NS_METHOD
-nsContainerFrame::DidReflow(nsIPresContext& aPresContext,
- nsDidReflowStatus aStatus)
-{
- NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
- ("enter nsContainerFrame::DidReflow: status=%d",
- aStatus));
- if (NS_FRAME_REFLOW_FINISHED == aStatus) {
- nsIFrame* kid;
- FirstChild(kid);
- while (nsnull != kid) {
- kid->DidReflow(aPresContext, aStatus);
- kid->GetNextSibling(kid);
- }
- }
-
- NS_FRAME_TRACE_OUT("nsContainerFrame::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);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Child frame enumeration
-
-NS_METHOD nsContainerFrame::FirstChild(nsIFrame*& aFirstChild) const
-{
- aFirstChild = mFirstChild;
- return NS_OK;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Painting
-
-NS_METHOD nsContainerFrame::Paint(nsIPresContext& aPresContext,
- nsIRenderingContext& aRenderingContext,
- const nsRect& aDirtyRect)
-{
- PaintChildren(aPresContext, aRenderingContext, aDirtyRect);
- return NS_OK;
-}
-
-// aDirtyRect is in our coordinate system
-// child rect's are also in our coordinate system
-void nsContainerFrame::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;
- }
-
- // XXX reminder: use the coordinates in the dirty rect to figure out
- // which set of children are impacted and only do the intersection
- // work for them. In addition, stop when we no longer overlap.
-
- nsIFrame* kid = mFirstChild;
- while (nsnull != kid) {
- 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();
- }
- }
- kid->GetNextSibling(kid);
- }
-
- if (hidden) {
- aRenderingContext.PopState();
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Events
-
-NS_METHOD nsContainerFrame::HandleEvent(nsIPresContext& aPresContext,
- nsGUIEvent* aEvent,
- nsEventStatus& aEventStatus)
-{
- aEventStatus = nsEventStatus_eIgnore;
-
- nsIFrame* kid;
- FirstChild(kid);
- while (nsnull != kid) {
- nsRect kidRect;
- kid->GetRect(kidRect);
- if (kidRect.Contains(aEvent->point)) {
- aEvent->point.MoveBy(-kidRect.x, -kidRect.y);
- kid->HandleEvent(aPresContext, aEvent, aEventStatus);
- aEvent->point.MoveBy(kidRect.x, kidRect.y);
- break;
- }
- kid->GetNextSibling(kid);
- }
-
- return NS_OK;
-}
-
-NS_METHOD nsContainerFrame::GetCursorAndContentAt(nsIPresContext& aPresContext,
- const nsPoint& aPoint,
- nsIFrame** aFrame,
- nsIContent** aContent,
- PRInt32& aCursor)
-{
- aCursor = NS_STYLE_CURSOR_INHERIT;
- *aContent = mContent;
-
- nsIFrame* kid;
- FirstChild(kid);
- nsPoint tmp;
- while (nsnull != kid) {
- nsRect kidRect;
- kid->GetRect(kidRect);
- if (kidRect.Contains(aPoint)) {
- tmp.MoveTo(aPoint.x - kidRect.x, aPoint.y - kidRect.y);
- kid->GetCursorAndContentAt(aPresContext, tmp, aFrame, aContent, aCursor);
- break;
- }
- kid->GetNextSibling(kid);
- }
- return NS_OK;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Helper member functions
-
-/**
- * Reflow a child frame and return the status of the reflow. If the
- * child is complete and it has next-in-flows (it was a splittable child)
- * then delete the next-in-flows.
- */
-nsReflowStatus nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
- nsIPresContext* aPresContext,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState)
-{
- nsReflowStatus status;
-
- NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
-#ifdef NS_DEBUG
- nsFrameState kidFrameState;
-
- aKidFrame->GetFrameState(kidFrameState);
- NS_ASSERTION(kidFrameState & NS_FRAME_IN_REFLOW, "kid frame is not in reflow");
-#endif
- aKidFrame->Reflow(*aPresContext, aDesiredSize, aReflowState, status);
-
- if (NS_FRAME_IS_COMPLETE(status)) {
- nsIFrame* kidNextInFlow;
-
- aKidFrame->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;
- aKidFrame->GetGeometricParent(parent);
- ((nsContainerFrame*)parent)->DeleteChildsNextInFlow(*aPresContext, aKidFrame);
- }
- }
- return status;
-}
-
-/**
- * Remove and delete aChild's next-in-flow(s). Updates the sibling and flow
- * pointers
- *
- * Updates the child count and content offsets of all containers that are
- * affected
- *
- * @param aChild child this child's next-in-flow
- * @return PR_TRUE if successful and PR_FALSE otherwise
- */
-PRBool
-nsContainerFrame::DeleteChildsNextInFlow(nsIPresContext& aPresContext, nsIFrame* aChild)
-{
- NS_PRECONDITION(IsChild(aChild), "bad geometric parent");
-
- nsIFrame* nextInFlow;
- nsContainerFrame* 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->DeleteChildsNextInFlow(aPresContext, nextInFlow);
- }
-
-#ifdef NS_DEBUG
- PRInt32 childCount;
- nsIFrame* firstChild;
-
- nextInFlow->FirstChild(firstChild);
- childCount = LengthOf(firstChild);
-
- if ((0 != childCount) || (nsnull != firstChild)) {
- nsIFrame* top = nextInFlow;
- for (;;) {
- nsIFrame* parent;
- top->GetGeometricParent(parent);
- if (nsnull == parent) {
- break;
- }
- top = parent;
- }
- top->List();
- }
- NS_ASSERTION((0 == childCount) && (nsnull == firstChild),
- "deleting !empty next-in-flow");
-#endif
-
- // Disconnect the next-in-flow from the flow list
- nextInFlow->BreakFromPrevFlow();
-
- // Take the next-in-flow out of the parent's child list
- if (parent->mFirstChild == nextInFlow) {
- nextInFlow->GetNextSibling(parent->mFirstChild);
-
- } else {
- nsIFrame* nextSibling;
-
- // Because the next-in-flow is not the first child of the parent
- // we know that it shares a parent with aChild. Therefore, we need
- // to capture the next-in-flow's next sibling (in case the
- // next-in-flow is the last next-in-flow for aChild AND the
- // next-in-flow is not the last child in parent)
- NS_ASSERTION(((nsContainerFrame*)parent)->IsChild(aChild), "screwy flow");
- aChild->GetNextSibling(nextSibling);
- NS_ASSERTION(nextSibling == nextInFlow, "unexpected sibling");
-
- nextInFlow->GetNextSibling(nextSibling);
- aChild->SetNextSibling(nextSibling);
- }
-
- // Delete the next-in-flow frame and adjust its parents child count
- WillDeleteNextInFlowFrame(nextInFlow);
- nextInFlow->DeleteFrame(aPresContext);
-
-#ifdef NS_DEBUG
- aChild->GetNextInFlow(nextInFlow);
- NS_POSTCONDITION(nsnull == nextInFlow, "non null next-in-flow");
-#endif
- return PR_TRUE;
-}
-
-void nsContainerFrame::WillDeleteNextInFlowFrame(nsIFrame* aNextInFlow)
-{
-}
-
-/**
- * Push aFromChild and its next siblings to the next-in-flow. Change the
- * geometric parent of each frame that's pushed. If there is no next-in-flow
- * the frames are placed on the overflow list (and the geometric parent is
- * left unchanged).
- *
- * Updates the next-in-flow's child count. Does not update the
- * pusher's child count.
- *
- * @param aFromChild the first child frame to push. It is disconnected from
- * aPrevSibling
- * @param aPrevSibling aFromChild's previous sibling. Must not be null. It's
- * an error to push a parent's first child frame
- */
-void nsContainerFrame::PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling)
-{
- NS_PRECONDITION(nsnull != aFromChild, "null pointer");
- NS_PRECONDITION(nsnull != aPrevSibling, "pushing first child");
-#ifdef NS_DEBUG
- nsIFrame* prevNextSibling;
-
- aPrevSibling->GetNextSibling(prevNextSibling);
- NS_PRECONDITION(prevNextSibling == aFromChild, "bad prev sibling");
-#endif
-
- // Disconnect aFromChild from its previous sibling
- aPrevSibling->SetNextSibling(nsnull);
-
- // Do we have a next-in-flow?
- nsContainerFrame* nextInFlow = (nsContainerFrame*)mNextInFlow;
- if (nsnull != nextInFlow) {
- PRInt32 numChildren = 0;
- nsIFrame* lastChild = nsnull;
-
- // Compute the number of children being pushed, and for each child change
- // its geometric parent. Remember the last child
- for (nsIFrame* f = aFromChild; nsnull != f; f->GetNextSibling(f)) {
- numChildren++;
-#ifdef NOISY
- printf(" ");
- ((nsFrame*)f)->ListTag(stdout);
- printf("\n");
-#endif
- lastChild = f;
- f->SetGeometricParent(nextInFlow);
-
- nsIFrame* contentParent;
-
- f->GetContentParent(contentParent);
- if (this == contentParent) {
- f->SetContentParent(nextInFlow);
- }
- }
- NS_ASSERTION(numChildren > 0, "no children to push");
-
- // Prepend the frames to our next-in-flow's child list
- lastChild->SetNextSibling(nextInFlow->mFirstChild);
- nextInFlow->mFirstChild = aFromChild;
-
- } else {
- // Add the frames to our overflow list
- NS_ASSERTION(nsnull == mOverflowList, "bad overflow list");
-#ifdef NOISY
- ListTag(stdout);
- printf(": pushing kids to my overflow list\n");
-#endif
- mOverflowList = aFromChild;
- }
-}
-
-/**
- * Moves any frames on the overflwo lists (the prev-in-flow's overflow list and
- * the receiver's overflow list) to the child list.
- *
- * Updates this frame's child count and content mapping.
- *
- * @return PR_TRUE if any frames were moved and PR_FALSE otherwise
- */
-PRBool nsContainerFrame::MoveOverflowToChildList()
-{
- PRBool result = PR_FALSE;
-
- // Check for an overflow list with our prev-in-flow
- nsContainerFrame* prevInFlow = (nsContainerFrame*)mPrevInFlow;
- if (nsnull != prevInFlow) {
- if (nsnull != prevInFlow->mOverflowList) {
- NS_ASSERTION(nsnull == mFirstChild, "bad overflow list");
- AppendChildren(prevInFlow->mOverflowList);
- prevInFlow->mOverflowList = nsnull;
- result = PR_TRUE;
- }
- }
-
- // It's also possible that we have an overflow list for ourselves
- if (nsnull != mOverflowList) {
- NS_ASSERTION(nsnull != mFirstChild, "overflow list but no mapped children");
- AppendChildren(mOverflowList, PR_FALSE);
- mOverflowList = nsnull;
- result = PR_TRUE;
- }
-
- return result;
-}
-
-/**
- * Append child list starting at aChild to this frame's child list. Used for
- * processing of the overflow list.
- *
- * Updates this frame's child count and content mapping.
- *
- * @param aChild the beginning of the child list
- * @param aSetParent if true each child's geometric (and content parent if
- * they're the same) parent is set to this frame.
- */
-void nsContainerFrame::AppendChildren(nsIFrame* aChild, PRBool aSetParent)
-{
- // Link the frames into our child frame list
- if (nsnull == mFirstChild) {
- // We have no children so aChild becomes the first child
- mFirstChild = aChild;
- } else {
- nsIFrame* lastChild = LastFrame(mFirstChild);
- lastChild->SetNextSibling(aChild);
- }
-
- // Update our child count and last content offset
- nsIFrame* lastChild;
- for (nsIFrame* f = aChild; nsnull != f; f->GetNextSibling(f)) {
- lastChild = f;
-
- // Reset the geometric parent if requested
- if (aSetParent) {
- nsIFrame* geometricParent;
- nsIFrame* contentParent;
-
- f->GetGeometricParent(geometricParent);
- f->GetContentParent(contentParent);
- if (contentParent == geometricParent) {
- f->SetContentParent(this);
- }
- f->SetGeometricParent(this);
- }
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Debugging
-
-NS_METHOD nsContainerFrame::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);
- PRBool outputMe = (PRBool)((nsnull==aFilter) || (PR_TRUE==aFilter->OutputTag(&tagString)));
- if (PR_TRUE==outputMe)
- {
- // Indent
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
-
- // Output the tag
- ListTag(out);
- nsIView* view;
- GetView(view);
- if (nsnull != view) {
- fprintf(out, " [view=%p]", view);
- }
-
- if (nsnull != mPrevInFlow) {
- fprintf(out, "prev-in-flow=%p ", mPrevInFlow);
- }
- if (nsnull != mNextInFlow) {
- fprintf(out, "next-in-flow=%p ", mNextInFlow);
- }
-
- // Output the rect
- out << mRect;
- }
-
- // Output the children
- if (nsnull != mFirstChild) {
- if (PR_TRUE==outputMe)
- {
- if (0 != mState) {
- fprintf(out, " [state=%08x]", mState);
- }
- fputs("<\n", out);
- }
- for (nsIFrame* child = mFirstChild; child; child->GetNextSibling(child)) {
- child->List(out, aIndent + 1, aFilter);
- }
- if (PR_TRUE==outputMe)
- {
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
- fputs(">\n", out);
- }
- } else {
- if (PR_TRUE==outputMe)
- {
- if (0 != mState) {
- fprintf(out, " [state=%08x]", mState);
- }
- fputs("<>\n", out);
- }
- }
-
- return NS_OK;
-}
-
-#define VERIFY_ASSERT(_expr, _msg) \
- if (!(_expr)) { \
- DumpTree(); \
- } \
- NS_ASSERTION(_expr, _msg)
-
-NS_METHOD nsContainerFrame::VerifyTree() const
-{
-#ifdef NS_DEBUG
- NS_ASSERTION(0 == (mState & NS_FRAME_IN_REFLOW), "frame is in reflow");
- VERIFY_ASSERT(nsnull == mOverflowList, "bad overflow list");
-#endif
- return NS_OK;
-}
-
-PRInt32 nsContainerFrame::LengthOf(nsIFrame* aFrame)
-{
- PRInt32 result = 0;
-
- while (nsnull != aFrame) {
- result++;
- aFrame->GetNextSibling(aFrame);
- }
-
- return result;
-}
-
-nsIFrame* nsContainerFrame::LastFrame(nsIFrame* aFrame)
-{
- nsIFrame* lastChild = nsnull;
-
- while (nsnull != aFrame) {
- lastChild = aFrame;
- aFrame->GetNextSibling(aFrame);
- }
-
- return lastChild;
-}
-
-nsIFrame* nsContainerFrame::FrameAt(nsIFrame* aFrame, PRInt32 aIndex)
-{
- while ((aIndex-- > 0) && (aFrame != nsnull)) {
- aFrame->GetNextSibling(aFrame);
- }
- return aFrame;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-#ifdef NS_DEBUG
-
-PRBool nsContainerFrame::IsChild(const nsIFrame* aChild) const
-{
- // Check the geometric parent
- nsIFrame* parent;
-
- aChild->GetGeometricParent(parent);
- if (parent != (nsIFrame*)this) {
- return PR_FALSE;
- }
-
- return PR_TRUE;
-}
-
-void nsContainerFrame::DumpTree() const
-{
- nsIFrame* root = (nsIFrame*)this;
- nsIFrame* parent = mGeometricParent;
-
- while (nsnull != parent) {
- root = parent;
- parent->GetGeometricParent(parent);
- }
-
- root->List();
-}
-
-#endif
diff --git a/layout/base/src/nsContainerFrame.h b/layout/generic/nsContainerFrame.h
similarity index 100%
rename from layout/base/src/nsContainerFrame.h
rename to layout/generic/nsContainerFrame.h
diff --git a/layout/base/src/nsFrame.cpp b/layout/generic/nsFrame.cpp
similarity index 100%
rename from layout/base/src/nsFrame.cpp
rename to layout/generic/nsFrame.cpp
diff --git a/layout/base/src/nsFrame.h b/layout/generic/nsFrame.h
similarity index 100%
rename from layout/base/src/nsFrame.h
rename to layout/generic/nsFrame.h
diff --git a/layout/base/src/nsSplittableFrame.cpp b/layout/generic/nsSplittableFrame.cpp
similarity index 100%
rename from layout/base/src/nsSplittableFrame.cpp
rename to layout/generic/nsSplittableFrame.cpp
diff --git a/layout/base/src/nsSplittableFrame.h b/layout/generic/nsSplittableFrame.h
similarity index 100%
rename from layout/base/src/nsSplittableFrame.h
rename to layout/generic/nsSplittableFrame.h
diff --git a/layout/html/base/src/makefile.win b/layout/html/base/src/makefile.win
index 2b6f37f0139b..077355338dca 100644
--- a/layout/html/base/src/makefile.win
+++ b/layout/html/base/src/makefile.win
@@ -27,6 +27,8 @@ CPPSRCS= \
nsBRFrame.cpp \
nsBlockFrame.cpp \
nsBodyFrame.cpp \
+ nsContainerFrame.cpp \
+ nsFrame.cpp \
nsFrameReflowState.cpp \
nsGlobalVariables.cpp \
nsHRFrame.cpp \
@@ -44,8 +46,10 @@ CPPSRCS= \
nsObjectFrame.cpp \
nsPageFrame.cpp \
nsPlaceholderFrame.cpp \
+ nsPresShell.cpp \
nsScrollFrame.cpp \
nsSpacerFrame.cpp \
+ nsSplittableFrame.cpp \
nsTextFrame.cpp \
nsWBRFrame.cpp \
$(NULL)
@@ -55,6 +59,8 @@ CPP_OBJS= \
.\$(OBJDIR)\nsBRFrame.obj \
.\$(OBJDIR)\nsBlockFrame.obj \
.\$(OBJDIR)\nsBodyFrame.obj \
+ .\$(OBJDIR)\nsContainerFrame.obj \
+ .\$(OBJDIR)\nsFrame.obj \
.\$(OBJDIR)\nsFrameReflowState.obj \
.\$(OBJDIR)\nsGlobalVariables.obj \
.\$(OBJDIR)\nsHRFrame.obj \
@@ -72,8 +78,10 @@ CPP_OBJS= \
.\$(OBJDIR)\nsObjectFrame.obj \
.\$(OBJDIR)\nsPageFrame.obj \
.\$(OBJDIR)\nsPlaceholderFrame.obj \
+ .\$(OBJDIR)\nsPresShell.obj \
.\$(OBJDIR)\nsScrollFrame.obj \
.\$(OBJDIR)\nsSpacerFrame.obj \
+ .\$(OBJDIR)\nsSplittableFrame.obj \
.\$(OBJDIR)\nsTextFrame.obj \
.\$(OBJDIR)\nsWBRFrame.obj \
$(NULL)
@@ -85,6 +93,7 @@ LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I$(PUBLIC)\js \
-I..\..\style\src \
-I..\..\content\src \
-I..\..\..\base\src -I$(PUBLIC)\plugin -I$(PUBLIC)\java \
+ -I$(PUBLIC)\pref \
-I$(PUBLIC)\oji
LCFLAGS = \
diff --git a/layout/html/base/src/nsContainerFrame.h b/layout/html/base/src/nsContainerFrame.h
new file mode 100644
index 000000000000..9b32bc284057
--- /dev/null
+++ b/layout/html/base/src/nsContainerFrame.h
@@ -0,0 +1,175 @@
+/* -*- 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 "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.
+ */
+#ifndef nsContainerFrame_h___
+#define nsContainerFrame_h___
+
+#include "nsSplittableFrame.h"
+
+/**
+ * Implementation of a container frame.
+ */
+class nsContainerFrame : public nsSplittableFrame
+{
+public:
+ NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler) const;
+
+ NS_IMETHOD Init(nsIPresContext& aPresContext, nsIFrame* aChildList);
+
+ NS_IMETHOD DeleteFrame(nsIPresContext& aPresContext);
+
+ NS_IMETHOD DidReflow(nsIPresContext& aPresContext,
+ nsDidReflowStatus aStatus);
+
+ // Painting
+ NS_IMETHOD Paint(nsIPresContext& aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect);
+
+ /**
+ * Pass through the event to the correct child frame.
+ * Return PR_TRUE if the event is consumed.
+ */
+ NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus);
+
+ NS_IMETHOD GetCursorAndContentAt(nsIPresContext& aPresContext,
+ const nsPoint& aPoint,
+ nsIFrame** aFrame,
+ nsIContent** aContent,
+ PRInt32& aCursor);
+
+ // Child frame enumeration.
+ // ChildAt() retruns null if the index is not in the range 0 .. ChildCount() - 1.
+ // IndexOf() returns -1 if the frame is not in the child list.
+ NS_IMETHOD FirstChild(nsIFrame*& aFirstChild) const;
+
+ // Debugging
+ NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0, nsIListFilter *aFilter = nsnull) const;
+ NS_IMETHOD VerifyTree() const;
+
+ /**
+ * Return the number of children in the sibling list, starting at aChild.
+ * Returns zero if aChild is nsnull.
+ */
+ static PRInt32 LengthOf(nsIFrame* aChild);
+
+ /**
+ * Return the last frame in the sibling list.
+ * Returns nsnullif aChild is nsnull.
+ */
+ static nsIFrame* LastFrame(nsIFrame* aChild);
+
+ /**
+ * Returns the frame at the specified index relative to aFrame
+ */
+ static nsIFrame* FrameAt(nsIFrame* aFrame, PRInt32 aIndex);
+
+ // XXX needs to be virtual so that nsBlockFrame can override it
+ virtual PRBool DeleteChildsNextInFlow(nsIPresContext& aPresContext,
+ nsIFrame* aChild);
+
+protected:
+ // Constructor. Takes as arguments the content object, the index in parent,
+ // and the Frame for the content parent
+ nsContainerFrame(nsIContent* aContent, nsIFrame* aParent);
+
+ virtual ~nsContainerFrame();
+
+ void SizeOfWithoutThis(nsISizeOfHandler* aHandler) const;
+
+ /**
+ * Prepare a continuation frame of this frame for reflow. Appends
+ * it to the flow, sets its content offsets, mLastContentIsComplete,
+ * and style context. Subclasses should invoke this method after
+ * construction of a continuing frame.
+ */
+ void PrepareContinuingFrame(nsIPresContext& aPresContext,
+ nsIFrame* aParent,
+ nsIStyleContext* aStyleContext,
+ nsContainerFrame* aContFrame);
+
+
+ virtual void PaintChildren(nsIPresContext& aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect);
+
+ /**
+ * Reflow a child frame and return the status of the reflow. If the child
+ * is complete and it has next-in-flows, then delete the next-in-flows.
+ */
+ nsReflowStatus ReflowChild(nsIFrame* aKidFrame,
+ nsIPresContext* aPresContext,
+ nsReflowMetrics& aDesiredSize,
+ const nsReflowState& aReflowState);
+
+ /**
+ * Moves any frames on both the prev-in-flow's overflow list and the receiver's
+ * overflow to the receiver's child list.
+ *
+ * Resets the overlist pointers to nsnull, and updates the receiver's child
+ * count and content mapping.
+ *
+ * @return PR_TRUE if any frames were moved and PR_FALSE otherwise
+ */
+ PRBool MoveOverflowToChildList();
+
+ /**
+ * Push aFromChild and its next siblings to the next-in-flow. Change the
+ * geometric parent of each frame that's pushed. If there is no next-in-flow
+ * the frames are placed on the overflow list (and the geometric parent is
+ * left unchanged).
+ *
+ * Updates the next-in-flow's child count. Does not update the
+ * pusher's child count.
+ *
+ * @param aFromChild the first child frame to push. It is disconnected from
+ * aPrevSibling
+ * @param aPrevSibling aFromChild's previous sibling. Must not be null. It's
+ * an error to push a parent's first child frame
+ */
+ void PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling);
+
+ /**
+ * Append child list starting at aChild to this frame's child list. Used for
+ * processing of the overflow list.
+ *
+ * Updates this frame's child count and content mapping.
+ *
+ * @param aChild the beginning of the child list
+ * @param aSetParent if true each child's geometric (and content parent if
+ * they're the same) parent is set to this frame.
+ */
+ void AppendChildren(nsIFrame* aChild, PRBool aSetParent = PR_TRUE);
+
+ virtual void WillDeleteNextInFlowFrame(nsIFrame* aNextInFlow);
+
+#ifdef NS_DEBUG
+ /**
+ * Returns PR_TRUE if aChild is a child of this frame.
+ */
+ PRBool IsChild(const nsIFrame* aChild) const;
+
+ void DumpTree() const;
+#endif
+
+ nsIFrame* mFirstChild;
+ nsIFrame* mOverflowList;
+};
+
+#endif /* nsContainerFrame_h___ */
diff --git a/layout/html/base/src/nsFrame.cpp b/layout/html/base/src/nsFrame.cpp
new file mode 100644
index 000000000000..36b0705e8c2c
--- /dev/null
+++ b/layout/html/base/src/nsFrame.cpp
@@ -0,0 +1,1880 @@
+/* -*- 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 "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.
+ */
+#include "nsFrame.h"
+#include "nsIContent.h"
+#include "nsIAtom.h"
+#include "nsString.h"
+#include "nsIStyleContext.h"
+#include "nsIView.h"
+#include "nsIViewManager.h"
+#include "nsIPresContext.h"
+#include "nsCRT.h"
+#include "nsGUIEvent.h"
+#include "nsDOMEvent.h"
+#include "nsStyleConsts.h"
+#include "nsIPresShell.h"
+#include "prlog.h"
+#include "prprf.h"
+#include
+#include "nsIPtr.h"
+#include "nsISizeOfHandler.h"
+
+#include "nsIDOMText.h"
+#include "nsSelectionRange.h"
+#include "nsDocument.h"
+#include "nsIDeviceContext.h"
+#include "nsIPresShell.h"
+
+// Some Misc #defines
+#define SELECTION_DEBUG 0
+#define FORCE_SELECTION_UPDATE 1
+#define TRACKER_DEBUG 0
+#define CALC_DEBUG 0
+
+// Tracker Data
+#define kInsertInRemoveList 0
+#define kInsertInAddList 1
+
+// Kludged Content stuff
+nsIFrame * fFrameArray[1024];
+nsIContent * fContentArray[1024];
+PRInt32 fMax = -1;
+
+nsIContent * fTrackerContentArrayRemoveList[1024];
+PRInt32 fTrackerRemoveListMax = 0;
+nsIContent * fTrackerContentArrayAddList[1024];
+PRInt32 fTrackerAddListMax = 0;
+
+nsIDocument *gDoc = nsnull;
+
+// [HACK] Foward Declarations
+void RefreshContentFrames(nsIPresContext& aPresContext, nsIContent * aStartContent, nsIContent * aEndContent);
+void ForceDrawFrame(nsFrame * aFrame);
+void resetContentTrackers();
+void RefreshFromContentTrackers(nsIPresContext& aPresContext);
+void addRangeToSelectionTrackers(nsIContent * aStartContent, nsIContent * aEndContent, PRUint32 aType);
+
+
+
+
+// Initialize Global Selection Data
+nsIFrame * nsFrame::mCurrentFrame = nsnull;
+PRBool nsFrame::mDoingSelection = PR_FALSE;
+PRBool nsFrame::mDidDrag = PR_FALSE;
+PRInt32 nsFrame::mStartPos = 0;
+
+// Selection data is valid only from the Mouse Press to the Mouse Release
+nsSelectionRange * nsFrame::mSelectionRange = nsnull;
+nsISelection * nsFrame::mSelection = nsnull;
+
+nsSelectionPoint * nsFrame::mStartSelectionPoint = nsnull;
+nsSelectionPoint * nsFrame::mEndSelectionPoint = nsnull;
+
+//----------------------------------------------------------------------
+
+static PRBool gShowFrameBorders = PR_FALSE;
+
+NS_LAYOUT void nsIFrame::ShowFrameBorders(PRBool aEnable)
+{
+ gShowFrameBorders = aEnable;
+}
+
+NS_LAYOUT PRBool nsIFrame::GetShowFrameBorders()
+{
+ return gShowFrameBorders;
+}
+
+////////////////////////////////////////////////
+// Debug Listing Helper Class
+////////////////////////////////////////////////
+class TableListFilter : public nsIListFilter
+{
+private:
+ static char* kTagTable[];
+
+public:
+
+ TableListFilter()
+ {};
+
+ virtual ~TableListFilter()
+ {};
+
+ virtual PRBool OutputTag(nsAutoString *aTag) const
+ {
+ PRBool result = PR_FALSE;
+ if (nsnull!=aTag && 0!=aTag->Length())
+ {
+ for (PRInt32 i=0; ; i++)
+ {
+ const char *tableTag = kTagTable[i];
+ if (nsnull==tableTag)
+ break;
+ if (aTag->EqualsIgnoreCase(tableTag))
+ {
+ result = PR_TRUE;
+ break;
+ }
+ }
+ }
+ return result;
+ };
+
+};
+
+char* TableListFilter::kTagTable[] = {
+ "table",
+ "tbody", "thead", "tfoot",
+ "tr", "td", "th",
+ "colgroup", "col",
+ //"caption", captions are left out because there's no caption frame
+ // to hang a decent output method on.
+ ""
+};
+
+NS_LAYOUT nsIListFilter * nsIFrame::GetFilter(nsString *aFilterName)
+{
+ nsIListFilter *result = nsnull;
+ if (nsnull!=aFilterName)
+ {
+ if (aFilterName->EqualsIgnoreCase("table"))
+ {
+ static nsIListFilter * tableListFilter;
+ if (nsnull==tableListFilter)
+ tableListFilter = new TableListFilter();
+ result = tableListFilter;
+ }
+ }
+ return result;
+}
+
+/**
+ * Note: the log module is created during library initialization which
+ * means that you cannot perform logging before then.
+ */
+PRLogModuleInfo* nsIFrame::gLogModule = PR_NewLogModule("frame");
+
+static PRLogModuleInfo* gFrameVerifyTreeLogModuleInfo;
+
+static PRBool gFrameVerifyTreeEnable = PRBool(0x55);
+
+NS_LAYOUT PRBool
+nsIFrame::GetVerifyTreeEnable()
+{
+#ifdef NS_DEBUG
+ if (gFrameVerifyTreeEnable == PRBool(0x55)) {
+ if (nsnull == gFrameVerifyTreeLogModuleInfo) {
+ gFrameVerifyTreeLogModuleInfo = PR_NewLogModule("frameverifytree");
+ gFrameVerifyTreeEnable = 0 != gFrameVerifyTreeLogModuleInfo->level;
+ printf("Note: frameverifytree is %sabled\n",
+ gFrameVerifyTreeEnable ? "en" : "dis");
+ }
+ }
+#endif
+ return gFrameVerifyTreeEnable;
+}
+
+NS_LAYOUT void
+nsIFrame::SetVerifyTreeEnable(PRBool aEnabled)
+{
+ gFrameVerifyTreeEnable = aEnabled;
+}
+
+NS_LAYOUT PRLogModuleInfo*
+nsIFrame::GetLogModuleInfo()
+{
+ return gLogModule;
+}
+
+//----------------------------------------------------------------------
+
+static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID);
+
+nsresult
+nsFrame::NewFrame(nsIFrame** aInstancePtrResult,
+ nsIContent* aContent,
+ nsIFrame* aParent)
+{
+ NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
+ if (nsnull == aInstancePtrResult) {
+ return NS_ERROR_NULL_POINTER;
+ }
+ nsIFrame* it = new nsFrame(aContent, aParent);
+ if (nsnull == it) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ *aInstancePtrResult = it;
+ return NS_OK;
+}
+
+void* nsFrame::operator new(size_t size)
+{
+ void* result = new char[size];
+
+ nsCRT::zero(result, size);
+ return result;
+}
+
+nsFrame::nsFrame(nsIContent* aContent, nsIFrame* aParent)
+ : mContent(aContent), mContentParent(aParent), mGeometricParent(aParent)
+{
+ NS_ADDREF(mContent);
+ mState = NS_FRAME_FIRST_REFLOW;
+}
+
+nsFrame::~nsFrame()
+{
+ NS_IF_RELEASE(mContent);
+ NS_IF_RELEASE(mStyleContext);
+ if (nsnull != mView) {
+ // Break association between view and frame
+ mView->Destroy();
+ mView = nsnull;
+ }
+
+ if (mStartSelectionPoint != nsnull) {
+ delete mStartSelectionPoint;
+ mStartSelectionPoint = nsnull;
+ }
+ if (mEndSelectionPoint != nsnull) {
+ delete mEndSelectionPoint;
+ mEndSelectionPoint = nsnull;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// nsISupports
+
+nsresult nsFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
+{
+ if (NULL == aInstancePtr) {
+ return NS_ERROR_NULL_POINTER;
+ }
+ static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
+ static NS_DEFINE_IID(kClassIID, kIFrameIID);
+ if (aIID.Equals(kClassIID) || (aIID.Equals(kISupportsIID))) {
+ *aInstancePtr = (void*)this;
+ return NS_OK;
+ }
+ return NS_NOINTERFACE;
+}
+
+nsrefcnt nsFrame::AddRef(void)
+{
+ NS_WARNING("not supported for frames");
+ return 1;
+}
+
+nsrefcnt nsFrame::Release(void)
+{
+ NS_WARNING("not supported for frames");
+ return 1;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// nsIFrame
+
+NS_IMETHODIMP nsFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList)
+{
+ if (nsnull != aChildList) {
+ NS_ERROR("not a container");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::DeleteFrame(nsIPresContext& aPresContext)
+{
+ //XXX Why is this done in nsFrame instead of some frame class
+ // that actually loads images?
+ aPresContext.StopLoadImage(this);
+
+ //Set to prevent event dispatch during destruct
+ if (nsnull != mView) {
+ mView->SetClientData(nsnull);
+ }
+
+ delete this;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFrame::SizeOf(nsISizeOfHandler* aHandler) const
+{
+ aHandler->Add(sizeof(*this));
+ SizeOfWithoutThis(aHandler);
+ return NS_OK;
+}
+
+void
+nsFrame::SizeOfWithoutThis(nsISizeOfHandler* aHandler) const
+{
+ // Note: style context's are accounted for via the style system's
+ // sizeof support
+
+ // Note: content is accounted for via the content system's sizeof
+ // support
+}
+
+NS_METHOD nsFrame::GetContent(nsIContent*& aContent) const
+{
+ if (nsnull != mContent) {
+ NS_ADDREF(mContent);
+ }
+ aContent = mContent;
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::GetContentIndex(PRInt32& aIndexInParent) const
+{
+ nsIContent* parent;
+ mContent->GetParent(parent);
+ if (nsnull != parent) {
+ parent->IndexOf(mContent, aIndexInParent);
+ NS_RELEASE(parent);
+ }
+ else {
+ aIndexInParent = 0;
+ }
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::GetStyleContext(nsIPresContext* aPresContext,
+ nsIStyleContext*& aStyleContext)
+{
+ if ((nsnull == mStyleContext) && (nsnull != aPresContext)) {
+ mStyleContext = aPresContext->ResolveStyleContextFor(mContent, mGeometricParent); // XXX should be content parent???
+ if (nsnull != mStyleContext) {
+ DidSetStyleContext(aPresContext);
+ }
+ }
+ NS_IF_ADDREF(mStyleContext);
+ aStyleContext = mStyleContext;
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::SetStyleContext(nsIPresContext* aPresContext,nsIStyleContext* aContext)
+{
+ NS_PRECONDITION(nsnull != aContext, "null ptr");
+ if (aContext != mStyleContext) {
+ NS_IF_RELEASE(mStyleContext);
+ if (nsnull != aContext) {
+ mStyleContext = aContext;
+ NS_ADDREF(aContext);
+ DidSetStyleContext(aPresContext);
+ }
+ }
+
+ return NS_OK;
+}
+
+// Subclass hook for style post processing
+NS_METHOD nsFrame::DidSetStyleContext(nsIPresContext* aPresContext)
+{
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::GetStyleData(nsStyleStructID aSID, const nsStyleStruct*& aStyleStruct) const
+{
+ NS_ASSERTION(mStyleContext!=nsnull,"null style context");
+ if (mStyleContext) {
+ aStyleStruct = mStyleContext->GetStyleData(aSID);
+ } else {
+ aStyleStruct = nsnull;
+ }
+ return NS_OK;
+}
+
+// Geometric and content parent member functions
+
+NS_METHOD nsFrame::GetContentParent(nsIFrame*& aParent) const
+{
+ aParent = mContentParent;
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::SetContentParent(const nsIFrame* aParent)
+{
+ mContentParent = (nsIFrame*)aParent;
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::GetGeometricParent(nsIFrame*& aParent) const
+{
+ aParent = mGeometricParent;
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::SetGeometricParent(const nsIFrame* aParent)
+{
+ mGeometricParent = (nsIFrame*)aParent;
+ return NS_OK;
+}
+
+// Bounding rect member functions
+
+NS_METHOD nsFrame::GetRect(nsRect& aRect) const
+{
+ aRect = mRect;
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::GetOrigin(nsPoint& aPoint) const
+{
+ aPoint.x = mRect.x;
+ aPoint.y = mRect.y;
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::GetSize(nsSize& aSize) const
+{
+ aSize.width = mRect.width;
+ aSize.height = mRect.height;
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::SetRect(const nsRect& aRect)
+{
+ MoveTo(aRect.x, aRect.y);
+ SizeTo(aRect.width, aRect.height);
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::MoveTo(nscoord aX, nscoord aY)
+{
+ mRect.x = aX;
+ mRect.y = aY;
+
+ // Let the view know
+ if ((nsnull != mView) && (0 == (mState & NS_FRAME_IN_REFLOW))) {
+ // Position view relative to its parent, not relative to our
+ // parent frame (our parent frame may not have a view).
+ nsIView* parentWithView;
+ nsPoint origin;
+ GetOffsetFromView(origin, parentWithView);
+ nsIViewManager *vm;
+ mView->GetViewManager(vm);
+ vm->MoveViewTo(mView, origin.x, origin.y);
+ NS_RELEASE(vm);
+ }
+
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::SizeTo(nscoord aWidth, nscoord aHeight)
+{
+ mRect.width = aWidth;
+ mRect.height = aHeight;
+
+ // Let the view know
+ if ((nsnull != mView) && (0 == (mState & NS_FRAME_IN_REFLOW))) {
+ nsIViewManager *vm;
+ mView->GetViewManager(vm);
+ vm->ResizeView(mView, aWidth, aHeight);
+ NS_RELEASE(vm);
+ }
+ return NS_OK;
+}
+
+// Child frame enumeration
+
+NS_METHOD nsFrame::FirstChild(nsIFrame*& aFirstChild) const
+{
+ aFirstChild = nsnull;
+ return NS_OK;
+}
+
+PRBool nsFrame::DisplaySelection(nsIPresContext& aPresContext, PRBool isOkToTurnOn)
+{
+ PRBool result = PR_FALSE;
+
+ nsIPresShell *shell = aPresContext.GetShell();
+ if (nsnull != shell) {
+ nsIDocument *doc = shell->GetDocument();
+ if (nsnull != doc) {
+ result = doc->GetDisplaySelection();
+ if (isOkToTurnOn && !result) {
+ doc->SetDisplaySelection(PR_TRUE);
+ result = PR_TRUE;
+ }
+ NS_RELEASE(doc);
+ }
+ NS_RELEASE(shell);
+ }
+
+ return result;
+}
+
+NS_METHOD nsFrame::Paint(nsIPresContext& aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect)
+{
+ if (DisplaySelection(aPresContext) == PR_FALSE)
+ return NS_OK;
+
+ PRBool clearAfterPaint = PR_FALSE;
+
+ // Get Content
+ nsIContent * content;
+ GetContent(content);
+ PRInt32 n;
+ content->ChildCount(n);
+ if (n > 0) {
+ NS_RELEASE(content);
+ return NS_OK;
+ }
+
+ nsIPresShell * shell = aPresContext.GetShell();
+ nsIDocument * doc = shell->GetDocument();
+ if (mSelectionRange == nsnull) { // Get Selection Object
+ nsISelection * selection;
+ doc->GetSelection(selection);
+
+ mSelectionRange = selection->GetRange();
+
+ clearAfterPaint = PR_TRUE;
+ NS_RELEASE(selection);
+ }
+
+ nsIContent * selStartContent = mSelectionRange->GetStartContent(); // ref counted
+ nsIContent * selEndContent = mSelectionRange->GetEndContent(); // ref counted
+
+ if (doc->IsInRange(selStartContent, selEndContent, content)) {
+ nsRect rect;
+ GetRect(rect);
+ rect.width--;
+ rect.height--;
+ aRenderingContext.SetColor(NS_RGB(0,0,255));
+ aRenderingContext.DrawRect(rect);
+ aRenderingContext.DrawLine(rect.x, rect.y, rect.x+rect.width, rect.y+rect.height);
+ aRenderingContext.DrawLine(rect.x, rect.y+rect.height, rect.x+rect.width, rect.y);
+ }
+
+ if (clearAfterPaint) {
+ mSelectionRange = nsnull;
+ }
+ NS_IF_RELEASE(selStartContent);
+ NS_IF_RELEASE(selEndContent);
+ NS_RELEASE(content);
+ NS_RELEASE(doc);
+ NS_RELEASE(shell);
+
+ return NS_OK;
+}
+
+/**
+ *
+ */
+NS_METHOD nsFrame::HandleEvent(nsIPresContext& aPresContext,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus)
+{
+ aEventStatus = nsEventStatus_eIgnore;
+
+ 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(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 (SELECTION_DEBUG) printf("Message: %d-------------------------------------------------------------\n",aEvent->message);
+
+
+ if (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) {
+ if (mDoingSelection) {
+ HandleRelease(aPresContext, aEvent, aEventStatus);
+ }
+ } else if (aEvent->message == NS_MOUSE_MOVE) {
+ mDidDrag = PR_TRUE;
+ HandleDrag(aPresContext, aEvent, aEventStatus);
+ if (SELECTION_DEBUG) printf("HandleEvent(Drag)::mSelectionRange %s\n", mSelectionRange->ToString());
+
+ } else if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) {
+ HandlePress(aPresContext, aEvent, aEventStatus);
+ }
+ }
+
+ return NS_OK;
+}
+
+/**
+ * Handles the Mouse Press Event for the frame
+ */
+NS_METHOD nsFrame::HandlePress(nsIPresContext& aPresContext,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus)
+{
+ if (DisplaySelection(aPresContext, PR_TRUE) == PR_FALSE)
+ {
+ aEventStatus = nsEventStatus_eIgnore;
+ return NS_OK;
+ }
+
+ nsFrame * currentFrame = this;
+ nsIPresShell * shell = aPresContext.GetShell();
+ nsMouseEvent * mouseEvent = (nsMouseEvent *)aEvent;
+
+ gDoc = shell->GetDocument();
+
+ nsISelection * selection;
+ gDoc->GetSelection(selection);
+
+
+ mSelectionRange = selection->GetRange();
+
+ PRUint32 actualOffset = 0;
+
+ mDoingSelection = PR_TRUE;
+ mDidDrag = PR_FALSE;
+ mCurrentFrame = currentFrame;
+
+ mStartPos = GetPosition(aPresContext, aEvent, currentFrame, actualOffset);
+
+ // Click count is 1
+ nsIContent * newContent;
+ currentFrame->GetContent(newContent);
+
+ mCurrentFrame = currentFrame;
+
+ if (mStartSelectionPoint == nsnull) {
+ mStartSelectionPoint = new nsSelectionPoint(nsnull, -1, PR_TRUE);
+ }
+ if (mEndSelectionPoint == nsnull) {
+ mEndSelectionPoint = new nsSelectionPoint(nsnull, -1, PR_TRUE);
+ }
+
+ mSelectionRange->GetStartPoint(mStartSelectionPoint);
+ mSelectionRange->GetEndPoint(mEndSelectionPoint);
+
+ resetContentTrackers();
+
+ // Get the Current Start and End Content Pointers
+ nsIContent * selStartContent = mSelectionRange->GetStartContent(); // ref counted
+ nsIContent * selEndContent = mSelectionRange->GetEndContent(); // ref counted
+
+ if (SELECTION_DEBUG) printf("****** Shift[%s]\n", (mouseEvent->isShift?"Down":"Up"));
+
+ PRBool inRange = gDoc->IsInRange(selStartContent, selEndContent, newContent);
+
+ if (inRange) {
+ //resetContentTrackers();
+ if (TRACKER_DEBUG) printf("Adding split range to removed selection. Shift[%s]\n", (mouseEvent->isShift?"Down":"Up"));
+
+ if (mouseEvent->isShift) {
+ if (newContent == selStartContent && newContent == selEndContent) {
+ addRangeToSelectionTrackers(newContent, newContent, kInsertInAddList);
+ } else {
+ if (selStartContent == newContent) {
+ // Trackers just do painting so add all the content nodes in the remove list
+ // even though you might think you shouldn't put the start content node there
+ addRangeToSelectionTrackers(selStartContent, selEndContent, kInsertInRemoveList);
+ } else if (selEndContent == newContent) {
+ // just repaint the end content node
+ addRangeToSelectionTrackers(selEndContent, selEndContent, kInsertInAddList);
+ } else {
+ if (gDoc->IsBefore(newContent, selEndContent)) {
+ addRangeToSelectionTrackers(newContent, selEndContent, kInsertInRemoveList);
+ } else {
+ addRangeToSelectionTrackers(selEndContent, newContent, kInsertInRemoveList);
+ }
+ }
+ }
+ mEndSelectionPoint->SetPoint(newContent, mStartPos, PR_FALSE);
+ } else {
+ addRangeToSelectionTrackers(selStartContent, selEndContent, kInsertInRemoveList); // removed from selection
+
+ mStartSelectionPoint->SetPoint(newContent, mStartPos, PR_TRUE);
+ mEndSelectionPoint->SetPoint(newContent, mStartPos, PR_TRUE);
+
+ addRangeToSelectionTrackers(newContent, newContent, kInsertInAddList); // add to selection
+ }
+
+ } else if (gDoc->IsBefore(newContent, selStartContent)) {
+ if (mouseEvent->isShift) {
+ if (mStartSelectionPoint->IsAnchor()) {
+ if (SELECTION_DEBUG) printf("New Content is before, Start will now be end\n");
+
+ addRangeToSelectionTrackers(selStartContent, selEndContent, kInsertInRemoveList); // removed from selection
+
+ mEndSelectionPoint->SetPoint(selStartContent, mStartSelectionPoint->GetOffset(), PR_TRUE);
+ mStartSelectionPoint->SetPoint(newContent, mStartPos, PR_FALSE);
+
+ // End Point has changed
+ nsIContent * endcontent = mEndSelectionPoint->GetContent(); // ref counted
+ addRangeToSelectionTrackers(newContent, endcontent, kInsertInAddList); // add to selection
+ NS_RELEASE(endcontent);
+ } else {
+ if (SELECTION_DEBUG) printf("New Content is before, Appending to Beginning\n");
+ addRangeToSelectionTrackers(newContent, selEndContent, kInsertInAddList); // add to selection
+ mStartSelectionPoint->SetPoint(newContent, mStartPos, PR_FALSE);
+ }
+ } else {
+ if (SELECTION_DEBUG) printf("Adding full range to removed selection. (insert selection)\n");
+ addRangeToSelectionTrackers(selStartContent, selEndContent, kInsertInRemoveList); // removed from selection
+
+ mEndSelectionPoint->SetPoint(newContent, mStartPos, PR_TRUE);
+
+ mStartSelectionPoint->SetPoint(newContent, mStartPos, PR_TRUE);
+
+ addRangeToSelectionTrackers(newContent, newContent, kInsertInAddList); // add to selection
+ }
+ } else { // Content is After End
+
+ if (mouseEvent->isShift) {
+ if (selStartContent == nsnull && selEndContent == nsnull) {
+ // Shift Click without first clicking in the window
+ // is interpreted the same as just clicking in a window
+ mEndSelectionPoint->SetPoint(newContent, mStartPos, PR_TRUE);
+ mStartSelectionPoint->SetPoint(newContent, mStartPos, PR_TRUE);
+ addRangeToSelectionTrackers(newContent, newContent, kInsertInAddList); // add to selection
+
+ } else if (mStartSelectionPoint->IsAnchor()) {
+ if (SELECTION_DEBUG) printf("New Content is after, Append new content\n");
+ addRangeToSelectionTrackers(selEndContent, newContent, kInsertInAddList); // add to selection
+ mEndSelectionPoint->SetPoint(newContent, mStartPos, PR_FALSE);
+
+ } else {
+ if (SELECTION_DEBUG) printf("New Content is after, End will now be Start\n");
+
+ addRangeToSelectionTrackers(selStartContent, selEndContent, kInsertInRemoveList); // removed from selection
+ mStartSelectionPoint->SetPoint(selEndContent, mEndSelectionPoint->GetOffset(), PR_TRUE);
+ mEndSelectionPoint->SetPoint(newContent, mStartPos, PR_FALSE);
+ addRangeToSelectionTrackers(newContent, newContent, kInsertInAddList); // add to selection
+ }
+
+ } else {
+ if (TRACKER_DEBUG) printf("Adding full range to removed selection.\n");
+ addRangeToSelectionTrackers(selStartContent, selEndContent, kInsertInRemoveList); // removed from selection
+
+ mEndSelectionPoint->SetPoint(newContent, mStartPos, PR_TRUE);
+
+ mStartSelectionPoint->SetPoint(newContent, mStartPos, PR_TRUE);
+
+ addRangeToSelectionTrackers(newContent, newContent, kInsertInAddList); // add to selection
+ }
+ }
+
+
+ mSelectionRange->SetStartPoint(mStartSelectionPoint);
+ mSelectionRange->SetEndPoint(mEndSelectionPoint);
+
+ //if (selStartContent) printf("selStartContent count %d\n", selStartContent->Release());
+ //if (selEndContent) printf("selEndContent count %d\n", selEndContent->Release());
+ //if (newContent) printf("newContent count %d\n", newContent->Release());
+
+ NS_IF_RELEASE(selStartContent);
+ NS_IF_RELEASE(selEndContent);
+ NS_IF_RELEASE(newContent);
+
+ RefreshFromContentTrackers(aPresContext);
+
+
+ if (SELECTION_DEBUG) printf("HandleEvent::mSelectionRange %s\n", mSelectionRange->ToString());
+
+ // Force Update
+ ForceDrawFrame(this);
+
+ NS_RELEASE(shell);
+ NS_RELEASE(selection);
+
+ aEventStatus = nsEventStatus_eIgnore;
+ return NS_OK;
+
+}
+
+NS_METHOD nsFrame::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;
+
+ //if (aFrame != nsnull) {
+ //printf("nsFrame::HandleDrag\n");
+
+ // Check to see if we have changed frame
+ if (this != mCurrentFrame) {
+ // We are in a new Frame!
+ if (SELECTION_DEBUG) printf("HandleDrag::Different Frame in selection!\n");
+
+ // Get Content for current Frame
+ nsIContent * currentContent;
+ mCurrentFrame->GetContent(currentContent);
+
+ // Get Content for New Frame
+ nsIContent * newContent;
+ this->GetContent(newContent);
+
+ // Check to see if we are still in the same Content
+ if (currentContent == newContent) {
+ if (SELECTION_DEBUG) printf("HandleDrag::New Frame, same content.\n");
+
+ AdjustPointsInSameContent(aPresContext, aEvent);
+ addRangeToSelectionTrackers(currentContent, currentContent, kInsertInAddList);
+
+ } else if (gDoc->IsBefore(newContent, currentContent)) {
+ if (SELECTION_DEBUG) printf("HandleDrag::New Frame, is Before.\n");
+
+ resetContentTrackers();
+ NewContentIsBefore(aPresContext, aEvent, newContent, currentContent, this);
+
+ } else { // Content is AFTER
+ if (SELECTION_DEBUG) printf("HandleDrag::New Frame, is After.\n");
+
+ resetContentTrackers();
+ NewContentIsAfter(aPresContext, aEvent, newContent, currentContent, this);
+ }
+ mCurrentFrame = this;
+
+ NS_RELEASE(currentContent);
+ NS_RELEASE(newContent);
+ } else if ((nsnull != mStartSelectionPoint) && (nsnull != mEndSelectionPoint)) {
+ if (SELECTION_DEBUG) printf("HandleDrag::Same Frame.\n");
+
+ // Same Frame as before
+ //if (SELECTION_DEBUG) printf("\nSame Start: %s\n", mStartSelectionPoint->ToString());
+ //if (SELECTION_DEBUG) printf("Same End: %s\n", mEndSelectionPoint->ToString());
+ // [TODO] Uncomment these soon
+
+ nsIContent * selStartContent = mStartSelectionPoint->GetContent();
+ nsIContent * selEndContent = mEndSelectionPoint->GetContent();
+
+ if (selStartContent == selEndContent) {
+ if (SELECTION_DEBUG) printf("Start & End Frame are the same: \n");
+ AdjustPointsInSameContent(aPresContext, aEvent);
+ } else {
+ if (SELECTION_DEBUG) printf("Start & End Frame are different: \n");
+
+ // Get Content for New Frame
+ nsIContent * newContent;
+ this->GetContent(newContent);
+ PRInt32 newPos = -1;
+ PRUint32 actualOffset = 0;
+
+ newPos = GetPosition(aPresContext, aEvent, this, actualOffset);
+
+ if (newContent == selStartContent) {
+ if (SELECTION_DEBUG) printf("New Content equals Start Content\n");
+ mStartSelectionPoint->SetOffset(newPos);
+ mSelectionRange->SetStartPoint(mStartSelectionPoint);
+ } else if (newContent == selEndContent) {
+ if (SELECTION_DEBUG) printf("New Content equals End Content\n");
+ mEndSelectionPoint->SetOffset(newPos);
+ mSelectionRange->SetEndPoint(mEndSelectionPoint);
+ } else {
+ if (SELECTION_DEBUG) printf("=====\n=====\n=====\n=====\n=====\n=====\n Should NOT be here.\n");
+ }
+
+ //if (SELECTION_DEBUG) printf("*Same Start: "+mStartSelectionPoint->GetOffset()+
+ // " "+mStartSelectionPoint->IsAnchor()+
+ // " End: "+mEndSelectionPoint->GetOffset() +
+ // " "+mEndSelectionPoint->IsAnchor());
+ NS_RELEASE(newContent);
+ }
+ NS_IF_RELEASE(selStartContent);
+ NS_IF_RELEASE(selEndContent);
+ }
+ //}
+
+
+ NS_IF_RELEASE(startContent);
+ NS_IF_RELEASE(endContent);
+
+ // Force Update
+ ForceDrawFrame(this);
+ //RefreshContentFrames(aPresContext, startContent, endContent);
+ RefreshFromContentTrackers(aPresContext);
+
+ aEventStatus = nsEventStatus_eIgnore;
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::HandleRelease(nsIPresContext& aPresContext,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus)
+{
+ mDoingSelection = PR_FALSE;
+ aEventStatus = nsEventStatus_eIgnore;
+ NS_IF_RELEASE(gDoc);
+ return NS_OK;
+}
+
+//--------------------------------------------------------------------------
+//-- GetPosition
+//--------------------------------------------------------------------------
+PRInt32 nsFrame::GetPosition(nsIPresContext& aPresContext,
+ nsGUIEvent * aEvent,
+ nsIFrame * aNewFrame,
+ PRUint32& aAcutalContentOffset) {
+
+ //PRInt32 offset;
+ //PRInt32 width;
+ //CalcCursorPosition(aPresContext, aEvent, aNewFrame, offset, width);
+ //offset += aNewFrame->GetContentOffset();
+
+ //return offset;
+ aAcutalContentOffset = 0;
+ return -1;
+}
+
+/********************************************************
+* Adjusts the Starting and Ending TextPoint for a Range
+*********************************************************/
+void nsFrame::AdjustPointsInNewContent(nsIPresContext& aPresContext,
+ nsGUIEvent * aEvent,
+ nsIFrame * aNewFrame) {
+ PRUint32 actualOffset = 0;
+
+ // Get new Cursor Poition in the new content
+ PRInt32 newPos = GetPosition(aPresContext, aEvent, aNewFrame, actualOffset);
+
+ if (mStartSelectionPoint->IsAnchor()) {
+ if (newPos == mStartSelectionPoint->GetOffset()) {
+ mEndSelectionPoint->SetOffset(newPos);
+ mEndSelectionPoint->SetAnchor(PR_TRUE);
+ mSelectionRange->SetEndPoint(mEndSelectionPoint);
+ } else if (newPos < mStartSelectionPoint->GetOffset()) {
+ mEndSelectionPoint->SetOffset(mStartSelectionPoint->GetOffset());
+ mEndSelectionPoint->SetAnchor(PR_TRUE);
+ mStartSelectionPoint->SetOffset(newPos);
+ mStartSelectionPoint->SetAnchor(PR_FALSE);
+ mSelectionRange->SetRange(mStartSelectionPoint, mEndSelectionPoint);
+ } else {
+ mEndSelectionPoint->SetOffset(newPos);
+ mSelectionRange->SetEndPoint(mEndSelectionPoint);
+ }
+ } else if (mEndSelectionPoint->IsAnchor()) {
+ int endPos = mEndSelectionPoint->GetOffset();
+ if (newPos == mEndSelectionPoint->GetOffset()) {
+ mStartSelectionPoint->SetOffset(newPos);
+ mStartSelectionPoint->SetAnchor(PR_TRUE);
+ mSelectionRange->SetStartPoint(mStartSelectionPoint);
+ } else if (newPos > mEndSelectionPoint->GetOffset()) {
+ mEndSelectionPoint->SetOffset(newPos);
+ mEndSelectionPoint->SetAnchor(PR_FALSE);
+ mStartSelectionPoint->SetOffset(endPos);
+ mStartSelectionPoint->SetAnchor(PR_TRUE);
+ mSelectionRange->SetRange(mStartSelectionPoint, mEndSelectionPoint);
+ } else {
+ mStartSelectionPoint->SetOffset(newPos);
+ mSelectionRange->SetStartPoint(mStartSelectionPoint);
+ }
+ } else {
+ // [TODO] Should get here
+ // throw exception
+ if (SELECTION_DEBUG) printf("--\n--\n--\n--\n--\n--\n--\n Should be here. #102\n");
+ //return;
+ }
+}
+
+/********************************************************
+* Adjusts the Starting and Ending TextPoint for a Range
+*********************************************************/
+void nsFrame::AdjustPointsInSameContent(nsIPresContext& aPresContext,
+ nsGUIEvent * aEvent) {
+ PRUint32 actualOffset = 0;
+
+ // Get new Cursor Poition in the same content
+ PRInt32 newPos = GetPosition(aPresContext, aEvent, mCurrentFrame, actualOffset);
+ //newPos += actualOffset;
+ if (SELECTION_DEBUG) printf("AdjustTextPointsInSameContent newPos: %d\n", newPos);
+
+ if (mStartSelectionPoint->IsAnchor()) {
+ if (newPos == mStartSelectionPoint->GetOffset()) {
+ mEndSelectionPoint->SetOffset(newPos);
+ mEndSelectionPoint->SetAnchor(PR_TRUE);
+ mSelectionRange->SetEndPoint(mEndSelectionPoint);
+ } else if (newPos < mStartSelectionPoint->GetOffset()) {
+ mStartSelectionPoint->SetOffset(newPos);
+ mStartSelectionPoint->SetAnchor(PR_FALSE);
+ mEndSelectionPoint->SetAnchor(PR_TRUE);
+ mSelectionRange->SetRange(mStartSelectionPoint, mEndSelectionPoint);
+ } else {
+ mEndSelectionPoint->SetAnchor(PR_FALSE);
+ mEndSelectionPoint->SetOffset(newPos);
+ mSelectionRange->SetEndPoint(mEndSelectionPoint);
+ }
+ } else if (mEndSelectionPoint->IsAnchor()) {
+ if (newPos == mEndSelectionPoint->GetOffset()) {
+ mStartSelectionPoint->SetOffset(newPos);
+ mStartSelectionPoint->SetAnchor(PR_TRUE);
+ mSelectionRange->SetStartPoint(mStartSelectionPoint);
+ } else if (newPos > mEndSelectionPoint->GetOffset()) {
+ mEndSelectionPoint->SetOffset(newPos);
+ mEndSelectionPoint->SetAnchor(PR_FALSE);
+ mStartSelectionPoint->SetAnchor(PR_TRUE);
+ mSelectionRange->SetRange(mStartSelectionPoint, mEndSelectionPoint);
+ } else {
+ mStartSelectionPoint->SetAnchor(PR_FALSE);
+ mStartSelectionPoint->SetOffset(newPos);
+ mSelectionRange->SetStartPoint(mStartSelectionPoint);
+ }
+ } else {
+ // [TODO] Should get here
+ // throw exception
+ if (SELECTION_DEBUG) printf("--\n--\n--\n--\n--\n--\n--\n Should be here. #101\n");
+ //return;
+ }
+
+ if (SELECTION_DEBUG) printf("Start %s End %s\n", mStartSelectionPoint->ToString(), mEndSelectionPoint->ToString());
+ //}
+}
+
+NS_METHOD nsFrame::GetCursorAndContentAt(nsIPresContext& aPresContext,
+ const nsPoint& aPoint,
+ nsIFrame** aFrame,
+ nsIContent** aContent,
+ PRInt32& aCursor)
+{
+ *aContent = mContent;
+ aCursor = NS_STYLE_CURSOR_INHERIT;
+ return NS_OK;
+}
+
+// Resize and incremental reflow
+NS_METHOD
+nsFrame::GetFrameState(nsFrameState& aResult)
+{
+ aResult = mState;
+ return NS_OK;
+}
+
+NS_METHOD
+nsFrame::SetFrameState(nsFrameState aNewState)
+{
+ mState = aNewState;
+ return NS_OK;
+}
+
+// Resize reflow methods
+
+NS_METHOD
+nsFrame::WillReflow(nsIPresContext& aPresContext)
+{
+ NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
+ ("WillReflow: oldState=%x", mState));
+ mState |= NS_FRAME_IN_REFLOW;
+ return NS_OK;
+}
+
+NS_METHOD
+nsFrame::DidReflow(nsIPresContext& aPresContext,
+ nsDidReflowStatus aStatus)
+{
+ NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
+ ("nsFrame::DidReflow: aStatus=%d", aStatus));
+ if (NS_FRAME_REFLOW_FINISHED == aStatus) {
+ mState &= ~(NS_FRAME_IN_REFLOW | NS_FRAME_FIRST_REFLOW);
+
+ if (nsnull != mView) {
+ // Position and size view relative to its parent, not relative to our
+ // parent frame (our parent frame may not have a view).
+ nsIView* parentWithView;
+ nsPoint origin;
+ GetOffsetFromView(origin, parentWithView);
+ nsIViewManager *vm;
+ mView->GetViewManager(vm);
+ vm->ResizeView(mView, mRect.width, mRect.height);
+ vm->MoveViewTo(mView, origin.x, origin.y);
+ NS_RELEASE(vm);
+ }
+ }
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::Reflow(nsIPresContext& aPresContext,
+ nsReflowMetrics& aDesiredSize,
+ const nsReflowState& aReflowState,
+ nsReflowStatus& aStatus)
+{
+ aDesiredSize.width = 0;
+ aDesiredSize.height = 0;
+ aDesiredSize.ascent = 0;
+ aDesiredSize.descent = 0;
+ if (nsnull != aDesiredSize.maxElementSize) {
+ aDesiredSize.maxElementSize->width = 0;
+ aDesiredSize.maxElementSize->height = 0;
+ }
+ aStatus = NS_FRAME_COMPLETE;
+
+ if (eReflowReason_Incremental == aReflowState.reason) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::ContentChanged(nsIPresContext* aPresContext,
+ nsIContent* aChild,
+ nsISupports* aSubContent)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsFrame::AttributeChanged(nsIPresContext* aPresContext,
+ nsIContent* aChild,
+ nsIAtom* aAttribute,
+ PRInt32 aHint)
+{
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::GetReflowMetrics(nsIPresContext& aPresContext,
+ nsReflowMetrics& aMetrics)
+{
+ aMetrics.width = mRect.width;
+ aMetrics.height = mRect.height;
+ aMetrics.ascent = mRect.height;
+ aMetrics.descent = 0;
+ return NS_OK;
+}
+
+// Flow member functions
+
+NS_METHOD nsFrame::IsSplittable(nsSplittableType& aIsSplittable) const
+{
+ aIsSplittable = NS_FRAME_NOT_SPLITTABLE;
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::CreateContinuingFrame(nsIPresContext& aPresContext,
+ nsIFrame* aParent,
+ nsIStyleContext* aStyleContext,
+ nsIFrame*& aContinuingFrame)
+{
+ NS_ERROR("not splittable");
+ aContinuingFrame = nsnull;
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_METHOD nsFrame::GetPrevInFlow(nsIFrame*& aPrevInFlow) const
+{
+ aPrevInFlow = nsnull;
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::SetPrevInFlow(nsIFrame*)
+{
+ NS_ERROR("not splittable");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_METHOD nsFrame::GetNextInFlow(nsIFrame*& aNextInFlow) const
+{
+ aNextInFlow = nsnull;
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::SetNextInFlow(nsIFrame*)
+{
+ NS_ERROR("not splittable");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_METHOD nsFrame::AppendToFlow(nsIFrame* aAfterFrame)
+{
+ NS_ERROR("not splittable");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_METHOD nsFrame::PrependToFlow(nsIFrame* aBeforeFrame)
+{
+ NS_ERROR("not splittable");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_METHOD nsFrame::RemoveFromFlow()
+{
+ NS_ERROR("not splittable");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_METHOD nsFrame::BreakFromPrevFlow()
+{
+ NS_ERROR("not splittable");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_METHOD nsFrame::BreakFromNextFlow()
+{
+ NS_ERROR("not splittable");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+// Associated view object
+NS_METHOD nsFrame::GetView(nsIView*& aView) const
+{
+ aView = mView;
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::SetView(nsIView* aView)
+{
+ nsresult rv;
+
+ if (nsnull != aView) {
+ mView = aView;
+ aView->SetClientData(this);
+ rv = NS_OK;
+ }
+ else
+ rv = NS_OK;
+
+ return rv;
+}
+
+// Find the first geometric parent that has a view
+NS_METHOD nsFrame::GetParentWithView(nsIFrame*& aParent) const
+{
+ aParent = mGeometricParent;
+
+ while (nsnull != aParent) {
+ nsIView* parView;
+
+ aParent->GetView(parView);
+ if (nsnull != parView) {
+ break;
+ }
+ aParent->GetGeometricParent(aParent);
+ }
+
+ return NS_OK;
+}
+
+// Returns the offset from this frame to the closest geometric parent that
+// has a view. Also returns the containing view or null in case of error
+NS_METHOD nsFrame::GetOffsetFromView(nsPoint& aOffset, nsIView*& aView) const
+{
+ nsIFrame* frame = (nsIFrame*)this;
+
+ aView = nsnull;
+ aOffset.MoveTo(0, 0);
+ do {
+ nsPoint origin;
+
+ frame->GetOrigin(origin);
+ aOffset += origin;
+ frame->GetGeometricParent(frame);
+ if (nsnull != frame) {
+ frame->GetView(aView);
+ }
+ } while ((nsnull != frame) && (nsnull == aView));
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::GetWindow(nsIWidget*& aWindow) const
+{
+ nsIFrame* frame = (nsIFrame*)this;
+
+ aWindow = nsnull;
+ while (nsnull != frame) {
+ nsIView* view;
+
+ frame->GetView(view);
+ if (nsnull != view) {
+ view->GetWidget(aWindow);
+ if (nsnull != aWindow) {
+ break;
+ }
+ }
+ frame->GetParentWithView(frame);
+ }
+ NS_POSTCONDITION(nsnull != aWindow, "no window in frame tree");
+ return NS_OK;
+}
+
+void
+nsFrame::Invalidate(const nsRect& aDamageRect,
+ PRBool aImmediate) const
+{
+ nsIViewManager* viewManager = nsnull;
+
+ PRUint32 flags = aImmediate ? NS_VMREFRESH_IMMEDIATE : NS_VMREFRESH_NO_SYNC;
+ if (nsnull != mView) {
+ mView->GetViewManager(viewManager);
+ viewManager->UpdateView(mView, aDamageRect, flags);
+
+ } else {
+ nsRect rect(aDamageRect);
+ nsPoint offset;
+ nsIView* view;
+
+ GetOffsetFromView(offset, view);
+ NS_ASSERTION(nsnull != view, "no view");
+ rect += offset;
+ view->GetViewManager(viewManager);
+ viewManager->UpdateView(view, rect, flags);
+ }
+
+ NS_IF_RELEASE(viewManager);
+}
+
+// Style sizing methods
+NS_METHOD nsFrame::IsPercentageBase(PRBool& aBase) const
+{
+ const nsStylePosition* position;
+ GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)position);
+ if (position->mPosition != NS_STYLE_POSITION_NORMAL) {
+ aBase = PR_TRUE;
+ }
+ else {
+ const nsStyleDisplay* display;
+ GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
+ if ((display->mDisplay == NS_STYLE_DISPLAY_BLOCK) ||
+ (display->mDisplay == NS_STYLE_DISPLAY_LIST_ITEM)) {
+ aBase = PR_TRUE;
+ }
+ else {
+ aBase = PR_FALSE;
+ }
+ }
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::GetAutoMarginSize(PRUint8 aSide, nscoord& aSize) const
+{
+ aSize = 0; // XXX probably not right, subclass override?
+ return NS_OK;
+}
+
+
+// Sibling pointer used to link together frames
+
+NS_METHOD nsFrame::GetNextSibling(nsIFrame*& aNextSibling) const
+{
+ aNextSibling = mNextSibling;
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::SetNextSibling(nsIFrame* aNextSibling)
+{
+ mNextSibling = aNextSibling;
+ return NS_OK;
+}
+
+// Transparency query
+NS_METHOD nsFrame::IsTransparent(PRBool& aTransparent) const
+{
+ //XXX this needs to be overridden in just about every leaf class? MMP
+ aTransparent = PR_TRUE;
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::Scrolled(nsIView *aView)
+{
+ return NS_OK;
+}
+
+// Debugging
+NS_METHOD nsFrame::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);
+ }
+ if ((nsnull==aFilter) || (PR_TRUE==aFilter->OutputTag(&tagString)))
+ {
+ // Indent
+ for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
+
+ // Output the tag and rect
+ ListTag(out);
+ if (nsnull != mView) {
+ fprintf(out, " [view=%p]", mView);
+ }
+ fputs(" ", out);
+ out << mRect;
+ if (0 != mState) {
+ fprintf(out, " [state=%08x]", mState);
+ }
+ fputs("<>\n", out);
+ }
+ return NS_OK;
+}
+
+// Output the frame's tag
+NS_METHOD nsFrame::ListTag(FILE* out) const
+{
+ nsIAtom* tag;
+ mContent->GetTag(tag);
+ if (tag != nsnull) {
+ nsAutoString buf;
+ tag->ToString(buf);
+ fputs(buf, out);
+ NS_RELEASE(tag);
+ }
+ PRInt32 contentIndex;
+
+ GetContentIndex(contentIndex);
+ fprintf(out, "(%d)@%p", contentIndex, this);
+ return NS_OK;
+}
+
+NS_METHOD nsFrame::VerifyTree() const
+{
+ NS_ASSERTION(0 == (mState & NS_FRAME_IN_REFLOW), "frame is in reflow");
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------------
+
+/********************************************************
+* Handles a when the cursor enters new content that is before
+* the content that the cursor is currently in
+*********************************************************/
+void nsFrame::NewContentIsBefore(nsIPresContext& aPresContext,
+ nsGUIEvent * aEvent,
+ nsIContent * aNewContent,
+ nsIContent * aCurrentContent,
+ nsIFrame * aNewFrame)
+{
+ if (SELECTION_DEBUG) printf("New Frame, New content is before.\n");
+ // Dragging mouse to the left or backward in content
+ //
+ // 1) The cursor is being dragged backward in the content
+ // and the mouse is "after" the anchor in the content
+ // and the current piece of content is being removed from the selection
+ //
+ // This section cover two cases:
+ // 2) The cursor is being dragged backward in the content
+ // and the mouse is "before" the anchor in the content
+ // and each new piece of content is being added to the selection
+
+ if ((nsnull == mStartSelectionPoint) || (nsnull == mEndSelectionPoint)) {
+ return;
+ }
+ nsIPresShell * shell = aPresContext.GetShell();
+ nsIDocument * doc = shell->GetDocument();
+ nsIContent * selStartContent = mStartSelectionPoint->GetContent();
+ nsIContent * selEndContent = mEndSelectionPoint->GetContent();
+
+ PRBool inRange = doc->IsInRange(selStartContent, selEndContent, aNewContent);
+
+ // Check to see if the new content is in the selection
+ if (inRange) {
+
+ // Case #1 - Remove Current Content from Selection (at End)
+ if (SELECTION_DEBUG) printf("Case #1 - (Before) New Content is in selected Range.\n");
+
+
+ if (aNewContent == selStartContent) {
+ // [TODO] This is where we might have to delete from end to new content
+
+ // Returns the new End Point, if Start and End are on the
+ // same content then End Point's Cursor is set to Start's
+ mEndSelectionPoint->SetContent(selStartContent);
+ AdjustPointsInNewContent(aPresContext, aEvent, aNewFrame);
+
+ } else {
+ PRUint32 actualOffset = 0;
+ PRInt32 newPos = GetPosition(aPresContext, aEvent, aNewFrame, actualOffset);
+ mEndSelectionPoint->SetPoint(aNewContent, newPos, PR_FALSE);
+ mSelectionRange->SetEndPoint(mEndSelectionPoint);
+ }
+
+ // The current content is being removed from Selection
+ addRangeToSelectionTrackers(aNewContent, aCurrentContent, kInsertInRemoveList);
+ } else {
+ // Case #2 - Add new content to selection (At Start)
+ if (SELECTION_DEBUG) printf("Case #2 - (Before) New Content is NOT in selected Range. Moving Start Backward.\n");
+
+ PRUint32 actualOffset = 0;
+ PRInt32 newPos = GetPosition(aPresContext, aEvent, aNewFrame, actualOffset);
+
+ // Create new TextPoint and move Start Point backward
+ mStartSelectionPoint->SetPoint(aNewContent, newPos, PR_FALSE); // position is set correctly in adjustTextPoints
+ mSelectionRange->SetStartPoint(mStartSelectionPoint);
+
+ // The New Content is added to Tracker
+ addRangeToSelectionTrackers(aNewContent, aCurrentContent, kInsertInAddList);
+ }
+ NS_RELEASE(selStartContent);
+ NS_RELEASE(selEndContent);
+ NS_RELEASE(doc);
+ NS_RELEASE(shell);
+}
+
+ /********************************************************
+* Refreshes each content's frame
+*********************************************************/
+void RefreshAllContentFrames(nsIFrame * aFrame, nsIContent * aContent)
+{
+ nsIContent* frameContent;
+ aFrame->GetContent(frameContent);
+ if (frameContent == aContent) {
+ ForceDrawFrame((nsFrame *)aFrame);
+ }
+ NS_RELEASE(frameContent);
+
+ aFrame->FirstChild(aFrame);
+ while (aFrame) {
+ RefreshAllContentFrames(aFrame, aContent);
+ aFrame->GetNextSibling(aFrame);
+ }
+}
+
+/********************************************************
+* Refreshes each content's frame
+*********************************************************/
+void RefreshContentFrames(nsIPresContext& aPresContext,
+ nsIContent * aStartContent,
+ nsIContent * aEndContent)
+{
+ //-------------------------------------
+ // Undraw all the current selected frames
+ // XXX Kludge for now
+ nsIPresShell * shell = aPresContext.GetShell();
+ nsIFrame * rootFrame = shell->GetRootFrame();
+
+ PRBool foundStart = PR_FALSE;
+ for (PRInt32 i=0;iFindFrameWithContent(node));
+ RefreshAllContentFrames(rootFrame, node);
+ if (aStartContent == aEndContent) {
+ break;
+ }
+ } else if (foundStart) {
+ //ForceDrawFrame((nsFrame *)shell->FindFrameWithContent(node));
+ RefreshAllContentFrames(rootFrame, node);
+ } else if (aEndContent == node) {
+ //ForceDrawFrame((nsFrame *)shell->FindFrameWithContent(node));
+ RefreshAllContentFrames(rootFrame, node);
+ break;
+ }
+ }
+ //NS_RELEASE(rootFrame);
+ NS_RELEASE(shell);
+ //-------------------------------------
+}
+
+/********************************************************
+* Handles a when the cursor enters new content that is After
+* the content that the cursor is currently in
+*********************************************************/
+void nsFrame::NewContentIsAfter(nsIPresContext& aPresContext,
+ nsGUIEvent * aEvent,
+ nsIContent * aNewContent,
+ nsIContent * aCurrentContent,
+ nsIFrame * aNewFrame)
+{
+ if (SELECTION_DEBUG) printf("New Frame, New content is after.\n");
+
+
+ // Dragging Mouse to the Right
+ //
+ // 3) The cursor is being dragged foward in the content
+ // and the mouse is "before" the anchor in the content
+ // and the current piece of content is being removed from the selection
+ //
+ // This section cover two cases:
+ // 4) The cursor is being dragged foward in the content
+ // and the mouse is "after" the anchor in the content
+ // and each new piece of content is being added to the selection
+ //
+
+ // Check to see if the new content is in the selection
+ nsIPresShell * shell = aPresContext.GetShell();
+ nsIDocument * doc = shell->GetDocument();
+ nsIContent * selStartContent = mStartSelectionPoint->GetContent();
+ nsIContent * selEndContent = mEndSelectionPoint->GetContent();
+
+ PRBool inRange = doc->IsInRange(selStartContent, selEndContent, aNewContent);
+
+ if (inRange) {
+ // Case #3 - Remove Content (from Start)
+ if (SELECTION_DEBUG) printf("Case #3 - (After) New Content is in selected Range.\n");
+
+ // Remove Current Content in Tracker, but leave New Content in Selection
+ addRangeToSelectionTrackers(mStartSelectionPoint->GetContent(), aNewContent, kInsertInRemoveList);
+
+ PRUint32 actualOffset = 0;
+ // [TODO] Always get nearest Text content
+ PRInt32 newPos = GetPosition(aPresContext, aEvent, aNewFrame, actualOffset);
+
+ // Check to see if the new Content is the same as the End Point's
+ if (aNewContent == selEndContent) {
+ if (SELECTION_DEBUG) printf("New Content matches End Point\n");
+
+ mStartSelectionPoint->SetContent(aNewContent);
+ AdjustPointsInNewContent(aPresContext, aEvent, aNewFrame);
+
+ } else {
+ if (SELECTION_DEBUG) printf("New Content does NOT matches End Point\n");
+ mStartSelectionPoint->SetPoint(aNewContent, newPos, PR_FALSE);
+ mSelectionRange->SetStartPoint(mStartSelectionPoint);
+ }
+
+ } else {
+ if (SELECTION_DEBUG)
+ printf("Case #4 - (After) Adding New Content\n");
+
+ // Case #2 - Adding Content (at End)
+ PRUint32 actualOffset = 0;
+ // The new content is not in the selection
+ PRInt32 newPos = GetPosition(aPresContext, aEvent, aNewFrame, actualOffset);
+
+ // Check to see if we need to create a new SelectionPoint and add it
+ // or do we simply move the existing start or end point
+ if (selStartContent == selEndContent) {
+ if (SELECTION_DEBUG) printf("Case #4 - Start & End Content the Same\n");
+ // Move start or end point
+ // Get new Cursor Poition in the new content
+
+ if (mStartSelectionPoint->IsAnchor()) {
+ if (SELECTION_DEBUG) printf("Case #4 - Start is Anchor\n");
+ // Since the Start is the Anchor just adjust the end
+
+ // XXX Note this includes the current End point (it should be end->nextContent)
+ addRangeToSelectionTrackers(selEndContent, aNewContent, kInsertInAddList);
+
+ mEndSelectionPoint->SetPoint(aNewContent, newPos, PR_FALSE);
+ mSelectionRange->SetEndPoint(mEndSelectionPoint);
+
+ } else {
+ if (SELECTION_DEBUG) printf("Case #4 - Start is NOT Anchor\n");
+ // Because End was the anchor, we need to set the Start Point to
+ // the End's Offset and set it to be the new anchor
+ addRangeToSelectionTrackers(selStartContent,selEndContent, kInsertInRemoveList);
+
+ int endPos = mEndSelectionPoint->GetOffset();
+ mStartSelectionPoint->SetOffset(endPos);
+ mStartSelectionPoint->SetAnchor(PR_TRUE);
+
+ // The Start point was being moved so when it jumped to the new frame
+ // we needed to make it the new End Point
+ mEndSelectionPoint->SetPoint(aNewContent, newPos, PR_FALSE);
+ mSelectionRange->SetRange(mStartSelectionPoint, mEndSelectionPoint);
+
+ // The Content values have changed so go get new contents
+ nsIContent * startContent = mStartSelectionPoint->GetContent();
+ nsIContent * endContent = mEndSelectionPoint->GetContent();
+ addRangeToSelectionTrackers(startContent, endContent, kInsertInRemoveList);
+ NS_RELEASE(startContent);
+ NS_RELEASE(endContent);
+ }
+ } else {
+ if (SELECTION_DEBUG) printf("Case #4 - Start & End Content NOT the Same\n");
+ // Adjust the end point
+ mEndSelectionPoint->SetPoint(aNewContent, newPos, PR_FALSE);
+ mSelectionRange->SetRange(mStartSelectionPoint, mEndSelectionPoint);
+
+ // Add New Content to Selection Tracker
+ // The Content values have changed so go get new contents
+ // NOTE: selEndContent holds the "old" end content pointer
+ // and endContent hold the "new" content pointer
+ nsIContent * endContent = mEndSelectionPoint->GetContent();
+ addRangeToSelectionTrackers(selEndContent, endContent, kInsertInAddList);
+ NS_RELEASE(endContent);
+ }
+ }
+
+ NS_RELEASE(selStartContent);
+ NS_RELEASE(selEndContent);
+ NS_RELEASE(doc);
+ NS_RELEASE(shell);
+}
+
+/**
+ *
+ */
+void ForceDrawFrame(nsFrame * aFrame)//, PRBool)
+{
+ if (aFrame == nsnull) {
+ return;
+ }
+ nsRect rect;
+ nsIView * view;
+ nsPoint pnt;
+ aFrame->GetOffsetFromView(pnt, view);
+ aFrame->GetRect(rect);
+ rect.x = pnt.x;
+ rect.y = pnt.y;
+ if (view != nsnull) {
+ nsIViewManager * viewMgr;
+ view->GetViewManager(viewMgr);
+ if (viewMgr != nsnull) {
+ viewMgr->UpdateView(view, rect, 0);
+ NS_RELEASE(viewMgr);
+ }
+ //viewMgr->UpdateView(view, rect, NS_VMREFRESH_DOUBLE_BUFFER | NS_VMREFRESH_IMMEDIATE);
+ }
+
+}
+
+
+/////////////////////////////////////////////////
+// Selection Tracker Methods
+/////////////////////////////////////////////////
+
+//----------------------------
+//
+//----------------------------
+void resetContentTrackers() {
+ PRInt32 i;
+ for (i=0;iGetRootFrame();
+ for (i=0;iFindFrameWithContent(fTrackerContentArrayRemoveList[i]));
+ if (SELECTION_DEBUG) printf("ForceDrawFrame (remove) content 0x%X\n", fTrackerContentArrayRemoveList[i]);
+ }
+ for (i=0;iFindFrameWithContent(fTrackerContentArrayAddList[i]);
+ //ForceDrawFrame((nsFrame *)frame);
+ RefreshAllContentFrames(rootFrame, fTrackerContentArrayAddList[i]);
+ if (SELECTION_DEBUG) printf("ForceDrawFrame (add) content 0x%X\n", fTrackerContentArrayAddList[i]);
+ }
+ NS_RELEASE(shell);
+ resetContentTrackers();
+}
+
+//----------------------------
+//
+//----------------------------
+void addRangeToSelectionTrackers(nsIContent * aStartContent, nsIContent * aEndContent, PRUint32 aType)
+{
+ if (aStartContent == nsnull || aEndContent == nsnull) {
+ return;
+ }
+ nsIContent ** contentList = (aType == kInsertInRemoveList?fTrackerContentArrayRemoveList:fTrackerContentArrayAddList);
+ int inx = (aType == kInsertInRemoveList?fTrackerRemoveListMax:fTrackerAddListMax);
+
+ NS_ADDREF(aStartContent);
+ nsIContent * contentPtr = aStartContent;
+ while (contentPtr != aEndContent) {
+ contentList[inx++] = contentPtr;
+ contentPtr = gDoc->GetNextContent(contentPtr); // This does an AddRef
+ }
+ contentList[inx++] = aEndContent;
+
+ if (SELECTION_DEBUG) printf("Adding to %s %d\n", (aType == kInsertInRemoveList?"Remove Array":"Add Array"), inx);
+
+ if (aType == kInsertInRemoveList) {
+ fTrackerRemoveListMax = inx;
+ } else { // kInsertInAddList
+ fTrackerAddListMax = inx;
+ }
+}
+
+
+#ifdef NS_DEBUG
+static void
+GetTagName(nsFrame* aFrame, nsIContent* aContent, PRIntn aResultSize,
+ char* aResult)
+{
+ char namebuf[40];
+ namebuf[0] = 0;
+ if (nsnull != aContent) {
+ nsIAtom* tag;
+ aContent->GetTag(tag);
+ if (nsnull != tag) {
+ nsAutoString tmp;
+ tag->ToString(tmp);
+ tmp.ToCString(namebuf, sizeof(namebuf));
+ NS_RELEASE(tag);
+ }
+ }
+ PR_snprintf(aResult, aResultSize, "%s@%p", namebuf, aFrame);
+}
+
+void
+nsFrame::Trace(const char* aMethod, PRBool aEnter)
+{
+ if (NS_FRAME_LOG_TEST(gLogModule, NS_FRAME_TRACE_CALLS)) {
+ char tagbuf[40];
+ GetTagName(this, mContent, sizeof(tagbuf), tagbuf);
+ PR_LogPrint("%s: %s %s", tagbuf, aEnter ? "enter" : "exit", aMethod);
+ }
+}
+
+void
+nsFrame::Trace(const char* aMethod, PRBool aEnter, nsReflowStatus aStatus)
+{
+ if (NS_FRAME_LOG_TEST(gLogModule, NS_FRAME_TRACE_CALLS)) {
+ char tagbuf[40];
+ GetTagName(this, mContent, sizeof(tagbuf), tagbuf);
+ PR_LogPrint("%s: %s %s, status=%scomplete%s",
+ tagbuf, aEnter ? "enter" : "exit", aMethod,
+ NS_FRAME_IS_NOT_COMPLETE(aStatus) ? "not" : "",
+ (NS_FRAME_REFLOW_NEXTINFLOW & aStatus) ? "+reflow" : "");
+ }
+}
+
+void
+nsFrame::TraceMsg(const char* aFormatString, ...)
+{
+ if (NS_FRAME_LOG_TEST(gLogModule, NS_FRAME_TRACE_CALLS)) {
+ // Format arguments into a buffer
+ char argbuf[200];
+ va_list ap;
+ va_start(ap, aFormatString);
+ PR_vsnprintf(argbuf, sizeof(argbuf), aFormatString, ap);
+ va_end(ap);
+
+ char tagbuf[40];
+ GetTagName(this, mContent, sizeof(tagbuf), tagbuf);
+ PR_LogPrint("%s: %s", tagbuf, argbuf);
+ }
+}
+#endif
diff --git a/layout/html/base/src/nsFrame.h b/layout/html/base/src/nsFrame.h
new file mode 100644
index 000000000000..8e75f3215794
--- /dev/null
+++ b/layout/html/base/src/nsFrame.h
@@ -0,0 +1,294 @@
+/* -*- 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 "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.
+ */
+#ifndef nsFrame_h___
+#define nsFrame_h___
+
+#include "nsIFrame.h"
+#include "nsRect.h"
+#include "nsISelection.h"
+#include "nsSelectionRange.h"
+#include "nsSelectionPoint.h"
+#include "prlog.h"
+
+/**
+ * nsFrame logging constants. We redefine the nspr
+ * PRLogModuleInfo.level field to be a bitfield. Each bit controls a
+ * specific type of logging. Each logging operation has associated
+ * inline methods defined below.
+ */
+#define NS_FRAME_TRACE_CALLS 0x1
+#define NS_FRAME_TRACE_PUSH_PULL 0x2
+#define NS_FRAME_TRACE_CHILD_REFLOW 0x4
+#define NS_FRAME_TRACE_NEW_FRAMES 0x8
+
+#define NS_FRAME_LOG_TEST(_lm,_bit) (PRIntn((_lm)->level) & (_bit))
+
+#ifdef NS_DEBUG
+#define NS_FRAME_LOG(_bit,_args) \
+ PR_BEGIN_MACRO \
+ if (NS_FRAME_LOG_TEST(nsIFrame::GetLogModuleInfo(),_bit)) { \
+ PR_LogPrint _args; \
+ } \
+ PR_END_MACRO
+#else
+#define NS_FRAME_LOG(_bit,_args)
+#endif
+
+// XXX Need to rework this so that logging is free when it's off
+#ifdef NS_DEBUG
+#define NS_FRAME_TRACE_IN(_method) Trace(_method, PR_TRUE)
+
+#define NS_FRAME_TRACE_OUT(_method) Trace(_method, PR_FALSE)
+
+// XXX remove me
+#define NS_FRAME_TRACE_MSG(_bit,_args) \
+ PR_BEGIN_MACRO \
+ if (NS_FRAME_LOG_TEST(nsIFrame::GetLogModuleInfo(),_bit)) { \
+ TraceMsg _args; \
+ } \
+ PR_END_MACRO
+
+#define NS_FRAME_TRACE(_bit,_args) \
+ PR_BEGIN_MACRO \
+ if (NS_FRAME_LOG_TEST(nsIFrame::GetLogModuleInfo(),_bit)) { \
+ TraceMsg _args; \
+ } \
+ PR_END_MACRO
+
+#define NS_FRAME_TRACE_REFLOW_IN(_method) Trace(_method, PR_TRUE)
+
+#define NS_FRAME_TRACE_REFLOW_OUT(_method, _status) \
+ Trace(_method, PR_FALSE, _status)
+
+#else
+#define NS_FRAME_TRACE(_bits,_args)
+#define NS_FRAME_TRACE_IN(_method)
+#define NS_FRAME_TRACE_OUT(_method)
+#define NS_FRAME_TRACE_MSG(_bits,_args)
+#define NS_FRAME_TRACE_REFLOW_IN(_method)
+#define NS_FRAME_TRACE_REFLOW_OUT(_method, _status)
+#endif
+
+//----------------------------------------------------------------------
+
+// Implementation of a simple frame with no children and that isn't splittable
+class nsFrame : public nsIFrame
+{
+public:
+ /**
+ * Create a new "empty" frame that maps a given piece of content into a
+ * 0,0 area.
+ */
+ static nsresult NewFrame(nsIFrame** aInstancePtrResult,
+ nsIContent* aContent,
+ nsIFrame* aParent);
+
+ // Overloaded new operator. Initializes the memory to 0
+ void* operator new(size_t size);
+
+ // nsISupports
+ NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
+
+ // nsIFrame
+ NS_IMETHOD Init(nsIPresContext& aPresContext, nsIFrame* aChildList);
+ NS_IMETHOD DeleteFrame(nsIPresContext& aPresContext);
+ NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler) const;
+ NS_IMETHOD GetContent(nsIContent*& aContent) const;
+ NS_IMETHOD GetContentIndex(PRInt32& aIndexInParent) const;
+ NS_IMETHOD GetStyleContext(nsIPresContext* aContext,
+ nsIStyleContext*& aStyleContext);
+ NS_IMETHOD SetStyleContext(nsIPresContext* aPresContext,
+ nsIStyleContext* aContext);
+ NS_IMETHOD GetStyleData(nsStyleStructID aSID,
+ const nsStyleStruct*& aStyleStruct) const;
+ NS_IMETHOD GetContentParent(nsIFrame*& aParent) const;
+ NS_IMETHOD SetContentParent(const nsIFrame* aParent);
+ NS_IMETHOD GetGeometricParent(nsIFrame*& aParent) const;
+ NS_IMETHOD SetGeometricParent(const nsIFrame* aParent);
+ NS_IMETHOD GetRect(nsRect& aRect) const;
+ NS_IMETHOD GetOrigin(nsPoint& aPoint) const;
+ NS_IMETHOD GetSize(nsSize& aSize) const;
+ NS_IMETHOD SetRect(const nsRect& aRect);
+ NS_IMETHOD MoveTo(nscoord aX, nscoord aY);
+ NS_IMETHOD SizeTo(nscoord aWidth, nscoord aHeight);
+ NS_IMETHOD FirstChild(nsIFrame*& aFirstChild) const;
+ NS_IMETHOD Paint(nsIPresContext& aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect);
+ NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus);
+ NS_IMETHOD GetCursorAndContentAt(nsIPresContext& aPresContext,
+ const nsPoint& aPoint,
+ nsIFrame** aFrame,
+ nsIContent** aContent,
+ PRInt32& aCursor);
+ NS_IMETHOD GetFrameState(nsFrameState& aResult);
+ NS_IMETHOD SetFrameState(nsFrameState aNewState);
+ NS_IMETHOD WillReflow(nsIPresContext& aPresContext);
+ NS_IMETHOD DidReflow(nsIPresContext& aPresContext,
+ nsDidReflowStatus aStatus);
+ NS_IMETHOD Reflow(nsIPresContext& aPresContext,
+ nsReflowMetrics& aDesiredSize,
+ const nsReflowState& aReflowState,
+ nsReflowStatus& aStatus);
+
+ NS_IMETHOD ContentChanged(nsIPresContext* aPresContext,
+ nsIContent* aChild,
+ nsISupports* aSubContent);
+ NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
+ nsIContent* aChild,
+ nsIAtom* aAttribute,
+ PRInt32 aHint);
+ NS_IMETHOD GetReflowMetrics(nsIPresContext& aPresContext,
+ nsReflowMetrics& aMetrics);
+ NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const;
+ NS_IMETHOD CreateContinuingFrame(nsIPresContext& aPresContext,
+ nsIFrame* aParent,
+ nsIStyleContext* aStyleContext,
+ nsIFrame*& aContinuingFrame);
+ NS_IMETHOD GetPrevInFlow(nsIFrame*& aPrevInFlow) const;
+ NS_IMETHOD SetPrevInFlow(nsIFrame*);
+ NS_IMETHOD GetNextInFlow(nsIFrame*& aNextInFlow) const;
+ NS_IMETHOD SetNextInFlow(nsIFrame*);
+ NS_IMETHOD AppendToFlow(nsIFrame* aAfterFrame);
+ NS_IMETHOD PrependToFlow(nsIFrame* aAfterFrame);
+ NS_IMETHOD RemoveFromFlow();
+ NS_IMETHOD BreakFromPrevFlow();
+ NS_IMETHOD BreakFromNextFlow();
+ NS_IMETHOD GetView(nsIView*& aView) const;
+ NS_IMETHOD SetView(nsIView* aView);
+ NS_IMETHOD GetParentWithView(nsIFrame*& aParent) const;
+ NS_IMETHOD GetOffsetFromView(nsPoint& aOffset, nsIView*& aView) const;
+ NS_IMETHOD GetWindow(nsIWidget*&) const;
+ NS_IMETHOD IsPercentageBase(PRBool& aBase) const;
+ NS_IMETHOD GetAutoMarginSize(PRUint8 aSide, nscoord& aSize) const;
+ NS_IMETHOD GetNextSibling(nsIFrame*& aNextSibling) const;
+ NS_IMETHOD SetNextSibling(nsIFrame* aNextSibling);
+ NS_IMETHOD IsTransparent(PRBool& aTransparent) const;
+ NS_IMETHOD Scrolled(nsIView *aView);
+ NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0, nsIListFilter *aFilter = nsnull) const;
+ NS_IMETHOD ListTag(FILE* out = stdout) const;
+ NS_IMETHOD VerifyTree() const;
+
+ // Selection Methods
+ NS_IMETHOD HandlePress(nsIPresContext& aPresContext,
+ nsGUIEvent * aEvent,
+ nsEventStatus& aEventStatus);
+
+ NS_IMETHOD HandleDrag(nsIPresContext& aPresContext,
+ nsGUIEvent * aEvent,
+ nsEventStatus& aEventStatus);
+
+ NS_IMETHOD HandleRelease(nsIPresContext& aPresContext,
+ nsGUIEvent * aEvent,
+ nsEventStatus& aEventStatus);
+
+ virtual PRInt32 GetPosition(nsIPresContext& aPresContext,
+ nsGUIEvent* aEvent,
+ nsIFrame * aNewFrame,
+ PRUint32& aAcutalContentOffset);
+
+ //--------------------------------------------------
+ // Additional methods
+
+ // Invalidate part of the frame by asking the view manager to repaint.
+ // aDamageRect is in the frame's local coordinate space
+ void Invalidate(const nsRect& aDamageRect,
+ PRBool aImmediate = PR_FALSE) const;
+
+#ifdef NS_DEBUG
+ /**
+ * Tracing method that writes a method enter/exit routine to the
+ * nspr log using the nsIFrame log module. The tracing is only
+ * done when the NS_FRAME_TRACE_CALLS bit is set in the log module's
+ * level field.
+ */
+ void Trace(const char* aMethod, PRBool aEnter);
+ void Trace(const char* aMethod, PRBool aEnter, nsReflowStatus aStatus);
+ void TraceMsg(const char* fmt, ...);
+#endif
+
+protected:
+ virtual void NewContentIsBefore(nsIPresContext& aPresContext,
+ nsGUIEvent * aEvent,
+ nsIContent * aNewContent,
+ nsIContent * aCurrentContent,
+ nsIFrame * aNewFrame);
+
+ virtual void NewContentIsAfter(nsIPresContext& aPresContext,
+ nsGUIEvent * aEvent,
+ nsIContent * aNewContent,
+ nsIContent * aCurrentContent,
+ nsIFrame * aNewFrame);
+
+ virtual void AdjustPointsInNewContent(nsIPresContext& aPresContext,
+ nsGUIEvent * aEvent,
+ nsIFrame * aNewFrame);
+
+ virtual void AdjustPointsInSameContent(nsIPresContext& aPresContext,
+ nsGUIEvent * aEvent);
+
+ PRBool DisplaySelection(nsIPresContext& aPresContext, PRBool isOkToTurnOn = PR_FALSE);
+
+ // Style post processing hook
+ NS_IMETHOD DidSetStyleContext(nsIPresContext* aPresContext);
+
+
+
+ // Constructor. Takes as arguments the content object, the index in parent,
+ // and the Frame for the content parent
+ nsFrame(nsIContent* aContent, nsIFrame* aParent);
+
+ virtual ~nsFrame();
+
+ void SizeOfWithoutThis(nsISizeOfHandler* aHandler) const;
+
+ nsRect mRect;
+ nsIContent* mContent;
+ nsIStyleContext* mStyleContext;
+ nsIFrame* mContentParent;
+ nsIFrame* mGeometricParent;
+ nsIFrame* mNextSibling; // singly linked list of frames
+ nsFrameState mState;
+
+ ///////////////////////////////////
+ // Important Selection Variables
+ ///////////////////////////////////
+ static nsIFrame * mCurrentFrame;
+ static PRBool mDoingSelection;
+ static PRBool mDidDrag;
+ static PRInt32 mStartPos;
+
+ // Selection data is valid only from the Mouse Press to the Mouse Release
+ static nsSelectionRange * mSelectionRange;
+ static nsISelection * mSelection;
+
+ static nsSelectionPoint * mStartSelectionPoint;
+ static nsSelectionPoint * mEndSelectionPoint;
+ ///////////////////////////////////
+
+
+private:
+ nsIView* mView; // must use accessor member functions
+
+ NS_IMETHOD_(nsrefcnt) AddRef(void);
+ NS_IMETHOD_(nsrefcnt) Release(void);
+};
+
+#endif /* nsFrame_h___ */
diff --git a/layout/html/base/src/nsPresShell.cpp b/layout/html/base/src/nsPresShell.cpp
new file mode 100644
index 000000000000..12e931335f91
--- /dev/null
+++ b/layout/html/base/src/nsPresShell.cpp
@@ -0,0 +1,1140 @@
+/* -*- 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 "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.
+ */
+#include "nsIPresShell.h"
+#include "nsIPresContext.h"
+#include "nsIContent.h"
+#include "nsIDocument.h"
+#include "nsIDocumentObserver.h"
+#include "nsIStyleSet.h"
+#include "nsIStyleContext.h"
+#include "nsFrame.h"
+#include "nsIReflowCommand.h"
+#include "nsIViewManager.h"
+#include "nsCRT.h"
+#include "plhash.h"
+#include "prlog.h"
+#include "nsVoidArray.h"
+#include "nsIPref.h"
+#include "nsIViewObserver.h"
+#include "nsContainerFrame.h"
+
+static PRBool gsNoisyRefs = PR_FALSE;
+#undef NOISY
+
+#if 0
+static PLHashNumber
+HashKey(nsIFrame* key)
+{
+ return (PLHashNumber) key;
+}
+
+static PRIntn
+CompareKeys(nsIFrame* key1, nsIFrame* key2)
+{
+ return key1 == key2;
+}
+
+class FrameHashTable {
+public:
+ FrameHashTable();
+ ~FrameHashTable();
+
+ void* Get(nsIFrame* aKey);
+ void* Put(nsIFrame* aKey, void* aValue);
+ void* Remove(nsIFrame* aKey);
+
+protected:
+ PLHashTable* mTable;
+};
+
+FrameHashTable::FrameHashTable()
+{
+ mTable = PL_NewHashTable(8, (PLHashFunction) HashKey,
+ (PLHashComparator) CompareKeys,
+ (PLHashComparator) nsnull,
+ nsnull, nsnull);
+}
+
+FrameHashTable::~FrameHashTable()
+{
+ // XXX if debugging then we should assert that the table is empty
+ PL_HashTableDestroy(mTable);
+}
+
+/**
+ * Get the data associated with a frame.
+ */
+void*
+FrameHashTable::Get(nsIFrame* aKey)
+{
+ PRInt32 hashCode = (PRInt32) aKey;
+ PLHashEntry** hep = PL_HashTableRawLookup(mTable, hashCode, aKey);
+ PLHashEntry* he = *hep;
+ if (nsnull != he) {
+ return he->value;
+ }
+ return nsnull;
+}
+
+/**
+ * Create an association between a frame and some data. This call
+ * returns an old association if there was one (or nsnull if there
+ * wasn't).
+ */
+void*
+FrameHashTable::Put(nsIFrame* aKey, void* aData)
+{
+ PRInt32 hashCode = (PRInt32) aKey;
+ PLHashEntry** hep = PL_HashTableRawLookup(mTable, hashCode, aKey);
+ PLHashEntry* he = *hep;
+ if (nsnull != he) {
+ void* oldValue = he->value;
+ he->value = aData;
+ return oldValue;
+ }
+ PL_HashTableRawAdd(mTable, hep, hashCode, aKey, aData);
+ return nsnull;
+}
+
+/**
+ * Remove an association between a frame and it's data. This returns
+ * the old associated data.
+ */
+void*
+FrameHashTable::Remove(nsIFrame* aKey)
+{
+ PRInt32 hashCode = (PRInt32) aKey;
+ PLHashEntry** hep = PL_HashTableRawLookup(mTable, hashCode, aKey);
+ PLHashEntry* he = *hep;
+ void* oldValue = nsnull;
+ if (nsnull != he) {
+ oldValue = he->value;
+ PL_HashTableRawRemove(mTable, hep, he);
+ }
+ return oldValue;
+}
+#endif
+
+//----------------------------------------------------------------------
+
+static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
+static NS_DEFINE_IID(kIPresShellIID, NS_IPRESSHELL_IID);
+static NS_DEFINE_IID(kIDocumentObserverIID, NS_IDOCUMENT_OBSERVER_IID);
+static NS_DEFINE_IID(kIViewObserverIID, NS_IVIEWOBSERVER_IID);
+
+class PresShell : public nsIPresShell, public nsIViewObserver,
+ private nsIDocumentObserver
+
+{
+public:
+ PresShell();
+
+ void* operator new(size_t sz) {
+ void* rv = new char[sz];
+ nsCRT::zero(rv, sz);
+ return rv;
+ }
+
+ // nsISupports
+ NS_DECL_ISUPPORTS
+
+ // nsIDocumentObserver
+ NS_IMETHOD BeginUpdate(nsIDocument *aDocument);
+ NS_IMETHOD EndUpdate(nsIDocument *aDocument);
+ NS_IMETHOD BeginLoad(nsIDocument *aDocument);
+ NS_IMETHOD EndLoad(nsIDocument *aDocument);
+ NS_IMETHOD BeginReflow(nsIDocument *aDocument, nsIPresShell* aShell);
+ NS_IMETHOD EndReflow(nsIDocument *aDocument, nsIPresShell* aShell);
+ NS_IMETHOD ContentChanged(nsIDocument *aDocument,
+ nsIContent* aContent,
+ nsISupports* aSubContent);
+ NS_IMETHOD AttributeChanged(nsIDocument *aDocument,
+ nsIContent* aContent,
+ nsIAtom* aAttribute,
+ PRInt32 aHint);
+ NS_IMETHOD ContentAppended(nsIDocument *aDocument,
+ nsIContent* aContainer,
+ PRInt32 aNewIndexInContainer);
+ NS_IMETHOD ContentInserted(nsIDocument *aDocument,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ PRInt32 aIndexInContainer);
+ NS_IMETHOD ContentReplaced(nsIDocument *aDocument,
+ nsIContent* aContainer,
+ nsIContent* aOldChild,
+ nsIContent* aNewChild,
+ PRInt32 aIndexInContainer);
+ NS_IMETHOD ContentRemoved(nsIDocument *aDocument,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ PRInt32 aIndexInContainer);
+ NS_IMETHOD StyleSheetAdded(nsIDocument *aDocument,
+ nsIStyleSheet* aStyleSheet);
+ NS_IMETHOD DocumentWillBeDestroyed(nsIDocument *aDocument);
+
+ // nsIPresShell
+ NS_IMETHOD Init(nsIDocument* aDocument,
+ nsIPresContext* aPresContext,
+ nsIViewManager* aViewManager,
+ nsIStyleSet* aStyleSet);
+ virtual nsIDocument* GetDocument();
+ virtual nsIPresContext* GetPresContext();
+ virtual nsIViewManager* GetViewManager();
+ virtual nsIStyleSet* GetStyleSet();
+ NS_IMETHOD EnterReflowLock();
+ NS_IMETHOD ExitReflowLock();
+ virtual void BeginObservingDocument();
+ virtual void EndObservingDocument();
+ NS_IMETHOD InitialReflow(nscoord aWidth, nscoord aHeight);
+ NS_IMETHOD ResizeReflow(nscoord aWidth, nscoord aHeight);
+ virtual nsIFrame* GetRootFrame();
+ virtual nsIFrame* FindFrameWithContent(nsIContent* aContent);
+ virtual void AppendReflowCommand(nsIReflowCommand* aReflowCommand);
+ virtual void ProcessReflowCommands();
+
+ //nsIViewObserver
+
+ //nsIViewObserver interface
+
+ NS_IMETHOD Paint(nsIView *aView,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect);
+ NS_IMETHOD HandleEvent(nsIView* aView,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus);
+ NS_IMETHOD Scrolled(nsIView *aView);
+ NS_IMETHOD ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight);
+
+protected:
+ ~PresShell();
+
+#ifdef NS_DEBUG
+ void VerifyIncrementalReflow();
+#endif
+
+ nsIDocument* mDocument;
+ nsIPresContext* mPresContext;
+ nsIStyleSet* mStyleSet;
+ nsIFrame* mRootFrame;
+ nsIViewManager* mViewManager;
+ PRUint32 mUpdateCount;
+ nsVoidArray mReflowCommands;
+ PRUint32 mReflowLockCount;
+};
+
+#ifdef NS_DEBUG
+/**
+ * Note: the log module is created during library initialization which
+ * means that you cannot perform logging before then.
+ */
+static PRLogModuleInfo* gLogModule = PR_NewLogModule("verifyreflow");
+#endif
+
+static PRBool gVerifyReflow = PRBool(0x55);
+
+NS_LAYOUT PRBool
+nsIPresShell::GetVerifyReflowEnable()
+{
+#ifdef NS_DEBUG
+ if (gVerifyReflow == PRBool(0x55)) {
+ gVerifyReflow = 0 != gLogModule->level;
+ printf("Note: verifyreflow is %sabled\n",
+ gVerifyReflow ? "en" : "dis");
+ }
+#endif
+ return gVerifyReflow;
+}
+
+NS_LAYOUT void
+nsIPresShell::SetVerifyReflowEnable(PRBool aEnabled)
+{
+ gVerifyReflow = aEnabled;
+}
+
+//----------------------------------------------------------------------
+
+NS_LAYOUT nsresult
+NS_NewPresShell(nsIPresShell** aInstancePtrResult)
+{
+ NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
+ if (nsnull == aInstancePtrResult) {
+ return NS_ERROR_NULL_POINTER;
+ }
+ PresShell* it = new PresShell();
+ if (nsnull == it) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ return it->QueryInterface(kIPresShellIID, (void **) aInstancePtrResult);
+}
+
+PresShell::PresShell()
+{
+}
+
+#ifdef NS_DEBUG
+// for debugging only
+nsrefcnt PresShell::AddRef(void)
+{
+ if (gsNoisyRefs) printf("PresShell: AddRef: %x, cnt = %d \n",this, mRefCnt+1);
+ return ++mRefCnt;
+}
+
+// for debugging only
+nsrefcnt PresShell::Release(void)
+{
+ if (gsNoisyRefs==PR_TRUE) printf("PresShell Release: %x, cnt = %d \n",this, mRefCnt-1);
+ if (--mRefCnt == 0) {
+ if (gsNoisyRefs==PR_TRUE) printf("PresShell Delete: %x, \n",this);
+ delete this;
+ return 0;
+ }
+ return mRefCnt;
+}
+#else
+NS_IMPL_ADDREF(PresShell)
+NS_IMPL_RELEASE(PresShell)
+#endif
+
+nsresult
+PresShell::QueryInterface(const nsIID& aIID, void** aInstancePtr)
+{
+ if (aIID.Equals(kIPresShellIID)) {
+ nsIPresShell* tmp = this;
+ *aInstancePtr = (void*) tmp;
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+ if (aIID.Equals(kIDocumentObserverIID)) {
+ nsIDocumentObserver* tmp = this;
+ *aInstancePtr = (void*) tmp;
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+ if (aIID.Equals(kIViewObserverIID)) {
+ nsIViewObserver* tmp = this;
+ *aInstancePtr = (void*) tmp;
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+ if (aIID.Equals(kISupportsIID)) {
+ nsIPresShell* tmp = this;
+ nsISupports* tmp2 = tmp;
+ *aInstancePtr = (void*) tmp2;
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+ return NS_NOINTERFACE;
+}
+
+PresShell::~PresShell()
+{
+ mRefCnt = 99;/* XXX hack! get around re-entrancy bugs */
+ if (nsnull != mRootFrame) {
+ mRootFrame->DeleteFrame(*mPresContext);
+ }
+ NS_IF_RELEASE(mViewManager);
+ //Release mPresContext after mViewManager
+ NS_IF_RELEASE(mPresContext);
+ NS_IF_RELEASE(mStyleSet);
+ if (nsnull != mDocument) {
+ mDocument->DeleteShell(this);
+ NS_RELEASE(mDocument);
+ }
+ mRefCnt = 0;
+}
+
+/**
+ * Initialize the presentation shell. Create view manager and style
+ * manager.
+ */
+nsresult
+PresShell::Init(nsIDocument* aDocument,
+ nsIPresContext* aPresContext,
+ nsIViewManager* aViewManager,
+ nsIStyleSet* aStyleSet)
+{
+ NS_PRECONDITION(nsnull != aDocument, "null ptr");
+ NS_PRECONDITION(nsnull != aPresContext, "null ptr");
+ NS_PRECONDITION(nsnull != aViewManager, "null ptr");
+ if ((nsnull == aDocument) || (nsnull == aPresContext) ||
+ (nsnull == aViewManager)) {
+ return NS_ERROR_NULL_POINTER;
+ }
+ if (nsnull != mDocument) {
+ return NS_ERROR_ALREADY_INITIALIZED;
+ }
+
+ mDocument = aDocument;
+ NS_ADDREF(aDocument);
+ mViewManager = aViewManager;
+ NS_ADDREF(mViewManager);
+
+ //doesn't add a ref since we own it... MMP
+ mViewManager->SetViewObserver((nsIViewObserver *)this);
+
+ // Bind the context to the presentation shell.
+ mPresContext = aPresContext;
+ NS_ADDREF(aPresContext);
+ aPresContext->SetShell(this);
+
+ mStyleSet = aStyleSet;
+ NS_ADDREF(aStyleSet);
+
+ return NS_OK;
+}
+
+NS_METHOD
+PresShell::EnterReflowLock()
+{
+ ++mReflowLockCount;
+ return NS_OK;
+}
+
+NS_METHOD
+PresShell::ExitReflowLock()
+{
+ PRUint32 newReflowLockCount = mReflowLockCount - 1;
+ if (newReflowLockCount == 0) {
+ ProcessReflowCommands();
+ }
+ mReflowLockCount = newReflowLockCount;
+ return NS_OK;
+}
+
+nsIDocument*
+PresShell::GetDocument()
+{
+ NS_IF_ADDREF(mDocument);
+ return mDocument;
+}
+
+nsIPresContext*
+PresShell::GetPresContext()
+{
+ NS_IF_ADDREF(mPresContext);
+ return mPresContext;
+}
+
+nsIViewManager*
+PresShell::GetViewManager()
+{
+ NS_IF_ADDREF(mViewManager);
+ return mViewManager;
+}
+
+nsIStyleSet*
+PresShell::GetStyleSet()
+{
+ NS_IF_ADDREF(mStyleSet);
+ return mStyleSet;
+}
+
+// Make shell be a document observer
+void
+PresShell::BeginObservingDocument()
+{
+ if (nsnull != mDocument) {
+ mDocument->AddObserver(this);
+ }
+}
+
+// Make shell stop being a document observer
+void
+PresShell::EndObservingDocument()
+{
+ if (nsnull != mDocument) {
+ mDocument->RemoveObserver(this);
+ }
+}
+
+NS_IMETHODIMP
+PresShell::InitialReflow(nscoord aWidth, nscoord aHeight)
+{
+ NS_PRECONDITION(nsnull == mRootFrame, "unexpected root frame");
+
+ EnterReflowLock();
+
+ if (nsnull != mPresContext) {
+ nsRect r(0, 0, aWidth, aHeight);
+ mPresContext->SetVisibleArea(r);
+ }
+
+ if (nsnull == mRootFrame) {
+ if (nsnull != mDocument) {
+ nsIContent* root = mDocument->GetRootContent();
+ if (nsnull != root) {
+ // Have style sheet processor construct a frame for the
+ // root content object
+ mStyleSet->ConstructFrame(mPresContext, root, nsnull, mRootFrame);
+ NS_RELEASE(root);
+ }
+ }
+ }
+
+ if (nsnull != mRootFrame) {
+ // Kick off a top-down reflow
+ NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
+ ("enter nsPresShell::InitialReflow: %d,%d", aWidth, aHeight));
+#ifdef NS_DEBUG
+ if (nsIFrame::GetVerifyTreeEnable()) {
+ mRootFrame->VerifyTree();
+ }
+#endif
+ nsRect bounds;
+ mPresContext->GetVisibleArea(bounds);
+ nsSize maxSize(bounds.width, bounds.height);
+ nsReflowMetrics desiredSize(nsnull);
+ nsReflowStatus status;
+ nsReflowState reflowState(mRootFrame, eReflowReason_Initial, maxSize);
+
+ mRootFrame->Reflow(*mPresContext, desiredSize, reflowState, status);
+ mRootFrame->SizeTo(desiredSize.width, desiredSize.height);
+#ifdef NS_DEBUG
+ if (nsIFrame::GetVerifyTreeEnable()) {
+ mRootFrame->VerifyTree();
+ }
+#endif
+ NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, ("exit nsPresShell::InitialReflow"));
+ }
+
+ ExitReflowLock();
+
+ return NS_OK; //XXX this needs to be real. MMP
+}
+
+NS_IMETHODIMP
+PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
+{
+ EnterReflowLock();
+
+ if (nsnull != mPresContext) {
+ nsRect r(0, 0, aWidth, aHeight);
+ mPresContext->SetVisibleArea(r);
+ }
+
+ // If we don't have a root frame yet, that means we haven't had our initial
+ // reflow...
+ if (nsnull != mRootFrame) {
+ // Kick off a top-down reflow
+ NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
+ ("enter nsPresShell::ResizeReflow: %d,%d", aWidth, aHeight));
+#ifdef NS_DEBUG
+ if (nsIFrame::GetVerifyTreeEnable()) {
+ mRootFrame->VerifyTree();
+ }
+#endif
+ nsRect bounds;
+ mPresContext->GetVisibleArea(bounds);
+ nsSize maxSize(bounds.width, bounds.height);
+ nsReflowMetrics desiredSize(nsnull);
+ nsReflowStatus status;
+ nsReflowState reflowState(mRootFrame, eReflowReason_Resize, maxSize);
+
+ mRootFrame->Reflow(*mPresContext, desiredSize, reflowState, status);
+ mRootFrame->SizeTo(desiredSize.width, desiredSize.height);
+#ifdef NS_DEBUG
+ if (nsIFrame::GetVerifyTreeEnable()) {
+ mRootFrame->VerifyTree();
+ }
+#endif
+ NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, ("exit nsPresShell::ResizeReflow"));
+
+ // XXX if debugging then we should assert that the cache is empty
+ } else {
+#ifdef NOISY
+ printf("PresShell::ResizeReflow: null root frame\n");
+#endif
+ }
+
+ ExitReflowLock();
+
+ return NS_OK; //XXX this needs to be real. MMP
+}
+
+nsIFrame*
+PresShell::GetRootFrame()
+{
+ return mRootFrame;
+}
+
+NS_IMETHODIMP
+PresShell::BeginUpdate(nsIDocument *aDocument)
+{
+ mUpdateCount++;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PresShell::EndUpdate(nsIDocument *aDocument)
+{
+ NS_PRECONDITION(0 != mUpdateCount, "too many EndUpdate's");
+ if (--mUpdateCount == 0) {
+ // XXX do something here
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PresShell::BeginLoad(nsIDocument *aDocument)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PresShell::EndLoad(nsIDocument *aDocument)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PresShell::BeginReflow(nsIDocument *aDocument, nsIPresShell* aShell)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PresShell::EndReflow(nsIDocument *aDocument, nsIPresShell* aShell)
+{
+ return NS_OK;
+}
+
+void
+PresShell::AppendReflowCommand(nsIReflowCommand* aReflowCommand)
+{
+ mReflowCommands.AppendElement(aReflowCommand);
+ NS_ADDREF(aReflowCommand);
+}
+
+void
+PresShell::ProcessReflowCommands()
+{
+ if (0 != mReflowCommands.Count()) {
+ nsReflowMetrics desiredSize(nsnull);
+
+ while (0 != mReflowCommands.Count()) {
+ nsIReflowCommand* rc = (nsIReflowCommand*) mReflowCommands.ElementAt(0);
+ mReflowCommands.RemoveElementAt(0);
+
+ // Dispatch the reflow command
+ nsSize maxSize;
+ mRootFrame->GetSize(maxSize);
+#ifdef NS_DEBUG
+ nsIReflowCommand::ReflowType type;
+ rc->GetType(type);
+ NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
+ ("PresShell::ProcessReflowCommands: begin reflow command type=%d",
+ type));
+#endif
+ rc->Dispatch(*mPresContext, desiredSize, maxSize);
+ NS_RELEASE(rc);
+ NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
+ ("PresShell::ProcessReflowCommands: end reflow command"));
+ }
+
+ // Place and size the root frame
+ mRootFrame->SizeTo(desiredSize.width, desiredSize.height);
+#ifdef NS_DEBUG
+ if (nsIFrame::GetVerifyTreeEnable()) {
+ mRootFrame->VerifyTree();
+ }
+ if (GetVerifyReflowEnable()) {
+ VerifyIncrementalReflow();
+ }
+#endif
+ }
+}
+
+#ifdef NS_DEBUG
+static char*
+ContentTag(nsIContent* aContent, PRIntn aSlot)
+{
+ static char buf0[100], buf1[100], buf2[100];
+ static char* bufs[] = { buf0, buf1, buf2 };
+ char* buf = bufs[aSlot];
+ nsIAtom* atom;
+ aContent->GetTag(atom);
+ if (nsnull != atom) {
+ nsAutoString tmp;
+ atom->ToString(tmp);
+ tmp.ToCString(buf, 100);
+ }
+ else {
+ buf[0] = 0;
+ }
+ return buf;
+}
+#endif
+
+NS_IMETHODIMP
+PresShell::ContentChanged(nsIDocument *aDocument,
+ nsIContent* aContent,
+ nsISupports* aSubContent)
+{
+ NS_PRECONDITION(nsnull != mRootFrame, "null root frame");
+
+ EnterReflowLock();
+ nsresult rv = mStyleSet->ContentChanged(mPresContext, aContent, aSubContent);
+ ExitReflowLock();
+ return rv;
+}
+
+NS_IMETHODIMP
+PresShell::AttributeChanged(nsIDocument *aDocument,
+ nsIContent* aContent,
+ nsIAtom* aAttribute,
+ PRInt32 aHint)
+{
+ NS_PRECONDITION(nsnull != mRootFrame, "null root frame");
+
+ EnterReflowLock();
+ nsresult rv = mStyleSet->AttributeChanged(mPresContext, aContent, aAttribute, aHint);
+ ExitReflowLock();
+ return rv;
+}
+
+NS_IMETHODIMP
+PresShell::ContentAppended(nsIDocument *aDocument,
+ nsIContent* aContainer,
+ PRInt32 aNewIndexInContainer)
+{
+ EnterReflowLock();
+ nsresult rv = mStyleSet->ContentAppended(mPresContext, aContainer, aNewIndexInContainer);
+ ExitReflowLock();
+ return rv;
+}
+
+NS_IMETHODIMP
+PresShell::ContentInserted(nsIDocument* aDocument,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ PRInt32 aIndexInContainer)
+{
+ EnterReflowLock();
+ nsresult rv = mStyleSet->ContentInserted(mPresContext, aContainer, aChild, aIndexInContainer);
+ ExitReflowLock();
+ return rv;
+}
+
+NS_IMETHODIMP
+PresShell::ContentReplaced(nsIDocument* aDocument,
+ nsIContent* aContainer,
+ nsIContent* aOldChild,
+ nsIContent* aNewChild,
+ PRInt32 aIndexInContainer)
+{
+ EnterReflowLock();
+ nsresult rv = mStyleSet->ContentReplaced(mPresContext, aContainer, aOldChild,
+ aNewChild, aIndexInContainer);
+ ExitReflowLock();
+ return rv;
+}
+
+NS_IMETHODIMP
+PresShell::ContentRemoved(nsIDocument *aDocument,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ PRInt32 aIndexInContainer)
+{
+ EnterReflowLock();
+ nsresult rv = mStyleSet->ContentRemoved(mPresContext, aContainer,
+ aChild, aIndexInContainer);
+ ExitReflowLock();
+ return rv;
+}
+
+NS_IMETHODIMP
+PresShell::StyleSheetAdded(nsIDocument *aDocument,
+ nsIStyleSheet* aStyleSheet)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PresShell::DocumentWillBeDestroyed(nsIDocument *aDocument)
+{
+ return NS_OK;
+}
+
+static nsIFrame*
+FindFrameWithContent(nsIFrame* aFrame, nsIContent* aContent)
+{
+ nsIContent* frameContent;
+
+ aFrame->GetContent(frameContent);
+ if (frameContent == aContent) {
+ NS_RELEASE(frameContent);
+ return aFrame;
+ }
+ NS_RELEASE(frameContent);
+
+ aFrame->FirstChild(aFrame);
+ while (aFrame) {
+ nsIFrame* result = FindFrameWithContent(aFrame, aContent);
+
+ if (result) {
+ return result;
+ }
+
+ aFrame->GetNextSibling(aFrame);
+ }
+
+ return nsnull;
+}
+
+nsIFrame*
+PresShell::FindFrameWithContent(nsIContent* aContent)
+{
+ // For the time being do a brute force depth-first search of
+ // the frame tree
+ return ::FindFrameWithContent(mRootFrame, aContent);
+}
+
+//nsIViewObserver
+
+NS_IMETHODIMP PresShell :: Paint(nsIView *aView,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect)
+{
+ void* clientData;
+ nsIFrame* frame;
+ nsresult rv;
+
+ NS_ASSERTION(!(nsnull == aView), "null view");
+
+ aView->GetClientData(clientData);
+ frame = (nsIFrame *)clientData;
+
+ if (nsnull != frame)
+ rv = frame->Paint(*mPresContext, aRenderingContext, aDirtyRect);
+ else
+ rv = NS_OK;
+
+ return rv;
+}
+
+NS_IMETHODIMP PresShell :: HandleEvent(nsIView *aView,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus)
+{
+ void* clientData;
+ nsIFrame* frame;
+ nsresult rv;
+
+ NS_ASSERTION(!(nsnull == aView), "null view");
+
+ aView->GetClientData(clientData);
+ frame = (nsIFrame *)clientData;
+
+ if (nsnull != frame)
+ rv = frame->HandleEvent(*mPresContext, aEvent, aEventStatus);
+ else
+ rv = NS_OK;
+
+ return rv;
+}
+
+NS_IMETHODIMP PresShell :: Scrolled(nsIView *aView)
+{
+ void* clientData;
+ nsIFrame* frame;
+ nsresult rv;
+
+ NS_ASSERTION(!(nsnull == aView), "null view");
+
+ aView->GetClientData(clientData);
+ frame = (nsIFrame *)clientData;
+
+ if (nsnull != frame)
+ rv = frame->Scrolled(aView);
+ else
+ rv = NS_OK;
+
+ return rv;
+}
+
+NS_IMETHODIMP PresShell :: ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight)
+{
+ return ResizeReflow(aWidth, aHeight);
+}
+
+#ifdef NS_DEBUG
+#include "nsViewsCID.h"
+#include "nsWidgetsCID.h"
+#include "nsIScrollableView.h"
+#include "nsIDeviceContext.h"
+#include "nsIURL.h"
+#include "nsICSSParser.h"
+#include "nsIStyleSheet.h"
+
+static NS_DEFINE_IID(kViewManagerCID, NS_VIEW_MANAGER_CID);
+static NS_DEFINE_IID(kIViewManagerIID, NS_IVIEWMANAGER_IID);
+static NS_DEFINE_IID(kScrollingViewCID, NS_SCROLLING_VIEW_CID);
+static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID);
+static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID);
+static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
+
+static void
+ShowDiffs(nsIFrame* k1, nsIFrame* k2, const nsRect& r1, const nsRect& r2)
+{
+ printf("verifyreflow: ");
+ k1->ListTag(stdout);
+ printf(" ");
+ stdout << r1;
+ printf(" != ");
+ k2->ListTag(stdout);
+ printf(" ");
+ stdout << r2;
+ printf("\n");
+}
+
+static void
+CompareTrees(nsIFrame* aA, nsIFrame* aB)
+{
+ nsIFrame* k1, *k2;
+ aA->FirstChild(k1);
+ aB->FirstChild(k2);
+ NS_ASSERTION(nsContainerFrame::LengthOf(k1) == nsContainerFrame::LengthOf(k2),
+ "child counts don't match");
+
+ nsRect r1, r2;
+ nsIView* v1, *v2;
+ nsIWidget* w1, *w2;
+ for (;;) {
+ if (nsnull == k1) {
+ NS_ASSERTION(nsnull == k2, "child lists are different");
+ break;
+ }
+ NS_ASSERTION(nsnull != k2, "child lists are different");
+
+ // Verify that the frames are the same size
+ k1->GetRect(r1);
+ k2->GetRect(r2);
+ if (r1 != r2) {
+ ShowDiffs(k1, k2, r1, r2);
+ }
+ else {
+ // Make sure either both have views or neither have views; if they
+ // do have views, make sure the views are the same size. If the
+ // views have widgets, make sure they both do or neither does. If
+ // they do, make sure the widgets are the same size.
+ k1->GetView(v1);
+ k2->GetView(v2);
+ if (nsnull != v1) {
+ NS_ASSERTION(nsnull != v2, "child views are not matched");
+ v1->GetBounds(r1);
+ v2->GetBounds(r2);
+ NS_ASSERTION(r1 == r2, "child views are different sizes");
+
+ v1->GetWidget(w1);
+ v2->GetWidget(w2);
+ if (nsnull != w1) {
+ NS_ASSERTION(nsnull != w2, "child widgets are not matched");
+ w1->GetBounds(r1);
+ w2->GetBounds(r2);
+ NS_ASSERTION(r1 == r2, "child widgets are different sizes");
+ }
+ else {
+ NS_ASSERTION(nsnull == w2, "child widgets are not matched");
+ }
+ }
+ else {
+ NS_ASSERTION(nsnull == v2, "child views are not matched");
+ }
+
+ // Compare the sub-trees too
+ CompareTrees(k1, k2);
+ }
+
+ // Advance to next sibling
+ k1->GetNextSibling(k1);
+ k2->GetNextSibling(k2);
+ }
+}
+
+// XXX: copy of nsWebWidget's ua.css loading code!!!
+#define UA_CSS_URL "resource:/res/ua.css"
+
+static nsIStyleSheet* gUAStyleSheet;
+
+static nsresult
+InitUAStyleSheet()
+{
+ nsresult rv = NS_OK;
+
+ if (nsnull == gUAStyleSheet) { // snarf one
+ nsIURL* uaURL;
+ rv = NS_NewURL(&uaURL, nsnull, UA_CSS_URL); // XXX this bites, fix it
+ if (NS_OK == rv) {
+ // Get an input stream from the url
+ PRInt32 ec;
+ nsIInputStream* in = uaURL->Open(&ec);
+ if (nsnull != in) {
+ // Translate the input using the argument character set id into unicode
+ nsIUnicharInputStream* uin;
+ rv = NS_NewConverterStream(&uin, nsnull, in);
+ if (NS_OK == rv) {
+ // Create parser and set it up to process the input file
+ nsICSSParser* css;
+ rv = NS_NewCSSParser(&css);
+ if (NS_OK == rv) {
+ // Parse the input and produce a style set
+ // XXX note: we are ignoring rv until the error code stuff in the
+ // input routines is converted to use nsresult's
+ css->Parse(uin, uaURL, gUAStyleSheet);
+ NS_RELEASE(css);
+ }
+ NS_RELEASE(uin);
+ }
+ NS_RELEASE(in);
+ }
+ else {
+// printf("open of %s failed: error=%x\n", UA_CSS_URL, ec);
+ rv = NS_ERROR_ILLEGAL_VALUE; // XXX need a better error code here
+ }
+
+ NS_RELEASE(uaURL);
+ }
+ }
+ return rv;
+}
+
+static nsresult
+CreateStyleSet(nsIDocument* aDocument, nsIStyleSet** aStyleSet)
+{
+ nsresult rv = InitUAStyleSheet();
+ if (NS_OK != rv) {
+ NS_WARNING("unable to load UA style sheet");
+ }
+
+ rv = NS_NewStyleSet(aStyleSet);
+ if (NS_OK == rv) {
+ PRInt32 index = aDocument->GetNumberOfStyleSheets();
+ while (0 < index--) {
+ // NOTE: turn the order around for the set
+ nsIStyleSheet* sheet = aDocument->GetStyleSheetAt(index);
+ (*aStyleSet)->AppendDocStyleSheet(sheet);
+ NS_RELEASE(sheet);
+ }
+ // XXX this is just wrong, the UA style sheet should be owned by the UA
+ // for that matter, the style set should be created by the UA too
+ if (nsnull != gUAStyleSheet) {
+ (*aStyleSet)->AppendBackstopStyleSheet(gUAStyleSheet);
+ }
+ }
+ return rv;
+}
+
+// After an incremental reflow, we verify the correctness by doing a
+// full reflow into a fresh frame tree.
+void
+PresShell::VerifyIncrementalReflow()
+{
+ // All the stuff we are creating that needs releasing
+ nsIPresContext* cx;
+ nsIViewManager* vm;
+ nsIView* view;
+ nsIPresShell* sh;
+ nsIStyleSet* ss;
+
+ // Create a presentation context to view the new frame tree
+ nsresult rv;
+ if (mPresContext->IsPaginated()) {
+ rv = NS_NewPrintPreviewContext(&cx);
+ }
+ else {
+ rv = NS_NewGalleyContext(&cx);
+ }
+ NS_ASSERTION(NS_OK == rv, "failed to create presentation context");
+ nsIDeviceContext* dc = mPresContext->GetDeviceContext();
+ nsIPref* prefs;
+ mPresContext->GetPrefs(prefs);
+ cx->Init(dc, prefs);
+ NS_IF_RELEASE(prefs);
+
+ rv = CreateStyleSet(mDocument, &ss);
+ NS_ASSERTION(NS_OK == rv, "failed to create style set");
+
+ // Get our scrolling preference
+ nsScrollPreference scrolling;
+ nsIView* rootView;
+ mViewManager->GetRootView(rootView);
+ nsIScrollableView* scrollView;
+ rv = rootView->QueryInterface(kScrollViewIID, (void**)&scrollView);
+ if (NS_OK == rv) {
+ scrollView->GetScrollPreference(scrolling);
+ }
+ nsIWidget* rootWidget;
+ rootView->GetWidget(rootWidget);
+ void* nativeParentWidget = rootWidget->GetNativeData(NS_NATIVE_WIDGET);
+
+ // Create a new view manager.
+ rv = nsRepository::CreateInstance(kViewManagerCID, nsnull, kIViewManagerIID,
+ (void**) &vm);
+ if ((NS_OK != rv) || (NS_OK != vm->Init(dc))) {
+ NS_ASSERTION(NS_OK == rv, "failed to create view manager");
+ }
+
+ NS_RELEASE(dc);
+
+ vm->SetViewObserver((nsIViewObserver *)this);
+
+ // Create a child window of the parent that is our "root view/window"
+ // Create a view
+ nsRect tbounds;
+ mPresContext->GetVisibleArea(tbounds);
+// tbounds *= mPresContext->GetPixelsToTwips();
+ rv = nsRepository::CreateInstance(kScrollingViewCID, nsnull, kIViewIID,
+ (void **) &view);
+ if ((NS_OK != rv) || (NS_OK != view->Init(vm, tbounds, nsnull, &kWidgetCID,
+ nsnull, nativeParentWidget))) {
+ NS_ASSERTION(NS_OK == rv, "failed to create scroll view");
+ }
+ rv = view->QueryInterface(kScrollViewIID, (void**)&scrollView);
+ if (NS_OK == rv) {
+ scrollView->SetScrollPreference(scrolling);
+ }
+ else {
+ NS_ASSERTION(0, "invalid scrolling view");
+ }
+
+ // Setup hierarchical relationship in view manager
+ vm->SetRootView(view);
+
+ // Make the new presentation context the same size as our
+ // presentation context.
+ nsRect r;
+ mPresContext->GetVisibleArea(r);
+ cx->SetVisibleArea(r);
+
+ // Create a new presentation shell to view the document
+ rv = mDocument->CreateShell(cx, vm, ss, &sh);
+ NS_ASSERTION(NS_OK == rv, "failed to create presentation shell");
+ sh->ResizeReflow(r.width, r.height);
+
+ // Now that the document has been reflowed, use its frame tree to
+ // compare against our frame tree.
+ CompareTrees(GetRootFrame(), sh->GetRootFrame());
+
+ NS_RELEASE(vm);
+
+ NS_RELEASE(cx);
+ NS_RELEASE(sh);
+
+ NS_RELEASE(ss);
+}
+#endif
diff --git a/layout/html/base/src/nsSplittableFrame.cpp b/layout/html/base/src/nsSplittableFrame.cpp
new file mode 100644
index 000000000000..2a004b5bab57
--- /dev/null
+++ b/layout/html/base/src/nsSplittableFrame.cpp
@@ -0,0 +1,182 @@
+/* -*- 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 "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.
+ */
+#include "nsSplittableFrame.h"
+#include "nsIContent.h"
+#include "nsIPresContext.h"
+#include "nsIStyleContext.h"
+#include "nsISizeOfHandler.h"
+
+nsSplittableFrame::nsSplittableFrame(nsIContent* aContent,
+ nsIFrame* aParent)
+ : nsFrame(aContent, aParent)
+{
+}
+
+nsSplittableFrame::~nsSplittableFrame()
+{
+}
+
+NS_IMETHODIMP
+nsSplittableFrame::SizeOf(nsISizeOfHandler* aHandler) const
+{
+ aHandler->Add(sizeof(*this));
+ nsSplittableFrame::SizeOfWithoutThis(aHandler);
+ return NS_OK;
+}
+
+void
+nsSplittableFrame::SizeOfWithoutThis(nsISizeOfHandler* aHandler) const
+{
+ nsFrame::SizeOfWithoutThis(aHandler);
+ if (!aHandler->HaveSeen(mPrevInFlow)) {
+ mPrevInFlow->SizeOf(aHandler);
+ }
+ if (!aHandler->HaveSeen(mNextInFlow)) {
+ mNextInFlow->SizeOf(aHandler);
+ }
+}
+
+// Flow member functions
+
+NS_IMETHODIMP
+nsSplittableFrame::IsSplittable(nsSplittableType& aIsSplittable) const
+{
+ aIsSplittable = NS_FRAME_SPLITTABLE;
+ return NS_OK;
+}
+
+NS_METHOD nsSplittableFrame::GetPrevInFlow(nsIFrame*& aPrevInFlow) const
+{
+ aPrevInFlow = mPrevInFlow;
+ return NS_OK;
+}
+
+NS_METHOD nsSplittableFrame::SetPrevInFlow(nsIFrame* aFrame)
+{
+ mPrevInFlow = aFrame;
+ return NS_OK;
+}
+
+NS_METHOD nsSplittableFrame::GetNextInFlow(nsIFrame*& aNextInFlow) const
+{
+ aNextInFlow = mNextInFlow;
+ return NS_OK;
+}
+
+NS_METHOD nsSplittableFrame::SetNextInFlow(nsIFrame* aFrame)
+{
+ mNextInFlow = aFrame;
+ return NS_OK;
+}
+
+nsIFrame* nsSplittableFrame::GetFirstInFlow() const
+{
+ nsSplittableFrame* firstInFlow;
+ nsSplittableFrame* prevInFlow = (nsSplittableFrame*)this;
+ while (nsnull!=prevInFlow) {
+ firstInFlow = prevInFlow;
+ prevInFlow = (nsSplittableFrame*)firstInFlow->mPrevInFlow;
+ }
+ NS_POSTCONDITION(nsnull!=firstInFlow, "illegal state in flow chain.");
+ return firstInFlow;
+}
+
+nsIFrame* nsSplittableFrame::GetLastInFlow() const
+{
+ nsSplittableFrame* lastInFlow;
+ nsSplittableFrame* nextInFlow = (nsSplittableFrame*)this;
+ while (nsnull!=nextInFlow) {
+ lastInFlow = nextInFlow;
+ nextInFlow = (nsSplittableFrame*)lastInFlow->mNextInFlow;
+ }
+ NS_POSTCONDITION(nsnull!=lastInFlow, "illegal state in flow chain.");
+ return lastInFlow;
+}
+
+// Append this frame to flow after aAfterFrame
+NS_METHOD nsSplittableFrame::AppendToFlow(nsIFrame* aAfterFrame)
+{
+ NS_PRECONDITION(aAfterFrame != nsnull, "null pointer");
+
+ mPrevInFlow = aAfterFrame;
+ aAfterFrame->GetNextInFlow(mNextInFlow);
+ mPrevInFlow->SetNextInFlow(this);
+ if (mNextInFlow) {
+ mNextInFlow->SetPrevInFlow(this);
+ }
+ return NS_OK;
+}
+
+// Prepend this frame to flow before aBeforeFrame
+NS_METHOD nsSplittableFrame::PrependToFlow(nsIFrame* aBeforeFrame)
+{
+ NS_PRECONDITION(aBeforeFrame != nsnull, "null pointer");
+
+ aBeforeFrame->GetPrevInFlow(mPrevInFlow);
+ mNextInFlow = aBeforeFrame;
+ mNextInFlow->SetPrevInFlow(this);
+ if (mPrevInFlow) {
+ mPrevInFlow->SetNextInFlow(this);
+ }
+ return NS_OK;
+}
+
+// Remove this frame from the flow. Connects prev in flow and next in flow
+NS_METHOD nsSplittableFrame::RemoveFromFlow()
+{
+ if (mPrevInFlow) {
+ mPrevInFlow->SetNextInFlow(mNextInFlow);
+ }
+
+ if (mNextInFlow) {
+ mNextInFlow->SetPrevInFlow(mPrevInFlow);
+ }
+
+ mPrevInFlow = mNextInFlow = nsnull;
+ return NS_OK;
+}
+
+// Detach from previous frame in flow
+NS_METHOD nsSplittableFrame::BreakFromPrevFlow()
+{
+ if (mPrevInFlow) {
+ mPrevInFlow->SetNextInFlow(nsnull);
+ mPrevInFlow = nsnull;
+ }
+ return NS_OK;
+}
+
+// Detach from next frame in flow
+NS_METHOD nsSplittableFrame::BreakFromNextFlow()
+{
+ if (mNextInFlow) {
+ mNextInFlow->SetPrevInFlow(nsnull);
+ mNextInFlow = nsnull;
+ }
+ return NS_OK;
+}
+
+nsIFrame * nsSplittableFrame::GetPrevInFlow()
+{
+ return mPrevInFlow;
+}
+
+nsIFrame * nsSplittableFrame::GetNextInFlow()
+{
+ return mNextInFlow;
+}
diff --git a/layout/html/base/src/nsSplittableFrame.h b/layout/html/base/src/nsSplittableFrame.h
new file mode 100644
index 000000000000..ce9e9f5cd755
--- /dev/null
+++ b/layout/html/base/src/nsSplittableFrame.h
@@ -0,0 +1,71 @@
+/* -*- 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 "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.
+ */
+#ifndef nsSplittableFrame_h___
+#define nsSplittableFrame_h___
+
+#include "nsFrame.h"
+
+// Derived class that allows splitting
+class nsSplittableFrame : public nsFrame
+{
+public:
+ NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler) const;
+ // CreateContinuingFrame() does the default behavior of using the
+ // content delegate to create a new frame
+ NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const;
+
+ // Flow member functions.
+ NS_IMETHOD GetPrevInFlow(nsIFrame*& aPrevInFlow) const;
+ NS_IMETHOD SetPrevInFlow(nsIFrame*);
+ NS_IMETHOD GetNextInFlow(nsIFrame*& aNextInFlow) const;
+ NS_IMETHOD SetNextInFlow(nsIFrame*);
+
+ /**
+ * Return the first frame in our current flow.
+ */
+ nsIFrame* GetFirstInFlow() const;
+
+ /**
+ * Return the last frame in our current flow.
+ */
+ nsIFrame* GetLastInFlow() const;
+
+ NS_IMETHOD AppendToFlow(nsIFrame* aAfterFrame);
+ NS_IMETHOD PrependToFlow(nsIFrame* aAfterFrame);
+ NS_IMETHOD RemoveFromFlow();
+ NS_IMETHOD BreakFromPrevFlow();
+ NS_IMETHOD BreakFromNextFlow();
+
+ nsIFrame* GetPrevInFlow();
+ nsIFrame* GetNextInFlow();
+
+
+protected:
+ // Constructor. Takes as arguments the content object, the index in parent,
+ // and the Frame for the content parent
+ nsSplittableFrame(nsIContent* aContent, nsIFrame* aParent);
+
+ virtual ~nsSplittableFrame();
+
+ void SizeOfWithoutThis(nsISizeOfHandler* aHandler) const;
+
+ nsIFrame* mPrevInFlow;
+ nsIFrame* mNextInFlow;
+};
+
+#endif /* nsSplittableFrame_h___ */