Skip to content

Commit

Permalink
Use Windows 10's virtual terminal if available
Browse files Browse the repository at this point in the history
  • Loading branch information
mridgers committed May 18, 2023
1 parent 8f820d7 commit 530196a
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 6 deletions.
1 change: 1 addition & 0 deletions clink/terminal/include/terminal/terminal.h
Expand Up @@ -12,6 +12,7 @@ struct Terminal
{
TerminalIn* in;
TerminalOut* out;
uintptr_t impl;
};

//------------------------------------------------------------------------------
Expand Down
60 changes: 54 additions & 6 deletions clink/terminal/src/terminal.cpp
Expand Up @@ -6,20 +6,55 @@
#include "ecma48_terminal_out.h"
#include "win_screen_buffer.h"
#include "win_terminal_in.h"
#include "win_terminal_out.h"

#include <core/base.h>

//------------------------------------------------------------------------------
#if defined(PLATFORM_WINDOWS)
struct WinVirtualTerminal
{
DWORD prev_mode = ~0u;
ScreenBuffer* screen = nullptr;
};
#endif

//------------------------------------------------------------------------------
Terminal terminal_create(ScreenBuffer* screen)
{
#if defined(PLATFORM_WINDOWS)
if (screen == nullptr)
screen = new WinScreenBuffer(); // TODO: this leaks.
auto* impl = new WinVirtualTerminal();

Terminal terminal;
terminal.in = new WinTerminalIn();
terminal.out = nullptr;
terminal.impl = uintptr_t(impl);

// Try and use Win10's VT100 support
DWORD prev_mode;
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
if (GetConsoleMode(handle, &prev_mode))
{
if (SetConsoleMode(handle, prev_mode|ENABLE_VIRTUAL_TERMINAL_PROCESSING))
{
impl->prev_mode = prev_mode;
terminal.out = new WinTerminalOut();
}
}

return {
new WinTerminalIn(),
new Ecma48TerminalOut(*screen),
};
// If it wasn't possible to enable VT100 support we'll fallback to Clink's
if (terminal.out == nullptr)
{
if (screen == nullptr)
{
screen = new WinScreenBuffer();
impl->screen = screen;
}

terminal.out = new Ecma48TerminalOut(*screen);
}

return terminal;
#else
return {};
#endif
Expand All @@ -30,4 +65,17 @@ void terminal_destroy(const Terminal& terminal)
{
delete terminal.out;
delete terminal.in;

auto* impl = (WinVirtualTerminal*)(terminal.impl);

if (impl->prev_mode != ~0u)
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleMode(handle, impl->prev_mode);
}

if (impl->screen != nullptr)
delete impl->screen;

delete impl;
}

0 comments on commit 530196a

Please sign in to comment.