forked from mirrors/gecko-dev
		
	(Path is actually r=froydnj.) Bug 1400459 devirtualized nsIAtom so that it is no longer a subclass of nsISupports. This means that nsAtom is now a better name for it than nsIAtom. MozReview-Commit-ID: 91U22X2NydP --HG-- rename : xpcom/ds/nsIAtom.h => xpcom/ds/nsAtom.h extra : rebase_source : ac3e904a21b8b48e74534fff964f1623ee937c67
		
			
				
	
	
		
			1281 lines
		
	
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1281 lines
		
	
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
						|
/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
#include "inDOMView.h"
 | 
						|
#include "inIDOMUtils.h"
 | 
						|
 | 
						|
#include "inLayoutUtils.h"
 | 
						|
 | 
						|
#include "nsString.h"
 | 
						|
#include "nsReadableUtils.h"
 | 
						|
#include "nsIDOMNode.h"
 | 
						|
#include "nsIDOMNodeFilter.h"
 | 
						|
#include "nsIDOMNodeList.h"
 | 
						|
#include "nsIDOMCharacterData.h"
 | 
						|
#include "nsIDOMAttr.h"
 | 
						|
#include "nsIDOMMozNamedAttrMap.h"
 | 
						|
#include "nsIDOMMutationEvent.h"
 | 
						|
#include "nsBindingManager.h"
 | 
						|
#include "nsNameSpaceManager.h"
 | 
						|
#include "nsIDocument.h"
 | 
						|
#include "nsIServiceManager.h"
 | 
						|
#include "nsITreeColumns.h"
 | 
						|
#include "nsITreeBoxObject.h"
 | 
						|
#include "mozilla/dom/Element.h"
 | 
						|
#include "mozilla/Services.h"
 | 
						|
 | 
						|
#ifdef ACCESSIBILITY
 | 
						|
#include "nsAccessibilityService.h"
 | 
						|
#endif
 | 
						|
 | 
						|
using namespace mozilla;
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////
 | 
						|
// inDOMViewNode
 | 
						|
 | 
						|
class inDOMViewNode
 | 
						|
{
 | 
						|
public:
 | 
						|
  inDOMViewNode() {}
 | 
						|
  explicit inDOMViewNode(nsIDOMNode* aNode);
 | 
						|
  ~inDOMViewNode();
 | 
						|
 | 
						|
  nsCOMPtr<nsIDOMNode> node;
 | 
						|
 | 
						|
  inDOMViewNode* parent;
 | 
						|
  inDOMViewNode* next;
 | 
						|
  inDOMViewNode* previous;
 | 
						|
 | 
						|
  int32_t level;
 | 
						|
  bool isOpen;
 | 
						|
  bool isContainer;
 | 
						|
  bool hasAnonymous;
 | 
						|
  bool hasSubDocument;
 | 
						|
};
 | 
						|
 | 
						|
inDOMViewNode::inDOMViewNode(nsIDOMNode* aNode) :
 | 
						|
  node(aNode),
 | 
						|
  parent(nullptr),
 | 
						|
  next(nullptr),
 | 
						|
  previous(nullptr),
 | 
						|
  level(0),
 | 
						|
  isOpen(false),
 | 
						|
  isContainer(false),
 | 
						|
  hasAnonymous(false),
 | 
						|
  hasSubDocument(false)
 | 
						|
{
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
inDOMViewNode::~inDOMViewNode()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
inDOMView::inDOMView() :
 | 
						|
  mShowAnonymous(false),
 | 
						|
  mShowSubDocuments(false),
 | 
						|
  mShowWhitespaceNodes(true),
 | 
						|
  mShowAccessibleNodes(false),
 | 
						|
  mWhatToShow(nsIDOMNodeFilter::SHOW_ALL)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
inDOMView::~inDOMView()
 | 
						|
{
 | 
						|
  SetRootNode(nullptr);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////
 | 
						|
// nsISupports
 | 
						|
 | 
						|
NS_IMPL_ISUPPORTS(inDOMView,
 | 
						|
                  inIDOMView,
 | 
						|
                  nsITreeView,
 | 
						|
                  nsIMutationObserver)
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////
 | 
						|
// inIDOMView
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetRootNode(nsIDOMNode** aNode)
 | 
						|
{
 | 
						|
  *aNode = mRootNode;
 | 
						|
  NS_IF_ADDREF(*aNode);
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::SetRootNode(nsIDOMNode* aNode)
 | 
						|
{
 | 
						|
  if (mTree)
 | 
						|
    mTree->BeginUpdateBatch();
 | 
						|
 | 
						|
  if (mRootDocument) {
 | 
						|
    // remove previous document observer
 | 
						|
    nsCOMPtr<nsINode> doc(do_QueryInterface(mRootDocument));
 | 
						|
    if (doc)
 | 
						|
      doc->RemoveMutationObserver(this);
 | 
						|
  }
 | 
						|
 | 
						|
  RemoveAllNodes();
 | 
						|
 | 
						|
  mRootNode = aNode;
 | 
						|
 | 
						|
  if (aNode) {
 | 
						|
    // If we are able to show element nodes, then start with the root node
 | 
						|
    // as the first node in the buffer
 | 
						|
    if (mWhatToShow & nsIDOMNodeFilter::SHOW_ELEMENT) {
 | 
						|
      // allocate new node array
 | 
						|
      AppendNode(CreateNode(aNode, nullptr));
 | 
						|
    } else {
 | 
						|
      // place only the children of the root node in the buffer
 | 
						|
      ExpandNode(-1);
 | 
						|
    }
 | 
						|
 | 
						|
    // store an owning reference to document so that it isn't
 | 
						|
    // destroyed before we are
 | 
						|
    mRootDocument = do_QueryInterface(aNode);
 | 
						|
    if (!mRootDocument) {
 | 
						|
      aNode->GetOwnerDocument(getter_AddRefs(mRootDocument));
 | 
						|
    }
 | 
						|
 | 
						|
    // add document observer
 | 
						|
    nsCOMPtr<nsINode> doc(do_QueryInterface(mRootDocument));
 | 
						|
    if (doc)
 | 
						|
      doc->AddMutationObserver(this);
 | 
						|
  } else {
 | 
						|
    mRootDocument = nullptr;
 | 
						|
  }
 | 
						|
 | 
						|
  if (mTree)
 | 
						|
    mTree->EndUpdateBatch();
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetNodeFromRowIndex(int32_t rowIndex, nsIDOMNode **_retval)
 | 
						|
{
 | 
						|
  inDOMViewNode* viewNode = nullptr;
 | 
						|
  RowToNode(rowIndex, &viewNode);
 | 
						|
  if (!viewNode) return NS_ERROR_FAILURE;
 | 
						|
  *_retval = viewNode->node;
 | 
						|
  NS_IF_ADDREF(*_retval);
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetRowIndexFromNode(nsIDOMNode *node, int32_t *_retval)
 | 
						|
{
 | 
						|
  NodeToRow(node, _retval);
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetShowAnonymousContent(bool *aShowAnonymousContent)
 | 
						|
{
 | 
						|
  *aShowAnonymousContent = mShowAnonymous;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::SetShowAnonymousContent(bool aShowAnonymousContent)
 | 
						|
{
 | 
						|
  mShowAnonymous = aShowAnonymousContent;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetShowSubDocuments(bool *aShowSubDocuments)
 | 
						|
{
 | 
						|
  *aShowSubDocuments = mShowSubDocuments;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::SetShowSubDocuments(bool aShowSubDocuments)
 | 
						|
{
 | 
						|
  mShowSubDocuments = aShowSubDocuments;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetShowWhitespaceNodes(bool *aShowWhitespaceNodes)
 | 
						|
{
 | 
						|
  *aShowWhitespaceNodes = mShowWhitespaceNodes;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::SetShowWhitespaceNodes(bool aShowWhitespaceNodes)
 | 
						|
{
 | 
						|
  mShowWhitespaceNodes = aShowWhitespaceNodes;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetShowAccessibleNodes(bool *aShowAccessibleNodes)
 | 
						|
{
 | 
						|
  *aShowAccessibleNodes = mShowAccessibleNodes;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::SetShowAccessibleNodes(bool aShowAccessibleNodes)
 | 
						|
{
 | 
						|
  mShowAccessibleNodes = aShowAccessibleNodes;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetWhatToShow(uint32_t *aWhatToShow)
 | 
						|
{
 | 
						|
  *aWhatToShow = mWhatToShow;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::SetWhatToShow(uint32_t aWhatToShow)
 | 
						|
{
 | 
						|
  mWhatToShow = aWhatToShow;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::Rebuild()
 | 
						|
{
 | 
						|
  nsCOMPtr<nsIDOMNode> root;
 | 
						|
  GetRootNode(getter_AddRefs(root));
 | 
						|
  SetRootNode(root);
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////
 | 
						|
// nsITreeView
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetRowCount(int32_t *aRowCount)
 | 
						|
{
 | 
						|
  *aRowCount = GetRowCount();
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetRowProperties(int32_t index, nsAString& aProps)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetCellProperties(int32_t row, nsITreeColumn* col,
 | 
						|
                             nsAString& aProps)
 | 
						|
{
 | 
						|
  inDOMViewNode* node = nullptr;
 | 
						|
  RowToNode(row, &node);
 | 
						|
  if (!node) return NS_ERROR_FAILURE;
 | 
						|
 | 
						|
  nsCOMPtr<nsIContent> content = do_QueryInterface(node->node);
 | 
						|
  if (content && content->IsInAnonymousSubtree()) {
 | 
						|
    aProps.AppendLiteral("anonymous ");
 | 
						|
  }
 | 
						|
 | 
						|
  uint16_t nodeType;
 | 
						|
  node->node->GetNodeType(&nodeType);
 | 
						|
  switch (nodeType) {
 | 
						|
    case nsIDOMNode::ELEMENT_NODE:
 | 
						|
      aProps.AppendLiteral("ELEMENT_NODE");
 | 
						|
      break;
 | 
						|
    case nsIDOMNode::ATTRIBUTE_NODE:
 | 
						|
      aProps.AppendLiteral("ATTRIBUTE_NODE");
 | 
						|
      break;
 | 
						|
    case nsIDOMNode::TEXT_NODE:
 | 
						|
      aProps.AppendLiteral("TEXT_NODE");
 | 
						|
      break;
 | 
						|
    case nsIDOMNode::CDATA_SECTION_NODE:
 | 
						|
      aProps.AppendLiteral("CDATA_SECTION_NODE");
 | 
						|
      break;
 | 
						|
    case nsIDOMNode::ENTITY_REFERENCE_NODE:
 | 
						|
      aProps.AppendLiteral("ENTITY_REFERENCE_NODE");
 | 
						|
      break;
 | 
						|
    case nsIDOMNode::ENTITY_NODE:
 | 
						|
      aProps.AppendLiteral("ENTITY_NODE");
 | 
						|
      break;
 | 
						|
    case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
 | 
						|
      aProps.AppendLiteral("PROCESSING_INSTRUCTION_NODE");
 | 
						|
      break;
 | 
						|
    case nsIDOMNode::COMMENT_NODE:
 | 
						|
      aProps.AppendLiteral("COMMENT_NODE");
 | 
						|
      break;
 | 
						|
    case nsIDOMNode::DOCUMENT_NODE:
 | 
						|
      aProps.AppendLiteral("DOCUMENT_NODE");
 | 
						|
      break;
 | 
						|
    case nsIDOMNode::DOCUMENT_TYPE_NODE:
 | 
						|
      aProps.AppendLiteral("DOCUMENT_TYPE_NODE");
 | 
						|
      break;
 | 
						|
    case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
 | 
						|
      aProps.AppendLiteral("DOCUMENT_FRAGMENT_NODE");
 | 
						|
      break;
 | 
						|
    case nsIDOMNode::NOTATION_NODE:
 | 
						|
      aProps.AppendLiteral("NOTATION_NODE");
 | 
						|
      break;
 | 
						|
  }
 | 
						|
 | 
						|
#ifdef ACCESSIBILITY
 | 
						|
  if (mShowAccessibleNodes) {
 | 
						|
    nsAccessibilityService* accService = GetOrCreateAccService();
 | 
						|
    NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
 | 
						|
 | 
						|
    if (accService->HasAccessible(node->node))
 | 
						|
      aProps.AppendLiteral(" ACCESSIBLE_NODE");
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetColumnProperties(nsITreeColumn* col, nsAString& aProps)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetImageSrc(int32_t row, nsITreeColumn* col, nsAString& _retval)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetProgressMode(int32_t row, nsITreeColumn* col, int32_t* _retval)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetCellValue(int32_t row, nsITreeColumn* col, nsAString& _retval)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetCellText(int32_t row, nsITreeColumn* col, nsAString& _retval)
 | 
						|
{
 | 
						|
  inDOMViewNode* node = nullptr;
 | 
						|
  RowToNode(row, &node);
 | 
						|
  if (!node) return NS_ERROR_FAILURE;
 | 
						|
 | 
						|
  nsIDOMNode* domNode = node->node;
 | 
						|
 | 
						|
  nsAutoString colID;
 | 
						|
  col->GetId(colID);
 | 
						|
  if (colID.EqualsLiteral("colNodeName"))
 | 
						|
    domNode->GetNodeName(_retval);
 | 
						|
  else if (colID.EqualsLiteral("colLocalName"))
 | 
						|
    domNode->GetLocalName(_retval);
 | 
						|
  else if (colID.EqualsLiteral("colPrefix"))
 | 
						|
    domNode->GetPrefix(_retval);
 | 
						|
  else if (colID.EqualsLiteral("colNamespaceURI"))
 | 
						|
    domNode->GetNamespaceURI(_retval);
 | 
						|
  else if (colID.EqualsLiteral("colNodeType")) {
 | 
						|
    uint16_t nodeType;
 | 
						|
    domNode->GetNodeType(&nodeType);
 | 
						|
    nsAutoString temp;
 | 
						|
    temp.AppendInt(int32_t(nodeType));
 | 
						|
    _retval = temp;
 | 
						|
  } else if (colID.EqualsLiteral("colNodeValue"))
 | 
						|
    domNode->GetNodeValue(_retval);
 | 
						|
  else {
 | 
						|
    if (StringBeginsWith(colID, NS_LITERAL_STRING("col@"))) {
 | 
						|
      nsCOMPtr<nsIDOMElement> el = do_QueryInterface(node->node);
 | 
						|
      if (el) {
 | 
						|
        nsAutoString attr;
 | 
						|
        colID.Right(attr, colID.Length()-4); // have to use this because Substring is crashing on me!
 | 
						|
        el->GetAttribute(attr, _retval);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::IsContainer(int32_t index, bool *_retval)
 | 
						|
{
 | 
						|
  inDOMViewNode* node = nullptr;
 | 
						|
  RowToNode(index, &node);
 | 
						|
  if (!node) return NS_ERROR_FAILURE;
 | 
						|
 | 
						|
  *_retval = node->isContainer;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::IsContainerOpen(int32_t index, bool *_retval)
 | 
						|
{
 | 
						|
  inDOMViewNode* node = nullptr;
 | 
						|
  RowToNode(index, &node);
 | 
						|
  if (!node) return NS_ERROR_FAILURE;
 | 
						|
 | 
						|
  *_retval = node->isOpen;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::IsContainerEmpty(int32_t index, bool *_retval)
 | 
						|
{
 | 
						|
  inDOMViewNode* node = nullptr;
 | 
						|
  RowToNode(index, &node);
 | 
						|
  if (!node) return NS_ERROR_FAILURE;
 | 
						|
 | 
						|
  *_retval = node->isContainer ? false : true;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetLevel(int32_t index, int32_t *_retval)
 | 
						|
{
 | 
						|
  inDOMViewNode* node = nullptr;
 | 
						|
  RowToNode(index, &node);
 | 
						|
  if (!node) return NS_ERROR_FAILURE;
 | 
						|
 | 
						|
  *_retval = node->level;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetParentIndex(int32_t rowIndex, int32_t *_retval)
 | 
						|
{
 | 
						|
  inDOMViewNode* node = nullptr;
 | 
						|
  RowToNode(rowIndex, &node);
 | 
						|
  if (!node) return NS_ERROR_FAILURE;
 | 
						|
 | 
						|
  // GetParentIndex returns -1 if there is no parent
 | 
						|
  *_retval = -1;
 | 
						|
 | 
						|
  inDOMViewNode* checkNode = nullptr;
 | 
						|
  int32_t i = rowIndex - 1;
 | 
						|
  do {
 | 
						|
    nsresult rv = RowToNode(i, &checkNode);
 | 
						|
    if (NS_FAILED(rv)) {
 | 
						|
      // No parent. Just break out.
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (checkNode == node->parent) {
 | 
						|
      *_retval = i;
 | 
						|
      return NS_OK;
 | 
						|
    }
 | 
						|
    --i;
 | 
						|
  } while (checkNode);
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::HasNextSibling(int32_t rowIndex, int32_t afterIndex, bool *_retval)
 | 
						|
{
 | 
						|
  inDOMViewNode* node = nullptr;
 | 
						|
  RowToNode(rowIndex, &node);
 | 
						|
  if (!node) return NS_ERROR_FAILURE;
 | 
						|
 | 
						|
  *_retval = node->next != nullptr;
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::ToggleOpenState(int32_t index)
 | 
						|
{
 | 
						|
  inDOMViewNode* node = nullptr;
 | 
						|
  RowToNode(index, &node);
 | 
						|
  if (!node) return NS_ERROR_FAILURE;
 | 
						|
 | 
						|
  int32_t oldCount = GetRowCount();
 | 
						|
  if (node->isOpen)
 | 
						|
    CollapseNode(index);
 | 
						|
  else
 | 
						|
    ExpandNode(index);
 | 
						|
 | 
						|
  // Update the twisty.
 | 
						|
  mTree->InvalidateRow(index);
 | 
						|
 | 
						|
  mTree->RowCountChanged(index+1, GetRowCount() - oldCount);
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::SetTree(nsITreeBoxObject *tree)
 | 
						|
{
 | 
						|
  mTree = tree;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::GetSelection(nsITreeSelection * *aSelection)
 | 
						|
{
 | 
						|
  *aSelection = mSelection;
 | 
						|
  NS_IF_ADDREF(*aSelection);
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP inDOMView::SetSelection(nsITreeSelection * aSelection)
 | 
						|
{
 | 
						|
  mSelection = aSelection;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::SelectionChanged()
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::SetCellValue(int32_t row, nsITreeColumn* col, const nsAString& value)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::SetCellText(int32_t row, nsITreeColumn* col, const nsAString& value)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::CycleHeader(nsITreeColumn* col)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::CycleCell(int32_t row, nsITreeColumn* col)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::IsEditable(int32_t row, nsITreeColumn* col, bool *_retval)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::IsSelectable(int32_t row, nsITreeColumn* col, bool *_retval)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::IsSeparator(int32_t index, bool *_retval)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::IsSorted(bool *_retval)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::CanDrop(int32_t index, int32_t orientation,
 | 
						|
                   nsIDOMDataTransfer* aDataTransfer, bool *_retval)
 | 
						|
{
 | 
						|
  *_retval = false;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::Drop(int32_t row, int32_t orientation, nsIDOMDataTransfer* aDataTransfer)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::PerformAction(const char16_t *action)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::PerformActionOnRow(const char16_t *action, int32_t row)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
inDOMView::PerformActionOnCell(const char16_t* action, int32_t row, nsITreeColumn* col)
 | 
						|
{
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////////////////
 | 
						|
// nsIMutationObserver
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::NodeWillBeDestroyed(const nsINode* aNode)
 | 
						|
{
 | 
						|
  NS_NOTREACHED("Document destroyed while we're holding a strong ref to it");
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::AttributeChanged(nsIDocument* aDocument, dom::Element* aElement,
 | 
						|
                            int32_t aNameSpaceID, nsAtom* aAttribute,
 | 
						|
                            int32_t aModType,
 | 
						|
                            const nsAttrValue* aOldValue)
 | 
						|
{
 | 
						|
  if (!mTree) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!(mWhatToShow & nsIDOMNodeFilter::SHOW_ATTRIBUTE)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
 | 
						|
 | 
						|
  // get the dom attribute node, if there is any
 | 
						|
  nsCOMPtr<nsIDOMElement> el(do_QueryInterface(aElement));
 | 
						|
  nsCOMPtr<nsIDOMAttr> domAttr;
 | 
						|
  nsDependentAtomString attrStr(aAttribute);
 | 
						|
  if (aNameSpaceID) {
 | 
						|
    nsNameSpaceManager* nsm = nsNameSpaceManager::GetInstance();
 | 
						|
    if (!nsm) {
 | 
						|
      // we can't find out which attribute we want :(
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    nsString attrNS;
 | 
						|
    nsresult rv = nsm->GetNameSpaceURI(aNameSpaceID, attrNS);
 | 
						|
    if (NS_FAILED(rv)) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    (void)el->GetAttributeNodeNS(attrNS, attrStr, getter_AddRefs(domAttr));
 | 
						|
  } else {
 | 
						|
    (void)el->GetAttributeNode(attrStr, getter_AddRefs(domAttr));
 | 
						|
  }
 | 
						|
 | 
						|
  if (aModType == nsIDOMMutationEvent::MODIFICATION) {
 | 
						|
    // No fancy stuff here, just invalidate the changed row
 | 
						|
    if (!domAttr) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    int32_t row = 0;
 | 
						|
    NodeToRow(domAttr, &row);
 | 
						|
    mTree->InvalidateRange(row, row);
 | 
						|
  } else if (aModType == nsIDOMMutationEvent::ADDITION) {
 | 
						|
    if (!domAttr) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    // get the number of attributes on this content node
 | 
						|
    nsCOMPtr<nsIDOMMozNamedAttrMap> attrs;
 | 
						|
    el->GetAttributes(getter_AddRefs(attrs));
 | 
						|
    uint32_t attrCount;
 | 
						|
    attrs->GetLength(&attrCount);
 | 
						|
 | 
						|
    inDOMViewNode* contentNode = nullptr;
 | 
						|
    int32_t contentRow;
 | 
						|
    int32_t attrRow;
 | 
						|
    if (mRootNode == el &&
 | 
						|
        !(mWhatToShow & nsIDOMNodeFilter::SHOW_ELEMENT)) {
 | 
						|
      // if this view has a root node but is not displaying it,
 | 
						|
      // it is ok to act as if the changed attribute is on the root.
 | 
						|
      attrRow = attrCount - 1;
 | 
						|
    } else {
 | 
						|
      if (NS_FAILED(NodeToRow(el, &contentRow))) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      RowToNode(contentRow, &contentNode);
 | 
						|
      if (!contentNode->isOpen) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      attrRow = contentRow + attrCount;
 | 
						|
    }
 | 
						|
 | 
						|
    inDOMViewNode* newNode = CreateNode(domAttr, contentNode);
 | 
						|
    inDOMViewNode* insertNode = nullptr;
 | 
						|
    RowToNode(attrRow, &insertNode);
 | 
						|
    if (insertNode) {
 | 
						|
      if (contentNode &&
 | 
						|
          insertNode->level <= contentNode->level) {
 | 
						|
        RowToNode(attrRow-1, &insertNode);
 | 
						|
        InsertLinkAfter(newNode, insertNode);
 | 
						|
      } else
 | 
						|
        InsertLinkBefore(newNode, insertNode);
 | 
						|
    }
 | 
						|
    InsertNode(newNode, attrRow);
 | 
						|
    mTree->RowCountChanged(attrRow, 1);
 | 
						|
  } else if (aModType == nsIDOMMutationEvent::REMOVAL) {
 | 
						|
    // At this point, the attribute is already gone from the DOM, but is still represented
 | 
						|
    // in our mRows array.  Search through the content node's children for the corresponding
 | 
						|
    // node and remove it.
 | 
						|
 | 
						|
    // get the row of the content node
 | 
						|
    inDOMViewNode* contentNode = nullptr;
 | 
						|
    int32_t contentRow;
 | 
						|
    int32_t baseLevel;
 | 
						|
    if (NS_SUCCEEDED(NodeToRow(el, &contentRow))) {
 | 
						|
      RowToNode(contentRow, &contentNode);
 | 
						|
      baseLevel = contentNode->level;
 | 
						|
    } else {
 | 
						|
      if (mRootNode == el) {
 | 
						|
        contentRow = -1;
 | 
						|
        baseLevel = -1;
 | 
						|
      } else
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    // search for the attribute node that was removed
 | 
						|
    inDOMViewNode* checkNode = nullptr;
 | 
						|
    int32_t row = 0;
 | 
						|
    for (row = contentRow+1; row < GetRowCount(); ++row) {
 | 
						|
      checkNode = GetNodeAt(row);
 | 
						|
      if (checkNode->level == baseLevel+1) {
 | 
						|
        domAttr = do_QueryInterface(checkNode->node);
 | 
						|
        if (domAttr) {
 | 
						|
          nsAutoString attrName;
 | 
						|
          domAttr->GetNodeName(attrName);
 | 
						|
          if (attrName.Equals(attrStr)) {
 | 
						|
            // we have found the row for the attribute that was removed
 | 
						|
            RemoveLink(checkNode);
 | 
						|
            RemoveNode(row);
 | 
						|
            mTree->RowCountChanged(row, -1);
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (checkNode->level <= baseLevel)
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
 }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::ContentAppended(nsIDocument *aDocument,
 | 
						|
                           nsIContent* aContainer,
 | 
						|
                           nsIContent* aFirstNewContent)
 | 
						|
{
 | 
						|
  if (!mTree) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  for (nsIContent* cur = aFirstNewContent; cur; cur = cur->GetNextSibling()) {
 | 
						|
    // Our ContentInserted impl doesn't use the index
 | 
						|
    ContentInserted(aDocument, aContainer, cur);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::ContentInserted(nsIDocument *aDocument, nsIContent* aContainer,
 | 
						|
                           nsIContent* aChild)
 | 
						|
{
 | 
						|
  if (!mTree)
 | 
						|
    return;
 | 
						|
 | 
						|
  nsresult rv;
 | 
						|
  nsCOMPtr<nsIDOMNode> childDOMNode(do_QueryInterface(aChild));
 | 
						|
  nsCOMPtr<nsIDOMNode> parent;
 | 
						|
  if (!mDOMUtils) {
 | 
						|
    mDOMUtils = services::GetInDOMUtils();
 | 
						|
    if (!mDOMUtils) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  mDOMUtils->GetParentForNode(childDOMNode, mShowAnonymous,
 | 
						|
                              getter_AddRefs(parent));
 | 
						|
 | 
						|
  // find the inDOMViewNode for the parent of the inserted content
 | 
						|
  int32_t parentRow = 0;
 | 
						|
  if (NS_FAILED(rv = NodeToRow(parent, &parentRow)))
 | 
						|
    return;
 | 
						|
  inDOMViewNode* parentNode = nullptr;
 | 
						|
  if (NS_FAILED(rv = RowToNode(parentRow, &parentNode)))
 | 
						|
    return;
 | 
						|
 | 
						|
  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
 | 
						|
 | 
						|
  if (!parentNode->isOpen) {
 | 
						|
    // Parent is not open, so don't bother creating tree rows for the
 | 
						|
    // kids.  But do indicate that it's now a container, if needed.
 | 
						|
    if (!parentNode->isContainer) {
 | 
						|
      parentNode->isContainer = true;
 | 
						|
      mTree->InvalidateRow(parentRow);
 | 
						|
    }
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  // get the previous sibling of the inserted content
 | 
						|
  nsCOMPtr<nsIDOMNode> previous;
 | 
						|
  GetRealPreviousSibling(childDOMNode, parent, getter_AddRefs(previous));
 | 
						|
  inDOMViewNode* previousNode = nullptr;
 | 
						|
 | 
						|
  int32_t row = 0;
 | 
						|
  if (previous) {
 | 
						|
    // find the inDOMViewNode for the previous sibling of the inserted content
 | 
						|
    int32_t previousRow = 0;
 | 
						|
    if (NS_FAILED(rv = NodeToRow(previous, &previousRow)))
 | 
						|
      return;
 | 
						|
    if (NS_FAILED(rv = RowToNode(previousRow, &previousNode)))
 | 
						|
      return;
 | 
						|
 | 
						|
    // get the last descendant of the previous row, which is the row
 | 
						|
    // after which to insert this new row
 | 
						|
    GetLastDescendantOf(previousNode, previousRow, &row);
 | 
						|
    ++row;
 | 
						|
  } else {
 | 
						|
    // there is no previous sibling, so the new row will be inserted after the parent
 | 
						|
    row = parentRow+1;
 | 
						|
  }
 | 
						|
 | 
						|
  inDOMViewNode* newNode = CreateNode(childDOMNode, parentNode);
 | 
						|
 | 
						|
  if (previous) {
 | 
						|
    InsertLinkAfter(newNode, previousNode);
 | 
						|
  } else {
 | 
						|
    int32_t firstChildRow;
 | 
						|
    if (NS_SUCCEEDED(GetFirstDescendantOf(parentNode, parentRow, &firstChildRow))) {
 | 
						|
      inDOMViewNode* firstChild;
 | 
						|
      RowToNode(firstChildRow, &firstChild);
 | 
						|
      InsertLinkBefore(newNode, firstChild);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // insert new node
 | 
						|
  InsertNode(newNode, row);
 | 
						|
 | 
						|
  mTree->RowCountChanged(row, 1);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::ContentRemoved(nsIDocument *aDocument, nsIContent* aContainer,
 | 
						|
                          nsIContent* aChild, nsIContent* aPreviousSibling)
 | 
						|
{
 | 
						|
  if (!mTree)
 | 
						|
    return;
 | 
						|
 | 
						|
  nsresult rv;
 | 
						|
 | 
						|
  // find the inDOMViewNode for the old child
 | 
						|
  nsCOMPtr<nsIDOMNode> oldDOMNode(do_QueryInterface(aChild));
 | 
						|
  int32_t row = 0;
 | 
						|
  if (NS_FAILED(rv = NodeToRow(oldDOMNode, &row)))
 | 
						|
    return;
 | 
						|
  inDOMViewNode* oldNode;
 | 
						|
  if (NS_FAILED(rv = RowToNode(row, &oldNode)))
 | 
						|
    return;
 | 
						|
 | 
						|
  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
 | 
						|
 | 
						|
  // The parent may no longer be a container.  Note that we don't want
 | 
						|
  // to access oldNode after calling RemoveNode, so do this now.
 | 
						|
  inDOMViewNode* parentNode = oldNode->parent;
 | 
						|
  bool isOnlyChild = oldNode->previous == nullptr && oldNode->next == nullptr;
 | 
						|
 | 
						|
  // Keep track of how many rows we are removing.  It's at least one,
 | 
						|
  // but if we're open it's more.
 | 
						|
  int32_t oldCount = GetRowCount();
 | 
						|
 | 
						|
  if (oldNode->isOpen)
 | 
						|
    CollapseNode(row);
 | 
						|
 | 
						|
  RemoveLink(oldNode);
 | 
						|
  RemoveNode(row);
 | 
						|
 | 
						|
  if (isOnlyChild) {
 | 
						|
    // Fix up the parent
 | 
						|
    parentNode->isContainer = false;
 | 
						|
    parentNode->isOpen = false;
 | 
						|
    mTree->InvalidateRow(NodeToRow(parentNode));
 | 
						|
  }
 | 
						|
 | 
						|
  mTree->RowCountChanged(row, GetRowCount() - oldCount);
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////////////////
 | 
						|
// inDOMView
 | 
						|
 | 
						|
//////// NODE MANAGEMENT
 | 
						|
 | 
						|
inDOMViewNode*
 | 
						|
inDOMView::GetNodeAt(int32_t aRow)
 | 
						|
{
 | 
						|
  return mNodes.ElementAt(aRow);
 | 
						|
}
 | 
						|
 | 
						|
int32_t
 | 
						|
inDOMView::GetRowCount()
 | 
						|
{
 | 
						|
  return mNodes.Length();
 | 
						|
}
 | 
						|
 | 
						|
int32_t
 | 
						|
inDOMView::NodeToRow(inDOMViewNode* aNode)
 | 
						|
{
 | 
						|
  return mNodes.IndexOf(aNode);
 | 
						|
}
 | 
						|
 | 
						|
inDOMViewNode*
 | 
						|
inDOMView::CreateNode(nsIDOMNode* aNode, inDOMViewNode* aParent)
 | 
						|
{
 | 
						|
  inDOMViewNode* viewNode = new inDOMViewNode(aNode);
 | 
						|
  viewNode->level = aParent ? aParent->level+1 : 0;
 | 
						|
  viewNode->parent = aParent;
 | 
						|
 | 
						|
  nsCOMArray<nsIDOMNode> grandKids;
 | 
						|
  GetChildNodesFor(aNode, grandKids);
 | 
						|
  viewNode->isContainer = (grandKids.Count() > 0);
 | 
						|
  return viewNode;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
inDOMView::RowOutOfBounds(int32_t aRow, int32_t aCount)
 | 
						|
{
 | 
						|
  return aRow < 0 || aRow >= GetRowCount() || aCount+aRow > GetRowCount();
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::AppendNode(inDOMViewNode* aNode)
 | 
						|
{
 | 
						|
  mNodes.AppendElement(aNode);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::InsertNode(inDOMViewNode* aNode, int32_t aRow)
 | 
						|
{
 | 
						|
  if (RowOutOfBounds(aRow, 1))
 | 
						|
    AppendNode(aNode);
 | 
						|
  else
 | 
						|
    mNodes.InsertElementAt(aRow, aNode);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::RemoveNode(int32_t aRow)
 | 
						|
{
 | 
						|
  if (RowOutOfBounds(aRow, 1))
 | 
						|
    return;
 | 
						|
 | 
						|
  delete GetNodeAt(aRow);
 | 
						|
  mNodes.RemoveElementAt(aRow);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::ReplaceNode(inDOMViewNode* aNode, int32_t aRow)
 | 
						|
{
 | 
						|
  if (RowOutOfBounds(aRow, 1))
 | 
						|
    return;
 | 
						|
 | 
						|
  delete GetNodeAt(aRow);
 | 
						|
  mNodes.ElementAt(aRow) = aNode;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::InsertNodes(nsTArray<inDOMViewNode*>& aNodes, int32_t aRow)
 | 
						|
{
 | 
						|
  if (aRow < 0 || aRow > GetRowCount())
 | 
						|
    return;
 | 
						|
 | 
						|
  mNodes.InsertElementsAt(aRow, aNodes);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::RemoveNodes(int32_t aRow, int32_t aCount)
 | 
						|
{
 | 
						|
  if (aRow < 0)
 | 
						|
    return;
 | 
						|
 | 
						|
  int32_t rowCount = GetRowCount();
 | 
						|
  for (int32_t i = aRow; i < aRow+aCount && i < rowCount; ++i) {
 | 
						|
    delete GetNodeAt(i);
 | 
						|
  }
 | 
						|
 | 
						|
  mNodes.RemoveElementsAt(aRow, aCount);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::RemoveAllNodes()
 | 
						|
{
 | 
						|
  int32_t rowCount = GetRowCount();
 | 
						|
  for (int32_t i = 0; i < rowCount; ++i) {
 | 
						|
    delete GetNodeAt(i);
 | 
						|
  }
 | 
						|
 | 
						|
  mNodes.Clear();
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::ExpandNode(int32_t aRow)
 | 
						|
{
 | 
						|
  inDOMViewNode* node = nullptr;
 | 
						|
  RowToNode(aRow, &node);
 | 
						|
 | 
						|
  nsCOMArray<nsIDOMNode> kids;
 | 
						|
  GetChildNodesFor(node ? node->node : mRootNode,
 | 
						|
                   kids);
 | 
						|
  int32_t kidCount = kids.Count();
 | 
						|
 | 
						|
  nsTArray<inDOMViewNode*> list(kidCount);
 | 
						|
 | 
						|
  inDOMViewNode* newNode = nullptr;
 | 
						|
  inDOMViewNode* prevNode = nullptr;
 | 
						|
 | 
						|
  for (int32_t i = 0; i < kidCount; ++i) {
 | 
						|
    newNode = CreateNode(kids[i], node);
 | 
						|
    list.AppendElement(newNode);
 | 
						|
 | 
						|
    if (prevNode)
 | 
						|
      prevNode->next = newNode;
 | 
						|
    newNode->previous = prevNode;
 | 
						|
    prevNode = newNode;
 | 
						|
  }
 | 
						|
 | 
						|
  InsertNodes(list, aRow+1);
 | 
						|
 | 
						|
  if (node)
 | 
						|
    node->isOpen = true;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::CollapseNode(int32_t aRow)
 | 
						|
{
 | 
						|
  inDOMViewNode* node = nullptr;
 | 
						|
  nsresult rv = RowToNode(aRow, &node);
 | 
						|
  if (NS_FAILED(rv)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  int32_t row = 0;
 | 
						|
  GetLastDescendantOf(node, aRow, &row);
 | 
						|
 | 
						|
  RemoveNodes(aRow+1, row-aRow);
 | 
						|
 | 
						|
  node->isOpen = false;
 | 
						|
}
 | 
						|
 | 
						|
//////// NODE AND ROW CONVERSION
 | 
						|
 | 
						|
nsresult
 | 
						|
inDOMView::RowToNode(int32_t aRow, inDOMViewNode** aNode)
 | 
						|
{
 | 
						|
  if (aRow < 0 || aRow >= GetRowCount())
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
 | 
						|
  *aNode = GetNodeAt(aRow);
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
inDOMView::NodeToRow(nsIDOMNode* aNode, int32_t* aRow)
 | 
						|
{
 | 
						|
  int32_t rowCount = GetRowCount();
 | 
						|
  for (int32_t i = 0; i < rowCount; ++i) {
 | 
						|
    if (GetNodeAt(i)->node == aNode) {
 | 
						|
      *aRow = i;
 | 
						|
      return NS_OK;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  *aRow = -1;
 | 
						|
  return NS_ERROR_FAILURE;
 | 
						|
}
 | 
						|
 | 
						|
//////// NODE HIERARCHY MUTATION
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::InsertLinkAfter(inDOMViewNode* aNode, inDOMViewNode* aInsertAfter)
 | 
						|
{
 | 
						|
  if (aInsertAfter->next)
 | 
						|
    aInsertAfter->next->previous = aNode;
 | 
						|
  aNode->next = aInsertAfter->next;
 | 
						|
  aInsertAfter->next = aNode;
 | 
						|
  aNode->previous = aInsertAfter;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::InsertLinkBefore(inDOMViewNode* aNode, inDOMViewNode* aInsertBefore)
 | 
						|
{
 | 
						|
  if (aInsertBefore->previous)
 | 
						|
    aInsertBefore->previous->next = aNode;
 | 
						|
  aNode->previous = aInsertBefore->previous;
 | 
						|
  aInsertBefore->previous = aNode;
 | 
						|
  aNode->next = aInsertBefore;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::RemoveLink(inDOMViewNode* aNode)
 | 
						|
{
 | 
						|
  if (aNode->previous)
 | 
						|
    aNode->previous->next = aNode->next;
 | 
						|
  if (aNode->next)
 | 
						|
    aNode->next->previous = aNode->previous;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
inDOMView::ReplaceLink(inDOMViewNode* aNewNode, inDOMViewNode* aOldNode)
 | 
						|
{
 | 
						|
  if (aOldNode->previous)
 | 
						|
    aOldNode->previous->next = aNewNode;
 | 
						|
  if (aOldNode->next)
 | 
						|
    aOldNode->next->previous = aNewNode;
 | 
						|
  aNewNode->next = aOldNode->next;
 | 
						|
  aNewNode->previous = aOldNode->previous;
 | 
						|
}
 | 
						|
 | 
						|
//////// NODE HIERARCHY UTILITIES
 | 
						|
 | 
						|
nsresult
 | 
						|
inDOMView::GetFirstDescendantOf(inDOMViewNode* aNode, int32_t aRow, int32_t* aResult)
 | 
						|
{
 | 
						|
  // get the first node that is a descendant of the previous sibling
 | 
						|
  int32_t row = 0;
 | 
						|
  inDOMViewNode* node;
 | 
						|
  for (row = aRow+1; row < GetRowCount(); ++row) {
 | 
						|
    node = GetNodeAt(row);
 | 
						|
    if (node->parent == aNode) {
 | 
						|
      *aResult = row;
 | 
						|
      return NS_OK;
 | 
						|
    }
 | 
						|
    if (node->level <= aNode->level)
 | 
						|
      break;
 | 
						|
  }
 | 
						|
  return NS_ERROR_FAILURE;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
inDOMView::GetLastDescendantOf(inDOMViewNode* aNode, int32_t aRow, int32_t* aResult)
 | 
						|
{
 | 
						|
  // get the last node that is a descendant of the previous sibling
 | 
						|
  int32_t row = 0;
 | 
						|
  for (row = aRow+1; row < GetRowCount(); ++row) {
 | 
						|
    if (GetNodeAt(row)->level <= aNode->level)
 | 
						|
      break;
 | 
						|
  }
 | 
						|
  *aResult = row-1;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
//////// DOM UTILITIES
 | 
						|
 | 
						|
nsresult
 | 
						|
inDOMView::GetChildNodesFor(nsIDOMNode* aNode, nsCOMArray<nsIDOMNode>& aResult)
 | 
						|
{
 | 
						|
  NS_ENSURE_ARG(aNode);
 | 
						|
  // attribute nodes
 | 
						|
  if (mWhatToShow & nsIDOMNodeFilter::SHOW_ATTRIBUTE) {
 | 
						|
    nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
 | 
						|
    if (element) {
 | 
						|
      nsCOMPtr<nsIDOMMozNamedAttrMap> attrs;
 | 
						|
      element->GetAttributes(getter_AddRefs(attrs));
 | 
						|
      if (attrs) {
 | 
						|
        AppendAttrsToArray(attrs, aResult);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (mWhatToShow & nsIDOMNodeFilter::SHOW_ELEMENT) {
 | 
						|
    nsCOMPtr<nsIDOMNodeList> kids;
 | 
						|
    if (!mDOMUtils) {
 | 
						|
      mDOMUtils = services::GetInDOMUtils();
 | 
						|
      if (!mDOMUtils) {
 | 
						|
        return NS_ERROR_FAILURE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    mDOMUtils->GetChildrenForNode(aNode, mShowAnonymous,
 | 
						|
                                  getter_AddRefs(kids));
 | 
						|
 | 
						|
    if (kids) {
 | 
						|
      AppendKidsToArray(kids, aResult);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (mShowSubDocuments) {
 | 
						|
    nsCOMPtr<nsIDOMNode> domdoc =
 | 
						|
      do_QueryInterface(inLayoutUtils::GetSubDocumentFor(aNode));
 | 
						|
    if (domdoc) {
 | 
						|
      aResult.AppendObject(domdoc);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
inDOMView::GetRealPreviousSibling(nsIDOMNode* aNode, nsIDOMNode* aRealParent, nsIDOMNode** aSibling)
 | 
						|
{
 | 
						|
  // XXXjrh: This won't work for some cases during some situations where XBL insertion points
 | 
						|
  // are involved.  Fix me!
 | 
						|
  aNode->GetPreviousSibling(aSibling);
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
inDOMView::AppendKidsToArray(nsIDOMNodeList* aKids,
 | 
						|
                             nsCOMArray<nsIDOMNode>& aArray)
 | 
						|
{
 | 
						|
  uint32_t l = 0;
 | 
						|
  aKids->GetLength(&l);
 | 
						|
  nsCOMPtr<nsIDOMNode> kid;
 | 
						|
  uint16_t nodeType = 0;
 | 
						|
 | 
						|
  // Try and get DOM Utils in case we don't have one yet.
 | 
						|
  if (!mShowWhitespaceNodes && !mDOMUtils) {
 | 
						|
    mDOMUtils = services::GetInDOMUtils();
 | 
						|
  }
 | 
						|
 | 
						|
  for (uint32_t i = 0; i < l; ++i) {
 | 
						|
    aKids->Item(i, getter_AddRefs(kid));
 | 
						|
    kid->GetNodeType(&nodeType);
 | 
						|
 | 
						|
    NS_ASSERTION(nodeType && nodeType <= nsIDOMNode::NOTATION_NODE,
 | 
						|
                 "Unknown node type. "
 | 
						|
                 "Were new types added to the spec?");
 | 
						|
    // As of DOM Level 2 Core and Traversal, each NodeFilter constant
 | 
						|
    // is defined as the lower nth bit in the NodeFilter bitmask,
 | 
						|
    // where n is the numeric constant of the nodeType it represents.
 | 
						|
    // If this invariant ever changes, we will need to update the
 | 
						|
    // following line.
 | 
						|
    uint32_t filterForNodeType = 1 << (nodeType - 1);
 | 
						|
 | 
						|
    if (mWhatToShow & filterForNodeType) {
 | 
						|
      if ((nodeType == nsIDOMNode::TEXT_NODE ||
 | 
						|
           nodeType == nsIDOMNode::COMMENT_NODE) &&
 | 
						|
          !mShowWhitespaceNodes && mDOMUtils) {
 | 
						|
        nsCOMPtr<nsIDOMCharacterData> data = do_QueryInterface(kid);
 | 
						|
        NS_ASSERTION(data, "Does not implement nsIDOMCharacterData!");
 | 
						|
        bool ignore;
 | 
						|
        mDOMUtils->IsIgnorableWhitespace(data, &ignore);
 | 
						|
        if (ignore) {
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      aArray.AppendElement(kid.forget());
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
inDOMView::AppendAttrsToArray(nsIDOMMozNamedAttrMap* aAttributes,
 | 
						|
                              nsCOMArray<nsIDOMNode>& aArray)
 | 
						|
{
 | 
						|
  uint32_t l = 0;
 | 
						|
  aAttributes->GetLength(&l);
 | 
						|
  nsCOMPtr<nsIDOMAttr> attribute;
 | 
						|
  for (uint32_t i = 0; i < l; ++i) {
 | 
						|
    aAttributes->Item(i, getter_AddRefs(attribute));
 | 
						|
    aArray.AppendElement(attribute.forget());
 | 
						|
  }
 | 
						|
  return NS_OK;
 | 
						|
}
 |