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