Skip to content
Open
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
28 changes: 18 additions & 10 deletions src/lTerm.ml
Original file line number Diff line number Diff line change
Expand Up @@ -210,16 +210,24 @@ let create
term.input_stream <- Lwt_stream.from (fun () -> Lwt_io.read_char_opt term.ic);
(* Setup initial size and size updater. *)
if term.outgoing_is_a_tty then begin
let check_size () =
let size = get_size_from_fd term.outgoing_fd in
if size <> term.size then begin
term.size <- size;
Lwt_condition.signal term.notify (LTerm_event.Resize size)
end
in
term.size <- get_size_from_fd term.outgoing_fd;
term.last_reported_size <- term.size;
term.event <- E.map check_size resize_event
try
let check_size () =
try
let size = get_size_from_fd term.outgoing_fd in
if size <> term.size then begin
term.size <- size;
Lwt_condition.signal term.notify (LTerm_event.Resize size)
end
with Unix.Unix_error _ -> ()
in
term.size <- get_size_from_fd term.outgoing_fd;
term.last_reported_size <- term.size;
term.event <- E.map check_size resize_event
with Unix.Unix_error _ ->
(* If we can't get the terminal size (e.g. on Windows when the
handle passes isatty but is not a real console), fall back to
treating it as a non-tty. *)
term.outgoing_is_a_tty <- false
end;
return term)
Lwt.fail
Expand Down
27 changes: 23 additions & 4 deletions src/lTerm_term_stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,22 @@

CAMLprim value lt_term_get_size_from_fd(value fd)
{
HANDLE h = Handle_val(fd);
CONSOLE_SCREEN_BUFFER_INFO info;
DWORD mode;
value result;

if (!GetConsoleScreenBufferInfo(Handle_val(fd), &info)) {
/* Validate that the handle is a usable console handle before calling
GetConsoleScreenBufferInfo. On some Windows environments (e.g. GitHub
Actions runners using ConPTY), _isatty() may return true for handles
that are not real console screen buffers, causing
GetConsoleScreenBufferInfo to crash with an access violation. */
if (h == INVALID_HANDLE_VALUE || h == NULL || !GetConsoleMode(h, &mode)) {
win32_maperr(ERROR_INVALID_HANDLE);
uerror("GetConsoleScreenBufferInfo", Nothing);
}

if (!GetConsoleScreenBufferInfo(h, &info)) {
win32_maperr(GetLastError());
uerror("GetConsoleScreenBufferInfo", Nothing);
}
Expand All @@ -39,21 +51,28 @@ CAMLprim value lt_term_get_size_from_fd(value fd)

CAMLprim value lt_term_set_size_from_fd(value fd, value val_size)
{
HANDLE h = Handle_val(fd);
CONSOLE_SCREEN_BUFFER_INFO info;
SMALL_RECT rect;
DWORD mode;

/* Validate that the handle is a usable console handle. */
if (h == INVALID_HANDLE_VALUE || h == NULL || !GetConsoleMode(h, &mode)) {
win32_maperr(ERROR_INVALID_HANDLE);
uerror("SetConsoleWindowInfo", Nothing);
}

if (!GetConsoleScreenBufferInfo(Handle_val(fd), &info)) {
if (!GetConsoleScreenBufferInfo(h, &info)) {
win32_maperr(GetLastError());
uerror("GetConsoleScreenBufferInfo", Nothing);
}

rect;
rect.Top = info.srWindow.Top;
rect.Left = info.srWindow.Left;
rect.Bottom = rect.Top + Int_val(Field(val_size, 0)) - 1;
rect.Right = rect.Left + Int_val(Field(val_size, 1)) - 1;

if (!SetConsoleWindowInfo(Handle_val(fd), TRUE, &rect)) {
if (!SetConsoleWindowInfo(h, TRUE, &rect)) {
win32_maperr(GetLastError());
uerror("SetConsoleWindowInfo", Nothing);
}
Expand Down