mirror of https://github.com/icsharpcode/ILSpy.git
270 changed files with 18922 additions and 9211 deletions
@ -0,0 +1,109 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
|
||||||
|
//
|
||||||
|
// 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; |
||||||
|
|
||||||
|
public class TypeAnalysisTests |
||||||
|
{ |
||||||
|
public byte SubtractFrom256(byte b) |
||||||
|
{ |
||||||
|
return (byte)(256 - (int)b); |
||||||
|
} |
||||||
|
|
||||||
|
#region Shift
|
||||||
|
public int LShiftInteger(int num1, int num2) |
||||||
|
{ |
||||||
|
return num1 << num2; |
||||||
|
} |
||||||
|
|
||||||
|
public uint LShiftUnsignedInteger(uint num1, uint num2) |
||||||
|
{ |
||||||
|
return num1 << (int)num2; |
||||||
|
} |
||||||
|
|
||||||
|
public long LShiftLong(long num1, long num2) |
||||||
|
{ |
||||||
|
return num1 << (int)num2; |
||||||
|
} |
||||||
|
|
||||||
|
public ulong LShiftUnsignedLong(ulong num1, ulong num2) |
||||||
|
{ |
||||||
|
return num1 << (int)num2; |
||||||
|
} |
||||||
|
|
||||||
|
public int RShiftInteger(int num1, int num2) |
||||||
|
{ |
||||||
|
return num1 >> num2; |
||||||
|
} |
||||||
|
|
||||||
|
public uint RShiftUnsignedInteger(uint num1, int num2) |
||||||
|
{ |
||||||
|
return num1 >> num2; |
||||||
|
} |
||||||
|
|
||||||
|
public long RShiftLong(long num1, long num2) |
||||||
|
{ |
||||||
|
return num1 >> (int)num2; |
||||||
|
} |
||||||
|
|
||||||
|
public ulong RShiftUnsignedLong(ulong num1, ulong num2) |
||||||
|
{ |
||||||
|
return num1 >> (int)num2; |
||||||
|
} |
||||||
|
|
||||||
|
public int ShiftByte(byte num) |
||||||
|
{ |
||||||
|
return (int)num << 8; |
||||||
|
} |
||||||
|
|
||||||
|
public int RShiftByte(byte num) |
||||||
|
{ |
||||||
|
return num >> 8; |
||||||
|
} |
||||||
|
|
||||||
|
public uint RShiftByteWithZeroExtension(byte num) |
||||||
|
{ |
||||||
|
return (uint)num >> 8; |
||||||
|
} |
||||||
|
|
||||||
|
public int RShiftByteAsSByte(byte num) |
||||||
|
{ |
||||||
|
return (sbyte)num >> 8; |
||||||
|
} |
||||||
|
|
||||||
|
public int RShiftSByte(sbyte num) |
||||||
|
{ |
||||||
|
return num >> 8; |
||||||
|
} |
||||||
|
|
||||||
|
public uint RShiftSByteWithZeroExtension(sbyte num) |
||||||
|
{ |
||||||
|
return (uint)num >> 8; |
||||||
|
} |
||||||
|
|
||||||
|
public int RShiftSByteAsByte(sbyte num) |
||||||
|
{ |
||||||
|
return (byte)num >> 8; |
||||||
|
} |
||||||
|
#endregion
|
||||||
|
|
||||||
|
public int GetHashCode(long num) |
||||||
|
{ |
||||||
|
return (int)num ^ (int)(num >> 32); |
||||||
|
} |
||||||
|
} |
||||||
@ -1,183 +0,0 @@ |
|||||||
// Copyright (c) Cristian Civera (cristian@aspitalia.com)
|
|
||||||
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.ComponentModel; |
|
||||||
using System.Reflection; |
|
||||||
using System.Text; |
|
||||||
using System.IO; |
|
||||||
using System.Linq; |
|
||||||
using Microsoft.Win32; |
|
||||||
using System.Threading; |
|
||||||
using System.Security.Permissions; |
|
||||||
using System.Security; |
|
||||||
|
|
||||||
namespace Ricciolo.StylesExplorer.MarkupReflection |
|
||||||
{ |
|
||||||
public delegate void AssemblyResolveEventHandler(object s, AssemblyResolveEventArgs e); |
|
||||||
|
|
||||||
public class AppDomainTypeResolver : MarshalByRefObject, ITypeResolver |
|
||||||
{ |
|
||||||
private readonly AppDomain _domain; |
|
||||||
private string baseDir; |
|
||||||
|
|
||||||
public event AssemblyResolveEventHandler AssemblyResolve; |
|
||||||
|
|
||||||
public static AppDomainTypeResolver GetIntoNewAppDomain(string baseDir) |
|
||||||
{ |
|
||||||
AppDomainSetup info = new AppDomainSetup(); |
|
||||||
info.ApplicationBase = Environment.CurrentDirectory; |
|
||||||
AppDomain domain = AppDomain.CreateDomain("AppDomainTypeResolver", null, info, new PermissionSet(PermissionState.Unrestricted)); |
|
||||||
AppDomainTypeResolver resolver = (AppDomainTypeResolver)domain.CreateInstanceAndUnwrap(typeof(AppDomainTypeResolver).Assembly.FullName, |
|
||||||
typeof(AppDomainTypeResolver).FullName, false, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, new object[] { domain, baseDir }, null, null, null); |
|
||||||
|
|
||||||
return resolver; |
|
||||||
} |
|
||||||
|
|
||||||
Assembly domain_AssemblyResolve(object sender, ResolveEventArgs args) |
|
||||||
{ |
|
||||||
// Cerco di risolvere automaticamente
|
|
||||||
AssemblyName name = new AssemblyName(args.Name); |
|
||||||
string fileName = Path.Combine(this.baseDir, name.Name + ".exe"); |
|
||||||
if (!File.Exists(fileName)) |
|
||||||
fileName = Path.Combine(this.baseDir, name.Name + ".dll"); |
|
||||||
|
|
||||||
// Carico il percorso autocalcolato
|
|
||||||
if (File.Exists(fileName)) |
|
||||||
return Assembly.LoadFile(fileName); |
|
||||||
|
|
||||||
if (AssemblyResolve != null) |
|
||||||
{ |
|
||||||
AssemblyResolveEventArgs e = new AssemblyResolveEventArgs(args.Name, this.baseDir); |
|
||||||
AssemblyResolve(this, e); |
|
||||||
if (!String.IsNullOrEmpty(e.Location) && File.Exists(e.Location)) |
|
||||||
return Assembly.LoadFile(e.Location); |
|
||||||
} |
|
||||||
|
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
public static void DestroyResolver(AppDomainTypeResolver resolver) |
|
||||||
{ |
|
||||||
if (resolver == null) throw new ArgumentNullException("resolver"); |
|
||||||
|
|
||||||
ThreadPool.QueueUserWorkItem(delegate |
|
||||||
{ |
|
||||||
AppDomain.Unload(resolver.Domain); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
protected AppDomainTypeResolver(AppDomain domain, string baseDir) |
|
||||||
{ |
|
||||||
_domain = domain; |
|
||||||
this.baseDir = baseDir; |
|
||||||
|
|
||||||
domain.AssemblyResolve += new ResolveEventHandler(domain_AssemblyResolve); |
|
||||||
} |
|
||||||
|
|
||||||
public BamlAssembly LoadAssembly(AssemblyName asm) |
|
||||||
{ |
|
||||||
//return new BamlAssembly(Assembly.Load(asm));
|
|
||||||
return new BamlAssembly(_domain.Load(asm)); |
|
||||||
} |
|
||||||
|
|
||||||
public BamlAssembly LoadAssembly(string location) |
|
||||||
{ |
|
||||||
Assembly asm = Assembly.LoadFile(location); |
|
||||||
return new BamlAssembly(asm); |
|
||||||
//return _domain.Load(System.IO.File.ReadAllBytes(location));
|
|
||||||
//return Assembly.LoadFrom(location);
|
|
||||||
} |
|
||||||
|
|
||||||
public BamlAssembly[] GetReferencedAssemblies(BamlAssembly asm) |
|
||||||
{ |
|
||||||
AssemblyName[] list = asm.Assembly.GetReferencedAssemblies(); |
|
||||||
|
|
||||||
return (from an in list |
|
||||||
select this.LoadAssembly(an)).ToArray(); |
|
||||||
} |
|
||||||
|
|
||||||
public AppDomain Domain |
|
||||||
{ |
|
||||||
get { return _domain; } |
|
||||||
} |
|
||||||
|
|
||||||
#region ITypeResolver Members
|
|
||||||
|
|
||||||
public IType GetTypeByAssemblyQualifiedName(string name) |
|
||||||
{ |
|
||||||
return new DotNetType(name); |
|
||||||
} |
|
||||||
|
|
||||||
public IDependencyPropertyDescriptor GetDependencyPropertyDescriptor(string name, IType ownerType, IType targetType) |
|
||||||
{ |
|
||||||
if (name == null) throw new ArgumentNullException("name"); |
|
||||||
if (ownerType == null) throw new ArgumentNullException("ownerType"); |
|
||||||
if (targetType == null) throw new ArgumentNullException("targetType"); |
|
||||||
|
|
||||||
Type dOwnerType = ((DotNetType)ownerType).Type; |
|
||||||
Type dTargetType = ((DotNetType)targetType).Type; |
|
||||||
|
|
||||||
try |
|
||||||
{ |
|
||||||
DependencyPropertyDescriptor propertyDescriptor = DependencyPropertyDescriptor.FromName(name, dOwnerType, dTargetType); |
|
||||||
if (propertyDescriptor != null) |
|
||||||
return new WpfDependencyPropertyDescriptor(propertyDescriptor); |
|
||||||
return null; |
|
||||||
} |
|
||||||
catch (Exception) |
|
||||||
{ |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public bool IsLocalAssembly(string name) |
|
||||||
{ |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
public string RuntimeVersion { |
|
||||||
get { |
|
||||||
throw new NotImplementedException(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public override object InitializeLifetimeService() |
|
||||||
{ |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public class AssemblyResolveEventArgs : MarshalByRefObject |
|
||||||
{ |
|
||||||
|
|
||||||
private string _location; |
|
||||||
private string _name; |
|
||||||
private string _baseDir; |
|
||||||
|
|
||||||
public AssemblyResolveEventArgs(string name, string baseDir) |
|
||||||
{ |
|
||||||
_name = name; |
|
||||||
_baseDir = baseDir; |
|
||||||
} |
|
||||||
|
|
||||||
public string Location |
|
||||||
{ |
|
||||||
get { return _location; } |
|
||||||
set { _location = value; } |
|
||||||
} |
|
||||||
|
|
||||||
public string Name |
|
||||||
{ |
|
||||||
get { return _name; } |
|
||||||
} |
|
||||||
|
|
||||||
public string BaseDir |
|
||||||
{ |
|
||||||
get { return _baseDir; } |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,112 +0,0 @@ |
|||||||
// Copyright (c) Cristian Civera (cristian@aspitalia.com)
|
|
||||||
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using System.Collections; |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.Collections.ObjectModel; |
|
||||||
using System.IO; |
|
||||||
using System.Reflection; |
|
||||||
using System.Resources; |
|
||||||
using System.Text; |
|
||||||
|
|
||||||
namespace Ricciolo.StylesExplorer.MarkupReflection |
|
||||||
{ |
|
||||||
public class BamlAssembly : MarshalByRefObject |
|
||||||
{ |
|
||||||
private readonly string _filePath; |
|
||||||
private Assembly _assembly; |
|
||||||
private BamlFileList _bamlFile; |
|
||||||
|
|
||||||
public BamlAssembly(Assembly assembly) |
|
||||||
{ |
|
||||||
_assembly = assembly; |
|
||||||
_filePath = assembly.CodeBase; |
|
||||||
|
|
||||||
ReadBaml(); |
|
||||||
} |
|
||||||
|
|
||||||
public BamlAssembly(string filePath) |
|
||||||
{ |
|
||||||
this._filePath = Path.GetFullPath(filePath); |
|
||||||
this._assembly = Assembly.LoadFile(this.FilePath); |
|
||||||
if (String.Compare(this.Assembly.CodeBase, this.FilePath, true) != 0) |
|
||||||
throw new ArgumentException("Cannot load filePath because Assembly is already loaded", "filePath"); |
|
||||||
|
|
||||||
ReadBaml(); |
|
||||||
} |
|
||||||
|
|
||||||
private void ReadBaml() |
|
||||||
{ |
|
||||||
// Get available names
|
|
||||||
string[] resources = this.Assembly.GetManifestResourceNames(); |
|
||||||
foreach (string res in resources) |
|
||||||
{ |
|
||||||
// Solo le risorse
|
|
||||||
if (String.Compare(Path.GetExtension(res), ".resources", true) != 0) continue; |
|
||||||
|
|
||||||
// Get stream
|
|
||||||
using (Stream stream = this.Assembly.GetManifestResourceStream(res)) |
|
||||||
{ |
|
||||||
try |
|
||||||
{ |
|
||||||
ResourceReader reader = new ResourceReader(stream); |
|
||||||
foreach (DictionaryEntry entry in reader) |
|
||||||
{ |
|
||||||
if (String.Compare(Path.GetExtension(entry.Key.ToString()), ".baml", true) == 0 && entry.Value is Stream) |
|
||||||
{ |
|
||||||
BamlFile bm = new BamlFile(GetAssemblyResourceUri(entry.Key.ToString()), (Stream)entry.Value); |
|
||||||
this.BamlFiles.Add(bm); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
catch (ArgumentException) |
|
||||||
{} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private Uri GetAssemblyResourceUri(string resourceName) |
|
||||||
{ |
|
||||||
AssemblyName asm = this.Assembly.GetName(); |
|
||||||
byte[] data = asm.GetPublicKeyToken(); |
|
||||||
StringBuilder token = new StringBuilder(data.Length * 2); |
|
||||||
for (int x = 0; x < data.Length; x++) |
|
||||||
{ |
|
||||||
token.Append(data[x].ToString("x", System.Globalization.CultureInfo.InvariantCulture)); |
|
||||||
} |
|
||||||
|
|
||||||
return new Uri(String.Format(@"{0};V{1};{2};component\{3}", asm.Name, asm.Version, token, Path.ChangeExtension(resourceName, ".xaml")), UriKind.RelativeOrAbsolute); |
|
||||||
} |
|
||||||
|
|
||||||
public string FilePath |
|
||||||
{ |
|
||||||
get { return _filePath; } |
|
||||||
} |
|
||||||
|
|
||||||
public Assembly Assembly |
|
||||||
{ |
|
||||||
get { return _assembly; } |
|
||||||
} |
|
||||||
|
|
||||||
public BamlFileList BamlFiles |
|
||||||
{ |
|
||||||
get |
|
||||||
{ |
|
||||||
if (_bamlFile == null) |
|
||||||
_bamlFile = new BamlFileList(); |
|
||||||
return _bamlFile; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public override object InitializeLifetimeService() |
|
||||||
{ |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
[Serializable()] |
|
||||||
public class BamlFileList : Collection<BamlFile> |
|
||||||
{} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,80 +0,0 @@ |
|||||||
// Copyright (c) Cristian Civera (cristian@aspitalia.com)
|
|
||||||
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using System.Collections; |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.ComponentModel; |
|
||||||
using System.IO; |
|
||||||
using System.Resources; |
|
||||||
using System.Text; |
|
||||||
using System.Windows; |
|
||||||
|
|
||||||
namespace Ricciolo.StylesExplorer.MarkupReflection |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Rappresenta un singole file Baml all'interno di un assembly
|
|
||||||
/// </summary>
|
|
||||||
public class BamlFile : Component |
|
||||||
{ |
|
||||||
private Uri _uri; |
|
||||||
private readonly Stream _stream; |
|
||||||
|
|
||||||
public BamlFile(Uri uri, Stream stream) |
|
||||||
{ |
|
||||||
if (uri == null) |
|
||||||
new ArgumentNullException("uri"); |
|
||||||
if (stream == null) |
|
||||||
throw new ArgumentNullException("stream"); |
|
||||||
|
|
||||||
_uri = uri; |
|
||||||
_stream = stream; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Carica il Baml attraverso il motore di WPF con Application.LoadComponent
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public object LoadContent() |
|
||||||
{ |
|
||||||
try |
|
||||||
{ |
|
||||||
return Application.LoadComponent(this.Uri); |
|
||||||
} |
|
||||||
catch (Exception e) |
|
||||||
{ |
|
||||||
throw new InvalidOperationException("Invalid baml file.", e); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected override void Dispose(bool disposing) |
|
||||||
{ |
|
||||||
base.Dispose(disposing); |
|
||||||
|
|
||||||
if (disposing) |
|
||||||
this.Stream.Dispose(); |
|
||||||
} |
|
||||||
|
|
||||||
public override object InitializeLifetimeService() |
|
||||||
{ |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Restituisce lo stream originale contenente il Baml
|
|
||||||
/// </summary>
|
|
||||||
public Stream Stream |
|
||||||
{ |
|
||||||
get { return _stream; } |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Restituisce l'indirizzo secondo lo schema pack://
|
|
||||||
/// </summary>
|
|
||||||
public Uri Uri |
|
||||||
{ |
|
||||||
get { return _uri; } |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,64 +0,0 @@ |
|||||||
// Copyright (c) Cristian Civera (cristian@aspitalia.com)
|
|
||||||
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.Text; |
|
||||||
|
|
||||||
namespace Ricciolo.StylesExplorer.MarkupReflection |
|
||||||
{ |
|
||||||
public class DotNetType : MarshalByRefObject, IType |
|
||||||
{ |
|
||||||
private readonly string _assemblyQualifiedName; |
|
||||||
private Type _type; |
|
||||||
|
|
||||||
public DotNetType(string assemblyQualifiedName) |
|
||||||
{ |
|
||||||
if (assemblyQualifiedName == null) throw new ArgumentNullException("assemblyQualifiedName"); |
|
||||||
|
|
||||||
_assemblyQualifiedName = assemblyQualifiedName; |
|
||||||
_type = Type.GetType(assemblyQualifiedName, false, true); |
|
||||||
} |
|
||||||
|
|
||||||
#region IType Members
|
|
||||||
|
|
||||||
public string AssemblyQualifiedName |
|
||||||
{ |
|
||||||
get { return _assemblyQualifiedName; } |
|
||||||
} |
|
||||||
|
|
||||||
public bool IsSubclassOf(IType type) |
|
||||||
{ |
|
||||||
if (type == null) throw new ArgumentNullException("type"); |
|
||||||
if (!(type is DotNetType)) throw new ArgumentException("type"); |
|
||||||
if (_type == null) return false; |
|
||||||
return this._type.IsSubclassOf(((DotNetType)type).Type); |
|
||||||
} |
|
||||||
|
|
||||||
public bool Equals(IType type) |
|
||||||
{ |
|
||||||
if (type == null) throw new ArgumentNullException("type"); |
|
||||||
if (!(type is DotNetType)) throw new ArgumentException("type"); |
|
||||||
if (_type == null) return false; |
|
||||||
return this._type.Equals(((DotNetType)type).Type); |
|
||||||
} |
|
||||||
|
|
||||||
public IType BaseType { |
|
||||||
get { |
|
||||||
return new DotNetType(this._type.BaseType.AssemblyQualifiedName); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public Type Type |
|
||||||
{ |
|
||||||
get { return _type; } |
|
||||||
} |
|
||||||
|
|
||||||
public override object InitializeLifetimeService() |
|
||||||
{ |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -0,0 +1,68 @@ |
|||||||
|
// Copyright (c) Cristian Civera (cristian@aspitalia.com)
|
||||||
|
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.ComponentModel; |
||||||
|
using System.Diagnostics; |
||||||
|
using System.Globalization; |
||||||
|
using System.IO; |
||||||
|
using System.Linq; |
||||||
|
using System.Reflection; |
||||||
|
using System.Text; |
||||||
|
using System.Xml; |
||||||
|
using System.Windows.Media; |
||||||
|
|
||||||
|
namespace Ricciolo.StylesExplorer.MarkupReflection |
||||||
|
{ |
||||||
|
class NodesCollection : List<XmlBamlNode> |
||||||
|
{ |
||||||
|
public XmlBamlNode Last |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
if (this.Count > 0) |
||||||
|
{ |
||||||
|
int i = this.Count - 1; |
||||||
|
return this[i]; |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void RemoveLast() |
||||||
|
{ |
||||||
|
if (this.Count > 0) |
||||||
|
this.Remove(this.Last); |
||||||
|
} |
||||||
|
|
||||||
|
public XmlBamlNode Dequeue() |
||||||
|
{ |
||||||
|
return DequeueInternal(true); |
||||||
|
} |
||||||
|
|
||||||
|
public XmlBamlNode Peek() |
||||||
|
{ |
||||||
|
return DequeueInternal(false); |
||||||
|
} |
||||||
|
|
||||||
|
XmlBamlNode DequeueInternal(bool remove) |
||||||
|
{ |
||||||
|
if (this.Count > 0) |
||||||
|
{ |
||||||
|
XmlBamlNode node = this[0]; |
||||||
|
if (remove) |
||||||
|
this.RemoveAt(0); |
||||||
|
return node; |
||||||
|
} |
||||||
|
else |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public void Enqueue(XmlBamlNode node) |
||||||
|
{ |
||||||
|
this.Add(node); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -1,35 +0,0 @@ |
|||||||
// Copyright (c) Cristian Civera (cristian@aspitalia.com)
|
|
||||||
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.ComponentModel; |
|
||||||
using System.Text; |
|
||||||
|
|
||||||
namespace Ricciolo.StylesExplorer.MarkupReflection |
|
||||||
{ |
|
||||||
public class WpfDependencyPropertyDescriptor : MarshalByRefObject, IDependencyPropertyDescriptor |
|
||||||
{ |
|
||||||
private readonly DependencyPropertyDescriptor _propertyDescriptor; |
|
||||||
|
|
||||||
public WpfDependencyPropertyDescriptor(DependencyPropertyDescriptor propertyDescriptor) |
|
||||||
{ |
|
||||||
if (propertyDescriptor == null) throw new ArgumentNullException("propertyDescriptor"); |
|
||||||
_propertyDescriptor = propertyDescriptor; |
|
||||||
} |
|
||||||
|
|
||||||
#region IDependencyPropertyDescriptor Members
|
|
||||||
|
|
||||||
public bool IsAttached |
|
||||||
{ |
|
||||||
get { return _propertyDescriptor.IsAttached; } |
|
||||||
} |
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public override object InitializeLifetimeService() |
|
||||||
{ |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -0,0 +1,23 @@ |
|||||||
|
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||||
|
<Color x:Key="VeryDark" A="255" R="70" G="70" B="70" /> |
||||||
|
<Color x:Key="Dark" A="255" R="102" G="102" B="102" /> |
||||||
|
<Color x:Key="Medium" A="255" R="140" G="140" B="140" /> |
||||||
|
<Color x:Key="Light" A="255" R="204" G="204" B="204" /> |
||||||
|
<Color x:Key="VeryLight" A="255" R="241" G="241" B="241" /> |
||||||
|
<Color x:Key="OffWhite" A="255" R="255" G="255" B="255" /> |
||||||
|
<Color x:Key="Highlight" A="255" R="220" G="107" B="47" /> |
||||||
|
<SolidColorBrush x:Key="VeryDarkBrush" Color="{StaticResource VeryDark}" /> |
||||||
|
<SolidColorBrush x:Key="DarkBrush" Color="{StaticResource Dark}" /> |
||||||
|
<SolidColorBrush x:Key="MediumBrush" Color="{StaticResource Medium}" /> |
||||||
|
<SolidColorBrush x:Key="LightBrush" Color="{StaticResource Light}" /> |
||||||
|
<SolidColorBrush x:Key="VeryLightBrush" Color="{StaticResource VeryLight}" /> |
||||||
|
<SolidColorBrush x:Key="OffWhiteBrush" Color="{StaticResource OffWhite}" /> |
||||||
|
<SolidColorBrush x:Key="HighlightBrush" Color="{StaticResource Highlight}" /> |
||||||
|
<LinearGradientBrush x:Key="EdgeBorder" StartPoint="0,0" EndPoint="0,1"> |
||||||
|
<GradientStop Color="#0000" Offset="0" /> |
||||||
|
<GradientStop Color="#1000" Offset="0.65" /> |
||||||
|
<GradientStop Color="#3000" Offset="1" /> |
||||||
|
</LinearGradientBrush> |
||||||
|
<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#6FFF" /> |
||||||
|
<SolidColorBrush x:Key="SelectedBackgroundBrush" Color="{StaticResource Light}" /> |
||||||
|
</ResourceDictionary> |
||||||
@ -0,0 +1,26 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<UserControl |
||||||
|
x:Class="ICSharpCode.ILSpy.Controls.ResourceStringTable" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||||
|
<UserControl.CommandBindings> |
||||||
|
<CommandBinding Command="ApplicationCommands.Copy" |
||||||
|
Executed="ExecuteCopy" |
||||||
|
CanExecute="CanExecuteCopy"/> |
||||||
|
</UserControl.CommandBindings> |
||||||
|
<ListView |
||||||
|
Name="resourceListView" |
||||||
|
SelectionMode="Extended"> |
||||||
|
<ListView.View> |
||||||
|
<GridView |
||||||
|
AllowsColumnReorder="False"> |
||||||
|
<GridView.Columns> |
||||||
|
<GridViewColumn |
||||||
|
Header="Resource id" |
||||||
|
DisplayMemberBinding="{Binding Key}" /> |
||||||
|
<GridViewColumn |
||||||
|
Header="Resource value" |
||||||
|
DisplayMemberBinding="{Binding Value}" /> |
||||||
|
</GridView.Columns> |
||||||
|
</GridView> |
||||||
|
</ListView.View> |
||||||
|
</ListView> |
||||||
|
</UserControl> |
||||||
@ -0,0 +1,51 @@ |
|||||||
|
/* |
||||||
|
* Created by SharpDevelop. |
||||||
|
* User: Ronny Klier |
||||||
|
* Date: 31.05.2011 |
||||||
|
* Time: 00:13 |
||||||
|
* |
||||||
|
* To change this template use Tools | Options | Coding | Edit Standard Headers. |
||||||
|
*/ |
||||||
|
using System; |
||||||
|
using System.Collections; |
||||||
|
using System.Text; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Controls; |
||||||
|
using System.Windows.Data; |
||||||
|
using System.Windows.Documents; |
||||||
|
using System.Windows.Input; |
||||||
|
using System.Windows.Media; |
||||||
|
|
||||||
|
namespace ICSharpCode.ILSpy.Controls |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for ResourceStringTable.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class ResourceStringTable : UserControl |
||||||
|
{ |
||||||
|
public ResourceStringTable(IEnumerable strings) |
||||||
|
{ |
||||||
|
InitializeComponent(); |
||||||
|
// set size to fit decompiler window
|
||||||
|
// TODO: there should be a more transparent way to do this
|
||||||
|
MaxWidth = MainWindow.Instance.mainPane.ActualWidth-20; |
||||||
|
MaxHeight = MainWindow.Instance.mainPane.ActualHeight-100; |
||||||
|
resourceListView.ItemsSource = strings; |
||||||
|
} |
||||||
|
|
||||||
|
void ExecuteCopy(object sender, ExecutedRoutedEventArgs args) |
||||||
|
{ |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
foreach (var item in resourceListView.SelectedItems) |
||||||
|
{ |
||||||
|
sb.AppendLine(item.ToString()); |
||||||
|
} |
||||||
|
Clipboard.SetText(sb.ToString()); |
||||||
|
} |
||||||
|
|
||||||
|
void CanExecuteCopy(object sender, CanExecuteRoutedEventArgs args) |
||||||
|
{ |
||||||
|
args.CanExecute = true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,72 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build"> |
||||||
|
<PropertyGroup> |
||||||
|
<ProjectGuid>{F054A788-B591-4561-A8BA-AE745BBEB817}</ProjectGuid> |
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
||||||
|
<Platform Condition=" '$(Platform)' == '' ">x86</Platform> |
||||||
|
<OutputType>Library</OutputType> |
||||||
|
<RootNamespace>ICSharpCode.Editor</RootNamespace> |
||||||
|
<AssemblyName>ICSharpCode.Editor</AssemblyName> |
||||||
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> |
||||||
|
<TargetFrameworkProfile>Client</TargetFrameworkProfile> |
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder> |
||||||
|
<SignAssembly>False</SignAssembly> |
||||||
|
<DelaySign>False</DelaySign> |
||||||
|
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent> |
||||||
|
<DocumentationFile>bin\Debug\ICSharpCode.Editor.xml</DocumentationFile> |
||||||
|
<AllowUnsafeBlocks>False</AllowUnsafeBlocks> |
||||||
|
<NoStdLib>False</NoStdLib> |
||||||
|
<WarningLevel>4</WarningLevel> |
||||||
|
<TreatWarningsAsErrors>false</TreatWarningsAsErrors> |
||||||
|
<RunCodeAnalysis>False</RunCodeAnalysis> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition=" '$(Platform)' == 'x86' "> |
||||||
|
<PlatformTarget>x86</PlatformTarget> |
||||||
|
<RegisterForComInterop>False</RegisterForComInterop> |
||||||
|
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies> |
||||||
|
<BaseAddress>4194304</BaseAddress> |
||||||
|
<FileAlignment>4096</FileAlignment> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> |
||||||
|
<OutputPath>bin\Debug\</OutputPath> |
||||||
|
<DebugSymbols>true</DebugSymbols> |
||||||
|
<DebugType>Full</DebugType> |
||||||
|
<Optimize>False</Optimize> |
||||||
|
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow> |
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants> |
||||||
|
<StartAction>Project</StartAction> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> |
||||||
|
<OutputPath>bin\Release\</OutputPath> |
||||||
|
<DebugSymbols>False</DebugSymbols> |
||||||
|
<DebugType>None</DebugType> |
||||||
|
<Optimize>True</Optimize> |
||||||
|
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow> |
||||||
|
<DefineConstants>TRACE</DefineConstants> |
||||||
|
</PropertyGroup> |
||||||
|
<ItemGroup> |
||||||
|
<Reference Include="System" /> |
||||||
|
<Reference Include="System.Core"> |
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework> |
||||||
|
</Reference> |
||||||
|
<Reference Include="System.Xml" /> |
||||||
|
<Reference Include="System.Xml.Linq"> |
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework> |
||||||
|
</Reference> |
||||||
|
</ItemGroup> |
||||||
|
<ItemGroup> |
||||||
|
<Compile Include="IDocument.cs" /> |
||||||
|
<Compile Include="IDocumentLine.cs" /> |
||||||
|
<Compile Include="ISegment.cs" /> |
||||||
|
<Compile Include="ITextEditor.cs" /> |
||||||
|
<Compile Include="ITextSource.cs" /> |
||||||
|
<Compile Include="LinkedElement.cs" /> |
||||||
|
<Compile Include="ReadOnlyDocument.cs" /> |
||||||
|
<Compile Include="StringTextSource.cs" /> |
||||||
|
<Compile Include="TextLocation.cs" /> |
||||||
|
<Compile Include="ITextAnchor.cs" /> |
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" /> |
||||||
|
<Compile Include="TextChangeEventArgs.cs" /> |
||||||
|
</ItemGroup> |
||||||
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" /> |
||||||
|
</Project> |
||||||
@ -0,0 +1,141 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
|
||||||
|
namespace ICSharpCode.Editor |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// A document representing a source code file for refactoring.
|
||||||
|
/// Line and column counting starts at 1.
|
||||||
|
/// Offset counting starts at 0.
|
||||||
|
/// </summary>
|
||||||
|
public interface IDocument : ITextSource, IServiceProvider |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Gets/Sets the text of the whole document..
|
||||||
|
/// </summary>
|
||||||
|
new string Text { get; set; } // hides TextBuffer.Text to add the setter
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is raised when the Text property changes.
|
||||||
|
/// </summary>
|
||||||
|
event EventHandler TextChanged; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the total number of lines in the document.
|
||||||
|
/// </summary>
|
||||||
|
int TotalNumberOfLines { get; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the document line with the specified number.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lineNumber">The number of the line to retrieve. The first line has number 1.</param>
|
||||||
|
IDocumentLine GetLine(int lineNumber); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the document line that contains the specified offset.
|
||||||
|
/// </summary>
|
||||||
|
IDocumentLine GetLineByOffset(int offset); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the offset from a text location.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="GetLocation"/>
|
||||||
|
int GetOffset(int line, int column); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the offset from a text location.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="GetLocation"/>
|
||||||
|
int GetOffset(TextLocation location); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the location from an offset.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="GetOffset(TextLocation)"/>
|
||||||
|
TextLocation GetLocation(int offset); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inserts text.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="offset">The offset at which the text is inserted.</param>
|
||||||
|
/// <param name="text">The new text.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// Anchors positioned exactly at the insertion offset will move according to their movement type.
|
||||||
|
/// For AnchorMovementType.Default, they will move behind the inserted text.
|
||||||
|
/// The caret will also move behind the inserted text.
|
||||||
|
/// </remarks>
|
||||||
|
void Insert(int offset, string text); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inserts text.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="offset">The offset at which the text is inserted.</param>
|
||||||
|
/// <param name="text">The new text.</param>
|
||||||
|
/// <param name="defaultAnchorMovementType">
|
||||||
|
/// Anchors positioned exactly at the insertion offset will move according to the anchor's movement type.
|
||||||
|
/// For AnchorMovementType.Default, they will move according to the movement type specified by this parameter.
|
||||||
|
/// The caret will also move according to the <paramref name="defaultAnchorMovementType"/> parameter.
|
||||||
|
/// </param>
|
||||||
|
void Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes text.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="offset">Starting offset of the text to be removed.</param>
|
||||||
|
/// <param name="length">Length of the text to be removed.</param>
|
||||||
|
void Remove(int offset, int length); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Replaces text.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="offset">The starting offset of the text to be replaced.</param>
|
||||||
|
/// <param name="length">The length of the text to be replaced.</param>
|
||||||
|
/// <param name="newText">The new text.</param>
|
||||||
|
void Replace(int offset, int length, string newText); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Make the document combine the following actions into a single
|
||||||
|
/// action for undo purposes.
|
||||||
|
/// </summary>
|
||||||
|
void StartUndoableAction(); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ends the undoable action started with <see cref="StartUndoableAction"/>.
|
||||||
|
/// </summary>
|
||||||
|
void EndUndoableAction(); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an undo group. Dispose the returned value to close the undo group.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>An object that closes the undo group when Dispose() is called.</returns>
|
||||||
|
IDisposable OpenUndoGroup(); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="ITextAnchor"/> at the specified offset.
|
||||||
|
/// </summary>
|
||||||
|
/// <inheritdoc cref="ITextAnchor" select="remarks|example"/>
|
||||||
|
ITextAnchor CreateAnchor(int offset); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This event is called directly before a change is applied to the document.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// It is invalid to modify the document within this event handler.
|
||||||
|
/// Aborting the change (by throwing an exception) is likely to cause corruption of data structures
|
||||||
|
/// that listen to the Changing and Changed events.
|
||||||
|
/// </remarks>
|
||||||
|
event EventHandler<TextChangeEventArgs> Changing; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This event is called directly after a change is applied to the document.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// It is invalid to modify the document within this event handler.
|
||||||
|
/// Aborting the event handler (by throwing an exception) is likely to cause corruption of data structures
|
||||||
|
/// that listen to the Changing and Changed events.
|
||||||
|
/// </remarks>
|
||||||
|
event EventHandler<TextChangeEventArgs> Changed; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,30 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
|
||||||
|
namespace ICSharpCode.Editor |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// A line inside a <see cref="IDocument"/>.
|
||||||
|
/// </summary>
|
||||||
|
public interface IDocumentLine : ISegment |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Gets the length of this line, including the line delimiter.
|
||||||
|
/// </summary>
|
||||||
|
int TotalLength { get; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the length of the line terminator.
|
||||||
|
/// Returns 1 or 2; or 0 at the end of the document.
|
||||||
|
/// </summary>
|
||||||
|
int DelimiterLength { get; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of this line.
|
||||||
|
/// The first line has the number 1.
|
||||||
|
/// </summary>
|
||||||
|
int LineNumber { get; } |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,55 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
|
||||||
|
namespace ICSharpCode.Editor |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// An (Offset,Length)-pair.
|
||||||
|
/// </summary>
|
||||||
|
public interface ISegment |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Gets the start offset of the segment.
|
||||||
|
/// </summary>
|
||||||
|
int Offset { get; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the length of the segment.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Must not be negative.</remarks>
|
||||||
|
int Length { get; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the end offset of the segment.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>EndOffset = Offset + Length;</remarks>
|
||||||
|
int EndOffset { get; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for <see cref="ISegment"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static class ISegmentExtensions |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the segment contains the offset.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// True, if offset is between segment.Start and segment.End (inclusive); otherwise, false.
|
||||||
|
/// </returns>
|
||||||
|
public static bool Contains (this ISegment segment, int offset) |
||||||
|
{ |
||||||
|
return segment.Offset <= offset && offset <= segment.EndOffset; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True, if the segment contains the specified segment, false otherwise.
|
||||||
|
/// </summary>
|
||||||
|
public static bool Contains (this ISegment thisSegment, ISegment segment) |
||||||
|
{ |
||||||
|
return segment != null && thisSegment.Offset <= segment.Offset && segment.EndOffset <= thisSegment.EndOffset; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,102 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
|
||||||
|
namespace ICSharpCode.Editor |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// The TextAnchor class references an offset (a position between two characters).
|
||||||
|
/// It automatically updates the offset when text is inserted/removed in front of the anchor.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Use the <see cref="ITextAnchor.Offset"/> property to get the offset from a text anchor.
|
||||||
|
/// Use the <see cref="IDocument.CreateAnchor"/> method to create an anchor from an offset.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// The document will automatically update all text anchors; and because it uses weak references to do so,
|
||||||
|
/// the garbage collector can simply collect the anchor object when you don't need it anymore.
|
||||||
|
/// </para>
|
||||||
|
/// <para>Moreover, the document is able to efficiently update a large number of anchors without having to look
|
||||||
|
/// at each anchor object individually. Updating the offsets of all anchors usually only takes time logarithmic
|
||||||
|
/// to the number of anchors. Retrieving the <see cref="ITextAnchor.Offset"/> property also runs in O(lg N).</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// Usage:
|
||||||
|
/// <code>TextAnchor anchor = document.CreateAnchor(offset);
|
||||||
|
/// ChangeMyDocument();
|
||||||
|
/// int newOffset = anchor.Offset;
|
||||||
|
/// </code>
|
||||||
|
/// </example>
|
||||||
|
public interface ITextAnchor |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Gets the text location of this anchor.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="InvalidOperationException">Thrown when trying to get the Offset from a deleted anchor.</exception>
|
||||||
|
TextLocation Location { get; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the offset of the text anchor.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="InvalidOperationException">Thrown when trying to get the Offset from a deleted anchor.</exception>
|
||||||
|
int Offset { get; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controls how the anchor moves.
|
||||||
|
/// </summary>
|
||||||
|
AnchorMovementType MovementType { get; set; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies whether the anchor survives deletion of the text containing it.
|
||||||
|
/// <c>false</c>: The anchor is deleted when the a selection that includes the anchor is deleted.
|
||||||
|
/// <c>true</c>: The anchor is not deleted.
|
||||||
|
/// </summary>
|
||||||
|
bool SurviveDeletion { get; set; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the anchor was deleted.
|
||||||
|
/// </summary>
|
||||||
|
bool IsDeleted { get; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs after the anchor was deleted.
|
||||||
|
/// </summary>
|
||||||
|
event EventHandler Deleted; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the line number of the anchor.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="InvalidOperationException">Thrown when trying to get the Offset from a deleted anchor.</exception>
|
||||||
|
int Line { get; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the column number of this anchor.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="InvalidOperationException">Thrown when trying to get the Offset from a deleted anchor.</exception>
|
||||||
|
int Column { get; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines how a text anchor moves.
|
||||||
|
/// </summary>
|
||||||
|
public enum AnchorMovementType |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// When text is inserted at the anchor position, the type of the insertion
|
||||||
|
/// determines where the caret moves to. For normal insertions, the anchor will stay
|
||||||
|
/// behind the inserted text.
|
||||||
|
/// </summary>
|
||||||
|
Default, |
||||||
|
/// <summary>
|
||||||
|
/// Behaves like a start marker - when text is inserted at the anchor position, the anchor will stay
|
||||||
|
/// before the inserted text.
|
||||||
|
/// </summary>
|
||||||
|
BeforeInsertion, |
||||||
|
/// <summary>
|
||||||
|
/// Behave like an end marker - when text is insered at the anchor position, the anchor will move
|
||||||
|
/// after the inserted text.
|
||||||
|
/// </summary>
|
||||||
|
AfterInsertion |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,100 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Threading.Tasks; |
||||||
|
|
||||||
|
namespace ICSharpCode.Editor |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Interface for text editors.
|
||||||
|
/// </summary>
|
||||||
|
public interface ITextEditor : IServiceProvider |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Gets the document that is being edited.
|
||||||
|
/// </summary>
|
||||||
|
IDocument Document { get; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an object that represents the caret inside this text editor.
|
||||||
|
/// </summary>
|
||||||
|
ITextEditorCaret Caret { get; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the caret to the specified line/column and brings the caret into view.
|
||||||
|
/// </summary>
|
||||||
|
void JumpTo(int line, int column); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the start offset of the selection.
|
||||||
|
/// </summary>
|
||||||
|
int SelectionStart { get; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the length of the selection.
|
||||||
|
/// </summary>
|
||||||
|
int SelectionLength { get; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets/Sets the selected text.
|
||||||
|
/// </summary>
|
||||||
|
string SelectedText { get; set; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the selection.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="selectionStart">Start offset of the selection</param>
|
||||||
|
/// <param name="selectionLength">Length of the selection</param>
|
||||||
|
void Select(int selectionStart, int selectionLength); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shows the specified linked elements, and allows the user to edit them.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Returns true when the user has finished editing the elements and pressed Return;
|
||||||
|
/// or false when editing is aborted for any reason.
|
||||||
|
/// </returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// The user can also edit other parts of the document (or other documents) while in link mode.
|
||||||
|
/// In case of success (true return value), this method will update the offsets of the linked elements
|
||||||
|
/// to reflect the changes done by the user.
|
||||||
|
/// If the text editor does not support link mode, it will immediately return false.
|
||||||
|
/// </remarks>
|
||||||
|
// Task<bool> ShowLinkedElements(IEnumerable<LinkedElement> linkedElements);
|
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the caret in a text editor.
|
||||||
|
/// </summary>
|
||||||
|
public interface ITextEditorCaret |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Gets/Sets the caret offset;
|
||||||
|
/// </summary>
|
||||||
|
int Offset { get; set; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets/Sets the caret line number.
|
||||||
|
/// Line numbers are counted starting from 1.
|
||||||
|
/// </summary>
|
||||||
|
int Line { get; set; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets/Sets the caret column number.
|
||||||
|
/// Column numbers are counted starting from 1.
|
||||||
|
/// </summary>
|
||||||
|
int Column { get; set; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets/sets the caret location.
|
||||||
|
/// </summary>
|
||||||
|
TextLocation Location { get; set; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is raised whenever the location of the caret has changed.
|
||||||
|
/// </summary>
|
||||||
|
event EventHandler LocationChanged; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,147 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.IO; |
||||||
|
|
||||||
|
namespace ICSharpCode.Editor |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// A read-only view on a (potentially mutable) text source.
|
||||||
|
/// The IDocument interfaces derives from this interface.
|
||||||
|
/// </summary>
|
||||||
|
public interface ITextSource |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Gets a version identifier for this text source.
|
||||||
|
/// Returns null for unversioned text sources.
|
||||||
|
/// </summary>
|
||||||
|
ITextSourceVersion Version { get; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an immutable snapshot of this text source.
|
||||||
|
/// Unlike all other methods in this interface, this method is thread-safe.
|
||||||
|
/// </summary>
|
||||||
|
ITextSource CreateSnapshot(); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an immutable snapshot of a part of this text source.
|
||||||
|
/// Unlike all other methods in this interface, this method is thread-safe.
|
||||||
|
/// </summary>
|
||||||
|
ITextSource CreateSnapshot(int offset, int length); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new TextReader to read from this text source.
|
||||||
|
/// </summary>
|
||||||
|
TextReader CreateReader(); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new TextReader to read from this text source.
|
||||||
|
/// </summary>
|
||||||
|
TextReader CreateReader(int offset, int length); |
||||||
|
|
||||||
|
/// <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; } |
||||||
|
|
||||||
|
/// <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>
|
||||||
|
/// 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 GetText(int offset, int length); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the text for a portion of the document.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">offset or length is outside the valid range.</exception>
|
||||||
|
string GetText(ISegment segment); |
||||||
|
|
||||||
|
/// <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 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); |
||||||
|
|
||||||
|
/* What about: |
||||||
|
void Insert (int offset, string value); |
||||||
|
void Remove (int offset, int count); |
||||||
|
void Remove (ISegment segment); |
||||||
|
|
||||||
|
void Replace (int offset, int count, string value); |
||||||
|
|
||||||
|
Or more search operations: |
||||||
|
|
||||||
|
IEnumerable<int> SearchForward (string pattern, int startIndex); |
||||||
|
IEnumerable<int> SearchForwardIgnoreCase (string pattern, int startIndex); |
||||||
|
|
||||||
|
IEnumerable<int> SearchBackward (string pattern, int startIndex); |
||||||
|
IEnumerable<int> SearchBackwardIgnoreCase (string pattern, int startIndex); |
||||||
|
*/ |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a version identifier for a text source.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Verions can be used to efficiently detect whether a document has changed and needs reparsing;
|
||||||
|
/// or even to implement incremental parsers.
|
||||||
|
/// It is a separate class from ITextBuffer to allow the GC to collect the text buffer while
|
||||||
|
/// the version checkpoint is still in use.
|
||||||
|
/// </remarks>
|
||||||
|
public interface ITextSourceVersion |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Gets whether this checkpoint belongs to the same document as the other checkpoint.
|
||||||
|
/// </summary>
|
||||||
|
bool BelongsToSameDocumentAs(ITextSourceVersion other); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares the age of this checkpoint to the other checkpoint.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This method is thread-safe.</remarks>
|
||||||
|
/// <exception cref="ArgumentException">Raised if 'other' belongs to a different document than this version.</exception>
|
||||||
|
/// <returns>-1 if this version is older than <paramref name="other"/>.
|
||||||
|
/// 0 if <c>this</c> version instance represents the same version as <paramref name="other"/>.
|
||||||
|
/// 1 if this version is newer than <paramref name="other"/>.</returns>
|
||||||
|
int CompareAge(ITextSourceVersion other); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the changes from this checkpoint to the other checkpoint.
|
||||||
|
/// If 'other' is older than this checkpoint, reverse changes are calculated.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This method is thread-safe.</remarks>
|
||||||
|
/// <exception cref="ArgumentException">Raised if 'other' belongs to a different document than this checkpoint.</exception>
|
||||||
|
IEnumerable<TextChangeEventArgs> GetChangesTo(ITextSourceVersion other); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates where the offset has moved in the other buffer version.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="ArgumentException">Raised if 'other' belongs to a different document than this checkpoint.</exception>
|
||||||
|
int MoveOffsetTo(ITextSourceVersion other, int oldOffset, AnchorMovementType movement); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,68 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
|
||||||
|
namespace ICSharpCode.Editor |
||||||
|
{ |
||||||
|
// I'm not sure if we need this.
|
||||||
|
// How about a method in the context - this method could wrap the internal representation.
|
||||||
|
// public void StartTextLinkMode (int linkLength, IEnumerable<int> offsets)
|
||||||
|
// and maybe then variations taking more than one link element ?
|
||||||
|
|
||||||
|
// /// <summary>
|
||||||
|
// /// Represents an element in the text editor that is either editable, or bound to another editable element.
|
||||||
|
// /// Used with <see cref="ITextEditor.ShowLinkedElements"/>
|
||||||
|
// /// </summary>
|
||||||
|
// public class LinkedElement
|
||||||
|
// {
|
||||||
|
// LinkedElement boundTo;
|
||||||
|
//
|
||||||
|
// /// <summary>
|
||||||
|
// /// Gets/Sets the start offset of this linked element.
|
||||||
|
// /// </summary>
|
||||||
|
// public int StartOffset { get; set; }
|
||||||
|
//
|
||||||
|
// /// <summary>
|
||||||
|
// /// Gets/Sets the end offset of this linked element.
|
||||||
|
// /// </summary>
|
||||||
|
// public int EndOffset { get; set; }
|
||||||
|
//
|
||||||
|
// /// <summary>
|
||||||
|
// /// Gets the linked element to which this element is bound.
|
||||||
|
// /// </summary>
|
||||||
|
// public LinkedElement BoundTo {
|
||||||
|
// get { return boundTo; }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /// <summary>
|
||||||
|
// /// Gets whether this element is editable. Returns true if this element is not bound.
|
||||||
|
// /// </summary>
|
||||||
|
// public bool IsEditable {
|
||||||
|
// get { return boundTo == null; }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /// <summary>
|
||||||
|
// /// Creates a new editable element.
|
||||||
|
// /// </summary>
|
||||||
|
// public LinkedElement(int startOffset, int endOffset)
|
||||||
|
// {
|
||||||
|
// this.StartOffset = startOffset;
|
||||||
|
// this.EndOffset = endOffset;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /// <summary>
|
||||||
|
// /// Creates a new element that is bound to <paramref name="boundTo"/>.
|
||||||
|
// /// </summary>
|
||||||
|
// public LinkedElement(int startOffset, int endOffset, LinkedElement boundTo)
|
||||||
|
// {
|
||||||
|
// if (boundTo == null)
|
||||||
|
// throw new ArgumentNullException("boundTo");
|
||||||
|
// this.StartOffset = startOffset;
|
||||||
|
// this.EndOffset = endOffset;
|
||||||
|
// while (boundTo.boundTo != null)
|
||||||
|
// boundTo = boundTo.boundTo;
|
||||||
|
// this.boundTo = boundTo;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
} |
||||||
@ -0,0 +1,31 @@ |
|||||||
|
#region Using directives
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Reflection; |
||||||
|
using System.Runtime.InteropServices; |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("ICSharpCode.Editor")] |
||||||
|
[assembly: AssemblyDescription("")] |
||||||
|
[assembly: AssemblyConfiguration("")] |
||||||
|
[assembly: AssemblyCompany("")] |
||||||
|
[assembly: AssemblyProduct("ICSharpCode.Editor")] |
||||||
|
[assembly: AssemblyCopyright("Copyright 2011")] |
||||||
|
[assembly: AssemblyTrademark("")] |
||||||
|
[assembly: AssemblyCulture("")] |
||||||
|
|
||||||
|
// This sets the default COM visibility of types in the assembly to invisible.
|
||||||
|
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
|
||||||
|
[assembly: ComVisible(false)] |
||||||
|
|
||||||
|
// The assembly version has following format :
|
||||||
|
//
|
||||||
|
// Major.Minor.Build.Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can use the default the Revision and
|
||||||
|
// Build Numbers by using the '*' as shown below:
|
||||||
|
[assembly: AssemblyVersion("1.0.*")] |
||||||
@ -0,0 +1,321 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
|
||||||
|
namespace ICSharpCode.Editor |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Read-only implementation of <see cref="IDocument"/>.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ReadOnlyDocument : IDocument |
||||||
|
{ |
||||||
|
readonly ITextSource textSource; |
||||||
|
int[] lines; |
||||||
|
|
||||||
|
static readonly char[] newline = { '\r', '\n' }; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new ReadOnlyDocument from the given text source.
|
||||||
|
/// </summary>
|
||||||
|
public ReadOnlyDocument(ITextSource textSource) |
||||||
|
{ |
||||||
|
if (textSource == null) |
||||||
|
throw new ArgumentNullException("textSource"); |
||||||
|
// ensure that underlying buffer is immutable
|
||||||
|
this.textSource = textSource.CreateSnapshot(); |
||||||
|
List<int> lines = new List<int>(); |
||||||
|
lines.Add(0); |
||||||
|
int offset = 0; |
||||||
|
int textLength = textSource.TextLength; |
||||||
|
while ((offset = textSource.IndexOfAny(newline, offset, textLength - offset)) >= 0) { |
||||||
|
offset++; |
||||||
|
if (textSource.GetCharAt(offset - 1) == '\r' && offset < textLength && textSource.GetCharAt(offset) == '\n') { |
||||||
|
offset++; |
||||||
|
} |
||||||
|
lines.Add(offset); |
||||||
|
} |
||||||
|
this.lines = lines.ToArray(); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new ReadOnlyDocument from the given string.
|
||||||
|
/// </summary>
|
||||||
|
public ReadOnlyDocument(string text) |
||||||
|
: this(new StringTextSource(text)) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
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; |
||||||
|
readonly int offset, endOffset; |
||||||
|
|
||||||
|
public ReadOnlyDocumentLine(ReadOnlyDocument doc, int lineNumber) |
||||||
|
{ |
||||||
|
this.doc = doc; |
||||||
|
this.lineNumber = lineNumber; |
||||||
|
this.offset = doc.GetStartOffset(lineNumber); |
||||||
|
this.endOffset = doc.GetEndOffset(lineNumber); |
||||||
|
} |
||||||
|
|
||||||
|
public int Offset { |
||||||
|
get { return offset; } |
||||||
|
} |
||||||
|
|
||||||
|
public int Length { |
||||||
|
get { return endOffset - offset; } |
||||||
|
} |
||||||
|
|
||||||
|
public int EndOffset { |
||||||
|
get { return endOffset; } |
||||||
|
} |
||||||
|
|
||||||
|
public int TotalLength { |
||||||
|
get { |
||||||
|
return doc.GetTotalEndOffset(lineNumber) - offset; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public int DelimiterLength { |
||||||
|
get { |
||||||
|
return doc.GetTotalEndOffset(lineNumber) - endOffset; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public int LineNumber { |
||||||
|
get { return lineNumber; } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
int GetStartOffset(int lineNumber) |
||||||
|
{ |
||||||
|
return lines[lineNumber-1]; |
||||||
|
} |
||||||
|
|
||||||
|
int GetTotalEndOffset(int lineNumber) |
||||||
|
{ |
||||||
|
return lineNumber < lines.Length ? lines[lineNumber] : textSource.TextLength; |
||||||
|
} |
||||||
|
|
||||||
|
int GetEndOffset(int lineNumber) |
||||||
|
{ |
||||||
|
if (lineNumber == lines.Length) |
||||||
|
return textSource.TextLength; |
||||||
|
int off = lines[lineNumber] - 1; |
||||||
|
if (off > 0 && textSource.GetCharAt(off - 1) == '\r' && textSource.GetCharAt(off) == '\n') |
||||||
|
off--; |
||||||
|
return off; |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IDocumentLine GetLineByOffset(int offset) |
||||||
|
{ |
||||||
|
return GetLine(GetLineNumberForOffset(offset)); |
||||||
|
} |
||||||
|
|
||||||
|
int GetLineNumberForOffset(int offset) |
||||||
|
{ |
||||||
|
int r = Array.BinarySearch(lines, offset); |
||||||
|
return r < 0 ? ~r : r + 1; |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public int GetOffset(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; |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public int GetOffset(TextLocation location) |
||||||
|
{ |
||||||
|
return GetOffset(location.Line, location.Column); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public TextLocation GetLocation(int offset) |
||||||
|
{ |
||||||
|
if (offset < 0 || offset > textSource.TextLength) |
||||||
|
throw new ArgumentOutOfRangeException("offset", offset, "Value must be between 0 and " + textSource.TextLength); |
||||||
|
int line = GetLineNumberForOffset(offset); |
||||||
|
return new TextLocation(offset-GetStartOffset(line)+1, line); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string Text { |
||||||
|
get { return textSource.Text; } |
||||||
|
set { |
||||||
|
throw new NotSupportedException(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public int TotalNumberOfLines { |
||||||
|
get { return lines.Length; } |
||||||
|
} |
||||||
|
|
||||||
|
ITextSourceVersion ITextSource.Version { |
||||||
|
get { return null; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public int TextLength { |
||||||
|
get { return textSource.TextLength; } |
||||||
|
} |
||||||
|
|
||||||
|
event EventHandler<TextChangeEventArgs> IDocument.Changing { add {} remove {} } |
||||||
|
|
||||||
|
event EventHandler<TextChangeEventArgs> IDocument.Changed { add {} remove {} } |
||||||
|
|
||||||
|
event EventHandler IDocument.TextChanged { add {} remove {} } |
||||||
|
|
||||||
|
void IDocument.Insert(int offset, string text) |
||||||
|
{ |
||||||
|
throw new NotSupportedException(); |
||||||
|
} |
||||||
|
|
||||||
|
void IDocument.Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType) |
||||||
|
{ |
||||||
|
throw new NotSupportedException(); |
||||||
|
} |
||||||
|
|
||||||
|
void IDocument.Remove(int offset, int length) |
||||||
|
{ |
||||||
|
throw new NotSupportedException(); |
||||||
|
} |
||||||
|
|
||||||
|
void IDocument.Replace(int offset, int length, string newText) |
||||||
|
{ |
||||||
|
throw new NotSupportedException(); |
||||||
|
} |
||||||
|
|
||||||
|
void IDocument.StartUndoableAction() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
void IDocument.EndUndoableAction() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
IDisposable IDocument.OpenUndoGroup() |
||||||
|
{ |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public ITextAnchor CreateAnchor(int offset) |
||||||
|
{ |
||||||
|
return new ReadOnlyDocumentTextAnchor(GetLocation(offset), offset); |
||||||
|
} |
||||||
|
|
||||||
|
sealed class ReadOnlyDocumentTextAnchor : ITextAnchor |
||||||
|
{ |
||||||
|
readonly TextLocation location; |
||||||
|
readonly int offset; |
||||||
|
|
||||||
|
public ReadOnlyDocumentTextAnchor(TextLocation location, int offset) |
||||||
|
{ |
||||||
|
this.location = location; |
||||||
|
this.offset = offset; |
||||||
|
} |
||||||
|
|
||||||
|
public event EventHandler Deleted { add {} remove {} } |
||||||
|
|
||||||
|
public TextLocation 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; } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public ITextSource CreateSnapshot() |
||||||
|
{ |
||||||
|
return textSource; // textBuffer is immutable
|
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public ITextSource CreateSnapshot(int offset, int length) |
||||||
|
{ |
||||||
|
return textSource.CreateSnapshot(offset, length); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public System.IO.TextReader CreateReader() |
||||||
|
{ |
||||||
|
return textSource.CreateReader(); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public System.IO.TextReader CreateReader(int offset, int length) |
||||||
|
{ |
||||||
|
return textSource.CreateReader(offset, length); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public char GetCharAt(int offset) |
||||||
|
{ |
||||||
|
return textSource.GetCharAt(offset); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string GetText(int offset, int length) |
||||||
|
{ |
||||||
|
return textSource.GetText(offset, length); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string GetText(ISegment segment) |
||||||
|
{ |
||||||
|
return textSource.GetText(segment); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public int IndexOfAny(char[] anyOf, int startIndex, int count) |
||||||
|
{ |
||||||
|
return textSource.IndexOfAny(anyOf, startIndex, count); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public object GetService(Type serviceType) |
||||||
|
{ |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,91 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.IO; |
||||||
|
|
||||||
|
namespace ICSharpCode.Editor |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Implements the ITextSource interface using a string.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable] |
||||||
|
public class StringTextSource : ITextSource |
||||||
|
{ |
||||||
|
readonly string text; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new StringTextSource with the given text.
|
||||||
|
/// </summary>
|
||||||
|
public StringTextSource(string text) |
||||||
|
{ |
||||||
|
if (text == null) |
||||||
|
throw new ArgumentNullException("text"); |
||||||
|
this.text = text; |
||||||
|
} |
||||||
|
|
||||||
|
ITextSourceVersion ITextSource.Version { |
||||||
|
get { return null; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public int TextLength { |
||||||
|
get { return text.Length; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string Text { |
||||||
|
get { return text; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public ITextSource CreateSnapshot() |
||||||
|
{ |
||||||
|
return this; // StringTextBuffer is immutable
|
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public ITextSource CreateSnapshot(int offset, int length) |
||||||
|
{ |
||||||
|
return new StringTextSource(text.Substring(offset, length)); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public TextReader CreateReader() |
||||||
|
{ |
||||||
|
return new StringReader(text); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public TextReader CreateReader(int offset, int length) |
||||||
|
{ |
||||||
|
return new StringReader(text.Substring(offset, length)); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public char GetCharAt(int offset) |
||||||
|
{ |
||||||
|
return text[offset]; |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string GetText(int offset, int length) |
||||||
|
{ |
||||||
|
return text.Substring(offset, length); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string GetText(ISegment segment) |
||||||
|
{ |
||||||
|
if (segment == null) |
||||||
|
throw new ArgumentNullException("segment"); |
||||||
|
return text.Substring(segment.Offset, segment.Length); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public int IndexOfAny(char[] anyOf, int startIndex, int count) |
||||||
|
{ |
||||||
|
return text.IndexOfAny(anyOf, startIndex, count); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,64 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
|
||||||
|
namespace ICSharpCode.Editor |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Describes a change of the document text.
|
||||||
|
/// This class is thread-safe.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable] |
||||||
|
public class TextChangeEventArgs : EventArgs |
||||||
|
{ |
||||||
|
readonly int offset; |
||||||
|
readonly string removedText; |
||||||
|
readonly string insertedText; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The offset at which the change occurs.
|
||||||
|
/// </summary>
|
||||||
|
public int Offset { |
||||||
|
get { return offset; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The text that was inserted.
|
||||||
|
/// </summary>
|
||||||
|
public string RemovedText { |
||||||
|
get { return removedText; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The number of characters removed.
|
||||||
|
/// </summary>
|
||||||
|
public int RemovalLength { |
||||||
|
get { return removedText.Length; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The text that was inserted.
|
||||||
|
/// </summary>
|
||||||
|
public string InsertedText { |
||||||
|
get { return insertedText; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The number of characters inserted.
|
||||||
|
/// </summary>
|
||||||
|
public int InsertionLength { |
||||||
|
get { return insertedText.Length; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new TextChangeEventArgs object.
|
||||||
|
/// </summary>
|
||||||
|
public TextChangeEventArgs(int offset, string removedText, string insertedText) |
||||||
|
{ |
||||||
|
this.offset = offset; |
||||||
|
this.removedText = removedText ?? string.Empty; |
||||||
|
this.insertedText = insertedText ?? string.Empty; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,173 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Globalization; |
||||||
|
|
||||||
|
namespace ICSharpCode.Editor |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// A line/column position.
|
||||||
|
/// Text editor lines/columns are counted started from one.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The document provides the methods <see cref="IDocument.GetLocation"/> and
|
||||||
|
/// <see cref="IDocument.GetOffset(TextLocation)"/> to convert between offsets and TextLocations.
|
||||||
|
/// </remarks>
|
||||||
|
[Serializable] |
||||||
|
public struct TextLocation : IComparable<TextLocation>, IEquatable<TextLocation> |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Represents no text location (0, 0).
|
||||||
|
/// </summary>
|
||||||
|
public static readonly TextLocation Empty = new TextLocation(0, 0); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constant of the minimum line.
|
||||||
|
/// </summary>
|
||||||
|
public const int MinLine = 1; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constant of the minimum column.
|
||||||
|
/// </summary>
|
||||||
|
public const int MinColumn = 1; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a TextLocation instance.
|
||||||
|
/// </summary>
|
||||||
|
public TextLocation(int line, int column) |
||||||
|
{ |
||||||
|
this.line = line; |
||||||
|
this.column = column; |
||||||
|
} |
||||||
|
|
||||||
|
int column, line; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the line number.
|
||||||
|
/// </summary>
|
||||||
|
public int Line { |
||||||
|
get { return line; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the column number.
|
||||||
|
/// </summary>
|
||||||
|
public int Column { |
||||||
|
get { return column; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the TextLocation instance is empty.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsEmpty { |
||||||
|
get { |
||||||
|
return column < MinLine && line < MinColumn; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a string representation for debugging purposes.
|
||||||
|
/// </summary>
|
||||||
|
public override string ToString() |
||||||
|
{ |
||||||
|
return string.Format(CultureInfo.InvariantCulture, "(Line {1}, Col {0})", this.column, this.line); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a hash code.
|
||||||
|
/// </summary>
|
||||||
|
public override int GetHashCode() |
||||||
|
{ |
||||||
|
return unchecked (191 * column.GetHashCode() ^ line.GetHashCode()); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Equality test.
|
||||||
|
/// </summary>
|
||||||
|
public override bool Equals(object obj) |
||||||
|
{ |
||||||
|
if (!(obj is TextLocation)) return false; |
||||||
|
return (TextLocation)obj == this; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Equality test.
|
||||||
|
/// </summary>
|
||||||
|
public bool Equals(TextLocation other) |
||||||
|
{ |
||||||
|
return this == other; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Equality test.
|
||||||
|
/// </summary>
|
||||||
|
public static bool operator ==(TextLocation left, TextLocation right) |
||||||
|
{ |
||||||
|
return left.column == right.column && left.line == right.line; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inequality test.
|
||||||
|
/// </summary>
|
||||||
|
public static bool operator !=(TextLocation left, TextLocation right) |
||||||
|
{ |
||||||
|
return left.column != right.column || left.line != right.line; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares two text locations.
|
||||||
|
/// </summary>
|
||||||
|
public static bool operator <(TextLocation left, TextLocation right) |
||||||
|
{ |
||||||
|
if (left.line < right.line) |
||||||
|
return true; |
||||||
|
else if (left.line == right.line) |
||||||
|
return left.column < right.column; |
||||||
|
else |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares two text locations.
|
||||||
|
/// </summary>
|
||||||
|
public static bool operator >(TextLocation left, TextLocation right) |
||||||
|
{ |
||||||
|
if (left.line > right.line) |
||||||
|
return true; |
||||||
|
else if (left.line == right.line) |
||||||
|
return left.column > right.column; |
||||||
|
else |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares two text locations.
|
||||||
|
/// </summary>
|
||||||
|
public static bool operator <=(TextLocation left, TextLocation right) |
||||||
|
{ |
||||||
|
return !(left > right); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares two text locations.
|
||||||
|
/// </summary>
|
||||||
|
public static bool operator >=(TextLocation left, TextLocation right) |
||||||
|
{ |
||||||
|
return !(left < right); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares two text locations.
|
||||||
|
/// </summary>
|
||||||
|
public int CompareTo(TextLocation other) |
||||||
|
{ |
||||||
|
if (this == other) |
||||||
|
return 0; |
||||||
|
if (this < other) |
||||||
|
return -1; |
||||||
|
else |
||||||
|
return 1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue