about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2020-01-14 14:02:20 +0900
committerGitHub <noreply@github.com>2020-01-14 14:02:20 +0900
commit974b69927b2ca665a414a477717d40320cc7fbbd (patch)
treeb7e9f3b25e40a1d7270c732bec1ecd771c111caa
parent9e47ddd399fab91af5eb804727f9f1400a140753 (diff)
parentf9a57469612ba457fb7865aef944bf05d7664516 (diff)
downloadrust-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.rs2
-rw-r--r--src/libterm/terminfo/mod.rs4
-rw-r--r--src/libterm/terminfo/parser/compiled.rs39
-rw-r--r--src/libterm/win.rs2
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> {