namespace Terminal.Gui; /// /// Represents a single row/column in a Terminal.Gui rendering surface (e.g. and /// ). /// public record struct Cell (Attribute? Attribute = null, bool IsDirty = false, Rune Rune = default) { /// The attributes to use when drawing the Glyph. public Attribute? Attribute { get; set; } = Attribute; /// /// Gets or sets a value indicating whether this has been modified since the /// last time it was drawn. /// public bool IsDirty { get; set; } = IsDirty; private Rune _rune = Rune; /// The character to display. If is , then is ignored. public Rune Rune { get => _rune; set { CombiningMarks.Clear (); _rune = value; } } private List _combiningMarks; /// /// The combining marks for that when combined makes this Cell a combining sequence. If /// empty, then is ignored. /// /// /// Only valid in the rare case where is a combining sequence that could not be normalized to a /// single Rune. /// internal List CombiningMarks { get => _combiningMarks ?? []; private set => _combiningMarks = value ?? []; } /// public override string ToString () { return $"[{Rune}, {Attribute}]"; } /// Converts the string into a . /// The string to convert. /// The to use. /// public static List ToCellList (string str, Attribute? attribute = null) { List cells = new (); foreach (Rune rune in str.EnumerateRunes ()) { cells.Add (new () { Rune = rune, Attribute = attribute }); } return cells; } /// /// Splits a string into a List that will contain a for each line. /// /// The string content. /// The color scheme. /// A for each line. public static List> StringToLinesOfCells (string content, Attribute? attribute = null) { List cells = content.EnumerateRunes () .Select (x => new Cell { Rune = x, Attribute = attribute }) .ToList (); return SplitNewLines (cells); } /// Converts a generic collection into a string. /// The enumerable cell to convert. /// public static string ToString (IEnumerable cells) { var str = string.Empty; foreach (Cell cell in cells) { str += cell.Rune.ToString (); } return str; } /// Converts a generic collection into a string. /// The enumerable cell to convert. /// public static string ToString (List> cellsList) { var str = string.Empty; for (var i = 0; i < cellsList.Count; i++) { IEnumerable cellList = cellsList [i]; str += ToString (cellList); if (i + 1 < cellsList.Count) { str += Environment.NewLine; } } return str; } // Turns the string into cells, this does not split the contents on a newline if it is present. internal static List StringToCells (string str, Attribute? attribute = null) { List cells = []; foreach (Rune rune in str.ToRunes ()) { cells.Add (new () { Rune = rune, Attribute = attribute }); } return cells; } internal static List ToCells (IEnumerable runes, Attribute? attribute = null) { List cells = new (); foreach (Rune rune in runes) { cells.Add (new () { Rune = rune, Attribute = attribute }); } return cells; } private static List> SplitNewLines (List cells) { List> lines = []; int start = 0, i = 0; var hasCR = false; // ASCII code 13 = Carriage Return. // ASCII code 10 = Line Feed. for (; i < cells.Count; i++) { if (cells [i].Rune.Value == 13) { hasCR = true; continue; } if (cells [i].Rune.Value == 10) { if (i - start > 0) { lines.Add (cells.GetRange (start, hasCR ? i - 1 - start : i - start)); } else { lines.Add (StringToCells (string.Empty)); } start = i + 1; hasCR = false; } } if (i - start >= 0) { lines.Add (cells.GetRange (start, i - start)); } return lines; } /// /// Splits a rune cell list into a List that will contain a for each line. /// /// The cells list. /// public static List> ToCells (List cells) { return SplitNewLines (cells); } }