Coverage Report

Created: 2018-09-25 14:53

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