diff --git a/TODO.md b/TODO.md index 0de744b0e944eefab5ff4dc281077d9e516a2838..97c6da47502cd885d780168f31df8fcc1bdf0e38 100644 --- a/TODO.md +++ b/TODO.md @@ -67,5 +67,5 @@ Unix Windows - [ ] is_atty is not working with cygwin/msys -- [ ] UTF-16 surrogate pair +- [X] UTF-16 surrogate pair - [ ] handle ansi escape code (https://docs.rs/console/0.6.1/console/fn.strip_ansi_codes.html ?) diff --git a/src/tty/windows.rs b/src/tty/windows.rs index 4ec42098be063e49d909ba219a100612769f17ad..0bdfc2f6ba518388ca47fde81d106db5241b7771 100644 --- a/src/tty/windows.rs +++ b/src/tty/windows.rs @@ -87,13 +87,13 @@ impl RawMode for Mode { /// Console input reader pub struct ConsoleRawReader { handle: HANDLE, - buf: Option<u16>, + buf: [u16; 2], } impl ConsoleRawReader { pub fn new() -> Result<ConsoleRawReader> { let handle = try!(get_std_handle(STDIN_FILENO)); - Ok(ConsoleRawReader { handle, buf: None }) + Ok(ConsoleRawReader { handle, buf: [0; 2] }) } } @@ -105,6 +105,7 @@ impl RawReader for ConsoleRawReader { let mut rec: wincon::INPUT_RECORD = unsafe { mem::zeroed() }; let mut count = 0; + let mut surrogate = false; loop { // TODO GetNumberOfConsoleInputEvents check!(consoleapi::ReadConsoleInputW( @@ -192,9 +193,19 @@ impl RawReader for ConsoleRawReader { } else if utf16 == 27 { return Ok(KeyPress::Esc); } else { - // TODO How to support surrogate pair ? - self.buf = Some(utf16); - let orc = decode_utf16(self).next(); + if utf16 >= 0xD800 && utf16 < 0xDC00 { + surrogate = true; + self.buf[0] = utf16; + continue; + } + let buf = if surrogate { + self.buf[1] = utf16; + &self.buf[..] + } else { + self.buf[0] = utf16; + &self.buf[..1] + }; + let orc = decode_utf16(buf.iter().cloned()).next(); if orc.is_none() { return Err(error::ReadlineError::Eof); } @@ -209,16 +220,6 @@ impl RawReader for ConsoleRawReader { } } -impl Iterator for ConsoleRawReader { - type Item = u16; - - fn next(&mut self) -> Option<u16> { - let buf = self.buf; - self.buf = None; - buf - } -} - pub struct ConsoleRenderer { out: Stdout, handle: HANDLE,