1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/editor/libeditor/base/nsSelectionState.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,668 @@ 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 "mozilla/Assertions.h" // for MOZ_ASSERT, etc 1.10 +#include "mozilla/dom/Selection.h" // for Selection 1.11 +#include "nsAString.h" // for nsAString_internal::Length 1.12 +#include "nsAutoPtr.h" // for nsRefPtr, getter_AddRefs, etc 1.13 +#include "nsCycleCollectionParticipant.h" 1.14 +#include "nsDebug.h" // for NS_ENSURE_TRUE, etc 1.15 +#include "nsEditor.h" // for nsEditor 1.16 +#include "nsEditorUtils.h" // for nsEditorUtils 1.17 +#include "nsError.h" // for NS_OK, etc 1.18 +#include "nsIDOMCharacterData.h" // for nsIDOMCharacterData 1.19 +#include "nsIDOMNode.h" // for nsIDOMNode 1.20 +#include "nsIDOMRange.h" // for nsIDOMRange, etc 1.21 +#include "nsISelection.h" // for nsISelection 1.22 +#include "nsISupportsImpl.h" // for nsRange::Release 1.23 +#include "nsRange.h" // for nsRange 1.24 +#include "nsSelectionState.h" 1.25 + 1.26 +using namespace mozilla; 1.27 +using namespace mozilla::dom; 1.28 + 1.29 +/*************************************************************************** 1.30 + * class for recording selection info. stores selection as collection of 1.31 + * { {startnode, startoffset} , {endnode, endoffset} } tuples. Can't store 1.32 + * ranges since dom gravity will possibly change the ranges. 1.33 + */ 1.34 +nsSelectionState::nsSelectionState() : mArray(){} 1.35 + 1.36 +nsSelectionState::~nsSelectionState() 1.37 +{ 1.38 + MakeEmpty(); 1.39 +} 1.40 + 1.41 +void 1.42 +nsSelectionState::DoTraverse(nsCycleCollectionTraversalCallback &cb) 1.43 +{ 1.44 + for (uint32_t i = 0, iEnd = mArray.Length(); i < iEnd; ++i) 1.45 + { 1.46 + nsRangeStore* item = mArray[i]; 1.47 + NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, 1.48 + "selection state mArray[i].startNode"); 1.49 + cb.NoteXPCOMChild(item->startNode); 1.50 + NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, 1.51 + "selection state mArray[i].endNode"); 1.52 + cb.NoteXPCOMChild(item->endNode); 1.53 + } 1.54 +} 1.55 + 1.56 +void 1.57 +nsSelectionState::SaveSelection(Selection* aSel) 1.58 +{ 1.59 + MOZ_ASSERT(aSel); 1.60 + int32_t arrayCount = mArray.Length(); 1.61 + int32_t rangeCount = aSel->GetRangeCount(); 1.62 + 1.63 + // if we need more items in the array, new them 1.64 + if (arrayCount < rangeCount) { 1.65 + for (int32_t i = arrayCount; i < rangeCount; i++) { 1.66 + mArray.AppendElement(); 1.67 + mArray[i] = new nsRangeStore(); 1.68 + } 1.69 + } else if (arrayCount > rangeCount) { 1.70 + // else if we have too many, delete them 1.71 + for (int32_t i = arrayCount - 1; i >= rangeCount; i--) { 1.72 + mArray.RemoveElementAt(i); 1.73 + } 1.74 + } 1.75 + 1.76 + // now store the selection ranges 1.77 + for (int32_t i = 0; i < rangeCount; i++) { 1.78 + mArray[i]->StoreRange(aSel->GetRangeAt(i)); 1.79 + } 1.80 +} 1.81 + 1.82 +nsresult 1.83 +nsSelectionState::RestoreSelection(nsISelection *aSel) 1.84 +{ 1.85 + NS_ENSURE_TRUE(aSel, NS_ERROR_NULL_POINTER); 1.86 + nsresult res; 1.87 + uint32_t i, arrayCount = mArray.Length(); 1.88 + 1.89 + // clear out selection 1.90 + aSel->RemoveAllRanges(); 1.91 + 1.92 + // set the selection ranges anew 1.93 + for (i=0; i<arrayCount; i++) 1.94 + { 1.95 + nsRefPtr<nsRange> range; 1.96 + mArray[i]->GetRange(getter_AddRefs(range)); 1.97 + NS_ENSURE_TRUE(range, NS_ERROR_UNEXPECTED); 1.98 + 1.99 + res = aSel->AddRange(range); 1.100 + if(NS_FAILED(res)) return res; 1.101 + 1.102 + } 1.103 + return NS_OK; 1.104 +} 1.105 + 1.106 +bool 1.107 +nsSelectionState::IsCollapsed() 1.108 +{ 1.109 + if (1 != mArray.Length()) return false; 1.110 + nsRefPtr<nsRange> range; 1.111 + mArray[0]->GetRange(getter_AddRefs(range)); 1.112 + NS_ENSURE_TRUE(range, false); 1.113 + bool bIsCollapsed = false; 1.114 + range->GetCollapsed(&bIsCollapsed); 1.115 + return bIsCollapsed; 1.116 +} 1.117 + 1.118 +bool 1.119 +nsSelectionState::IsEqual(nsSelectionState *aSelState) 1.120 +{ 1.121 + NS_ENSURE_TRUE(aSelState, false); 1.122 + uint32_t i, myCount = mArray.Length(), itsCount = aSelState->mArray.Length(); 1.123 + if (myCount != itsCount) return false; 1.124 + if (myCount < 1) return false; 1.125 + 1.126 + for (i=0; i<myCount; i++) 1.127 + { 1.128 + nsRefPtr<nsRange> myRange, itsRange; 1.129 + mArray[i]->GetRange(getter_AddRefs(myRange)); 1.130 + aSelState->mArray[i]->GetRange(getter_AddRefs(itsRange)); 1.131 + NS_ENSURE_TRUE(myRange && itsRange, false); 1.132 + 1.133 + int16_t compResult; 1.134 + nsresult rv; 1.135 + rv = myRange->CompareBoundaryPoints(nsIDOMRange::START_TO_START, itsRange, &compResult); 1.136 + if (NS_FAILED(rv) || compResult) return false; 1.137 + rv = myRange->CompareBoundaryPoints(nsIDOMRange::END_TO_END, itsRange, &compResult); 1.138 + if (NS_FAILED(rv) || compResult) return false; 1.139 + } 1.140 + // if we got here, they are equal 1.141 + return true; 1.142 +} 1.143 + 1.144 +void 1.145 +nsSelectionState::MakeEmpty() 1.146 +{ 1.147 + // free any items in the array 1.148 + mArray.Clear(); 1.149 +} 1.150 + 1.151 +bool 1.152 +nsSelectionState::IsEmpty() 1.153 +{ 1.154 + return mArray.IsEmpty(); 1.155 +} 1.156 + 1.157 +/*************************************************************************** 1.158 + * nsRangeUpdater: class for updating nsIDOMRanges in response to editor actions. 1.159 + */ 1.160 + 1.161 +nsRangeUpdater::nsRangeUpdater() : mArray(), mLock(false) {} 1.162 + 1.163 +nsRangeUpdater::~nsRangeUpdater() 1.164 +{ 1.165 + // nothing to do, we don't own the items in our array. 1.166 +} 1.167 + 1.168 +void 1.169 +nsRangeUpdater::RegisterRangeItem(nsRangeStore *aRangeItem) 1.170 +{ 1.171 + if (!aRangeItem) return; 1.172 + if (mArray.Contains(aRangeItem)) 1.173 + { 1.174 + NS_ERROR("tried to register an already registered range"); 1.175 + return; // don't register it again. It would get doubly adjusted. 1.176 + } 1.177 + mArray.AppendElement(aRangeItem); 1.178 +} 1.179 + 1.180 +void 1.181 +nsRangeUpdater::DropRangeItem(nsRangeStore *aRangeItem) 1.182 +{ 1.183 + if (!aRangeItem) return; 1.184 + mArray.RemoveElement(aRangeItem); 1.185 +} 1.186 + 1.187 +nsresult 1.188 +nsRangeUpdater::RegisterSelectionState(nsSelectionState &aSelState) 1.189 +{ 1.190 + uint32_t i, theCount = aSelState.mArray.Length(); 1.191 + if (theCount < 1) return NS_ERROR_FAILURE; 1.192 + 1.193 + for (i=0; i<theCount; i++) 1.194 + { 1.195 + RegisterRangeItem(aSelState.mArray[i]); 1.196 + } 1.197 + 1.198 + return NS_OK; 1.199 +} 1.200 + 1.201 +nsresult 1.202 +nsRangeUpdater::DropSelectionState(nsSelectionState &aSelState) 1.203 +{ 1.204 + uint32_t i, theCount = aSelState.mArray.Length(); 1.205 + if (theCount < 1) return NS_ERROR_FAILURE; 1.206 + 1.207 + for (i=0; i<theCount; i++) 1.208 + { 1.209 + DropRangeItem(aSelState.mArray[i]); 1.210 + } 1.211 + 1.212 + return NS_OK; 1.213 +} 1.214 + 1.215 +// gravity methods: 1.216 + 1.217 +nsresult 1.218 +nsRangeUpdater::SelAdjCreateNode(nsIDOMNode *aParent, int32_t aPosition) 1.219 +{ 1.220 + if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc... 1.221 + NS_ENSURE_TRUE(aParent, NS_ERROR_NULL_POINTER); 1.222 + uint32_t i, count = mArray.Length(); 1.223 + if (!count) { 1.224 + return NS_OK; 1.225 + } 1.226 + 1.227 + nsRangeStore *item; 1.228 + 1.229 + for (i=0; i<count; i++) 1.230 + { 1.231 + item = mArray[i]; 1.232 + NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER); 1.233 + 1.234 + if ((item->startNode.get() == aParent) && (item->startOffset > aPosition)) 1.235 + item->startOffset++; 1.236 + if ((item->endNode.get() == aParent) && (item->endOffset > aPosition)) 1.237 + item->endOffset++; 1.238 + } 1.239 + return NS_OK; 1.240 +} 1.241 + 1.242 +nsresult 1.243 +nsRangeUpdater::SelAdjInsertNode(nsIDOMNode *aParent, int32_t aPosition) 1.244 +{ 1.245 + return SelAdjCreateNode(aParent, aPosition); 1.246 +} 1.247 + 1.248 +void 1.249 +nsRangeUpdater::SelAdjDeleteNode(nsIDOMNode *aNode) 1.250 +{ 1.251 + if (mLock) { 1.252 + // lock set by Will/DidReplaceParent, etc... 1.253 + return; 1.254 + } 1.255 + MOZ_ASSERT(aNode); 1.256 + uint32_t i, count = mArray.Length(); 1.257 + if (!count) { 1.258 + return; 1.259 + } 1.260 + 1.261 + int32_t offset = 0; 1.262 + nsCOMPtr<nsIDOMNode> parent = nsEditor::GetNodeLocation(aNode, &offset); 1.263 + 1.264 + // check for range endpoints that are after aNode and in the same parent 1.265 + nsRangeStore *item; 1.266 + for (i=0; i<count; i++) 1.267 + { 1.268 + item = mArray[i]; 1.269 + MOZ_ASSERT(item); 1.270 + 1.271 + if ((item->startNode.get() == parent) && (item->startOffset > offset)) 1.272 + item->startOffset--; 1.273 + if ((item->endNode.get() == parent) && (item->endOffset > offset)) 1.274 + item->endOffset--; 1.275 + 1.276 + // check for range endpoints that are in aNode 1.277 + if (item->startNode == aNode) 1.278 + { 1.279 + item->startNode = parent; 1.280 + item->startOffset = offset; 1.281 + } 1.282 + if (item->endNode == aNode) 1.283 + { 1.284 + item->endNode = parent; 1.285 + item->endOffset = offset; 1.286 + } 1.287 + 1.288 + // check for range endpoints that are in descendants of aNode 1.289 + nsCOMPtr<nsIDOMNode> oldStart; 1.290 + if (nsEditorUtils::IsDescendantOf(item->startNode, aNode)) 1.291 + { 1.292 + oldStart = item->startNode; // save for efficiency hack below. 1.293 + item->startNode = parent; 1.294 + item->startOffset = offset; 1.295 + } 1.296 + 1.297 + // avoid having to call IsDescendantOf() for common case of range startnode == range endnode. 1.298 + if ((item->endNode == oldStart) || nsEditorUtils::IsDescendantOf(item->endNode, aNode)) 1.299 + { 1.300 + item->endNode = parent; 1.301 + item->endOffset = offset; 1.302 + } 1.303 + } 1.304 +} 1.305 + 1.306 + 1.307 +nsresult 1.308 +nsRangeUpdater::SelAdjSplitNode(nsIDOMNode *aOldRightNode, int32_t aOffset, nsIDOMNode *aNewLeftNode) 1.309 +{ 1.310 + if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc... 1.311 + NS_ENSURE_TRUE(aOldRightNode && aNewLeftNode, NS_ERROR_NULL_POINTER); 1.312 + uint32_t i, count = mArray.Length(); 1.313 + if (!count) { 1.314 + return NS_OK; 1.315 + } 1.316 + 1.317 + int32_t offset; 1.318 + nsCOMPtr<nsIDOMNode> parent = nsEditor::GetNodeLocation(aOldRightNode, &offset); 1.319 + 1.320 + // first part is same as inserting aNewLeftnode 1.321 + nsresult result = SelAdjInsertNode(parent,offset-1); 1.322 + NS_ENSURE_SUCCESS(result, result); 1.323 + 1.324 + // next step is to check for range enpoints inside aOldRightNode 1.325 + nsRangeStore *item; 1.326 + 1.327 + for (i=0; i<count; i++) 1.328 + { 1.329 + item = mArray[i]; 1.330 + NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER); 1.331 + 1.332 + if (item->startNode.get() == aOldRightNode) 1.333 + { 1.334 + if (item->startOffset > aOffset) 1.335 + { 1.336 + item->startOffset -= aOffset; 1.337 + } 1.338 + else 1.339 + { 1.340 + item->startNode = aNewLeftNode; 1.341 + } 1.342 + } 1.343 + if (item->endNode.get() == aOldRightNode) 1.344 + { 1.345 + if (item->endOffset > aOffset) 1.346 + { 1.347 + item->endOffset -= aOffset; 1.348 + } 1.349 + else 1.350 + { 1.351 + item->endNode = aNewLeftNode; 1.352 + } 1.353 + } 1.354 + } 1.355 + return NS_OK; 1.356 +} 1.357 + 1.358 + 1.359 +nsresult 1.360 +nsRangeUpdater::SelAdjJoinNodes(nsIDOMNode *aLeftNode, 1.361 + nsIDOMNode *aRightNode, 1.362 + nsIDOMNode *aParent, 1.363 + int32_t aOffset, 1.364 + int32_t aOldLeftNodeLength) 1.365 +{ 1.366 + if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc... 1.367 + NS_ENSURE_TRUE(aLeftNode && aRightNode && aParent, NS_ERROR_NULL_POINTER); 1.368 + uint32_t i, count = mArray.Length(); 1.369 + if (!count) { 1.370 + return NS_OK; 1.371 + } 1.372 + 1.373 + nsRangeStore *item; 1.374 + 1.375 + for (i=0; i<count; i++) 1.376 + { 1.377 + item = mArray[i]; 1.378 + NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER); 1.379 + 1.380 + if (item->startNode.get() == aParent) 1.381 + { 1.382 + // adjust start point in aParent 1.383 + if (item->startOffset > aOffset) 1.384 + { 1.385 + item->startOffset--; 1.386 + } 1.387 + else if (item->startOffset == aOffset) 1.388 + { 1.389 + // join keeps right hand node 1.390 + item->startNode = aRightNode; 1.391 + item->startOffset = aOldLeftNodeLength; 1.392 + } 1.393 + } 1.394 + else if (item->startNode.get() == aRightNode) 1.395 + { 1.396 + // adjust start point in aRightNode 1.397 + item->startOffset += aOldLeftNodeLength; 1.398 + } 1.399 + else if (item->startNode.get() == aLeftNode) 1.400 + { 1.401 + // adjust start point in aLeftNode 1.402 + item->startNode = aRightNode; 1.403 + } 1.404 + 1.405 + if (item->endNode.get() == aParent) 1.406 + { 1.407 + // adjust end point in aParent 1.408 + if (item->endOffset > aOffset) 1.409 + { 1.410 + item->endOffset--; 1.411 + } 1.412 + else if (item->endOffset == aOffset) 1.413 + { 1.414 + // join keeps right hand node 1.415 + item->endNode = aRightNode; 1.416 + item->endOffset = aOldLeftNodeLength; 1.417 + } 1.418 + } 1.419 + else if (item->endNode.get() == aRightNode) 1.420 + { 1.421 + // adjust end point in aRightNode 1.422 + item->endOffset += aOldLeftNodeLength; 1.423 + } 1.424 + else if (item->endNode.get() == aLeftNode) 1.425 + { 1.426 + // adjust end point in aLeftNode 1.427 + item->endNode = aRightNode; 1.428 + } 1.429 + } 1.430 + 1.431 + return NS_OK; 1.432 +} 1.433 + 1.434 + 1.435 +nsresult 1.436 +nsRangeUpdater::SelAdjInsertText(nsIDOMCharacterData *aTextNode, int32_t aOffset, const nsAString &aString) 1.437 +{ 1.438 + if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc... 1.439 + 1.440 + uint32_t count = mArray.Length(); 1.441 + if (!count) { 1.442 + return NS_OK; 1.443 + } 1.444 + nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aTextNode)); 1.445 + NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER); 1.446 + 1.447 + uint32_t len=aString.Length(), i; 1.448 + nsRangeStore *item; 1.449 + for (i=0; i<count; i++) 1.450 + { 1.451 + item = mArray[i]; 1.452 + NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER); 1.453 + 1.454 + if ((item->startNode.get() == node) && (item->startOffset > aOffset)) 1.455 + item->startOffset += len; 1.456 + if ((item->endNode.get() == node) && (item->endOffset > aOffset)) 1.457 + item->endOffset += len; 1.458 + } 1.459 + return NS_OK; 1.460 +} 1.461 + 1.462 + 1.463 +nsresult 1.464 +nsRangeUpdater::SelAdjDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength) 1.465 +{ 1.466 + if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc... 1.467 + 1.468 + uint32_t i, count = mArray.Length(); 1.469 + if (!count) { 1.470 + return NS_OK; 1.471 + } 1.472 + nsRangeStore *item; 1.473 + nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aTextNode)); 1.474 + NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER); 1.475 + 1.476 + for (i=0; i<count; i++) 1.477 + { 1.478 + item = mArray[i]; 1.479 + NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER); 1.480 + 1.481 + if ((item->startNode.get() == node) && (item->startOffset > aOffset)) 1.482 + { 1.483 + item->startOffset -= aLength; 1.484 + if (item->startOffset < 0) item->startOffset = 0; 1.485 + } 1.486 + if ((item->endNode.get() == node) && (item->endOffset > aOffset)) 1.487 + { 1.488 + item->endOffset -= aLength; 1.489 + if (item->endOffset < 0) item->endOffset = 0; 1.490 + } 1.491 + } 1.492 + return NS_OK; 1.493 +} 1.494 + 1.495 + 1.496 +nsresult 1.497 +nsRangeUpdater::WillReplaceContainer() 1.498 +{ 1.499 + if (mLock) return NS_ERROR_UNEXPECTED; 1.500 + mLock = true; 1.501 + return NS_OK; 1.502 +} 1.503 + 1.504 + 1.505 +nsresult 1.506 +nsRangeUpdater::DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode) 1.507 +{ 1.508 + NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED); 1.509 + mLock = false; 1.510 + 1.511 + NS_ENSURE_TRUE(aOriginalNode && aNewNode, NS_ERROR_NULL_POINTER); 1.512 + uint32_t i, count = mArray.Length(); 1.513 + if (!count) { 1.514 + return NS_OK; 1.515 + } 1.516 + 1.517 + nsRangeStore *item; 1.518 + 1.519 + for (i=0; i<count; i++) 1.520 + { 1.521 + item = mArray[i]; 1.522 + NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER); 1.523 + 1.524 + if (item->startNode.get() == aOriginalNode) 1.525 + item->startNode = aNewNode; 1.526 + if (item->endNode.get() == aOriginalNode) 1.527 + item->endNode = aNewNode; 1.528 + } 1.529 + return NS_OK; 1.530 +} 1.531 + 1.532 + 1.533 +nsresult 1.534 +nsRangeUpdater::WillRemoveContainer() 1.535 +{ 1.536 + if (mLock) return NS_ERROR_UNEXPECTED; 1.537 + mLock = true; 1.538 + return NS_OK; 1.539 +} 1.540 + 1.541 + 1.542 +nsresult 1.543 +nsRangeUpdater::DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aOffset, uint32_t aNodeOrigLen) 1.544 +{ 1.545 + NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED); 1.546 + mLock = false; 1.547 + 1.548 + NS_ENSURE_TRUE(aNode && aParent, NS_ERROR_NULL_POINTER); 1.549 + uint32_t i, count = mArray.Length(); 1.550 + if (!count) { 1.551 + return NS_OK; 1.552 + } 1.553 + 1.554 + nsRangeStore *item; 1.555 + 1.556 + for (i=0; i<count; i++) 1.557 + { 1.558 + item = mArray[i]; 1.559 + NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER); 1.560 + 1.561 + if (item->startNode.get() == aNode) 1.562 + { 1.563 + item->startNode = aParent; 1.564 + item->startOffset += aOffset; 1.565 + } 1.566 + else if ((item->startNode.get() == aParent) && (item->startOffset > aOffset)) 1.567 + item->startOffset += (int32_t)aNodeOrigLen-1; 1.568 + 1.569 + if (item->endNode.get() == aNode) 1.570 + { 1.571 + item->endNode = aParent; 1.572 + item->endOffset += aOffset; 1.573 + } 1.574 + else if ((item->endNode.get() == aParent) && (item->endOffset > aOffset)) 1.575 + item->endOffset += (int32_t)aNodeOrigLen-1; 1.576 + } 1.577 + return NS_OK; 1.578 +} 1.579 + 1.580 + 1.581 +nsresult 1.582 +nsRangeUpdater::WillInsertContainer() 1.583 +{ 1.584 + if (mLock) return NS_ERROR_UNEXPECTED; 1.585 + mLock = true; 1.586 + return NS_OK; 1.587 +} 1.588 + 1.589 + 1.590 +nsresult 1.591 +nsRangeUpdater::DidInsertContainer() 1.592 +{ 1.593 + NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED); 1.594 + mLock = false; 1.595 + return NS_OK; 1.596 +} 1.597 + 1.598 + 1.599 +void 1.600 +nsRangeUpdater::WillMoveNode() 1.601 +{ 1.602 + mLock = true; 1.603 +} 1.604 + 1.605 + 1.606 +void 1.607 +nsRangeUpdater::DidMoveNode(nsINode* aOldParent, int32_t aOldOffset, 1.608 + nsINode* aNewParent, int32_t aNewOffset) 1.609 +{ 1.610 + MOZ_ASSERT(aOldParent); 1.611 + MOZ_ASSERT(aNewParent); 1.612 + NS_ENSURE_TRUE_VOID(mLock); 1.613 + mLock = false; 1.614 + 1.615 + nsIDOMNode* oldParent = aOldParent->AsDOMNode(); 1.616 + nsIDOMNode* newParent = aNewParent->AsDOMNode(); 1.617 + 1.618 + for (uint32_t i = 0, count = mArray.Length(); i < count; ++i) { 1.619 + nsRangeStore* item = mArray[i]; 1.620 + NS_ENSURE_TRUE_VOID(item); 1.621 + 1.622 + // like a delete in aOldParent 1.623 + if (item->startNode == oldParent && item->startOffset > aOldOffset) { 1.624 + item->startOffset--; 1.625 + } 1.626 + if (item->endNode == oldParent && item->endOffset > aOldOffset) { 1.627 + item->endOffset--; 1.628 + } 1.629 + 1.630 + // and like an insert in aNewParent 1.631 + if (item->startNode == newParent && item->startOffset > aNewOffset) { 1.632 + item->startOffset++; 1.633 + } 1.634 + if (item->endNode == newParent && item->endOffset > aNewOffset) { 1.635 + item->endOffset++; 1.636 + } 1.637 + } 1.638 +} 1.639 + 1.640 + 1.641 + 1.642 +/*************************************************************************** 1.643 + * helper class for nsSelectionState. nsRangeStore stores range endpoints. 1.644 + */ 1.645 + 1.646 + // DEBUG: int32_t nsRangeStore::n = 0; 1.647 + 1.648 +nsRangeStore::nsRangeStore() 1.649 +{ 1.650 + // DEBUG: n++; printf("range store alloc count=%d\n", n); 1.651 +} 1.652 +nsRangeStore::~nsRangeStore() 1.653 +{ 1.654 + // DEBUG: n--; printf("range store alloc count=%d\n", n); 1.655 +} 1.656 + 1.657 +nsresult nsRangeStore::StoreRange(nsIDOMRange *aRange) 1.658 +{ 1.659 + NS_ENSURE_TRUE(aRange, NS_ERROR_NULL_POINTER); 1.660 + aRange->GetStartContainer(getter_AddRefs(startNode)); 1.661 + aRange->GetEndContainer(getter_AddRefs(endNode)); 1.662 + aRange->GetStartOffset(&startOffset); 1.663 + aRange->GetEndOffset(&endOffset); 1.664 + return NS_OK; 1.665 +} 1.666 + 1.667 +nsresult nsRangeStore::GetRange(nsRange** outRange) 1.668 +{ 1.669 + return nsRange::CreateRange(startNode, startOffset, endNode, endOffset, 1.670 + outRange); 1.671 +}