diff options
| author | Yuki Okushi <huyuumi.dev@gmail.com> | 2020-01-14 14:02:20 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-01-14 14:02:20 +0900 |
| commit | 974b69927b2ca665a414a477717d40320cc7fbbd (patch) | |
| tree | b7e9f3b25e40a1d7270c732bec1ecd771c111caa | |
| parent | 9e47ddd399fab91af5eb804727f9f1400a140753 (diff) | |
| parent | f9a57469612ba457fb7865aef944bf05d7664516 (diff) | |
| download | rust-974b69927b2ca665a414a477717d40320cc7fbbd.tar.gz rust-974b69927b2ca665a414a477717d40320cc7fbbd.zip | |
Rollup merge of #68036 - euclio:libterm-ncurses6-fix, r=KodrAus
libterm: parse extended terminfo format Fixes #45728. Modifies libterm to parse the extended terminfo format introduced in ncurses 6.1. This fixes the lack of color in test output for users with newer ncurses versions. The ideal fix for this would be to migrate libtest to use `termcolor` (https://github.com/rust-lang/rust/issues/60349), but that's blocked for the foreseeable future.
| -rw-r--r-- | src/libterm/lib.rs | 2 | ||||
| -rw-r--r-- | src/libterm/terminfo/mod.rs | 4 | ||||
| -rw-r--r-- | src/libterm/terminfo/parser/compiled.rs | 39 | ||||
| -rw-r--r-- | src/libterm/win.rs | 2 |
4 files changed, 27 insertions, 20 deletions
diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index d2e3b07ab85..2116b433fce 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -91,7 +91,7 @@ pub fn stderr() -> Option<Box<StderrTerminal>> { #[allow(missing_docs)] pub mod color { /// Number for a terminal color - pub type Color = u16; + pub type Color = u32; pub const BLACK: Color = 0; pub const RED: Color = 1; diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs index f1adc536a3d..918875e792a 100644 --- a/src/libterm/terminfo/mod.rs +++ b/src/libterm/terminfo/mod.rs @@ -24,7 +24,7 @@ pub struct TermInfo { /// Map of capability name to boolean value pub bools: HashMap<String, bool>, /// Map of capability name to numeric value - pub numbers: HashMap<String, u16>, + pub numbers: HashMap<String, u32>, /// Map of capability name to raw (unexpanded) string pub strings: HashMap<String, Vec<u8>>, } @@ -129,7 +129,7 @@ fn cap_for_attr(attr: Attr) -> &'static str { /// A Terminal that knows how many colors it supports, with a reference to its /// parsed Terminfo database record. pub struct TerminfoTerminal<T> { - num_colors: u16, + num_colors: u32, out: T, ti: TermInfo, } diff --git a/src/libterm/terminfo/parser/compiled.rs b/src/libterm/terminfo/parser/compiled.rs index d36adb72c8e..fbc5aebdb2c 100644 --- a/src/libterm/terminfo/parser/compiled.rs +++ b/src/libterm/terminfo/parser/compiled.rs @@ -159,16 +159,16 @@ pub static stringnames: &[&str] = &[ "cbt", "_", "cr", "csr", "tbc", "clear", fn read_le_u16(r: &mut dyn io::Read) -> io::Result<u16> { let mut b = [0; 2]; - let mut amt = 0; - while amt < b.len() { - match r.read(&mut b[amt..])? { - 0 => return Err(io::Error::new(io::ErrorKind::Other, "end of file")), - n => amt += n, - } - } + r.read_exact(&mut b)?; Ok((b[0] as u16) | ((b[1] as u16) << 8)) } +fn read_le_u32(r: &mut dyn io::Read) -> io::Result<u32> { + let mut b = [0; 4]; + r.read_exact(&mut b)?; + Ok((b[0] as u32) | ((b[1] as u32) << 8) | ((b[2] as u32) << 16) | ((b[3] as u32) << 24)) +} + fn read_byte(r: &mut dyn io::Read) -> io::Result<u8> { match r.bytes().next() { Some(s) => s, @@ -194,9 +194,12 @@ pub fn parse(file: &mut dyn io::Read, longnames: bool) -> Result<TermInfo, Strin // Check magic number let magic = t!(read_le_u16(file)); - if magic != 0x011A { - return Err(format!("invalid magic number: expected {:x}, found {:x}", 0x011A, magic)); - } + + let extended = match magic { + 0o0432 => false, + 0o01036 => true, + _ => return Err(format!("invalid magic number, found {:o}", magic)), + }; // According to the spec, these fields must be >= -1 where -1 means that the feature is not // supported. Using 0 instead of -1 works because we skip sections with length 0. @@ -258,11 +261,15 @@ pub fn parse(file: &mut dyn io::Read, longnames: bool) -> Result<TermInfo, Strin t!(read_byte(file)); // compensate for padding } - let numbers_map: HashMap<String, u16> = t! { - (0..numbers_count).filter_map(|i| match read_le_u16(file) { - Ok(0xFFFF) => None, - Ok(n) => Some(Ok((nnames[i].to_string(), n))), - Err(e) => Some(Err(e)) + let numbers_map: HashMap<String, u32> = t! { + (0..numbers_count).filter_map(|i| { + let number = if extended { read_le_u32(file) } else { read_le_u16(file).map(Into::into) }; + + match number { + Ok(0xFFFF) => None, + Ok(n) => Some(Ok((nnames[i].to_string(), n))), + Err(e) => Some(Err(e)) + } }).collect() }; @@ -318,7 +325,7 @@ pub fn msys_terminfo() -> TermInfo { strings.insert("setab".to_string(), b"\x1B[4%p1%dm".to_vec()); let mut numbers = HashMap::new(); - numbers.insert("colors".to_string(), 8u16); + numbers.insert("colors".to_string(), 8); TermInfo { names: vec!["cygwin".to_string()], // msys is a fork of an older cygwin version diff --git a/src/libterm/win.rs b/src/libterm/win.rs index b6c607a3081..c24cf9518aa 100644 --- a/src/libterm/win.rs +++ b/src/libterm/win.rs @@ -89,7 +89,7 @@ fn bits_to_color(bits: u16) -> color::Color { _ => unreachable!(), }; - color | (bits & 0x8) // copy the hi-intensity bit + color | (u32::from(bits) & 0x8) // copy the hi-intensity bit } impl<T: Write + Send + 'static> WinConsole<T> { |
