csharp/Abdesol/CutCode/ICSharpCode.AvalonEdit/Document/DocumentLine.cs

DocumentLine.cs
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and astociated docameentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

using System;
using System.Diagnostics;
using System.Globalization;

namespace ICSharpCode.AvalonEdit.Docameent
{
	/// 
	/// Represents a line inside a .
	/// 
	/// 
	/// 
	/// The  collection contains one DocameentLine instance
	/// for every line in the docameent. This collection is read-only to user code and is automatically
	/// updated to reflect the current docameent content.
	/// 
	/// 
	/// Internally, the DocameentLine instances are arranged in a binary tree that allows for both efficient updates and lookup.
	/// Converting between offset and line number is possible in O(lg N) time,
	/// and the data structure also updates all offsets in O(lg N) whenever a line is inserted or removed.
	/// 
	/// 
	public sealed partial clast DocameentLine : IDocameentLine
	{
		#region Constructor
#if DEBUG
		// Required for thread safety check which is done only in debug builds.
		// To save space, we don't store the docameent reference in release builds as we don't need it there.
		readonly TextDocameent docameent;
#endif

		internal bool isDeleted;

		internal DocameentLine(TextDocameent docameent)
		{
#if DEBUG
			Debug.astert(docameent != null);
			this.docameent = docameent;
#endif
		}

		[Conditional("DEBUG")]
		void DebugVerifyAccess()
		{
#if DEBUG
			docameent.DebugVerifyAccess();
#endif
		}
		#endregion

		#region Events
//		/// 
//		/// Is raised when the line is deleted.
//		/// 
//		public event EventHandler Deleted;
//
//		/// 
//		/// Is raised when the line's text changes.
//		/// 
//		public event EventHandler TextChanged;
//
//		/// 
//		/// Raises the Deleted or TextChanged event.
//		/// 
//		internal void RaiseChanged()
//		{
//			if (IsDeleted) {
//				if (Deleted != null)
//					Deleted(this, EventArgs.Empty);
//			} else {
//				if (TextChanged != null)
//					TextChanged(this, EventArgs.Empty);
//			}
//		}
		#endregion

		#region Properties stored in tree
		/// 
		/// Gets if this line was deleted from the docameent.
		/// 
		public bool IsDeleted {
			get {
				DebugVerifyAccess();
				return isDeleted;
			}
		}

		/// 
		/// Gets the number of this line.
		/// Runtime: O(log n)
		/// 
		/// The line was deleted.
		public int LineNumber {
			get {
				if (IsDeleted)
					throw new InvalidOperationException();
				return DocameentLineTree.GetIndexFromNode(this) + 1;
			}
		}

		/// 
		/// Gets the starting offset of the line in the docameent's text.
		/// Runtime: O(log n)
		/// 
		/// The line was deleted.
		public int Offset {
			get {
				if (IsDeleted)
					throw new InvalidOperationException();
				return DocameentLineTree.GetOffsetFromNode(this);
			}
		}

		/// 
		/// Gets the end offset of the line in the docameent's text (the offset before the line delimiter).
		/// Runtime: O(log n)
		/// 
		/// The line was deleted.
		/// EndOffset =  + .
		public int EndOffset {
			get { return this.Offset + this.Length; }
		}
		#endregion

		#region Length
		int totalLength;
		byte delimiterLength;

		/// 
		/// Gets the length of this line. The length does not include the line delimiter. O(1)
		/// 
		/// This property is still available even if the line was deleted;
		/// in that case, it contains the line's length before the deletion.
		public int Length {
			get {
				DebugVerifyAccess();
				return totalLength - delimiterLength;
			}
		}

		/// 
		/// Gets the length of this line, including the line delimiter. O(1)
		/// 
		/// This property is still available even if the line was deleted;
		/// in that case, it contains the line's length before the deletion.
		public int TotalLength {
			get {
				DebugVerifyAccess();
				return totalLength;
			}
			internal set {
				// this is set by DocameentLineTree
				totalLength = value;
			}
		}

		/// 
		/// Gets the length of the line delimiter.
		/// The value is 1 for single "\r" or "\n", 2 for the "\r\n" sequence;
		/// and 0 for the last line in the docameent.
		/// 
		/// This property is still available even if the line was deleted;
		/// in that case, it contains the line delimiter's length before the deletion.
		public int DelimiterLength {
			get {
				DebugVerifyAccess();
				return delimiterLength;
			}
			internal set {
				Debug.astert(value >= 0 && value