insertAtAllCursors method
Inserts textToInsert at all cursor positions (primary + secondary).
Insertions are performed from the last (highest-offset) cursor to the first so that earlier offsets are not invalidated by later insertions. After insertion, all cursor positions are updated to sit after the inserted text.
Implementation
void insertAtAllCursors(String textToInsert) {
if (readOnly || _multiCursors.isEmpty) return;
_flushBuffer();
final selectionBefore = _selection;
final primaryOffset = selection.extentOffset.clamp(0, _rope.length);
final offsets = <int>[primaryOffset];
for (final c in _multiCursors) {
offsets.add(_multiCursorToOffset(c).clamp(0, _rope.length));
}
final uniqueOffsets = offsets.toSet().toList()
..sort((a, b) => a.compareTo(b));
final compound = _undoController?.beginCompoundOperation();
for (final offset in uniqueOffsets.reversed) {
final safeOffset = offset.clamp(0, _rope.length);
_rope.insert(safeOffset, textToInsert);
_currentVersion++;
_recordInsertion(
safeOffset,
textToInsert,
selectionBefore,
TextSelection.collapsed(offset: safeOffset + textToInsert.length),
);
}
compound?.end();
final primaryIndex = uniqueOffsets.indexOf(primaryOffset);
final primaryNewOffset =
(primaryOffset + (primaryIndex + 1) * textToInsert.length).clamp(
0,
_rope.length,
);
_selection = TextSelection.collapsed(offset: primaryNewOffset);
_multiCursors.clear();
for (int k = 0; k < uniqueOffsets.length; k++) {
final newOffset = (uniqueOffsets[k] + (k + 1) * textToInsert.length)
.clamp(0, _rope.length);
if (newOffset == primaryNewOffset) continue;
final newLine = _rope.getLineAtOffset(newOffset);
final newLineStart = _rope.getLineStartOffset(newLine);
_multiCursors.add((line: newLine, character: newOffset - newLineStart));
}
multiCursorsChanged = true;
dirtyRegion = TextRange(start: 0, end: _rope.length);
_scheduleSyncToConnection();
notifyListeners();
}