using System.Collections.Generic; using System; using System.Text; using System.Drawing; namespace FastColoredTextBoxNS { /// /// Line of text /// public class Line : IList { protected List chars; public string FoldingStartMarker { get; set; } public string FoldingEndMarker { get; set; } /// /// Text of line was changed /// public bool IsChanged { get; set; } /// /// Time of last visit of caret in this line /// /// This property can be used for forward/backward navigating public DateTime LastVisit { get; set; } /// /// Background brush. /// public Brush BackgroundBrush { get; set;} /// /// Unique ID /// public int UniqueId { get; private set; } /// /// Count of needed start spaces for AutoIndent /// public int AutoIndentSpacesNeededCount { get; set; } internal Line(int uid) { this.UniqueId = uid; chars = new List(); } /// /// Clears style of chars, delete folding markers /// public void ClearStyle(StyleIndex styleIndex) { FoldingStartMarker = null; FoldingEndMarker = null; for (int i = 0; i < Count; i++) { Char c = this[i]; c.style &= ~styleIndex; this[i] = c; } } /// /// Text of the line /// public virtual string Text { get{ StringBuilder sb = new StringBuilder(Count); foreach(Char c in this) sb.Append(c.c); return sb.ToString(); } } /// /// Clears folding markers /// public void ClearFoldingMarkers() { FoldingStartMarker = null; FoldingEndMarker = null; } /// /// Count of start spaces /// public int StartSpacesCount { get { int spacesCount = 0; for (int i = 0; i < Count; i++) if (this[i].c == ' ') spacesCount++; else break; return spacesCount; } } public int IndexOf(Char item) { return chars.IndexOf(item); } public void Insert(int index, Char item) { chars.Insert(index, item); } public void RemoveAt(int index) { chars.RemoveAt(index); } public Char this[int index] { get { return chars[index]; } set { chars[index] = value; } } public void Add(Char item) { chars.Add(item); } public void Clear() { chars.Clear(); } public bool Contains(Char item) { return chars.Contains(item); } public void CopyTo(Char[] array, int arrayIndex) { chars.CopyTo(array, arrayIndex); } /// /// Chars count /// public int Count { get { return chars.Count; } } public bool IsReadOnly { get { return false; } } public bool Remove(Char item) { return chars.Remove(item); } public IEnumerator GetEnumerator() { return chars.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return chars.GetEnumerator() as System.Collections.IEnumerator; } public virtual void RemoveRange(int index, int count) { if (index >= Count) return; chars.RemoveRange(index, Math.Min(Count - index, count)); } public virtual void TrimExcess() { chars.TrimExcess(); } public virtual void AddRange(IEnumerable collection) { chars.AddRange(collection); } } public struct LineInfo { List cutOffPositions; //Y coordinate of line on screen internal int startY; internal int bottomPadding; //indent of secondary wordwrap strings (in chars) internal int wordWrapIndent; /// /// Visible state /// public VisibleState VisibleState; public LineInfo(int startY) { cutOffPositions = null; VisibleState = VisibleState.Visible; this.startY = startY; bottomPadding = 0; wordWrapIndent = 0; } /// /// Positions for wordwrap cutoffs /// public List CutOffPositions { get { if (cutOffPositions == null) cutOffPositions = new List(); return cutOffPositions; } } /// /// Count of wordwrap string count for this line /// public int WordWrapStringsCount { get { switch (VisibleState) { case VisibleState.Visible: if (cutOffPositions == null) return 1; else return cutOffPositions.Count + 1; case VisibleState.Hidden: return 0; case VisibleState.StartOfHiddenBlock: return 1; } return 0; } } internal int GetWordWrapStringStartPosition(int iWordWrapLine) { return iWordWrapLine == 0 ? 0 : CutOffPositions[iWordWrapLine - 1]; } internal int GetWordWrapStringFinishPosition(int iWordWrapLine, Line line) { if (WordWrapStringsCount <= 0) return 0; return iWordWrapLine == WordWrapStringsCount - 1 ? line.Count - 1 : CutOffPositions[iWordWrapLine] - 1; } /// /// Gets index of wordwrap string for given char position /// public int GetWordWrapStringIndex(int iChar) { if (cutOffPositions == null || cutOffPositions.Count == 0) return 0; for (int i = 0; i < cutOffPositions.Count; i++) if (cutOffPositions[i] >/*>=*/ iChar) return i; return cutOffPositions.Count; } } public enum VisibleState: byte { Visible, StartOfHiddenBlock, Hidden } public enum IndentMarker { None, Increased, Decreased } }