/src/mozilla-central/layout/generic/nsFrameList.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef nsFrameList_h___ |
8 | | #define nsFrameList_h___ |
9 | | |
10 | | #include <stdio.h> /* for FILE* */ |
11 | | #include "nsDebug.h" |
12 | | #include "nsTArray.h" |
13 | | #include "mozilla/FunctionTypeTraits.h" |
14 | | #include "mozilla/RefPtr.h" |
15 | | #include "mozilla/ReverseIterator.h" |
16 | | |
17 | | #if defined(DEBUG) || defined(MOZ_DUMP_PAINTING) |
18 | | // DEBUG_FRAME_DUMP enables nsIFrame::List and related methods. |
19 | | // You can also define this in a non-DEBUG build if you need frame dumps. |
20 | | #define DEBUG_FRAME_DUMP 1 |
21 | | #endif |
22 | | |
23 | | class nsContainerFrame; |
24 | | class nsIContent; |
25 | | class nsIFrame; |
26 | | class nsIPresShell; |
27 | | class nsPresContext; |
28 | | |
29 | | namespace mozilla { |
30 | | namespace layout { |
31 | | class FrameChildList; |
32 | | enum FrameChildListID { |
33 | | // The individual concrete child lists. |
34 | | kPrincipalList = 0x1, |
35 | | kPopupList = 0x2, |
36 | | kCaptionList = 0x4, |
37 | | kColGroupList = 0x8, |
38 | | kSelectPopupList = 0x10, |
39 | | kAbsoluteList = 0x20, |
40 | | kFixedList = 0x40, |
41 | | kOverflowList = 0x80, |
42 | | kOverflowContainersList = 0x100, |
43 | | kExcessOverflowContainersList = 0x200, |
44 | | kOverflowOutOfFlowList = 0x400, |
45 | | kFloatList = 0x800, |
46 | | kBulletList = 0x1000, |
47 | | kPushedFloatsList = 0x2000, |
48 | | kBackdropList = 0x4000, |
49 | | // A special alias for kPrincipalList that suppress the reflow request that |
50 | | // is normally done when manipulating child lists. |
51 | | kNoReflowPrincipalList = 0x8000 |
52 | | }; |
53 | | |
54 | | // A helper class for nsIFrame::Destroy[From]. It's defined here because |
55 | | // nsFrameList needs it and we can't use nsIFrame here. |
56 | | struct PostFrameDestroyData { |
57 | | PostFrameDestroyData(const PostFrameDestroyData&) = delete; |
58 | 0 | PostFrameDestroyData() = default; |
59 | | |
60 | | AutoTArray<RefPtr<nsIContent>, 100> mAnonymousContent; |
61 | | void AddAnonymousContent(already_AddRefed<nsIContent>&& aContent) |
62 | 0 | { |
63 | 0 | mAnonymousContent.AppendElement(aContent); |
64 | 0 | } |
65 | | }; |
66 | | } // namespace layout |
67 | | } // namespace mozilla |
68 | | |
69 | | // Uncomment this to enable expensive frame-list integrity checking |
70 | | // #define DEBUG_FRAME_LIST |
71 | | |
72 | | /** |
73 | | * A class for managing a list of frames. |
74 | | */ |
75 | | class nsFrameList { |
76 | | public: |
77 | | nsFrameList() : |
78 | | mFirstChild(nullptr), mLastChild(nullptr) |
79 | 0 | { |
80 | 0 | } |
81 | | |
82 | | nsFrameList(nsIFrame* aFirstFrame, nsIFrame* aLastFrame) : |
83 | | mFirstChild(aFirstFrame), mLastChild(aLastFrame) |
84 | 0 | { |
85 | 0 | VerifyList(); |
86 | 0 | } |
87 | | |
88 | | nsFrameList(const nsFrameList& aOther) : |
89 | | mFirstChild(aOther.mFirstChild), mLastChild(aOther.mLastChild) |
90 | 0 | { |
91 | 0 | } |
92 | | |
93 | | /** |
94 | | * Infallibly allocate a nsFrameList from the shell arena. |
95 | | */ |
96 | | void* operator new(size_t sz, nsIPresShell* aPresShell); |
97 | | |
98 | | /** |
99 | | * Deallocate this list that was allocated from the shell arena. |
100 | | * The list is required to be empty. |
101 | | */ |
102 | | void Delete(nsIPresShell* aPresShell); |
103 | | |
104 | | /** |
105 | | * For each frame in this list: remove it from the list then call |
106 | | * Destroy() on it. |
107 | | */ |
108 | | void DestroyFrames(); |
109 | | |
110 | | /** |
111 | | * For each frame in this list: remove it from the list then call |
112 | | * DestroyFrom(aDestructRoot, aPostDestroyData) on it. |
113 | | */ |
114 | | void DestroyFramesFrom(nsIFrame* aDestructRoot, |
115 | | mozilla::layout::PostFrameDestroyData& aPostDestroyData); |
116 | | |
117 | 0 | void Clear() { mFirstChild = mLastChild = nullptr; } |
118 | | |
119 | | void SetFrames(nsIFrame* aFrameList); |
120 | | |
121 | 0 | void SetFrames(nsFrameList& aFrameList) { |
122 | 0 | MOZ_ASSERT(!mFirstChild, "Losing frames"); |
123 | 0 |
|
124 | 0 | mFirstChild = aFrameList.FirstChild(); |
125 | 0 | mLastChild = aFrameList.LastChild(); |
126 | 0 | aFrameList.Clear(); |
127 | 0 | } |
128 | | |
129 | | class Slice; |
130 | | |
131 | | /** |
132 | | * Append aFrameList to this list. If aParent is not null, |
133 | | * reparents the newly added frames. Clears out aFrameList and |
134 | | * returns a list slice represening the newly-appended frames. |
135 | | */ |
136 | 0 | Slice AppendFrames(nsContainerFrame* aParent, nsFrameList& aFrameList) { |
137 | 0 | return InsertFrames(aParent, LastChild(), aFrameList); |
138 | 0 | } |
139 | | |
140 | | |
141 | | /** |
142 | | * Append aFrame to this list. If aParent is not null, |
143 | | * reparents the newly added frame. |
144 | | */ |
145 | 0 | void AppendFrame(nsContainerFrame* aParent, nsIFrame* aFrame) { |
146 | 0 | nsFrameList temp(aFrame, aFrame); |
147 | 0 | AppendFrames(aParent, temp); |
148 | 0 | } |
149 | | |
150 | | /** |
151 | | * Take aFrame out of the frame list. This also disconnects aFrame |
152 | | * from the sibling list. The frame must be non-null and present on |
153 | | * this list. |
154 | | */ |
155 | | void RemoveFrame(nsIFrame* aFrame); |
156 | | |
157 | | /** |
158 | | * Take the frames after aAfterFrame out of the frame list. If |
159 | | * aAfterFrame is null, removes the entire list. |
160 | | * @param aAfterFrame a frame in this list, or null |
161 | | * @return the removed frames, if any |
162 | | */ |
163 | | nsFrameList RemoveFramesAfter(nsIFrame* aAfterFrame); |
164 | | |
165 | | /** |
166 | | * Take the first frame (if any) out of the frame list. |
167 | | * @return the first child, or nullptr if the list is empty |
168 | | */ |
169 | | nsIFrame* RemoveFirstChild(); |
170 | | |
171 | | /** |
172 | | * The following two functions are intended to be used in concert for |
173 | | * removing a frame from its frame list when the set of possible frame |
174 | | * lists is known in advance, but the exact frame list is unknown. |
175 | | * aFrame must be non-null. |
176 | | * Example use: |
177 | | * bool removed = frameList1.StartRemoveFrame(aFrame) || |
178 | | * frameList2.ContinueRemoveFrame(aFrame) || |
179 | | * frameList3.ContinueRemoveFrame(aFrame); |
180 | | * MOZ_ASSERT(removed); |
181 | | * |
182 | | * @note One of the frame lists MUST contain aFrame, if it's on some other |
183 | | * frame list then the example above will likely lead to crashes. |
184 | | * This function is O(1). |
185 | | * @return true iff aFrame was removed from /some/ list, not necessarily |
186 | | * this one. If it was removed from a different list then it is |
187 | | * guaranteed that that list is still non-empty. |
188 | | * (this method is implemented in nsIFrame.h to be able to inline) |
189 | | */ |
190 | | inline bool StartRemoveFrame(nsIFrame* aFrame); |
191 | | |
192 | | /** |
193 | | * Precondition: StartRemoveFrame MUST be called before this. |
194 | | * This function is O(1). |
195 | | * @see StartRemoveFrame |
196 | | * @return true iff aFrame was removed from this list |
197 | | * (this method is implemented in nsIFrame.h to be able to inline) |
198 | | */ |
199 | | inline bool ContinueRemoveFrame(nsIFrame* aFrame); |
200 | | |
201 | | /** |
202 | | * Take aFrame out of the frame list and then destroy it. |
203 | | * The frame must be non-null and present on this list. |
204 | | */ |
205 | | void DestroyFrame(nsIFrame* aFrame); |
206 | | |
207 | | /** |
208 | | * Insert aFrame right after aPrevSibling, or prepend it to this |
209 | | * list if aPrevSibling is null. If aParent is not null, also |
210 | | * reparents newly-added frame. Note that this method always |
211 | | * sets the frame's nextSibling pointer. |
212 | | */ |
213 | | void InsertFrame(nsContainerFrame* aParent, nsIFrame* aPrevSibling, |
214 | 0 | nsIFrame* aFrame) { |
215 | 0 | nsFrameList temp(aFrame, aFrame); |
216 | 0 | InsertFrames(aParent, aPrevSibling, temp); |
217 | 0 | } |
218 | | |
219 | | |
220 | | /** |
221 | | * Inserts aFrameList into this list after aPrevSibling (at the beginning if |
222 | | * aPrevSibling is null). If aParent is not null, reparents the newly added |
223 | | * frames. Clears out aFrameList and returns a list slice representing the |
224 | | * newly-inserted frames. |
225 | | */ |
226 | | Slice InsertFrames(nsContainerFrame* aParent, nsIFrame* aPrevSibling, |
227 | | nsFrameList& aFrameList); |
228 | | |
229 | | class FrameLinkEnumerator; |
230 | | |
231 | | /** |
232 | | * Split this list just before the first frame that matches aPredicate, |
233 | | * and return a nsFrameList containing all the frames before it. The |
234 | | * matched frame and all frames after it stay in this list. If no matched |
235 | | * frame exists, all the frames are drained into the returned list, and |
236 | | * this list ends up empty. |
237 | | * |
238 | | * aPredicate should be of this function signature: bool(nsIFrame*). |
239 | | */ |
240 | | template<typename Predicate> |
241 | 0 | nsFrameList Split(Predicate&& aPredicate) { |
242 | 0 | static_assert( |
243 | 0 | std::is_same<typename mozilla::FunctionTypeTraits<Predicate>::ReturnType, |
244 | 0 | bool>::value && |
245 | 0 | mozilla::FunctionTypeTraits<Predicate>::arity == 1 && |
246 | 0 | std::is_same<typename mozilla::FunctionTypeTraits<Predicate>::template ParameterType<0>, |
247 | 0 | nsIFrame*>::value, |
248 | 0 | "aPredicate should be of this function signature: bool(nsIFrame*)"); |
249 | 0 |
|
250 | 0 | FrameLinkEnumerator link(*this); |
251 | 0 | link.Find(aPredicate); |
252 | 0 | return ExtractHead(link); |
253 | 0 | } Unexecuted instantiation: Unified_cpp_layout_base1.cpp:nsFrameList nsFrameList::Split<nsCSSFrameConstructor::AppendFramesToParent(nsFrameConstructorState&, nsContainerFrame*, nsFrameItems&, nsIFrame*, bool)::$_3>(nsCSSFrameConstructor::AppendFramesToParent(nsFrameConstructorState&, nsContainerFrame*, nsFrameItems&, nsIFrame*, bool)::$_3&&) Unexecuted instantiation: Unified_cpp_layout_base1.cpp:nsFrameList nsFrameList::Split<nsCSSFrameConstructor::AppendFramesToParent(nsFrameConstructorState&, nsContainerFrame*, nsFrameItems&, nsIFrame*, bool)::$_4>(nsCSSFrameConstructor::AppendFramesToParent(nsFrameConstructorState&, nsContainerFrame*, nsFrameItems&, nsIFrame*, bool)::$_4&&) Unexecuted instantiation: Unified_cpp_layout_base1.cpp:nsFrameList nsFrameList::Split<nsCSSFrameConstructor::WrapFramesInFirstLineFrame(nsFrameConstructorState&, nsIContent*, nsContainerFrame*, nsFirstLineFrame*, nsFrameItems&)::$_7>(nsCSSFrameConstructor::WrapFramesInFirstLineFrame(nsFrameConstructorState&, nsIContent*, nsContainerFrame*, nsFirstLineFrame*, nsFrameItems&)::$_7&&) Unexecuted instantiation: Unified_cpp_layout_base1.cpp:nsFrameList nsFrameList::Split<nsCSSFrameConstructor::CreateIBSiblings(nsFrameConstructorState&, nsContainerFrame*, bool, nsFrameItems&, nsFrameItems&)::$_9>(nsCSSFrameConstructor::CreateIBSiblings(nsFrameConstructorState&, nsContainerFrame*, bool, nsFrameItems&, nsFrameItems&)::$_9&&) Unexecuted instantiation: Unified_cpp_layout_base1.cpp:nsFrameList nsFrameList::Split<nsCSSFrameConstructor::CreateIBSiblings(nsFrameConstructorState&, nsContainerFrame*, bool, nsFrameItems&, nsFrameItems&)::$_10>(nsCSSFrameConstructor::CreateIBSiblings(nsFrameConstructorState&, nsContainerFrame*, bool, nsFrameItems&, nsFrameItems&)::$_10&&) |
254 | | |
255 | | /** |
256 | | * Split this frame list such that all the frames before the link pointed to |
257 | | * by aLink end up in the returned list, while the remaining frames stay in |
258 | | * this list. After this call, aLink points to the beginning of this list. |
259 | | */ |
260 | | nsFrameList ExtractHead(FrameLinkEnumerator& aLink); |
261 | | |
262 | | /** |
263 | | * Split this frame list such that all the frames coming after the link |
264 | | * pointed to by aLink end up in the returned list, while the frames before |
265 | | * that link stay in this list. After this call, aLink is at end. |
266 | | */ |
267 | | nsFrameList ExtractTail(FrameLinkEnumerator& aLink); |
268 | | |
269 | 0 | nsIFrame* FirstChild() const { |
270 | 0 | return mFirstChild; |
271 | 0 | } |
272 | | |
273 | 0 | nsIFrame* LastChild() const { |
274 | 0 | return mLastChild; |
275 | 0 | } |
276 | | |
277 | | nsIFrame* FrameAt(int32_t aIndex) const; |
278 | | int32_t IndexOf(nsIFrame* aFrame) const; |
279 | | |
280 | 0 | bool IsEmpty() const { |
281 | 0 | return nullptr == mFirstChild; |
282 | 0 | } |
283 | | |
284 | 0 | bool NotEmpty() const { |
285 | 0 | return nullptr != mFirstChild; |
286 | 0 | } |
287 | | |
288 | | bool ContainsFrame(const nsIFrame* aFrame) const; |
289 | | |
290 | | /** |
291 | | * Get the number of frames in this list. Note that currently the |
292 | | * implementation has O(n) time complexity. Do not call it repeatedly in hot |
293 | | * code. |
294 | | */ |
295 | | int32_t GetLength() const; |
296 | | |
297 | | /** |
298 | | * If this frame list has only one frame, return that frame. |
299 | | * Otherwise, return null. |
300 | | */ |
301 | 0 | nsIFrame* OnlyChild() const { |
302 | 0 | if (FirstChild() == LastChild()) { |
303 | 0 | return FirstChild(); |
304 | 0 | } |
305 | 0 | return nullptr; |
306 | 0 | } |
307 | | |
308 | | /** |
309 | | * Call SetParent(aParent) for each frame in this list. |
310 | | * @param aParent the new parent frame, must be non-null |
311 | | */ |
312 | | void ApplySetParent(nsContainerFrame* aParent) const; |
313 | | |
314 | | /** |
315 | | * If this frame list is non-empty then append it to aLists as the |
316 | | * aListID child list. |
317 | | * (this method is implemented in FrameChildList.h for dependency reasons) |
318 | | */ |
319 | | inline void AppendIfNonempty(nsTArray<mozilla::layout::FrameChildList>* aLists, |
320 | | mozilla::layout::FrameChildListID aListID) const; |
321 | | |
322 | | /** |
323 | | * Return the frame before this frame in visual order (after Bidi reordering). |
324 | | * If aFrame is null, return the last frame in visual order. |
325 | | */ |
326 | | nsIFrame* GetPrevVisualFor(nsIFrame* aFrame) const; |
327 | | |
328 | | /** |
329 | | * Return the frame after this frame in visual order (after Bidi reordering). |
330 | | * If aFrame is null, return the first frame in visual order. |
331 | | */ |
332 | | nsIFrame* GetNextVisualFor(nsIFrame* aFrame) const; |
333 | | |
334 | | #ifdef DEBUG_FRAME_DUMP |
335 | | void List(FILE* out) const; |
336 | | #endif |
337 | | |
338 | | static inline const nsFrameList& EmptyList(); |
339 | | |
340 | | class Enumerator; |
341 | | |
342 | | /** |
343 | | * A class representing a slice of a frame list. |
344 | | */ |
345 | | class Slice { |
346 | | friend class Enumerator; |
347 | | |
348 | | public: |
349 | | // Implicit on purpose, so that we can easily create enumerators from |
350 | | // nsFrameList via this impicit constructor. |
351 | | MOZ_IMPLICIT Slice(const nsFrameList& aList) : |
352 | | #ifdef DEBUG |
353 | | mList(aList), |
354 | | #endif |
355 | | mStart(aList.FirstChild()), |
356 | | mEnd(nullptr) |
357 | 0 | {} |
358 | | |
359 | | Slice(const nsFrameList& aList, nsIFrame* aStart, nsIFrame* aEnd) : |
360 | | #ifdef DEBUG |
361 | | mList(aList), |
362 | | #endif |
363 | | mStart(aStart), |
364 | | mEnd(aEnd) |
365 | 0 | {} |
366 | | |
367 | | Slice(const Slice& aOther) : |
368 | | #ifdef DEBUG |
369 | | mList(aOther.mList), |
370 | | #endif |
371 | | mStart(aOther.mStart), |
372 | | mEnd(aOther.mEnd) |
373 | | {} |
374 | | |
375 | | private: |
376 | | #ifdef DEBUG |
377 | | const nsFrameList& mList; |
378 | | #endif |
379 | | nsIFrame* const mStart; // our starting frame |
380 | | const nsIFrame* const mEnd; // The first frame that is NOT in the slice. |
381 | | // May be null. |
382 | | }; |
383 | | |
384 | | class Enumerator { |
385 | | public: |
386 | | explicit Enumerator(const Slice& aSlice) : |
387 | | #ifdef DEBUG |
388 | | mSlice(aSlice), |
389 | | #endif |
390 | | mFrame(aSlice.mStart), |
391 | | mEnd(aSlice.mEnd) |
392 | 0 | {} |
393 | | |
394 | | Enumerator(const Enumerator& aOther) : |
395 | | #ifdef DEBUG |
396 | | mSlice(aOther.mSlice), |
397 | | #endif |
398 | | mFrame(aOther.mFrame), |
399 | | mEnd(aOther.mEnd) |
400 | | {} |
401 | | |
402 | 0 | bool AtEnd() const { |
403 | 0 | // Can't just check mEnd, because some table code goes and destroys the |
404 | 0 | // tail of the frame list (including mEnd!) while iterating over the |
405 | 0 | // frame list. |
406 | 0 | return !mFrame || mFrame == mEnd; |
407 | 0 | } |
408 | | |
409 | | /* Next() needs to know about nsIFrame, and nsIFrame will need to |
410 | | know about nsFrameList methods, so in order to inline this put |
411 | | the implementation in nsIFrame.h */ |
412 | | inline void Next(); |
413 | | |
414 | | /** |
415 | | * Get the current frame we're pointing to. Do not call this on an |
416 | | * iterator that is at end! |
417 | | */ |
418 | 0 | nsIFrame* get() const { |
419 | 0 | MOZ_ASSERT(!AtEnd(), "Enumerator is at end"); |
420 | 0 | return mFrame; |
421 | 0 | } |
422 | | |
423 | | /** |
424 | | * Get an enumerator that is just like this one, but not limited in terms of |
425 | | * the part of the list it will traverse. |
426 | | */ |
427 | 0 | Enumerator GetUnlimitedEnumerator() const { |
428 | 0 | return Enumerator(*this, nullptr); |
429 | 0 | } |
430 | | |
431 | | #ifdef DEBUG |
432 | | const nsFrameList& List() const { return mSlice.mList; } |
433 | | #endif |
434 | | |
435 | | protected: |
436 | | Enumerator(const Enumerator& aOther, const nsIFrame* const aNewEnd): |
437 | | #ifdef DEBUG |
438 | | mSlice(aOther.mSlice), |
439 | | #endif |
440 | | mFrame(aOther.mFrame), |
441 | | mEnd(aNewEnd) |
442 | 0 | {} |
443 | | |
444 | | #ifdef DEBUG |
445 | | /* Has to be an object, not a reference, since the slice could |
446 | | well be a temporary constructed from an nsFrameList */ |
447 | | const Slice mSlice; |
448 | | #endif |
449 | | nsIFrame* mFrame; // our current frame. |
450 | | const nsIFrame* const mEnd; // The first frame we should NOT enumerate. |
451 | | // May be null. |
452 | | }; |
453 | | |
454 | | /** |
455 | | * A class that can be used to enumerate links between frames. When created |
456 | | * from an nsFrameList, it points to the "link" immediately before the first |
457 | | * frame. It can then be advanced until it points to the "link" immediately |
458 | | * after the last frame. At any position, PrevFrame() and NextFrame() are |
459 | | * the frames before and after the given link. This means PrevFrame() is |
460 | | * null when the enumerator is at the beginning of the list and NextFrame() |
461 | | * is null when it's AtEnd(). |
462 | | */ |
463 | | class FrameLinkEnumerator : private Enumerator { |
464 | | public: |
465 | | friend class nsFrameList; |
466 | | |
467 | | explicit FrameLinkEnumerator(const nsFrameList& aList) : |
468 | | Enumerator(aList), |
469 | | mPrev(nullptr) |
470 | 0 | {} |
471 | | |
472 | | FrameLinkEnumerator(const FrameLinkEnumerator& aOther) : |
473 | | Enumerator(aOther), |
474 | | mPrev(aOther.mPrev) |
475 | | {} |
476 | | |
477 | | /* This constructor needs to know about nsIFrame, and nsIFrame will need to |
478 | | know about nsFrameList methods, so in order to inline this put |
479 | | the implementation in nsIFrame.h */ |
480 | | inline FrameLinkEnumerator(const nsFrameList& aList, nsIFrame* aPrevFrame); |
481 | | |
482 | | void operator=(const FrameLinkEnumerator& aOther) { |
483 | | MOZ_ASSERT(&List() == &aOther.List(), "Different lists?"); |
484 | | mFrame = aOther.mFrame; |
485 | | mPrev = aOther.mPrev; |
486 | | } |
487 | | |
488 | | inline void Next(); |
489 | | |
490 | | /** |
491 | | * Find the first frame from the current position that satisfies |
492 | | * aPredicate, and stop at it. If no such frame exists, then this method |
493 | | * advances to the end of the list. |
494 | | * |
495 | | * aPredicate should be of this function signature: bool(nsIFrame*). |
496 | | * |
497 | | * Note: Find() needs to see the definition of Next(), so put this |
498 | | * definition in nsIFrame.h. |
499 | | */ |
500 | | template<typename Predicate> |
501 | | inline void Find(Predicate&& aPredicate); |
502 | | |
503 | 0 | bool AtEnd() const { return Enumerator::AtEnd(); } |
504 | | |
505 | 0 | nsIFrame* PrevFrame() const { return mPrev; } |
506 | 0 | nsIFrame* NextFrame() const { return mFrame; } |
507 | | |
508 | | protected: |
509 | | nsIFrame* mPrev; |
510 | | }; |
511 | | |
512 | | class Iterator |
513 | | { |
514 | | public: |
515 | | Iterator(const nsFrameList& aList, nsIFrame* aCurrent) |
516 | | : mList(aList) |
517 | | , mCurrent(aCurrent) |
518 | 0 | {} |
519 | | |
520 | | Iterator(const Iterator& aOther) |
521 | | : mList(aOther.mList) |
522 | | , mCurrent(aOther.mCurrent) |
523 | 0 | {} |
524 | | |
525 | 0 | nsIFrame* operator*() const { return mCurrent; } |
526 | | |
527 | | // The operators need to know about nsIFrame, hence the |
528 | | // implementations are in nsIFrame.h |
529 | | Iterator& operator++(); |
530 | | Iterator& operator--(); |
531 | | |
532 | | Iterator operator++(int) { auto ret = *this; ++*this; return ret; } |
533 | | Iterator operator--(int) { auto ret = *this; --*this; return ret; } |
534 | | |
535 | | friend bool operator==(const Iterator& aIter1, const Iterator& aIter2); |
536 | | friend bool operator!=(const Iterator& aIter1, const Iterator& aIter2); |
537 | | |
538 | | private: |
539 | | const nsFrameList& mList; |
540 | | nsIFrame* mCurrent; |
541 | | }; |
542 | | |
543 | | typedef Iterator iterator; |
544 | | typedef Iterator const_iterator; |
545 | | typedef mozilla::ReverseIterator<Iterator> reverse_iterator; |
546 | | typedef mozilla::ReverseIterator<Iterator> const_reverse_iterator; |
547 | | |
548 | 0 | iterator begin() const { return iterator(*this, mFirstChild); } |
549 | | const_iterator cbegin() const { return begin(); } |
550 | 0 | iterator end() const { return iterator(*this, nullptr); } |
551 | | const_iterator cend() const { return end(); } |
552 | 0 | reverse_iterator rbegin() const { return reverse_iterator(end()); } |
553 | | const_reverse_iterator crbegin() const { return rbegin(); } |
554 | 0 | reverse_iterator rend() const { return reverse_iterator(begin()); } |
555 | | const_reverse_iterator crend() const { return rend(); } |
556 | | |
557 | | private: |
558 | | void operator delete(void*) = delete; |
559 | | |
560 | | #ifdef DEBUG_FRAME_LIST |
561 | | void VerifyList() const; |
562 | | #else |
563 | 0 | void VerifyList() const {} |
564 | | #endif |
565 | | |
566 | | protected: |
567 | | /** |
568 | | * Disconnect aFrame from its siblings. This must only be called if aFrame |
569 | | * is NOT the first or last sibling, because otherwise its nsFrameList will |
570 | | * have a stale mFirst/LastChild pointer. This precondition is asserted. |
571 | | * This function is O(1). |
572 | | */ |
573 | | static void UnhookFrameFromSiblings(nsIFrame* aFrame); |
574 | | |
575 | | nsIFrame* mFirstChild; |
576 | | nsIFrame* mLastChild; |
577 | | }; |
578 | | |
579 | | inline bool |
580 | | operator==(const nsFrameList::Iterator& aIter1, |
581 | | const nsFrameList::Iterator& aIter2) |
582 | 0 | { |
583 | 0 | MOZ_ASSERT(&aIter1.mList == &aIter2.mList, |
584 | 0 | "must not compare iterator from different list"); |
585 | 0 | return aIter1.mCurrent == aIter2.mCurrent; |
586 | 0 | } |
587 | | |
588 | | inline bool |
589 | | operator!=(const nsFrameList::Iterator& aIter1, |
590 | | const nsFrameList::Iterator& aIter2) |
591 | 0 | { |
592 | 0 | MOZ_ASSERT(&aIter1.mList == &aIter2.mList, |
593 | 0 | "Must not compare iterator from different list"); |
594 | 0 | return aIter1.mCurrent != aIter2.mCurrent; |
595 | 0 | } |
596 | | |
597 | | namespace mozilla { |
598 | | namespace layout { |
599 | | |
600 | | /** |
601 | | * Simple "auto_ptr" for nsFrameLists allocated from the shell arena. |
602 | | * The frame list given to the constructor will be deallocated (if non-null) |
603 | | * in the destructor. The frame list must then be empty. |
604 | | */ |
605 | | class AutoFrameListPtr { |
606 | | public: |
607 | | AutoFrameListPtr(nsPresContext* aPresContext, nsFrameList* aFrameList) |
608 | 0 | : mPresContext(aPresContext), mFrameList(aFrameList) {} |
609 | | ~AutoFrameListPtr(); |
610 | 0 | operator nsFrameList*() const { return mFrameList; } |
611 | 0 | nsFrameList* operator->() const { return mFrameList; } |
612 | | private: |
613 | | nsPresContext* mPresContext; |
614 | | nsFrameList* mFrameList; |
615 | | }; |
616 | | |
617 | | namespace detail { |
618 | | union AlignedFrameListBytes { |
619 | | void* ptr; |
620 | | char bytes[sizeof(nsFrameList)]; |
621 | | }; |
622 | | extern const AlignedFrameListBytes gEmptyFrameListBytes; |
623 | | } // namespace detail |
624 | | |
625 | | } // namespace layout |
626 | | } // namespace mozilla |
627 | | |
628 | | /* static */ inline const nsFrameList& |
629 | | nsFrameList::EmptyList() |
630 | 0 | { |
631 | 0 | return *reinterpret_cast<const nsFrameList*>(&mozilla::layout::detail::gEmptyFrameListBytes); |
632 | 0 | } |
633 | | |
634 | | #endif /* nsFrameList_h___ */ |