Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
263 changes: 129 additions & 134 deletions Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ internal class WindowsConsole {
public const int STD_ERROR_HANDLE = -12;

internal IntPtr InputHandle, OutputHandle;
IntPtr screenBuffer;
readonly uint originalConsoleMode;
CursorVisibility? initialCursorVisibility = null;
CursorVisibility? currentCursorVisibility = null;
Expand All @@ -39,47 +40,47 @@ public WindowsConsole ()

public bool WriteToConsole (Size size, CharInfo [] charInfoBuffer, Coord coords, SmallRect window)
{
//if (OutputHandle == IntPtr.Zero) {
// ReadFromConsoleOutput (size, coords, ref window);
//}
if (!IsWindowsTerminal && screenBuffer == IntPtr.Zero) {
ReadFromConsoleOutput (size, coords, ref window);
}

return WriteConsoleOutput (OutputHandle, charInfoBuffer, coords, new Coord () { X = window.Left, Y = window.Top }, ref window);
}
if (!initialCursorVisibility.HasValue && GetCursorVisibility (out CursorVisibility visibility)) {
initialCursorVisibility = visibility;
}

//public void ReadFromConsoleOutput (Size size, Coord coords, ref SmallRect window)
//{
// OutputHandle = CreateConsoleScreenBuffer (
// DesiredAccess.GenericRead | DesiredAccess.GenericWrite,
// ShareMode.FileShareRead | ShareMode.FileShareWrite,
// IntPtr.Zero,
// 1,
// IntPtr.Zero
// );
// if (ScreenBuffer == INVALID_HANDLE_VALUE) {
// var err = Marshal.GetLastWin32Error ();
return WriteConsoleOutput (IsWindowsTerminal ? OutputHandle : screenBuffer, charInfoBuffer, coords, new Coord () { X = window.Left, Y = window.Top }, ref window);
}

// if (err != 0)
// throw new System.ComponentModel.Win32Exception (err);
// }
public void ReadFromConsoleOutput (Size size, Coord coords, ref SmallRect window)
{
screenBuffer = CreateConsoleScreenBuffer (
DesiredAccess.GenericRead | DesiredAccess.GenericWrite,
ShareMode.FileShareRead | ShareMode.FileShareWrite,
IntPtr.Zero,
1,
IntPtr.Zero
);
if (screenBuffer == INVALID_HANDLE_VALUE) {
var err = Marshal.GetLastWin32Error ();

// if (!initialCursorVisibility.HasValue && GetCursorVisibility (out CursorVisibility visibility)) {
// initialCursorVisibility = visibility;
// }
if (err != 0)
throw new System.ComponentModel.Win32Exception (err);
}

// if (!SetConsoleActiveScreenBuffer (ScreenBuffer)) {
// throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
// }
if (!SetConsoleActiveScreenBuffer (screenBuffer)) {
throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
}

// OriginalStdOutChars = new CharInfo [size.Height * size.Width];
OriginalStdOutChars = new CharInfo [size.Height * size.Width];

// if (!ReadConsoleOutput (ScreenBuffer, OriginalStdOutChars, coords, new Coord () { X = 0, Y = 0 }, ref window)) {
// throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
// }
//}
if (!ReadConsoleOutput (screenBuffer, OriginalStdOutChars, coords, new Coord () { X = 0, Y = 0 }, ref window)) {
throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
}
}

public bool SetCursorPosition (Coord position)
{
return SetConsoleCursorPosition (OutputHandle, position);
return SetConsoleCursorPosition (IsWindowsTerminal ? OutputHandle : screenBuffer, position);
}

public void SetInitialCursorVisibility ()
Expand All @@ -91,11 +92,11 @@ public void SetInitialCursorVisibility ()

public bool GetCursorVisibility (out CursorVisibility visibility)
{
if (OutputHandle == IntPtr.Zero) {
if ((IsWindowsTerminal ? OutputHandle : screenBuffer) == IntPtr.Zero) {
visibility = CursorVisibility.Invisible;
return false;
}
if (!GetConsoleCursorInfo (OutputHandle, out ConsoleCursorInfo info)) {
if (!GetConsoleCursorInfo (IsWindowsTerminal ? OutputHandle : screenBuffer, out ConsoleCursorInfo info)) {
var err = Marshal.GetLastWin32Error ();
if (err != 0) {
throw new System.ComponentModel.Win32Exception (err);
Expand Down Expand Up @@ -148,7 +149,7 @@ public bool SetCursorVisibility (CursorVisibility visibility)
bVisible = ((uint)visibility & 0xFF00) != 0
};

if (!SetConsoleCursorInfo (OutputHandle, ref info))
if (!SetConsoleCursorInfo (IsWindowsTerminal ? OutputHandle : screenBuffer, ref info))
return false;

currentCursorVisibility = visibility;
Expand All @@ -164,28 +165,28 @@ public void Cleanup ()
}

ConsoleMode = originalConsoleMode;
//if (!SetConsoleActiveScreenBuffer (OutputHandle)) {
// var err = Marshal.GetLastWin32Error ();
// Console.WriteLine ("Error: {0}", err);
//}
if (!SetConsoleActiveScreenBuffer (OutputHandle)) {
var err = Marshal.GetLastWin32Error ();
Console.WriteLine ("Error: {0}", err);
}

//if (ScreenBuffer != IntPtr.Zero) {
// CloseHandle (ScreenBuffer);
//}
if (screenBuffer != IntPtr.Zero) {
CloseHandle (screenBuffer);
}

//ScreenBuffer = IntPtr.Zero;
screenBuffer = IntPtr.Zero;
}

internal Size GetConsoleBufferWindow (out Point position)
{
if (OutputHandle == IntPtr.Zero) {
if ((IsWindowsTerminal ? OutputHandle : screenBuffer) == IntPtr.Zero) {
position = Point.Empty;
return Size.Empty;
}

var csbi = new CONSOLE_SCREEN_BUFFER_INFOEX ();
csbi.cbSize = (uint)Marshal.SizeOf (csbi);
if (!GetConsoleScreenBufferInfoEx (OutputHandle, ref csbi)) {
if (!GetConsoleScreenBufferInfoEx ((IsWindowsTerminal ? OutputHandle : screenBuffer), ref csbi)) {
//throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
position = Point.Empty;
return Size.Empty;
Expand All @@ -211,68 +212,70 @@ internal Size GetConsoleOutputWindow (out Point position)
return sz;
}

//internal Size SetConsoleWindow (short cols, short rows)
//{
// var csbi = new CONSOLE_SCREEN_BUFFER_INFOEX ();
// csbi.cbSize = (uint)Marshal.SizeOf (csbi);

// if (!GetConsoleScreenBufferInfoEx (ScreenBuffer, ref csbi)) {
// throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
// }
// var maxWinSize = GetLargestConsoleWindowSize (ScreenBuffer);
// var newCols = Math.Min (cols, maxWinSize.X);
// var newRows = Math.Min (rows, maxWinSize.Y);
// csbi.dwSize = new Coord (newCols, Math.Max (newRows, (short)1));
// csbi.srWindow = new SmallRect (0, 0, newCols, newRows);
// csbi.dwMaximumWindowSize = new Coord (newCols, newRows);
// if (!SetConsoleScreenBufferInfoEx (ScreenBuffer, ref csbi)) {
// throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
// }
// var winRect = new SmallRect (0, 0, (short)(newCols - 1), (short)Math.Max (newRows - 1, 0));
// if (!SetConsoleWindowInfo (OutputHandle, true, ref winRect)) {
// //throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
// return new Size (cols, rows);
// }
// SetConsoleOutputWindow (csbi);
// return new Size (winRect.Right + 1, newRows - 1 < 0 ? 0 : winRect.Bottom + 1);
//}

//void SetConsoleOutputWindow (CONSOLE_SCREEN_BUFFER_INFOEX csbi)
//{
// if (ScreenBuffer != IntPtr.Zero && !SetConsoleScreenBufferInfoEx (ScreenBuffer, ref csbi)) {
// throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
// }
//}

//internal Size SetConsoleOutputWindow (out Point position)
//{
// if (ScreenBuffer == IntPtr.Zero) {
// position = Point.Empty;
// return Size.Empty;
// }

// var csbi = new CONSOLE_SCREEN_BUFFER_INFOEX ();
// csbi.cbSize = (uint)Marshal.SizeOf (csbi);
// if (!GetConsoleScreenBufferInfoEx (ScreenBuffer, ref csbi)) {
// throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
// }
// var sz = new Size (csbi.srWindow.Right - csbi.srWindow.Left + 1,
// Math.Max (csbi.srWindow.Bottom - csbi.srWindow.Top + 1, 0));
// position = new Point (csbi.srWindow.Left, csbi.srWindow.Top);
// SetConsoleOutputWindow (csbi);
// var winRect = new SmallRect (0, 0, (short)(sz.Width - 1), (short)Math.Max (sz.Height - 1, 0));
// if (!SetConsoleScreenBufferInfoEx (OutputHandle, ref csbi)) {
// throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
// }
// if (!SetConsoleWindowInfo (OutputHandle, true, ref winRect)) {
// throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
// }

// return sz;
//}
internal Size SetConsoleWindow (short cols, short rows)
{
var csbi = new CONSOLE_SCREEN_BUFFER_INFOEX ();
csbi.cbSize = (uint)Marshal.SizeOf (csbi);

if (!GetConsoleScreenBufferInfoEx (IsWindowsTerminal ? OutputHandle : screenBuffer, ref csbi)) {
throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
}
var maxWinSize = GetLargestConsoleWindowSize (IsWindowsTerminal ? OutputHandle : screenBuffer);
var newCols = Math.Min (cols, maxWinSize.X);
var newRows = Math.Min (rows, maxWinSize.Y);
csbi.dwSize = new Coord (newCols, Math.Max (newRows, (short)1));
csbi.srWindow = new SmallRect (0, 0, newCols, newRows);
csbi.dwMaximumWindowSize = new Coord (newCols, newRows);
if (!SetConsoleScreenBufferInfoEx (IsWindowsTerminal ? OutputHandle : screenBuffer, ref csbi)) {
throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
}
var winRect = new SmallRect (0, 0, (short)(newCols - 1), (short)Math.Max (newRows - 1, 0));
if (!SetConsoleWindowInfo (OutputHandle, true, ref winRect)) {
//throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
return new Size (cols, rows);
}
SetConsoleOutputWindow (csbi);
return new Size (winRect.Right + 1, newRows - 1 < 0 ? 0 : winRect.Bottom + 1);
}

void SetConsoleOutputWindow (CONSOLE_SCREEN_BUFFER_INFOEX csbi)
{
if ((IsWindowsTerminal ? OutputHandle : screenBuffer) != IntPtr.Zero && !SetConsoleScreenBufferInfoEx (IsWindowsTerminal ? OutputHandle : screenBuffer, ref csbi)) {
throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
}
}

internal Size SetConsoleOutputWindow (out Point position)
{
if ((IsWindowsTerminal ? OutputHandle : screenBuffer) == IntPtr.Zero) {
position = Point.Empty;
return Size.Empty;
}

var csbi = new CONSOLE_SCREEN_BUFFER_INFOEX ();
csbi.cbSize = (uint)Marshal.SizeOf (csbi);
if (!GetConsoleScreenBufferInfoEx (IsWindowsTerminal ? OutputHandle : screenBuffer, ref csbi)) {
throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
}
var sz = new Size (csbi.srWindow.Right - csbi.srWindow.Left + 1,
Math.Max (csbi.srWindow.Bottom - csbi.srWindow.Top + 1, 0));
position = new Point (csbi.srWindow.Left, csbi.srWindow.Top);
SetConsoleOutputWindow (csbi);
var winRect = new SmallRect (0, 0, (short)(sz.Width - 1), (short)Math.Max (sz.Height - 1, 0));
if (!SetConsoleScreenBufferInfoEx (OutputHandle, ref csbi)) {
throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
}
if (!SetConsoleWindowInfo (OutputHandle, true, ref winRect)) {
throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
}

return sz;
}

//bool ContinueListeningForConsoleEvents = true;

internal bool IsWindowsTerminal { get; set; }

public uint ConsoleMode {
get {
GetConsoleMode (InputHandle, out uint v);
Expand Down Expand Up @@ -733,7 +736,7 @@ public WindowsDriver ()
WinConsole = new WindowsConsole ();
clipboard = new WindowsClipboard ();

isWindowsTerminal = Environment.GetEnvironmentVariable ("WT_SESSION") != null || Environment.GetEnvironmentVariable ("VSAPPIDNAME") != null;
WinConsole.IsWindowsTerminal = isWindowsTerminal = Environment.GetEnvironmentVariable ("WT_SESSION") != null || Environment.GetEnvironmentVariable ("VSAPPIDNAME") != null;
}

public override void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> keyHandler, Action<KeyEvent> keyDownHandler, Action<KeyEvent> keyUpHandler, Action<MouseEvent> mouseHandler)
Expand All @@ -747,28 +750,28 @@ public override void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> keyHandle

mLoop.ProcessInput = (e) => ProcessInput (e);

//mLoop.WinChanged = (e) => {
// ChangeWin (e);
//};
}

//private void ChangeWin (Size e)
//{
// var w = e.Width;
// if (w == cols - 3 && e.Height < rows) {
// w += 3;
// }
// var newSize = WinConsole.SetConsoleWindow (
// (short)Math.Max (w, 16), (short)Math.Max (e.Height, 0));

// left = 0;
// top = 0;
// cols = newSize.Width;
// rows = newSize.Height;
// ResizeScreen ();
// UpdateOffScreen ();
// TerminalResized.Invoke ();
//}
mLoop.WinChanged = (e) => {
ChangeWin (e);
};
}

private void ChangeWin (Size e)
{
var w = e.Width;
if (w == cols - 3 && e.Height < rows) {
w += 3;
}
var newSize = WinConsole.SetConsoleWindow (
(short)Math.Max (w, 16), (short)Math.Max (e.Height, 0));

left = 0;
top = 0;
cols = newSize.Width;
rows = newSize.Height;
ResizeScreen ();
UpdateOffScreen ();
TerminalResized.Invoke ();
}

void ProcessInput (WindowsConsole.InputRecord inputEvent)
{
Expand Down Expand Up @@ -892,14 +895,6 @@ void ProcessInput (WindowsConsole.InputRecord inputEvent)
case WindowsConsole.EventType.Focus:
keyModifiers = null;
break;

case WindowsConsole.EventType.WindowBufferSize:
cols = inputEvent.WindowBufferSizeEvent.size.X;
rows = inputEvent.WindowBufferSizeEvent.size.Y;

ResizeScreen ();
TerminalResized.Invoke ();
break;
}
}

Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/Resources/Strings.ja-JP.resx
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,6 @@
<value>終える</value>
</data>
<data name="wzNext" xml:space="preserve">
<value>次に</value>
<value>次に...</value>
</data>
</root>
2 changes: 1 addition & 1 deletion Terminal.Gui/Resources/Strings.pt-PT.resx
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,6 @@
<value>Acabam_ento</value>
</data>
<data name="wzNext" xml:space="preserve">
<value>S_eguir</value>
<value>S_eguir...</value>
</data>
</root>
2 changes: 1 addition & 1 deletion Terminal.Gui/Terminal.Gui.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<DebugType>portable</DebugType>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>net472;netstandard2.0;netstandard2.1;net6.0;net7.0;net8.0</TargetFrameworks>
<TargetFrameworks>net472;netstandard2.0;netstandard2.1;net6.0;net8.0</TargetFrameworks>
<RootNamespace>Terminal.Gui</RootNamespace>
<AssemblyName>Terminal.Gui</AssemblyName>
<SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>
Expand Down
Loading