Skip to content

Commit 1153403

Browse files
authored
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` (#60349), but that's blocked for the foreseeable future.
2 parents c91515f + f9a5746 commit 1153403

File tree

4 files changed

+27
-20
lines changed

4 files changed

+27
-20
lines changed

src/libterm/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ pub fn stderr() -> Option<Box<StderrTerminal>> {
9191
#[allow(missing_docs)]
9292
pub mod color {
9393
/// Number for a terminal color
94-
pub type Color = u16;
94+
pub type Color = u32;
9595

9696
pub const BLACK: Color = 0;
9797
pub const RED: Color = 1;

src/libterm/terminfo/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub struct TermInfo {
2424
/// Map of capability name to boolean value
2525
pub bools: HashMap<String, bool>,
2626
/// Map of capability name to numeric value
27-
pub numbers: HashMap<String, u16>,
27+
pub numbers: HashMap<String, u32>,
2828
/// Map of capability name to raw (unexpanded) string
2929
pub strings: HashMap<String, Vec<u8>>,
3030
}
@@ -129,7 +129,7 @@ fn cap_for_attr(attr: Attr) -> &'static str {
129129
/// A Terminal that knows how many colors it supports, with a reference to its
130130
/// parsed Terminfo database record.
131131
pub struct TerminfoTerminal<T> {
132-
num_colors: u16,
132+
num_colors: u32,
133133
out: T,
134134
ti: TermInfo,
135135
}

src/libterm/terminfo/parser/compiled.rs

+23-16
Original file line numberDiff line numberDiff line change
@@ -159,16 +159,16 @@ pub static stringnames: &[&str] = &[ "cbt", "_", "cr", "csr", "tbc", "clear",
159159

160160
fn read_le_u16(r: &mut dyn io::Read) -> io::Result<u16> {
161161
let mut b = [0; 2];
162-
let mut amt = 0;
163-
while amt < b.len() {
164-
match r.read(&mut b[amt..])? {
165-
0 => return Err(io::Error::new(io::ErrorKind::Other, "end of file")),
166-
n => amt += n,
167-
}
168-
}
162+
r.read_exact(&mut b)?;
169163
Ok((b[0] as u16) | ((b[1] as u16) << 8))
170164
}
171165

166+
fn read_le_u32(r: &mut dyn io::Read) -> io::Result<u32> {
167+
let mut b = [0; 4];
168+
r.read_exact(&mut b)?;
169+
Ok((b[0] as u32) | ((b[1] as u32) << 8) | ((b[2] as u32) << 16) | ((b[3] as u32) << 24))
170+
}
171+
172172
fn read_byte(r: &mut dyn io::Read) -> io::Result<u8> {
173173
match r.bytes().next() {
174174
Some(s) => s,
@@ -194,9 +194,12 @@ pub fn parse(file: &mut dyn io::Read, longnames: bool) -> Result<TermInfo, Strin
194194

195195
// Check magic number
196196
let magic = t!(read_le_u16(file));
197-
if magic != 0x011A {
198-
return Err(format!("invalid magic number: expected {:x}, found {:x}", 0x011A, magic));
199-
}
197+
198+
let extended = match magic {
199+
0o0432 => false,
200+
0o01036 => true,
201+
_ => return Err(format!("invalid magic number, found {:o}", magic)),
202+
};
200203

201204
// According to the spec, these fields must be >= -1 where -1 means that the feature is not
202205
// 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
258261
t!(read_byte(file)); // compensate for padding
259262
}
260263

261-
let numbers_map: HashMap<String, u16> = t! {
262-
(0..numbers_count).filter_map(|i| match read_le_u16(file) {
263-
Ok(0xFFFF) => None,
264-
Ok(n) => Some(Ok((nnames[i].to_string(), n))),
265-
Err(e) => Some(Err(e))
264+
let numbers_map: HashMap<String, u32> = t! {
265+
(0..numbers_count).filter_map(|i| {
266+
let number = if extended { read_le_u32(file) } else { read_le_u16(file).map(Into::into) };
267+
268+
match number {
269+
Ok(0xFFFF) => None,
270+
Ok(n) => Some(Ok((nnames[i].to_string(), n))),
271+
Err(e) => Some(Err(e))
272+
}
266273
}).collect()
267274
};
268275

@@ -318,7 +325,7 @@ pub fn msys_terminfo() -> TermInfo {
318325
strings.insert("setab".to_string(), b"\x1B[4%p1%dm".to_vec());
319326

320327
let mut numbers = HashMap::new();
321-
numbers.insert("colors".to_string(), 8u16);
328+
numbers.insert("colors".to_string(), 8);
322329

323330
TermInfo {
324331
names: vec!["cygwin".to_string()], // msys is a fork of an older cygwin version

src/libterm/win.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ fn bits_to_color(bits: u16) -> color::Color {
8989
_ => unreachable!(),
9090
};
9191

92-
color | (bits & 0x8) // copy the hi-intensity bit
92+
color | (u32::from(bits) & 0x8) // copy the hi-intensity bit
9393
}
9494

9595
impl<T: Write + Send + 'static> WinConsole<T> {

0 commit comments

Comments
 (0)