// Token: 0x06003B87 RID: 15239 RVA: 0x0010F4AC File Offset: 0x0010D6AC
        internal static bool ParagraphsAreMergeable(Block firstParagraphOrBlockUIContainer, Block secondParagraphOrBlockUIContainer)
        {
            if (firstParagraphOrBlockUIContainer == null || secondParagraphOrBlockUIContainer == null || firstParagraphOrBlockUIContainer == secondParagraphOrBlockUIContainer)
            {
                return(false);
            }
            TextPointer textPointer  = firstParagraphOrBlockUIContainer.ElementEnd;
            TextPointer elementStart = secondParagraphOrBlockUIContainer.ElementStart;

            while (textPointer.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd)
            {
                if (!TextSchema.AllowsParagraphMerging(textPointer.Parent.GetType()))
                {
                    return(false);
                }
                textPointer = textPointer.GetNextContextPosition(LogicalDirection.Forward);
            }
            while (textPointer.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart)
            {
                if (textPointer.CompareTo(elementStart) == 0)
                {
                    return(true);
                }
                textPointer = textPointer.GetNextContextPosition(LogicalDirection.Forward);
                if (!TextSchema.AllowsParagraphMerging(textPointer.Parent.GetType()))
                {
                    return(false);
                }
            }
            return(false);
        }
Beispiel #2
0
        // Checks whether two paragraphs are meargeable.
        // To be meargeable they need to be separated by s sequence of closing, then opening
        // tags only.
        // And all tags must be Sections/Lists/ListItems only.
        internal static bool ParagraphsAreMergeable(Block firstParagraphOrBlockUIContainer, Block secondParagraphOrBlockUIContainer)
        {
            if (firstParagraphOrBlockUIContainer == null || secondParagraphOrBlockUIContainer == null ||
                firstParagraphOrBlockUIContainer == secondParagraphOrBlockUIContainer)
            {
                return(false); // nothing to merge
            }

            TextPointer position = firstParagraphOrBlockUIContainer.ElementEnd;
            TextPointer startOfSecondParagraph = secondParagraphOrBlockUIContainer.ElementStart;

            // Skip and check all closing tags (if any)
            while (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd)
            {
                if (!TextSchema.AllowsParagraphMerging(position.Parent.GetType()))
                {
                    return(false); // Crossing hard-structured element. Paragraphs are not meargeable.
                }

                position = position.GetNextContextPosition(LogicalDirection.Forward);
            }

            // Skip and check all opening tags (if any)
            while (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart)
            {
                if (position.CompareTo(startOfSecondParagraph) == 0)
                {
                    // Successfully skipped all tags, and reached the seconfParagraph.
                    // The paragraphs are meargeable.
                    return(true);
                }

                position = position.GetNextContextPosition(LogicalDirection.Forward);

                if (!TextSchema.AllowsParagraphMerging(position.Parent.GetType()))
                {
                    return(false); // Crossing hardd-structured element. Paragraphs are not meargeable.
                }
            }

            // Non-tag run found. Paragraphs are not meargeable.
            return(false);
        }
Beispiel #3
0
        // --------------------------------------------------------------------
        //
        // Internal Methods
        //
        // --------------------------------------------------------------------

        #region Internal Methods

        /// <summary>
        /// Merges two paragraphs followinng one another.
        /// The content of a second paragraph is moved into the end
        /// of the first one.
        /// </summary>
        /// <param name="firstParagraphOrBlockUIContainer">
        /// First of two merged paragraphs or BlockUIContainer.
        /// </param>
        /// <param name="secondParagraphOrBlockUIContainer">
        /// Second of two mered paragraphs or BlockUIContainer.
        /// </param>
        /// <returns>
        /// true if paragraphs have been merged; false if no actions where made.
        /// </returns>
        internal static bool MergeParagraphs(Block firstParagraphOrBlockUIContainer, Block secondParagraphOrBlockUIContainer)
        {
            if (!ParagraphsAreMergeable(firstParagraphOrBlockUIContainer, secondParagraphOrBlockUIContainer))
            {
                return(false); // Cannot mearge these paragraphs.
            }

            // Store parent list item of a second paragraph -
            // to correct its structure after the merge
            ListItem secondListItem = secondParagraphOrBlockUIContainer.PreviousBlock == null ? secondParagraphOrBlockUIContainer.Parent as ListItem : null;

            if (secondListItem != null && secondListItem.PreviousListItem == null && secondParagraphOrBlockUIContainer.NextBlock is List)
            {
                // The second paragraph is a first list item in some list.
                // It has a sublists in it, so this sublist must be unindented
                // to avoid double bulleted line.
                List sublistOfSecondParagraph = (List)secondParagraphOrBlockUIContainer.NextBlock;
                if (sublistOfSecondParagraph.ElementEnd.CompareTo(secondListItem.ContentEnd) == 0)
                {
                    secondListItem.Reposition(null, null);
                }
                else
                {
                    secondListItem.Reposition(sublistOfSecondParagraph.ElementEnd, secondListItem.ContentEnd);
                }
                // At this point the schema is temporaty broken: the secondParagraph and the sublistOfSecondParagraph have List as a parent
                sublistOfSecondParagraph.Reposition(null, null);
                // The schema is repared as to sublistOfSecondParagraph concern, but still broken for secondParagraph - must be corrected in the following code
            }

            // Move the second paragraph out of its wrappers separating from the first paragraph (if any).
            // We can not use RepositionWithContent because it would destroy
            // all pointers and ranges within a moved paragraph.
            // Instead we reposition elements around the two paragraphs.
            while (secondParagraphOrBlockUIContainer.ElementStart.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart)
            {
                TextElement parentBlock = (TextElement)secondParagraphOrBlockUIContainer.Parent;
                Invariant.Assert(parentBlock != null);
                Invariant.Assert(TextSchema.AllowsParagraphMerging(parentBlock.GetType()));

                if (secondParagraphOrBlockUIContainer.ElementEnd.CompareTo(parentBlock.ContentEnd) == 0)
                {
                    // Remove ancestor block if it becomes empty
                    parentBlock.Reposition(null, null);
                }
                else
                {
                    // Move ancestor's Start after the end of our paragraph
                    parentBlock.Reposition(secondParagraphOrBlockUIContainer.ElementEnd, parentBlock.ContentEnd);
                }
            }

            // Store a position after the second paragraph where list merging may be needed
            TextPointer positionAfterSecondParagraph = secondParagraphOrBlockUIContainer.ElementEnd.GetFrozenPointer(LogicalDirection.Forward);

            // Move the second paragraph to become an immediate following sibling of the first paragraph
            while (true)
            {
                TextElement previousBlock = secondParagraphOrBlockUIContainer.ElementStart.GetAdjacentElement(LogicalDirection.Backward) as TextElement;
                // Note: We cannot use Block.NextSibling property, because the structure is invalid during this process

                Invariant.Assert(previousBlock != null);

                if (previousBlock is Paragraph || previousBlock is BlockUIContainer)
                {
                    break;
                }

                Invariant.Assert(TextSchema.AllowsParagraphMerging(previousBlock.GetType()));
                previousBlock.Reposition(previousBlock.ContentStart, secondParagraphOrBlockUIContainer.ElementEnd);
            }

            // Now that paragraphs are next to each other merge them.

            // If one of paragraphs is empty we will apply special logic - to preserve a formatting from a non-empty one
            if (secondParagraphOrBlockUIContainer.TextRange.IsEmpty)
            {
                secondParagraphOrBlockUIContainer.RepositionWithContent(null);
            }
            else if (firstParagraphOrBlockUIContainer.TextRange.IsEmpty)
            {
                firstParagraphOrBlockUIContainer.RepositionWithContent(null);
            }
            else if (firstParagraphOrBlockUIContainer is Paragraph && secondParagraphOrBlockUIContainer is Paragraph)
            {
                // Do reposition magic for merging paragraph content
                // without destroying any pointers positioned in them.
                // Pull the second paragraph into the first one
                Invariant.Assert(firstParagraphOrBlockUIContainer.ElementEnd.CompareTo(secondParagraphOrBlockUIContainer.ElementStart) == 0);
                firstParagraphOrBlockUIContainer.Reposition(firstParagraphOrBlockUIContainer.ContentStart, secondParagraphOrBlockUIContainer.ElementEnd);

                // Store inline merging position
                TextPointer inlineMergingPosition = secondParagraphOrBlockUIContainer.ElementStart;

                // Now we can delete the second paragraph
                secondParagraphOrBlockUIContainer.Reposition(null, null);

                // Merge formatting elements at the point of paragraphs merging
                TextRangeEdit.MergeFormattingInlines(inlineMergingPosition);
            }

            // Merge ListItems wrapping first and second paragraphs.
            ListItem followingListItem = positionAfterSecondParagraph.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart
                ? positionAfterSecondParagraph.GetAdjacentElement(LogicalDirection.Forward) as ListItem : null;

            if (followingListItem != null && followingListItem == secondListItem)
            {
                ListItem precedingListItem = positionAfterSecondParagraph.GetAdjacentElement(LogicalDirection.Backward) as ListItem;
                if (precedingListItem != null)
                {
                    // Merge the second list item with the preceding one
                    Invariant.Assert(positionAfterSecondParagraph.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart);
                    Invariant.Assert(positionAfterSecondParagraph.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementEnd);
                    precedingListItem.Reposition(precedingListItem.ContentStart, followingListItem.ElementEnd);
                    followingListItem.Reposition(null, null);
                }
            }

            // Merge lists at merge position
            MergeLists(positionAfterSecondParagraph);

            return(true);
        }
        // Token: 0x06003B7E RID: 15230 RVA: 0x0010EB84 File Offset: 0x0010CD84
        internal static bool MergeParagraphs(Block firstParagraphOrBlockUIContainer, Block secondParagraphOrBlockUIContainer)
        {
            if (!TextRangeEditLists.ParagraphsAreMergeable(firstParagraphOrBlockUIContainer, secondParagraphOrBlockUIContainer))
            {
                return(false);
            }
            ListItem listItem = (secondParagraphOrBlockUIContainer.PreviousBlock == null) ? (secondParagraphOrBlockUIContainer.Parent as ListItem) : null;

            if (listItem != null && listItem.PreviousListItem == null && secondParagraphOrBlockUIContainer.NextBlock is List)
            {
                List list = (List)secondParagraphOrBlockUIContainer.NextBlock;
                if (list.ElementEnd.CompareTo(listItem.ContentEnd) == 0)
                {
                    listItem.Reposition(null, null);
                }
                else
                {
                    listItem.Reposition(list.ElementEnd, listItem.ContentEnd);
                }
                list.Reposition(null, null);
            }
            while (secondParagraphOrBlockUIContainer.ElementStart.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart)
            {
                TextElement textElement = (TextElement)secondParagraphOrBlockUIContainer.Parent;
                Invariant.Assert(textElement != null);
                Invariant.Assert(TextSchema.AllowsParagraphMerging(textElement.GetType()));
                if (secondParagraphOrBlockUIContainer.ElementEnd.CompareTo(textElement.ContentEnd) == 0)
                {
                    textElement.Reposition(null, null);
                }
                else
                {
                    textElement.Reposition(secondParagraphOrBlockUIContainer.ElementEnd, textElement.ContentEnd);
                }
            }
            TextPointer frozenPointer = secondParagraphOrBlockUIContainer.ElementEnd.GetFrozenPointer(LogicalDirection.Forward);

            for (;;)
            {
                TextElement textElement2 = secondParagraphOrBlockUIContainer.ElementStart.GetAdjacentElement(LogicalDirection.Backward) as TextElement;
                Invariant.Assert(textElement2 != null);
                if (textElement2 is Paragraph || textElement2 is BlockUIContainer)
                {
                    break;
                }
                Invariant.Assert(TextSchema.AllowsParagraphMerging(textElement2.GetType()));
                textElement2.Reposition(textElement2.ContentStart, secondParagraphOrBlockUIContainer.ElementEnd);
            }
            if (secondParagraphOrBlockUIContainer.TextRange.IsEmpty)
            {
                secondParagraphOrBlockUIContainer.RepositionWithContent(null);
            }
            else if (firstParagraphOrBlockUIContainer.TextRange.IsEmpty)
            {
                firstParagraphOrBlockUIContainer.RepositionWithContent(null);
            }
            else if (firstParagraphOrBlockUIContainer is Paragraph && secondParagraphOrBlockUIContainer is Paragraph)
            {
                Invariant.Assert(firstParagraphOrBlockUIContainer.ElementEnd.CompareTo(secondParagraphOrBlockUIContainer.ElementStart) == 0);
                firstParagraphOrBlockUIContainer.Reposition(firstParagraphOrBlockUIContainer.ContentStart, secondParagraphOrBlockUIContainer.ElementEnd);
                TextPointer elementStart = secondParagraphOrBlockUIContainer.ElementStart;
                secondParagraphOrBlockUIContainer.Reposition(null, null);
                TextRangeEdit.MergeFormattingInlines(elementStart);
            }
            ListItem listItem2 = (frozenPointer.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart) ? (frozenPointer.GetAdjacentElement(LogicalDirection.Forward) as ListItem) : null;

            if (listItem2 != null && listItem2 == listItem)
            {
                ListItem listItem3 = frozenPointer.GetAdjacentElement(LogicalDirection.Backward) as ListItem;
                if (listItem3 != null)
                {
                    Invariant.Assert(frozenPointer.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart);
                    Invariant.Assert(frozenPointer.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementEnd);
                    listItem3.Reposition(listItem3.ContentStart, listItem2.ElementEnd);
                    listItem2.Reposition(null, null);
                }
            }
            TextRangeEditLists.MergeLists(frozenPointer);
            return(true);
        }