mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2026-01-01 16:59:35 +01:00
Fixes drivers for wide runes handling which also works on Windows Terminal.
This commit is contained in:
@@ -52,27 +52,47 @@ namespace Terminal.Gui {
|
||||
static bool sync = false;
|
||||
public override void AddRune (Rune rune)
|
||||
{
|
||||
if (Clip.Contains (ccol, crow)) {
|
||||
rune = MakePrintable (rune);
|
||||
var runeWidth = Rune.ColumnWidth (rune);
|
||||
var validClip = IsValidContent (ccol, crow, Clip);
|
||||
|
||||
if (validClip) {
|
||||
if (needMove) {
|
||||
Curses.move (crow, ccol);
|
||||
needMove = false;
|
||||
}
|
||||
rune = MakePrintable (rune);
|
||||
if (runeWidth < 2 && ccol > 0
|
||||
&& Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) {
|
||||
|
||||
Curses.move (crow, ccol - 1);
|
||||
Curses.addch ((int)(uint)' ');
|
||||
contents [crow, ccol - 1, 0] = (int)(uint)' ';
|
||||
Curses.move (crow, ccol);
|
||||
} else if (runeWidth < 2 && ccol < Cols - 1 && Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) {
|
||||
|
||||
Curses.move (crow, ccol + 1);
|
||||
Curses.addch ((int)(uint)' ');
|
||||
contents [crow, ccol + 1, 0] = (int)(uint)' ';
|
||||
Curses.move (crow, ccol);
|
||||
}
|
||||
Curses.addch ((int)(uint)rune);
|
||||
contents [crow, ccol, 0] = (int)(uint)rune;
|
||||
contents [crow, ccol, 1] = currentAttribute;
|
||||
contents [crow, ccol, 2] = 1;
|
||||
} else
|
||||
needMove = true;
|
||||
if (sync)
|
||||
Application.Driver.Refresh ();
|
||||
|
||||
ccol++;
|
||||
var runeWidth = Rune.ColumnWidth (rune);
|
||||
if (runeWidth > 1) {
|
||||
for (int i = 1; i < runeWidth; i++) {
|
||||
ccol++;
|
||||
if (validClip) {
|
||||
contents [crow, ccol, 1] = currentAttribute;
|
||||
contents [crow, ccol, 2] = 0;
|
||||
}
|
||||
ccol++;
|
||||
}
|
||||
|
||||
if (sync)
|
||||
UpdateScreen ();
|
||||
}
|
||||
|
||||
public override void AddStr (ustring str)
|
||||
@@ -933,7 +953,7 @@ namespace Terminal.Gui {
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateOffScreen ()
|
||||
public override void UpdateOffScreen ()
|
||||
{
|
||||
contents = new int [Rows, Cols, 3];
|
||||
for (int row = 0; row < Rows; row++) {
|
||||
|
||||
@@ -922,6 +922,7 @@ namespace Terminal.Gui {
|
||||
{
|
||||
BufferWidth = width;
|
||||
BufferHeight = height;
|
||||
_buffer = new char [BufferWidth, BufferHeight];
|
||||
}
|
||||
|
||||
//
|
||||
@@ -1060,7 +1061,8 @@ namespace Terminal.Gui {
|
||||
/// <param name="top"></param>
|
||||
public static void SetWindowPosition (int left, int top)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
WindowLeft = left;
|
||||
WindowTop = top;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -1094,7 +1096,8 @@ namespace Terminal.Gui {
|
||||
/// <param name="height"></param>
|
||||
public static void SetWindowSize (int width, int height)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
WindowWidth = width;
|
||||
WindowHeight = height;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -37,23 +37,23 @@ namespace Terminal.Gui {
|
||||
/// </summary>
|
||||
internal override int [,,] Contents => contents;
|
||||
|
||||
void UpdateOffscreen ()
|
||||
{
|
||||
int cols = Cols;
|
||||
int rows = Rows;
|
||||
//void UpdateOffscreen ()
|
||||
//{
|
||||
// int cols = Cols;
|
||||
// int rows = Rows;
|
||||
|
||||
contents = new int [rows, cols, 3];
|
||||
for (int r = 0; r < rows; r++) {
|
||||
for (int c = 0; c < cols; c++) {
|
||||
contents [r, c, 0] = ' ';
|
||||
contents [r, c, 1] = MakeColor (ConsoleColor.Gray, ConsoleColor.Black);
|
||||
contents [r, c, 2] = 0;
|
||||
}
|
||||
}
|
||||
dirtyLine = new bool [rows];
|
||||
for (int row = 0; row < rows; row++)
|
||||
dirtyLine [row] = true;
|
||||
}
|
||||
// contents = new int [rows, cols, 3];
|
||||
// for (int r = 0; r < rows; r++) {
|
||||
// for (int c = 0; c < cols; c++) {
|
||||
// contents [r, c, 0] = ' ';
|
||||
// contents [r, c, 1] = MakeColor (ConsoleColor.Gray, ConsoleColor.Black);
|
||||
// contents [r, c, 2] = 0;
|
||||
// }
|
||||
// }
|
||||
// dirtyLine = new bool [rows];
|
||||
// for (int row = 0; row < rows; row++)
|
||||
// dirtyLine [row] = true;
|
||||
//}
|
||||
|
||||
static bool sync = false;
|
||||
|
||||
@@ -89,13 +89,14 @@ namespace Terminal.Gui {
|
||||
FakeConsole.CursorLeft = Clip.X;
|
||||
needMove = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void AddRune (Rune rune)
|
||||
{
|
||||
rune = MakePrintable (rune);
|
||||
if (Clip.Contains (ccol, crow)) {
|
||||
var validClip = IsValidContent (ccol, crow, Clip);
|
||||
|
||||
if (validClip) {
|
||||
if (needMove) {
|
||||
//MockConsole.CursorLeft = ccol;
|
||||
//MockConsole.CursorTop = crow;
|
||||
@@ -107,7 +108,20 @@ namespace Terminal.Gui {
|
||||
dirtyLine [crow] = true;
|
||||
} else
|
||||
needMove = true;
|
||||
|
||||
ccol++;
|
||||
var runeWidth = Rune.ColumnWidth (rune);
|
||||
if (runeWidth > 1) {
|
||||
for (int i = 1; i < runeWidth; i++) {
|
||||
if (validClip) {
|
||||
contents [crow, ccol, 1] = currentAttribute;
|
||||
contents [crow, ccol, 2] = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
ccol++;
|
||||
}
|
||||
}
|
||||
//if (ccol == Cols) {
|
||||
// ccol = 0;
|
||||
// if (crow + 1 < Rows)
|
||||
@@ -218,26 +232,7 @@ namespace Terminal.Gui {
|
||||
{
|
||||
int top = Top;
|
||||
int left = Left;
|
||||
int rows = Math.Min (Console.WindowHeight + top, Rows);
|
||||
int cols = Cols;
|
||||
|
||||
FakeConsole.CursorTop = 0;
|
||||
FakeConsole.CursorLeft = 0;
|
||||
for (int row = top; row < rows; row++) {
|
||||
dirtyLine [row] = false;
|
||||
for (int col = left; col < cols; col++) {
|
||||
contents [row, col, 2] = 0;
|
||||
var color = contents [row, col, 1];
|
||||
if (color != redrawColor)
|
||||
SetColor (color);
|
||||
FakeConsole.Write ((char)contents [row, col, 0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Refresh ()
|
||||
{
|
||||
int rows = Rows;
|
||||
int rows = Math.Min (FakeConsole.WindowHeight + top, Rows);
|
||||
int cols = Cols;
|
||||
|
||||
var savedRow = FakeConsole.CursorTop;
|
||||
@@ -247,12 +242,21 @@ namespace Terminal.Gui {
|
||||
continue;
|
||||
dirtyLine [row] = false;
|
||||
for (int col = 0; col < cols; col++) {
|
||||
if (contents [row, col, 2] != 1)
|
||||
continue;
|
||||
|
||||
FakeConsole.CursorTop = row;
|
||||
FakeConsole.CursorLeft = col;
|
||||
for (; col < cols && contents [row, col, 2] == 1; col++) {
|
||||
for (; col < cols; col++) {
|
||||
if (col > 0 && contents [row, col, 2] == 0
|
||||
&& Rune.ColumnWidth ((char)contents [row, col - 1, 0]) > 1) {
|
||||
FakeConsole.CursorLeft = col + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (col < cols - 1 && Rune.ColumnWidth ((char)contents [row, col, 0]) > 1
|
||||
&& (contents [row, col + 1, 2] == 1 || col == cols - 1)) {
|
||||
|
||||
contents [row, col, 0] = ' ';
|
||||
}
|
||||
|
||||
var color = contents [row, col, 1];
|
||||
if (color != redrawColor)
|
||||
SetColor (color);
|
||||
@@ -266,6 +270,12 @@ namespace Terminal.Gui {
|
||||
FakeConsole.CursorLeft = savedCol;
|
||||
}
|
||||
|
||||
public override void Refresh ()
|
||||
{
|
||||
UpdateScreen ();
|
||||
UpdateCursor ();
|
||||
}
|
||||
|
||||
Attribute currentAttribute;
|
||||
public override void SetAttribute (Attribute c)
|
||||
{
|
||||
@@ -388,6 +398,7 @@ namespace Terminal.Gui {
|
||||
|
||||
Action<KeyEvent> keyHandler;
|
||||
Action<KeyEvent> keyUpHandler;
|
||||
private CursorVisibility savedCursorVisibility;
|
||||
|
||||
public override void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> keyHandler, Action<KeyEvent> keyDownHandler, Action<KeyEvent> keyUpHandler, Action<MouseEvent> mouseHandler)
|
||||
{
|
||||
@@ -427,31 +438,32 @@ namespace Terminal.Gui {
|
||||
/// <inheritdoc/>
|
||||
public override bool GetCursorVisibility (out CursorVisibility visibility)
|
||||
{
|
||||
if (FakeConsole.CursorVisible) {
|
||||
visibility = CursorVisibility.Default;
|
||||
} else {
|
||||
visibility = CursorVisibility.Invisible;
|
||||
}
|
||||
visibility = FakeConsole.CursorVisible
|
||||
? CursorVisibility.Default
|
||||
: CursorVisibility.Invisible;
|
||||
|
||||
return false;
|
||||
return FakeConsole.CursorVisible;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool SetCursorVisibility (CursorVisibility visibility)
|
||||
{
|
||||
if (visibility == CursorVisibility.Invisible) {
|
||||
FakeConsole.CursorVisible = false;
|
||||
} else {
|
||||
FakeConsole.CursorVisible = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
savedCursorVisibility = visibility;
|
||||
return FakeConsole.CursorVisible = visibility == CursorVisibility.Default;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool EnsureCursorVisibility ()
|
||||
{
|
||||
return false;
|
||||
if (!(ccol >= 0 && crow >= 0 && ccol < Cols && crow < Rows)) {
|
||||
GetCursorVisibility (out CursorVisibility cursorVisibility);
|
||||
savedCursorVisibility = cursorVisibility;
|
||||
SetCursorVisibility (CursorVisibility.Invisible);
|
||||
return false;
|
||||
}
|
||||
|
||||
SetCursorVisibility (savedCursorVisibility);
|
||||
return FakeConsole.CursorVisible;
|
||||
}
|
||||
|
||||
public override void SendKeys (char keyChar, ConsoleKey key, bool shift, bool alt, bool control)
|
||||
@@ -461,20 +473,24 @@ namespace Terminal.Gui {
|
||||
|
||||
public void SetBufferSize (int width, int height)
|
||||
{
|
||||
cols = FakeConsole.WindowWidth = FakeConsole.BufferWidth = width;
|
||||
rows = FakeConsole.WindowHeight = FakeConsole.BufferHeight = height;
|
||||
FakeConsole.SetBufferSize (width, height);
|
||||
cols = width;
|
||||
rows = height;
|
||||
if (!HeightAsBuffer) {
|
||||
SetWindowSize (width, height);
|
||||
}
|
||||
ProcessResize ();
|
||||
}
|
||||
|
||||
public void SetWindowSize (int width, int height)
|
||||
{
|
||||
FakeConsole.WindowWidth = width;
|
||||
FakeConsole.WindowHeight = height;
|
||||
if (width > cols || !HeightAsBuffer) {
|
||||
cols = FakeConsole.BufferWidth = width;
|
||||
}
|
||||
if (height > rows || !HeightAsBuffer) {
|
||||
rows = FakeConsole.BufferHeight = height;
|
||||
FakeConsole.SetWindowSize (width, height);
|
||||
if (!HeightAsBuffer) {
|
||||
if (width != cols || height != rows) {
|
||||
SetBufferSize (width, height);
|
||||
cols = width;
|
||||
rows = height;
|
||||
}
|
||||
}
|
||||
ProcessResize ();
|
||||
}
|
||||
@@ -482,12 +498,13 @@ namespace Terminal.Gui {
|
||||
public void SetWindowPosition (int left, int top)
|
||||
{
|
||||
if (HeightAsBuffer) {
|
||||
this.left = FakeConsole.WindowLeft = Math.Max (Math.Min (left, Cols - FakeConsole.WindowWidth), 0);
|
||||
this.top = FakeConsole.WindowTop = Math.Max (Math.Min (top, Rows - Console.WindowHeight), 0);
|
||||
this.left = Math.Max (Math.Min (left, Cols - FakeConsole.WindowWidth), 0);
|
||||
this.top = Math.Max (Math.Min (top, Rows - FakeConsole.WindowHeight), 0);
|
||||
} else if (this.left > 0 || this.top > 0) {
|
||||
this.left = FakeConsole.WindowLeft = 0;
|
||||
this.top = FakeConsole.WindowTop = 0;
|
||||
this.left = 0;
|
||||
this.top = 0;
|
||||
}
|
||||
FakeConsole.SetWindowPosition (this.left, this.top);
|
||||
}
|
||||
|
||||
void ProcessResize ()
|
||||
@@ -500,14 +517,14 @@ namespace Terminal.Gui {
|
||||
void ResizeScreen ()
|
||||
{
|
||||
if (!HeightAsBuffer) {
|
||||
if (Console.WindowHeight > 0) {
|
||||
if (FakeConsole.WindowHeight > 0) {
|
||||
// Can raise an exception while is still resizing.
|
||||
try {
|
||||
#pragma warning disable CA1416
|
||||
Console.CursorTop = 0;
|
||||
Console.CursorLeft = 0;
|
||||
Console.WindowTop = 0;
|
||||
Console.WindowLeft = 0;
|
||||
FakeConsole.CursorTop = 0;
|
||||
FakeConsole.CursorLeft = 0;
|
||||
FakeConsole.WindowTop = 0;
|
||||
FakeConsole.WindowLeft = 0;
|
||||
#pragma warning restore CA1416
|
||||
} catch (System.IO.IOException) {
|
||||
return;
|
||||
@@ -518,8 +535,8 @@ namespace Terminal.Gui {
|
||||
} else {
|
||||
try {
|
||||
#pragma warning disable CA1416
|
||||
Console.WindowLeft = Math.Max (Math.Min (left, Cols - Console.WindowWidth), 0);
|
||||
Console.WindowTop = Math.Max (Math.Min (top, Rows - Console.WindowHeight), 0);
|
||||
FakeConsole.WindowLeft = Math.Max (Math.Min (left, Cols - FakeConsole.WindowWidth), 0);
|
||||
FakeConsole.WindowTop = Math.Max (Math.Min (top, Rows - FakeConsole.WindowHeight), 0);
|
||||
#pragma warning restore CA1416
|
||||
} catch (Exception) {
|
||||
return;
|
||||
@@ -532,7 +549,7 @@ namespace Terminal.Gui {
|
||||
dirtyLine = new bool [Rows];
|
||||
}
|
||||
|
||||
void UpdateOffScreen ()
|
||||
public override void UpdateOffScreen ()
|
||||
{
|
||||
// Can raise an exception while is still resizing.
|
||||
try {
|
||||
@@ -569,7 +586,17 @@ namespace Terminal.Gui {
|
||||
#region Unused
|
||||
public override void UpdateCursor ()
|
||||
{
|
||||
//
|
||||
if (!EnsureCursorVisibility ())
|
||||
return;
|
||||
|
||||
// Prevents the exception of size changing during resizing.
|
||||
try {
|
||||
if (ccol >= 0 && ccol < FakeConsole.BufferWidth && crow >= 0 && crow < FakeConsole.BufferHeight) {
|
||||
FakeConsole.SetCursorPosition (ccol, crow);
|
||||
}
|
||||
} catch (System.IO.IOException) {
|
||||
} catch (ArgumentOutOfRangeException) {
|
||||
}
|
||||
}
|
||||
|
||||
public override void StartReportingMouseMoves ()
|
||||
|
||||
@@ -1216,6 +1216,7 @@ namespace Terminal.Gui {
|
||||
|
||||
// Current row, and current col, tracked by Move/AddCh only
|
||||
int ccol, crow;
|
||||
|
||||
public override void Move (int col, int row)
|
||||
{
|
||||
ccol = col;
|
||||
@@ -1229,28 +1230,25 @@ namespace Terminal.Gui {
|
||||
}
|
||||
rune = MakePrintable (rune);
|
||||
var runeWidth = Rune.ColumnWidth (rune);
|
||||
if (Clip.Contains (ccol, crow) && ccol + Math.Max (runeWidth, 1) <= Cols) {
|
||||
var validClip = IsValidContent (ccol, crow, Clip);
|
||||
|
||||
if (validClip) {
|
||||
contents [crow, ccol, 0] = (int)(uint)rune;
|
||||
contents [crow, ccol, 1] = currentAttribute;
|
||||
contents [crow, ccol, 2] = 1;
|
||||
dirtyLine [crow] = true;
|
||||
|
||||
ccol++;
|
||||
if (runeWidth > 1) {
|
||||
for (int i = 1; i < runeWidth; i++) {
|
||||
if (ccol < cols) {
|
||||
contents [crow, ccol, 2] = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
ccol++;
|
||||
}
|
||||
}
|
||||
} else if (ccol > -1 && crow > -1 && ccol < cols && crow < rows) {
|
||||
contents [crow, ccol, 2] = 1;
|
||||
dirtyLine [crow] = true;
|
||||
}
|
||||
|
||||
ccol++;
|
||||
if (runeWidth > 1) {
|
||||
if (validClip) {
|
||||
contents [crow, ccol, 1] = currentAttribute;
|
||||
contents [crow, ccol, 2] = 0;
|
||||
}
|
||||
ccol++;
|
||||
}
|
||||
|
||||
//if (ccol == Cols) {
|
||||
// ccol = 0;
|
||||
// if (crow + 1 < Rows)
|
||||
@@ -1306,7 +1304,6 @@ namespace Terminal.Gui {
|
||||
cols = Console.WindowWidth;
|
||||
rows = Console.WindowHeight;
|
||||
|
||||
Clear ();
|
||||
ResizeScreen ();
|
||||
UpdateOffScreen ();
|
||||
|
||||
@@ -1352,6 +1349,8 @@ namespace Terminal.Gui {
|
||||
Colors.Error.HotNormal = MakeColor (ConsoleColor.Black, ConsoleColor.White);
|
||||
Colors.Error.HotFocus = MakeColor (ConsoleColor.Black, ConsoleColor.DarkRed);
|
||||
Colors.Error.Disabled = MakeColor (ConsoleColor.DarkGray, ConsoleColor.White);
|
||||
|
||||
Clear ();
|
||||
}
|
||||
|
||||
void ResizeScreen ()
|
||||
@@ -1395,28 +1394,29 @@ namespace Terminal.Gui {
|
||||
$";{Rows};{Cols}w");
|
||||
}
|
||||
}
|
||||
|
||||
Clip = new Rect (0, 0, Cols, Rows);
|
||||
|
||||
contents = new int [Rows, Cols, 3];
|
||||
dirtyLine = new bool [Rows];
|
||||
}
|
||||
|
||||
void UpdateOffScreen ()
|
||||
public override void UpdateOffScreen ()
|
||||
{
|
||||
// Can raise an exception while is still resizing.
|
||||
try {
|
||||
for (int row = 0; row < rows; row++) {
|
||||
for (int c = 0; c < cols; c++) {
|
||||
contents [row, c, 0] = ' ';
|
||||
contents [row, c, 1] = (ushort)Colors.TopLevel.Normal;
|
||||
contents [row, c, 2] = 0;
|
||||
dirtyLine [row] = true;
|
||||
}
|
||||
}
|
||||
} catch (IndexOutOfRangeException) { }
|
||||
contents = new int [Rows, Cols, 3];
|
||||
dirtyLine = new bool [Rows];
|
||||
|
||||
winChanging = false;
|
||||
lock (contents) {
|
||||
// Can raise an exception while is still resizing.
|
||||
try {
|
||||
for (int row = 0; row < rows; row++) {
|
||||
for (int c = 0; c < cols; c++) {
|
||||
contents [row, c, 0] = ' ';
|
||||
contents [row, c, 1] = (ushort)Colors.TopLevel.Normal;
|
||||
contents [row, c, 2] = 0;
|
||||
dirtyLine [row] = true;
|
||||
}
|
||||
}
|
||||
} catch (IndexOutOfRangeException) { }
|
||||
|
||||
winChanging = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override Attribute MakeAttribute (Color fore, Color back)
|
||||
@@ -1427,6 +1427,7 @@ namespace Terminal.Gui {
|
||||
public override void Refresh ()
|
||||
{
|
||||
UpdateScreen ();
|
||||
UpdateCursor ();
|
||||
}
|
||||
|
||||
int redrawAttr = -1;
|
||||
@@ -1443,7 +1444,7 @@ namespace Terminal.Gui {
|
||||
int rows = Math.Min (Console.WindowHeight + top, Rows);
|
||||
int cols = Cols;
|
||||
|
||||
Console.CursorVisible = false;
|
||||
var savedCursorVisible = Console.CursorVisible = false;
|
||||
for (int row = top; row < rows; row++) {
|
||||
if (!dirtyLine [row]) {
|
||||
continue;
|
||||
@@ -1454,13 +1455,29 @@ namespace Terminal.Gui {
|
||||
if (Console.WindowHeight > 0 && !SetCursorPosition (col, row)) {
|
||||
return;
|
||||
}
|
||||
var lastCol = -1;
|
||||
for (; col < cols; col++) {
|
||||
if (contents [row, col, 2] != 1) {
|
||||
if (col > 0 && contents [row, col, 2] == 0
|
||||
&& Rune.ColumnWidth ((char)contents [row, col - 1, 0]) > 1) {
|
||||
|
||||
if (col == cols - 1 && output.Length > 0) {
|
||||
Console.CursorLeft = lastCol;
|
||||
Console.Write (output);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (col < cols - 1 && Rune.ColumnWidth ((char)contents [row, col, 0]) > 1
|
||||
&& (contents [row, col + 1, 2] == 1 || col == cols - 1)) {
|
||||
|
||||
contents [row, col, 0] = ' ';
|
||||
}
|
||||
|
||||
var attr = contents [row, col, 1];
|
||||
if (attr != redrawAttr) {
|
||||
output.Append (WriteAttributes (attr));
|
||||
if (lastCol == -1)
|
||||
lastCol = col;
|
||||
}
|
||||
if (AlwaysSetPosition && !SetCursorPosition (col, row)) {
|
||||
return;
|
||||
@@ -1469,6 +1486,8 @@ namespace Terminal.Gui {
|
||||
Console.Write ($"{output}{(char)contents [row, col, 0]}");
|
||||
} else {
|
||||
output.Append ((char)contents [row, col, 0]);
|
||||
if (lastCol == -1)
|
||||
lastCol = col;
|
||||
}
|
||||
contents [row, col, 2] = 0;
|
||||
if (!AlwaysSetPosition && col == cols - 1) {
|
||||
@@ -1477,8 +1496,7 @@ namespace Terminal.Gui {
|
||||
}
|
||||
}
|
||||
}
|
||||
Console.CursorVisible = true;
|
||||
UpdateCursor ();
|
||||
Console.CursorVisible = savedCursorVisible;
|
||||
}
|
||||
|
||||
System.Text.StringBuilder WriteAttributes (int attr)
|
||||
@@ -1553,11 +1571,16 @@ namespace Terminal.Gui {
|
||||
}
|
||||
}
|
||||
|
||||
private CursorVisibility? savedCursorVisibility;
|
||||
|
||||
public override void UpdateCursor ()
|
||||
{
|
||||
if (!EnsureCursorVisibility ())
|
||||
return;
|
||||
|
||||
// Prevents the exception of size changing during resizing.
|
||||
try {
|
||||
if (ccol >= 0 && ccol <= cols && crow >= 0 && crow <= rows) {
|
||||
if (ccol >= 0 && ccol < Console.BufferWidth && crow >= 0 && crow < Console.BufferHeight) {
|
||||
Console.SetCursorPosition (ccol, crow);
|
||||
}
|
||||
} catch (System.IO.IOException) {
|
||||
@@ -1885,21 +1908,30 @@ namespace Terminal.Gui {
|
||||
/// <inheritdoc/>
|
||||
public override bool GetCursorVisibility (out CursorVisibility visibility)
|
||||
{
|
||||
visibility = CursorVisibility.Default;
|
||||
|
||||
return false;
|
||||
visibility = savedCursorVisibility ?? CursorVisibility.Default;
|
||||
return visibility == CursorVisibility.Default;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool SetCursorVisibility (CursorVisibility visibility)
|
||||
{
|
||||
return false;
|
||||
savedCursorVisibility = visibility;
|
||||
return Console.CursorVisible = visibility == CursorVisibility.Default;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool EnsureCursorVisibility ()
|
||||
{
|
||||
return false;
|
||||
if (!(ccol >= 0 && crow >= 0 && ccol < Cols && crow < Rows)) {
|
||||
GetCursorVisibility (out CursorVisibility cursorVisibility);
|
||||
savedCursorVisibility = cursorVisibility;
|
||||
SetCursorVisibility (CursorVisibility.Invisible);
|
||||
return false;
|
||||
}
|
||||
|
||||
SetCursorVisibility (savedCursorVisibility ?? CursorVisibility.Default);
|
||||
return savedCursorVisibility == CursorVisibility.Default;
|
||||
}
|
||||
|
||||
public override void SendKeys (char keyChar, ConsoleKey key, bool shift, bool alt, bool control)
|
||||
|
||||
@@ -1443,7 +1443,7 @@ namespace Terminal.Gui {
|
||||
WinConsole.ForceRefreshCursorVisibility ();
|
||||
}
|
||||
|
||||
void UpdateOffScreen ()
|
||||
public override void UpdateOffScreen ()
|
||||
{
|
||||
contents = new int [rows, cols, 3];
|
||||
for (int row = 0; row < rows; row++) {
|
||||
@@ -1468,9 +1468,26 @@ namespace Terminal.Gui {
|
||||
public override void AddRune (Rune rune)
|
||||
{
|
||||
rune = MakePrintable (rune);
|
||||
var runeWidth = Rune.ColumnWidth (rune);
|
||||
var position = crow * Cols + ccol;
|
||||
var validClip = IsValidContent (ccol, crow, Clip);
|
||||
|
||||
if (Clip.Contains (ccol, crow)) {
|
||||
if (validClip) {
|
||||
if (runeWidth < 2 && ccol > 0
|
||||
&& Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) {
|
||||
|
||||
var prevPosition = crow * Cols + (ccol - 1);
|
||||
OutputBuffer [prevPosition].Char.UnicodeChar = ' ';
|
||||
contents [crow, ccol - 1, 0] = (int)(uint)' ';
|
||||
|
||||
} else if (runeWidth < 2 && ccol < Cols - 1 && Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) {
|
||||
|
||||
var prevPosition = crow * Cols + ccol + 1;
|
||||
OutputBuffer [prevPosition].Char.UnicodeChar = (char)' ';
|
||||
contents [crow, ccol + 1, 0] = (int)(uint)' ';
|
||||
} else if (rune != ' ') {
|
||||
|
||||
}
|
||||
OutputBuffer [position].Attributes = (ushort)currentAttribute;
|
||||
OutputBuffer [position].Char.UnicodeChar = (char)rune;
|
||||
contents [crow, ccol, 0] = (int)(uint)rune;
|
||||
@@ -1480,17 +1497,18 @@ namespace Terminal.Gui {
|
||||
}
|
||||
|
||||
ccol++;
|
||||
var runeWidth = Rune.ColumnWidth (rune);
|
||||
if (runeWidth > 1) {
|
||||
for (int i = 1; i < runeWidth; i++) {
|
||||
AddStr (" ");
|
||||
if (validClip) {
|
||||
position = crow * Cols + ccol;
|
||||
OutputBuffer [position].Attributes = (ushort)currentAttribute;
|
||||
OutputBuffer [position].Char.UnicodeChar = '\0';
|
||||
contents [crow, ccol, 0] = (int)(uint)'\0';
|
||||
contents [crow, ccol, 1] = currentAttribute;
|
||||
contents [crow, ccol, 2] = 0;
|
||||
}
|
||||
ccol++;
|
||||
}
|
||||
//if (ccol == Cols) {
|
||||
// ccol = 0;
|
||||
// if (crow + 1 < Rows)
|
||||
// crow++;
|
||||
//}
|
||||
|
||||
if (sync)
|
||||
UpdateScreen ();
|
||||
}
|
||||
|
||||
@@ -701,6 +701,16 @@ namespace Terminal.Gui {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the column and line are in a valid range from the size of the driver.
|
||||
/// </summary>
|
||||
/// <param name="col">The column.</param>
|
||||
/// <param name="row">The row.</param>
|
||||
/// <param name="clip">The clip.</param>
|
||||
/// <returns><c>true</c>if it's a valid range,<c>false</c>otherwise.</returns>
|
||||
public bool IsValidContent (int col, int row, Rect clip) =>
|
||||
col >= 0 && row >= 0 && col < Cols && row < Rows && clip.Contains (col, row);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified
|
||||
/// </summary>
|
||||
@@ -751,6 +761,11 @@ namespace Terminal.Gui {
|
||||
/// </summary>
|
||||
public abstract void End ();
|
||||
|
||||
/// <summary>
|
||||
/// Reset and recreate the contents and the driver buffer.
|
||||
/// </summary>
|
||||
public abstract void UpdateOffScreen ();
|
||||
|
||||
/// <summary>
|
||||
/// Redraws the physical screen with the contents that have been queued up via any of the printing commands.
|
||||
/// </summary>
|
||||
@@ -824,7 +839,8 @@ namespace Terminal.Gui {
|
||||
if (!ustring.IsNullOrEmpty (title) && width > 4 && region.Y + paddingTop <= region.Y + paddingBottom) {
|
||||
Move (region.X + 1 + paddingLeft, region.Y + paddingTop);
|
||||
AddRune (' ');
|
||||
var str = title.RuneCount >= width ? title [0, width - 2] : title;
|
||||
var str = title.Sum (r => Math.Max (Rune.ColumnWidth (r), 1)) >= width
|
||||
? TextFormatter.Format (title, width - 2, false, false) [0] : title;
|
||||
AddStr (str);
|
||||
AddRune (' ');
|
||||
}
|
||||
|
||||
@@ -339,10 +339,10 @@ namespace Terminal.Gui.ConsoleDrivers {
|
||||
Assert.Equal (25, Application.Driver.Rows);
|
||||
Assert.Equal (120, Console.BufferWidth);
|
||||
Assert.Equal (25, Console.BufferHeight);
|
||||
Assert.Equal (120, Console.WindowWidth);
|
||||
Assert.Equal (80, Console.WindowWidth);
|
||||
Assert.Equal (25, Console.WindowHeight);
|
||||
driver.SetWindowPosition (121, 25);
|
||||
Assert.Equal (0, Console.WindowLeft);
|
||||
Assert.Equal (40, Console.WindowLeft);
|
||||
Assert.Equal (0, Console.WindowTop);
|
||||
|
||||
driver.SetWindowSize (90, 25);
|
||||
@@ -388,17 +388,19 @@ namespace Terminal.Gui.ConsoleDrivers {
|
||||
Assert.Equal (0, Console.WindowLeft);
|
||||
Assert.Equal (0, Console.WindowTop);
|
||||
|
||||
// MockDriver will now be sets to 120x25
|
||||
// MockDriver will now be sets to 80x40
|
||||
driver.SetBufferSize (80, 40);
|
||||
Assert.Equal (80, Application.Driver.Cols);
|
||||
Assert.Equal (40, Application.Driver.Rows);
|
||||
Assert.Equal (80, Console.BufferWidth);
|
||||
Assert.Equal (40, Console.BufferHeight);
|
||||
Assert.Equal (80, Console.WindowWidth);
|
||||
Assert.Equal (40, Console.WindowHeight);
|
||||
driver.SetWindowPosition (80, 40);
|
||||
Assert.Equal (25, Console.WindowHeight);
|
||||
Assert.Equal (0, Console.WindowLeft);
|
||||
Assert.Equal (0, Console.WindowTop);
|
||||
driver.SetWindowPosition (80, 40);
|
||||
Assert.Equal (0, Console.WindowLeft);
|
||||
Assert.Equal (15, Console.WindowTop);
|
||||
|
||||
driver.SetWindowSize (80, 20);
|
||||
Assert.Equal (80, Application.Driver.Cols);
|
||||
@@ -407,6 +409,8 @@ namespace Terminal.Gui.ConsoleDrivers {
|
||||
Assert.Equal (40, Console.BufferHeight);
|
||||
Assert.Equal (80, Console.WindowWidth);
|
||||
Assert.Equal (20, Console.WindowHeight);
|
||||
Assert.Equal (0, Console.WindowLeft);
|
||||
Assert.Equal (15, Console.WindowTop);
|
||||
driver.SetWindowPosition (80, 41);
|
||||
Assert.Equal (0, Console.WindowLeft);
|
||||
Assert.Equal (20, Console.WindowTop);
|
||||
|
||||
Reference in New Issue
Block a user