diff options
Diffstat (limited to 'main/src/core/Mono.Texteditor/Mono.TextEditor/Document')
8 files changed, 284 insertions, 933 deletions
diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/BufferedTextReader.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/BufferedTextReader.cs deleted file mode 100644 index 77340951be..0000000000 --- a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/BufferedTextReader.cs +++ /dev/null @@ -1,93 +0,0 @@ -// BufferedTextReader.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2008 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -using System; -using System.IO; - -namespace Mono.TextEditor -{ - /// <summary> - /// Wraps the IBuffer interface to a System.IO.TextReader model. - /// </summary> - class BufferedTextReader : System.IO.TextReader - { - int position = 0; - IBuffer buffer; - - public BufferedTextReader (IBuffer buffer) - { - this.buffer = buffer; - } - - protected override void Dispose (bool disposing) - { - if (disposing) - buffer = null; - } - - public override void Close () - { - Dispose (); - } - - public override int Peek () - { - if (position < 0 || position >= buffer.TextLength) - return -1; - return buffer.GetCharAt (position); - } - - public override int Read () - { - if (position < 0 || position >= buffer.TextLength) - return -1; - return buffer.GetCharAt (position++); - } - - public override int Read (char[] buffer, int index, int count) - { - if (buffer == null) - throw new ArgumentNullException (); - int lastOffset = System.Math.Min (this.buffer.TextLength, position + count); - int length = lastOffset - position; - if (length <= 0) - return 0; - string text = this.buffer.GetTextAt (position, length); - text.CopyTo (0, buffer, index, length); - position += length; - return length; - } - - public override string ReadToEnd () - { - if (position < 0 || position >= buffer.TextLength) - return ""; - string result = this.buffer.GetTextAt (position, buffer.TextLength - position); - position = buffer.TextLength; - return result; - } - } -} diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/DiffTracker.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/DiffTracker.cs index 1b56c0130f..1c8a1e190a 100644 --- a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/DiffTracker.cs +++ b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/DiffTracker.cs @@ -46,7 +46,7 @@ namespace Mono.TextEditor public Mono.TextEditor.TextDocument.LineState GetLineState (DocumentLine line) { - if (line != null) { + if (line != null && lineStates != null) { try { var info = lineStates [line.LineNumber]; if (info != null) { diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/DocumentUpdateRequest.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/DocumentUpdateRequest.cs index bf4ce8f02d..baa5551ec1 100644 --- a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/DocumentUpdateRequest.cs +++ b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/DocumentUpdateRequest.cs @@ -29,7 +29,7 @@ namespace Mono.TextEditor { public abstract class DocumentUpdateRequest { - public abstract void Update (TextEditor editor); + public abstract void Update (MonoTextEditor editor); } public class SinglePositionUpdate : DocumentUpdateRequest @@ -42,7 +42,7 @@ namespace Mono.TextEditor this.column = column; } - public override void Update (TextEditor editor) + public override void Update (MonoTextEditor editor) { editor.RedrawPosition (line, column); } @@ -50,7 +50,7 @@ namespace Mono.TextEditor public class UpdateAll : DocumentUpdateRequest { - public override void Update (TextEditor editor) + public override void Update (MonoTextEditor editor) { editor.QueueDraw (); } @@ -65,7 +65,7 @@ namespace Mono.TextEditor this.line = line; } - public override void Update (TextEditor editor) + public override void Update (MonoTextEditor editor) { editor.RedrawLine (line); } @@ -81,7 +81,7 @@ namespace Mono.TextEditor this.end = end; } - public override void Update (TextEditor editor) + public override void Update (MonoTextEditor editor) { editor.TextViewMargin.PurgeLayoutCache (); editor.RedrawLines (start, end); diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/GapBuffer.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/GapBuffer.cs deleted file mode 100644 index 7ba81771aa..0000000000 --- a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/GapBuffer.cs +++ /dev/null @@ -1,599 +0,0 @@ -// GapBuffer.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2007 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// - -using System; -using System.Text; -using System.Collections.Generic; - -namespace Mono.TextEditor -{ - public sealed class GapBuffer : IBuffer - { - char[] buffer = new char[0]; - - int gapBegin = 0; - int gapEnd = 0; - int gapLength = 0; - - const int minGapLength = 4 * 1024; - const int maxGapLength = 32 * 1024; - - public int TextLength { - get { - return buffer.Length - gapLength; - } - } - - public void Insert (int offset, string text) - { - Replace (offset, 0, text); - } - - public void Remove (int offset, int count) - { - Replace (offset, count, null); - } - - public void Remove (TextSegment segment) - { - Remove (segment.Offset, segment.Length); - } - - public string GetTextAt (TextSegment segment) - { - return GetTextAt (segment.Offset, segment.Length); - } - - public string Text { - get { - return GetTextAt (0, TextLength); - } - set { - buffer = value != null ? value.ToCharArray () : new char[0]; - gapBegin = gapEnd = gapLength = 0; - } - } - - public char GetCharAt (int offset) - { - return buffer[offset < gapBegin ? offset : offset + gapLength]; - } - - public string GetTextAt (int offset, int count) - { - int end = offset + count; - if (end < gapBegin) - return new string (buffer, offset, count); - if (offset > gapBegin) - return new string (buffer, offset + gapLength, count); - - int leftBlockSize = gapBegin - offset; - int rightBlockSize = end - gapBegin; - char[] result = new char [leftBlockSize + rightBlockSize]; - Array.Copy (buffer, offset, result, 0, leftBlockSize); - Array.Copy (buffer, gapEnd, result, leftBlockSize, rightBlockSize); - return new string (result); - } - - public void Replace (int offset, int count, string text) - { - if (!string.IsNullOrEmpty (text)) { - PlaceGap (offset, text.Length - count); - text.CopyTo (0, buffer, offset, text.Length); - gapBegin += text.Length; - } else { - PlaceGap (offset, 0); - } - gapEnd += count; - gapLength = gapEnd - gapBegin; - if (gapLength > maxGapLength) - CreateBuffer (gapBegin, minGapLength); - } - - void PlaceGap (int newOffset, int minLength) - { - if (gapLength < minLength) { - if (minLength < maxGapLength) { - CreateBuffer (newOffset, minLength + (maxGapLength - minLength) / 2); - } else { - CreateBuffer (newOffset, minLength + minGapLength); - } - return; - } - - int delta = gapBegin - newOffset; - if (delta > 0) { - Array.Copy (buffer, newOffset, buffer, gapEnd - delta, delta); - } else { - Array.Copy (buffer, gapEnd, buffer, gapBegin, -delta); - } - gapBegin -= delta; - gapEnd -= delta; - } - - void CreateBuffer (int gapOffset, int gapLength) - { - gapLength = System.Math.Max (minGapLength, gapLength); - - char[] newBuffer = new char[TextLength + gapLength]; - if (gapOffset < gapBegin) { - Array.Copy (buffer, 0, newBuffer, 0, gapOffset); - Array.Copy (buffer, gapOffset, newBuffer, gapOffset + gapLength, gapBegin - gapOffset); - Array.Copy (buffer, gapEnd, newBuffer, newBuffer.Length - (buffer.Length - gapEnd), buffer.Length - gapEnd); - } else { - Array.Copy (buffer, 0, newBuffer, 0, gapBegin); - Array.Copy (buffer, gapEnd, newBuffer, gapBegin, gapOffset - gapBegin); - int lastPartLength = newBuffer.Length - (gapOffset + gapLength); - Array.Copy (buffer, buffer.Length - lastPartLength, newBuffer, gapOffset + gapLength, lastPartLength); - } - - gapBegin = gapOffset; - gapEnd = gapOffset + gapLength; - this.gapLength = gapLength; - buffer = newBuffer; - } - - - // TODO: Optimize! - int IBuffer.IndexOf (char c, int startIndex, int count) - { - return Text.IndexOf (c, startIndex, count); - } - - int IBuffer.IndexOfAny (char[] anyOf, int startIndex, int count) - { - return Text.IndexOfAny (anyOf, startIndex, count); - } - - public int IndexOf (string searchText, int startIndex, int count, StringComparison comparisonType) - { - return Text.IndexOf (searchText, startIndex, count, comparisonType); - } - - int IBuffer.LastIndexOf (char c, int startIndex, int count) - { - return Text.LastIndexOf (c, startIndex, count); - } - - public int LastIndexOf (string searchText, int startIndex, int count, StringComparison comparisonType) - { - return Text.LastIndexOf (searchText, startIndex, count, comparisonType); - } - -// #region Search -// unsafe int SearchForwardInternal (string pattern, int startIndex) -// { -// if (startIndex > gapBegin) -// startIndex += gapLength; -// -// int valueLen = pattern.Length; -// if (startIndex >= buffer.Length - valueLen + 1) -// return -1; -// -// fixed (char* bufferPtr = buffer, patternPtr = pattern) { -// char* ap = bufferPtr + startIndex; -// char* bufferPhysEnd = bufferPtr + buffer.Length; -// char* bufferEnd = bufferPhysEnd - valueLen + 1; -// char* gapBeginPtr = bufferPtr + gapBegin; -// char* gapEndPtr = bufferPtr + gapEnd; -// char* stopGap = gapBeginPtr - valueLen + 1; -// char* patternPos1Ptr = patternPtr + 1; -// char* patternEndPtr = patternPtr + valueLen; -// char p0 = *patternPtr; -// -// if (ap < gapBeginPtr) { -// if (stopGap > bufferPtr) { -// while (ap < stopGap) { -// if (*ap == p0) { -// char* p = ap + 1; -// char* v = patternPos1Ptr; -// while (v < patternEndPtr) { -// if (*p != *v) -// goto NextVal; -// v++; -// p++; -// } -// return (int)(ap - bufferPtr); -// } -// NextVal: -// ap++; -// } -// } -// -// while (ap != gapBeginPtr) { -// if (*ap == p0) { -// char* p = ap + 1; -// char* v = patternPos1Ptr; -// while (v < patternEndPtr) { -// if (*p != *v) -// goto NextVal; -// v++; -// p++; -// if (p == gapBeginPtr) -// p = gapEndPtr; -// } -// return (int)(ap - bufferPtr); -// } -// NextVal: -// ap++; -// } -// } -// -// if (ap < gapEndPtr) -// ap = gapEndPtr; -// if (ap < bufferEnd) { -// while (ap != bufferEnd) { -// if (*ap == p0) { -// char* p = ap + 1; -// char* v = patternPos1Ptr; -// while (v < patternEndPtr) { -// if (*p != *v) -// goto NextVal; -// v++; -// p++; -// } -// return (int)(ap - gapLength - bufferPtr); -// } -// NextVal: -// ap++; -// } -// } -// } -// return -1; -// } -// -// unsafe int SearchForwardInternalIgnoreCase (string pattern, int startIndex) -// { -// if (startIndex > gapBegin) -// startIndex += gapLength; -// -// int valueLen = pattern.Length; -// if (startIndex >= buffer.Length - valueLen + 1) -// return -1; -// -// fixed (char* bufferPtr = buffer, patternPtr = pattern) { -// char* ap = bufferPtr + startIndex; -// char* bufferPhysEnd = bufferPtr + buffer.Length; -// char* bufferEnd = bufferPhysEnd - valueLen + 1; -// char* gapBeginPtr = bufferPtr + gapBegin; -// char* gapEndPtr = bufferPtr + gapEnd; -// char* stopGap = gapBeginPtr - valueLen + 1; -// char* patternPos1Ptr = patternPtr + 1; -// char* patternEndPtr = patternPtr + valueLen; -// char p0 = *patternPtr; -// -// if (ap < gapBeginPtr) { -// if (stopGap > bufferPtr) { -// while (ap < stopGap) { -// if (char.ToUpper (*ap) == p0) { -// char* p = ap + 1; -// char* v = patternPos1Ptr; -// while (v < patternEndPtr) { -// if (char.ToUpper (*p) != *v) -// goto NextVal; -// v++; -// p++; -// } -// return (int)(ap - bufferPtr); -// } -// NextVal: -// ap++; -// } -// } -// -// while (ap != gapBeginPtr) { -// if (char.ToUpper (*ap) == p0) { -// char* p = ap + 1; -// char* v = patternPos1Ptr; -// while (v < patternEndPtr) { -// if (char.ToUpper (*p) != *v) -// goto NextVal; -// v++; -// p++; -// if (p == gapBeginPtr) -// p = gapEndPtr; -// } -// return (int)(ap - bufferPtr); -// } -// NextVal: -// ap++; -// } -// } -// -// if (ap < gapEndPtr) -// ap = gapEndPtr; -// if (ap < bufferEnd) { -// while (ap != bufferEnd) { -// if (char.ToUpper (*ap) == p0) { -// char* p = ap + 1; -// char* v = patternPos1Ptr; -// while (v < patternEndPtr) { -// if (char.ToUpper (*p) != *v) -// goto NextVal; -// v++; -// p++; -// } -// return (int)(ap - gapLength - bufferPtr); -// } -// NextVal: -// ap++; -// } -// } -// } -// return -1; -// } -// -// public IEnumerable<int> SearchForward (string pattern, int startIndex) -// { -// int idx = startIndex; -// while ((idx = SearchForwardInternal (pattern, idx)) != -1) { -// yield return idx; -// idx += pattern.Length; -// } -// } -// -// public IEnumerable<int> SearchForwardIgnoreCase (string pattern, int startIndex) -// { -// pattern = pattern.ToUpper (); -// int idx = startIndex; -// while ((idx = SearchForwardInternalIgnoreCase (pattern, idx)) != -1) { -// yield return idx; -// idx += pattern.Length; -// } -// } -// -// unsafe int SearchBackwardInternal (string pattern, int startIndex) -// { -// int valueLen = pattern.Length; -// if (startIndex < valueLen - 1) -// return -1; -// if (startIndex > gapBegin) -// startIndex += gapLength; -// fixed (char* bufferPtr = buffer, patternPtr = pattern) { -// char* ap = bufferPtr + startIndex; -// char* bufferEnd = bufferPtr + valueLen - 1; -// -// char* bufferPhysEnd = bufferPtr + buffer.Length; -// char* gapBeginPtr = bufferPtr + gapBegin; -// char* gapEndPtr = bufferPtr + gapEnd; -// char* stopGap = gapEndPtr + valueLen - 1; -// char* patternPos1Ptr = patternPtr + valueLen - 2; -// char* patternEndPtr = patternPtr - 1; -// char p0 = *(patternPtr + valueLen - 1); -// -// if (ap >= gapEndPtr) { -// if (stopGap < bufferPhysEnd) { -// while (ap >= stopGap) { -// if (*ap == p0) { -// char* p = ap - 1; -// char* v = patternPos1Ptr; -// while (v > patternEndPtr) { -// if (*p != *v) -// goto NextVal; -// v--; -// p--; -// } -// return (int)(p - gapLength - bufferPtr + 1); -// } -// NextVal: -// ap--; -// } -// } -// -// while (ap >= gapEndPtr) { -// if (*ap == p0) { -// char* p = ap - 1; -// char* v = patternPos1Ptr; -// while (v > patternEndPtr) { -// if (*p != *v) -// goto NextVal; -// v--; -// if (p == gapEndPtr) { -// p = gapBeginPtr - 1; -// } else { -// p--; -// } -// } -// if (p >= gapEndPtr) -// return (int)(p - gapLength - bufferPtr + 1); -// return (int)(p - bufferPtr + 1); -// } -// NextVal: -// ap--; -// } -// } -// -// while (ap >= bufferEnd) { -// if (*ap == p0) { -// char* p = ap - 1; -// char* v = patternPos1Ptr; -// while (v > patternEndPtr) { -// if (*p != *v) -// goto NextVal; -// v--; -// p--; -// } -// return (int)(p - bufferPtr + 1); -// } -// NextVal: -// ap--; -// } -// } -// return -1; -// } -// -// unsafe int SearchBackwardInternalIgnoreCase (string pattern, int startIndex) -// { -// int valueLen = pattern.Length; -// if (startIndex < valueLen - 1) -// return -1; -// if (startIndex > gapBegin) -// startIndex += gapLength; -// -// fixed (char* bufferPtr = buffer, patternPtr = pattern) { -// char* ap = bufferPtr + startIndex; -// char* bufferEnd = bufferPtr + valueLen - 1; -// -// char* bufferPhysEnd = bufferPtr + buffer.Length; -// char* gapBeginPtr = bufferPtr + gapBegin; -// char* gapEndPtr = bufferPtr + gapEnd; -// char* stopGap = gapEndPtr + valueLen - 1; -// char* patternPos1Ptr = patternPtr + valueLen - 2; -// char* patternEndPtr = patternPtr - 1; -// char p0 = *(patternPtr + valueLen - 1); -// -// if (ap >= gapEndPtr) { -// if (stopGap < bufferPhysEnd) { -// while (ap >= stopGap) { -// if (char.ToUpper (*ap) == p0) { -// char* p = ap - 1; -// char* v = patternPos1Ptr; -// while (v > patternEndPtr) { -// if (char.ToUpper (*p) != *v) -// goto NextVal; -// v--; -// p--; -// } -// return (int)(p - gapLength - bufferPtr + 1); -// } -// NextVal: -// ap--; -// } -// } -// -// while (ap >= gapEndPtr) { -// if (char.ToUpper (*ap) == p0) { -// char* p = ap - 1; -// char* v = patternPos1Ptr; -// while (v > patternEndPtr) { -// if (char.ToUpper (*p) != *v) -// goto NextVal; -// v--; -// if (p == gapEndPtr) { -// p = gapBeginPtr - 1; -// } else { -// p--; -// } -// } -// if (p >= gapEndPtr) -// return (int)(p - gapLength - bufferPtr + 1); -// return (int)(p - bufferPtr + 1); -// } -// NextVal: -// ap--; -// } -// } -// while (ap >= bufferEnd) { -// if (char.ToUpper (*ap) == p0) { -// char* p = ap - 1; -// char* v = patternPos1Ptr; -// while (v > patternEndPtr) { -// if (char.ToUpper (*p) != *v) -// goto NextVal; -// v--; -// p--; -// } -// return (int)(p - bufferPtr + 1); -// } -// NextVal: -// ap--; -// } -// } -// return -1; -// } -// -// public IEnumerable<int> SearchBackward (string pattern, int startIndex) -// { -// int idx = startIndex; -// while ((idx = SearchBackwardInternal (pattern, idx)) != -1) { -// yield return idx; -// idx -= pattern.Length; -// } -// } -// -// public IEnumerable<int> SearchBackwardIgnoreCase (string pattern, int startIndex) -// { -// pattern = pattern.ToUpper (); -// int idx = startIndex; -// while ((idx = SearchBackwardInternalIgnoreCase (pattern, idx)) != -1) { -// yield return idx; -// idx -= pattern.Length; -// } -// } -// -// /* Boyer-Moore-Horspool-Raita implementation: (but on Intel Core i brute force outpeforms it. -// -// static int[] ProcessString (string pattern) -// { -// var result = new int[char.MaxValue]; -// for (int i = 0; i < result.Length; i++) -// result[i] = pattern.Length - 1; -// for (int i = 0; i < pattern.Length - 1; ++i) { -// result[pattern[i]] = pattern.Length - i - 1; -// } -// return result; -// } -// unsafe static int bmhrSearchBytes (string text, string pattern, int textStart, int[] b) -// { -// int lastIndex = text.Length + pattern.Length - 1; -// if (textStart >= lastIndex) -// return -1; -// -// int m = pattern.Length - 1; -// int mMinusOne = pattern.Length - 2; -// -// var last = pattern[pattern.Length - 1]; -// var first = pattern[0]; -// -// fixed (char* textPtr = text, pattenrPtr = pattern) { -// char* i = textPtr + textStart + pattern.Length - 1; -// char* endText = textPtr + lastIndex; -// while (i < endText) { -// if (*i == last) { -// //if (*(i - m) == first) { -// char* k = i - 1; -// char* pp = pattenrPtr + mMinusOne; -// -// while (pp >= pattenrPtr && *k == *pp) { -// --k; -// --pp; -// } -// -// if (pp < pattenrPtr) -// return (int)(k - textPtr) + 1; -// // } -// } -// i += b[*i]; -// } -// } -// return -1; -// } -// * */ -// #endregion - - } -}
\ No newline at end of file diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/IBuffer.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/IBuffer.cs deleted file mode 100644 index 0cfffef74e..0000000000 --- a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/IBuffer.cs +++ /dev/null @@ -1,131 +0,0 @@ -// IBuffer.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2007 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// - -using System; -using System.Collections.Generic; -using System.Text; - -namespace Mono.TextEditor -{ - public interface IBuffer - { - /// <summary> - /// Gets the total text length. - /// </summary> - /// <returns>The length of the text, in characters.</returns> - /// <remarks>This is the same as Text.Length, but is more efficient because - /// it doesn't require creating a String object.</remarks> - int TextLength { - get; - } - - /// <summary> - /// Gets the whole text as string. - /// </summary> - string Text { - get; - set; - } - - /// <summary> - /// Replaces text. - /// </summary> - /// <param name="offset">The starting offset of the text to be replaced.</param> - /// <param name="count">The length of the text to be replaced.</param> - /// <param name="value">The new text.</param> - void Replace (int offset, int count, string value); - - /// <summary> - /// Retrieves the text for a portion of the document. - /// </summary> - /// <exception cref="ArgumentOutOfRangeException">offset or length is outside the valid range.</exception> - /// <remarks>This is the same as Text.Substring, but is more efficient because - /// it doesn't require creating a String object for the whole document.</remarks> - string GetTextAt (int offset, int count); - - /// <summary> - /// Gets a character at the specified position in the document. - /// </summary> - /// <paramref name="offset">The index of the character to get.</paramref> - /// <exception cref="ArgumentOutOfRangeException">Offset is outside the valid range (0 to TextLength-1).</exception> - /// <returns>The character at the specified position.</returns> - /// <remarks>This is the same as Text[offset], but is more efficient because - /// it doesn't require creating a String object.</remarks> - char GetCharAt (int offset); - - /// <summary> - /// Gets the index of the first occurrence of the character in the specified array. - /// </summary> - /// <param name="c">Character to search for</param> - /// <param name="startIndex">Start index of the area to search.</param> - /// <param name="count">Length of the area to search.</param> - /// <returns>The first index where the character was found; or -1 if no occurrence was found.</returns> - int IndexOf (char c, int startIndex, int count); - - /// <summary> - /// Gets the index of the first occurrence of any character in the specified array. - /// </summary> - /// <param name="anyOf">Characters to search for</param> - /// <param name="startIndex">Start index of the area to search.</param> - /// <param name="count">Length of the area to search.</param> - /// <returns>The first index where any character was found; or -1 if no occurrence was found.</returns> - int IndexOfAny (char[] anyOf, int startIndex, int count); - - /// <summary> - /// Gets the index of the first occurrence of the specified search text in this text source. - /// </summary> - /// <param name="searchText">The search text</param> - /// <param name="startIndex">Start index of the area to search.</param> - /// <param name="count">Length of the area to search.</param> - /// <param name="comparisonType">String comparison to use.</param> - /// <returns>The first index where the search term was found; or -1 if no occurrence was found.</returns> - int IndexOf (string searchText, int startIndex, int count, StringComparison comparisonType); - - /// <summary> - /// Gets the index of the last occurrence of the specified character in this text source. - /// </summary> - /// <param name="c">The search character</param> - /// <param name="startIndex">Start index of the area to search.</param> - /// <param name="count">Length of the area to search.</param> - /// <returns>The last index where the search term was found; or -1 if no occurrence was found.</returns> - /// <remarks>The search proceeds backwards from (startIndex+count) to startIndex. - /// This is different than the meaning of the parameters on string.LastIndexOf!</remarks> - int LastIndexOf (char c, int startIndex, int count); - - /// <summary> - /// Gets the index of the last occurrence of the specified search text in this text source. - /// </summary> - /// <param name="searchText">The search text</param> - /// <param name="startIndex">Start index of the area to search.</param> - /// <param name="count">Length of the area to search.</param> - /// <param name="comparisonType">String comparison to use.</param> - /// <returns>The last index where the search term was found; or -1 if no occurrence was found.</returns> - /// <remarks>The search proceeds backwards from (startIndex+count) to startIndex. - /// This is different than the meaning of the parameters on string.LastIndexOf!</remarks> - int LastIndexOf (string searchText, int startIndex, int count, StringComparison comparisonType); - } -} diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/ImmutableLineSplitter.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/ImmutableLineSplitter.cs new file mode 100644 index 0000000000..a2d65da072 --- /dev/null +++ b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/ImmutableLineSplitter.cs @@ -0,0 +1,179 @@ +// +// ImmutableLineSplitter.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Linq; +using ICSharpCode.NRefactory; +using System.Collections.Generic; + +namespace Mono.TextEditor +{ + class ImmutableLineSplitter : ILineSplitter + { + readonly LineSegment[] lines; + + sealed class LineSegment : DocumentLine + { + readonly ImmutableLineSplitter splitter; + readonly int lineNumber; + + public override int Offset { get; set; } + + public override int LineNumber { + get { + return lineNumber + 1; + } + } + + public override DocumentLine NextLine { + get { + return splitter.Get (lineNumber + 1); + } + } + + public override DocumentLine PreviousLine { + get { + return splitter.Get (lineNumber - 1); + } + } + + public LineSegment (ImmutableLineSplitter splitter, int lineNumber, int offset, int length, UnicodeNewline newLine) : base(length, newLine) + { + this.splitter = splitter; + this.lineNumber = lineNumber; + Offset = offset; + } + } + + public ImmutableLineSplitter (ILineSplitter src) + { + if (src == null) + throw new ArgumentNullException ("src"); + lines = new LineSegment[src.Count]; + int cur = 0; + foreach (var line in src.Lines) { + lines [cur] = new LineSegment (this, cur, line.Offset, line.LengthIncludingDelimiter, line.UnicodeNewline); + cur++; + } + } + + #region ILineSplitter implementation + + public event EventHandler<LineEventArgs> LineChanged; + + public event EventHandler<LineEventArgs> LineInserted; + + public event EventHandler<LineEventArgs> LineRemoved; + + public void Clear () + { + } + + public void Initalize (string text, out DocumentLine longestLine) + { + longestLine = null; + } + + public DocumentLine Get (int number) + { + return lines [number - 1]; + } + + public DocumentLine GetLineByOffset (int offset) + { + return lines [OffsetToLineNumber (offset) - 1]; + } + + public int OffsetToLineNumber (int offset) + { + int min = 0; + int max = lines.Length - 1; + while (min <= max) { + int mid = (min + max) / 2; + var middleLine = lines [mid]; + if (offset < middleLine.Offset) { + max = mid - 1; + } else if (offset > middleLine.EndOffset) { + min = mid + 1; + } else { + return mid + 1; + } + } + return lines.Length; + } + + public void TextReplaced (object sender, DocumentChangeEventArgs args) + { + } + + public void TextRemove (int offset, int length) + { + } + + public void TextInsert (int offset, string text) + { + } + + public IEnumerable<DocumentLine> GetLinesBetween (int startLine, int endLine) + { + for (int i = startLine; i <= endLine; i++) + yield return Get (i); + } + + public IEnumerable<DocumentLine> GetLinesStartingAt (int startLine) + { + for (int i = startLine; i <= Count; i++) + yield return Get (i); + } + + public IEnumerable<DocumentLine> GetLinesReverseStartingAt (int startLine) + { + for (int i = startLine; i-- > DocumentLocation.MinLine;) + yield return Get (i); + } + + public int Count { + get { + return lines.Length; + } + } + + public bool LineEndingMismatch { + get; + set; + } + + public System.Collections.Generic.IEnumerable<DocumentLine> Lines { + get { + return lines; + } + } + + #endregion + + + } +} + diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/StringBuffer.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/StringBuffer.cs deleted file mode 100644 index ba504a179a..0000000000 --- a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/StringBuffer.cs +++ /dev/null @@ -1,70 +0,0 @@ - -using System; -using System.Collections.Generic; -using System.Text; -namespace Mono.TextEditor -{ - /// <summary>
- /// Simple implementation of the buffer interface to support fast read-only documents.
- /// </summary> - public class StringBuffer : IBuffer
- {
- string buffer;
-
- public StringBuffer (string buffer)
- {
- this.buffer = buffer;
- }
-
- #region IBuffer Members
- int IBuffer.TextLength {
- get { return buffer.Length; }
- }
-
- string IBuffer.Text {
- get { return buffer; }
- set { buffer = value; }
- }
-
- void IBuffer.Replace (int offset, int count, string value)
- {
- throw new NotSupportedException ("Operation not supported on this buffer.");
- }
-
- string IBuffer.GetTextAt (int offset, int count)
- {
- return buffer.Substring (offset, count);
- }
-
- char IBuffer.GetCharAt (int offset)
- {
- return buffer[offset];
- }
- - int IBuffer.IndexOf (char c, int startIndex, int count) - { - return buffer.IndexOf (c, startIndex, count); - } - - int IBuffer.IndexOfAny (char[] anyOf, int startIndex, int count) - { - return buffer.IndexOfAny (anyOf, startIndex, count); - } - - public int IndexOf (string searchText, int startIndex, int count, StringComparison comparisonType) - { - return buffer.IndexOf (searchText, startIndex, count, comparisonType); - } - - int IBuffer.LastIndexOf (char c, int startIndex, int count) - { - return buffer.LastIndexOf (c, startIndex, count); - } - - public int LastIndexOf (string searchText, int startIndex, int count, StringComparison comparisonType) - { - return buffer.LastIndexOf (searchText, startIndex, count, comparisonType); - } - #endregion - } -} diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/TextDocument.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/TextDocument.cs index f69c94d427..1b958ef287 100644 --- a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/TextDocument.cs +++ b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/TextDocument.cs @@ -40,7 +40,7 @@ namespace Mono.TextEditor { public class TextDocument : ICSharpCode.NRefactory.AbstractAnnotatable, ICSharpCode.NRefactory.Editor.IDocument { - readonly IBuffer buffer; + readonly Rope<char> buffer; readonly ILineSplitter splitter; ISyntaxMode syntaxMode = null; @@ -61,11 +61,21 @@ namespace Mono.TextEditor lock (this) { mimeType = value; SyntaxMode = SyntaxModeService.GetSyntaxMode (this, value); + OnMimeTypeChanged (EventArgs.Empty); } } } } - + + public event EventHandler MimeTypeChanged; + + protected virtual void OnMimeTypeChanged (EventArgs e) + { + EventHandler handler = this.MimeTypeChanged; + if (handler != null) + handler (this, e); + } + string fileName; public string FileName { get { @@ -91,6 +101,16 @@ namespace Mono.TextEditor set; } + public bool UseBom { + get; + set; + } + + public System.Text.Encoding Encoding { + get; + set; + } + internal ILineSplitter Splitter { get { return splitter; @@ -135,11 +155,10 @@ namespace Mono.TextEditor } } - protected TextDocument (IBuffer buffer,ILineSplitter splitter) + protected TextDocument (Rope<char> buffer,ILineSplitter splitter) { this.buffer = buffer; this.splitter = splitter; - splitter.LineChanged += SplitterLineSegmentTreeLineChanged; splitter.LineRemoved += HandleSplitterLineSegmentTreeLineRemoved; foldSegmentTree.tree.NodeRemoved += HandleFoldSegmentTreetreeNodeRemoved; textSegmentMarkerTree.InstallListener (this); @@ -152,7 +171,7 @@ namespace Mono.TextEditor foldedSegments.Remove (e.Node); } - public TextDocument () : this(new GapBuffer (), new LineSplitter ()) + public TextDocument () : this(new Rope<char> (), new LineSplitter ()) { } @@ -163,41 +182,56 @@ namespace Mono.TextEditor public static TextDocument CreateImmutableDocument (string text, bool suppressHighlighting = true) { - return new TextDocument (new StringBuffer (text), new PrimitiveLineSplitter ()) { + return new TextDocument (CharRope.Create (text), new PrimitiveLineSplitter ()) { SuppressHighlightUpdate = suppressHighlighting, Text = text, ReadOnly = true }; } - void SplitterLineSegmentTreeLineChanged (object sender, LineEventArgs e) - { - if (LineChanged != null) - LineChanged (this, e); + public event EventHandler<LineEventArgs> LineChanged { + add { splitter.LineChanged += value; } + remove { splitter.LineChanged -= value; } } - - public event EventHandler<LineEventArgs> LineChanged; - // public event EventHandler<LineEventArgs> LineInserted; - + + public event EventHandler<LineEventArgs> LineInserted { + add { splitter.LineInserted += value; } + remove { splitter.LineInserted -= value; } + } + + public event EventHandler<LineEventArgs> LineRemoved { + add { splitter.LineRemoved += value; } + remove { splitter.LineRemoved -= value; } + } + #region Buffer implementation + public int TextLength { get { - return buffer.TextLength; + return buffer.Length; } } public bool SuppressHighlightUpdate { get; set; } internal DocumentLine longestLineAtTextSet; + WeakReference cachedText; public string Text { get { - return buffer.Text; + string completeText = cachedText != null ? (cachedText.Target as string) : null; + if (completeText == null) { + completeText = buffer.ToString(); + cachedText = new WeakReference(completeText); + } + return completeText; } set { var args = new DocumentChangeEventArgs (0, Text, value); textSegmentMarkerTree.Clear (); OnTextReplacing (args); - buffer.Text = value; + cachedText = null; + buffer.Clear (); + buffer.InsertText (0, value); extendingTextMarkers = new List<TextLineMarker> (); splitter.Initalize (value, out longestLineAtTextSet); ClearFoldSegments (); @@ -255,8 +289,10 @@ namespace Mono.TextEditor } redoStack.Clear (); } - - buffer.Replace (offset, count, value); + cachedText = null; + buffer.RemoveRange(offset, count); + if (!string.IsNullOrEmpty (value)) + buffer.InsertText (offset, value); foldSegmentTree.UpdateOnTextReplace (this, args); splitter.TextReplaced (this, args); versionProvider.AppendChange (args); @@ -274,7 +310,7 @@ namespace Mono.TextEditor if (endOffset > TextLength) throw new ArgumentException ("endOffset > Length"); - return buffer.GetTextAt (startOffset, endOffset - startOffset); + return buffer.ToString (startOffset, endOffset - startOffset); } public string GetTextBetween (DocumentLocation start, DocumentLocation end) @@ -297,7 +333,7 @@ namespace Mono.TextEditor throw new ArgumentException ("count < 0"); if (offset + count > TextLength) throw new ArgumentException ("offset + count is beyond EOF"); - return buffer.GetTextAt (offset, count); + return buffer.ToString (offset, count); } public string GetTextAt (DocumentRegion region) @@ -337,17 +373,17 @@ namespace Mono.TextEditor throw new ArgumentException ("offset < 0"); if (offset >= TextLength) throw new ArgumentException ("offset >= TextLength"); - return buffer.GetCharAt (offset); + return buffer [offset]; } public char GetCharAt (DocumentLocation location) { - return buffer.GetCharAt (LocationToOffset (location)); + return buffer [LocationToOffset (location)]; } public char GetCharAt (int line, int column) { - return buffer.GetCharAt (LocationToOffset (line, column)); + return buffer [LocationToOffset (line, column)]; } /// <summary> @@ -1176,6 +1212,11 @@ namespace Mono.TextEditor return foldSegmentTree.GetSegmentsOverlapping (line.Offset, line.Length).Cast<FoldSegment> (); } + public IEnumerable<FoldSegment> GetFoldingContaining (int offset, int length) + { + return foldSegmentTree.GetSegmentsOverlapping (offset, length).Cast<FoldSegment> (); + } + public IEnumerable<FoldSegment> GetStartFoldings (int lineNumber) { return GetStartFoldings (this.GetLine (lineNumber)); @@ -1188,6 +1229,11 @@ namespace Mono.TextEditor return GetFoldingContaining (line).Where (fold => fold.StartLine == line); } + public IEnumerable<FoldSegment> GetStartFoldings (int offset, int length) + { + return GetFoldingContaining (offset, length).Where (fold => offset <= fold.StartLine.Offset && fold.StartLine.Offset < offset + length); + } + public IEnumerable<FoldSegment> GetEndFoldings (int lineNumber) { return GetStartFoldings (this.GetLine (lineNumber)); @@ -1200,7 +1246,12 @@ namespace Mono.TextEditor yield return segment; } } - + + public IEnumerable<FoldSegment> GetEndFoldings (int offset, int length) + { + return GetFoldingContaining (offset, length).Where (fold => offset <= fold.EndLine.Offset && fold.EndLine.Offset < offset + length); + } + public int GetLineCount (FoldSegment segment) { return segment.EndLine.LineNumber - segment.StartLine.LineNumber; @@ -1656,12 +1707,14 @@ namespace Mono.TextEditor #region Diff + + int[] GetDiffCodes (ref int codeCounter, Dictionary<string, int> codeDictionary, bool includeEol) { int i = 0; var result = new int[LineCount]; foreach (DocumentLine line in Lines) { - string lineText = buffer.GetTextAt (line.Offset, includeEol ? line.LengthIncludingDelimiter : line.Length); + string lineText = buffer.ToString (line.Offset, includeEol ? line.LengthIncludingDelimiter : line.Length); int curCode; if (!codeDictionary.TryGetValue (lineText, out curCode)) { codeDictionary[lineText] = curCode = ++codeCounter; @@ -1854,12 +1907,12 @@ namespace Mono.TextEditor public System.IO.TextReader CreateReader () { - return new BufferedTextReader (buffer); + return new RopeTextReader (buffer); } public System.IO.TextReader CreateReader (int offset, int length) { - throw new NotImplementedException (); + return new RopeTextReader(buffer.GetRange(offset, length)); } string ICSharpCode.NRefactory.Editor.ITextSource.GetText (int offset, int length) @@ -1893,25 +1946,37 @@ namespace Mono.TextEditor } } - public SnapshotDocument (string text, ITextSourceVersion version) : base (new StringBuffer (text), new PrimitiveLineSplitter ()) + public SnapshotDocument (TextDocument doc) : base (doc.buffer.Clone(), new ImmutableLineSplitter (doc.splitter)) { - this.version = version; - Text = text; + this.version = doc.Version; + fileName = doc.fileName; + Encoding = doc.Encoding; + UseBom = doc.UseBom; + mimeType = doc.mimeType; + ReadOnly = true; } } public TextDocument CreateDocumentSnapshot () { - return new SnapshotDocument (Text, Version); + return new SnapshotDocument (this); } - ICSharpCode.NRefactory.Editor.IDocument ICSharpCode.NRefactory.Editor.IDocument.CreateDocumentSnapshot () + public Mono.TextEditor.Utils.Rope<char> CloneRope () { - return new SnapshotDocument (Text, Version); + return buffer.Clone (); } + public Mono.TextEditor.Utils.Rope<char> CloneRope (int offset, int count) + { + return buffer.GetRange (offset, count); + } + ICSharpCode.NRefactory.Editor.IDocument ICSharpCode.NRefactory.Editor.IDocument.CreateDocumentSnapshot () + { + return new SnapshotDocument (this); + } #endregion } |