Skip to content

Commit

Permalink
Rollup merge of rust-lang#68036 - euclio:libterm-ncurses6-fix, r=KodrAus
Browse files Browse the repository at this point in the history
libterm: parse extended terminfo format

Fixes rust-lang#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` (rust-lang#60349), but that's blocked for the foreseeable future.
  • Loading branch information
Dylan-DPC authored Jan 13, 2020
2 parents c91515f + f9a5746 commit 1153403
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/libterm/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions src/libterm/terminfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>>,
}
Expand Down Expand Up @@ -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,
}
Expand Down
39 changes: 23 additions & 16 deletions src/libterm/terminfo/parser/compiled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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.
Expand Down Expand Up @@ -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()
};

Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/libterm/win.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down

0 comments on commit 1153403

Please sign in to comment.