Various pagination related bug fixes; pass in reflow command to FindTextRuns

This commit is contained in:
kipp 1998-06-30 20:14:04 +00:00
Родитель f6fcd6698d
Коммит a4bf798d9b
2 изменённых файлов: 317 добавлений и 138 удалений

Просмотреть файл

@ -181,8 +181,12 @@ protected:
PRBool IsPseudoFrame() const;
nsresult InitialReflow(nsCSSBlockReflowState& aState);
nsresult FrameAppendedReflow(nsCSSBlockReflowState& aState);
nsresult CreateNewFrames(nsIPresContext* aPresContext);
nsresult FindTextRuns(nsCSSBlockReflowState& aState);
nsresult ChildIncrementalReflow(nsCSSBlockReflowState& aState);
@ -220,7 +224,7 @@ protected:
PRBool PullFrame(nsCSSBlockReflowState& aState,
LineData* aToLine,
LineData* aFromLine,
LineData** aFromList,
PRBool aUpdateGeometricParent,
nsInlineReflowStatus& aResult);
@ -338,12 +342,12 @@ LineData::~LineData()
}
static void
ListFloaters(FILE* out, PRInt32 aIndent, nsVoidArray* aFloaters)
ListFloaters(FILE* out, nsVoidArray* aFloaters)
{
PRInt32 i, n = aFloaters->Count();
for (i = 0; i < n; i++) {
nsIFrame* frame = (nsIFrame*) aFloaters->ElementAt(i);
frame->List(out, aIndent);
frame->ListTag(out);
}
}
@ -361,7 +365,7 @@ LineData::List(FILE* out, PRInt32 aIndent) const
{
PRInt32 i;
for (i = aIndent; --i >= 0; ) fputs(" ", out);
fprintf(out, "%p: count=%d state=%x {%d,%d,%d,%d} <\n",
fprintf(out, "line %p: count=%d state=%x {%d,%d,%d,%d} <\n",
this, mChildCount, GetState(),
mBounds.x, mBounds.y, mBounds.width, mBounds.height);
@ -375,9 +379,8 @@ LineData::List(FILE* out, PRInt32 aIndent) const
for (i = aIndent; --i >= 0; ) fputs(" ", out);
if (nsnull != mFloaters) {
fputs("> bcl-floaters=<\n", out);
ListFloaters(out, aIndent + 1, mFloaters);
for (i = aIndent; --i >= 0; ) fputs(" ", out);
fputs("> bcl-floaters=<", out);
ListFloaters(out, mFloaters);
}
fputs(">\n", out);
}
@ -846,8 +849,7 @@ nsCSSBlockFrame::CreateContinuingFrame(nsIPresContext* aCX,
PrepareContinuingFrame(aCX, aParent, aStyleContext, cf);
aContinuingFrame = cf;
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("nsCSSBlockFrame::CreateContinuingFrame: prev-in-flow=%p newFrame=%p",
this, cf));
("nsCSSBlockFrame::CreateContinuingFrame: newFrame=%p", cf));
return NS_OK;
}
@ -907,8 +909,8 @@ nsCSSBlockFrame::List(FILE* out, PRInt32 aIndent) const
// Dump run-in floaters
if (nsnull != mRunInFloaters) {
fputs(" run-in-floaters=<\n", out);
ListFloaters(out, aIndent + 1, mRunInFloaters);
fputs(" run-in-floaters=<", out);
ListFloaters(out, mRunInFloaters);
for (i = aIndent; --i >= 0; ) fputs(" ", out);
fputs(">", out);
}
@ -934,6 +936,8 @@ nsCSSBlockFrame::List(FILE* out, PRInt32 aIndent) const
if (nsnull != mTextRuns) {
fputs(" text-runs=<\n", out);
ListTextRuns(out, aIndent + 1, mTextRuns);
for (i = aIndent; --i >= 0; ) fputs(" ", out);
fputs(">", out);
}
fputs("\n", out);
@ -1111,10 +1115,6 @@ nsCSSBlockFrame::Reflow(nsIPresContext* aPresContext,
// that needs generating.
if (eReflowReason_Initial == aReflowState.reason) {
NS_ASSERTION(0 != (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
nsresult rv = ProcessInitialReflow(aPresContext);
if (NS_OK != rv) {
return rv;
}
}
else {
NS_ASSERTION(0 == (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
@ -1131,7 +1131,7 @@ nsCSSBlockFrame::Reflow(nsIPresContext* aPresContext,
if (eReflowReason_Initial == state.reason) {
DrainOverflowLines();
state.GetAvailableSpace();
rv = FrameAppendedReflow(state);
rv = InitialReflow(state);
mState &= ~NS_FRAME_FIRST_REFLOW;
}
else if (eReflowReason_Incremental == state.reason) {
@ -1183,7 +1183,12 @@ nsCSSBlockFrame::Reflow(nsIPresContext* aPresContext,
mLastContentIsComplete = line->GetLastContentIsComplete();
}
if (state.mBlockIsPseudo) {
PropagateContentOffsets();
// Tell our parent to update it's offsets because our offsets have
// changed.
nsContainerFrame* parent = (nsContainerFrame*) mGeometricParent;
parent->PropagateContentOffsets(this, mFirstContentOffset,
mLastContentOffset,
mLastContentIsComplete);
}
#endif
@ -1359,6 +1364,33 @@ IsBlock(PRUint8 aDisplay)
return PR_FALSE;
}
nsresult
nsCSSBlockFrame::InitialReflow(nsCSSBlockReflowState& aState)
{
// Create synthetic content (XXX a hack)
nsresult rv = ProcessInitialReflow(aState.mPresContext);
if (NS_OK != rv) {
return rv;
}
// Create new frames
if (nsnull == mNextInFlow) {
rv = CreateNewFrames(aState.mPresContext);
if (NS_OK != rv) {
return rv;
}
}
// Generate text-run information
rv = FindTextRuns(aState);
if (NS_OK != rv) {
return rv;
}
// Reflow everything
return ResizeReflow(aState);
}
// XXX this is not incremental; yuck. it's because of
// DrainOverflowLines; we don't know how to reflow the overflow lines
// and incrementally handle the new lines....time for dirty bits!
@ -1366,40 +1398,57 @@ IsBlock(PRUint8 aDisplay)
nsresult
nsCSSBlockFrame::FrameAppendedReflow(nsCSSBlockReflowState& aState)
{
// Determine the starting kidContentIndex and the childPrevInFlow if
// the last child is not yet complete.
PRInt32 kidContentIndex = 0;
nsIFrame* childPrevInFlow = nsnull;
nsIFrame* lastFrame = nsnull;
LineData* lastLine = nsnull;
if ((nsnull == mLines) && (nsnull != mPrevInFlow)) {
nsCSSBlockFrame* prev = (nsCSSBlockFrame*)mPrevInFlow;
lastLine = LastLine(prev->mLines);
if (nsnull != lastLine) {
lastFrame = lastLine->LastChild();
lastFrame->GetContentIndex(kidContentIndex);
if (lastLine->GetLastContentIsComplete()) {
kidContentIndex++;
}
else {
childPrevInFlow = lastFrame;
}
nsresult rv = CreateNewFrames(aState.mPresContext);
if (NS_OK != rv) {
return rv;
}
// Generate text-run information
rv = FindTextRuns(aState);
if (NS_OK != rv) {
return rv;
}
// XXX temporary: Reflow everything
return ResizeReflow(aState);
}
nsresult
nsCSSBlockFrame::CreateNewFrames(nsIPresContext* aPresContext)
{
NS_ASSERTION((nsnull == mOverflowLines) && (nsnull == mNextInFlow),
"bad call to CreateNewFrames");
// Get our last line and then get its last child. Use that
// information to determine our kidContentIndex.
LineData* lastLine = LastLine(mLines);
nsIFrame* lastFrame;
PRInt32 kidContentIndex;
if (nsnull != lastLine) {
lastFrame = lastLine->LastChild();
lastFrame->GetContentIndex(kidContentIndex);
if (lastLine->GetLastContentIsComplete()) {
kidContentIndex++;
}
lastLine = nsnull;
lastFrame = nsnull;
else {
#ifdef NS_DEBUG
// Because we always create continuations as we find them (XXX
// sigh) instead of when we need them, we can assert that if the
// last child is not complete then it already has a continuation.
nsIFrame* kidNextInFlow;
lastFrame->GetNextInFlow(kidNextInFlow);
NS_ASSERTION(nsnull != kidNextInFlow, "whoops");
}
#endif
}
else {
lastLine = LastLine(mLines);
if (nsnull != lastLine) {
lastFrame = lastLine->LastChild();
lastFrame->GetContentIndex(kidContentIndex);
if (lastLine->GetLastContentIsComplete()) {
kidContentIndex++;
}
else {
childPrevInFlow = lastFrame;
}
}
// We can't have an empty line list and have a prev-in-flow. If we
// have a prev-in-flow then we are its continuation which means it
// must have pushed some lines into its overflow list; therefore
// we must have some lines.
NS_ASSERTION(nsnull == mPrevInFlow, "prev-in-flow without overflow lines");
lastFrame = nsnull;
kidContentIndex = 0;
}
// Make sure that new inlines go onto the end of the lastLine when
@ -1415,6 +1464,9 @@ nsCSSBlockFrame::FrameAppendedReflow(nsCSSBlockReflowState& aState)
nsresult rv;
PRInt32 lastContentIndex;
lastContentIndex = mContent->ChildCount();
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("enter nsCSSBlockFrame::CreateNewFrames: kidContentIndex=%d lastContentIndex=%d",
kidContentIndex, lastContentIndex));
for (; kidContentIndex < lastContentIndex; kidContentIndex++) {
nsIContent* kid;
kid = mContent->ChildAt(kidContentIndex);
@ -1424,8 +1476,7 @@ nsCSSBlockFrame::FrameAppendedReflow(nsCSSBlockReflowState& aState)
// Create frame for our new child and add it to the sibling list
nsIFrame* frame;
rv = nsHTMLBase::CreateFrame(aState.mPresContext, this, kid,
childPrevInFlow, frame);
rv = nsHTMLBase::CreateFrame(aPresContext, this, kid, nsnull, frame);
NS_RELEASE(kid);
if (NS_OK != rv) {
return rv;
@ -1434,7 +1485,9 @@ nsCSSBlockFrame::FrameAppendedReflow(nsCSSBlockReflowState& aState)
lastFrame->SetNextSibling(frame);
}
lastFrame = frame;
childPrevInFlow = nsnull;
//XXX childPrevInFlow = nsnull;
NS_FRAME_TRACE(NS_FRAME_TRACE_NEW_FRAMES,
("nsCSSBlockFrame::CreateNewFrames: new-frame=%p", frame));
// See if the child is a block or non-block
const nsStyleDisplay* kidDisplay;
@ -1499,15 +1552,9 @@ nsCSSBlockFrame::FrameAppendedReflow(nsCSSBlockReflowState& aState)
lastLine->SetLastContentIsComplete();
}
// Generate text-run information
rv = FindTextRuns(aState);
if (NS_OK != rv) {
return rv;
}
// XXX temporary; use dirty bits instead so we can skip over all of
// the lines that weren't changed.
return ResizeReflow(aState);
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("exit nsCSSBlockFrame::CreateNewFrames"));
return NS_OK;
}
nsresult
@ -1528,7 +1575,8 @@ nsCSSBlockFrame::FindTextRuns(nsCSSBlockReflowState& aState)
nsIInlineReflow* inlineReflow;
if (NS_OK == frame->QueryInterface(kIInlineReflowIID,
(void**)&inlineReflow)) {
nsresult rv = inlineReflow->FindTextRuns(aState.mLineLayout);
nsresult rv = inlineReflow->FindTextRuns(aState.mLineLayout,
aState.reflowCommand);
if (NS_OK != rv) {
return rv;
}
@ -1768,13 +1816,9 @@ nsCSSBlockFrame::ReflowLine(nsCSSBlockReflowState& aState,
// Pull frames from the next line until we can't
while (nsnull != aLine->mNext) {
LineData* line = aLine->mNext;
keepGoing = PullFrame(aState, aLine, line, PR_FALSE, aReflowResult);
if (0 == line->mChildCount) {
aLine->mNext = line->mNext;
line->mNext = aState.mFreeList; // put on freelist
aState.mFreeList = line;
}
LineData** linep = &aLine->mNext;
keepGoing = PullFrame(aState, aLine, &aLine->mNext,
PR_FALSE, aReflowResult);
if (!keepGoing) {
goto done;
}
@ -1789,12 +1833,8 @@ nsCSSBlockFrame::ReflowLine(nsCSSBlockReflowState& aState,
aState.mNextInFlow = nextInFlow;
continue;
}
keepGoing = PullFrame(aState, aLine, line, PR_TRUE, aReflowResult);
if (0 == line->mChildCount) {
nextInFlow->mLines = line->mNext;
line->mNext = aState.mFreeList; // put on freelist
aState.mFreeList = line;
}
keepGoing = PullFrame(aState, aLine, &nextInFlow->mLines,
PR_TRUE, aReflowResult);
if (!keepGoing) {
goto done;
}
@ -2012,19 +2052,23 @@ nsCSSBlockFrame::ReflowBlockFrame(nsCSSBlockReflowState& aState,
}
if (nsnull != nextInFlow) {
// We made a next-in-flow for the block child frame. Create a
// line to map that block childs next-in-flow and then push that
// line to our next-in-flow.
// line to map the block childs next-in-flow.
LineData* line = new LineData(nextInFlow, 1);
if (nsnull == line) {
aReflowResult = nsInlineReflowStatus(NS_ERROR_OUT_OF_MEMORY);
return PR_FALSE;
}
line->SetLastContentIsComplete();
line->SetIsBlock();
line->mNext = aLine->mNext;
aLine->mNext = line;
}
// Push the new line to the next-in-flow
aState.mPrevLine = aLine;
// Advance mPrevLine because we are keeping aLine (since some of
// the child block frame fit). Then push any remaining lines to
// our next-in-flow
aState.mPrevLine = aLine;
if (nsnull != aLine->mNext) {
PushLines(aState);
}
aReflowResult = NS_INLINE_LINE_BREAK_AFTER(reflowStatus);
@ -2182,27 +2226,34 @@ nsCSSBlockFrame::SplitLine(nsCSSBlockReflowState& aState,
PRBool
nsCSSBlockFrame::PullFrame(nsCSSBlockReflowState& aState,
LineData* aLine,
LineData* aFromLine,
LineData** aFromList,
PRBool aUpdateGeometricParent,
nsInlineReflowStatus& aReflowResult)
{
if (0 == aFromLine->mChildCount) {
NS_ASSERTION(nsnull == aFromLine->mFirstChild, "bad line");
LineData* fromLine = *aFromList;
NS_ASSERTION(nsnull != fromLine, "bad line to pull from");
if (0 == fromLine->mChildCount) {
// Discard empty lines immediately. Empty lines can happen here
// because of DeleteChildsNextInFlow not being able to delete
// lines.
*aFromList = fromLine->mNext;
fromLine->mNext = aState.mFreeList;
aState.mFreeList = fromLine;
return PR_TRUE;
}
// If our line is not empty and the child in aFromLine is a block
// then we cannot pull up the frame into this line.
if ((0 != aLine->mChildCount) && aFromLine->IsBlock()) {
if ((0 != aLine->mChildCount) && fromLine->IsBlock()) {
aReflowResult = NS_INLINE_LINE_BREAK_BEFORE(0);
return PR_FALSE;
}
// Take frame from aFromLine
nsIFrame* frame = aFromLine->mFirstChild;
// Take frame from fromLine
nsIFrame* frame = fromLine->mFirstChild;
if (0 == aLine->mChildCount++) {
aLine->mFirstChild = frame;
aLine->SetIsBlock(aFromLine->IsBlock());
aLine->SetIsBlock(fromLine->IsBlock());
#ifdef NS_DEBUG
const nsStyleDisplay* display;
frame->GetStyleData(eStyleStruct_Display,
@ -2211,11 +2262,15 @@ nsCSSBlockFrame::PullFrame(nsCSSBlockReflowState& aState,
NS_ASSERTION(isBlock == aLine->IsBlock(), "bad line isBlock");
#endif
}
if (0 != --aFromLine->mChildCount) {
frame->GetNextSibling(aFromLine->mFirstChild);
if (0 != --fromLine->mChildCount) {
frame->GetNextSibling(fromLine->mFirstChild);
}
else {
aFromLine->mFirstChild = nsnull;
// Free up the fromLine now that it's empty
*aFromList = fromLine->mNext;
fromLine->mFirstChild = nsnull;
fromLine->mNext = aState.mFreeList;
aState.mFreeList = fromLine;
}
// Change geometric parents
@ -2346,28 +2401,6 @@ nsCSSBlockFrame::PushLines(nsCSSBlockReflowState& aState)
LineData* lastLine = aState.mPrevLine;
LineData* nextLine = lastLine->mNext;
#if XXX
// Strip out empty lines
LineData** lp = &nextLine;
for (;;) {
LineData* line = *lp;
if (nsnull == line) {
break;
}
if (0 == line->mChildCount) {
NS_ASSERTION(nsnull == line->mFirstChild, "bad line");
*lp = line->mNext;
line->mNext = aState.mFreeList;
aState.mFreeList = line;
continue;
}
lp = &line->mNext;
}
if (nsnull == nextLine) {
// Nothing to push: they were all empty
return;
}
#endif
lastLine->mNext = nsnull;
mOverflowLines = nextLine;
@ -2428,6 +2461,9 @@ nsCSSBlockFrame::DrainOverflowLines()
lastLine->mNext = mLines;
mLines = line;
}
// Update our first-content-index now that we have a new first child
mLines->mFirstChild->GetContentIndex(mFirstContentOffset);
}
}
@ -2442,11 +2478,17 @@ nsCSSBlockFrame::DrainOverflowLines()
LineData* lastLine = LastLine(mLines);
if (nsnull == lastLine) {
mLines = mOverflowLines;
// Update our first-content-index now that we have a new first child
mLines->mFirstChild->GetContentIndex(mFirstContentOffset);
}
else {
lastLine->mNext = mOverflowLines;
nsIFrame* lastFrame = lastLine->LastChild();
lastFrame->SetNextSibling(mOverflowLines->mFirstChild);
// Update our last-content-index now that we have a new last child
lastLine = LastLine(mOverflowLines);
lastLine->LastChild()->GetContentIndex(mLastContentOffset);
}
mOverflowLines = nsnull;
}
@ -2459,6 +2501,7 @@ nsCSSBlockFrame::DrainOverflowLines()
return NS_OK;
}
// XXX a copy of nsHTMLContainerFrame's
NS_IMETHODIMP
nsCSSBlockFrame::ContentAppended(nsIPresShell* aShell,
nsIPresContext* aPresContext,

Просмотреть файл

@ -29,11 +29,6 @@
// test: <b>...<br></b> : make sure that it works in pullup case and
// non-pullup case
// XXX As coded today, the reflow-status is mapped into
// complete/not-complete before returning. If we want to support other
// kinds of breaks we need to return the complete breaking status
// outward properly.
// content appended INCREMENTAL reflow
// content inserted INCREMENTAL reflow
// content deleted INCREMENTAL reflow
@ -159,6 +154,8 @@ nsCSSInlineFrame::CreateContinuingFrame(nsIPresContext* aCX,
}
PrepareContinuingFrame(aCX, aParent, aStyleContext, cf);
aContinuingFrame = cf;
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("nsCSSInlineFrame::CreateContinuingFrame: newFrame=%p", cf));
return NS_OK;
}
@ -169,7 +166,8 @@ nsCSSInlineFrame::DeleteNextInFlowsFor(nsIFrame* aChild)
}
NS_IMETHODIMP
nsCSSInlineFrame::FindTextRuns(nsCSSLineLayout& aLineLayout)
nsCSSInlineFrame::FindTextRuns(nsCSSLineLayout& aLineLayout,
nsIReflowCommand* aReflowCommand)
{
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("enter nsCSSInlineFrame::FindTextRuns [%d,%d,%c]",
@ -179,11 +177,31 @@ nsCSSInlineFrame::FindTextRuns(nsCSSLineLayout& aLineLayout)
PRInt32 n;
nsresult rv = NS_OK;
// Create any new frames first
if (mNextInFlow == nsnull) {
rv = CreateNewFrames(aLineLayout);
if (NS_OK != rv) {
goto done;
// Gather up children from the overflow lists
DrainOverflowLists();
// Create new frames if necessary
if (NS_FRAME_FIRST_REFLOW & mState) {
if ((nsnull == mPrevInFlow) && (nsnull == mNextInFlow) &&
(0 == mChildCount)) {
rv = CreateNewFrames(aLineLayout.mPresContext);
if (NS_OK != rv) {
goto done;
}
}
}
else if (nsnull != aReflowCommand) {
nsIFrame* target;
aReflowCommand->GetTarget(target);
if (this == target) {
nsIReflowCommand::ReflowType type;
aReflowCommand->GetType(type);
if (nsIReflowCommand::FrameAppended == type) {
rv = CreateNewFrames(aLineLayout.mPresContext);
if (NS_OK != rv) {
goto done;
}
}
}
}
@ -194,7 +212,7 @@ nsCSSInlineFrame::FindTextRuns(nsCSSLineLayout& aLineLayout)
nsIInlineReflow* inlineReflow;
if (NS_OK == frame->QueryInterface(kIInlineReflowIID,
(void**)&inlineReflow)) {
rv = inlineReflow->FindTextRuns(aLineLayout);
rv = inlineReflow->FindTextRuns(aLineLayout, aReflowCommand);
if (NS_OK != rv) {
return rv;
}
@ -244,8 +262,8 @@ nsCSSInlineFrame::InlineReflow(nsCSSLineLayout& aLineLayout,
PRBool(nsnull != aMetrics.maxElementSize));
nsresult rv = NS_OK;
if (eReflowReason_Initial == state.reason) {
MoveOverflowToChildList();
rv = FrameAppendedReflow(state);
DrainOverflowLists();
rv = InitialReflow(state);
mState &= ~NS_FRAME_FIRST_REFLOW;
}
else if (eReflowReason_Incremental == state.reason) {
@ -275,7 +293,7 @@ nsCSSInlineFrame::InlineReflow(nsCSSLineLayout& aLineLayout,
}
}
else if (eReflowReason_Resize == state.reason) {
MoveOverflowToChildList();
DrainOverflowLists();
rv = ResizeReflow(state);
}
ComputeFinalSize(state, aMetrics);
@ -364,7 +382,30 @@ nsCSSInlineFrame::ComputeFinalSize(nsCSSInlineReflowState& aState,
}
}
// XXX this isn't very incremental; we can do better SOMEDAY
nsInlineReflowStatus
nsCSSInlineFrame::InitialReflow(nsCSSInlineReflowState& aState)
{
NS_PRECONDITION(nsnull == mNextInFlow, "bad frame-appended-reflow");
NS_PRECONDITION(mLastContentIsComplete == PR_TRUE, "bad state");
// Create any frames that need creating; note that they should have been
if ((nsnull == mPrevInFlow) && (nsnull == mNextInFlow) &&
(0 == mChildCount)) {
nsresult rv = CreateNewFrames(aState.mPresContext);
if (NS_OK != rv) {
return rv;
}
}
nsInlineReflowStatus rs = NS_FRAME_COMPLETE;
if (0 != mChildCount) {
if (!ReflowMapped(aState, rs)) {
return rs;
}
}
return rs;
}
nsInlineReflowStatus
nsCSSInlineFrame::FrameAppendedReflow(nsCSSInlineReflowState& aState)
{
@ -372,9 +413,9 @@ nsCSSInlineFrame::FrameAppendedReflow(nsCSSInlineReflowState& aState)
NS_PRECONDITION(mLastContentIsComplete == PR_TRUE, "bad state");
// Create any frames that need creating
nsresult rv = CreateNewFrames(aState.mInlineLayout.mLineLayout);
nsresult rv = CreateNewFrames(aState.mPresContext);
if (NS_OK != rv) {
return nsInlineReflowStatus(rv);
return rv;
}
nsInlineReflowStatus rs = NS_FRAME_COMPLETE;
@ -387,8 +428,12 @@ nsCSSInlineFrame::FrameAppendedReflow(nsCSSInlineReflowState& aState)
}
nsresult
nsCSSInlineFrame::CreateNewFrames(nsCSSLineLayout& aLineLayout)
nsCSSInlineFrame::CreateNewFrames(nsIPresContext* aPresContext)
{
// reason: initial: (a) null nif, pif: create frames
// (b) pullup: don't create frames
// reason: incremental: (a) append targetted at us => create frames
// Get the childPrevInFlow for our eventual first child if we are a
// continuation and we have no children and the last child in our
// prev-in-flow is incomplete. While we are at it, we also compute
@ -427,8 +472,8 @@ nsCSSInlineFrame::CreateNewFrames(nsCSSLineLayout& aLineLayout)
// Create child
nsIFrame* child;
rv = nsHTMLBase::CreateFrame(aLineLayout.mPresContext, this, kid,
childPrevInFlow, child);
rv = nsHTMLBase::CreateFrame(aPresContext, this, kid, childPrevInFlow,
child);
NS_RELEASE(kid);
if (NS_OK != rv) {
return rv;
@ -775,12 +820,16 @@ nsCSSInlineFrame::PullUpChildren(nsCSSInlineReflowState& aState,
keepGoing = PR_TRUE;
done:;
// XXX Why bother? Assuming our offsets are correct then our
// next-in-flow will pick up where we left off.
#if XXX
nextInFlow = (nsCSSInlineFrame*) mNextInFlow;
if ((nsnull != nextInFlow) && (nsnull == nextInFlow->mFirstChild)) {
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus)) {
AdjustOffsetOfEmptyNextInFlows();
}
}
#endif
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("exit nsCSSInlineFrame::PullUpChildren: childCount=%d rs=%x",
@ -813,15 +862,11 @@ nsCSSInlineFrame::PullOneChild(nsCSSInlineFrame* aNextInFlow,
kidFrame, aNextInFlow->mChildCount - 1));
// Take the frame away from the next-in-flow. Update it's first
// content offset and propagate upward the offset if the
// next-in-flow is a pseudo-frame.
// content offset.
kidFrame->GetNextSibling(aNextInFlow->mFirstChild);
aNextInFlow->mChildCount--;
if (nsnull != aNextInFlow->mFirstChild) {
aNextInFlow->SetFirstContentOffset(aNextInFlow->mFirstChild);
if (aNextInFlow->IsPseudoFrame()) {
aNextInFlow->PropagateContentOffsets();
}
}
}
@ -864,8 +909,11 @@ nsCSSInlineFrame::MaybeCreateNextInFlow(nsCSSInlineReflowState& aState,
void
nsCSSInlineFrame::PushKids(nsCSSInlineReflowState& aState,
nsIFrame* aPrevChild, nsIFrame* aPushedChild)
nsIFrame* aPrevChild,
nsIFrame* aPushedChild)
{
NS_ASSERTION(nsnull == mOverflowList, "bad overflow list");
// Count how many children are being pushed
PRInt32 pushCount = mChildCount - aState.mInlineLayout.mFrameNum;
@ -874,11 +922,99 @@ nsCSSInlineFrame::PushKids(nsCSSInlineReflowState& aState,
if (0 != pushCount) {
NS_FRAME_TRACE(NS_FRAME_TRACE_PUSH_PULL,
("nsCSSInlineFrame::PushKids: pushing %d children", pushCount));
PushChildren(aPushedChild, aPrevChild, PR_TRUE/* XXX ignored! */);
// Break sibling list
aPrevChild->SetNextSibling(nsnull);
mChildCount -= pushCount;
// Place overflow frames on our overflow list; our next-in-flow
// will pick them up when it is reflowed
mOverflowList = aPushedChild;
}
#ifdef NS_DEBUG
PRInt32 len = LengthOf(mFirstChild);
NS_ASSERTION(len == mChildCount, "child count is wrong");
#endif
}
void
nsCSSInlineFrame::DrainOverflowLists()
{
// Our prev-in-flows overflow list goes before my children and must
// be re-parented.
if (nsnull != mPrevInFlow) {
nsCSSInlineFrame* prevInFlow = (nsCSSInlineFrame*) mPrevInFlow;
if (nsnull != prevInFlow->mOverflowList) {
nsIFrame* frame = prevInFlow->mOverflowList;
nsIFrame* lastFrame = nsnull;
PRInt32 count = 0;
while (nsnull != frame) {
// Reparent the frame
frame->SetGeometricParent(this);
nsIFrame* contentParent;
frame->GetContentParent(contentParent);
if (prevInFlow == contentParent) {
frame->SetContentParent(this);
}
// Advance through the list
count++;
lastFrame = frame;
frame->GetNextSibling(frame);
}
// Join the two frame lists together and update our child count
#if XXX
if (nsnull == mFirstChild) {
// We are a continuation of our prev-in-flow; we assume that
// the last child was complete.
mLastContentIsComplete = PR_TRUE;
}
#endif
nsIFrame* newFirstChild = prevInFlow->mOverflowList;
newFirstChild->GetContentIndex(mFirstContentOffset);
lastFrame->SetNextSibling(mFirstChild);
mFirstChild = newFirstChild;
prevInFlow->mOverflowList = nsnull;
mChildCount += count;
}
}
// Our overflow list goes to the end of our child list
if (nsnull != mOverflowList) {
// Append the overflow list to the end of our child list
nsIFrame* lastFrame;
LastChild(lastFrame);
if (nsnull == lastFrame) {
mFirstChild = mOverflowList;
mFirstChild->GetContentIndex(mFirstContentOffset);
}
else {
lastFrame->SetNextSibling(mOverflowList);
}
// Count how many frames are on the overflow list and then update
// our count
nsIFrame* frame = mOverflowList;
PRInt32 count = 0;
while (nsnull != frame) {
count++;
frame->GetNextSibling(frame);
}
mChildCount += count;
mOverflowList = nsnull;
#if XXX
// We get here when we pushed some children to a potential
// next-in-flow and then our parent decided to reflow us instead
// of continuing us.
NS_ASSERTION(nsnull == mNextInFlow, "huh?");
mLastContentIsComplete = PR_TRUE;
#endif
}
// XXX What do we set mLastContentIsComplete to?
#ifdef NS_DEBUG
PRInt32 len = LengthOf(mFirstChild);
NS_ASSERTION(len == mChildCount, "child count is wrong");
#endif
}