diff options
| author | Victoria Plitt <Victoria.Plitt@twine-s.com> | 2019-04-08 13:49:55 +0300 |
|---|---|---|
| committer | Victoria Plitt <Victoria.Plitt@twine-s.com> | 2019-04-08 13:49:55 +0300 |
| commit | fc8a05358a92cc3c77c5f1e30d536807ef0614fd (patch) | |
| tree | c65f696ebd60f3790145721307c255e5a339923f /Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Document/GapTextBuffer.cs | |
| parent | b4a71931ea52636c6b36376aa9d71697ccf73524 (diff) | |
| download | Tango-fc8a05358a92cc3c77c5f1e30d536807ef0614fd.tar.gz Tango-fc8a05358a92cc3c77c5f1e30d536807ef0614fd.zip | |
were added scripting projects
Diffstat (limited to 'Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Document/GapTextBuffer.cs')
| -rw-r--r-- | Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Document/GapTextBuffer.cs | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Document/GapTextBuffer.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Document/GapTextBuffer.cs new file mode 100644 index 000000000..a617284a9 --- /dev/null +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Document/GapTextBuffer.cs @@ -0,0 +1,192 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Diagnostics; +using System.Text; + +using Tango.Scripting.Editors.Utils; + +namespace Tango.Scripting.Editors.Document +{ + /* + /// <summary> + /// Implementation of a gap text buffer. + /// </summary> + sealed class GapTextBuffer + { + char[] buffer = Empty<char>.Array; + + /// <summary> + /// The current text content. + /// Is set to null whenever the buffer changes, and gets a value only when the + /// full text content is requested. + /// </summary> + string textContent; + + /// <summary> + /// last GetText result + /// </summary> + string lastGetTextResult; + int lastGetTextRequestOffset; + + int gapBeginOffset; + int gapEndOffset; + int gapLength; // gapLength == gapEndOffset - gapBeginOffset + + /// <summary> + /// when gap is too small for inserted text or gap is too large (exceeds maxGapLength), + /// a new buffer is reallocated with a new gap of at least this size. + /// </summary> + const int minGapLength = 128; + + /// <summary> + /// when the gap exceeds this size, reallocate a smaller buffer + /// </summary> + const int maxGapLength = 4096; + + public int Length { + get { + return buffer.Length - gapLength; + } + } + + /// <summary> + /// Gets the buffer content. + /// </summary> + public string Text { + get { + if (textContent == null) + textContent = GetText(0, Length); + return textContent; + } + set { + Debug.Assert(value != null); + textContent = value; lastGetTextResult = null; + buffer = new char[value.Length + minGapLength]; + value.CopyTo(0, buffer, 0, value.Length); + gapBeginOffset = value.Length; + gapEndOffset = buffer.Length; + gapLength = gapEndOffset - gapBeginOffset; + } + } + + public char GetCharAt(int offset) + { + return offset < gapBeginOffset ? buffer[offset] : buffer[offset + gapLength]; + } + + public string GetText(int offset, int length) + { + if (length == 0) + return string.Empty; + if (lastGetTextRequestOffset == offset && lastGetTextResult != null && length == lastGetTextResult.Length) + return lastGetTextResult; + + int end = offset + length; + string result; + if (end < gapBeginOffset) { + result = new string(buffer, offset, length); + } else if (offset > gapBeginOffset) { + result = new string(buffer, offset + gapLength, length); + } else { + int block1Size = gapBeginOffset - offset; + int block2Size = end - gapBeginOffset; + + StringBuilder buf = new StringBuilder(block1Size + block2Size); + buf.Append(buffer, offset, block1Size); + buf.Append(buffer, gapEndOffset, block2Size); + result = buf.ToString(); + } + lastGetTextRequestOffset = offset; + lastGetTextResult = result; + return result; + } + + /// <summary> + /// Inserts text at the specified offset. + /// </summary> + public void Insert(int offset, string text) + { + Debug.Assert(offset >= 0 && offset <= Length); + + if (text.Length == 0) + return; + + textContent = null; lastGetTextResult = null; + PlaceGap(offset, text.Length); + text.CopyTo(0, buffer, gapBeginOffset, text.Length); + gapBeginOffset += text.Length; + gapLength = gapEndOffset - gapBeginOffset; + } + + /// <summary> + /// Remove <paramref name="length"/> characters at <paramref name="offset"/>. + /// Leave a gap of at least <paramref name="reserveGapSize"/>. + /// </summary> + public void Remove(int offset, int length, int reserveGapSize) + { + Debug.Assert(offset >= 0 && offset <= Length); + Debug.Assert(length >= 0 && offset + length <= Length); + Debug.Assert(reserveGapSize >= 0); + + if (length == 0) + return; + + textContent = null; lastGetTextResult = null; + PlaceGap(offset, reserveGapSize - length); + gapEndOffset += length; // delete removed text + gapLength = gapEndOffset - gapBeginOffset; + if (gapLength - reserveGapSize > maxGapLength && gapLength - reserveGapSize > buffer.Length / 4) { + // shrink gap + MakeNewBuffer(gapBeginOffset, reserveGapSize + minGapLength); + } + } + + void PlaceGap(int newGapOffset, int minRequiredGapLength) + { + if (gapLength < minRequiredGapLength) { + // enlarge gap + MakeNewBuffer(newGapOffset, minRequiredGapLength + Math.Max(minGapLength, buffer.Length / 8)); + } else { + while (newGapOffset < gapBeginOffset) { + buffer[--gapEndOffset] = buffer[--gapBeginOffset]; + } + while (newGapOffset > gapBeginOffset) { + buffer[gapBeginOffset++] = buffer[gapEndOffset++]; + } + } + } + + void MakeNewBuffer(int newGapOffset, int newGapLength) + { + char[] newBuffer = new char[Length + newGapLength]; + Debug.WriteLine("GapTextBuffer was reallocated, new size=" + newBuffer.Length); + if (newGapOffset < gapBeginOffset) { + // gap is moving backwards + + // first part: + Array.Copy(buffer, 0, newBuffer, 0, newGapOffset); + // moving middle part: + Array.Copy(buffer, newGapOffset, newBuffer, newGapOffset + newGapLength, gapBeginOffset - newGapOffset); + // last part: + Array.Copy(buffer, gapEndOffset, newBuffer, newBuffer.Length - (buffer.Length - gapEndOffset), buffer.Length - gapEndOffset); + } else { + // gap is moving forwards + // first part: + Array.Copy(buffer, 0, newBuffer, 0, gapBeginOffset); + // moving middle part: + Array.Copy(buffer, gapEndOffset, newBuffer, gapBeginOffset, newGapOffset - gapBeginOffset); + // last part: + int lastPartLength = newBuffer.Length - (newGapOffset + newGapLength); + Array.Copy(buffer, buffer.Length - lastPartLength, newBuffer, newGapOffset + newGapLength, lastPartLength); + } + + gapBeginOffset = newGapOffset; + gapEndOffset = newGapOffset + newGapLength; + gapLength = newGapLength; + buffer = newBuffer; + } + } + */ +} |
