editor/libeditor/base/nsSelectionState.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
michael@0 7 #include "mozilla/dom/Selection.h" // for Selection
michael@0 8 #include "nsAString.h" // for nsAString_internal::Length
michael@0 9 #include "nsAutoPtr.h" // for nsRefPtr, getter_AddRefs, etc
michael@0 10 #include "nsCycleCollectionParticipant.h"
michael@0 11 #include "nsDebug.h" // for NS_ENSURE_TRUE, etc
michael@0 12 #include "nsEditor.h" // for nsEditor
michael@0 13 #include "nsEditorUtils.h" // for nsEditorUtils
michael@0 14 #include "nsError.h" // for NS_OK, etc
michael@0 15 #include "nsIDOMCharacterData.h" // for nsIDOMCharacterData
michael@0 16 #include "nsIDOMNode.h" // for nsIDOMNode
michael@0 17 #include "nsIDOMRange.h" // for nsIDOMRange, etc
michael@0 18 #include "nsISelection.h" // for nsISelection
michael@0 19 #include "nsISupportsImpl.h" // for nsRange::Release
michael@0 20 #include "nsRange.h" // for nsRange
michael@0 21 #include "nsSelectionState.h"
michael@0 22
michael@0 23 using namespace mozilla;
michael@0 24 using namespace mozilla::dom;
michael@0 25
michael@0 26 /***************************************************************************
michael@0 27 * class for recording selection info. stores selection as collection of
michael@0 28 * { {startnode, startoffset} , {endnode, endoffset} } tuples. Can't store
michael@0 29 * ranges since dom gravity will possibly change the ranges.
michael@0 30 */
michael@0 31 nsSelectionState::nsSelectionState() : mArray(){}
michael@0 32
michael@0 33 nsSelectionState::~nsSelectionState()
michael@0 34 {
michael@0 35 MakeEmpty();
michael@0 36 }
michael@0 37
michael@0 38 void
michael@0 39 nsSelectionState::DoTraverse(nsCycleCollectionTraversalCallback &cb)
michael@0 40 {
michael@0 41 for (uint32_t i = 0, iEnd = mArray.Length(); i < iEnd; ++i)
michael@0 42 {
michael@0 43 nsRangeStore* item = mArray[i];
michael@0 44 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
michael@0 45 "selection state mArray[i].startNode");
michael@0 46 cb.NoteXPCOMChild(item->startNode);
michael@0 47 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
michael@0 48 "selection state mArray[i].endNode");
michael@0 49 cb.NoteXPCOMChild(item->endNode);
michael@0 50 }
michael@0 51 }
michael@0 52
michael@0 53 void
michael@0 54 nsSelectionState::SaveSelection(Selection* aSel)
michael@0 55 {
michael@0 56 MOZ_ASSERT(aSel);
michael@0 57 int32_t arrayCount = mArray.Length();
michael@0 58 int32_t rangeCount = aSel->GetRangeCount();
michael@0 59
michael@0 60 // if we need more items in the array, new them
michael@0 61 if (arrayCount < rangeCount) {
michael@0 62 for (int32_t i = arrayCount; i < rangeCount; i++) {
michael@0 63 mArray.AppendElement();
michael@0 64 mArray[i] = new nsRangeStore();
michael@0 65 }
michael@0 66 } else if (arrayCount > rangeCount) {
michael@0 67 // else if we have too many, delete them
michael@0 68 for (int32_t i = arrayCount - 1; i >= rangeCount; i--) {
michael@0 69 mArray.RemoveElementAt(i);
michael@0 70 }
michael@0 71 }
michael@0 72
michael@0 73 // now store the selection ranges
michael@0 74 for (int32_t i = 0; i < rangeCount; i++) {
michael@0 75 mArray[i]->StoreRange(aSel->GetRangeAt(i));
michael@0 76 }
michael@0 77 }
michael@0 78
michael@0 79 nsresult
michael@0 80 nsSelectionState::RestoreSelection(nsISelection *aSel)
michael@0 81 {
michael@0 82 NS_ENSURE_TRUE(aSel, NS_ERROR_NULL_POINTER);
michael@0 83 nsresult res;
michael@0 84 uint32_t i, arrayCount = mArray.Length();
michael@0 85
michael@0 86 // clear out selection
michael@0 87 aSel->RemoveAllRanges();
michael@0 88
michael@0 89 // set the selection ranges anew
michael@0 90 for (i=0; i<arrayCount; i++)
michael@0 91 {
michael@0 92 nsRefPtr<nsRange> range;
michael@0 93 mArray[i]->GetRange(getter_AddRefs(range));
michael@0 94 NS_ENSURE_TRUE(range, NS_ERROR_UNEXPECTED);
michael@0 95
michael@0 96 res = aSel->AddRange(range);
michael@0 97 if(NS_FAILED(res)) return res;
michael@0 98
michael@0 99 }
michael@0 100 return NS_OK;
michael@0 101 }
michael@0 102
michael@0 103 bool
michael@0 104 nsSelectionState::IsCollapsed()
michael@0 105 {
michael@0 106 if (1 != mArray.Length()) return false;
michael@0 107 nsRefPtr<nsRange> range;
michael@0 108 mArray[0]->GetRange(getter_AddRefs(range));
michael@0 109 NS_ENSURE_TRUE(range, false);
michael@0 110 bool bIsCollapsed = false;
michael@0 111 range->GetCollapsed(&bIsCollapsed);
michael@0 112 return bIsCollapsed;
michael@0 113 }
michael@0 114
michael@0 115 bool
michael@0 116 nsSelectionState::IsEqual(nsSelectionState *aSelState)
michael@0 117 {
michael@0 118 NS_ENSURE_TRUE(aSelState, false);
michael@0 119 uint32_t i, myCount = mArray.Length(), itsCount = aSelState->mArray.Length();
michael@0 120 if (myCount != itsCount) return false;
michael@0 121 if (myCount < 1) return false;
michael@0 122
michael@0 123 for (i=0; i<myCount; i++)
michael@0 124 {
michael@0 125 nsRefPtr<nsRange> myRange, itsRange;
michael@0 126 mArray[i]->GetRange(getter_AddRefs(myRange));
michael@0 127 aSelState->mArray[i]->GetRange(getter_AddRefs(itsRange));
michael@0 128 NS_ENSURE_TRUE(myRange && itsRange, false);
michael@0 129
michael@0 130 int16_t compResult;
michael@0 131 nsresult rv;
michael@0 132 rv = myRange->CompareBoundaryPoints(nsIDOMRange::START_TO_START, itsRange, &compResult);
michael@0 133 if (NS_FAILED(rv) || compResult) return false;
michael@0 134 rv = myRange->CompareBoundaryPoints(nsIDOMRange::END_TO_END, itsRange, &compResult);
michael@0 135 if (NS_FAILED(rv) || compResult) return false;
michael@0 136 }
michael@0 137 // if we got here, they are equal
michael@0 138 return true;
michael@0 139 }
michael@0 140
michael@0 141 void
michael@0 142 nsSelectionState::MakeEmpty()
michael@0 143 {
michael@0 144 // free any items in the array
michael@0 145 mArray.Clear();
michael@0 146 }
michael@0 147
michael@0 148 bool
michael@0 149 nsSelectionState::IsEmpty()
michael@0 150 {
michael@0 151 return mArray.IsEmpty();
michael@0 152 }
michael@0 153
michael@0 154 /***************************************************************************
michael@0 155 * nsRangeUpdater: class for updating nsIDOMRanges in response to editor actions.
michael@0 156 */
michael@0 157
michael@0 158 nsRangeUpdater::nsRangeUpdater() : mArray(), mLock(false) {}
michael@0 159
michael@0 160 nsRangeUpdater::~nsRangeUpdater()
michael@0 161 {
michael@0 162 // nothing to do, we don't own the items in our array.
michael@0 163 }
michael@0 164
michael@0 165 void
michael@0 166 nsRangeUpdater::RegisterRangeItem(nsRangeStore *aRangeItem)
michael@0 167 {
michael@0 168 if (!aRangeItem) return;
michael@0 169 if (mArray.Contains(aRangeItem))
michael@0 170 {
michael@0 171 NS_ERROR("tried to register an already registered range");
michael@0 172 return; // don't register it again. It would get doubly adjusted.
michael@0 173 }
michael@0 174 mArray.AppendElement(aRangeItem);
michael@0 175 }
michael@0 176
michael@0 177 void
michael@0 178 nsRangeUpdater::DropRangeItem(nsRangeStore *aRangeItem)
michael@0 179 {
michael@0 180 if (!aRangeItem) return;
michael@0 181 mArray.RemoveElement(aRangeItem);
michael@0 182 }
michael@0 183
michael@0 184 nsresult
michael@0 185 nsRangeUpdater::RegisterSelectionState(nsSelectionState &aSelState)
michael@0 186 {
michael@0 187 uint32_t i, theCount = aSelState.mArray.Length();
michael@0 188 if (theCount < 1) return NS_ERROR_FAILURE;
michael@0 189
michael@0 190 for (i=0; i<theCount; i++)
michael@0 191 {
michael@0 192 RegisterRangeItem(aSelState.mArray[i]);
michael@0 193 }
michael@0 194
michael@0 195 return NS_OK;
michael@0 196 }
michael@0 197
michael@0 198 nsresult
michael@0 199 nsRangeUpdater::DropSelectionState(nsSelectionState &aSelState)
michael@0 200 {
michael@0 201 uint32_t i, theCount = aSelState.mArray.Length();
michael@0 202 if (theCount < 1) return NS_ERROR_FAILURE;
michael@0 203
michael@0 204 for (i=0; i<theCount; i++)
michael@0 205 {
michael@0 206 DropRangeItem(aSelState.mArray[i]);
michael@0 207 }
michael@0 208
michael@0 209 return NS_OK;
michael@0 210 }
michael@0 211
michael@0 212 // gravity methods:
michael@0 213
michael@0 214 nsresult
michael@0 215 nsRangeUpdater::SelAdjCreateNode(nsIDOMNode *aParent, int32_t aPosition)
michael@0 216 {
michael@0 217 if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
michael@0 218 NS_ENSURE_TRUE(aParent, NS_ERROR_NULL_POINTER);
michael@0 219 uint32_t i, count = mArray.Length();
michael@0 220 if (!count) {
michael@0 221 return NS_OK;
michael@0 222 }
michael@0 223
michael@0 224 nsRangeStore *item;
michael@0 225
michael@0 226 for (i=0; i<count; i++)
michael@0 227 {
michael@0 228 item = mArray[i];
michael@0 229 NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
michael@0 230
michael@0 231 if ((item->startNode.get() == aParent) && (item->startOffset > aPosition))
michael@0 232 item->startOffset++;
michael@0 233 if ((item->endNode.get() == aParent) && (item->endOffset > aPosition))
michael@0 234 item->endOffset++;
michael@0 235 }
michael@0 236 return NS_OK;
michael@0 237 }
michael@0 238
michael@0 239 nsresult
michael@0 240 nsRangeUpdater::SelAdjInsertNode(nsIDOMNode *aParent, int32_t aPosition)
michael@0 241 {
michael@0 242 return SelAdjCreateNode(aParent, aPosition);
michael@0 243 }
michael@0 244
michael@0 245 void
michael@0 246 nsRangeUpdater::SelAdjDeleteNode(nsIDOMNode *aNode)
michael@0 247 {
michael@0 248 if (mLock) {
michael@0 249 // lock set by Will/DidReplaceParent, etc...
michael@0 250 return;
michael@0 251 }
michael@0 252 MOZ_ASSERT(aNode);
michael@0 253 uint32_t i, count = mArray.Length();
michael@0 254 if (!count) {
michael@0 255 return;
michael@0 256 }
michael@0 257
michael@0 258 int32_t offset = 0;
michael@0 259 nsCOMPtr<nsIDOMNode> parent = nsEditor::GetNodeLocation(aNode, &offset);
michael@0 260
michael@0 261 // check for range endpoints that are after aNode and in the same parent
michael@0 262 nsRangeStore *item;
michael@0 263 for (i=0; i<count; i++)
michael@0 264 {
michael@0 265 item = mArray[i];
michael@0 266 MOZ_ASSERT(item);
michael@0 267
michael@0 268 if ((item->startNode.get() == parent) && (item->startOffset > offset))
michael@0 269 item->startOffset--;
michael@0 270 if ((item->endNode.get() == parent) && (item->endOffset > offset))
michael@0 271 item->endOffset--;
michael@0 272
michael@0 273 // check for range endpoints that are in aNode
michael@0 274 if (item->startNode == aNode)
michael@0 275 {
michael@0 276 item->startNode = parent;
michael@0 277 item->startOffset = offset;
michael@0 278 }
michael@0 279 if (item->endNode == aNode)
michael@0 280 {
michael@0 281 item->endNode = parent;
michael@0 282 item->endOffset = offset;
michael@0 283 }
michael@0 284
michael@0 285 // check for range endpoints that are in descendants of aNode
michael@0 286 nsCOMPtr<nsIDOMNode> oldStart;
michael@0 287 if (nsEditorUtils::IsDescendantOf(item->startNode, aNode))
michael@0 288 {
michael@0 289 oldStart = item->startNode; // save for efficiency hack below.
michael@0 290 item->startNode = parent;
michael@0 291 item->startOffset = offset;
michael@0 292 }
michael@0 293
michael@0 294 // avoid having to call IsDescendantOf() for common case of range startnode == range endnode.
michael@0 295 if ((item->endNode == oldStart) || nsEditorUtils::IsDescendantOf(item->endNode, aNode))
michael@0 296 {
michael@0 297 item->endNode = parent;
michael@0 298 item->endOffset = offset;
michael@0 299 }
michael@0 300 }
michael@0 301 }
michael@0 302
michael@0 303
michael@0 304 nsresult
michael@0 305 nsRangeUpdater::SelAdjSplitNode(nsIDOMNode *aOldRightNode, int32_t aOffset, nsIDOMNode *aNewLeftNode)
michael@0 306 {
michael@0 307 if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
michael@0 308 NS_ENSURE_TRUE(aOldRightNode && aNewLeftNode, NS_ERROR_NULL_POINTER);
michael@0 309 uint32_t i, count = mArray.Length();
michael@0 310 if (!count) {
michael@0 311 return NS_OK;
michael@0 312 }
michael@0 313
michael@0 314 int32_t offset;
michael@0 315 nsCOMPtr<nsIDOMNode> parent = nsEditor::GetNodeLocation(aOldRightNode, &offset);
michael@0 316
michael@0 317 // first part is same as inserting aNewLeftnode
michael@0 318 nsresult result = SelAdjInsertNode(parent,offset-1);
michael@0 319 NS_ENSURE_SUCCESS(result, result);
michael@0 320
michael@0 321 // next step is to check for range enpoints inside aOldRightNode
michael@0 322 nsRangeStore *item;
michael@0 323
michael@0 324 for (i=0; i<count; i++)
michael@0 325 {
michael@0 326 item = mArray[i];
michael@0 327 NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
michael@0 328
michael@0 329 if (item->startNode.get() == aOldRightNode)
michael@0 330 {
michael@0 331 if (item->startOffset > aOffset)
michael@0 332 {
michael@0 333 item->startOffset -= aOffset;
michael@0 334 }
michael@0 335 else
michael@0 336 {
michael@0 337 item->startNode = aNewLeftNode;
michael@0 338 }
michael@0 339 }
michael@0 340 if (item->endNode.get() == aOldRightNode)
michael@0 341 {
michael@0 342 if (item->endOffset > aOffset)
michael@0 343 {
michael@0 344 item->endOffset -= aOffset;
michael@0 345 }
michael@0 346 else
michael@0 347 {
michael@0 348 item->endNode = aNewLeftNode;
michael@0 349 }
michael@0 350 }
michael@0 351 }
michael@0 352 return NS_OK;
michael@0 353 }
michael@0 354
michael@0 355
michael@0 356 nsresult
michael@0 357 nsRangeUpdater::SelAdjJoinNodes(nsIDOMNode *aLeftNode,
michael@0 358 nsIDOMNode *aRightNode,
michael@0 359 nsIDOMNode *aParent,
michael@0 360 int32_t aOffset,
michael@0 361 int32_t aOldLeftNodeLength)
michael@0 362 {
michael@0 363 if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
michael@0 364 NS_ENSURE_TRUE(aLeftNode && aRightNode && aParent, NS_ERROR_NULL_POINTER);
michael@0 365 uint32_t i, count = mArray.Length();
michael@0 366 if (!count) {
michael@0 367 return NS_OK;
michael@0 368 }
michael@0 369
michael@0 370 nsRangeStore *item;
michael@0 371
michael@0 372 for (i=0; i<count; i++)
michael@0 373 {
michael@0 374 item = mArray[i];
michael@0 375 NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
michael@0 376
michael@0 377 if (item->startNode.get() == aParent)
michael@0 378 {
michael@0 379 // adjust start point in aParent
michael@0 380 if (item->startOffset > aOffset)
michael@0 381 {
michael@0 382 item->startOffset--;
michael@0 383 }
michael@0 384 else if (item->startOffset == aOffset)
michael@0 385 {
michael@0 386 // join keeps right hand node
michael@0 387 item->startNode = aRightNode;
michael@0 388 item->startOffset = aOldLeftNodeLength;
michael@0 389 }
michael@0 390 }
michael@0 391 else if (item->startNode.get() == aRightNode)
michael@0 392 {
michael@0 393 // adjust start point in aRightNode
michael@0 394 item->startOffset += aOldLeftNodeLength;
michael@0 395 }
michael@0 396 else if (item->startNode.get() == aLeftNode)
michael@0 397 {
michael@0 398 // adjust start point in aLeftNode
michael@0 399 item->startNode = aRightNode;
michael@0 400 }
michael@0 401
michael@0 402 if (item->endNode.get() == aParent)
michael@0 403 {
michael@0 404 // adjust end point in aParent
michael@0 405 if (item->endOffset > aOffset)
michael@0 406 {
michael@0 407 item->endOffset--;
michael@0 408 }
michael@0 409 else if (item->endOffset == aOffset)
michael@0 410 {
michael@0 411 // join keeps right hand node
michael@0 412 item->endNode = aRightNode;
michael@0 413 item->endOffset = aOldLeftNodeLength;
michael@0 414 }
michael@0 415 }
michael@0 416 else if (item->endNode.get() == aRightNode)
michael@0 417 {
michael@0 418 // adjust end point in aRightNode
michael@0 419 item->endOffset += aOldLeftNodeLength;
michael@0 420 }
michael@0 421 else if (item->endNode.get() == aLeftNode)
michael@0 422 {
michael@0 423 // adjust end point in aLeftNode
michael@0 424 item->endNode = aRightNode;
michael@0 425 }
michael@0 426 }
michael@0 427
michael@0 428 return NS_OK;
michael@0 429 }
michael@0 430
michael@0 431
michael@0 432 nsresult
michael@0 433 nsRangeUpdater::SelAdjInsertText(nsIDOMCharacterData *aTextNode, int32_t aOffset, const nsAString &aString)
michael@0 434 {
michael@0 435 if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
michael@0 436
michael@0 437 uint32_t count = mArray.Length();
michael@0 438 if (!count) {
michael@0 439 return NS_OK;
michael@0 440 }
michael@0 441 nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aTextNode));
michael@0 442 NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
michael@0 443
michael@0 444 uint32_t len=aString.Length(), i;
michael@0 445 nsRangeStore *item;
michael@0 446 for (i=0; i<count; i++)
michael@0 447 {
michael@0 448 item = mArray[i];
michael@0 449 NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
michael@0 450
michael@0 451 if ((item->startNode.get() == node) && (item->startOffset > aOffset))
michael@0 452 item->startOffset += len;
michael@0 453 if ((item->endNode.get() == node) && (item->endOffset > aOffset))
michael@0 454 item->endOffset += len;
michael@0 455 }
michael@0 456 return NS_OK;
michael@0 457 }
michael@0 458
michael@0 459
michael@0 460 nsresult
michael@0 461 nsRangeUpdater::SelAdjDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength)
michael@0 462 {
michael@0 463 if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
michael@0 464
michael@0 465 uint32_t i, count = mArray.Length();
michael@0 466 if (!count) {
michael@0 467 return NS_OK;
michael@0 468 }
michael@0 469 nsRangeStore *item;
michael@0 470 nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aTextNode));
michael@0 471 NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
michael@0 472
michael@0 473 for (i=0; i<count; i++)
michael@0 474 {
michael@0 475 item = mArray[i];
michael@0 476 NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
michael@0 477
michael@0 478 if ((item->startNode.get() == node) && (item->startOffset > aOffset))
michael@0 479 {
michael@0 480 item->startOffset -= aLength;
michael@0 481 if (item->startOffset < 0) item->startOffset = 0;
michael@0 482 }
michael@0 483 if ((item->endNode.get() == node) && (item->endOffset > aOffset))
michael@0 484 {
michael@0 485 item->endOffset -= aLength;
michael@0 486 if (item->endOffset < 0) item->endOffset = 0;
michael@0 487 }
michael@0 488 }
michael@0 489 return NS_OK;
michael@0 490 }
michael@0 491
michael@0 492
michael@0 493 nsresult
michael@0 494 nsRangeUpdater::WillReplaceContainer()
michael@0 495 {
michael@0 496 if (mLock) return NS_ERROR_UNEXPECTED;
michael@0 497 mLock = true;
michael@0 498 return NS_OK;
michael@0 499 }
michael@0 500
michael@0 501
michael@0 502 nsresult
michael@0 503 nsRangeUpdater::DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode)
michael@0 504 {
michael@0 505 NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED);
michael@0 506 mLock = false;
michael@0 507
michael@0 508 NS_ENSURE_TRUE(aOriginalNode && aNewNode, NS_ERROR_NULL_POINTER);
michael@0 509 uint32_t i, count = mArray.Length();
michael@0 510 if (!count) {
michael@0 511 return NS_OK;
michael@0 512 }
michael@0 513
michael@0 514 nsRangeStore *item;
michael@0 515
michael@0 516 for (i=0; i<count; i++)
michael@0 517 {
michael@0 518 item = mArray[i];
michael@0 519 NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
michael@0 520
michael@0 521 if (item->startNode.get() == aOriginalNode)
michael@0 522 item->startNode = aNewNode;
michael@0 523 if (item->endNode.get() == aOriginalNode)
michael@0 524 item->endNode = aNewNode;
michael@0 525 }
michael@0 526 return NS_OK;
michael@0 527 }
michael@0 528
michael@0 529
michael@0 530 nsresult
michael@0 531 nsRangeUpdater::WillRemoveContainer()
michael@0 532 {
michael@0 533 if (mLock) return NS_ERROR_UNEXPECTED;
michael@0 534 mLock = true;
michael@0 535 return NS_OK;
michael@0 536 }
michael@0 537
michael@0 538
michael@0 539 nsresult
michael@0 540 nsRangeUpdater::DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aOffset, uint32_t aNodeOrigLen)
michael@0 541 {
michael@0 542 NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED);
michael@0 543 mLock = false;
michael@0 544
michael@0 545 NS_ENSURE_TRUE(aNode && aParent, NS_ERROR_NULL_POINTER);
michael@0 546 uint32_t i, count = mArray.Length();
michael@0 547 if (!count) {
michael@0 548 return NS_OK;
michael@0 549 }
michael@0 550
michael@0 551 nsRangeStore *item;
michael@0 552
michael@0 553 for (i=0; i<count; i++)
michael@0 554 {
michael@0 555 item = mArray[i];
michael@0 556 NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
michael@0 557
michael@0 558 if (item->startNode.get() == aNode)
michael@0 559 {
michael@0 560 item->startNode = aParent;
michael@0 561 item->startOffset += aOffset;
michael@0 562 }
michael@0 563 else if ((item->startNode.get() == aParent) && (item->startOffset > aOffset))
michael@0 564 item->startOffset += (int32_t)aNodeOrigLen-1;
michael@0 565
michael@0 566 if (item->endNode.get() == aNode)
michael@0 567 {
michael@0 568 item->endNode = aParent;
michael@0 569 item->endOffset += aOffset;
michael@0 570 }
michael@0 571 else if ((item->endNode.get() == aParent) && (item->endOffset > aOffset))
michael@0 572 item->endOffset += (int32_t)aNodeOrigLen-1;
michael@0 573 }
michael@0 574 return NS_OK;
michael@0 575 }
michael@0 576
michael@0 577
michael@0 578 nsresult
michael@0 579 nsRangeUpdater::WillInsertContainer()
michael@0 580 {
michael@0 581 if (mLock) return NS_ERROR_UNEXPECTED;
michael@0 582 mLock = true;
michael@0 583 return NS_OK;
michael@0 584 }
michael@0 585
michael@0 586
michael@0 587 nsresult
michael@0 588 nsRangeUpdater::DidInsertContainer()
michael@0 589 {
michael@0 590 NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED);
michael@0 591 mLock = false;
michael@0 592 return NS_OK;
michael@0 593 }
michael@0 594
michael@0 595
michael@0 596 void
michael@0 597 nsRangeUpdater::WillMoveNode()
michael@0 598 {
michael@0 599 mLock = true;
michael@0 600 }
michael@0 601
michael@0 602
michael@0 603 void
michael@0 604 nsRangeUpdater::DidMoveNode(nsINode* aOldParent, int32_t aOldOffset,
michael@0 605 nsINode* aNewParent, int32_t aNewOffset)
michael@0 606 {
michael@0 607 MOZ_ASSERT(aOldParent);
michael@0 608 MOZ_ASSERT(aNewParent);
michael@0 609 NS_ENSURE_TRUE_VOID(mLock);
michael@0 610 mLock = false;
michael@0 611
michael@0 612 nsIDOMNode* oldParent = aOldParent->AsDOMNode();
michael@0 613 nsIDOMNode* newParent = aNewParent->AsDOMNode();
michael@0 614
michael@0 615 for (uint32_t i = 0, count = mArray.Length(); i < count; ++i) {
michael@0 616 nsRangeStore* item = mArray[i];
michael@0 617 NS_ENSURE_TRUE_VOID(item);
michael@0 618
michael@0 619 // like a delete in aOldParent
michael@0 620 if (item->startNode == oldParent && item->startOffset > aOldOffset) {
michael@0 621 item->startOffset--;
michael@0 622 }
michael@0 623 if (item->endNode == oldParent && item->endOffset > aOldOffset) {
michael@0 624 item->endOffset--;
michael@0 625 }
michael@0 626
michael@0 627 // and like an insert in aNewParent
michael@0 628 if (item->startNode == newParent && item->startOffset > aNewOffset) {
michael@0 629 item->startOffset++;
michael@0 630 }
michael@0 631 if (item->endNode == newParent && item->endOffset > aNewOffset) {
michael@0 632 item->endOffset++;
michael@0 633 }
michael@0 634 }
michael@0 635 }
michael@0 636
michael@0 637
michael@0 638
michael@0 639 /***************************************************************************
michael@0 640 * helper class for nsSelectionState. nsRangeStore stores range endpoints.
michael@0 641 */
michael@0 642
michael@0 643 // DEBUG: int32_t nsRangeStore::n = 0;
michael@0 644
michael@0 645 nsRangeStore::nsRangeStore()
michael@0 646 {
michael@0 647 // DEBUG: n++; printf("range store alloc count=%d\n", n);
michael@0 648 }
michael@0 649 nsRangeStore::~nsRangeStore()
michael@0 650 {
michael@0 651 // DEBUG: n--; printf("range store alloc count=%d\n", n);
michael@0 652 }
michael@0 653
michael@0 654 nsresult nsRangeStore::StoreRange(nsIDOMRange *aRange)
michael@0 655 {
michael@0 656 NS_ENSURE_TRUE(aRange, NS_ERROR_NULL_POINTER);
michael@0 657 aRange->GetStartContainer(getter_AddRefs(startNode));
michael@0 658 aRange->GetEndContainer(getter_AddRefs(endNode));
michael@0 659 aRange->GetStartOffset(&startOffset);
michael@0 660 aRange->GetEndOffset(&endOffset);
michael@0 661 return NS_OK;
michael@0 662 }
michael@0 663
michael@0 664 nsresult nsRangeStore::GetRange(nsRange** outRange)
michael@0 665 {
michael@0 666 return nsRange::CreateRange(startNode, startOffset, endNode, endOffset,
michael@0 667 outRange);
michael@0 668 }

mercurial