michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 sw=2 et tw=79: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/dom/XBLChildrenElement.h" michael@0: #include "nsCharSeparatedTokenizer.h" michael@0: #include "mozilla/dom/NodeListBinding.h" michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: michael@0: XBLChildrenElement::~XBLChildrenElement() michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ADDREF_INHERITED(XBLChildrenElement, Element) michael@0: NS_IMPL_RELEASE_INHERITED(XBLChildrenElement, Element) michael@0: michael@0: NS_INTERFACE_TABLE_HEAD(XBLChildrenElement) michael@0: NS_INTERFACE_TABLE_INHERITED(XBLChildrenElement, nsIDOMNode, michael@0: nsIDOMElement) michael@0: NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE michael@0: NS_INTERFACE_MAP_END_INHERITING(Element) michael@0: michael@0: NS_IMPL_ELEMENT_CLONE(XBLChildrenElement) michael@0: michael@0: nsIAtom* michael@0: XBLChildrenElement::GetIDAttributeName() const michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: nsIAtom* michael@0: XBLChildrenElement::DoGetID() const michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: nsresult michael@0: XBLChildrenElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, michael@0: bool aNotify) michael@0: { michael@0: if (aAttribute == nsGkAtoms::includes && michael@0: aNameSpaceID == kNameSpaceID_None) { michael@0: mIncludes.Clear(); michael@0: } michael@0: michael@0: return Element::UnsetAttr(aNameSpaceID, aAttribute, aNotify); michael@0: } michael@0: michael@0: bool michael@0: XBLChildrenElement::ParseAttribute(int32_t aNamespaceID, michael@0: nsIAtom* aAttribute, michael@0: const nsAString& aValue, michael@0: nsAttrValue& aResult) michael@0: { michael@0: if (aAttribute == nsGkAtoms::includes && michael@0: aNamespaceID == kNameSpaceID_None) { michael@0: mIncludes.Clear(); michael@0: nsCharSeparatedTokenizer tok(aValue, '|', michael@0: nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL); michael@0: while (tok.hasMoreTokens()) { michael@0: nsCOMPtr atom = do_GetAtom(tok.nextToken()); michael@0: mIncludes.AppendElement(atom); michael@0: } michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: } // namespace mozilla michael@0: } // namespace dom michael@0: michael@0: using namespace mozilla::dom; michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsAnonymousContentList, mParent) michael@0: michael@0: NS_IMPL_CYCLE_COLLECTING_ADDREF(nsAnonymousContentList) michael@0: NS_IMPL_CYCLE_COLLECTING_RELEASE(nsAnonymousContentList) michael@0: michael@0: NS_INTERFACE_TABLE_HEAD(nsAnonymousContentList) michael@0: NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY michael@0: NS_INTERFACE_TABLE_INHERITED(nsAnonymousContentList, nsINodeList, michael@0: nsIDOMNodeList) michael@0: NS_INTERFACE_TABLE_TO_MAP_SEGUE michael@0: NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsAnonymousContentList) michael@0: NS_INTERFACE_MAP_ENTRY(nsISupports) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMETHODIMP michael@0: nsAnonymousContentList::GetLength(uint32_t* aLength) michael@0: { michael@0: if (!mParent) { michael@0: *aLength = 0; michael@0: return NS_OK; michael@0: } michael@0: michael@0: uint32_t count = 0; michael@0: for (nsIContent* child = mParent->GetFirstChild(); michael@0: child; michael@0: child = child->GetNextSibling()) { michael@0: if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) { michael@0: XBLChildrenElement* point = static_cast(child); michael@0: if (!point->mInsertedChildren.IsEmpty()) { michael@0: count += point->mInsertedChildren.Length(); michael@0: } michael@0: else { michael@0: count += point->GetChildCount(); michael@0: } michael@0: } michael@0: else { michael@0: ++count; michael@0: } michael@0: } michael@0: michael@0: *aLength = count; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsAnonymousContentList::Item(uint32_t aIndex, nsIDOMNode** aReturn) michael@0: { michael@0: nsIContent* item = Item(aIndex); michael@0: if (!item) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return CallQueryInterface(item, aReturn); michael@0: } michael@0: michael@0: nsIContent* michael@0: nsAnonymousContentList::Item(uint32_t aIndex) michael@0: { michael@0: if (!mParent) { michael@0: return nullptr; michael@0: } michael@0: michael@0: uint32_t remIndex = aIndex; michael@0: for (nsIContent* child = mParent->GetFirstChild(); michael@0: child; michael@0: child = child->GetNextSibling()) { michael@0: if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) { michael@0: XBLChildrenElement* point = static_cast(child); michael@0: if (!point->mInsertedChildren.IsEmpty()) { michael@0: if (remIndex < point->mInsertedChildren.Length()) { michael@0: return point->mInsertedChildren[remIndex]; michael@0: } michael@0: remIndex -= point->mInsertedChildren.Length(); michael@0: } michael@0: else { michael@0: if (remIndex < point->GetChildCount()) { michael@0: return point->GetChildAt(remIndex); michael@0: } michael@0: remIndex -= point->GetChildCount(); michael@0: } michael@0: } michael@0: else { michael@0: if (remIndex == 0) { michael@0: return child; michael@0: } michael@0: --remIndex; michael@0: } michael@0: } michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: int32_t michael@0: nsAnonymousContentList::IndexOf(nsIContent* aContent) michael@0: { michael@0: NS_ASSERTION(!aContent->NodeInfo()->Equals(nsGkAtoms::children, michael@0: kNameSpaceID_XBL), michael@0: "Looking for insertion point"); michael@0: michael@0: if (!mParent) { michael@0: return -1; michael@0: } michael@0: michael@0: uint32_t index = 0; michael@0: for (nsIContent* child = mParent->GetFirstChild(); michael@0: child; michael@0: child = child->GetNextSibling()) { michael@0: if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) { michael@0: XBLChildrenElement* point = static_cast(child); michael@0: if (!point->mInsertedChildren.IsEmpty()) { michael@0: uint32_t insIndex = point->mInsertedChildren.IndexOf(aContent); michael@0: if (insIndex != point->mInsertedChildren.NoIndex) { michael@0: return index + insIndex; michael@0: } michael@0: index += point->mInsertedChildren.Length(); michael@0: } michael@0: else { michael@0: int32_t insIndex = point->IndexOf(aContent); michael@0: if (insIndex != -1) { michael@0: return index + (uint32_t)insIndex; michael@0: } michael@0: index += point->GetChildCount(); michael@0: } michael@0: } michael@0: else { michael@0: if (child == aContent) { michael@0: return index; michael@0: } michael@0: ++index; michael@0: } michael@0: } michael@0: michael@0: return -1; michael@0: } michael@0: michael@0: JSObject* michael@0: nsAnonymousContentList::WrapObject(JSContext *cx) michael@0: { michael@0: return mozilla::dom::NodeListBinding::Wrap(cx, this); michael@0: }