Skip to content

Commit

Permalink
win: Emulate reverse, secure, and standout
Browse files Browse the repository at this point in the history
 * As cmr's comment says, COMMON_LVB_REVERSE_VIDEO and COMMON_LVB_UNDERSCORE
   are not usable. There is a mode flag (ENABLE_LVB_GRID_WORLDWIDE) that is
   supposed to make them work, but:
    1. COMMON_LVB_REVERSE_VIDEO works on Windows 10 regardless of whether
       this flag is set.
    2. I couldn't get COMMON_LVB_UNDERSCORE to work no matter what. Maybe
       it's this bug (microsoft/terminal#47).
       Maybe not, I don't know.
    3. Since setting ENABLE_LVB_GRID_WORLDWIDE fails on older Windows
       versions (tested on Windows 7), and since Windows 10 has the flag
       ENABLE_VIRTUAL_TERMINAL_PROCESSING which enables xterm-level
       ANSI compatibility. This whole exercise is pointless.

 * This commit adds simple emulations for three attributes:
    1. Reverse: simply reverse fg and bg.
    2. Secure: set fg = bg.
    3. Standout: set BACKGROUND_INTENSITY.

 This should improve the situation slightly on older versions of Windows.
 For Windows 10, we should take advantage of
 ENABLE_VIRTUAL_TERMINAL_PROCESSING. One approach of doing so will be
 shared in a following commit/PR.

Signed-off-by: Mohammad AlSaleh <CE.Mohammad.AlSaleh@gmail.com>
  • Loading branch information
MoSal committed Aug 22, 2018
1 parent 432cf48 commit be4b272
Showing 1 changed file with 51 additions and 6 deletions.
57 changes: 51 additions & 6 deletions src/win.rs
Expand Up @@ -24,7 +24,7 @@ use Result;
use Terminal;
use color;

use win::winapi::um::wincon::{SetConsoleCursorPosition, SetConsoleTextAttribute};
use win::winapi::um::wincon::{SetConsoleCursorPosition, SetConsoleTextAttribute, BACKGROUND_INTENSITY};
use win::winapi::um::wincon::{FillConsoleOutputCharacterW, GetConsoleScreenBufferInfo, COORD};
use win::winapi::um::wincon::FillConsoleOutputAttribute;
use win::winapi::shared::minwindef::{DWORD, WORD};
Expand All @@ -40,6 +40,9 @@ pub struct WinConsoleInfo {
def_background: color::Color,
foreground: color::Color,
background: color::Color,
reverse: bool,
secure: bool,
standout: bool,
}

/// A Terminal implementation which uses the Win32 Console API.
Expand Down Expand Up @@ -161,6 +164,9 @@ impl WinConsoleInfo {
def_background: bg,
foreground: fg,
background: bg,
reverse: false,
secure: false,
standout: false,
})
}
}
Expand All @@ -169,9 +175,28 @@ impl<T: Write + Send> WinConsole<T> {
fn apply(&mut self) -> io::Result<()> {
let out = conout()?;
let _unused = self.buf.flush();

let (mut fg, bg) = if self.info.reverse {
(self.info.background, self.info.foreground)
} else {
(self.info.foreground, self.info.background)
};

if self.info.secure {
fg = bg;
}

let mut accum: WORD = 0;
accum |= color_to_bits(self.info.foreground);
accum |= color_to_bits(self.info.background) << 4;

accum |= color_to_bits(fg);
accum |= color_to_bits(bg) << 4;

if self.info.standout {
accum |= BACKGROUND_INTENSITY;
} else {
accum &= BACKGROUND_INTENSITY ^ 0xFF;
}

unsafe {
SetConsoleTextAttribute(*out, accum);
}
Expand Down Expand Up @@ -233,22 +258,42 @@ impl<T: Write + Send> Terminal for WinConsole<T> {
self.apply()?;
Ok(())
}
Attr::Reverse => {
self.info.reverse = true;
self.apply()?;
Ok(())
}
Attr::Secure => {
self.info.secure = true;
self.apply()?;
Ok(())
}
Attr::Standout(v) => {
self.info.standout = v;
self.apply()?;
Ok(())
}
_ => Err(Error::NotSupported),
}
}

fn supports_attr(&self, attr: Attr) -> bool {
// it claims support for underscore and reverse video, but I can't get
// it to do anything -cmr
match attr {
Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => true,
Attr::ForegroundColor(_)
| Attr::BackgroundColor(_)
| Attr::Standout(_)
| Attr::Reverse
| Attr::Secure => true,
_ => false,
}
}

fn reset(&mut self) -> Result<()> {
self.info.foreground = self.info.def_foreground;
self.info.background = self.info.def_background;
self.info.reverse = false;
self.info.secure = false;
self.info.standout = false;
self.apply()?;

Ok(())
Expand Down

0 comments on commit be4b272

Please sign in to comment.