1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/generic/nsFrameList.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,550 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsFrameList.h" 1.10 +#include "nsIFrame.h" 1.11 +#include "nsLayoutUtils.h" 1.12 +#include "nsPresContext.h" 1.13 +#include "nsIPresShell.h" 1.14 + 1.15 +#include "nsGkAtoms.h" 1.16 +#include "nsILineIterator.h" 1.17 +#include "nsBidiPresUtils.h" 1.18 + 1.19 +namespace mozilla { 1.20 +namespace layout { 1.21 +namespace detail { 1.22 +const AlignedFrameListBytes gEmptyFrameListBytes = { 0 }; 1.23 +} 1.24 +} 1.25 +} 1.26 + 1.27 +void* 1.28 +nsFrameList::operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW 1.29 +{ 1.30 + return aPresShell->AllocateByObjectID(nsPresArena::nsFrameList_id, sz); 1.31 +} 1.32 + 1.33 +void 1.34 +nsFrameList::Delete(nsIPresShell* aPresShell) 1.35 +{ 1.36 + NS_PRECONDITION(this != &EmptyList(), "Shouldn't Delete() this list"); 1.37 + NS_ASSERTION(IsEmpty(), "Shouldn't Delete() a non-empty list"); 1.38 + 1.39 + aPresShell->FreeByObjectID(nsPresArena::nsFrameList_id, this); 1.40 +} 1.41 + 1.42 +void 1.43 +nsFrameList::DestroyFrames() 1.44 +{ 1.45 + while (nsIFrame* frame = RemoveFirstChild()) { 1.46 + frame->Destroy(); 1.47 + } 1.48 + mLastChild = nullptr; 1.49 +} 1.50 + 1.51 +void 1.52 +nsFrameList::DestroyFramesFrom(nsIFrame* aDestructRoot) 1.53 +{ 1.54 + NS_PRECONDITION(aDestructRoot, "Missing destruct root"); 1.55 + 1.56 + while (nsIFrame* frame = RemoveFirstChild()) { 1.57 + frame->DestroyFrom(aDestructRoot); 1.58 + } 1.59 + mLastChild = nullptr; 1.60 +} 1.61 + 1.62 +void 1.63 +nsFrameList::SetFrames(nsIFrame* aFrameList) 1.64 +{ 1.65 + NS_PRECONDITION(!mFirstChild, "Losing frames"); 1.66 + 1.67 + mFirstChild = aFrameList; 1.68 + mLastChild = nsLayoutUtils::GetLastSibling(mFirstChild); 1.69 +} 1.70 + 1.71 +void 1.72 +nsFrameList::RemoveFrame(nsIFrame* aFrame) 1.73 +{ 1.74 + NS_PRECONDITION(aFrame, "null ptr"); 1.75 +#ifdef DEBUG_FRAME_LIST 1.76 + // ContainsFrame is O(N) 1.77 + NS_PRECONDITION(ContainsFrame(aFrame), "wrong list"); 1.78 +#endif 1.79 + 1.80 + nsIFrame* nextFrame = aFrame->GetNextSibling(); 1.81 + if (aFrame == mFirstChild) { 1.82 + mFirstChild = nextFrame; 1.83 + aFrame->SetNextSibling(nullptr); 1.84 + if (!nextFrame) { 1.85 + mLastChild = nullptr; 1.86 + } 1.87 + } 1.88 + else { 1.89 + nsIFrame* prevSibling = aFrame->GetPrevSibling(); 1.90 + NS_ASSERTION(prevSibling && prevSibling->GetNextSibling() == aFrame, 1.91 + "Broken frame linkage"); 1.92 + prevSibling->SetNextSibling(nextFrame); 1.93 + aFrame->SetNextSibling(nullptr); 1.94 + if (!nextFrame) { 1.95 + mLastChild = prevSibling; 1.96 + } 1.97 + } 1.98 +} 1.99 + 1.100 +nsFrameList 1.101 +nsFrameList::RemoveFramesAfter(nsIFrame* aAfterFrame) 1.102 +{ 1.103 + if (!aAfterFrame) { 1.104 + nsFrameList result; 1.105 + result.InsertFrames(nullptr, nullptr, *this); 1.106 + return result; 1.107 + } 1.108 + 1.109 + NS_PRECONDITION(NotEmpty(), "illegal operation on empty list"); 1.110 +#ifdef DEBUG_FRAME_LIST 1.111 + NS_PRECONDITION(ContainsFrame(aAfterFrame), "wrong list"); 1.112 +#endif 1.113 + 1.114 + nsIFrame* tail = aAfterFrame->GetNextSibling(); 1.115 + // if (!tail) return EmptyList(); -- worth optimizing this case? 1.116 + nsIFrame* oldLastChild = mLastChild; 1.117 + mLastChild = aAfterFrame; 1.118 + aAfterFrame->SetNextSibling(nullptr); 1.119 + return nsFrameList(tail, tail ? oldLastChild : nullptr); 1.120 +} 1.121 + 1.122 +nsIFrame* 1.123 +nsFrameList::RemoveFirstChild() 1.124 +{ 1.125 + if (mFirstChild) { 1.126 + nsIFrame* firstChild = mFirstChild; 1.127 + RemoveFrame(firstChild); 1.128 + return firstChild; 1.129 + } 1.130 + return nullptr; 1.131 +} 1.132 + 1.133 +void 1.134 +nsFrameList::DestroyFrame(nsIFrame* aFrame) 1.135 +{ 1.136 + NS_PRECONDITION(aFrame, "null ptr"); 1.137 + RemoveFrame(aFrame); 1.138 + aFrame->Destroy(); 1.139 +} 1.140 + 1.141 +nsFrameList::Slice 1.142 +nsFrameList::InsertFrames(nsIFrame* aParent, nsIFrame* aPrevSibling, 1.143 + nsFrameList& aFrameList) 1.144 +{ 1.145 + NS_PRECONDITION(aFrameList.NotEmpty(), "Unexpected empty list"); 1.146 + 1.147 + if (aParent) { 1.148 + aFrameList.ApplySetParent(aParent); 1.149 + } 1.150 + 1.151 + NS_ASSERTION(IsEmpty() || 1.152 + FirstChild()->GetParent() == aFrameList.FirstChild()->GetParent(), 1.153 + "frame to add has different parent"); 1.154 + NS_ASSERTION(!aPrevSibling || 1.155 + aPrevSibling->GetParent() == aFrameList.FirstChild()->GetParent(), 1.156 + "prev sibling has different parent"); 1.157 +#ifdef DEBUG_FRAME_LIST 1.158 + // ContainsFrame is O(N) 1.159 + NS_ASSERTION(!aPrevSibling || ContainsFrame(aPrevSibling), 1.160 + "prev sibling is not on this list"); 1.161 +#endif 1.162 + 1.163 + nsIFrame* firstNewFrame = aFrameList.FirstChild(); 1.164 + nsIFrame* nextSibling; 1.165 + if (aPrevSibling) { 1.166 + nextSibling = aPrevSibling->GetNextSibling(); 1.167 + aPrevSibling->SetNextSibling(firstNewFrame); 1.168 + } 1.169 + else { 1.170 + nextSibling = mFirstChild; 1.171 + mFirstChild = firstNewFrame; 1.172 + } 1.173 + 1.174 + nsIFrame* lastNewFrame = aFrameList.LastChild(); 1.175 + lastNewFrame->SetNextSibling(nextSibling); 1.176 + if (!nextSibling) { 1.177 + mLastChild = lastNewFrame; 1.178 + } 1.179 + 1.180 + VerifyList(); 1.181 + 1.182 + aFrameList.Clear(); 1.183 + return Slice(*this, firstNewFrame, nextSibling); 1.184 +} 1.185 + 1.186 +nsFrameList 1.187 +nsFrameList::ExtractHead(FrameLinkEnumerator& aLink) 1.188 +{ 1.189 + NS_PRECONDITION(&aLink.List() == this, "Unexpected list"); 1.190 + NS_PRECONDITION(!aLink.PrevFrame() || 1.191 + aLink.PrevFrame()->GetNextSibling() == 1.192 + aLink.NextFrame(), 1.193 + "Unexpected PrevFrame()"); 1.194 + NS_PRECONDITION(aLink.PrevFrame() || 1.195 + aLink.NextFrame() == FirstChild(), 1.196 + "Unexpected NextFrame()"); 1.197 + NS_PRECONDITION(!aLink.PrevFrame() || 1.198 + aLink.NextFrame() != FirstChild(), 1.199 + "Unexpected NextFrame()"); 1.200 + NS_PRECONDITION(aLink.mEnd == nullptr, 1.201 + "Unexpected mEnd for frame link enumerator"); 1.202 + 1.203 + nsIFrame* prev = aLink.PrevFrame(); 1.204 + nsIFrame* newFirstFrame = nullptr; 1.205 + if (prev) { 1.206 + // Truncate the list after |prev| and hand the first part to our new list. 1.207 + prev->SetNextSibling(nullptr); 1.208 + newFirstFrame = mFirstChild; 1.209 + mFirstChild = aLink.NextFrame(); 1.210 + if (!mFirstChild) { // we handed over the whole list 1.211 + mLastChild = nullptr; 1.212 + } 1.213 + 1.214 + // Now make sure aLink doesn't point to a frame we no longer have. 1.215 + aLink.mPrev = nullptr; 1.216 + } 1.217 + // else aLink is pointing to before our first frame. Nothing to do. 1.218 + 1.219 + return nsFrameList(newFirstFrame, prev); 1.220 +} 1.221 + 1.222 +nsFrameList 1.223 +nsFrameList::ExtractTail(FrameLinkEnumerator& aLink) 1.224 +{ 1.225 + NS_PRECONDITION(&aLink.List() == this, "Unexpected list"); 1.226 + NS_PRECONDITION(!aLink.PrevFrame() || 1.227 + aLink.PrevFrame()->GetNextSibling() == 1.228 + aLink.NextFrame(), 1.229 + "Unexpected PrevFrame()"); 1.230 + NS_PRECONDITION(aLink.PrevFrame() || 1.231 + aLink.NextFrame() == FirstChild(), 1.232 + "Unexpected NextFrame()"); 1.233 + NS_PRECONDITION(!aLink.PrevFrame() || 1.234 + aLink.NextFrame() != FirstChild(), 1.235 + "Unexpected NextFrame()"); 1.236 + NS_PRECONDITION(aLink.mEnd == nullptr, 1.237 + "Unexpected mEnd for frame link enumerator"); 1.238 + 1.239 + nsIFrame* prev = aLink.PrevFrame(); 1.240 + nsIFrame* newFirstFrame; 1.241 + nsIFrame* newLastFrame; 1.242 + if (prev) { 1.243 + // Truncate the list after |prev| and hand the second part to our new list 1.244 + prev->SetNextSibling(nullptr); 1.245 + newFirstFrame = aLink.NextFrame(); 1.246 + newLastFrame = newFirstFrame ? mLastChild : nullptr; 1.247 + mLastChild = prev; 1.248 + } else { 1.249 + // Hand the whole list over to our new list 1.250 + newFirstFrame = mFirstChild; 1.251 + newLastFrame = mLastChild; 1.252 + Clear(); 1.253 + } 1.254 + 1.255 + // Now make sure aLink doesn't point to a frame we no longer have. 1.256 + aLink.mFrame = nullptr; 1.257 + 1.258 + NS_POSTCONDITION(aLink.AtEnd(), "What's going on here?"); 1.259 + 1.260 + return nsFrameList(newFirstFrame, newLastFrame); 1.261 +} 1.262 + 1.263 +nsIFrame* 1.264 +nsFrameList::FrameAt(int32_t aIndex) const 1.265 +{ 1.266 + NS_PRECONDITION(aIndex >= 0, "invalid arg"); 1.267 + if (aIndex < 0) return nullptr; 1.268 + nsIFrame* frame = mFirstChild; 1.269 + while ((aIndex-- > 0) && frame) { 1.270 + frame = frame->GetNextSibling(); 1.271 + } 1.272 + return frame; 1.273 +} 1.274 + 1.275 +int32_t 1.276 +nsFrameList::IndexOf(nsIFrame* aFrame) const 1.277 +{ 1.278 + int32_t count = 0; 1.279 + for (nsIFrame* f = mFirstChild; f; f = f->GetNextSibling()) { 1.280 + if (f == aFrame) 1.281 + return count; 1.282 + ++count; 1.283 + } 1.284 + return -1; 1.285 +} 1.286 + 1.287 +bool 1.288 +nsFrameList::ContainsFrame(const nsIFrame* aFrame) const 1.289 +{ 1.290 + NS_PRECONDITION(aFrame, "null ptr"); 1.291 + 1.292 + nsIFrame* frame = mFirstChild; 1.293 + while (frame) { 1.294 + if (frame == aFrame) { 1.295 + return true; 1.296 + } 1.297 + frame = frame->GetNextSibling(); 1.298 + } 1.299 + return false; 1.300 +} 1.301 + 1.302 +int32_t 1.303 +nsFrameList::GetLength() const 1.304 +{ 1.305 + int32_t count = 0; 1.306 + nsIFrame* frame = mFirstChild; 1.307 + while (frame) { 1.308 + count++; 1.309 + frame = frame->GetNextSibling(); 1.310 + } 1.311 + return count; 1.312 +} 1.313 + 1.314 +void 1.315 +nsFrameList::ApplySetParent(nsIFrame* aParent) const 1.316 +{ 1.317 + NS_ASSERTION(aParent, "null ptr"); 1.318 + 1.319 + for (nsIFrame* f = FirstChild(); f; f = f->GetNextSibling()) { 1.320 + f->SetParent(aParent); 1.321 + } 1.322 +} 1.323 + 1.324 +/* static */ void 1.325 +nsFrameList::UnhookFrameFromSiblings(nsIFrame* aFrame) 1.326 +{ 1.327 + MOZ_ASSERT(aFrame->GetPrevSibling() && aFrame->GetNextSibling()); 1.328 + nsIFrame* const nextSibling = aFrame->GetNextSibling(); 1.329 + nsIFrame* const prevSibling = aFrame->GetPrevSibling(); 1.330 + aFrame->SetNextSibling(nullptr); 1.331 + prevSibling->SetNextSibling(nextSibling); 1.332 + MOZ_ASSERT(!aFrame->GetPrevSibling() && !aFrame->GetNextSibling()); 1.333 +} 1.334 + 1.335 +#ifdef DEBUG_FRAME_DUMP 1.336 +void 1.337 +nsFrameList::List(FILE* out) const 1.338 +{ 1.339 + fprintf_stderr(out, "<\n"); 1.340 + for (nsIFrame* frame = mFirstChild; frame; 1.341 + frame = frame->GetNextSibling()) { 1.342 + frame->List(out, " "); 1.343 + } 1.344 + fprintf_stderr(out, ">\n"); 1.345 +} 1.346 +#endif 1.347 + 1.348 +nsIFrame* 1.349 +nsFrameList::GetPrevVisualFor(nsIFrame* aFrame) const 1.350 +{ 1.351 + if (!mFirstChild) 1.352 + return nullptr; 1.353 + 1.354 + nsIFrame* parent = mFirstChild->GetParent(); 1.355 + if (!parent) 1.356 + return aFrame ? aFrame->GetPrevSibling() : LastChild(); 1.357 + 1.358 + nsBidiLevel baseLevel = nsBidiPresUtils::GetFrameBaseLevel(mFirstChild); 1.359 + 1.360 + nsAutoLineIterator iter = parent->GetLineIterator(); 1.361 + if (!iter) { 1.362 + // Parent is not a block Frame 1.363 + if (parent->GetType() == nsGkAtoms::lineFrame) { 1.364 + // Line frames are not bidi-splittable, so need to consider bidi reordering 1.365 + if (baseLevel == NSBIDI_LTR) { 1.366 + return nsBidiPresUtils::GetFrameToLeftOf(aFrame, mFirstChild, -1); 1.367 + } else { // RTL 1.368 + return nsBidiPresUtils::GetFrameToRightOf(aFrame, mFirstChild, -1); 1.369 + } 1.370 + } else { 1.371 + // Just get the next or prev sibling, depending on block and frame direction. 1.372 + nsBidiLevel frameEmbeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(mFirstChild); 1.373 + if ((frameEmbeddingLevel & 1) == (baseLevel & 1)) { 1.374 + return aFrame ? aFrame->GetPrevSibling() : LastChild(); 1.375 + } else { 1.376 + return aFrame ? aFrame->GetNextSibling() : mFirstChild; 1.377 + } 1.378 + } 1.379 + } 1.380 + 1.381 + // Parent is a block frame, so use the LineIterator to find the previous visual 1.382 + // sibling on this line, or the last one on the previous line. 1.383 + 1.384 + int32_t thisLine; 1.385 + if (aFrame) { 1.386 + thisLine = iter->FindLineContaining(aFrame); 1.387 + if (thisLine < 0) 1.388 + return nullptr; 1.389 + } else { 1.390 + thisLine = iter->GetNumLines(); 1.391 + } 1.392 + 1.393 + nsIFrame* frame = nullptr; 1.394 + nsIFrame* firstFrameOnLine; 1.395 + int32_t numFramesOnLine; 1.396 + nsRect lineBounds; 1.397 + uint32_t lineFlags; 1.398 + 1.399 + if (aFrame) { 1.400 + iter->GetLine(thisLine, &firstFrameOnLine, &numFramesOnLine, lineBounds, &lineFlags); 1.401 + 1.402 + if (baseLevel == NSBIDI_LTR) { 1.403 + frame = nsBidiPresUtils::GetFrameToLeftOf(aFrame, firstFrameOnLine, numFramesOnLine); 1.404 + } else { // RTL 1.405 + frame = nsBidiPresUtils::GetFrameToRightOf(aFrame, firstFrameOnLine, numFramesOnLine); 1.406 + } 1.407 + } 1.408 + 1.409 + if (!frame && thisLine > 0) { 1.410 + // Get the last frame of the previous line 1.411 + iter->GetLine(thisLine - 1, &firstFrameOnLine, &numFramesOnLine, lineBounds, &lineFlags); 1.412 + 1.413 + if (baseLevel == NSBIDI_LTR) { 1.414 + frame = nsBidiPresUtils::GetFrameToLeftOf(nullptr, firstFrameOnLine, numFramesOnLine); 1.415 + } else { // RTL 1.416 + frame = nsBidiPresUtils::GetFrameToRightOf(nullptr, firstFrameOnLine, numFramesOnLine); 1.417 + } 1.418 + } 1.419 + return frame; 1.420 +} 1.421 + 1.422 +nsIFrame* 1.423 +nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const 1.424 +{ 1.425 + if (!mFirstChild) 1.426 + return nullptr; 1.427 + 1.428 + nsIFrame* parent = mFirstChild->GetParent(); 1.429 + if (!parent) 1.430 + return aFrame ? aFrame->GetPrevSibling() : mFirstChild; 1.431 + 1.432 + nsBidiLevel baseLevel = nsBidiPresUtils::GetFrameBaseLevel(mFirstChild); 1.433 + 1.434 + nsAutoLineIterator iter = parent->GetLineIterator(); 1.435 + if (!iter) { 1.436 + // Parent is not a block Frame 1.437 + if (parent->GetType() == nsGkAtoms::lineFrame) { 1.438 + // Line frames are not bidi-splittable, so need to consider bidi reordering 1.439 + if (baseLevel == NSBIDI_LTR) { 1.440 + return nsBidiPresUtils::GetFrameToRightOf(aFrame, mFirstChild, -1); 1.441 + } else { // RTL 1.442 + return nsBidiPresUtils::GetFrameToLeftOf(aFrame, mFirstChild, -1); 1.443 + } 1.444 + } else { 1.445 + // Just get the next or prev sibling, depending on block and frame direction. 1.446 + nsBidiLevel frameEmbeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(mFirstChild); 1.447 + if ((frameEmbeddingLevel & 1) == (baseLevel & 1)) { 1.448 + return aFrame ? aFrame->GetNextSibling() : mFirstChild; 1.449 + } else { 1.450 + return aFrame ? aFrame->GetPrevSibling() : LastChild(); 1.451 + } 1.452 + } 1.453 + } 1.454 + 1.455 + // Parent is a block frame, so use the LineIterator to find the next visual 1.456 + // sibling on this line, or the first one on the next line. 1.457 + 1.458 + int32_t thisLine; 1.459 + if (aFrame) { 1.460 + thisLine = iter->FindLineContaining(aFrame); 1.461 + if (thisLine < 0) 1.462 + return nullptr; 1.463 + } else { 1.464 + thisLine = -1; 1.465 + } 1.466 + 1.467 + nsIFrame* frame = nullptr; 1.468 + nsIFrame* firstFrameOnLine; 1.469 + int32_t numFramesOnLine; 1.470 + nsRect lineBounds; 1.471 + uint32_t lineFlags; 1.472 + 1.473 + if (aFrame) { 1.474 + iter->GetLine(thisLine, &firstFrameOnLine, &numFramesOnLine, lineBounds, &lineFlags); 1.475 + 1.476 + if (baseLevel == NSBIDI_LTR) { 1.477 + frame = nsBidiPresUtils::GetFrameToRightOf(aFrame, firstFrameOnLine, numFramesOnLine); 1.478 + } else { // RTL 1.479 + frame = nsBidiPresUtils::GetFrameToLeftOf(aFrame, firstFrameOnLine, numFramesOnLine); 1.480 + } 1.481 + } 1.482 + 1.483 + int32_t numLines = iter->GetNumLines(); 1.484 + if (!frame && thisLine < numLines - 1) { 1.485 + // Get the first frame of the next line 1.486 + iter->GetLine(thisLine + 1, &firstFrameOnLine, &numFramesOnLine, lineBounds, &lineFlags); 1.487 + 1.488 + if (baseLevel == NSBIDI_LTR) { 1.489 + frame = nsBidiPresUtils::GetFrameToRightOf(nullptr, firstFrameOnLine, numFramesOnLine); 1.490 + } else { // RTL 1.491 + frame = nsBidiPresUtils::GetFrameToLeftOf(nullptr, firstFrameOnLine, numFramesOnLine); 1.492 + } 1.493 + } 1.494 + return frame; 1.495 +} 1.496 + 1.497 +#ifdef DEBUG_FRAME_LIST 1.498 +void 1.499 +nsFrameList::VerifyList() const 1.500 +{ 1.501 + NS_ASSERTION((mFirstChild == nullptr) == (mLastChild == nullptr), 1.502 + "bad list state"); 1.503 + 1.504 + if (IsEmpty()) { 1.505 + return; 1.506 + } 1.507 + 1.508 + // Simple algorithm to find a loop in a linked list -- advance pointers 1.509 + // through it at speeds of 1 and 2, and if they ever get to be equal bail 1.510 + NS_ASSERTION(!mFirstChild->GetPrevSibling(), "bad prev sibling pointer"); 1.511 + nsIFrame *first = mFirstChild, *second = mFirstChild; 1.512 + for (;;) { 1.513 + first = first->GetNextSibling(); 1.514 + second = second->GetNextSibling(); 1.515 + if (!second) { 1.516 + break; 1.517 + } 1.518 + NS_ASSERTION(second->GetPrevSibling()->GetNextSibling() == second, 1.519 + "bad prev sibling pointer"); 1.520 + second = second->GetNextSibling(); 1.521 + if (first == second) { 1.522 + // Loop detected! Since second advances faster, they can't both be null; 1.523 + // we would have broken out of the loop long ago. 1.524 + NS_ERROR("loop in frame list. This will probably hang soon."); 1.525 + return; 1.526 + } 1.527 + if (!second) { 1.528 + break; 1.529 + } 1.530 + NS_ASSERTION(second->GetPrevSibling()->GetNextSibling() == second, 1.531 + "bad prev sibling pointer"); 1.532 + } 1.533 + 1.534 + NS_ASSERTION(mLastChild == nsLayoutUtils::GetLastSibling(mFirstChild), 1.535 + "bogus mLastChild"); 1.536 + // XXX we should also assert that all GetParent() are either null or 1.537 + // the same non-null value, but nsCSSFrameConstructor::nsFrameItems 1.538 + // prevents that, e.g. table captions. 1.539 +} 1.540 +#endif 1.541 + 1.542 +namespace mozilla { 1.543 +namespace layout { 1.544 + 1.545 +AutoFrameListPtr::~AutoFrameListPtr() 1.546 +{ 1.547 + if (mFrameList) { 1.548 + mFrameList->Delete(mPresContext->PresShell()); 1.549 + } 1.550 +} 1.551 + 1.552 +} 1.553 +}