Fix handling of removed-child incremental reflow to no longer crash (bug #1941); also disabled incremental behavior for remove and inserted for now so that layout looks correct

This commit is contained in:
kipp%netscape.com 1999-01-05 17:50:41 +00:00
parent 3a981f0215
commit e29f665a91
6 changed files with 648 additions and 264 deletions

View File

@ -923,6 +923,8 @@ nsBaseIBFrame::PrepareFrameInsertedReflow(nsBlockReflowState& aState)
// Insert the frame. This marks the affected lines dirty
InsertNewFrame(aState.mPresContext, this, newFrame, prevSibling);
// XXX temporary: incremental reflow doesn't (yet) work in this case
PrepareResizeReflow(aState);
return NS_OK;
}
@ -938,12 +940,11 @@ nsBaseIBFrame::PrepareFrameRemovedReflow(nsBlockReflowState& aState)
nsIFrame* deletedFrame;
aState.reflowCommand->GetChildFrame(deletedFrame);
// Get the previous sibling frame
nsIFrame* prevSibling;
aState.reflowCommand->GetPrevSiblingFrame(prevSibling);
// Remove the frame. This marks the affected lines dirty.
DoRemoveFrame(aState, this, deletedFrame, prevSibling);
DoRemoveFrame(aState, this, deletedFrame);
// XXX temporary: incremental reflow doesn't (yet) work in this case
PrepareResizeReflow(aState);
return NS_OK;
}
@ -2264,6 +2265,14 @@ nsBaseIBFrame::ReflowInlineFrame(nsBlockReflowState& aState,
aState.mReflowStatus = NS_FRAME_NOT_COMPLETE | NS_INLINE_BREAK |
NS_INLINE_BREAK_AFTER | NS_INLINE_MAKE_BREAK_TYPE(breakType);
}
else {
// Mark next line dirty in case SplitLine didn't end up
// pushing any frames.
nsLineBox* next = aLine->mNext;
if ((nsnull != next) && !next->IsBlock()) {
next->MarkDirty();
}
}
}
}
else if (NS_FRAME_IS_NOT_COMPLETE(frameReflowStatus)) {
@ -2299,6 +2308,14 @@ nsBaseIBFrame::ReflowInlineFrame(nsBlockReflowState& aState,
if (NS_FAILED(rv)) {
return rv;
}
if (0 == (BLOCK_IS_INLINE & mFlags)) {
// Mark next line dirty in case SplitLine didn't end up
// pushing any frames.
nsLineBox* next = aLine->mNext;
if ((nsnull != next) && !next->IsBlock()) {
next->MarkDirty();
}
}
}
}
else {
@ -2352,8 +2369,8 @@ nsBaseIBFrame::CreateContinuationFor(nsBlockReflowState& aState,
nsresult
nsBaseIBFrame::SplitLine(nsBlockReflowState& aState,
nsLineBox* aLine,
nsIFrame* aFrame)
nsLineBox* aLine,
nsIFrame* aFrame)
{
PRInt32 pushCount = aLine->ChildCount() -
aState.mInlineReflow->GetCurrentFrameNum();
@ -2955,7 +2972,7 @@ nsBaseIBFrame::AppendNewFrames(nsIPresContext& aPresContext,
nsresult
nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
nsBaseIBFrame* aParentFrame,
nsBaseIBFrame* aParentFrame,
nsIFrame* aNewFrame,
nsIFrame* aPrevSibling)
{
@ -2965,16 +2982,21 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
}
const nsStyleDisplay* display;
aNewFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
aNewFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
const nsStylePosition* position;
aNewFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock = nsLineLayout::TreatFrameAsBlock(display, position)
? LINE_IS_BLOCK : 0;
aNewFrame->GetStyleData(eStyleStruct_Position,
(const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock =
nsLineLayout::TreatFrameAsBlock(display, position)
? LINE_IS_BLOCK
: 0;
// See if we need to move the frame outside of the flow, and insert a
// placeholder frame in its place
nsIFrame* placeholder;
if (MoveFrameOutOfFlow(aPresContext, aNewFrame, display, position, placeholder)) {
if (MoveFrameOutOfFlow(aPresContext, aNewFrame, display, position,
placeholder)) {
// Add the placeholder frame to the flow
aNewFrame = placeholder;
newFrameIsBlock = PR_FALSE; // placeholder frame is always inline
@ -2995,21 +3017,23 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
nsLineBox* line = aParentFrame->mLines;
if (nsnull == aPrevSibling) {
// Insert new frame into the sibling list
aNewFrame->SetNextSibling(line->mFirstChild);
if (nsnull != line) {
aNewFrame->SetNextSibling(line->mFirstChild);
if (line->IsBlock() || newFrameIsBlock) {
// Create a new line
newLine = new nsLineBox(aNewFrame, 1, newFrameIsBlock);
if (nsnull == newLine) {
return NS_ERROR_OUT_OF_MEMORY;
if ((nsnull == line) || line->IsBlock() || newFrameIsBlock) {
// Create a new line
newLine = new nsLineBox(aNewFrame, 1, newFrameIsBlock);
if (nsnull == newLine) {
return NS_ERROR_OUT_OF_MEMORY;
}
newLine->mNext = aParentFrame->mLines;
aParentFrame->mLines = newLine;
} else {
// Insert frame at the front of the line
line->mFirstChild = aNewFrame;
line->mChildCount++;
line->MarkDirty();
}
newLine->mNext = aParentFrame->mLines;
aParentFrame->mLines = newLine;
} else {
// Insert frame at the front of the line
line->mFirstChild = aNewFrame;
line->mChildCount++;
line->MarkDirty();
}
}
else {
@ -3096,28 +3120,43 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
return NS_OK;
}
// XXX this code can't work...rewrite it!
nsresult
nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
nsBaseIBFrame* aParentFrame,
nsIFrame* aDeletedFrame,
nsIFrame* aPrevSibling)
nsIFrame* aDeletedFrame)
{
// Find the line that contains deletedFrame; we also find the pointer to
// the line.
// Find the line and the previous sibling that contains
// deletedFrame; we also find the pointer to the line.
nsBaseIBFrame* flow = this;
nsLineBox** linep = &flow->mLines;
nsLineBox* line = flow->mLines;
nsLineBox* prevLine = nsnull;
nsIFrame* prevSibling = nsnull;
while (nsnull != line) {
if (line->Contains(aDeletedFrame)) {
break;
nsIFrame* frame = line->mFirstChild;
PRInt32 n = line->ChildCount();
while (--n >= 0) {
if (frame == aDeletedFrame) {
goto found_frame;
}
prevSibling = frame;
frame->GetNextSibling(frame);
}
linep = &line->mNext;
prevLine = line;
line = line->mNext;
}
found_frame:;
#ifdef NS_DEBUG
NS_ASSERTION(nsnull != line, "can't find deleted frame in lines");
if (nsnull != prevSibling) {
nsIFrame* tmp;
prevSibling->GetNextSibling(tmp);
NS_ASSERTION(tmp == aDeletedFrame, "bad prevSibling");
}
#endif
// Remove frame and its continuations
// Remove frame and all of its continuations
while (nsnull != aDeletedFrame) {
while ((nsnull != line) && (nsnull != aDeletedFrame)) {
#ifdef NS_DEBUG
@ -3151,18 +3190,26 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
}
}
// Get the deleted frames next sibling
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
// Remove aDeletedFrame from the line
if (line->mFirstChild == aDeletedFrame) {
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
line->mFirstChild = nextFrame;
if (!line->IsBlock() && (nsnull != prevLine) && !prevLine->IsBlock()) {
// Make sure the previous line (if it's an inline line) gets
// a reflow too so that it can pullup from the line where we
// just removed the frame.
prevLine->MarkDirty();
}
}
// Take aDeletedFrame out of the sibling list
if (nsnull != aPrevSibling) {
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
aPrevSibling->SetNextSibling(nextFrame);
// Take aDeletedFrame out of the sibling list. Note that
// prevSibling will only be nsnull when we are deleting the very
// first frame.
if (nsnull != prevSibling) {
prevSibling->SetNextSibling(nextFrame);
}
// Destroy frame; capture its next-in-flow first in case we need
@ -3174,8 +3221,6 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
}
aDeletedFrame->DeleteFrame(aState.mPresContext);
aDeletedFrame = nextInFlow;
// XXX If next-in-flow is != next-sibling then we need to break
// out of this loop
// If line is empty, remove it now
nsLineBox* next = line->mNext;
@ -3185,17 +3230,36 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
delete line;
}
else {
line->MarkDirty();
linep = &line->mNext;
}
prevLine = line;
line = next;
// See if we should keep looking in the current flow's line list.
if (nsnull != aDeletedFrame) {
if (aDeletedFrame != nextFrame) {
// The deceased frames continuation is not the next frame in
// the current flow's frame list. Therefore we know that the
// continuation is in a different parent. So break out of
// the loop so that we advance to the next parent.
#ifdef NS_DEBUG
nsIFrame* contParent;
aDeletedFrame->GetContentParent(contParent);
NS_ASSERTION(contParent != flow, "strange continuation");
#endif
break;
}
}
}
// Advance to next flow block if the frame has more continuations
if (nsnull != aDeletedFrame) {
flow = (nsBaseIBFrame*) flow->mNextInFlow;
NS_ASSERTION(nsnull != flow, "whoops, continuation without a parent");
prevLine = nsnull;
line = flow->mLines;
aPrevSibling = nsnull;
prevSibling = nsnull;
}
}
return NS_OK;

View File

@ -923,6 +923,8 @@ nsBaseIBFrame::PrepareFrameInsertedReflow(nsBlockReflowState& aState)
// Insert the frame. This marks the affected lines dirty
InsertNewFrame(aState.mPresContext, this, newFrame, prevSibling);
// XXX temporary: incremental reflow doesn't (yet) work in this case
PrepareResizeReflow(aState);
return NS_OK;
}
@ -938,12 +940,11 @@ nsBaseIBFrame::PrepareFrameRemovedReflow(nsBlockReflowState& aState)
nsIFrame* deletedFrame;
aState.reflowCommand->GetChildFrame(deletedFrame);
// Get the previous sibling frame
nsIFrame* prevSibling;
aState.reflowCommand->GetPrevSiblingFrame(prevSibling);
// Remove the frame. This marks the affected lines dirty.
DoRemoveFrame(aState, this, deletedFrame, prevSibling);
DoRemoveFrame(aState, this, deletedFrame);
// XXX temporary: incremental reflow doesn't (yet) work in this case
PrepareResizeReflow(aState);
return NS_OK;
}
@ -2264,6 +2265,14 @@ nsBaseIBFrame::ReflowInlineFrame(nsBlockReflowState& aState,
aState.mReflowStatus = NS_FRAME_NOT_COMPLETE | NS_INLINE_BREAK |
NS_INLINE_BREAK_AFTER | NS_INLINE_MAKE_BREAK_TYPE(breakType);
}
else {
// Mark next line dirty in case SplitLine didn't end up
// pushing any frames.
nsLineBox* next = aLine->mNext;
if ((nsnull != next) && !next->IsBlock()) {
next->MarkDirty();
}
}
}
}
else if (NS_FRAME_IS_NOT_COMPLETE(frameReflowStatus)) {
@ -2299,6 +2308,14 @@ nsBaseIBFrame::ReflowInlineFrame(nsBlockReflowState& aState,
if (NS_FAILED(rv)) {
return rv;
}
if (0 == (BLOCK_IS_INLINE & mFlags)) {
// Mark next line dirty in case SplitLine didn't end up
// pushing any frames.
nsLineBox* next = aLine->mNext;
if ((nsnull != next) && !next->IsBlock()) {
next->MarkDirty();
}
}
}
}
else {
@ -2352,8 +2369,8 @@ nsBaseIBFrame::CreateContinuationFor(nsBlockReflowState& aState,
nsresult
nsBaseIBFrame::SplitLine(nsBlockReflowState& aState,
nsLineBox* aLine,
nsIFrame* aFrame)
nsLineBox* aLine,
nsIFrame* aFrame)
{
PRInt32 pushCount = aLine->ChildCount() -
aState.mInlineReflow->GetCurrentFrameNum();
@ -2955,7 +2972,7 @@ nsBaseIBFrame::AppendNewFrames(nsIPresContext& aPresContext,
nsresult
nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
nsBaseIBFrame* aParentFrame,
nsBaseIBFrame* aParentFrame,
nsIFrame* aNewFrame,
nsIFrame* aPrevSibling)
{
@ -2965,16 +2982,21 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
}
const nsStyleDisplay* display;
aNewFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
aNewFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
const nsStylePosition* position;
aNewFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock = nsLineLayout::TreatFrameAsBlock(display, position)
? LINE_IS_BLOCK : 0;
aNewFrame->GetStyleData(eStyleStruct_Position,
(const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock =
nsLineLayout::TreatFrameAsBlock(display, position)
? LINE_IS_BLOCK
: 0;
// See if we need to move the frame outside of the flow, and insert a
// placeholder frame in its place
nsIFrame* placeholder;
if (MoveFrameOutOfFlow(aPresContext, aNewFrame, display, position, placeholder)) {
if (MoveFrameOutOfFlow(aPresContext, aNewFrame, display, position,
placeholder)) {
// Add the placeholder frame to the flow
aNewFrame = placeholder;
newFrameIsBlock = PR_FALSE; // placeholder frame is always inline
@ -2995,21 +3017,23 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
nsLineBox* line = aParentFrame->mLines;
if (nsnull == aPrevSibling) {
// Insert new frame into the sibling list
aNewFrame->SetNextSibling(line->mFirstChild);
if (nsnull != line) {
aNewFrame->SetNextSibling(line->mFirstChild);
if (line->IsBlock() || newFrameIsBlock) {
// Create a new line
newLine = new nsLineBox(aNewFrame, 1, newFrameIsBlock);
if (nsnull == newLine) {
return NS_ERROR_OUT_OF_MEMORY;
if ((nsnull == line) || line->IsBlock() || newFrameIsBlock) {
// Create a new line
newLine = new nsLineBox(aNewFrame, 1, newFrameIsBlock);
if (nsnull == newLine) {
return NS_ERROR_OUT_OF_MEMORY;
}
newLine->mNext = aParentFrame->mLines;
aParentFrame->mLines = newLine;
} else {
// Insert frame at the front of the line
line->mFirstChild = aNewFrame;
line->mChildCount++;
line->MarkDirty();
}
newLine->mNext = aParentFrame->mLines;
aParentFrame->mLines = newLine;
} else {
// Insert frame at the front of the line
line->mFirstChild = aNewFrame;
line->mChildCount++;
line->MarkDirty();
}
}
else {
@ -3096,28 +3120,43 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
return NS_OK;
}
// XXX this code can't work...rewrite it!
nsresult
nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
nsBaseIBFrame* aParentFrame,
nsIFrame* aDeletedFrame,
nsIFrame* aPrevSibling)
nsIFrame* aDeletedFrame)
{
// Find the line that contains deletedFrame; we also find the pointer to
// the line.
// Find the line and the previous sibling that contains
// deletedFrame; we also find the pointer to the line.
nsBaseIBFrame* flow = this;
nsLineBox** linep = &flow->mLines;
nsLineBox* line = flow->mLines;
nsLineBox* prevLine = nsnull;
nsIFrame* prevSibling = nsnull;
while (nsnull != line) {
if (line->Contains(aDeletedFrame)) {
break;
nsIFrame* frame = line->mFirstChild;
PRInt32 n = line->ChildCount();
while (--n >= 0) {
if (frame == aDeletedFrame) {
goto found_frame;
}
prevSibling = frame;
frame->GetNextSibling(frame);
}
linep = &line->mNext;
prevLine = line;
line = line->mNext;
}
found_frame:;
#ifdef NS_DEBUG
NS_ASSERTION(nsnull != line, "can't find deleted frame in lines");
if (nsnull != prevSibling) {
nsIFrame* tmp;
prevSibling->GetNextSibling(tmp);
NS_ASSERTION(tmp == aDeletedFrame, "bad prevSibling");
}
#endif
// Remove frame and its continuations
// Remove frame and all of its continuations
while (nsnull != aDeletedFrame) {
while ((nsnull != line) && (nsnull != aDeletedFrame)) {
#ifdef NS_DEBUG
@ -3151,18 +3190,26 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
}
}
// Get the deleted frames next sibling
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
// Remove aDeletedFrame from the line
if (line->mFirstChild == aDeletedFrame) {
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
line->mFirstChild = nextFrame;
if (!line->IsBlock() && (nsnull != prevLine) && !prevLine->IsBlock()) {
// Make sure the previous line (if it's an inline line) gets
// a reflow too so that it can pullup from the line where we
// just removed the frame.
prevLine->MarkDirty();
}
}
// Take aDeletedFrame out of the sibling list
if (nsnull != aPrevSibling) {
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
aPrevSibling->SetNextSibling(nextFrame);
// Take aDeletedFrame out of the sibling list. Note that
// prevSibling will only be nsnull when we are deleting the very
// first frame.
if (nsnull != prevSibling) {
prevSibling->SetNextSibling(nextFrame);
}
// Destroy frame; capture its next-in-flow first in case we need
@ -3174,8 +3221,6 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
}
aDeletedFrame->DeleteFrame(aState.mPresContext);
aDeletedFrame = nextInFlow;
// XXX If next-in-flow is != next-sibling then we need to break
// out of this loop
// If line is empty, remove it now
nsLineBox* next = line->mNext;
@ -3185,17 +3230,36 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
delete line;
}
else {
line->MarkDirty();
linep = &line->mNext;
}
prevLine = line;
line = next;
// See if we should keep looking in the current flow's line list.
if (nsnull != aDeletedFrame) {
if (aDeletedFrame != nextFrame) {
// The deceased frames continuation is not the next frame in
// the current flow's frame list. Therefore we know that the
// continuation is in a different parent. So break out of
// the loop so that we advance to the next parent.
#ifdef NS_DEBUG
nsIFrame* contParent;
aDeletedFrame->GetContentParent(contParent);
NS_ASSERTION(contParent != flow, "strange continuation");
#endif
break;
}
}
}
// Advance to next flow block if the frame has more continuations
if (nsnull != aDeletedFrame) {
flow = (nsBaseIBFrame*) flow->mNextInFlow;
NS_ASSERTION(nsnull != flow, "whoops, continuation without a parent");
prevLine = nsnull;
line = flow->mLines;
aPrevSibling = nsnull;
prevSibling = nsnull;
}
}
return NS_OK;

View File

@ -923,6 +923,8 @@ nsBaseIBFrame::PrepareFrameInsertedReflow(nsBlockReflowState& aState)
// Insert the frame. This marks the affected lines dirty
InsertNewFrame(aState.mPresContext, this, newFrame, prevSibling);
// XXX temporary: incremental reflow doesn't (yet) work in this case
PrepareResizeReflow(aState);
return NS_OK;
}
@ -938,12 +940,11 @@ nsBaseIBFrame::PrepareFrameRemovedReflow(nsBlockReflowState& aState)
nsIFrame* deletedFrame;
aState.reflowCommand->GetChildFrame(deletedFrame);
// Get the previous sibling frame
nsIFrame* prevSibling;
aState.reflowCommand->GetPrevSiblingFrame(prevSibling);
// Remove the frame. This marks the affected lines dirty.
DoRemoveFrame(aState, this, deletedFrame, prevSibling);
DoRemoveFrame(aState, this, deletedFrame);
// XXX temporary: incremental reflow doesn't (yet) work in this case
PrepareResizeReflow(aState);
return NS_OK;
}
@ -2264,6 +2265,14 @@ nsBaseIBFrame::ReflowInlineFrame(nsBlockReflowState& aState,
aState.mReflowStatus = NS_FRAME_NOT_COMPLETE | NS_INLINE_BREAK |
NS_INLINE_BREAK_AFTER | NS_INLINE_MAKE_BREAK_TYPE(breakType);
}
else {
// Mark next line dirty in case SplitLine didn't end up
// pushing any frames.
nsLineBox* next = aLine->mNext;
if ((nsnull != next) && !next->IsBlock()) {
next->MarkDirty();
}
}
}
}
else if (NS_FRAME_IS_NOT_COMPLETE(frameReflowStatus)) {
@ -2299,6 +2308,14 @@ nsBaseIBFrame::ReflowInlineFrame(nsBlockReflowState& aState,
if (NS_FAILED(rv)) {
return rv;
}
if (0 == (BLOCK_IS_INLINE & mFlags)) {
// Mark next line dirty in case SplitLine didn't end up
// pushing any frames.
nsLineBox* next = aLine->mNext;
if ((nsnull != next) && !next->IsBlock()) {
next->MarkDirty();
}
}
}
}
else {
@ -2352,8 +2369,8 @@ nsBaseIBFrame::CreateContinuationFor(nsBlockReflowState& aState,
nsresult
nsBaseIBFrame::SplitLine(nsBlockReflowState& aState,
nsLineBox* aLine,
nsIFrame* aFrame)
nsLineBox* aLine,
nsIFrame* aFrame)
{
PRInt32 pushCount = aLine->ChildCount() -
aState.mInlineReflow->GetCurrentFrameNum();
@ -2955,7 +2972,7 @@ nsBaseIBFrame::AppendNewFrames(nsIPresContext& aPresContext,
nsresult
nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
nsBaseIBFrame* aParentFrame,
nsBaseIBFrame* aParentFrame,
nsIFrame* aNewFrame,
nsIFrame* aPrevSibling)
{
@ -2965,16 +2982,21 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
}
const nsStyleDisplay* display;
aNewFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
aNewFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
const nsStylePosition* position;
aNewFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock = nsLineLayout::TreatFrameAsBlock(display, position)
? LINE_IS_BLOCK : 0;
aNewFrame->GetStyleData(eStyleStruct_Position,
(const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock =
nsLineLayout::TreatFrameAsBlock(display, position)
? LINE_IS_BLOCK
: 0;
// See if we need to move the frame outside of the flow, and insert a
// placeholder frame in its place
nsIFrame* placeholder;
if (MoveFrameOutOfFlow(aPresContext, aNewFrame, display, position, placeholder)) {
if (MoveFrameOutOfFlow(aPresContext, aNewFrame, display, position,
placeholder)) {
// Add the placeholder frame to the flow
aNewFrame = placeholder;
newFrameIsBlock = PR_FALSE; // placeholder frame is always inline
@ -2995,21 +3017,23 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
nsLineBox* line = aParentFrame->mLines;
if (nsnull == aPrevSibling) {
// Insert new frame into the sibling list
aNewFrame->SetNextSibling(line->mFirstChild);
if (nsnull != line) {
aNewFrame->SetNextSibling(line->mFirstChild);
if (line->IsBlock() || newFrameIsBlock) {
// Create a new line
newLine = new nsLineBox(aNewFrame, 1, newFrameIsBlock);
if (nsnull == newLine) {
return NS_ERROR_OUT_OF_MEMORY;
if ((nsnull == line) || line->IsBlock() || newFrameIsBlock) {
// Create a new line
newLine = new nsLineBox(aNewFrame, 1, newFrameIsBlock);
if (nsnull == newLine) {
return NS_ERROR_OUT_OF_MEMORY;
}
newLine->mNext = aParentFrame->mLines;
aParentFrame->mLines = newLine;
} else {
// Insert frame at the front of the line
line->mFirstChild = aNewFrame;
line->mChildCount++;
line->MarkDirty();
}
newLine->mNext = aParentFrame->mLines;
aParentFrame->mLines = newLine;
} else {
// Insert frame at the front of the line
line->mFirstChild = aNewFrame;
line->mChildCount++;
line->MarkDirty();
}
}
else {
@ -3096,28 +3120,43 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
return NS_OK;
}
// XXX this code can't work...rewrite it!
nsresult
nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
nsBaseIBFrame* aParentFrame,
nsIFrame* aDeletedFrame,
nsIFrame* aPrevSibling)
nsIFrame* aDeletedFrame)
{
// Find the line that contains deletedFrame; we also find the pointer to
// the line.
// Find the line and the previous sibling that contains
// deletedFrame; we also find the pointer to the line.
nsBaseIBFrame* flow = this;
nsLineBox** linep = &flow->mLines;
nsLineBox* line = flow->mLines;
nsLineBox* prevLine = nsnull;
nsIFrame* prevSibling = nsnull;
while (nsnull != line) {
if (line->Contains(aDeletedFrame)) {
break;
nsIFrame* frame = line->mFirstChild;
PRInt32 n = line->ChildCount();
while (--n >= 0) {
if (frame == aDeletedFrame) {
goto found_frame;
}
prevSibling = frame;
frame->GetNextSibling(frame);
}
linep = &line->mNext;
prevLine = line;
line = line->mNext;
}
found_frame:;
#ifdef NS_DEBUG
NS_ASSERTION(nsnull != line, "can't find deleted frame in lines");
if (nsnull != prevSibling) {
nsIFrame* tmp;
prevSibling->GetNextSibling(tmp);
NS_ASSERTION(tmp == aDeletedFrame, "bad prevSibling");
}
#endif
// Remove frame and its continuations
// Remove frame and all of its continuations
while (nsnull != aDeletedFrame) {
while ((nsnull != line) && (nsnull != aDeletedFrame)) {
#ifdef NS_DEBUG
@ -3151,18 +3190,26 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
}
}
// Get the deleted frames next sibling
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
// Remove aDeletedFrame from the line
if (line->mFirstChild == aDeletedFrame) {
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
line->mFirstChild = nextFrame;
if (!line->IsBlock() && (nsnull != prevLine) && !prevLine->IsBlock()) {
// Make sure the previous line (if it's an inline line) gets
// a reflow too so that it can pullup from the line where we
// just removed the frame.
prevLine->MarkDirty();
}
}
// Take aDeletedFrame out of the sibling list
if (nsnull != aPrevSibling) {
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
aPrevSibling->SetNextSibling(nextFrame);
// Take aDeletedFrame out of the sibling list. Note that
// prevSibling will only be nsnull when we are deleting the very
// first frame.
if (nsnull != prevSibling) {
prevSibling->SetNextSibling(nextFrame);
}
// Destroy frame; capture its next-in-flow first in case we need
@ -3174,8 +3221,6 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
}
aDeletedFrame->DeleteFrame(aState.mPresContext);
aDeletedFrame = nextInFlow;
// XXX If next-in-flow is != next-sibling then we need to break
// out of this loop
// If line is empty, remove it now
nsLineBox* next = line->mNext;
@ -3185,17 +3230,36 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
delete line;
}
else {
line->MarkDirty();
linep = &line->mNext;
}
prevLine = line;
line = next;
// See if we should keep looking in the current flow's line list.
if (nsnull != aDeletedFrame) {
if (aDeletedFrame != nextFrame) {
// The deceased frames continuation is not the next frame in
// the current flow's frame list. Therefore we know that the
// continuation is in a different parent. So break out of
// the loop so that we advance to the next parent.
#ifdef NS_DEBUG
nsIFrame* contParent;
aDeletedFrame->GetContentParent(contParent);
NS_ASSERTION(contParent != flow, "strange continuation");
#endif
break;
}
}
}
// Advance to next flow block if the frame has more continuations
if (nsnull != aDeletedFrame) {
flow = (nsBaseIBFrame*) flow->mNextInFlow;
NS_ASSERTION(nsnull != flow, "whoops, continuation without a parent");
prevLine = nsnull;
line = flow->mLines;
aPrevSibling = nsnull;
prevSibling = nsnull;
}
}
return NS_OK;

View File

@ -923,6 +923,8 @@ nsBaseIBFrame::PrepareFrameInsertedReflow(nsBlockReflowState& aState)
// Insert the frame. This marks the affected lines dirty
InsertNewFrame(aState.mPresContext, this, newFrame, prevSibling);
// XXX temporary: incremental reflow doesn't (yet) work in this case
PrepareResizeReflow(aState);
return NS_OK;
}
@ -938,12 +940,11 @@ nsBaseIBFrame::PrepareFrameRemovedReflow(nsBlockReflowState& aState)
nsIFrame* deletedFrame;
aState.reflowCommand->GetChildFrame(deletedFrame);
// Get the previous sibling frame
nsIFrame* prevSibling;
aState.reflowCommand->GetPrevSiblingFrame(prevSibling);
// Remove the frame. This marks the affected lines dirty.
DoRemoveFrame(aState, this, deletedFrame, prevSibling);
DoRemoveFrame(aState, this, deletedFrame);
// XXX temporary: incremental reflow doesn't (yet) work in this case
PrepareResizeReflow(aState);
return NS_OK;
}
@ -2264,6 +2265,14 @@ nsBaseIBFrame::ReflowInlineFrame(nsBlockReflowState& aState,
aState.mReflowStatus = NS_FRAME_NOT_COMPLETE | NS_INLINE_BREAK |
NS_INLINE_BREAK_AFTER | NS_INLINE_MAKE_BREAK_TYPE(breakType);
}
else {
// Mark next line dirty in case SplitLine didn't end up
// pushing any frames.
nsLineBox* next = aLine->mNext;
if ((nsnull != next) && !next->IsBlock()) {
next->MarkDirty();
}
}
}
}
else if (NS_FRAME_IS_NOT_COMPLETE(frameReflowStatus)) {
@ -2299,6 +2308,14 @@ nsBaseIBFrame::ReflowInlineFrame(nsBlockReflowState& aState,
if (NS_FAILED(rv)) {
return rv;
}
if (0 == (BLOCK_IS_INLINE & mFlags)) {
// Mark next line dirty in case SplitLine didn't end up
// pushing any frames.
nsLineBox* next = aLine->mNext;
if ((nsnull != next) && !next->IsBlock()) {
next->MarkDirty();
}
}
}
}
else {
@ -2352,8 +2369,8 @@ nsBaseIBFrame::CreateContinuationFor(nsBlockReflowState& aState,
nsresult
nsBaseIBFrame::SplitLine(nsBlockReflowState& aState,
nsLineBox* aLine,
nsIFrame* aFrame)
nsLineBox* aLine,
nsIFrame* aFrame)
{
PRInt32 pushCount = aLine->ChildCount() -
aState.mInlineReflow->GetCurrentFrameNum();
@ -2955,7 +2972,7 @@ nsBaseIBFrame::AppendNewFrames(nsIPresContext& aPresContext,
nsresult
nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
nsBaseIBFrame* aParentFrame,
nsBaseIBFrame* aParentFrame,
nsIFrame* aNewFrame,
nsIFrame* aPrevSibling)
{
@ -2965,16 +2982,21 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
}
const nsStyleDisplay* display;
aNewFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
aNewFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
const nsStylePosition* position;
aNewFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock = nsLineLayout::TreatFrameAsBlock(display, position)
? LINE_IS_BLOCK : 0;
aNewFrame->GetStyleData(eStyleStruct_Position,
(const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock =
nsLineLayout::TreatFrameAsBlock(display, position)
? LINE_IS_BLOCK
: 0;
// See if we need to move the frame outside of the flow, and insert a
// placeholder frame in its place
nsIFrame* placeholder;
if (MoveFrameOutOfFlow(aPresContext, aNewFrame, display, position, placeholder)) {
if (MoveFrameOutOfFlow(aPresContext, aNewFrame, display, position,
placeholder)) {
// Add the placeholder frame to the flow
aNewFrame = placeholder;
newFrameIsBlock = PR_FALSE; // placeholder frame is always inline
@ -2995,21 +3017,23 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
nsLineBox* line = aParentFrame->mLines;
if (nsnull == aPrevSibling) {
// Insert new frame into the sibling list
aNewFrame->SetNextSibling(line->mFirstChild);
if (nsnull != line) {
aNewFrame->SetNextSibling(line->mFirstChild);
if (line->IsBlock() || newFrameIsBlock) {
// Create a new line
newLine = new nsLineBox(aNewFrame, 1, newFrameIsBlock);
if (nsnull == newLine) {
return NS_ERROR_OUT_OF_MEMORY;
if ((nsnull == line) || line->IsBlock() || newFrameIsBlock) {
// Create a new line
newLine = new nsLineBox(aNewFrame, 1, newFrameIsBlock);
if (nsnull == newLine) {
return NS_ERROR_OUT_OF_MEMORY;
}
newLine->mNext = aParentFrame->mLines;
aParentFrame->mLines = newLine;
} else {
// Insert frame at the front of the line
line->mFirstChild = aNewFrame;
line->mChildCount++;
line->MarkDirty();
}
newLine->mNext = aParentFrame->mLines;
aParentFrame->mLines = newLine;
} else {
// Insert frame at the front of the line
line->mFirstChild = aNewFrame;
line->mChildCount++;
line->MarkDirty();
}
}
else {
@ -3096,28 +3120,43 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
return NS_OK;
}
// XXX this code can't work...rewrite it!
nsresult
nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
nsBaseIBFrame* aParentFrame,
nsIFrame* aDeletedFrame,
nsIFrame* aPrevSibling)
nsIFrame* aDeletedFrame)
{
// Find the line that contains deletedFrame; we also find the pointer to
// the line.
// Find the line and the previous sibling that contains
// deletedFrame; we also find the pointer to the line.
nsBaseIBFrame* flow = this;
nsLineBox** linep = &flow->mLines;
nsLineBox* line = flow->mLines;
nsLineBox* prevLine = nsnull;
nsIFrame* prevSibling = nsnull;
while (nsnull != line) {
if (line->Contains(aDeletedFrame)) {
break;
nsIFrame* frame = line->mFirstChild;
PRInt32 n = line->ChildCount();
while (--n >= 0) {
if (frame == aDeletedFrame) {
goto found_frame;
}
prevSibling = frame;
frame->GetNextSibling(frame);
}
linep = &line->mNext;
prevLine = line;
line = line->mNext;
}
found_frame:;
#ifdef NS_DEBUG
NS_ASSERTION(nsnull != line, "can't find deleted frame in lines");
if (nsnull != prevSibling) {
nsIFrame* tmp;
prevSibling->GetNextSibling(tmp);
NS_ASSERTION(tmp == aDeletedFrame, "bad prevSibling");
}
#endif
// Remove frame and its continuations
// Remove frame and all of its continuations
while (nsnull != aDeletedFrame) {
while ((nsnull != line) && (nsnull != aDeletedFrame)) {
#ifdef NS_DEBUG
@ -3151,18 +3190,26 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
}
}
// Get the deleted frames next sibling
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
// Remove aDeletedFrame from the line
if (line->mFirstChild == aDeletedFrame) {
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
line->mFirstChild = nextFrame;
if (!line->IsBlock() && (nsnull != prevLine) && !prevLine->IsBlock()) {
// Make sure the previous line (if it's an inline line) gets
// a reflow too so that it can pullup from the line where we
// just removed the frame.
prevLine->MarkDirty();
}
}
// Take aDeletedFrame out of the sibling list
if (nsnull != aPrevSibling) {
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
aPrevSibling->SetNextSibling(nextFrame);
// Take aDeletedFrame out of the sibling list. Note that
// prevSibling will only be nsnull when we are deleting the very
// first frame.
if (nsnull != prevSibling) {
prevSibling->SetNextSibling(nextFrame);
}
// Destroy frame; capture its next-in-flow first in case we need
@ -3174,8 +3221,6 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
}
aDeletedFrame->DeleteFrame(aState.mPresContext);
aDeletedFrame = nextInFlow;
// XXX If next-in-flow is != next-sibling then we need to break
// out of this loop
// If line is empty, remove it now
nsLineBox* next = line->mNext;
@ -3185,17 +3230,36 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
delete line;
}
else {
line->MarkDirty();
linep = &line->mNext;
}
prevLine = line;
line = next;
// See if we should keep looking in the current flow's line list.
if (nsnull != aDeletedFrame) {
if (aDeletedFrame != nextFrame) {
// The deceased frames continuation is not the next frame in
// the current flow's frame list. Therefore we know that the
// continuation is in a different parent. So break out of
// the loop so that we advance to the next parent.
#ifdef NS_DEBUG
nsIFrame* contParent;
aDeletedFrame->GetContentParent(contParent);
NS_ASSERTION(contParent != flow, "strange continuation");
#endif
break;
}
}
}
// Advance to next flow block if the frame has more continuations
if (nsnull != aDeletedFrame) {
flow = (nsBaseIBFrame*) flow->mNextInFlow;
NS_ASSERTION(nsnull != flow, "whoops, continuation without a parent");
prevLine = nsnull;
line = flow->mLines;
aPrevSibling = nsnull;
prevSibling = nsnull;
}
}
return NS_OK;

View File

@ -923,6 +923,8 @@ nsBaseIBFrame::PrepareFrameInsertedReflow(nsBlockReflowState& aState)
// Insert the frame. This marks the affected lines dirty
InsertNewFrame(aState.mPresContext, this, newFrame, prevSibling);
// XXX temporary: incremental reflow doesn't (yet) work in this case
PrepareResizeReflow(aState);
return NS_OK;
}
@ -938,12 +940,11 @@ nsBaseIBFrame::PrepareFrameRemovedReflow(nsBlockReflowState& aState)
nsIFrame* deletedFrame;
aState.reflowCommand->GetChildFrame(deletedFrame);
// Get the previous sibling frame
nsIFrame* prevSibling;
aState.reflowCommand->GetPrevSiblingFrame(prevSibling);
// Remove the frame. This marks the affected lines dirty.
DoRemoveFrame(aState, this, deletedFrame, prevSibling);
DoRemoveFrame(aState, this, deletedFrame);
// XXX temporary: incremental reflow doesn't (yet) work in this case
PrepareResizeReflow(aState);
return NS_OK;
}
@ -2264,6 +2265,14 @@ nsBaseIBFrame::ReflowInlineFrame(nsBlockReflowState& aState,
aState.mReflowStatus = NS_FRAME_NOT_COMPLETE | NS_INLINE_BREAK |
NS_INLINE_BREAK_AFTER | NS_INLINE_MAKE_BREAK_TYPE(breakType);
}
else {
// Mark next line dirty in case SplitLine didn't end up
// pushing any frames.
nsLineBox* next = aLine->mNext;
if ((nsnull != next) && !next->IsBlock()) {
next->MarkDirty();
}
}
}
}
else if (NS_FRAME_IS_NOT_COMPLETE(frameReflowStatus)) {
@ -2299,6 +2308,14 @@ nsBaseIBFrame::ReflowInlineFrame(nsBlockReflowState& aState,
if (NS_FAILED(rv)) {
return rv;
}
if (0 == (BLOCK_IS_INLINE & mFlags)) {
// Mark next line dirty in case SplitLine didn't end up
// pushing any frames.
nsLineBox* next = aLine->mNext;
if ((nsnull != next) && !next->IsBlock()) {
next->MarkDirty();
}
}
}
}
else {
@ -2352,8 +2369,8 @@ nsBaseIBFrame::CreateContinuationFor(nsBlockReflowState& aState,
nsresult
nsBaseIBFrame::SplitLine(nsBlockReflowState& aState,
nsLineBox* aLine,
nsIFrame* aFrame)
nsLineBox* aLine,
nsIFrame* aFrame)
{
PRInt32 pushCount = aLine->ChildCount() -
aState.mInlineReflow->GetCurrentFrameNum();
@ -2955,7 +2972,7 @@ nsBaseIBFrame::AppendNewFrames(nsIPresContext& aPresContext,
nsresult
nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
nsBaseIBFrame* aParentFrame,
nsBaseIBFrame* aParentFrame,
nsIFrame* aNewFrame,
nsIFrame* aPrevSibling)
{
@ -2965,16 +2982,21 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
}
const nsStyleDisplay* display;
aNewFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
aNewFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
const nsStylePosition* position;
aNewFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock = nsLineLayout::TreatFrameAsBlock(display, position)
? LINE_IS_BLOCK : 0;
aNewFrame->GetStyleData(eStyleStruct_Position,
(const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock =
nsLineLayout::TreatFrameAsBlock(display, position)
? LINE_IS_BLOCK
: 0;
// See if we need to move the frame outside of the flow, and insert a
// placeholder frame in its place
nsIFrame* placeholder;
if (MoveFrameOutOfFlow(aPresContext, aNewFrame, display, position, placeholder)) {
if (MoveFrameOutOfFlow(aPresContext, aNewFrame, display, position,
placeholder)) {
// Add the placeholder frame to the flow
aNewFrame = placeholder;
newFrameIsBlock = PR_FALSE; // placeholder frame is always inline
@ -2995,21 +3017,23 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
nsLineBox* line = aParentFrame->mLines;
if (nsnull == aPrevSibling) {
// Insert new frame into the sibling list
aNewFrame->SetNextSibling(line->mFirstChild);
if (nsnull != line) {
aNewFrame->SetNextSibling(line->mFirstChild);
if (line->IsBlock() || newFrameIsBlock) {
// Create a new line
newLine = new nsLineBox(aNewFrame, 1, newFrameIsBlock);
if (nsnull == newLine) {
return NS_ERROR_OUT_OF_MEMORY;
if ((nsnull == line) || line->IsBlock() || newFrameIsBlock) {
// Create a new line
newLine = new nsLineBox(aNewFrame, 1, newFrameIsBlock);
if (nsnull == newLine) {
return NS_ERROR_OUT_OF_MEMORY;
}
newLine->mNext = aParentFrame->mLines;
aParentFrame->mLines = newLine;
} else {
// Insert frame at the front of the line
line->mFirstChild = aNewFrame;
line->mChildCount++;
line->MarkDirty();
}
newLine->mNext = aParentFrame->mLines;
aParentFrame->mLines = newLine;
} else {
// Insert frame at the front of the line
line->mFirstChild = aNewFrame;
line->mChildCount++;
line->MarkDirty();
}
}
else {
@ -3096,28 +3120,43 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
return NS_OK;
}
// XXX this code can't work...rewrite it!
nsresult
nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
nsBaseIBFrame* aParentFrame,
nsIFrame* aDeletedFrame,
nsIFrame* aPrevSibling)
nsIFrame* aDeletedFrame)
{
// Find the line that contains deletedFrame; we also find the pointer to
// the line.
// Find the line and the previous sibling that contains
// deletedFrame; we also find the pointer to the line.
nsBaseIBFrame* flow = this;
nsLineBox** linep = &flow->mLines;
nsLineBox* line = flow->mLines;
nsLineBox* prevLine = nsnull;
nsIFrame* prevSibling = nsnull;
while (nsnull != line) {
if (line->Contains(aDeletedFrame)) {
break;
nsIFrame* frame = line->mFirstChild;
PRInt32 n = line->ChildCount();
while (--n >= 0) {
if (frame == aDeletedFrame) {
goto found_frame;
}
prevSibling = frame;
frame->GetNextSibling(frame);
}
linep = &line->mNext;
prevLine = line;
line = line->mNext;
}
found_frame:;
#ifdef NS_DEBUG
NS_ASSERTION(nsnull != line, "can't find deleted frame in lines");
if (nsnull != prevSibling) {
nsIFrame* tmp;
prevSibling->GetNextSibling(tmp);
NS_ASSERTION(tmp == aDeletedFrame, "bad prevSibling");
}
#endif
// Remove frame and its continuations
// Remove frame and all of its continuations
while (nsnull != aDeletedFrame) {
while ((nsnull != line) && (nsnull != aDeletedFrame)) {
#ifdef NS_DEBUG
@ -3151,18 +3190,26 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
}
}
// Get the deleted frames next sibling
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
// Remove aDeletedFrame from the line
if (line->mFirstChild == aDeletedFrame) {
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
line->mFirstChild = nextFrame;
if (!line->IsBlock() && (nsnull != prevLine) && !prevLine->IsBlock()) {
// Make sure the previous line (if it's an inline line) gets
// a reflow too so that it can pullup from the line where we
// just removed the frame.
prevLine->MarkDirty();
}
}
// Take aDeletedFrame out of the sibling list
if (nsnull != aPrevSibling) {
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
aPrevSibling->SetNextSibling(nextFrame);
// Take aDeletedFrame out of the sibling list. Note that
// prevSibling will only be nsnull when we are deleting the very
// first frame.
if (nsnull != prevSibling) {
prevSibling->SetNextSibling(nextFrame);
}
// Destroy frame; capture its next-in-flow first in case we need
@ -3174,8 +3221,6 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
}
aDeletedFrame->DeleteFrame(aState.mPresContext);
aDeletedFrame = nextInFlow;
// XXX If next-in-flow is != next-sibling then we need to break
// out of this loop
// If line is empty, remove it now
nsLineBox* next = line->mNext;
@ -3185,17 +3230,36 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
delete line;
}
else {
line->MarkDirty();
linep = &line->mNext;
}
prevLine = line;
line = next;
// See if we should keep looking in the current flow's line list.
if (nsnull != aDeletedFrame) {
if (aDeletedFrame != nextFrame) {
// The deceased frames continuation is not the next frame in
// the current flow's frame list. Therefore we know that the
// continuation is in a different parent. So break out of
// the loop so that we advance to the next parent.
#ifdef NS_DEBUG
nsIFrame* contParent;
aDeletedFrame->GetContentParent(contParent);
NS_ASSERTION(contParent != flow, "strange continuation");
#endif
break;
}
}
}
// Advance to next flow block if the frame has more continuations
if (nsnull != aDeletedFrame) {
flow = (nsBaseIBFrame*) flow->mNextInFlow;
NS_ASSERTION(nsnull != flow, "whoops, continuation without a parent");
prevLine = nsnull;
line = flow->mLines;
aPrevSibling = nsnull;
prevSibling = nsnull;
}
}
return NS_OK;

View File

@ -923,6 +923,8 @@ nsBaseIBFrame::PrepareFrameInsertedReflow(nsBlockReflowState& aState)
// Insert the frame. This marks the affected lines dirty
InsertNewFrame(aState.mPresContext, this, newFrame, prevSibling);
// XXX temporary: incremental reflow doesn't (yet) work in this case
PrepareResizeReflow(aState);
return NS_OK;
}
@ -938,12 +940,11 @@ nsBaseIBFrame::PrepareFrameRemovedReflow(nsBlockReflowState& aState)
nsIFrame* deletedFrame;
aState.reflowCommand->GetChildFrame(deletedFrame);
// Get the previous sibling frame
nsIFrame* prevSibling;
aState.reflowCommand->GetPrevSiblingFrame(prevSibling);
// Remove the frame. This marks the affected lines dirty.
DoRemoveFrame(aState, this, deletedFrame, prevSibling);
DoRemoveFrame(aState, this, deletedFrame);
// XXX temporary: incremental reflow doesn't (yet) work in this case
PrepareResizeReflow(aState);
return NS_OK;
}
@ -2264,6 +2265,14 @@ nsBaseIBFrame::ReflowInlineFrame(nsBlockReflowState& aState,
aState.mReflowStatus = NS_FRAME_NOT_COMPLETE | NS_INLINE_BREAK |
NS_INLINE_BREAK_AFTER | NS_INLINE_MAKE_BREAK_TYPE(breakType);
}
else {
// Mark next line dirty in case SplitLine didn't end up
// pushing any frames.
nsLineBox* next = aLine->mNext;
if ((nsnull != next) && !next->IsBlock()) {
next->MarkDirty();
}
}
}
}
else if (NS_FRAME_IS_NOT_COMPLETE(frameReflowStatus)) {
@ -2299,6 +2308,14 @@ nsBaseIBFrame::ReflowInlineFrame(nsBlockReflowState& aState,
if (NS_FAILED(rv)) {
return rv;
}
if (0 == (BLOCK_IS_INLINE & mFlags)) {
// Mark next line dirty in case SplitLine didn't end up
// pushing any frames.
nsLineBox* next = aLine->mNext;
if ((nsnull != next) && !next->IsBlock()) {
next->MarkDirty();
}
}
}
}
else {
@ -2352,8 +2369,8 @@ nsBaseIBFrame::CreateContinuationFor(nsBlockReflowState& aState,
nsresult
nsBaseIBFrame::SplitLine(nsBlockReflowState& aState,
nsLineBox* aLine,
nsIFrame* aFrame)
nsLineBox* aLine,
nsIFrame* aFrame)
{
PRInt32 pushCount = aLine->ChildCount() -
aState.mInlineReflow->GetCurrentFrameNum();
@ -2955,7 +2972,7 @@ nsBaseIBFrame::AppendNewFrames(nsIPresContext& aPresContext,
nsresult
nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
nsBaseIBFrame* aParentFrame,
nsBaseIBFrame* aParentFrame,
nsIFrame* aNewFrame,
nsIFrame* aPrevSibling)
{
@ -2965,16 +2982,21 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
}
const nsStyleDisplay* display;
aNewFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
aNewFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
const nsStylePosition* position;
aNewFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock = nsLineLayout::TreatFrameAsBlock(display, position)
? LINE_IS_BLOCK : 0;
aNewFrame->GetStyleData(eStyleStruct_Position,
(const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock =
nsLineLayout::TreatFrameAsBlock(display, position)
? LINE_IS_BLOCK
: 0;
// See if we need to move the frame outside of the flow, and insert a
// placeholder frame in its place
nsIFrame* placeholder;
if (MoveFrameOutOfFlow(aPresContext, aNewFrame, display, position, placeholder)) {
if (MoveFrameOutOfFlow(aPresContext, aNewFrame, display, position,
placeholder)) {
// Add the placeholder frame to the flow
aNewFrame = placeholder;
newFrameIsBlock = PR_FALSE; // placeholder frame is always inline
@ -2995,21 +3017,23 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
nsLineBox* line = aParentFrame->mLines;
if (nsnull == aPrevSibling) {
// Insert new frame into the sibling list
aNewFrame->SetNextSibling(line->mFirstChild);
if (nsnull != line) {
aNewFrame->SetNextSibling(line->mFirstChild);
if (line->IsBlock() || newFrameIsBlock) {
// Create a new line
newLine = new nsLineBox(aNewFrame, 1, newFrameIsBlock);
if (nsnull == newLine) {
return NS_ERROR_OUT_OF_MEMORY;
if ((nsnull == line) || line->IsBlock() || newFrameIsBlock) {
// Create a new line
newLine = new nsLineBox(aNewFrame, 1, newFrameIsBlock);
if (nsnull == newLine) {
return NS_ERROR_OUT_OF_MEMORY;
}
newLine->mNext = aParentFrame->mLines;
aParentFrame->mLines = newLine;
} else {
// Insert frame at the front of the line
line->mFirstChild = aNewFrame;
line->mChildCount++;
line->MarkDirty();
}
newLine->mNext = aParentFrame->mLines;
aParentFrame->mLines = newLine;
} else {
// Insert frame at the front of the line
line->mFirstChild = aNewFrame;
line->mChildCount++;
line->MarkDirty();
}
}
else {
@ -3096,28 +3120,43 @@ nsBaseIBFrame::InsertNewFrame(nsIPresContext& aPresContext,
return NS_OK;
}
// XXX this code can't work...rewrite it!
nsresult
nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
nsBaseIBFrame* aParentFrame,
nsIFrame* aDeletedFrame,
nsIFrame* aPrevSibling)
nsIFrame* aDeletedFrame)
{
// Find the line that contains deletedFrame; we also find the pointer to
// the line.
// Find the line and the previous sibling that contains
// deletedFrame; we also find the pointer to the line.
nsBaseIBFrame* flow = this;
nsLineBox** linep = &flow->mLines;
nsLineBox* line = flow->mLines;
nsLineBox* prevLine = nsnull;
nsIFrame* prevSibling = nsnull;
while (nsnull != line) {
if (line->Contains(aDeletedFrame)) {
break;
nsIFrame* frame = line->mFirstChild;
PRInt32 n = line->ChildCount();
while (--n >= 0) {
if (frame == aDeletedFrame) {
goto found_frame;
}
prevSibling = frame;
frame->GetNextSibling(frame);
}
linep = &line->mNext;
prevLine = line;
line = line->mNext;
}
found_frame:;
#ifdef NS_DEBUG
NS_ASSERTION(nsnull != line, "can't find deleted frame in lines");
if (nsnull != prevSibling) {
nsIFrame* tmp;
prevSibling->GetNextSibling(tmp);
NS_ASSERTION(tmp == aDeletedFrame, "bad prevSibling");
}
#endif
// Remove frame and its continuations
// Remove frame and all of its continuations
while (nsnull != aDeletedFrame) {
while ((nsnull != line) && (nsnull != aDeletedFrame)) {
#ifdef NS_DEBUG
@ -3151,18 +3190,26 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
}
}
// Get the deleted frames next sibling
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
// Remove aDeletedFrame from the line
if (line->mFirstChild == aDeletedFrame) {
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
line->mFirstChild = nextFrame;
if (!line->IsBlock() && (nsnull != prevLine) && !prevLine->IsBlock()) {
// Make sure the previous line (if it's an inline line) gets
// a reflow too so that it can pullup from the line where we
// just removed the frame.
prevLine->MarkDirty();
}
}
// Take aDeletedFrame out of the sibling list
if (nsnull != aPrevSibling) {
nsIFrame* nextFrame;
aDeletedFrame->GetNextSibling(nextFrame);
aPrevSibling->SetNextSibling(nextFrame);
// Take aDeletedFrame out of the sibling list. Note that
// prevSibling will only be nsnull when we are deleting the very
// first frame.
if (nsnull != prevSibling) {
prevSibling->SetNextSibling(nextFrame);
}
// Destroy frame; capture its next-in-flow first in case we need
@ -3174,8 +3221,6 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
}
aDeletedFrame->DeleteFrame(aState.mPresContext);
aDeletedFrame = nextInFlow;
// XXX If next-in-flow is != next-sibling then we need to break
// out of this loop
// If line is empty, remove it now
nsLineBox* next = line->mNext;
@ -3185,17 +3230,36 @@ nsBaseIBFrame::DoRemoveFrame(nsBlockReflowState& aState,
delete line;
}
else {
line->MarkDirty();
linep = &line->mNext;
}
prevLine = line;
line = next;
// See if we should keep looking in the current flow's line list.
if (nsnull != aDeletedFrame) {
if (aDeletedFrame != nextFrame) {
// The deceased frames continuation is not the next frame in
// the current flow's frame list. Therefore we know that the
// continuation is in a different parent. So break out of
// the loop so that we advance to the next parent.
#ifdef NS_DEBUG
nsIFrame* contParent;
aDeletedFrame->GetContentParent(contParent);
NS_ASSERTION(contParent != flow, "strange continuation");
#endif
break;
}
}
}
// Advance to next flow block if the frame has more continuations
if (nsnull != aDeletedFrame) {
flow = (nsBaseIBFrame*) flow->mNextInFlow;
NS_ASSERTION(nsnull != flow, "whoops, continuation without a parent");
prevLine = nsnull;
line = flow->mLines;
aPrevSibling = nsnull;
prevSibling = nsnull;
}
}
return NS_OK;