// Creates a redo unit from an undo unit. private CompositionParentUndoUnit(CompositionParentUndoUnit undoUnit) : base(undoUnit) { _isFirstCompositionUnit = undoUnit._isFirstCompositionUnit; _isLastCompositionUnit = undoUnit._isLastCompositionUnit; }
// Merges another unit into this unit. internal void MergeCompositionUnit(CompositionParentUndoUnit unit) { object[] units = unit.CopyUnits(); Invariant.Assert(this.Locked); // If this fails, then the Locked = true below is invalid. this.Locked = false; for (int i = units.Length - 1; i >= 0; i--) { Add((IUndoUnit)units[i]); } this.Locked = true; MergeRedoSelectionState(unit); _isLastCompositionUnit |= unit.IsLastCompositionUnit; }
// Opens the composition undo unit if it exists on the top // of the stack. Otherwise, create a new composition undo unit // and add it to the undo stack. private CompositionParentUndoUnit OpenCompositionUndoUnit(ITextPointer compositionStart, ITextPointer compositionEnd) { UndoManager undoManager = UndoManager.GetUndoManager(this.TextContainer.Parent); if (undoManager == null || !undoManager.IsEnabled) { return null; } // The start position is where we'll put the caret if this composition is later // undone by a user. // // At this point some IMEs will not have updated the selection to a // position within the composition, suggesting that we always want to // use selection start. However, some IMEs will expand the composition backward on input // so the composition covers unmodified text. (E.g.: chinese prc pinyin IME // will expand to cover previously finalized text on <space> input.) // // So we use a hueristic: take the rightmost of the selection start or composition // start. ITextPointer start; if (compositionStart == null) { Invariant.Assert(compositionEnd == null); GetCompositionPositions(out compositionStart, out compositionEnd); } if (compositionStart != null && compositionStart.CompareTo(this.TextSelection.Start) > 0) { start = compositionStart; } else { start = this.TextSelection.Start; } CompositionParentUndoUnit unit = new CompositionParentUndoUnit(this.TextSelection, start, start, _nextUndoUnitIsFirstCompositionUnit); _nextUndoUnitIsFirstCompositionUnit = false; // Add the given composition undo unit to the undo manager and making it // as the opened undo unit. undoManager.Open(unit); return unit; }