예제 #1
0
        /// <summary>
        /// Merges two naighboring lists ending and starting at position mergePosition
        /// </summary>
        /// <param name="mergePosition">
        /// Position at with two List elements are expected to appear next to each other
        /// </param>
        /// <returns>
        /// true if there were two mergeable List elements and merge happened.
        /// false if there is no pair of List elements at the mergePosition.
        /// </returns>
        internal static bool MergeLists(TextPointer mergePosition)
        {
            if (mergePosition.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.ElementEnd ||
                mergePosition.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.ElementStart)
            {
                return(false);
            }

            List precedingList = mergePosition.GetAdjacentElement(LogicalDirection.Backward) as List;
            List followingList = mergePosition.GetAdjacentElement(LogicalDirection.Forward) as List;

            if (precedingList == null || followingList == null)
            {
                return(false);
            }

            precedingList.Reposition(precedingList.ContentStart, followingList.ElementEnd);
            followingList.Reposition(null, null);

            // We need to set appropriate FlowDirection property on the new List and its paragraph children.
            // We take the FlowDirection value from the preceding list.
            TextRangeEdit.SetParagraphProperty(precedingList.ElementStart, precedingList.ElementEnd,
                                               Paragraph.FlowDirectionProperty, precedingList.GetValue(Paragraph.FlowDirectionProperty));

            return(true);
        }
예제 #2
0
        // Returns true if passed textelement has any Hyperlink or AnchoredBlock descendant.
        // It this context, the element or one of its ancestors is a Hyperlink.
        private static bool HasIllegalHyperlinkDescendant(TextElement element, bool throwIfIllegalDescendent)
        {
            TextPointer start = element.ElementStart;
            TextPointer end   = element.ElementEnd;

            while (start.CompareTo(end) < 0)
            {
                TextPointerContext forwardContext = start.GetPointerContext(LogicalDirection.Forward);
                if (forwardContext == TextPointerContext.ElementStart)
                {
                    TextElement nextElement = (TextElement)start.GetAdjacentElement(LogicalDirection.Forward);

                    if (nextElement is Hyperlink ||
                        nextElement is AnchoredBlock)
                    {
                        if (throwIfIllegalDescendent)
                        {
                            throw new InvalidOperationException(SR.Get(SRID.TextSchema_IllegalHyperlinkChild, nextElement.GetType()));
                        }
                        return(true);
                    }
                }

                start = start.GetNextContextPosition(LogicalDirection.Forward);
            }
            return(false);
        }
        // Token: 0x06003C04 RID: 15364 RVA: 0x00114F28 File Offset: 0x00113128
        private static bool HasIllegalHyperlinkDescendant(TextElement element, bool throwIfIllegalDescendent)
        {
            TextPointer textPointer = element.ElementStart;
            TextPointer elementEnd  = element.ElementEnd;

            while (textPointer.CompareTo(elementEnd) < 0)
            {
                TextPointerContext pointerContext = textPointer.GetPointerContext(LogicalDirection.Forward);
                if (pointerContext == TextPointerContext.ElementStart)
                {
                    TextElement textElement = (TextElement)textPointer.GetAdjacentElement(LogicalDirection.Forward);
                    if (textElement is Hyperlink || textElement is AnchoredBlock)
                    {
                        if (throwIfIllegalDescendent)
                        {
                            throw new InvalidOperationException(SR.Get("TextSchema_IllegalHyperlinkChild", new object[]
                            {
                                textElement.GetType()
                            }));
                        }
                        return(true);
                    }
                }
                textPointer = textPointer.GetNextContextPosition(LogicalDirection.Forward);
            }
            return(false);
        }
        // Token: 0x06003B80 RID: 15232 RVA: 0x0010EE34 File Offset: 0x0010D034
        internal static bool MergeLists(TextPointer mergePosition)
        {
            if (mergePosition.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.ElementEnd || mergePosition.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.ElementStart)
            {
                return(false);
            }
            List list  = mergePosition.GetAdjacentElement(LogicalDirection.Backward) as List;
            List list2 = mergePosition.GetAdjacentElement(LogicalDirection.Forward) as List;

            if (list == null || list2 == null)
            {
                return(false);
            }
            list.Reposition(list.ContentStart, list2.ElementEnd);
            list2.Reposition(null, null);
            TextRangeEdit.SetParagraphProperty(list.ElementStart, list.ElementEnd, Block.FlowDirectionProperty, list.GetValue(Block.FlowDirectionProperty));
            return(true);
        }
        /// <summary>Initializes a new instance of the <see cref="T:System.Windows.Documents.Hyperlink" /> class, taking two <see cref="T:System.Windows.Documents.TextPointer" /> objects that indicate the beginning and end of a selection of content to be contained by the new <see cref="T:System.Windows.Documents.Hyperlink" />.</summary>
        /// <param name="start">A <see cref="T:System.Windows.Documents.TextPointer" /> indicating the beginning of a selection of content to be contained by the new <see cref="T:System.Windows.Documents.Hyperlink" />.</param>
        /// <param name="end">A <see cref="T:System.Windows.Documents.TextPointer" /> indicating the end of a selection of content to be contained by the new <see cref="T:System.Windows.Documents.Hyperlink" />.</param>
        /// <exception cref="T:System.ArgumentNullException">
        ///         <paramref name="start" /> or <paramref name="end" /> is <see langword="null" />.</exception>
        /// <exception cref="T:System.ArgumentException">
        ///         <paramref name="start" /> and <paramref name="end" /> do not resolve to a range of content suitable for enclosure by a <see cref="T:System.Windows.Documents.Span" /> element; for example, if <paramref name="start" /> and <paramref name="end" /> indicate positions in different paragraphs.</exception>
        // Token: 0x0600301F RID: 12319 RVA: 0x000D8A18 File Offset: 0x000D6C18
        public Hyperlink(TextPointer start, TextPointer end) : base(start, end)
        {
            TextPointer textPointer = base.ContentStart.CreatePointer();
            TextPointer contentEnd  = base.ContentEnd;

            while (textPointer.CompareTo(contentEnd) < 0)
            {
                Hyperlink hyperlink = textPointer.GetAdjacentElement(LogicalDirection.Forward) as Hyperlink;
                if (hyperlink != null)
                {
                    hyperlink.Reposition(null, null);
                }
                else
                {
                    textPointer.MoveToNextContextPosition(LogicalDirection.Forward);
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Creates a new Hyperlink instance covering existing content.
        /// </summary>
        /// <param name="start">
        /// Start position of the new Hyperlink.
        /// </param>
        /// <param name="end">
        /// End position of the new Hyperlink.
        /// </param>
        /// <remarks>
        /// start and end must both be parented by the same Paragraph, otherwise
        /// the method will raise an ArgumentException.
        /// </remarks>
        public Hyperlink(TextPointer start, TextPointer end) : base(start, end)
        {
            // After inserting this Hyperlink, we need to extract any child Hyperlinks.

            TextPointer navigator = this.ContentStart.CreatePointer();
            TextPointer stop      = this.ContentEnd;

            while (navigator.CompareTo(stop) < 0)
            {
                Hyperlink hyperlink = navigator.GetAdjacentElement(LogicalDirection.Forward) as Hyperlink;

                if (hyperlink != null)
                {
                    hyperlink.Reposition(null, null);
                }
                else
                {
                    navigator.MoveToNextContextPosition(LogicalDirection.Forward);
                }
            }
        }
예제 #7
0
        public void SetCell(BufferCell cell, TextPointer position, LogicalDirection direction)
        {
            TextRange range = null;

            TextPointer positionPlus = position.GetNextInsertionPosition(LogicalDirection.Forward);
            if (positionPlus != null)
            {
                range = new TextRange(position, positionPlus);
            }

            if (null == range || range.IsEmpty)
            {
                position = position.GetInsertionPosition(LogicalDirection.Forward);
                if (position != null)
                {
                    Run r = position.GetAdjacentElement(LogicalDirection.Forward) as Run;

                    if (null != r)
                    {
                        if (r.Text.Length > 0)
                        {
                            char[] chr = r.Text.ToCharArray();
                            chr[0] = cell.Character;
                            r.Text = chr.ToString();
                        }
                        else
                        {
                            r.Text = cell.Character.ToString();
                        }
                    }
                    else
                    {
                        r = position.GetAdjacentElement(LogicalDirection.Backward) as Run;
                        if (null != r
                            && r.Background == BrushFromConsoleColor(cell.BackgroundColor)
                            && r.Foreground == BrushFromConsoleColor(cell.ForegroundColor)
                        )
                        {
                            if (r.Text.Length > 0)
                            {
                                r.Text = r.Text + cell.Character;
                            }
                            else
                            {
                                r.Text = cell.Character.ToString();
                            }
                        }
                        else
                        {
                            r = new Run(cell.Character.ToString(), position);
                        }
                    }
                    r.Background = BrushFromConsoleColor(cell.BackgroundColor);
                    r.Foreground = BrushFromConsoleColor(cell.ForegroundColor);
                    //position = r.ElementStart;
                }

            }
            else
            {

                range.Text = cell.Character.ToString();
                range.ApplyPropertyValue(TextElement.BackgroundProperty, BrushFromConsoleColor(cell.BackgroundColor));
                range.ApplyPropertyValue(TextElement.ForegroundProperty, BrushFromConsoleColor(cell.ForegroundColor));
            }
        }
예제 #8
0
        /// <summary>
        /// Merges two naighboring lists ending and starting at position mergePosition
        /// </summary>
        /// <param name="mergePosition">
        /// Position at with two List elements are expected to appear next to each other
        /// </param>
        /// <returns>
        /// true if there were two mergeable List elements and merge happened.
        /// false if there is no pair of List elements at the mergePosition.
        /// </returns>
        internal static bool MergeLists(TextPointer mergePosition)
        {
            if (mergePosition.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.ElementEnd ||
                mergePosition.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.ElementStart)
            {
                return false;
            }

            List precedingList = mergePosition.GetAdjacentElement(LogicalDirection.Backward) as List;
            List followingList = mergePosition.GetAdjacentElement(LogicalDirection.Forward) as List;

            if (precedingList == null || followingList == null)
            {
                return false;
            }

            precedingList.Reposition(precedingList.ContentStart, followingList.ElementEnd);
            followingList.Reposition(null, null);

            // We need to set appropriate FlowDirection property on the new List and its paragraph children. 
            // We take the FlowDirection value from the preceding list.
            TextRangeEdit.SetParagraphProperty(precedingList.ElementStart, precedingList.ElementEnd,
                Paragraph.FlowDirectionProperty, precedingList.GetValue(Paragraph.FlowDirectionProperty));

            return true;
        }
예제 #9
0
        // Merges inline elements with equivalent formatting properties at a given position 
        // Returns true if some changes happened at this position, false otherwise 
        internal static bool MergeFormattingInlines(TextPointer position)
        { 
            // Remove unnecessary Spans around this position
            RemoveUnnecessarySpans(position);

            // Delete empty formatting elements at this position (if any) 
            ExtractEmptyFormattingElements(position);
 
            // Skip formatting tags towards potential merging position 
            while (position.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart &&
                TextSchema.IsMergeableInline(position.Parent.GetType())) 
            {
                position = ((Inline)position.Parent).ElementStart;
            }
            while (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd && 
                TextSchema.IsMergeableInline(position.Parent.GetType()))
            { 
                position = ((Inline)position.Parent).ElementEnd; 
            }
 
            // Merge formatting Inlines at this position
            Inline firstInline, secondInline;
            bool merged = false;
            while ( 
                position.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementEnd &&
                position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart && 
                (firstInline = position.GetAdjacentElement(LogicalDirection.Backward) as Inline) != null && 
                (secondInline = position.GetAdjacentElement(LogicalDirection.Forward) as Inline) != null)
            { 
                if (TextSchema.IsFormattingType(firstInline.GetType()) && firstInline.TextRange.IsEmpty)
                {
                    firstInline.RepositionWithContent(null);
                    merged = true; 
                }
                else if (TextSchema.IsFormattingType(secondInline.GetType()) && secondInline.TextRange.IsEmpty) 
                { 
                    secondInline.RepositionWithContent(null);
                    merged = true; 
                }
                else if (TextSchema.IsKnownType(firstInline.GetType()) && TextSchema.IsKnownType(secondInline.GetType()) &&
                    (firstInline is Run && secondInline is Run || firstInline is Span && secondInline is Span) &&
                    TextSchema.IsMergeableInline(firstInline.GetType()) && TextSchema.IsMergeableInline(secondInline.GetType()) 
                    && CharacterPropertiesAreEqual(firstInline, secondInline))
                { 
                    firstInline.Reposition(firstInline.ElementStart, secondInline.ElementEnd); 
                    secondInline.Reposition(null, null);
                    merged = true; 
                }
                else
                {
                    break; 
                }
            } 
 
            // Now that Inlines have been merged we can try to optimize tree structure
            // by eliminating some unecessary wrapping Inlines 
            if (merged)
            {
                RemoveUnnecessarySpans(position);
            } 

            return merged; 
        } 
예제 #10
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);
        }
예제 #11
0
        // Helper for DeleteContentInternal.
        // If startPosition is placed at the very front of its parent's sibling list, 
        // returns the next sibling following endPositoin (the new head of the sibling
        // list).  The new head node is interesting because its IMELeftEdgeCharCount may
        // change because of its new position.
        private TextTreeTextElementNode GetNextIMEVisibleNode(TextPointer startPosition, TextPointer endPosition) 
        {
            TextTreeTextElementNode nextIMEVisibleNode = null; 
 
            TextElement adjacentElement = startPosition.GetAdjacentElement(LogicalDirection.Forward) as TextElement;
            if (adjacentElement != null && adjacentElement.IsFirstIMEVisibleSibling) 
            {
                nextIMEVisibleNode = (TextTreeTextElementNode)endPosition.GetAdjacentSiblingNode(LogicalDirection.Forward);
            }
 
            return nextIMEVisibleNode;
        } 
    /// <summary>
    /// Test if the text pointer is in a hyperlink
    /// </summary>
    /// <param name="pos"></param>
    /// <returns></returns>
    private bool searchHyperlink(TextPointer pos)
    {
      if (null == pos)
        return false;

      TextPointerContext context = pos.GetPointerContext(LogicalDirection.Backward);

      if (null == context)
        return false;

      if (TextPointerContext.ElementStart == context)
      {
        object elem = pos.GetAdjacentElement(LogicalDirection.Backward);
        if (elem is Hyperlink)
        {
          return true;
        }
      }
      else if (TextPointerContext.ElementEnd == context)
      {
        object elem = pos.GetAdjacentElement(LogicalDirection.Backward);
        if (elem is Hyperlink)
        {
          return false;
        }
      }

      // go backwards...   
      TextPointer back = pos.GetNextContextPosition(LogicalDirection.Backward);
      return searchHyperlink(back);
    }
예제 #13
0
        /// <summary>
        /// Writes the container into the specified XmlWriter.
        /// </summary>
        private void WriteContainer(TextPointer start, TextPointer end, XmlWriter writer)
        {
            TextElement textElement;

            System.Diagnostics.Debug.Assert(start != null);
            System.Diagnostics.Debug.Assert(end != null);
            System.Diagnostics.Debug.Assert(writer != null);

            _writer = writer;

            WriteWordXmlHead();

            _cursor = start;
            while (_cursor.CompareTo(end) < 0)
            {
                switch (_cursor.GetPointerContext(_dir))
                {
                    case TextPointerContext.None:
                        System.Diagnostics.Debug.Assert(false,
                            "Next symbol should never be None if cursor < End.");
                        break;
                    case TextPointerContext.Text:
                        RequireOpenRange();
                        _writer.WriteStartElement(WordXmlSerializer.WordTextTag);
                        _writer.WriteString(_cursor.GetTextInRun(_dir));
                        _writer.WriteEndElement();
                        break;
                    case TextPointerContext.EmbeddedElement:
                        DependencyObject obj = _cursor.GetAdjacentElement(LogicalDirection.Forward);
                        if (obj is LineBreak)
                        {
                            RequireOpenRange();
                            _writer.WriteStartElement(WordXmlSerializer.WordBreakTag);
                            _writer.WriteEndElement();
                        }
                        // TODO: try to convert some known embedded objects.
                        break;
                    case TextPointerContext.ElementStart:
                        TextPointer position;
                        position = _cursor;
                        position = position.GetNextContextPosition(LogicalDirection.Forward);
                        textElement = position.Parent as TextElement;

                        if (textElement is Paragraph)
                        {
                            RequireClosedRange();
                            RequireOpenParagraph();
                        }
                        else if (textElement is Inline)
                        {
                            RequireClosedRange();
                            RequireOpenParagraph();
                            RequireOpenRange();
                        }
                        break;
                    case TextPointerContext.ElementEnd:
                        textElement = _cursor.Parent as TextElement;

                        if (textElement is Inline)
                        {
                            RequireClosedRange();
                        }
                        else if (textElement is Paragraph)
                        {
                            RequireClosedParagraph();
                        }
                        break;
                }
                _cursor = _cursor.GetNextContextPosition(_dir);
            }

            RequireClosedRange();
            WriteWordXmlTail();
        }
        // 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);
        }
예제 #15
0
        //-------------------------------------------------------------------
        // IContentHost Helpers
        //-------------------------------------------------------------------

        /// <summary>
        /// Searches for an element in the _structuralCache.TextContainer. If the element is found, returns the
        /// position at which it is found. Otherwise returns null.
        /// </summary>
        /// <param name="e">
        /// Element to be found.
        /// </param>
        /// <param name="isLimitedToTextView">
        /// bool value indicating whether the search should only be limited to the text view of the page,
        /// in which case we search only text segments in the text view
        /// </param>
        private TextPointer FindElementPosition(IInputElement e, bool isLimitedToTextView)
        {
            // Parameter validation
            Debug.Assert(e != null);

            // Validate that this function is only called when a TextContainer exists as complex content
            Debug.Assert(_structuralCache.TextContainer is TextContainer);

            TextPointer elementPosition = null;

            // If e is a TextElement we can optimize by checking its TextContainer
            if (e is TextElement)
            {
                if ((e as TextElement).TextContainer == _structuralCache.TextContainer)
                {
                    // Element found
                    elementPosition = new TextPointer((e as TextElement).ElementStart);
                }
                // else: elementPosition stays null
            }
            else
            {
                // Else: search for e in the complex content
                if (!(_structuralCache.TextContainer.Start is TextPointer) ||
                    !(_structuralCache.TextContainer.End is TextPointer))
                {
                    // Invalid TextContainer, don't search
                    return null;
                }

                TextPointer searchPosition = new TextPointer(_structuralCache.TextContainer.Start as TextPointer);
                while (elementPosition == null && ((ITextPointer)searchPosition).CompareTo(_structuralCache.TextContainer.End) < 0)
                {
                    // Search each position in _structuralCache.TextContainer for the element
                    switch (searchPosition.GetPointerContext(LogicalDirection.Forward))
                    {
                        case TextPointerContext.EmbeddedElement:
                            DependencyObject embeddedObject = searchPosition.GetAdjacentElement(LogicalDirection.Forward);
                            if (embeddedObject is ContentElement || embeddedObject is UIElement)
                            {
                                if (embeddedObject == e as ContentElement || embeddedObject == e as UIElement)
                                {
                                    // Element found. Stop searching
                                    elementPosition = new TextPointer(searchPosition);
                                    break;
                                }
                            }
                            break;
                        default:
                            break;
                    }
                    searchPosition.MoveToNextContextPosition(LogicalDirection.Forward);
                }
            }

            // If the element was found, check if we are limited to text view
            if (elementPosition != null)
            {
                if (isLimitedToTextView)
                {
                    // At this point, we should create TextView if it doesn't exist
                    _textView = GetTextView();
                    Invariant.Assert(_textView != null);
                    // Check all segements in text view for position
                    for (int segmentIndex = 0; segmentIndex < ((ITextView)_textView).TextSegments.Count; segmentIndex++)
                    {
                        if (((ITextPointer)elementPosition).CompareTo(((ITextView)_textView).TextSegments[segmentIndex].Start) >= 0 &&
                            ((ITextPointer)elementPosition).CompareTo(((ITextView)_textView).TextSegments[segmentIndex].End) < 0)
                        {
                            // Element lies within a segment. Return position
                            return elementPosition;
                        }
                    }
                    // Element not found in all segments of TextView. Set position to null
                    elementPosition = null;
                }
            }
            return elementPosition;
        }
예제 #16
0
        // Finds a Run element with ElementStart at or after the given pointer
        // Creates Runs at potential run positions if encounters some. 
        private static Run GetNextRun(TextPointer pointer, TextPointer limit) 
        {
            Run run = null; 

            while (pointer != null && pointer.CompareTo(limit) < 0)
            {
                if (pointer.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart && 
                    (run = pointer.GetAdjacentElement(LogicalDirection.Forward) as Run) != null)
                { 
                    break; 
                }
 
                if (TextPointerBase.IsAtPotentialRunPosition(pointer))
                {
                    pointer = TextRangeEditTables.EnsureInsertionPosition(pointer);
                    Invariant.Assert(pointer.Parent is Run); 
                    run = pointer.Parent as Run;
                    break; 
                } 

                // Advance the scanning pointer 
                pointer = pointer.GetNextContextPosition(LogicalDirection.Forward);
            }

            return run; 
        }
예제 #17
0
        private static void ApplyStructuralInlinePropertyAcrossRun(TextPointer start, TextPointer end, Run run, DependencyProperty formattingProperty, object value)
        { 
            if (start.CompareTo(end) == 0)
            {
                // When the range is empty we should ignore the command, except
                // for the case of empty Run which can be encountered in empty paragraphs 
                if (run.IsEmpty)
                { 
                    run.SetValue(formattingProperty, value); 
                }
            } 
            else
            {
                // Split elements at start and end boundaries.
                start = SplitFormattingElements(start, /*keepEmptyFormatting:*/false, /*limitingAncestor*/run.Parent as TextElement); 
                end = SplitFormattingElements(end, /*keepEmptyFormatting:*/false, /*limitingAncestor*/run.Parent as TextElement);
 
                run = (Run)start.GetAdjacentElement(LogicalDirection.Forward); 
                run.SetValue(formattingProperty, value);
            } 

            // Clear property value from all ancestors of this Run.
            FixupStructuralPropertyEnvironment(run, formattingProperty);
        } 
예제 #18
0
        // ------------------------------------------------------------------
        // IContentHost Helpers
        // ------------------------------------------------------------------

        /// <summary>
        /// Searches for an element in the _complexContent.TextContainer. If the element is found, returns the
        /// position at which it is found. Otherwise returns null.
        /// </summary>
        /// <param name="e">
        /// Element to be found.
        /// </param>
        /// <remarks>
        /// We assume that this function is called from within text if the caller knows that _complexContent exists
        /// and contains a TextContainer. Hence we assert for this condition within the function
        /// </remarks>
        private TextPointer FindElementPosition(IInputElement e)
        {
            // Parameter validation
            Debug.Assert(e != null);

            // Validate that this function is only called when a TextContainer exists as complex content
            Debug.Assert(_complexContent.TextContainer is TextContainer);

            TextPointer position;

            // If e is a TextElement we can optimize by checking its TextContainer
            if (e is TextElement)
            {
                if ((e as TextElement).TextContainer == _complexContent.TextContainer)
                {
                    // Element found
                    position = new TextPointer((e as TextElement).ElementStart);
                    return position;
                }
            }

            // Else: search for e in the complex content
            position = new TextPointer((TextPointer)_complexContent.TextContainer.Start);
            while (position.CompareTo((TextPointer)_complexContent.TextContainer.End) < 0)
            {
                // Search each position in _complexContent.TextContainer for the element
                switch (position.GetPointerContext(LogicalDirection.Forward))
                {
                    case TextPointerContext.EmbeddedElement:
                        DependencyObject embeddedObject = position.GetAdjacentElement(LogicalDirection.Forward);
                        if (embeddedObject is ContentElement || embeddedObject is UIElement)
                        {
                            if (embeddedObject == e as ContentElement || embeddedObject == e as UIElement)
                            {
                                return position;
                            }
                        }
                        break;
                    default:
                          break;
                }
                position.MoveByOffset(+1);
            }

            // Reached end of complex content without finding the element
            return null;
        }
예제 #19
0
        private static void ApplyStructuralInlinePropertyAcrossInline(TextPointer start, TextPointer end, TextElement commonAncestor, DependencyProperty formattingProperty, object value) 
        { 
            start = SplitFormattingElements(start, /*keepEmptyFormatting:*/false, commonAncestor);
            end = SplitFormattingElements(end, /*keepEmptyFormatting:*/false, commonAncestor); 

            DependencyObject forwardElement = start.GetAdjacentElement(LogicalDirection.Forward);
            DependencyObject backwardElement = end.GetAdjacentElement(LogicalDirection.Backward);
            if (forwardElement == backwardElement && 
                (forwardElement is Run || forwardElement is Span))
            { 
                // After splitting we have exactly one Run or Span between start and end. Use it for setting the property. 
                Inline inline = (Inline)start.GetAdjacentElement(LogicalDirection.Forward);
 
                // Set the property to existing element.
                inline.SetValue(formattingProperty, value);

                // Clear property value from all ancestors of this inline. 
                FixupStructuralPropertyEnvironment(inline, formattingProperty);
 
                if (forwardElement is Span) 
                {
                    // Clear property value from all Span and Run children of this span. 
                    ClearPropertyValueFromSpansAndRuns(inline.ContentStart, inline.ContentEnd, formattingProperty);
                }
            }
            else 
            {
                Span span; 
 
                if (commonAncestor is Span &&
                    start.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart && 
                    end.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd &&
                    start.GetAdjacentElement(LogicalDirection.Backward) == commonAncestor)
                {
                    // Special case when start and end are at parent Span boundaries. 
                    // Don't need to create a new Span in this case.
                    span = (Span)commonAncestor; 
                } 
                else
                { 
                    // Create a new span from start to end.
                    span = new Span();
                    span.Reposition(start, end);
                } 

                // Set property on the span. 
                span.SetValue(formattingProperty, value); 

                // Clear property value from all ancestors of this span. 
                FixupStructuralPropertyEnvironment(span, formattingProperty);

                // Clear property value from all Span and Run children of this span.
                ClearPropertyValueFromSpansAndRuns(span.ContentStart, span.ContentEnd, formattingProperty); 
            }
        } 
        // Validates that the sibling element at this position belong to expected itemType (Inline, Block, ListItem)
        private static void ValidateMergingPositions(Type itemType, TextPointer start, TextPointer end)
        {
            if (start.CompareTo(end) < 0)
            {
                // Verify inner part
                TextPointerContext forwardFromStart = start.GetPointerContext(LogicalDirection.Forward);
                TextPointerContext backwardFromEnd = end.GetPointerContext(LogicalDirection.Backward);
                Invariant.Assert(forwardFromStart == TextPointerContext.ElementStart, "Expecting first opening tag of pasted fragment");
                Invariant.Assert(backwardFromEnd == TextPointerContext.ElementEnd, "Expecting last closing tag of pasted fragment");
                Invariant.Assert(itemType.IsAssignableFrom(start.GetAdjacentElement(LogicalDirection.Forward).GetType()), "The first pasted fragment item is expected to be a " + itemType.Name);
                Invariant.Assert(itemType.IsAssignableFrom(end.GetAdjacentElement(LogicalDirection.Backward).GetType()), "The last pasted fragment item is expected to be a " + itemType.Name);

                // Veryfy outer part
                TextPointerContext backwardFromStart = start.GetPointerContext(LogicalDirection.Backward);
                TextPointerContext forwardFromEnd = end.GetPointerContext(LogicalDirection.Forward);
                Invariant.Assert(backwardFromStart == TextPointerContext.ElementStart || backwardFromStart == TextPointerContext.ElementEnd || backwardFromStart == TextPointerContext.None, "Bad context preceding a pasted fragment");
                Invariant.Assert(!(backwardFromStart == TextPointerContext.ElementEnd) || itemType.IsAssignableFrom(start.GetAdjacentElement(LogicalDirection.Backward).GetType()), "An element preceding a pasted fragment is expected to be a " + itemType.Name);
                Invariant.Assert(forwardFromEnd == TextPointerContext.ElementStart || forwardFromEnd == TextPointerContext.ElementEnd || forwardFromEnd == TextPointerContext.None, "Bad context following a pasted fragment");
                Invariant.Assert(!(forwardFromEnd == TextPointerContext.ElementStart) || itemType.IsAssignableFrom(end.GetAdjacentElement(LogicalDirection.Forward).GetType()), "An element following a pasted fragment is expected to be a " + itemType.Name);
            }
        }
예제 #21
0
		private static IEnumerable<Paragraph> GetParagraphsBetweenPositions(TextPointer start, TextPointer end)
		{
			var changedParas = new HashSet<Paragraph>();
			var para = start.Paragraph ?? start.GetAdjacentElement(LogicalDirection.Forward) as Paragraph;

			while (para != null && para.ContentStart.CompareTo(end) < 0)
			{
				changedParas.Add(para);
				para = para.NextBlock as Paragraph;
			}

			return changedParas;
		}