Browse Source

DocumentUtilitites: add LoadDocumentFromBuffer and LoadReadOnlyDocumentFromBuffer

pull/1/head
Daniel Grunwald 15 years ago
parent
commit
5091b49f8e
  1. 1
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  2. 35
      src/Main/Base/Project/Src/Editor/DocumentUtilitites.cs
  3. 281
      src/Main/Base/Project/Src/Editor/ReadOnlyDocument.cs

1
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -155,6 +155,7 @@ @@ -155,6 +155,7 @@
<Compile Include="Src\Editor\ITooltip.cs">
<DependentUpon>ToolTipService.cs</DependentUpon>
</Compile>
<Compile Include="Src\Editor\ReadOnlyDocument.cs" />
<Compile Include="Src\Editor\RefactoringDocumentAdapter.cs" />
<Compile Include="Src\Editor\Search\ISearchResult.cs" />
<Compile Include="Src\Editor\Search\ISearchResultFactory.cs" />

35
src/Main/Base/Project/Src/Editor/DocumentUtilitites.cs

@ -20,6 +20,30 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -20,6 +20,30 @@ namespace ICSharpCode.SharpDevelop.Editor
/// </summary>
public static class DocumentUtilitites
{
/// <summary>
/// Creates a new mutable document from the specified text buffer.
/// </summary>
/// <remarks>
/// Use the more efficient <see cref="LoadReadOnlyDocumentFromBuffer"/> if you only need a read-only document.
/// </remarks>
public static IDocument LoadDocumentFromBuffer(ITextBuffer buffer)
{
if (buffer == null)
throw new ArgumentNullException("buffer");
var doc = new TextDocument(GetTextSource(buffer));
return new AvalonEditDocumentAdapter(doc, null);
}
/// <summary>
/// Creates a new read-only document from the specified text buffer.
/// </summary>
public static IDocument LoadReadOnlyDocumentFromBuffer(ITextBuffer buffer)
{
if (buffer == null)
throw new ArgumentNullException("buffer");
return new ReadOnlyDocument(buffer);
}
/// <summary>
/// Gets the word in front of the caret.
/// </summary>
@ -173,17 +197,6 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -173,17 +197,6 @@ namespace ICSharpCode.SharpDevelop.Editor
return NormalizeNewLines(input, GetLineTerminator(document, lineNumber));
}
/// <summary>
/// Creates an IDocument from an ITextBuffer.
/// </summary>
public static IDocument LoadDocumentFromBuffer(ITextBuffer buffer)
{
if (buffer == null)
throw new ArgumentNullException("buffer");
TextDocument document = new TextDocument(buffer.Text);
return new AvalonEdit.AvalonEditDocumentAdapter(document, null);
}
#region ITextSource implementation
public static ICSharpCode.AvalonEdit.Document.ITextSource GetTextSource(ITextBuffer textBuffer)
{

281
src/Main/Base/Project/Src/Editor/ReadOnlyDocument.cs

@ -0,0 +1,281 @@ @@ -0,0 +1,281 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
namespace ICSharpCode.SharpDevelop.Editor
{
/// <summary>
/// Read-only implementation of IDocument.
/// </summary>
sealed class ReadOnlyDocument : IDocument
{
ITextBuffer textBuffer;
int[] lines;
public ReadOnlyDocument(ITextBuffer textBuffer)
{
// ensure that underlying buffer is immutable
this.textBuffer = textBuffer.CreateSnapshot();
List<int> lines = new List<int>();
lines.Add(0);
int offset = 0;
string newlineType;
var textSource = DocumentUtilitites.GetTextSource(this.textBuffer);
while ((offset = ICSharpCode.AvalonEdit.Document.TextUtilities.FindNextNewLine(textSource, offset, out newlineType)) >= 0) {
offset += newlineType.Length;
lines.Add(offset);
}
this.lines = lines.ToArray();
}
public IDocumentLine GetLine(int lineNumber)
{
if (lineNumber < 1 || lineNumber > lines.Length)
throw new ArgumentOutOfRangeException("lineNumber", lineNumber, "Value must be between 1 and " + lines.Length);
return new ReadOnlyDocumentLine(this, lineNumber);
}
sealed class ReadOnlyDocumentLine : IDocumentLine
{
readonly ReadOnlyDocument doc;
readonly int lineNumber;
public ReadOnlyDocumentLine(ReadOnlyDocument doc, int lineNumber)
{
this.doc = doc;
this.lineNumber = lineNumber;
}
public int Offset {
get {
return doc.GetStartOffset(lineNumber);
}
}
public int Length {
get {
return doc.GetEndOffset(lineNumber) - doc.GetStartOffset(lineNumber);
}
}
public int EndOffset {
get {
return doc.GetEndOffset(lineNumber);
}
}
public int TotalLength {
get {
return doc.GetTotalEndOffset(lineNumber) - doc.GetStartOffset(lineNumber);
}
}
public int DelimiterLength {
get {
return doc.GetTotalEndOffset(lineNumber) - doc.GetEndOffset(lineNumber);
}
}
public int LineNumber {
get { return lineNumber; }
}
public string Text {
get {
return doc.GetText(this.Offset, this.Length);
}
}
}
int GetStartOffset(int lineNumber)
{
return lines[lineNumber-1];
}
int GetTotalEndOffset(int lineNumber)
{
return lineNumber < lines.Length ? lines[lineNumber] : textBuffer.TextLength;
}
int GetEndOffset(int lineNumber)
{
if (lineNumber == lines.Length)
return textBuffer.TextLength;
int off = lines[lineNumber] - 1;
if (off > 0 && textBuffer.GetCharAt(off - 1) == '\r' && textBuffer.GetCharAt(off) == '\n')
off--;
return off;
}
public IDocumentLine GetLineForOffset(int offset)
{
return GetLine(GetLineNumberForOffset(offset));
}
int GetLineNumberForOffset(int offset)
{
int r = Array.BinarySearch(lines, offset);
return r < 0 ? ~r : r + 1;
}
public int PositionToOffset(int line, int column)
{
if (line < 1 || line > lines.Length)
throw new ArgumentOutOfRangeException("line", line, "Value must be between 1 and " + lines.Length);
int lineStart = GetStartOffset(line);
if (column <= 0)
return lineStart;
int lineEnd = GetEndOffset(line);
if (column >= lineEnd - lineStart)
return lineEnd;
return lineStart + column - 1;
}
public Location OffsetToPosition(int offset)
{
if (offset < 0 || offset > textBuffer.TextLength)
throw new ArgumentOutOfRangeException("offset", offset, "Value must be between 0 and " + textBuffer.TextLength);
int line = GetLineNumberForOffset(offset);
return new Location(offset-GetStartOffset(line)+1, line);
}
public event EventHandler<TextChangeEventArgs> Changing { add {} remove {} }
public event EventHandler<TextChangeEventArgs> Changed { add {} remove {} }
public event EventHandler TextChanged { add {} remove {} }
public string Text {
get { return textBuffer.Text; }
set {
throw new NotSupportedException();
}
}
public int TotalNumberOfLines {
get { return lines.Length; }
}
public ITextBufferVersion Version {
get { return null; }
}
public int TextLength {
get { return textBuffer.TextLength; }
}
public void Insert(int offset, string text)
{
throw new NotSupportedException();
}
public void Remove(int offset, int length)
{
throw new NotSupportedException();
}
public void Replace(int offset, int length, string newText)
{
throw new NotSupportedException();
}
public void StartUndoableAction()
{
}
public void EndUndoableAction()
{
}
public IDisposable OpenUndoGroup()
{
return new CallbackOnDispose(EndUndoableAction);
}
public ITextAnchor CreateAnchor(int offset)
{
return new ReadOnlyDocumentTextAnchor(OffsetToPosition(offset), offset);
}
sealed class ReadOnlyDocumentTextAnchor : ITextAnchor
{
readonly Location location;
readonly int offset;
public ReadOnlyDocumentTextAnchor(Location location, int offset)
{
this.location = location;
this.offset = offset;
}
public event EventHandler Deleted { add {} remove {} }
public Location Location {
get { return location; }
}
public int Offset {
get { return offset; }
}
public AnchorMovementType MovementType { get; set; }
public bool SurviveDeletion { get; set; }
public bool IsDeleted {
get { return false; }
}
public int Line {
get { return location.Line; }
}
public int Column {
get { return location.Column; }
}
}
public ITextBuffer CreateSnapshot()
{
return this; // ReadOnlyDocument is immutable
}
public ITextBuffer CreateSnapshot(int offset, int length)
{
return textBuffer.CreateSnapshot(offset, length);
}
public System.IO.TextReader CreateReader()
{
return textBuffer.CreateReader();
}
public System.IO.TextReader CreateReader(int offset, int length)
{
return textBuffer.CreateReader(offset, length);
}
public char GetCharAt(int offset)
{
return textBuffer.GetCharAt(offset);
}
public string GetText(int offset, int length)
{
return textBuffer.GetText(offset, length);
}
public object GetService(Type serviceType)
{
return null;
}
}
}
Loading…
Cancel
Save