layout/inspector/inDOMView.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/inspector/inDOMView.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1287 @@
     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 "inDOMView.h"
    1.10 +#include "inIDOMUtils.h"
    1.11 +
    1.12 +#include "inLayoutUtils.h"
    1.13 +
    1.14 +#include "nsString.h"
    1.15 +#include "nsReadableUtils.h"
    1.16 +#include "nsIDOMNode.h"
    1.17 +#include "nsIDOMNodeFilter.h"
    1.18 +#include "nsIDOMNodeList.h"
    1.19 +#include "nsIDOMCharacterData.h"
    1.20 +#include "nsIDOMAttr.h"
    1.21 +#include "nsIDOMMozNamedAttrMap.h"
    1.22 +#include "nsIDOMMutationEvent.h"
    1.23 +#include "nsBindingManager.h"
    1.24 +#include "nsNameSpaceManager.h"
    1.25 +#include "nsIDocument.h"
    1.26 +#include "nsIServiceManager.h"
    1.27 +#include "nsITreeColumns.h"
    1.28 +#include "nsITreeBoxObject.h"
    1.29 +#include "mozilla/dom/Element.h"
    1.30 +#include "mozilla/Services.h"
    1.31 +
    1.32 +#ifdef ACCESSIBILITY
    1.33 +#include "nsIAccessible.h"
    1.34 +#include "nsIAccessibilityService.h"
    1.35 +#endif
    1.36 +
    1.37 +using namespace mozilla;
    1.38 +
    1.39 +////////////////////////////////////////////////////////////////////////
    1.40 +// inDOMViewNode
    1.41 +
    1.42 +class inDOMViewNode
    1.43 +{
    1.44 +public:
    1.45 +  inDOMViewNode() {}
    1.46 +  inDOMViewNode(nsIDOMNode* aNode);
    1.47 +  ~inDOMViewNode();
    1.48 +
    1.49 +  nsCOMPtr<nsIDOMNode> node;
    1.50 +
    1.51 +  inDOMViewNode* parent;
    1.52 +  inDOMViewNode* next;
    1.53 +  inDOMViewNode* previous;
    1.54 +
    1.55 +  int32_t level;
    1.56 +  bool isOpen;
    1.57 +  bool isContainer;
    1.58 +  bool hasAnonymous;
    1.59 +  bool hasSubDocument;
    1.60 +};
    1.61 +
    1.62 +inDOMViewNode::inDOMViewNode(nsIDOMNode* aNode) :
    1.63 +  node(aNode),
    1.64 +  parent(nullptr),
    1.65 +  next(nullptr),
    1.66 +  previous(nullptr),
    1.67 +  level(0),
    1.68 +  isOpen(false),
    1.69 +  isContainer(false),
    1.70 +  hasAnonymous(false),
    1.71 +  hasSubDocument(false)
    1.72 +{
    1.73 +
    1.74 +}
    1.75 +
    1.76 +inDOMViewNode::~inDOMViewNode()
    1.77 +{
    1.78 +}
    1.79 +
    1.80 +////////////////////////////////////////////////////////////////////////
    1.81 +
    1.82 +inDOMView::inDOMView() :
    1.83 +  mShowAnonymous(false),
    1.84 +  mShowSubDocuments(false),
    1.85 +  mShowWhitespaceNodes(true),
    1.86 +  mShowAccessibleNodes(false),
    1.87 +  mWhatToShow(nsIDOMNodeFilter::SHOW_ALL)
    1.88 +{
    1.89 +}
    1.90 +
    1.91 +inDOMView::~inDOMView()
    1.92 +{
    1.93 +  SetRootNode(nullptr);
    1.94 +}
    1.95 +
    1.96 +
    1.97 +////////////////////////////////////////////////////////////////////////
    1.98 +// nsISupports
    1.99 +
   1.100 +NS_IMPL_ISUPPORTS(inDOMView,
   1.101 +                  inIDOMView,
   1.102 +                  nsITreeView,
   1.103 +                  nsIMutationObserver)
   1.104 +
   1.105 +////////////////////////////////////////////////////////////////////////
   1.106 +// inIDOMView
   1.107 +
   1.108 +NS_IMETHODIMP
   1.109 +inDOMView::GetRootNode(nsIDOMNode** aNode)
   1.110 +{
   1.111 +  *aNode = mRootNode;
   1.112 +  NS_IF_ADDREF(*aNode);
   1.113 +  return NS_OK;
   1.114 +}
   1.115 +
   1.116 +NS_IMETHODIMP
   1.117 +inDOMView::SetRootNode(nsIDOMNode* aNode)
   1.118 +{
   1.119 +  if (mTree)
   1.120 +    mTree->BeginUpdateBatch();
   1.121 +
   1.122 +  if (mRootDocument) {
   1.123 +    // remove previous document observer
   1.124 +    nsCOMPtr<nsINode> doc(do_QueryInterface(mRootDocument));
   1.125 +    if (doc)
   1.126 +      doc->RemoveMutationObserver(this);
   1.127 +  }
   1.128 +
   1.129 +  RemoveAllNodes();
   1.130 +
   1.131 +  mRootNode = aNode;
   1.132 +
   1.133 +  if (aNode) {
   1.134 +    // If we are able to show element nodes, then start with the root node
   1.135 +    // as the first node in the buffer
   1.136 +    if (mWhatToShow & nsIDOMNodeFilter::SHOW_ELEMENT) {
   1.137 +      // allocate new node array
   1.138 +      AppendNode(CreateNode(aNode, nullptr));
   1.139 +    } else {
   1.140 +      // place only the children of the root node in the buffer
   1.141 +      ExpandNode(-1);
   1.142 +    }
   1.143 +
   1.144 +    // store an owning reference to document so that it isn't
   1.145 +    // destroyed before we are
   1.146 +    mRootDocument = do_QueryInterface(aNode);
   1.147 +    if (!mRootDocument) {
   1.148 +      aNode->GetOwnerDocument(getter_AddRefs(mRootDocument));
   1.149 +    }
   1.150 +
   1.151 +    // add document observer
   1.152 +    nsCOMPtr<nsINode> doc(do_QueryInterface(mRootDocument));
   1.153 +    if (doc)
   1.154 +      doc->AddMutationObserver(this);
   1.155 +  } else {
   1.156 +    mRootDocument = nullptr;
   1.157 +  }
   1.158 +
   1.159 +  if (mTree)
   1.160 +    mTree->EndUpdateBatch();
   1.161 +
   1.162 +  return NS_OK;
   1.163 +}
   1.164 +
   1.165 +NS_IMETHODIMP
   1.166 +inDOMView::GetNodeFromRowIndex(int32_t rowIndex, nsIDOMNode **_retval)
   1.167 +{
   1.168 +  inDOMViewNode* viewNode = nullptr;
   1.169 +  RowToNode(rowIndex, &viewNode);
   1.170 +  if (!viewNode) return NS_ERROR_FAILURE;
   1.171 +  *_retval = viewNode->node;
   1.172 +  NS_IF_ADDREF(*_retval);
   1.173 +
   1.174 +  return NS_OK;
   1.175 +}
   1.176 +
   1.177 +NS_IMETHODIMP
   1.178 +inDOMView::GetRowIndexFromNode(nsIDOMNode *node, int32_t *_retval)
   1.179 +{
   1.180 +  NodeToRow(node, _retval);
   1.181 +  return NS_OK;
   1.182 +}
   1.183 +
   1.184 +
   1.185 +NS_IMETHODIMP
   1.186 +inDOMView::GetShowAnonymousContent(bool *aShowAnonymousContent)
   1.187 +{
   1.188 +  *aShowAnonymousContent = mShowAnonymous;
   1.189 +  return NS_OK;
   1.190 +}
   1.191 +
   1.192 +NS_IMETHODIMP
   1.193 +inDOMView::SetShowAnonymousContent(bool aShowAnonymousContent)
   1.194 +{
   1.195 +  mShowAnonymous = aShowAnonymousContent;
   1.196 +  return NS_OK;
   1.197 +}
   1.198 +
   1.199 +NS_IMETHODIMP
   1.200 +inDOMView::GetShowSubDocuments(bool *aShowSubDocuments)
   1.201 +{
   1.202 +  *aShowSubDocuments = mShowSubDocuments;
   1.203 +  return NS_OK;
   1.204 +}
   1.205 +
   1.206 +NS_IMETHODIMP
   1.207 +inDOMView::SetShowSubDocuments(bool aShowSubDocuments)
   1.208 +{
   1.209 +  mShowSubDocuments = aShowSubDocuments;
   1.210 +  return NS_OK;
   1.211 +}
   1.212 +
   1.213 +NS_IMETHODIMP
   1.214 +inDOMView::GetShowWhitespaceNodes(bool *aShowWhitespaceNodes)
   1.215 +{
   1.216 +  *aShowWhitespaceNodes = mShowWhitespaceNodes;
   1.217 +  return NS_OK;
   1.218 +}
   1.219 +
   1.220 +NS_IMETHODIMP
   1.221 +inDOMView::SetShowWhitespaceNodes(bool aShowWhitespaceNodes)
   1.222 +{
   1.223 +  mShowWhitespaceNodes = aShowWhitespaceNodes;
   1.224 +  return NS_OK;
   1.225 +}
   1.226 +
   1.227 +NS_IMETHODIMP
   1.228 +inDOMView::GetShowAccessibleNodes(bool *aShowAccessibleNodes)
   1.229 +{
   1.230 +  *aShowAccessibleNodes = mShowAccessibleNodes;
   1.231 +  return NS_OK;
   1.232 +}
   1.233 +
   1.234 +NS_IMETHODIMP
   1.235 +inDOMView::SetShowAccessibleNodes(bool aShowAccessibleNodes)
   1.236 +{
   1.237 +  mShowAccessibleNodes = aShowAccessibleNodes;
   1.238 +  return NS_OK;
   1.239 +}
   1.240 +
   1.241 +NS_IMETHODIMP
   1.242 +inDOMView::GetWhatToShow(uint32_t *aWhatToShow)
   1.243 +{
   1.244 +  *aWhatToShow = mWhatToShow;
   1.245 +  return NS_OK;
   1.246 +}
   1.247 +
   1.248 +NS_IMETHODIMP
   1.249 +inDOMView::SetWhatToShow(uint32_t aWhatToShow)
   1.250 +{
   1.251 +  mWhatToShow = aWhatToShow;
   1.252 +  return NS_OK;
   1.253 +}
   1.254 +
   1.255 +NS_IMETHODIMP
   1.256 +inDOMView::Rebuild()
   1.257 +{
   1.258 +  nsCOMPtr<nsIDOMNode> root;
   1.259 +  GetRootNode(getter_AddRefs(root));
   1.260 +  SetRootNode(root);
   1.261 +  return NS_OK;
   1.262 +}
   1.263 +
   1.264 +////////////////////////////////////////////////////////////////////////
   1.265 +// nsITreeView
   1.266 +
   1.267 +NS_IMETHODIMP
   1.268 +inDOMView::GetRowCount(int32_t *aRowCount)
   1.269 +{
   1.270 +  *aRowCount = GetRowCount();
   1.271 +  return NS_OK;
   1.272 +}
   1.273 +
   1.274 +NS_IMETHODIMP
   1.275 +inDOMView::GetRowProperties(int32_t index, nsAString& aProps)
   1.276 +{
   1.277 +  return NS_OK;
   1.278 +}
   1.279 +
   1.280 +NS_IMETHODIMP
   1.281 +inDOMView::GetCellProperties(int32_t row, nsITreeColumn* col,
   1.282 +                             nsAString& aProps)
   1.283 +{
   1.284 +  inDOMViewNode* node = nullptr;
   1.285 +  RowToNode(row, &node);
   1.286 +  if (!node) return NS_ERROR_FAILURE;
   1.287 +
   1.288 +  nsCOMPtr<nsIContent> content = do_QueryInterface(node->node);
   1.289 +  if (content && content->IsInAnonymousSubtree()) {
   1.290 +    aProps.AppendLiteral("anonymous ");
   1.291 +  }
   1.292 +
   1.293 +  uint16_t nodeType;
   1.294 +  node->node->GetNodeType(&nodeType);
   1.295 +  switch (nodeType) {
   1.296 +    case nsIDOMNode::ELEMENT_NODE:
   1.297 +      aProps.AppendLiteral("ELEMENT_NODE");
   1.298 +      break;
   1.299 +    case nsIDOMNode::ATTRIBUTE_NODE:
   1.300 +      aProps.AppendLiteral("ATTRIBUTE_NODE");
   1.301 +      break;
   1.302 +    case nsIDOMNode::TEXT_NODE:
   1.303 +      aProps.AppendLiteral("TEXT_NODE");
   1.304 +      break;
   1.305 +    case nsIDOMNode::CDATA_SECTION_NODE:
   1.306 +      aProps.AppendLiteral("CDATA_SECTION_NODE");
   1.307 +      break;
   1.308 +    case nsIDOMNode::ENTITY_REFERENCE_NODE:
   1.309 +      aProps.AppendLiteral("ENTITY_REFERENCE_NODE");
   1.310 +      break;
   1.311 +    case nsIDOMNode::ENTITY_NODE:
   1.312 +      aProps.AppendLiteral("ENTITY_NODE");
   1.313 +      break;
   1.314 +    case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
   1.315 +      aProps.AppendLiteral("PROCESSING_INSTRUCTION_NODE");
   1.316 +      break;
   1.317 +    case nsIDOMNode::COMMENT_NODE:
   1.318 +      aProps.AppendLiteral("COMMENT_NODE");
   1.319 +      break;
   1.320 +    case nsIDOMNode::DOCUMENT_NODE:
   1.321 +      aProps.AppendLiteral("DOCUMENT_NODE");
   1.322 +      break;
   1.323 +    case nsIDOMNode::DOCUMENT_TYPE_NODE:
   1.324 +      aProps.AppendLiteral("DOCUMENT_TYPE_NODE");
   1.325 +      break;
   1.326 +    case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
   1.327 +      aProps.AppendLiteral("DOCUMENT_FRAGMENT_NODE");
   1.328 +      break;
   1.329 +    case nsIDOMNode::NOTATION_NODE:
   1.330 +      aProps.AppendLiteral("NOTATION_NODE");
   1.331 +      break;
   1.332 +  }
   1.333 +
   1.334 +#ifdef ACCESSIBILITY
   1.335 +  if (mShowAccessibleNodes) {
   1.336 +    nsCOMPtr<nsIAccessibilityService> accService(
   1.337 +      do_GetService("@mozilla.org/accessibilityService;1"));
   1.338 +    NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
   1.339 +
   1.340 +    nsCOMPtr<nsIAccessible> accessible;
   1.341 +    nsresult rv =
   1.342 +      accService->GetAccessibleFor(node->node, getter_AddRefs(accessible));
   1.343 +    if (NS_SUCCEEDED(rv) && accessible)
   1.344 +      aProps.AppendLiteral(" ACCESSIBLE_NODE");
   1.345 +  }
   1.346 +#endif
   1.347 +
   1.348 +  return NS_OK;
   1.349 +}
   1.350 +
   1.351 +NS_IMETHODIMP
   1.352 +inDOMView::GetColumnProperties(nsITreeColumn* col, nsAString& aProps)
   1.353 +{
   1.354 +  return NS_OK;
   1.355 +}
   1.356 +
   1.357 +NS_IMETHODIMP
   1.358 +inDOMView::GetImageSrc(int32_t row, nsITreeColumn* col, nsAString& _retval)
   1.359 +{
   1.360 +  return NS_OK;
   1.361 +}
   1.362 +
   1.363 +NS_IMETHODIMP
   1.364 +inDOMView::GetProgressMode(int32_t row, nsITreeColumn* col, int32_t* _retval)
   1.365 +{
   1.366 +  return NS_OK;
   1.367 +}
   1.368 +
   1.369 +NS_IMETHODIMP
   1.370 +inDOMView::GetCellValue(int32_t row, nsITreeColumn* col, nsAString& _retval)
   1.371 +{
   1.372 +  return NS_OK;
   1.373 +}
   1.374 +
   1.375 +NS_IMETHODIMP
   1.376 +inDOMView::GetCellText(int32_t row, nsITreeColumn* col, nsAString& _retval)
   1.377 +{
   1.378 +  inDOMViewNode* node = nullptr;
   1.379 +  RowToNode(row, &node);
   1.380 +  if (!node) return NS_ERROR_FAILURE;
   1.381 +
   1.382 +  nsIDOMNode* domNode = node->node;
   1.383 +
   1.384 +  nsAutoString colID;
   1.385 +  col->GetId(colID);
   1.386 +  if (colID.EqualsLiteral("colNodeName"))
   1.387 +    domNode->GetNodeName(_retval);
   1.388 +  else if (colID.EqualsLiteral("colLocalName"))
   1.389 +    domNode->GetLocalName(_retval);
   1.390 +  else if (colID.EqualsLiteral("colPrefix"))
   1.391 +    domNode->GetPrefix(_retval);
   1.392 +  else if (colID.EqualsLiteral("colNamespaceURI"))
   1.393 +    domNode->GetNamespaceURI(_retval);
   1.394 +  else if (colID.EqualsLiteral("colNodeType")) {
   1.395 +    uint16_t nodeType;
   1.396 +    domNode->GetNodeType(&nodeType);
   1.397 +    nsAutoString temp;
   1.398 +    temp.AppendInt(int32_t(nodeType));
   1.399 +    _retval = temp;
   1.400 +  } else if (colID.EqualsLiteral("colNodeValue"))
   1.401 +    domNode->GetNodeValue(_retval);
   1.402 +  else {
   1.403 +    if (StringBeginsWith(colID, NS_LITERAL_STRING("col@"))) {
   1.404 +      nsCOMPtr<nsIDOMElement> el = do_QueryInterface(node->node);
   1.405 +      if (el) {
   1.406 +        nsAutoString attr;
   1.407 +        colID.Right(attr, colID.Length()-4); // have to use this because Substring is crashing on me!
   1.408 +        el->GetAttribute(attr, _retval);
   1.409 +      }
   1.410 +    }
   1.411 +  }
   1.412 +
   1.413 +  return NS_OK;
   1.414 +}
   1.415 +
   1.416 +NS_IMETHODIMP
   1.417 +inDOMView::IsContainer(int32_t index, bool *_retval)
   1.418 +{
   1.419 +  inDOMViewNode* node = nullptr;
   1.420 +  RowToNode(index, &node);
   1.421 +  if (!node) return NS_ERROR_FAILURE;
   1.422 +
   1.423 +  *_retval = node->isContainer;
   1.424 +  return NS_OK;
   1.425 +}
   1.426 +
   1.427 +NS_IMETHODIMP
   1.428 +inDOMView::IsContainerOpen(int32_t index, bool *_retval)
   1.429 +{
   1.430 +  inDOMViewNode* node = nullptr;
   1.431 +  RowToNode(index, &node);
   1.432 +  if (!node) return NS_ERROR_FAILURE;
   1.433 +
   1.434 +  *_retval = node->isOpen;
   1.435 +  return NS_OK;
   1.436 +}
   1.437 +
   1.438 +NS_IMETHODIMP
   1.439 +inDOMView::IsContainerEmpty(int32_t index, bool *_retval)
   1.440 +{
   1.441 +  inDOMViewNode* node = nullptr;
   1.442 +  RowToNode(index, &node);
   1.443 +  if (!node) return NS_ERROR_FAILURE;
   1.444 +
   1.445 +  *_retval = node->isContainer ? false : true;
   1.446 +  return NS_OK;
   1.447 +}
   1.448 +
   1.449 +NS_IMETHODIMP
   1.450 +inDOMView::GetLevel(int32_t index, int32_t *_retval)
   1.451 +{
   1.452 +  inDOMViewNode* node = nullptr;
   1.453 +  RowToNode(index, &node);
   1.454 +  if (!node) return NS_ERROR_FAILURE;
   1.455 +
   1.456 +  *_retval = node->level;
   1.457 +  return NS_OK;
   1.458 +}
   1.459 +
   1.460 +NS_IMETHODIMP
   1.461 +inDOMView::GetParentIndex(int32_t rowIndex, int32_t *_retval)
   1.462 +{
   1.463 +  inDOMViewNode* node = nullptr;
   1.464 +  RowToNode(rowIndex, &node);
   1.465 +  if (!node) return NS_ERROR_FAILURE;
   1.466 +
   1.467 +  // GetParentIndex returns -1 if there is no parent  
   1.468 +  *_retval = -1;
   1.469 +  
   1.470 +  inDOMViewNode* checkNode = nullptr;
   1.471 +  int32_t i = rowIndex - 1;
   1.472 +  do {
   1.473 +    nsresult rv = RowToNode(i, &checkNode);
   1.474 +    if (NS_FAILED(rv)) {
   1.475 +      // No parent. Just break out.
   1.476 +      break;
   1.477 +    }
   1.478 +    
   1.479 +    if (checkNode == node->parent) {
   1.480 +      *_retval = i;
   1.481 +      return NS_OK;
   1.482 +    }
   1.483 +    --i;
   1.484 +  } while (checkNode);
   1.485 +
   1.486 +  return NS_OK;
   1.487 +}
   1.488 +
   1.489 +NS_IMETHODIMP
   1.490 +inDOMView::HasNextSibling(int32_t rowIndex, int32_t afterIndex, bool *_retval)
   1.491 +{
   1.492 +  inDOMViewNode* node = nullptr;
   1.493 +  RowToNode(rowIndex, &node);
   1.494 +  if (!node) return NS_ERROR_FAILURE;
   1.495 +
   1.496 +  *_retval = node->next != nullptr;
   1.497 +
   1.498 +  return NS_OK;
   1.499 +}
   1.500 +
   1.501 +NS_IMETHODIMP
   1.502 +inDOMView::ToggleOpenState(int32_t index)
   1.503 +{
   1.504 +  inDOMViewNode* node = nullptr;
   1.505 +  RowToNode(index, &node);
   1.506 +  if (!node) return NS_ERROR_FAILURE;
   1.507 +
   1.508 +  int32_t oldCount = GetRowCount();
   1.509 +  if (node->isOpen)
   1.510 +    CollapseNode(index);
   1.511 +  else
   1.512 +    ExpandNode(index);
   1.513 +
   1.514 +  // Update the twisty.
   1.515 +  mTree->InvalidateRow(index);
   1.516 +
   1.517 +  mTree->RowCountChanged(index+1, GetRowCount() - oldCount);
   1.518 +
   1.519 +  return NS_OK;
   1.520 +}
   1.521 +
   1.522 +NS_IMETHODIMP
   1.523 +inDOMView::SetTree(nsITreeBoxObject *tree)
   1.524 +{
   1.525 +  mTree = tree;
   1.526 +  return NS_OK;
   1.527 +}
   1.528 +
   1.529 +NS_IMETHODIMP
   1.530 +inDOMView::GetSelection(nsITreeSelection * *aSelection)
   1.531 +{
   1.532 +  *aSelection = mSelection;
   1.533 +  NS_IF_ADDREF(*aSelection);
   1.534 +  return NS_OK;
   1.535 +}
   1.536 +
   1.537 +NS_IMETHODIMP inDOMView::SetSelection(nsITreeSelection * aSelection)
   1.538 +{
   1.539 +  mSelection = aSelection;
   1.540 +  return NS_OK;
   1.541 +}
   1.542 +
   1.543 +NS_IMETHODIMP
   1.544 +inDOMView::SelectionChanged()
   1.545 +{
   1.546 +  return NS_OK;
   1.547 +}
   1.548 +
   1.549 +NS_IMETHODIMP
   1.550 +inDOMView::SetCellValue(int32_t row, nsITreeColumn* col, const nsAString& value)
   1.551 +{
   1.552 +  return NS_OK;
   1.553 +}
   1.554 +
   1.555 +NS_IMETHODIMP
   1.556 +inDOMView::SetCellText(int32_t row, nsITreeColumn* col, const nsAString& value)
   1.557 +{
   1.558 +  return NS_OK;
   1.559 +}
   1.560 +
   1.561 +NS_IMETHODIMP
   1.562 +inDOMView::CycleHeader(nsITreeColumn* col)
   1.563 +{
   1.564 +  return NS_OK;
   1.565 +}
   1.566 +
   1.567 +NS_IMETHODIMP
   1.568 +inDOMView::CycleCell(int32_t row, nsITreeColumn* col)
   1.569 +{
   1.570 +  return NS_OK;
   1.571 +}
   1.572 +
   1.573 +NS_IMETHODIMP
   1.574 +inDOMView::IsEditable(int32_t row, nsITreeColumn* col, bool *_retval)
   1.575 +{
   1.576 +  return NS_OK;
   1.577 +}
   1.578 +
   1.579 +
   1.580 +NS_IMETHODIMP
   1.581 +inDOMView::IsSelectable(int32_t row, nsITreeColumn* col, bool *_retval)
   1.582 +{
   1.583 +  return NS_OK;
   1.584 +}
   1.585 +
   1.586 +NS_IMETHODIMP
   1.587 +inDOMView::IsSeparator(int32_t index, bool *_retval)
   1.588 +{
   1.589 +  return NS_OK;
   1.590 +}
   1.591 +
   1.592 +NS_IMETHODIMP
   1.593 +inDOMView::IsSorted(bool *_retval)
   1.594 +{
   1.595 +  return NS_OK;
   1.596 +}
   1.597 +
   1.598 +NS_IMETHODIMP
   1.599 +inDOMView::CanDrop(int32_t index, int32_t orientation,
   1.600 +                   nsIDOMDataTransfer* aDataTransfer, bool *_retval)
   1.601 +{
   1.602 +  *_retval = false;
   1.603 +  return NS_OK;
   1.604 +}
   1.605 +
   1.606 +NS_IMETHODIMP
   1.607 +inDOMView::Drop(int32_t row, int32_t orientation, nsIDOMDataTransfer* aDataTransfer)
   1.608 +{
   1.609 +  return NS_OK;
   1.610 +}
   1.611 +
   1.612 +NS_IMETHODIMP
   1.613 +inDOMView::PerformAction(const char16_t *action)
   1.614 +{
   1.615 +  return NS_OK;
   1.616 +}
   1.617 +
   1.618 +NS_IMETHODIMP
   1.619 +inDOMView::PerformActionOnRow(const char16_t *action, int32_t row)
   1.620 +{
   1.621 +  return NS_OK;
   1.622 +}
   1.623 +
   1.624 +NS_IMETHODIMP
   1.625 +inDOMView::PerformActionOnCell(const char16_t* action, int32_t row, nsITreeColumn* col)
   1.626 +{
   1.627 +  return NS_OK;
   1.628 +}
   1.629 +
   1.630 +///////////////////////////////////////////////////////////////////////
   1.631 +// nsIMutationObserver
   1.632 +
   1.633 +void
   1.634 +inDOMView::NodeWillBeDestroyed(const nsINode* aNode)
   1.635 +{
   1.636 +  NS_NOTREACHED("Document destroyed while we're holding a strong ref to it");
   1.637 +}
   1.638 +
   1.639 +void
   1.640 +inDOMView::AttributeChanged(nsIDocument* aDocument, dom::Element* aElement,
   1.641 +                            int32_t aNameSpaceID, nsIAtom* aAttribute,
   1.642 +                            int32_t aModType)
   1.643 +{
   1.644 +  if (!mTree) {
   1.645 +    return;
   1.646 +  }
   1.647 +
   1.648 +  if (!(mWhatToShow & nsIDOMNodeFilter::SHOW_ATTRIBUTE)) {
   1.649 +    return;
   1.650 +  }
   1.651 +
   1.652 +  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
   1.653 +  
   1.654 +  // get the dom attribute node, if there is any
   1.655 +  nsCOMPtr<nsIDOMElement> el(do_QueryInterface(aElement));
   1.656 +  nsCOMPtr<nsIDOMAttr> domAttr;
   1.657 +  nsDependentAtomString attrStr(aAttribute);
   1.658 +  if (aNameSpaceID) {
   1.659 +    nsNameSpaceManager* nsm = nsNameSpaceManager::GetInstance();
   1.660 +    if (!nsm) {
   1.661 +      // we can't find out which attribute we want :(
   1.662 +      return;
   1.663 +    }
   1.664 +    nsString attrNS;
   1.665 +    nsresult rv = nsm->GetNameSpaceURI(aNameSpaceID, attrNS);
   1.666 +    if (NS_FAILED(rv)) {
   1.667 +      return;
   1.668 +    }
   1.669 +    (void)el->GetAttributeNodeNS(attrNS, attrStr, getter_AddRefs(domAttr));
   1.670 +  } else {
   1.671 +    (void)el->GetAttributeNode(attrStr, getter_AddRefs(domAttr));
   1.672 +  }
   1.673 +
   1.674 +  if (aModType == nsIDOMMutationEvent::MODIFICATION) {
   1.675 +    // No fancy stuff here, just invalidate the changed row
   1.676 +    if (!domAttr) {
   1.677 +      return;
   1.678 +    }
   1.679 +    int32_t row = 0;
   1.680 +    NodeToRow(domAttr, &row);
   1.681 +    mTree->InvalidateRange(row, row);
   1.682 +  } else if (aModType == nsIDOMMutationEvent::ADDITION) {
   1.683 +    if (!domAttr) {
   1.684 +      return;
   1.685 +    }
   1.686 +    // get the number of attributes on this content node
   1.687 +    nsCOMPtr<nsIDOMMozNamedAttrMap> attrs;
   1.688 +    el->GetAttributes(getter_AddRefs(attrs));
   1.689 +    uint32_t attrCount;
   1.690 +    attrs->GetLength(&attrCount);
   1.691 +
   1.692 +    inDOMViewNode* contentNode = nullptr;
   1.693 +    int32_t contentRow;
   1.694 +    int32_t attrRow;
   1.695 +    if (mRootNode == el &&
   1.696 +        !(mWhatToShow & nsIDOMNodeFilter::SHOW_ELEMENT)) {
   1.697 +      // if this view has a root node but is not displaying it,
   1.698 +      // it is ok to act as if the changed attribute is on the root.
   1.699 +      attrRow = attrCount - 1;
   1.700 +    } else {
   1.701 +      if (NS_FAILED(NodeToRow(el, &contentRow))) {
   1.702 +        return;
   1.703 +      }
   1.704 +      RowToNode(contentRow, &contentNode);
   1.705 +      if (!contentNode->isOpen) {
   1.706 +        return;
   1.707 +      }
   1.708 +      attrRow = contentRow + attrCount;
   1.709 +    }
   1.710 +
   1.711 +    inDOMViewNode* newNode = CreateNode(domAttr, contentNode);
   1.712 +    inDOMViewNode* insertNode = nullptr;
   1.713 +    RowToNode(attrRow, &insertNode);
   1.714 +    if (insertNode) {
   1.715 +      if (contentNode &&
   1.716 +          insertNode->level <= contentNode->level) {
   1.717 +        RowToNode(attrRow-1, &insertNode);
   1.718 +        InsertLinkAfter(newNode, insertNode);
   1.719 +      } else
   1.720 +        InsertLinkBefore(newNode, insertNode);
   1.721 +    }
   1.722 +    InsertNode(newNode, attrRow);
   1.723 +    mTree->RowCountChanged(attrRow, 1);
   1.724 +  } else if (aModType == nsIDOMMutationEvent::REMOVAL) {
   1.725 +    // At this point, the attribute is already gone from the DOM, but is still represented
   1.726 +    // in our mRows array.  Search through the content node's children for the corresponding
   1.727 +    // node and remove it.
   1.728 +
   1.729 +    // get the row of the content node
   1.730 +    inDOMViewNode* contentNode = nullptr;
   1.731 +    int32_t contentRow;
   1.732 +    int32_t baseLevel;
   1.733 +    if (NS_SUCCEEDED(NodeToRow(el, &contentRow))) {
   1.734 +      RowToNode(contentRow, &contentNode);
   1.735 +      baseLevel = contentNode->level;
   1.736 +    } else {
   1.737 +      if (mRootNode == el) {
   1.738 +        contentRow = -1;
   1.739 +        baseLevel = -1;
   1.740 +      } else
   1.741 +        return;
   1.742 +    }
   1.743 +
   1.744 +    // search for the attribute node that was removed
   1.745 +    inDOMViewNode* checkNode = nullptr;
   1.746 +    int32_t row = 0;
   1.747 +    for (row = contentRow+1; row < GetRowCount(); ++row) {
   1.748 +      checkNode = GetNodeAt(row);
   1.749 +      if (checkNode->level == baseLevel+1) {
   1.750 +        domAttr = do_QueryInterface(checkNode->node);
   1.751 +        if (domAttr) {
   1.752 +          nsAutoString attrName;
   1.753 +          domAttr->GetNodeName(attrName);
   1.754 +          if (attrName.Equals(attrStr)) {
   1.755 +            // we have found the row for the attribute that was removed
   1.756 +            RemoveLink(checkNode);
   1.757 +            RemoveNode(row);
   1.758 +            mTree->RowCountChanged(row, -1);
   1.759 +            break;
   1.760 +          }
   1.761 +        }
   1.762 +      }
   1.763 +      if (checkNode->level <= baseLevel)
   1.764 +        break;
   1.765 +    }
   1.766 +
   1.767 + }
   1.768 +}
   1.769 +
   1.770 +void
   1.771 +inDOMView::ContentAppended(nsIDocument *aDocument,
   1.772 +                           nsIContent* aContainer,
   1.773 +                           nsIContent* aFirstNewContent,
   1.774 +                           int32_t /* unused */)
   1.775 +{
   1.776 +  if (!mTree) {
   1.777 +    return;
   1.778 +  }
   1.779 +
   1.780 +  for (nsIContent* cur = aFirstNewContent; cur; cur = cur->GetNextSibling()) {
   1.781 +    // Our ContentInserted impl doesn't use the index
   1.782 +    ContentInserted(aDocument, aContainer, cur, 0);
   1.783 +  }
   1.784 +}
   1.785 +
   1.786 +void
   1.787 +inDOMView::ContentInserted(nsIDocument *aDocument, nsIContent* aContainer,
   1.788 +                           nsIContent* aChild, int32_t /* unused */)
   1.789 +{
   1.790 +  if (!mTree)
   1.791 +    return;
   1.792 +
   1.793 +  nsresult rv;
   1.794 +  nsCOMPtr<nsIDOMNode> childDOMNode(do_QueryInterface(aChild));
   1.795 +  nsCOMPtr<nsIDOMNode> parent;
   1.796 +  if (!mDOMUtils) {
   1.797 +    mDOMUtils = services::GetInDOMUtils();
   1.798 +    if (!mDOMUtils) {
   1.799 +      return;
   1.800 +    }
   1.801 +  }
   1.802 +  mDOMUtils->GetParentForNode(childDOMNode, mShowAnonymous,
   1.803 +                              getter_AddRefs(parent));
   1.804 +
   1.805 +  // find the inDOMViewNode for the parent of the inserted content
   1.806 +  int32_t parentRow = 0;
   1.807 +  if (NS_FAILED(rv = NodeToRow(parent, &parentRow)))
   1.808 +    return;
   1.809 +  inDOMViewNode* parentNode = nullptr;
   1.810 +  if (NS_FAILED(rv = RowToNode(parentRow, &parentNode)))
   1.811 +    return;
   1.812 +
   1.813 +  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
   1.814 +  
   1.815 +  if (!parentNode->isOpen) {
   1.816 +    // Parent is not open, so don't bother creating tree rows for the
   1.817 +    // kids.  But do indicate that it's now a container, if needed.
   1.818 +    if (!parentNode->isContainer) {
   1.819 +      parentNode->isContainer = true;
   1.820 +      mTree->InvalidateRow(parentRow);
   1.821 +    }
   1.822 +    return;
   1.823 +  }
   1.824 +
   1.825 +  // get the previous sibling of the inserted content
   1.826 +  nsCOMPtr<nsIDOMNode> previous;
   1.827 +  GetRealPreviousSibling(childDOMNode, parent, getter_AddRefs(previous));
   1.828 +  inDOMViewNode* previousNode = nullptr;
   1.829 +
   1.830 +  int32_t row = 0;
   1.831 +  if (previous) {
   1.832 +    // find the inDOMViewNode for the previous sibling of the inserted content
   1.833 +    int32_t previousRow = 0;
   1.834 +    if (NS_FAILED(rv = NodeToRow(previous, &previousRow)))
   1.835 +      return;
   1.836 +    if (NS_FAILED(rv = RowToNode(previousRow, &previousNode)))
   1.837 +      return;
   1.838 +
   1.839 +    // get the last descendant of the previous row, which is the row
   1.840 +    // after which to insert this new row
   1.841 +    GetLastDescendantOf(previousNode, previousRow, &row);
   1.842 +    ++row;
   1.843 +  } else {
   1.844 +    // there is no previous sibling, so the new row will be inserted after the parent
   1.845 +    row = parentRow+1;
   1.846 +  }
   1.847 +
   1.848 +  inDOMViewNode* newNode = CreateNode(childDOMNode, parentNode);
   1.849 +
   1.850 +  if (previous) {
   1.851 +    InsertLinkAfter(newNode, previousNode);
   1.852 +  } else {
   1.853 +    int32_t firstChildRow;
   1.854 +    if (NS_SUCCEEDED(GetFirstDescendantOf(parentNode, parentRow, &firstChildRow))) {
   1.855 +      inDOMViewNode* firstChild;
   1.856 +      RowToNode(firstChildRow, &firstChild);
   1.857 +      InsertLinkBefore(newNode, firstChild);
   1.858 +    }
   1.859 +  }
   1.860 +
   1.861 +  // insert new node
   1.862 +  InsertNode(newNode, row);
   1.863 +
   1.864 +  mTree->RowCountChanged(row, 1);
   1.865 +}
   1.866 +
   1.867 +void
   1.868 +inDOMView::ContentRemoved(nsIDocument *aDocument, nsIContent* aContainer,
   1.869 +                          nsIContent* aChild, int32_t aIndexInContainer,
   1.870 +                          nsIContent* aPreviousSibling)
   1.871 +{
   1.872 +  if (!mTree)
   1.873 +    return;
   1.874 +
   1.875 +  nsresult rv;
   1.876 +
   1.877 +  // find the inDOMViewNode for the old child
   1.878 +  nsCOMPtr<nsIDOMNode> oldDOMNode(do_QueryInterface(aChild));
   1.879 +  int32_t row = 0;
   1.880 +  if (NS_FAILED(rv = NodeToRow(oldDOMNode, &row)))
   1.881 +    return;
   1.882 +  inDOMViewNode* oldNode;
   1.883 +  if (NS_FAILED(rv = RowToNode(row, &oldNode)))
   1.884 +    return;
   1.885 +
   1.886 +  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
   1.887 +  
   1.888 +  // The parent may no longer be a container.  Note that we don't want
   1.889 +  // to access oldNode after calling RemoveNode, so do this now.
   1.890 +  inDOMViewNode* parentNode = oldNode->parent;
   1.891 +  bool isOnlyChild = oldNode->previous == nullptr && oldNode->next == nullptr;
   1.892 +  
   1.893 +  // Keep track of how many rows we are removing.  It's at least one,
   1.894 +  // but if we're open it's more.
   1.895 +  int32_t oldCount = GetRowCount();
   1.896 +  
   1.897 +  if (oldNode->isOpen)
   1.898 +    CollapseNode(row);
   1.899 +
   1.900 +  RemoveLink(oldNode);
   1.901 +  RemoveNode(row);
   1.902 +
   1.903 +  if (isOnlyChild) {
   1.904 +    // Fix up the parent
   1.905 +    parentNode->isContainer = false;
   1.906 +    parentNode->isOpen = false;
   1.907 +    mTree->InvalidateRow(NodeToRow(parentNode));
   1.908 +  }
   1.909 +    
   1.910 +  mTree->RowCountChanged(row, GetRowCount() - oldCount);
   1.911 +}
   1.912 +
   1.913 +///////////////////////////////////////////////////////////////////////
   1.914 +// inDOMView
   1.915 +
   1.916 +//////// NODE MANAGEMENT
   1.917 +
   1.918 +inDOMViewNode*
   1.919 +inDOMView::GetNodeAt(int32_t aRow)
   1.920 +{
   1.921 +  return mNodes.ElementAt(aRow);
   1.922 +}
   1.923 +
   1.924 +int32_t
   1.925 +inDOMView::GetRowCount()
   1.926 +{
   1.927 +  return mNodes.Length();
   1.928 +}
   1.929 +
   1.930 +int32_t
   1.931 +inDOMView::NodeToRow(inDOMViewNode* aNode)
   1.932 +{
   1.933 +  return mNodes.IndexOf(aNode);
   1.934 +}
   1.935 +
   1.936 +inDOMViewNode*
   1.937 +inDOMView::CreateNode(nsIDOMNode* aNode, inDOMViewNode* aParent)
   1.938 +{
   1.939 +  inDOMViewNode* viewNode = new inDOMViewNode(aNode);
   1.940 +  viewNode->level = aParent ? aParent->level+1 : 0;
   1.941 +  viewNode->parent = aParent;
   1.942 +
   1.943 +  nsCOMArray<nsIDOMNode> grandKids;
   1.944 +  GetChildNodesFor(aNode, grandKids);
   1.945 +  viewNode->isContainer = (grandKids.Count() > 0);
   1.946 +  return viewNode;
   1.947 +}
   1.948 +
   1.949 +bool
   1.950 +inDOMView::RowOutOfBounds(int32_t aRow, int32_t aCount)
   1.951 +{
   1.952 +  return aRow < 0 || aRow >= GetRowCount() || aCount+aRow > GetRowCount();
   1.953 +}
   1.954 +
   1.955 +void
   1.956 +inDOMView::AppendNode(inDOMViewNode* aNode)
   1.957 +{
   1.958 +  mNodes.AppendElement(aNode);
   1.959 +}
   1.960 +
   1.961 +void
   1.962 +inDOMView::InsertNode(inDOMViewNode* aNode, int32_t aRow)
   1.963 +{
   1.964 +  if (RowOutOfBounds(aRow, 1))
   1.965 +    AppendNode(aNode);
   1.966 +  else
   1.967 +    mNodes.InsertElementAt(aRow, aNode);
   1.968 +}
   1.969 +
   1.970 +void
   1.971 +inDOMView::RemoveNode(int32_t aRow)
   1.972 +{
   1.973 +  if (RowOutOfBounds(aRow, 1))
   1.974 +    return;
   1.975 +
   1.976 +  delete GetNodeAt(aRow);
   1.977 +  mNodes.RemoveElementAt(aRow);
   1.978 +}
   1.979 +
   1.980 +void
   1.981 +inDOMView::ReplaceNode(inDOMViewNode* aNode, int32_t aRow)
   1.982 +{
   1.983 +  if (RowOutOfBounds(aRow, 1))
   1.984 +    return;
   1.985 +
   1.986 +  delete GetNodeAt(aRow);
   1.987 +  mNodes.ElementAt(aRow) = aNode;
   1.988 +}
   1.989 +
   1.990 +void
   1.991 +inDOMView::InsertNodes(nsTArray<inDOMViewNode*>& aNodes, int32_t aRow)
   1.992 +{
   1.993 +  if (aRow < 0 || aRow > GetRowCount())
   1.994 +    return;
   1.995 +
   1.996 +  mNodes.InsertElementsAt(aRow, aNodes);
   1.997 +}
   1.998 +
   1.999 +void
  1.1000 +inDOMView::RemoveNodes(int32_t aRow, int32_t aCount)
  1.1001 +{
  1.1002 +  if (aRow < 0)
  1.1003 +    return;
  1.1004 +
  1.1005 +  int32_t rowCount = GetRowCount();
  1.1006 +  for (int32_t i = aRow; i < aRow+aCount && i < rowCount; ++i) {
  1.1007 +    delete GetNodeAt(i);
  1.1008 +  }
  1.1009 +
  1.1010 +  mNodes.RemoveElementsAt(aRow, aCount);
  1.1011 +}
  1.1012 +
  1.1013 +void
  1.1014 +inDOMView::RemoveAllNodes()
  1.1015 +{
  1.1016 +  int32_t rowCount = GetRowCount();
  1.1017 +  for (int32_t i = 0; i < rowCount; ++i) {
  1.1018 +    delete GetNodeAt(i);
  1.1019 +  }
  1.1020 +
  1.1021 +  mNodes.Clear();
  1.1022 +}
  1.1023 +
  1.1024 +void
  1.1025 +inDOMView::ExpandNode(int32_t aRow)
  1.1026 +{
  1.1027 +  inDOMViewNode* node = nullptr;
  1.1028 +  RowToNode(aRow, &node);
  1.1029 +
  1.1030 +  nsCOMArray<nsIDOMNode> kids;
  1.1031 +  GetChildNodesFor(node ? node->node : mRootNode,
  1.1032 +                   kids);
  1.1033 +  int32_t kidCount = kids.Count();
  1.1034 +
  1.1035 +  nsTArray<inDOMViewNode*> list(kidCount);
  1.1036 +
  1.1037 +  inDOMViewNode* newNode = nullptr;
  1.1038 +  inDOMViewNode* prevNode = nullptr;
  1.1039 +
  1.1040 +  for (int32_t i = 0; i < kidCount; ++i) {
  1.1041 +    newNode = CreateNode(kids[i], node);
  1.1042 +    list.AppendElement(newNode);
  1.1043 +
  1.1044 +    if (prevNode)
  1.1045 +      prevNode->next = newNode;
  1.1046 +    newNode->previous = prevNode;
  1.1047 +    prevNode = newNode;
  1.1048 +  }
  1.1049 +
  1.1050 +  InsertNodes(list, aRow+1);
  1.1051 +
  1.1052 +  if (node)
  1.1053 +    node->isOpen = true;
  1.1054 +}
  1.1055 +
  1.1056 +void
  1.1057 +inDOMView::CollapseNode(int32_t aRow)
  1.1058 +{
  1.1059 +  inDOMViewNode* node = nullptr;
  1.1060 +  nsresult rv = RowToNode(aRow, &node);
  1.1061 +  if (NS_FAILED(rv)) {
  1.1062 +    return;
  1.1063 +  }
  1.1064 +
  1.1065 +  int32_t row = 0;
  1.1066 +  GetLastDescendantOf(node, aRow, &row);
  1.1067 +
  1.1068 +  RemoveNodes(aRow+1, row-aRow);
  1.1069 +
  1.1070 +  node->isOpen = false;
  1.1071 +}
  1.1072 +
  1.1073 +//////// NODE AND ROW CONVERSION
  1.1074 +
  1.1075 +nsresult
  1.1076 +inDOMView::RowToNode(int32_t aRow, inDOMViewNode** aNode)
  1.1077 +{
  1.1078 +  if (aRow < 0 || aRow >= GetRowCount())
  1.1079 +    return NS_ERROR_FAILURE;
  1.1080 +
  1.1081 +  *aNode = GetNodeAt(aRow);
  1.1082 +  return NS_OK;
  1.1083 +}
  1.1084 +
  1.1085 +nsresult
  1.1086 +inDOMView::NodeToRow(nsIDOMNode* aNode, int32_t* aRow)
  1.1087 +{
  1.1088 +  int32_t rowCount = GetRowCount();
  1.1089 +  for (int32_t i = 0; i < rowCount; ++i) {
  1.1090 +    if (GetNodeAt(i)->node == aNode) {
  1.1091 +      *aRow = i;
  1.1092 +      return NS_OK;
  1.1093 +    }
  1.1094 +  }
  1.1095 +
  1.1096 +  *aRow = -1;
  1.1097 +  return NS_ERROR_FAILURE;
  1.1098 +}
  1.1099 +
  1.1100 +//////// NODE HIERARCHY MUTATION
  1.1101 +
  1.1102 +void
  1.1103 +inDOMView::InsertLinkAfter(inDOMViewNode* aNode, inDOMViewNode* aInsertAfter)
  1.1104 +{
  1.1105 +  if (aInsertAfter->next)
  1.1106 +    aInsertAfter->next->previous = aNode;
  1.1107 +  aNode->next = aInsertAfter->next;
  1.1108 +  aInsertAfter->next = aNode;
  1.1109 +  aNode->previous = aInsertAfter;
  1.1110 +}
  1.1111 +
  1.1112 +void
  1.1113 +inDOMView::InsertLinkBefore(inDOMViewNode* aNode, inDOMViewNode* aInsertBefore)
  1.1114 +{
  1.1115 +  if (aInsertBefore->previous)
  1.1116 +    aInsertBefore->previous->next = aNode;
  1.1117 +  aNode->previous = aInsertBefore->previous;
  1.1118 +  aInsertBefore->previous = aNode;
  1.1119 +  aNode->next = aInsertBefore;
  1.1120 +}
  1.1121 +
  1.1122 +void
  1.1123 +inDOMView::RemoveLink(inDOMViewNode* aNode)
  1.1124 +{
  1.1125 +  if (aNode->previous)
  1.1126 +    aNode->previous->next = aNode->next;
  1.1127 +  if (aNode->next)
  1.1128 +    aNode->next->previous = aNode->previous;
  1.1129 +}
  1.1130 +
  1.1131 +void
  1.1132 +inDOMView::ReplaceLink(inDOMViewNode* aNewNode, inDOMViewNode* aOldNode)
  1.1133 +{
  1.1134 +  if (aOldNode->previous)
  1.1135 +    aOldNode->previous->next = aNewNode;
  1.1136 +  if (aOldNode->next)
  1.1137 +    aOldNode->next->previous = aNewNode;
  1.1138 +  aNewNode->next = aOldNode->next;
  1.1139 +  aNewNode->previous = aOldNode->previous;
  1.1140 +}
  1.1141 +
  1.1142 +//////// NODE HIERARCHY UTILITIES
  1.1143 +
  1.1144 +nsresult
  1.1145 +inDOMView::GetFirstDescendantOf(inDOMViewNode* aNode, int32_t aRow, int32_t* aResult)
  1.1146 +{
  1.1147 +  // get the first node that is a descendant of the previous sibling
  1.1148 +  int32_t row = 0;
  1.1149 +  inDOMViewNode* node;
  1.1150 +  for (row = aRow+1; row < GetRowCount(); ++row) {
  1.1151 +    node = GetNodeAt(row);
  1.1152 +    if (node->parent == aNode) {
  1.1153 +      *aResult = row;
  1.1154 +      return NS_OK;
  1.1155 +    }
  1.1156 +    if (node->level <= aNode->level)
  1.1157 +      break;
  1.1158 +  }
  1.1159 +  return NS_ERROR_FAILURE;
  1.1160 +}
  1.1161 +
  1.1162 +nsresult
  1.1163 +inDOMView::GetLastDescendantOf(inDOMViewNode* aNode, int32_t aRow, int32_t* aResult)
  1.1164 +{
  1.1165 +  // get the last node that is a descendant of the previous sibling
  1.1166 +  int32_t row = 0;
  1.1167 +  for (row = aRow+1; row < GetRowCount(); ++row) {
  1.1168 +    if (GetNodeAt(row)->level <= aNode->level)
  1.1169 +      break;
  1.1170 +  }
  1.1171 +  *aResult = row-1;
  1.1172 +  return NS_OK;
  1.1173 +}
  1.1174 +
  1.1175 +//////// DOM UTILITIES
  1.1176 +
  1.1177 +nsresult
  1.1178 +inDOMView::GetChildNodesFor(nsIDOMNode* aNode, nsCOMArray<nsIDOMNode>& aResult)
  1.1179 +{
  1.1180 +  NS_ENSURE_ARG(aNode);
  1.1181 +  // attribute nodes
  1.1182 +  if (mWhatToShow & nsIDOMNodeFilter::SHOW_ATTRIBUTE) {
  1.1183 +    nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
  1.1184 +    if (element) {
  1.1185 +      nsCOMPtr<nsIDOMMozNamedAttrMap> attrs;
  1.1186 +      element->GetAttributes(getter_AddRefs(attrs));
  1.1187 +      if (attrs) {
  1.1188 +        AppendAttrsToArray(attrs, aResult);
  1.1189 +      }
  1.1190 +    }
  1.1191 +  }
  1.1192 +
  1.1193 +  if (mWhatToShow & nsIDOMNodeFilter::SHOW_ELEMENT) {
  1.1194 +    nsCOMPtr<nsIDOMNodeList> kids;
  1.1195 +    if (!mDOMUtils) {
  1.1196 +      mDOMUtils = services::GetInDOMUtils();
  1.1197 +      if (!mDOMUtils) {
  1.1198 +        return NS_ERROR_FAILURE;
  1.1199 +      }
  1.1200 +    }
  1.1201 +
  1.1202 +    mDOMUtils->GetChildrenForNode(aNode, mShowAnonymous,
  1.1203 +                                  getter_AddRefs(kids));
  1.1204 +
  1.1205 +    if (kids) {
  1.1206 +      AppendKidsToArray(kids, aResult);
  1.1207 +    }
  1.1208 +  }
  1.1209 +
  1.1210 +  if (mShowSubDocuments) {
  1.1211 +    nsCOMPtr<nsIDOMNode> domdoc =
  1.1212 +      do_QueryInterface(inLayoutUtils::GetSubDocumentFor(aNode));
  1.1213 +    if (domdoc) {
  1.1214 +      aResult.AppendObject(domdoc);
  1.1215 +    }
  1.1216 +  }
  1.1217 +
  1.1218 +  return NS_OK;
  1.1219 +}
  1.1220 +
  1.1221 +nsresult
  1.1222 +inDOMView::GetRealPreviousSibling(nsIDOMNode* aNode, nsIDOMNode* aRealParent, nsIDOMNode** aSibling)
  1.1223 +{
  1.1224 +  // XXXjrh: This won't work for some cases during some situations where XBL insertion points
  1.1225 +  // are involved.  Fix me!
  1.1226 +  aNode->GetPreviousSibling(aSibling);
  1.1227 +  return NS_OK;
  1.1228 +}
  1.1229 +
  1.1230 +nsresult
  1.1231 +inDOMView::AppendKidsToArray(nsIDOMNodeList* aKids,
  1.1232 +                             nsCOMArray<nsIDOMNode>& aArray)
  1.1233 +{
  1.1234 +  uint32_t l = 0;
  1.1235 +  aKids->GetLength(&l);
  1.1236 +  nsCOMPtr<nsIDOMNode> kid;
  1.1237 +  uint16_t nodeType = 0;
  1.1238 +
  1.1239 +  // Try and get DOM Utils in case we don't have one yet.
  1.1240 +  if (!mShowWhitespaceNodes && !mDOMUtils) {
  1.1241 +    mDOMUtils = services::GetInDOMUtils();
  1.1242 +  }
  1.1243 +
  1.1244 +  for (uint32_t i = 0; i < l; ++i) {
  1.1245 +    aKids->Item(i, getter_AddRefs(kid));
  1.1246 +    kid->GetNodeType(&nodeType);
  1.1247 +
  1.1248 +    NS_ASSERTION(nodeType && nodeType <= nsIDOMNode::NOTATION_NODE,
  1.1249 +                 "Unknown node type. "
  1.1250 +                 "Were new types added to the spec?");
  1.1251 +    // As of DOM Level 2 Core and Traversal, each NodeFilter constant
  1.1252 +    // is defined as the lower nth bit in the NodeFilter bitmask,
  1.1253 +    // where n is the numeric constant of the nodeType it represents.
  1.1254 +    // If this invariant ever changes, we will need to update the
  1.1255 +    // following line.
  1.1256 +    uint32_t filterForNodeType = 1 << (nodeType - 1);
  1.1257 +
  1.1258 +    if (mWhatToShow & filterForNodeType) {
  1.1259 +      if ((nodeType == nsIDOMNode::TEXT_NODE ||
  1.1260 +           nodeType == nsIDOMNode::COMMENT_NODE) &&
  1.1261 +          !mShowWhitespaceNodes && mDOMUtils) {
  1.1262 +        nsCOMPtr<nsIDOMCharacterData> data = do_QueryInterface(kid);
  1.1263 +        NS_ASSERTION(data, "Does not implement nsIDOMCharacterData!");
  1.1264 +        bool ignore;
  1.1265 +        mDOMUtils->IsIgnorableWhitespace(data, &ignore);
  1.1266 +        if (ignore) {
  1.1267 +          continue;
  1.1268 +        }
  1.1269 +      }
  1.1270 +
  1.1271 +      aArray.AppendObject(kid);
  1.1272 +    }
  1.1273 +  }
  1.1274 +
  1.1275 +  return NS_OK;
  1.1276 +}
  1.1277 +
  1.1278 +nsresult
  1.1279 +inDOMView::AppendAttrsToArray(nsIDOMMozNamedAttrMap* aAttributes,
  1.1280 +                              nsCOMArray<nsIDOMNode>& aArray)
  1.1281 +{
  1.1282 +  uint32_t l = 0;
  1.1283 +  aAttributes->GetLength(&l);
  1.1284 +  nsCOMPtr<nsIDOMAttr> attribute;
  1.1285 +  for (uint32_t i = 0; i < l; ++i) {
  1.1286 +    aAttributes->Item(i, getter_AddRefs(attribute));
  1.1287 +    aArray.AppendObject(attribute);
  1.1288 +  }
  1.1289 +  return NS_OK;
  1.1290 +}

mercurial