Exemplo n.º 1
0
        // Deletes a specified run of content.
        //
        // On exit,
        //   symbolsRemoved <== count of symbols actually removed.
        //   removeStartIndex <== offset of first symbol affected by the edit.
        //
        // removeStartIndex is always <= endPosition.Offset, but it does not necessarily
        // match the position of the logically removed content.  In some rare cases
        // a scoping element may be removed, meaning we have two or more runs of
        // removed content, and removeStartIndex + symbolsRemoved < the offset of
        // the last position affected by the operation.
        private void RemoveContent(ITextPointer startPosition, ITextPointer endPosition, out int symbolsRemoved, out int removeStartIndex)
        {
            symbolsRemoved = 0;
            removeStartIndex = startPosition.Offset;

            if (startPosition.CompareTo(endPosition) == 0)
                return;

            TextContainer container = (TextContainer)startPosition.TextContainer;

            symbolsRemoved = container.SymbolCount;

            if (startPosition is TextPointer)
            {
                _minSymbolsRemovedIndex = Int32.MaxValue;
            }

            startPosition.DeleteContentToPosition(endPosition);

            if (startPosition is TextPointer)
            {
                removeStartIndex = _minSymbolsRemovedIndex;
            }

            symbolsRemoved = symbolsRemoved - container.SymbolCount;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Deletes a content covered by two positions assuming that
        /// the content crosses only paragraph-mergeable boundaries (if at all) -
        /// Paragraphs, Sections, Lists, ListItems, but not harder structural 
        /// elements like Tables, TableCells, TableRows, Floaters, Figures.
        /// </summary> 
        /// <param name="start"> 
        /// Position indicating a beginning of deleted content.
        /// </param> 
        /// <param name="end">
        /// Position indicating an end of deleted content.
        /// </param>
        internal static void DeleteParagraphContent(ITextPointer start, ITextPointer end) 
        {
            // Parameters validation 
            Invariant.Assert(start != null, "null check: start"); 
            Invariant.Assert(end != null, "null check: end");
            Invariant.Assert(start.CompareTo(end) <= 0, "expecting: start <= end"); 

            if (!(start is TextPointer))
            {
                // Abstract text container. We can only use basic abstract functionality here: 
                start.DeleteContentToPosition(end);
                return; 
            } 

            TextPointer startPosition = (TextPointer)start; 
            TextPointer endPosition = (TextPointer)end;

            // Delete all equi-scoped content in the given range
            DeleteEquiScopedContent(startPosition, endPosition); // delete content runs from start to root 
            DeleteEquiScopedContent(endPosition, startPosition); // delete contentruns from end to root
 
            // Merge crossed elements 
            if (startPosition.CompareTo(endPosition) < 0)
            { 
                if (TextPointerBase.IsAfterLastParagraph(endPosition))
                {
                    // This means that end position is after the last paragraph of a text container.
 
                    // When the last paragraph is empty (and selection crosses its end boundary)
                    // we need to delete it. 
                    // When last paragraph is not empty, we have to leave it as is. 
                    while (startPosition.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart &&
                        startPosition.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd) 
                    {
                        //
                        TextElement parent = (TextElement)startPosition.Parent;
                        if (parent is Inline || TextSchema.AllowsParagraphMerging(parent.GetType())) 
                        {
                            parent.RepositionWithContent(null); 
                        } 
                        else
                        { 
                            break;
                        }
                    }
                } 
                else
                { 
                    Block firstParagraphOrBlockUIContainer = startPosition.ParagraphOrBlockUIContainer; 
                    Block secondParagraphOrBlockUIContainer = endPosition.ParagraphOrBlockUIContainer;
 
                    // If startPosition and/or endPosition is parented by an empty ListItem, create an implicit paragraph in it.
                    // This will enable the following code to merge paragraphs in list items.

                    if (firstParagraphOrBlockUIContainer == null && TextPointerBase.IsInEmptyListItem(startPosition)) 
                    {
                        startPosition = TextRangeEditTables.EnsureInsertionPosition(startPosition); 
                        firstParagraphOrBlockUIContainer = startPosition.Paragraph; 
                        Invariant.Assert(firstParagraphOrBlockUIContainer != null, "EnsureInsertionPosition must create a paragraph inside list item - 1");
                    } 
                    if (secondParagraphOrBlockUIContainer == null && TextPointerBase.IsInEmptyListItem(endPosition))
                    {
                        endPosition = TextRangeEditTables.EnsureInsertionPosition(endPosition);
                        secondParagraphOrBlockUIContainer = endPosition.Paragraph; 
                        Invariant.Assert(secondParagraphOrBlockUIContainer != null, "EnsureInsertionPosition must create a paragraph inside list item - 2");
                    } 
 
                    if (firstParagraphOrBlockUIContainer != null && secondParagraphOrBlockUIContainer != null)
                    { 
                        TextRangeEditLists.MergeParagraphs(firstParagraphOrBlockUIContainer, secondParagraphOrBlockUIContainer);
                    }
                    else
                    { 
                        // When crossing BlockUIContainer boundaries we need to clear
                        // any empty BlockUIContainers and empty adjacent paragraphs 
                        MergeEmptyParagraphsAndBlockUIContainers(startPosition, endPosition); 
                    }
                } 
            }

            // Remove empty formatting elements
            MergeFormattingInlines(startPosition); 
            MergeFormattingInlines(endPosition);
 
            // Check for remaining empty BlockUICOntainer or empty Hyperlink elements 
            if (startPosition.Parent is BlockUIContainer && ((BlockUIContainer)startPosition.Parent).IsEmpty)
            { 
                ((BlockUIContainer)startPosition.Parent).Reposition(null, null);
            }
            else if (startPosition.Parent is Hyperlink && ((Hyperlink)startPosition.Parent).IsEmpty)
            { 
                ((Hyperlink)startPosition.Parent).Reposition(null, null);
 
                // After deleting an empty hyperlink, we might have inlines to merge. 
                MergeFormattingInlines(startPosition);
            } 
            //
        }