1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 // vim:cindent:ts=2:et:sw=2:
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/. */
7 /* base class for nsCounterList and nsQuoteList */
9 #include "nsGenConList.h"
10 #include "nsLayoutUtils.h"
11 #include "nsIContent.h"
19 for (nsGenConNode
*node
= Next(mFirstNode
); node
!= mFirstNode
;
20 node
= Next(mFirstNode
))
32 nsGenConList::DestroyNodesFor(nsIFrame
* aFrame
)
35 return false; // list empty
37 bool destroyed
= false;
38 while (mFirstNode
->mPseudoFrame
== aFrame
) {
40 node
= Next(mFirstNode
);
41 bool isLastNode
= node
== mFirstNode
; // before they're dangling
52 node
= Next(mFirstNode
);
53 while (node
!= mFirstNode
) {
54 if (node
->mPseudoFrame
== aFrame
) {
56 nsGenConNode
*nextNode
= Next(node
);
68 * Compute the type of the pseudo and the content for the pseudo that
69 * we'll use for comparison purposes.
70 * @param aContent the content to use is stored here; it's the element
71 * that generated the ::before or ::after content, or (if not for generated
72 * content), the frame's own element
73 * @return -1 for ::before, +1 for ::after, and 0 otherwise.
75 inline int32_t PseudoCompareType(nsIFrame
* aFrame
, nsIContent
** aContent
)
77 nsIAtom
*pseudo
= aFrame
->StyleContext()->GetPseudo();
78 if (pseudo
== nsCSSPseudoElements::before
) {
79 *aContent
= aFrame
->GetContent()->GetParent();
82 if (pseudo
== nsCSSPseudoElements::after
) {
83 *aContent
= aFrame
->GetContent()->GetParent();
86 *aContent
= aFrame
->GetContent();
91 nsGenConList::NodeAfter(const nsGenConNode
* aNode1
, const nsGenConNode
* aNode2
)
93 nsIFrame
*frame1
= aNode1
->mPseudoFrame
;
94 nsIFrame
*frame2
= aNode2
->mPseudoFrame
;
95 if (frame1
== frame2
) {
96 NS_ASSERTION(aNode2
->mContentIndex
!= aNode1
->mContentIndex
, "identical");
97 return aNode1
->mContentIndex
> aNode2
->mContentIndex
;
100 nsIContent
*content2
;
101 int32_t pseudoType1
= PseudoCompareType(frame1
, &content1
);
102 int32_t pseudoType2
= PseudoCompareType(frame2
, &content2
);
103 if (pseudoType1
== 0 || pseudoType2
== 0) {
104 if (content1
== content2
) {
105 NS_ASSERTION(pseudoType1
!= pseudoType2
, "identical");
106 return pseudoType2
== 0;
108 // We want to treat an element as coming before its :before (preorder
109 // traversal), so treating both as :before now works.
110 if (pseudoType1
== 0) pseudoType1
= -1;
111 if (pseudoType2
== 0) pseudoType2
= -1;
113 if (content1
== content2
) {
114 NS_ASSERTION(pseudoType1
!= pseudoType2
, "identical");
115 return pseudoType1
== 1;
118 // XXX Switch to the frame version of DoCompareTreePosition?
119 int32_t cmp
= nsLayoutUtils::DoCompareTreePosition(content1
, content2
,
120 pseudoType1
, -pseudoType2
);
121 NS_ASSERTION(cmp
!= 0, "same content, different frames");
126 nsGenConList::Insert(nsGenConNode
* aNode
)
130 if (NodeAfter(aNode
, Prev(mFirstNode
))) {
131 PR_INSERT_BEFORE(aNode
, mFirstNode
);
136 // the range of indices at which |aNode| could end up.
137 // (We already know it can't be at index mSize.)
138 uint32_t first
= 0, last
= mSize
- 1;
140 // A cursor to avoid walking more than the length of the list.
141 nsGenConNode
*curNode
= Prev(mFirstNode
);
142 uint32_t curIndex
= mSize
- 1;
144 while (first
!= last
) {
145 uint32_t test
= (first
+ last
) / 2;
146 if (last
== curIndex
) {
147 for ( ; curIndex
!= test
; --curIndex
)
148 curNode
= Prev(curNode
);
150 for ( ; curIndex
!= test
; ++curIndex
)
151 curNode
= Next(curNode
);
154 if (NodeAfter(aNode
, curNode
)) {
156 // if we exit the loop, we need curNode to be right
158 curNode
= Next(curNode
);
163 PR_INSERT_BEFORE(aNode
, curNode
);
164 if (curNode
== mFirstNode
) {
170 // initialize list with first node
171 PR_INIT_CLIST(aNode
);
176 NS_ASSERTION(aNode
== mFirstNode
|| NodeAfter(aNode
, Prev(aNode
)),
178 NS_ASSERTION(IsLast(aNode
) || NodeAfter(Next(aNode
), aNode
),