Exemplo n.º 1
0
        /// <summary>
        /// Add a new atomic edit to the array.  The edits cannot intersect each other.
        /// The spans in each edit must be based on the current state of the buffer,
        /// and not based on post-edit spans.  This EditArray will calculate the
        /// post edit spans for you.
        /// </summary>
        /// <param name="editSpan"></param>
        internal void Add(EditSpan editSpan)
        {
            if (editSpan == null)
            {
                throw new ArgumentNullException("editSpan");
            }

            for (int i = this.editList.Count - 1; i >= 0; i--)
            {
                EditSpan e = (EditSpan)this.editList[i];
                if (TextSpanHelper.Intersects(editSpan.Span, e.Span))
                {
                    string msg = SR.GetString(SR.EditIntersects, i);
#if LANGTRACE
                    Debug.Assert(false, msg);
                    TraceEdits();
#endif
                    throw new System.ArgumentException(msg);
                }
                if (TextSpanHelper.StartsAfterStartOf(editSpan.Span, e.Span))
                {
                    this.editList.Insert(i + 1, editSpan);
                    return;
                }
            }
            this.editList.Insert(0, editSpan);
        }
Exemplo n.º 2
0
 //returns true is span1 is Embedded in span2
 internal static bool IsEmbedded(TextSpan span1, TextSpan span2)
 {
     return(!TextSpanHelper.IsSameSpan(span1, span2) &&
            TextSpanHelper.StartsAfterStartOf(span1, span2) &&
            TextSpanHelper.EndsBeforeEndOf(span1, span2));
 }
Exemplo n.º 3
0
        void UpdateSelection(ArrayList edits)
        {
            int  lineDelta        = 0;
            int  indexDelta       = 0;
            int  currentLine      = 0;
            bool updateStart      = true;
            bool updateEnd        = true;
            bool selectionIsEmpty = TextSpanHelper.IsEmpty(this.selection);

            foreach (EditSpan es in edits)
            {
                TextSpan span      = es.Span;
                string   text      = es.Text;
                int      lastLine  = currentLine;
                int      lastDelta = indexDelta;

                if (currentLine != span.iStartLine)
                {
                    // We have moved to a new line, so the indexDelta is no longer relevant.
                    currentLine = span.iStartLine;
                    indexDelta  = 0;
                }

                // Now adjust the span based on the current deltas.
                span.iStartIndex += indexDelta;
                if (currentLine == span.iEndLine)
                {
                    span.iEndIndex += indexDelta;
                }
                span.iStartLine += lineDelta;
                span.iEndLine   += lineDelta;

                if (updateStart)
                {
                    TextSpan original = es.Span;
                    if (TextSpanHelper.ContainsInclusive(original, this.selection.iStartLine, this.selection.iStartIndex))
                    {
                        bool atEnd = (this.selection.iStartLine == original.iEndLine &&
                                      this.selection.iStartIndex == original.iEndIndex);
                        this.selection.iStartLine  = span.iStartLine;
                        this.selection.iStartIndex = span.iStartIndex;
                        if (atEnd)
                        {
                            // Selection was positioned at the end of the span, so
                            // skip past the inserted text to approximate that location.
                            if (es.LineCount > 0)
                            {
                                this.selection.iStartLine += es.LineCount;
                                this.selection.iStartIndex = es.LengthOfLastLine;
                            }
                            else
                            {
                                this.selection.iStartIndex += es.LengthOfLastLine;
                            }
                        }
                        updateStart = false; // done
                    }
                    else if (TextSpanHelper.StartsAfterStartOf(original, this.selection))
                    {
                        if (this.selection.iStartLine == lastLine)
                        {
                            this.selection.iStartIndex += lastDelta;
                        }
                        this.selection.iStartLine += lineDelta;
                        updateStart = false; // done.
                    }
                    if (!updateStart && selectionIsEmpty)
                    {
                        this.selection.iEndLine  = this.selection.iStartLine;
                        this.selection.iEndIndex = this.selection.iStartIndex;
                        updateEnd = false; // done
                    }
                }
                if (updateEnd)
                {
                    TextSpan original = es.Span;
                    if (TextSpanHelper.StartsAfterEndOf(original, this.selection))
                    {
                        if (this.selection.iEndLine == lastLine)
                        {
                            this.selection.iEndIndex += lastDelta;
                        }
                        this.selection.iEndLine += lineDelta;
                        updateEnd = false; // done.
                    }
                    else if (TextSpanHelper.ContainsInclusive(original, this.selection.iEndLine, this.selection.iEndIndex))
                    {
                        this.selection.iEndLine  = span.iStartLine;
                        this.selection.iEndIndex = span.iStartIndex;
                        // Now include the text we are inserting in the selection
                        if (es.LineCount > 0)
                        {
                            this.selection.iEndLine += es.LineCount;
                            this.selection.iEndIndex = es.LengthOfLastLine;
                        }
                        else
                        {
                            this.selection.iEndIndex += es.LengthOfLastLine;
                        }
                        updateEnd = false; // done.
                    }
                }

                // Now adjust the deltas based on whether we just deleted anything.
                if (span.iStartLine != span.iEndLine)
                {
                    // We are deleting one or more lines.
                    lineDelta  += (span.iStartLine - span.iEndLine);
                    indexDelta  = -span.iEndIndex;
                    currentLine = span.iStartLine;
                }
                else if (span.iStartIndex != span.iEndIndex)
                {
                    indexDelta += (span.iStartIndex - span.iEndIndex);
                }

                // Now adjust the deltas based on what we just inserted
                if (!string.IsNullOrEmpty(text))
                {
                    lineDelta += es.LineCount;
                    if (span.iStartLine != span.iEndLine) // we removed multiple lines
                    {
                        if (es.LineCount == 0)            // but we are not inserting any new lines
                        // Then we are appending to this line.
                        {
                            indexDelta = span.iStartIndex + es.LengthOfLastLine;
                        }
                        else
                        {
                            indexDelta = es.LengthOfLastLine; // otherwise we just started a new line.
                        }
                    }
                    else if (es.LineCount != 0)     // we inserted new lines
                    // then calculate delta between new position versus position on original line.
                    {
                        indexDelta += es.LengthOfLastLine - span.iStartIndex;
                    }
                    else
                    {
                        indexDelta += es.LengthOfLastLine; // then delta is simply what we just inserted
                    }
                }
            }

            if (updateStart)
            {
                // Then start of selection is off the end of the list of edits.
                if (this.selection.iStartLine == currentLine)
                {
                    this.selection.iStartIndex += indexDelta;
                }
                this.selection.iStartLine += lineDelta;
            }
            if (updateEnd)
            {
                // Then end of selection is off the end of the list of edits.
                if (this.selection.iEndLine == currentLine)
                {
                    this.selection.iEndIndex += indexDelta;
                }
                this.selection.iEndLine += lineDelta;
            }
        }
Exemplo n.º 4
0
        const int ChunkThreshold = 1000; // don't combine chunks separate by more than 1000 characters.

        ArrayList MergeEdits(ArrayList edits)
        {
            StringBuilder buffer    = new StringBuilder();
            EditSpan      combined  = null;
            ArrayList     merged    = new ArrayList();
            ArrayList     markers   = GetTextMarkers();
            int           markerPos = 0;
            TextSpan      marker    = (markers.Count > 0) ? (TextSpan)markers[0] : new TextSpan();

            foreach (EditSpan editSpan in edits)
            {
                TextSpan span = editSpan.Span;
                string   text = editSpan.Text;

                if (markerPos < markers.Count &&
                    (TextSpanHelper.StartsAfterStartOf(span, marker) || TextSpanHelper.EndsAfterStartOf(span, marker)))
                {
                    AddCombinedEdit(combined, buffer, merged);
                    if (TextSpanHelper.Intersects(span, marker))
                    {
                        combined = null;
                        // Have to apply this as a distinct edit operation.
                        merged.Add(editSpan);
                    }
                    else
                    {
                        combined = editSpan;
                        buffer.Append(text);
                    }
                    while (++markerPos < markers.Count)
                    {
                        marker = (TextSpan)markers[markerPos];
                        if (!TextSpanHelper.StartsAfterStartOf(span, marker) && !TextSpanHelper.EndsAfterStartOf(span, marker))
                        {
                            break;
                        }
                    }
                }
                else if (combined == null)
                {
                    combined = editSpan;
                    buffer.Append(text);
                }
                else
                {
                    // A little sanity check here, if there are too many characters in between the two
                    // edits, then keep them separate.
                    int startOffset = source.GetPositionOfLineIndex(combined.Span.iEndLine, combined.Span.iEndIndex);
                    int endOffset   = source.GetPositionOfLineIndex(span.iStartLine, span.iStartIndex);
                    if (endOffset - startOffset > ChunkThreshold)
                    {
                        AddCombinedEdit(combined, buffer, merged);
                        combined = editSpan;
                        buffer.Append(text);
                    }
                    else
                    {
                        // merge edit spans by adding the text in-between the current and previous spans.
                        TextSpan s       = combined.Span;
                        string   between = this.source.GetText(s.iEndLine, s.iEndIndex, span.iStartLine, span.iStartIndex);
                        buffer.Append(between);
                        buffer.Append(text); // and add the new text.
                        s.iEndIndex   = span.iEndIndex;
                        s.iEndLine    = span.iEndLine;
                        combined.Span = s;
                    }
                }
            }
            AddCombinedEdit(combined, buffer, merged);
            return(merged);
        }