From 5b139d1e48809738197fe0bf6b711df66cccc435 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 11 Sep 2018 12:40:02 -0700 Subject: [PATCH] Get window size on more Windows terminals. This is an alternate approach to determining the window size that works on more Windows terminals. Terminals with accurate width detection: Normal Windows console, cmder, ConEmu, VS Code, Hyper, etc. mintty-based terminals will always be 60 characters wide. Cygwin in a command console is ok, but running under x-windows will also always be 60. Tested on Windows 8 and Windows 10. Closes #5124. --- src/cargo/core/shell.rs | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/cargo/core/shell.rs b/src/cargo/core/shell.rs index 3beda22f32f..6b284b7fc76 100644 --- a/src/cargo/core/shell.rs +++ b/src/cargo/core/shell.rs @@ -359,18 +359,51 @@ mod imp { extern crate winapi; use std::mem; + use std::ptr; + use self::winapi::um::fileapi::*; + use self::winapi::um::handleapi::*; use self::winapi::um::processenv::*; use self::winapi::um::winbase::*; use self::winapi::um::wincon::*; + use self::winapi::um::winnt::*; pub fn stderr_width() -> Option { unsafe { let stdout = GetStdHandle(STD_ERROR_HANDLE); let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed(); - if GetConsoleScreenBufferInfo(stdout, &mut csbi) == 0 { + if GetConsoleScreenBufferInfo(stdout, &mut csbi) != 0 { + return Some((csbi.srWindow.Right - csbi.srWindow.Left) as usize) + } + + // On mintty/msys/cygwin based terminals, the above fails with + // INVALID_HANDLE_VALUE. Use an alternate method which works + // in that case as well. + let h = CreateFileA("CONOUT$\0".as_ptr() as *const CHAR, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + ptr::null_mut(), + OPEN_EXISTING, + 0, + ptr::null_mut() + ); + if h == INVALID_HANDLE_VALUE { return None; } - Some((csbi.srWindow.Right - csbi.srWindow.Left) as usize) + + let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed(); + let rc = GetConsoleScreenBufferInfo(h, &mut csbi); + CloseHandle(h); + if rc != 0 { + let width = (csbi.srWindow.Right - csbi.srWindow.Left) as usize; + // Some terminals, such as mintty, always return 79 instead of + // the actual width. In that case, use a conservative value. + if width == 79 { + return Some(60); + } else { + return Some(width); + } + } + return None; } } }