1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069 |
- //
- // ConsoleDriver.cs: Base class for Terminal.Gui ConsoleDriver implementations.
- //
- using System.Text;
- using System;
- using System.Diagnostics;
- using System.Linq;
- namespace Terminal.Gui;
- /// <summary>
- /// Base class for Terminal.Gui ConsoleDriver implementations.
- /// </summary>
- /// <remarks>
- /// There are currently four implementations:
- /// - <see cref="CursesDriver"/> (for Unix and Mac)
- /// - <see cref="WindowsDriver"/>
- /// - <see cref="NetDriver"/> that uses the .NET Console API
- /// - <see cref="FakeConsole"/> for unit testing.
- /// </remarks>
- public abstract class ConsoleDriver {
- /// <summary>
- /// Set this to true in any unit tests that attempt to test drivers other than FakeDriver.
- /// <code>
- /// public ColorTests ()
- /// {
- /// ConsoleDriver.RunningUnitTests = true;
- /// }
- /// </code>
- /// </summary>
- internal static bool RunningUnitTests { get; set; }
- #region Setup & Teardown
- /// <summary>
- /// Initializes the driver
- /// </summary>
- /// <returns>Returns an instance of <see cref="MainLoop"/> using the <see cref="IMainLoopDriver"/> for the driver.</returns>
- internal abstract MainLoop Init ();
- /// <summary>
- /// Ends the execution of the console driver.
- /// </summary>
- internal abstract void End ();
- #endregion
- /// <summary>
- /// The event fired when the terminal is resized.
- /// </summary>
- public event EventHandler<SizeChangedEventArgs> SizeChanged;
- /// <summary>
- /// Called when the terminal size changes. Fires the <see cref="SizeChanged"/> event.
- /// </summary>
- /// <param name="args"></param>
- public void OnSizeChanged (SizeChangedEventArgs args) => SizeChanged?.Invoke (this, args);
- /// <summary>
- /// The number of columns visible in the terminal.
- /// </summary>
- public virtual int Cols { get; internal set; }
- /// <summary>
- /// The number of rows visible in the terminal.
- /// </summary>
- public virtual int Rows { get; internal set; }
- /// <summary>
- /// The leftmost column in the terminal.
- /// </summary>
- public virtual int Left { get; internal set; } = 0;
- /// <summary>
- /// The topmost row in the terminal.
- /// </summary>
- public virtual int Top { get; internal set; } = 0;
- /// <summary>
- /// Get the operating system clipboard.
- /// </summary>
- public IClipboard Clipboard { get; internal set; }
- /// <summary>
- /// The contents of the application output. The driver outputs this buffer to the terminal when <see cref="UpdateScreen"/>
- /// is called.
- /// <remarks>
- /// The format of the array is rows, columns. The first index is the row, the second index is the column.
- /// </remarks>
- /// </summary>
- public Cell [,] Contents { get; internal set; }
- /// <summary>
- /// Gets the column last set by <see cref="Move"/>. <see cref="Col"/> and <see cref="Row"/>
- /// are used by <see cref="AddRune(Rune)"/> and <see cref="AddStr"/> to determine where to add content.
- /// </summary>
- public int Col { get; internal set; }
- /// <summary>
- /// Gets the row last set by <see cref="Move"/>. <see cref="Col"/> and <see cref="Row"/>
- /// are used by <see cref="AddRune(Rune)"/> and <see cref="AddStr"/> to determine where to add content.
- /// </summary>
- public int Row { get; internal set; }
- /// <summary>
- /// Updates <see cref="Col"/> and <see cref="Row"/> to the specified column and row in <see cref="Contents"/>.
- /// Used by <see cref="AddRune(Rune)"/> and <see cref="AddStr"/> to determine where to add content.
- /// </summary>
- /// <remarks>
- /// <para>
- /// This does not move the cursor on the screen, it only updates the internal state of the driver.
- /// </para>
- /// <para>
- /// If <paramref name="col"/> or <paramref name="row"/> are negative or beyond <see cref="Cols"/> and <see cref="Rows"/>,
- /// the method still sets those properties.
- /// </para>
- /// </remarks>
- /// <param name="col">Column to move to.</param>
- /// <param name="row">Row to move to.</param>
- public virtual void Move (int col, int row)
- {
- Col = col;
- Row = row;
- }
- /// <summary>
- /// Tests if the specified rune is supported by the driver.
- /// </summary>
- /// <param name="rune"></param>
- /// <returns><see langword="true"/> if the rune can be properly presented; <see langword="false"/> if the driver
- /// does not support displaying this rune.</returns>
- public virtual bool IsRuneSupported (Rune rune)
- {
- return Rune.IsValid (rune.Value);
- }
- /// <summary>
- /// Adds the specified rune to the display at the current cursor position.
- /// </summary>
- /// <remarks>
- /// <para>
- /// When the method returns, <see cref="Col"/> will be incremented by the number of columns <paramref name="rune"/> required,
- /// even if the new column value is outside of the <see cref="Clip"/> or screen dimensions defined by <see cref="Cols"/>.
- /// </para>
- /// <para>
- /// If <paramref name="rune"/> requires more than one column, and <see cref="Col"/> plus the number of columns needed
- /// exceeds the <see cref="Clip"/> or screen dimensions, the default Unicode replacement character (U+FFFD) will be added instead.
- /// </para>
- /// </remarks>
- /// <param name="rune">Rune to add.</param>
- public void AddRune (Rune rune)
- {
- int runeWidth = -1;
- var validLocation = IsValidLocation (Col, Row);
- if (validLocation) {
- rune = rune.MakePrintable ();
- runeWidth = rune.GetColumns ();
- if (runeWidth == 0 && rune.IsCombiningMark ()) {
- if (Col > 0) {
- if (Contents [Row, Col - 1].CombiningMarks.Count > 0) {
- // Just add this mark to the list
- Contents [Row, Col - 1].CombiningMarks.Add (rune);
- // Don't move to next column (let the driver figure out what to do).
- } else {
- // Attempt to normalize the cell to our left combined with this mark
- string combined = Contents [Row, Col - 1].Rune + rune.ToString ();
- // Normalize to Form C (Canonical Composition)
- string normalized = combined.Normalize (NormalizationForm.FormC);
- if (normalized.Length == 1) {
- // It normalized! We can just set the Cell to the left with the
- // normalized codepoint
- Contents [Row, Col - 1].Rune = (Rune)normalized [0];
- // Don't move to next column because we're already there
- } else {
- // It didn't normalize. Add it to the Cell to left's CM list
- Contents [Row, Col - 1].CombiningMarks.Add (rune);
- // Don't move to next column (let the driver figure out what to do).
- }
- }
- Contents [Row, Col - 1].Attribute = CurrentAttribute;
- Contents [Row, Col - 1].IsDirty = true;
- } else {
- // Most drivers will render a combining mark at col 0 as the mark
- Contents [Row, Col].Rune = rune;
- Contents [Row, Col].Attribute = CurrentAttribute;
- Contents [Row, Col].IsDirty = true;
- Col++;
- }
- } else {
- Contents [Row, Col].Attribute = CurrentAttribute;
- Contents [Row, Col].IsDirty = true;
- if (Col > 0) {
- // Check if cell to left has a wide glyph
- if (Contents [Row, Col - 1].Rune.GetColumns () > 1) {
- // Invalidate cell to left
- Contents [Row, Col - 1].Rune = Rune.ReplacementChar;
- Contents [Row, Col - 1].IsDirty = true;
- }
- }
- if (runeWidth < 1) {
- Contents [Row, Col].Rune = Rune.ReplacementChar;
- } else if (runeWidth == 1) {
- Contents [Row, Col].Rune = rune;
- if (Col < Clip.Right - 1) {
- Contents [Row, Col + 1].IsDirty = true;
- }
- } else if (runeWidth == 2) {
- if (Col == Clip.Right - 1) {
- // We're at the right edge of the clip, so we can't display a wide character.
- // TODO: Figure out if it is better to show a replacement character or ' '
- Contents [Row, Col].Rune = Rune.ReplacementChar;
- } else {
- Contents [Row, Col].Rune = rune;
- if (Col < Clip.Right - 1) {
- // Invalidate cell to right so that it doesn't get drawn
- // TODO: Figure out if it is better to show a replacement character or ' '
- Contents [Row, Col + 1].Rune = Rune.ReplacementChar;
- Contents [Row, Col + 1].IsDirty = true;
- }
- }
- } else {
- // This is a non-spacing character, so we don't need to do anything
- Contents [Row, Col].Rune = (Rune)' ';
- Contents [Row, Col].IsDirty = false;
- }
- _dirtyLines [Row] = true;
- }
- }
- if (runeWidth is < 0 or > 0) {
- Col++;
- }
- if (runeWidth > 1) {
- Debug.Assert (runeWidth <= 2);
- if (validLocation && Col < Clip.Right) {
- // This is a double-width character, and we are not at the end of the line.
- // Col now points to the second column of the character. Ensure it doesn't
- // Get rendered.
- Contents [Row, Col].IsDirty = false;
- Contents [Row, Col].Attribute = CurrentAttribute;
- // TODO: Determine if we should wipe this out (for now now)
- //Contents [Row, Col].Rune = (Rune)' ';
- }
- Col++;
- }
- }
- /// <summary>
- /// Adds the specified <see langword="char"/> to the display at the current cursor position. This method
- /// is a convenience method that calls <see cref="AddRune(Rune)"/> with the <see cref="Rune"/> constructor.
- /// </summary>
- /// <param name="c">Character to add.</param>
- public void AddRune (char c) => AddRune (new Rune (c));
- /// <summary>
- /// Adds the <paramref name="str"/> to the display at the cursor position.
- /// </summary>
- /// <remarks>
- /// <para>
- /// When the method returns, <see cref="Col"/> will be incremented by the number of columns <paramref name="str"/> required,
- /// unless the new column value is outside of the <see cref="Clip"/> or screen dimensions defined by <see cref="Cols"/>.
- /// </para>
- /// <para>
- /// If <paramref name="str"/> requires more columns than are available, the output will be clipped.
- /// </para>
- /// </remarks>
- /// <param name="str">String.</param>
- public void AddStr (string str)
- {
- var runes = str.EnumerateRunes ().ToList ();
- for (var i = 0; i < runes.Count; i++) {
- //if (runes [i].IsCombiningMark()) {
- // // Attempt to normalize
- // string combined = runes [i-1] + runes [i].ToString();
- // // Normalize to Form C (Canonical Composition)
- // string normalized = combined.Normalize (NormalizationForm.FormC);
- // runes [i-]
- //}
- AddRune (runes [i]);
- }
- }
- Rect _clip;
- /// <summary>
- /// Tests whether the specified coordinate are valid for drawing.
- /// </summary>
- /// <param name="col">The column.</param>
- /// <param name="row">The row.</param>
- /// <returns><see langword="false"/> if the coordinate is outside of the
- /// screen bounds or outside of <see cref="Clip"/>. <see langword="true"/> otherwise.</returns>
- public bool IsValidLocation (int col, int row) =>
- col >= 0 && row >= 0 &&
- col < Cols && row < Rows &&
- Clip.Contains (col, row);
- /// <summary>
- /// Gets or sets the clip rectangle that <see cref="AddRune(Rune)"/> and <see cref="AddStr(string)"/> are
- /// subject to.
- /// </summary>
- /// <value>The rectangle describing the bounds of <see cref="Clip"/>.</value>
- public Rect Clip {
- get => _clip;
- set => _clip = value;
- }
- /// <summary>
- /// Updates the screen to reflect all the changes that have been done to the display buffer
- /// </summary>
- public abstract void Refresh ();
- /// <summary>
- /// Sets the position of the terminal cursor to <see cref="Col"/> and <see cref="Row"/>.
- /// </summary>
- public abstract void UpdateCursor ();
- /// <summary>
- /// Gets the terminal cursor visibility.
- /// </summary>
- /// <param name="visibility">The current <see cref="CursorVisibility"/></param>
- /// <returns><see langword="true"/> upon success</returns>
- public abstract bool GetCursorVisibility (out CursorVisibility visibility);
- /// <summary>
- /// Sets the terminal cursor visibility.
- /// </summary>
- /// <param name="visibility">The wished <see cref="CursorVisibility"/></param>
- /// <returns><see langword="true"/> upon success</returns>
- public abstract bool SetCursorVisibility (CursorVisibility visibility);
- /// <summary>
- /// Determines if the terminal cursor should be visible or not and sets it accordingly.
- /// </summary>
- /// <returns><see langword="true"/> upon success</returns>
- public abstract bool EnsureCursorVisibility ();
- // As performance is a concern, we keep track of the dirty lines and only refresh those.
- // This is in addition to the dirty flag on each cell.
- internal bool [] _dirtyLines;
- /// <summary>
- /// Clears the <see cref="Contents"/> of the driver.
- /// </summary>
- public void ClearContents ()
- {
- // TODO: This method is really "Clear Contents" now and should not be abstract (or virtual)
- Contents = new Cell [Rows, Cols];
- Clip = new Rect (0, 0, Cols, Rows);
- _dirtyLines = new bool [Rows];
- lock (Contents) {
- // Can raise an exception while is still resizing.
- try {
- for (var row = 0; row < Rows; row++) {
- for (var c = 0; c < Cols; c++) {
- Contents [row, c] = new Cell () {
- Rune = (Rune)' ',
- Attribute = new Attribute (Color.White, Color.Black),
- IsDirty = true
- };
- _dirtyLines [row] = true;
- }
- }
- } catch (IndexOutOfRangeException) { }
- }
- }
- /// <summary>
- /// Redraws the physical screen with the contents that have been queued up via any of the printing commands.
- /// </summary>
- public abstract void UpdateScreen ();
- #region Color Handling
- /// <summary>
- /// Gets whether the <see cref="ConsoleDriver"/> supports TrueColor output.
- /// </summary>
- public virtual bool SupportsTrueColor { get => true; }
- /// <summary>
- /// Gets or sets whether the <see cref="ConsoleDriver"/> should use 16 colors instead of the default TrueColors. See <see cref="Application.Force16Colors"/>
- /// to change this setting via <see cref="ConfigurationManager"/>.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Will be forced to <see langword="true"/> if <see cref="ConsoleDriver.SupportsTrueColor"/> is <see langword="false"/>, indicating
- /// that the <see cref="ConsoleDriver"/> cannot support TrueColor.
- /// </para>
- /// </remarks>
- internal virtual bool Force16Colors {
- get => Application.Force16Colors || !SupportsTrueColor;
- set => Application.Force16Colors = (value || !SupportsTrueColor);
- }
- Attribute _currentAttribute;
- /// <summary>
- /// The <see cref="Attribute"/> that will be used for the next <see cref="AddRune(Rune)"/> or <see cref="AddStr"/> call.
- /// </summary>
- public Attribute CurrentAttribute {
- get => _currentAttribute;
- set {
- if (Application.Driver != null) {
- _currentAttribute = new Attribute (value.Foreground, value.Background);
- return;
- }
- _currentAttribute = value;
- }
- }
- /// <summary>
- /// Selects the specified attribute as the attribute to use for future calls to AddRune and AddString.
- /// </summary>
- /// <remarks>
- /// Implementations should call <c>base.SetAttribute(c)</c>.
- /// </remarks>
- /// <param name="c">C.</param>
- public Attribute SetAttribute (Attribute c)
- {
- var prevAttribute = CurrentAttribute;
- CurrentAttribute = c;
- return prevAttribute;
- }
- /// <summary>
- /// Gets the current <see cref="Attribute"/>.
- /// </summary>
- /// <returns>The current attribute.</returns>
- public Attribute GetAttribute () => CurrentAttribute;
- // TODO: This is only overridden by CursesDriver. Once CursesDriver supports 24-bit color, this virtual method can be
- // removed (and Attribute can lose the platformColor property).
- /// <summary>
- /// Makes an <see cref="Attribute"/>.
- /// </summary>
- /// <param name="foreground">The foreground color.</param>
- /// <param name="background">The background color.</param>
- /// <returns>The attribute for the foreground and background colors.</returns>
- public virtual Attribute MakeColor (Color foreground, Color background)
- {
- // Encode the colors into the int value.
- return new Attribute (
- platformColor: 0, // only used by cursesdriver!
- foreground: foreground,
- background: background
- );
- }
- #endregion
- #region Mouse and Keyboard
- /// <summary>
- /// Event fired when a key is pressed down. This is a precursor to <see cref="KeyUp"/>.
- /// </summary>
- public event EventHandler<Key> KeyDown;
- /// <summary>
- /// Called when a key is pressed down. Fires the <see cref="KeyDown"/> event. This is a precursor to <see cref="OnKeyUp"/>.
- /// </summary>
- /// <param name="a"></param>
- public void OnKeyDown (Key a) => KeyDown?.Invoke (this, a);
- /// <summary>
- /// Event fired when a key is released.
- /// </summary>
- /// <remarks>
- /// Drivers that do not support key release events will fire this event after <see cref="KeyDown"/> processing is complete.
- /// </remarks>
- public event EventHandler<Key> KeyUp;
- /// <summary>
- /// Called when a key is released. Fires the <see cref="KeyUp"/> event.
- /// </summary>
- /// <remarks>
- /// Drivers that do not support key release events will calls this method after <see cref="OnKeyDown"/> processing is complete.
- /// </remarks>
- /// <param name="a"></param>
- public void OnKeyUp (Key a) => KeyUp?.Invoke (this, a);
- /// <summary>
- /// Event fired when a mouse event occurs.
- /// </summary>
- public event EventHandler<MouseEventEventArgs> MouseEvent;
- /// <summary>
- /// Called when a mouse event occurs. Fires the <see cref="MouseEvent"/> event.
- /// </summary>
- /// <param name="a"></param>
- public void OnMouseEvent (MouseEventEventArgs a) => MouseEvent?.Invoke (this, a);
- /// <summary>
- /// Simulates a key press.
- /// </summary>
- /// <param name="keyChar">The key character.</param>
- /// <param name="key">The key.</param>
- /// <param name="shift">If <see langword="true"/> simulates the Shift key being pressed.</param>
- /// <param name="alt">If <see langword="true"/> simulates the Alt key being pressed.</param>
- /// <param name="ctrl">If <see langword="true"/> simulates the Ctrl key being pressed.</param>
- public abstract void SendKeys (char keyChar, ConsoleKey key, bool shift, bool alt, bool ctrl);
- #endregion
- /// <summary>
- /// Enables diagnostic functions
- /// </summary>
- [Flags]
- public enum DiagnosticFlags : uint {
- /// <summary>
- /// All diagnostics off
- /// </summary>
- Off = 0b_0000_0000,
- /// <summary>
- /// When enabled, <see cref="Frame.OnDrawFrames"/> will draw a
- /// ruler in the frame for any side with a padding value greater than 0.
- /// </summary>
- FrameRuler = 0b_0000_0001,
- /// <summary>
- /// When enabled, <see cref="Frame.OnDrawFrames"/> will draw a
- /// 'L', 'R', 'T', and 'B' when clearing <see cref="Thickness"/>'s instead of ' '.
- /// </summary>
- FramePadding = 0b_0000_0010,
- }
- /// <summary>
- /// Set flags to enable/disable <see cref="ConsoleDriver"/> diagnostics.
- /// </summary>
- public static DiagnosticFlags Diagnostics { get; set; }
- /// <summary>
- /// Suspends the application (e.g. on Linux via SIGTSTP) and upon resume, resets the console driver.
- /// </summary>
- /// <remarks>This is only implemented in <see cref="CursesDriver"/>.</remarks>
- public abstract void Suspend ();
- // TODO: Move FillRect to ./Drawing
- /// <summary>
- /// Fills the specified rectangle with the specified rune.
- /// </summary>
- /// <param name="rect"></param>
- /// <param name="rune"></param>
- public void FillRect (Rect rect, Rune rune = default)
- {
- for (var r = rect.Y; r < rect.Y + rect.Height; r++) {
- for (var c = rect.X; c < rect.X + rect.Width; c++) {
- Application.Driver.Move (c, r);
- Application.Driver.AddRune (rune == default ? new Rune (' ') : rune);
- }
- }
- }
- /// <summary>
- /// Fills the specified rectangle with the specified <see langword="char"/>. This method
- /// is a convenience method that calls <see cref="FillRect(Rect, Rune)"/>.
- /// </summary>
- /// <param name="rect"></param>
- /// <param name="c"></param>
- public void FillRect (Rect rect, char c) => FillRect (rect, new Rune (c));
- /// <summary>
- /// Returns the name of the driver and relevant library version information.
- /// </summary>
- /// <returns></returns>
- public virtual string GetVersionInfo () => GetType ().Name;
- }
- /// <summary>
- /// Terminal Cursor Visibility settings.
- /// </summary>
- /// <remarks>
- /// Hex value are set as 0xAABBCCDD where :
- ///
- /// AA stand for the TERMINFO DECSUSR parameter value to be used under Linux and MacOS
- /// BB stand for the NCurses curs_set parameter value to be used under Linux and MacOS
- /// CC stand for the CONSOLE_CURSOR_INFO.bVisible parameter value to be used under Windows
- /// DD stand for the CONSOLE_CURSOR_INFO.dwSize parameter value to be used under Windows
- ///</remarks>
- public enum CursorVisibility {
- /// <summary>
- /// Cursor caret has default
- /// </summary>
- /// <remarks>Works under Xterm-like terminal otherwise this is equivalent to <see ref="Underscore"/>. This default directly depends of the XTerm user configuration settings so it could be Block, I-Beam, Underline with possible blinking.</remarks>
- Default = 0x00010119,
- /// <summary>
- /// Cursor caret is hidden
- /// </summary>
- Invisible = 0x03000019,
- /// <summary>
- /// Cursor caret is normally shown as a blinking underline bar _
- /// </summary>
- Underline = 0x03010119,
- /// <summary>
- /// Cursor caret is normally shown as a underline bar _
- /// </summary>
- /// <remarks>Under Windows, this is equivalent to <see ref="UnderscoreBlinking"/></remarks>
- UnderlineFix = 0x04010119,
- /// <summary>
- /// Cursor caret is displayed a blinking vertical bar |
- /// </summary>
- /// <remarks>Works under Xterm-like terminal otherwise this is equivalent to <see ref="Underscore"/></remarks>
- Vertical = 0x05010119,
- /// <summary>
- /// Cursor caret is displayed a blinking vertical bar |
- /// </summary>
- /// <remarks>Works under Xterm-like terminal otherwise this is equivalent to <see ref="Underscore"/></remarks>
- VerticalFix = 0x06010119,
- /// <summary>
- /// Cursor caret is displayed as a blinking block ▉
- /// </summary>
- Box = 0x01020164,
- /// <summary>
- /// Cursor caret is displayed a block ▉
- /// </summary>
- /// <remarks>Works under Xterm-like terminal otherwise this is equivalent to <see ref="Block"/></remarks>
- BoxFix = 0x02020164,
- }
- /// <summary>
- /// The <see cref="KeyCode"/> enumeration encodes key information from <see cref="ConsoleDriver"/>s and provides a consistent
- /// way for application code to specify keys and receive key events.
- /// <para>
- /// The <see cref="Key"/> class provides a higher-level abstraction, with helper methods and properties for common
- /// operations. For example, <see cref="Key.IsAlt"/> and <see cref="Key.IsCtrl"/> provide a convenient way
- /// to check whether the Alt or Ctrl modifier keys were pressed when a key was pressed.
- /// </para>
- /// </summary>
- /// <remarks>
- /// <para>
- /// Lowercase alpha keys are encoded as values between 65 and 90 corresponding to the un-shifted A to Z keys on a keyboard. Enum values
- /// are provided for these (e.g. <see cref="KeyCode.A"/>, <see cref="KeyCode.B"/>, etc.). Even though the values are the same as the ASCII
- /// values for uppercase characters, these enum values represent *lowercase*, un-shifted characters.
- /// TODO: Strongly consider renaming these from .A to .Z to .A_Lowercase to .Z_Lowercase (or .a to .z).
- /// </para>
- /// <para>
- /// Numeric keys are the values between 48 and 57 corresponding to 0 to 9 (e.g. <see cref="KeyCode.D0"/>, <see cref="KeyCode.D1"/>, etc.).
- /// </para>
- /// <para>
- /// The shift modifiers (<see cref="KeyCode.ShiftMask"/>, <see cref="KeyCode.CtrlMask"/>, and <see cref="KeyCode.AltMask"/>) can be combined (with logical or)
- /// with the other key codes to represent shifted keys. For example, the <see cref="KeyCode.A"/> enum value represents the un-shifted 'a' key, while
- /// <see cref="KeyCode.ShiftMask"/> | <see cref="KeyCode.A"/> represents the 'A' key (shifted 'a' key). Likewise, <see cref="KeyCode.AltMask"/> | <see cref="KeyCode.A"/>
- /// represents the 'Alt+A' key combination.
- /// </para>
- /// <para>
- /// All other keys that produce a printable character are encoded as the Unicode value of the character. For example, the <see cref="KeyCode"/>
- /// for the '!' character is 33, which is the Unicode value for '!'. Likewise, `â` is 226, `Â` is 194, etc.
- /// </para>
- /// <para>
- /// If the <see cref="SpecialMask"/> is set, then the value is that of the special mask,
- /// otherwise, the value is the one of the lower bits (as extracted by <see cref="CharMask"/>).
- /// </para>
- /// </remarks>
- [Flags]
- public enum KeyCode : uint {
- /// <summary>
- /// Mask that indicates that this is a character value, values outside this range
- /// indicate special characters like Alt-key combinations or special keys on the
- /// keyboard like function keys, arrows keys and so on.
- /// </summary>
- CharMask = 0xfffff,
- /// <summary>
- /// If the <see cref="SpecialMask"/> is set, then the value is that of the special mask,
- /// otherwise, the value is the one of the lower bits (as extracted by <see cref="CharMask"/>).
- /// </summary>
- SpecialMask = 0xfff00000,
- /// <summary>
- /// The key code representing null or empty
- /// </summary>
- Null = '\0',
- /// <summary>
- /// Backspace key.
- /// </summary>
- Backspace = 8,
- /// <summary>
- /// The key code for the tab key (forwards tab key).
- /// </summary>
- Tab = 9,
- /// <summary>
- /// The key code for the return key.
- /// </summary>
- Enter = '\n',
- /// <summary>
- /// The key code for the clear key.
- /// </summary>
- Clear = 12,
- /// <summary>
- /// The key code for the Shift key.
- /// </summary>
- ShiftKey = 16,
- /// <summary>
- /// The key code for the Ctrl key.
- /// </summary>
- CtrlKey = 17,
- /// <summary>
- /// The key code for the Alt key.
- /// </summary>
- AltKey = 18,
- /// <summary>
- /// The key code for the CapsLock key.
- /// </summary>
- CapsLock = 20,
- ///// <summary>
- ///// The key code for the NumLock key.
- ///// </summary>
- //NumLock = 144,
- ///// <summary>
- ///// The key code for the ScrollLock key.
- ///// </summary>
- //ScrollLock = 145,
- /// <summary>
- /// The key code for the escape key.
- /// </summary>
- Esc = 27,
- /// <summary>
- /// The key code for the space bar key.
- /// </summary>
- Space = 32,
- /// <summary>
- /// Digit 0.
- /// </summary>
- D0 = 48,
- /// <summary>
- /// Digit 1.
- /// </summary>
- D1,
- /// <summary>
- /// Digit 2.
- /// </summary>
- D2,
- /// <summary>
- /// Digit 3.
- /// </summary>
- D3,
- /// <summary>
- /// Digit 4.
- /// </summary>
- D4,
- /// <summary>
- /// Digit 5.
- /// </summary>
- D5,
- /// <summary>
- /// Digit 6.
- /// </summary>
- D6,
- /// <summary>
- /// Digit 7.
- /// </summary>
- D7,
- /// <summary>
- /// Digit 8.
- /// </summary>
- D8,
- /// <summary>
- /// Digit 9.
- /// </summary>
- D9,
- /// <summary>
- /// The key code for the user pressing Shift-A
- /// </summary>
- A = 65,
- /// <summary>
- /// The key code for the user pressing Shift-B
- /// </summary>
- B,
- /// <summary>
- /// The key code for the user pressing Shift-C
- /// </summary>
- C,
- /// <summary>
- /// The key code for the user pressing Shift-D
- /// </summary>
- D,
- /// <summary>
- /// The key code for the user pressing Shift-E
- /// </summary>
- E,
- /// <summary>
- /// The key code for the user pressing Shift-F
- /// </summary>
- F,
- /// <summary>
- /// The key code for the user pressing Shift-G
- /// </summary>
- G,
- /// <summary>
- /// The key code for the user pressing Shift-H
- /// </summary>
- H,
- /// <summary>
- /// The key code for the user pressing Shift-I
- /// </summary>
- I,
- /// <summary>
- /// The key code for the user pressing Shift-J
- /// </summary>
- J,
- /// <summary>
- /// The key code for the user pressing Shift-K
- /// </summary>
- K,
- /// <summary>
- /// The key code for the user pressing Shift-L
- /// </summary>
- L,
- /// <summary>
- /// The key code for the user pressing Shift-M
- /// </summary>
- M,
- /// <summary>
- /// The key code for the user pressing Shift-N
- /// </summary>
- N,
- /// <summary>
- /// The key code for the user pressing Shift-O
- /// </summary>
- O,
- /// <summary>
- /// The key code for the user pressing Shift-P
- /// </summary>
- P,
- /// <summary>
- /// The key code for the user pressing Shift-Q
- /// </summary>
- Q,
- /// <summary>
- /// The key code for the user pressing Shift-R
- /// </summary>
- R,
- /// <summary>
- /// The key code for the user pressing Shift-S
- /// </summary>
- S,
- /// <summary>
- /// The key code for the user pressing Shift-T
- /// </summary>
- T,
- /// <summary>
- /// The key code for the user pressing Shift-U
- /// </summary>
- U,
- /// <summary>
- /// The key code for the user pressing Shift-V
- /// </summary>
- V,
- /// <summary>
- /// The key code for the user pressing Shift-W
- /// </summary>
- W,
- /// <summary>
- /// The key code for the user pressing Shift-X
- /// </summary>
- X,
- /// <summary>
- /// The key code for the user pressing Shift-Y
- /// </summary>
- Y,
- /// <summary>
- /// The key code for the user pressing Shift-Z
- /// </summary>
- Z,
- /// <summary>
- /// The key code for the user pressing A
- /// </summary>
- Delete = 127,
- /// <summary>
- /// When this value is set, the Key encodes the sequence Shift-KeyValue.
- /// </summary>
- ShiftMask = 0x10000000,
- /// <summary>
- /// When this value is set, the Key encodes the sequence Alt-KeyValue.
- /// And the actual value must be extracted by removing the AltMask.
- /// </summary>
- AltMask = 0x80000000,
- /// <summary>
- /// When this value is set, the Key encodes the sequence Ctrl-KeyValue.
- /// And the actual value must be extracted by removing the CtrlMask.
- /// </summary>
- CtrlMask = 0x40000000,
- /// <summary>
- /// Cursor up key
- /// </summary>
- CursorUp = 0x100000,
- /// <summary>
- /// Cursor down key.
- /// </summary>
- CursorDown,
- /// <summary>
- /// Cursor left key.
- /// </summary>
- CursorLeft,
- /// <summary>
- /// Cursor right key.
- /// </summary>
- CursorRight,
- /// <summary>
- /// Page Up key.
- /// </summary>
- PageUp,
- /// <summary>
- /// Page Down key.
- /// </summary>
- PageDown,
- /// <summary>
- /// Home key.
- /// </summary>
- Home,
- /// <summary>
- /// End key.
- /// </summary>
- End,
- /// <summary>
- /// Insert character key.
- /// </summary>
- InsertChar,
- /// <summary>
- /// Delete character key.
- /// </summary>
- DeleteChar,
- /// <summary>
- /// Print screen character key.
- /// </summary>
- PrintScreen,
- /// <summary>
- /// F1 key.
- /// </summary>
- F1,
- /// <summary>
- /// F2 key.
- /// </summary>
- F2,
- /// <summary>
- /// F3 key.
- /// </summary>
- F3,
- /// <summary>
- /// F4 key.
- /// </summary>
- F4,
- /// <summary>
- /// F5 key.
- /// </summary>
- F5,
- /// <summary>
- /// F6 key.
- /// </summary>
- F6,
- /// <summary>
- /// F7 key.
- /// </summary>
- F7,
- /// <summary>
- /// F8 key.
- /// </summary>
- F8,
- /// <summary>
- /// F9 key.
- /// </summary>
- F9,
- /// <summary>
- /// F10 key.
- /// </summary>
- F10,
- /// <summary>
- /// F11 key.
- /// </summary>
- F11,
- /// <summary>
- /// F12 key.
- /// </summary>
- F12,
- /// <summary>
- /// F13 key.
- /// </summary>
- F13,
- /// <summary>
- /// F14 key.
- /// </summary>
- F14,
- /// <summary>
- /// F15 key.
- /// </summary>
- F15,
- /// <summary>
- /// F16 key.
- /// </summary>
- F16,
- /// <summary>
- /// F17 key.
- /// </summary>
- F17,
- /// <summary>
- /// F18 key.
- /// </summary>
- F18,
- /// <summary>
- /// F19 key.
- /// </summary>
- F19,
- /// <summary>
- /// F20 key.
- /// </summary>
- F20,
- /// <summary>
- /// F21 key.
- /// </summary>
- F21,
- /// <summary>
- /// F22 key.
- /// </summary>
- F22,
- /// <summary>
- /// F23 key.
- /// </summary>
- F23,
- /// <summary>
- /// F24 key.
- /// </summary>
- F24,
- /// <summary>
- /// A key with an unknown mapping was raised.
- /// </summary>
- Unknown
- }
|