diff --git a/Cargo.lock b/Cargo.lock index d14530d8..dba08302 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ dependencies = [ "serde_derive 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "vte 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "vte 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1098,7 +1098,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "vte" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "utf8parse 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1344,7 +1344,7 @@ dependencies = [ "checksum utf8parse 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a15ea87f3194a3a454c78d79082b4f5e85f6956ddb6cb86bbfbe4892aa3c0323" "checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum vte 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0221cd88a06e81dea3ef4dcad02a881b19c03c48b6e6a34875cb301ec8de78d9" +"checksum vte 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8abafc42c98c6e9f8ee68f3b55daf55d2af7047052facec9f6ac08f4e2addfa1" "checksum walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c66c0b9792f0a765345452775f3adbd28dde9d33f30d13e5dcc5ae17cf6f3780" "checksum wayland-client 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ced3094c157b5cc0a08d40530e1a627d9f88b9a436971338d2646439128a559e" "checksum wayland-kbd 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "73bc10e84c1da90777beffecd24742baea17564ffc2a9918af41871c748eb050" diff --git a/Cargo.toml b/Cargo.toml index b93206c2..f7bbb161 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ parking_lot = { version = "0.3.1", features = ["nightly"] } serde = "0.9" serde_yaml = "0.6" serde_derive = "0.9" -vte = "0.2.1" +vte = "0.2.2" mio = "0.6" serde_json = "0.9" copypasta = { path = "./copypasta" } diff --git a/src/ansi.rs b/src/ansi.rs index c9f7e268..b1a70130 100644 --- a/src/ansi.rs +++ b/src/ansi.rs @@ -462,6 +462,12 @@ pub enum CharsetIndex { G3, } +impl Default for CharsetIndex { + fn default() -> Self { + CharsetIndex::G0 + } +} + /// Standard or common character sets which can be designated as G0-G3 #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum StandardCharset { @@ -469,6 +475,12 @@ pub enum StandardCharset { SpecialCharacterAndLineDrawing, } +impl Default for StandardCharset { + fn default() -> Self { + StandardCharset::Ascii + } +} + impl<'a, H, W> vte::Perform for Performer<'a, H, W> where H: Handler + TermInfo + 'a, W: io::Write + 'a diff --git a/src/term/mod.rs b/src/term/mod.rs index 92242071..a69d3f66 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -271,14 +271,9 @@ impl CharsetMapping for StandardCharset { } } +#[derive(Default, Copy, Clone)] struct Charsets([StandardCharset; 4]); -impl Charsets { - fn new() -> Charsets { - Charsets([StandardCharset::Ascii; 4]) - } -} - impl Index for Charsets { type Output = StandardCharset; fn index(&self, index: CharsetIndex) -> &StandardCharset { @@ -292,6 +287,18 @@ impl IndexMut for Charsets { } } +#[derive(Default, Copy, Clone)] +pub struct Cursor { + /// The location of this cursor + point: Point, + + /// Template cell when using this cursor + template: Cell, + + /// Currently configured graphic character sets + charsets: Charsets, +} + pub struct Term { /// The grid grid: Grid, @@ -315,13 +322,7 @@ pub struct Term { alt: bool, /// The cursor - cursor: Point, - - /// Alt cursor - alt_cursor: Point, - - /// Currently configured graphic character sets - charsets: Charsets, + cursor: Cursor, /// The graphic character set, out of `charsets`, which ASCII is currently /// being mapped to @@ -339,15 +340,18 @@ pub struct Term { /// Size size_info: SizeInfo, - /// Template cell - template_cell: Cell, - /// Empty cell empty_cell: Cell, pub dirty: bool, custom_cursor_colors: bool, + + /// Saved cursor from main grid + cursor_save: Cursor, + + /// Saved cursor from alt grid + cursor_save_alt: Cursor, } /// Terminal size info @@ -422,15 +426,14 @@ impl Term { grid: grid, alt_grid: alt, alt: false, - cursor: Point::default(), - alt_cursor: Point::default(), - active_charset: CharsetIndex::G0, - charsets: Charsets::new(), + active_charset: Default::default(), + cursor: Default::default(), + cursor_save: Default::default(), + cursor_save_alt: Default::default(), tabs: tabs, mode: Default::default(), scroll_region: scroll_region, size_info: size, - template_cell: template, empty_cell: template, custom_cursor_colors: config.custom_cursor_colors(), } @@ -590,7 +593,13 @@ impl Term { /// background color. Cells with an alternate background color are /// considered renderable as are cells with any text content. pub fn renderable_cells(&mut self, selection: &Selection) -> RenderableCellsIter { - RenderableCellsIter::new(&mut self.grid, &self.cursor, self.mode, selection, self.custom_cursor_colors) + RenderableCellsIter::new( + &mut self.grid, + &self.cursor.point, + self.mode, + selection, + self.custom_cursor_colors + ) } /// Resize terminal to new dimensions @@ -628,22 +637,22 @@ impl Term { self.scroll_region = Line(0)..self.grid.num_lines(); // Scroll up to keep cursor in terminal - if self.cursor.line >= num_lines { - let lines = self.cursor.line - num_lines + 1; + if self.cursor.point.line >= num_lines { + let lines = self.cursor.point.line - num_lines + 1; self.scroll_up(lines); - self.cursor.line -= lines; + self.cursor.point.line -= lines; } println!("num_cols, num_lines = {}, {}", num_cols, num_lines); // Resize grids to new size - let template = self.template_cell; + let template = self.cursor.template; self.grid.resize(num_lines, num_cols, &template); self.alt_grid.resize(num_lines, num_cols, &template); // Ensure cursor is in-bounds - self.cursor.line = limit(self.cursor.line, Line(0), num_lines - 1); - self.cursor.col = limit(self.cursor.col, Column(0), num_cols - 1); + self.cursor.point.line = limit(self.cursor.point.line, Line(0), num_lines - 1); + self.cursor.point.col = limit(self.cursor.point.col, Column(0), num_cols - 1); // Recreate tabs list self.tabs = IndexRange::from(Column(0)..self.grid.num_cols()) @@ -655,8 +664,8 @@ impl Term { if num_lines > old_lines { // Make sure bottom of terminal is clear let template = self.empty_cell; - self.grid.clear_region((self.cursor.line + 1).., |c| c.reset(&template)); - self.alt_grid.clear_region((self.cursor.line + 1).., |c| c.reset(&template)); + self.grid.clear_region((self.cursor.point.line + 1).., |c| c.reset(&template)); + self.alt_grid.clear_region((self.cursor.point.line + 1).., |c| c.reset(&template)); } // Reset scrolling region to new size @@ -676,7 +685,6 @@ impl Term { pub fn swap_alt(&mut self) { self.alt = !self.alt; ::std::mem::swap(&mut self.grid, &mut self.alt_grid); - ::std::mem::swap(&mut self.cursor, &mut self.alt_cursor); if self.alt { let template = self.empty_cell; @@ -782,32 +790,32 @@ impl ansi::Handler for Term { { let location = Point { - line: self.cursor.line, - col: self.cursor.col + line: self.cursor.point.line, + col: self.cursor.point.col }; let cell = &mut self.grid[&location]; cell.flags.insert(cell::WRAPLINE); } - if (self.cursor.line + 1) >= self.scroll_region.end { + if (self.cursor.point.line + 1) >= self.scroll_region.end { self.linefeed(); } else { - self.cursor.line += 1; + self.cursor.point.line += 1; } - self.cursor.col = Column(0); + self.cursor.point.col = Column(0); self.input_needs_wrap = false; } { - let cell = &mut self.grid[&self.cursor]; - *cell = self.template_cell; - cell.c = self.charsets[self.active_charset].map(c); + let cell = &mut self.grid[&self.cursor.point]; + *cell = self.cursor.template; + cell.c = self.cursor.charsets[self.active_charset].map(c); } - if (self.cursor.col + 1) < self.grid.num_cols() { - self.cursor.col += 1; + if (self.cursor.point.col + 1) < self.grid.num_cols() { + self.cursor.point.col += 1; } else { self.input_needs_wrap = true; } @@ -817,22 +825,22 @@ impl ansi::Handler for Term { #[inline] fn goto(&mut self, line: Line, col: Column) { trace!("goto: line={}, col={}", line, col); - self.cursor.line = min(line, self.grid.num_lines() - 1); - self.cursor.col = min(col, self.grid.num_cols() - 1); + self.cursor.point.line = min(line, self.grid.num_lines() - 1); + self.cursor.point.col = min(col, self.grid.num_cols() - 1); self.input_needs_wrap = false; } #[inline] fn goto_line(&mut self, line: Line) { trace!("goto_line: {}", line); - self.cursor.line = min(line, self.grid.num_lines() - 1); + self.cursor.point.line = min(line, self.grid.num_lines() - 1); self.input_needs_wrap = false; } #[inline] fn goto_col(&mut self, col: Column) { trace!("goto_col: {}", col); - self.cursor.col = min(col, self.grid.num_cols() - 1); + self.cursor.point.col = min(col, self.grid.num_cols() - 1); self.input_needs_wrap = false; } @@ -840,13 +848,13 @@ impl ansi::Handler for Term { fn insert_blank(&mut self, count: Column) { // Ensure inserting within terminal bounds - let count = min(count, self.size_info.cols() - self.cursor.col); + let count = min(count, self.size_info.cols() - self.cursor.point.col); - let source = self.cursor.col; - let destination = self.cursor.col + count; + let source = self.cursor.point.col; + let destination = self.cursor.point.col + count; let num_cells = (self.size_info.cols() - destination).0; - let line = self.cursor.line; // borrowck + let line = self.cursor.point.line; // borrowck let line = &mut self.grid[line]; unsafe { @@ -867,27 +875,27 @@ impl ansi::Handler for Term { #[inline] fn move_up(&mut self, lines: Line) { trace!("move_up: {}", lines); - let lines = min(self.cursor.line, lines); - self.cursor.line = min(self.cursor.line - lines, self.grid.num_lines() -1); + let lines = min(self.cursor.point.line, lines); + self.cursor.point.line = min(self.cursor.point.line - lines, self.grid.num_lines() -1); } #[inline] fn move_down(&mut self, lines: Line) { trace!("move_down: {}", lines); - self.cursor.line = min(self.cursor.line + lines, self.grid.num_lines() - 1); + self.cursor.point.line = min(self.cursor.point.line + lines, self.grid.num_lines() - 1); } #[inline] fn move_forward(&mut self, cols: Column) { trace!("move_forward: {}", cols); - self.cursor.col = min(self.cursor.col + cols, self.grid.num_cols() - 1); + self.cursor.point.col = min(self.cursor.point.col + cols, self.grid.num_cols() - 1); self.input_needs_wrap = false; } #[inline] fn move_backward(&mut self, cols: Column) { trace!("move_backward: {}", cols); - self.cursor.col -= min(self.cursor.col, cols); + self.cursor.point.col -= min(self.cursor.point.col, cols); self.input_needs_wrap = false; } @@ -910,7 +918,7 @@ impl ansi::Handler for Term { fn put_tab(&mut self, mut count: i64) { trace!("put_tab: {}", count); - let mut col = self.cursor.col; + let mut col = self.cursor.point.col; while col < self.grid.num_cols() && count != 0 { count -= 1; loop { @@ -921,7 +929,7 @@ impl ansi::Handler for Term { } } - self.cursor.col = col; + self.cursor.point.col = col; self.input_needs_wrap = false; } @@ -929,8 +937,8 @@ impl ansi::Handler for Term { #[inline] fn backspace(&mut self) { trace!("backspace"); - if self.cursor.col > Column(0) { - self.cursor.col -= 1; + if self.cursor.point.col > Column(0) { + self.cursor.point.col -= 1; self.input_needs_wrap = false; } } @@ -939,7 +947,7 @@ impl ansi::Handler for Term { #[inline] fn carriage_return(&mut self) { trace!("carriage_return"); - self.cursor.col = Column(0); + self.cursor.point.col = Column(0); self.input_needs_wrap = false; } @@ -947,10 +955,10 @@ impl ansi::Handler for Term { #[inline] fn linefeed(&mut self) { trace!("linefeed"); - if (self.cursor.line + 1) >= self.scroll_region.end { + if (self.cursor.point.line + 1) >= self.scroll_region.end { self.scroll_up(Line(1)); } else { - self.cursor.line += 1; + self.cursor.point.line += 1; } } @@ -990,8 +998,8 @@ impl ansi::Handler for Term { #[inline] fn insert_blank_lines(&mut self, lines: Line) { trace!("insert_blank_lines: {}", lines); - if self.scroll_region.contains_(self.cursor.line) { - let origin = self.cursor.line; + if self.scroll_region.contains_(self.cursor.point.line) { + let origin = self.cursor.point.line; self.scroll_down_relative(origin, lines); } } @@ -999,19 +1007,19 @@ impl ansi::Handler for Term { #[inline] fn delete_lines(&mut self, lines: Line) { trace!("delete_lines: {}", lines); - if self.scroll_region.contains_(self.cursor.line) { - let origin = self.cursor.line; + if self.scroll_region.contains_(self.cursor.point.line) { + let origin = self.cursor.point.line; self.scroll_up_relative(origin, lines); } } #[inline] fn erase_chars(&mut self, count: Column) { - trace!("erase_chars: {}, {}", count, self.cursor.col); - let start = self.cursor.col; + trace!("erase_chars: {}, {}", count, self.cursor.point.col); + let start = self.cursor.point.col; let end = min(start + count, self.grid.num_cols() - 1); - let row = &mut self.grid[self.cursor.line]; + let row = &mut self.grid[self.cursor.point.line]; let template = self.empty_cell; for c in &mut row[start..end] { c.reset(&template); @@ -1023,11 +1031,11 @@ impl ansi::Handler for Term { // Ensure deleting within terminal bounds let count = min(count, self.size_info.cols()); - let start = self.cursor.col; + let start = self.cursor.point.col; let end = min(start + count, self.grid.num_cols() - 1); let n = (self.size_info.cols() - end).0; - let line = self.cursor.line; // borrowck + let line = self.cursor.point.line; // borrowck let line = &mut self.grid[line]; unsafe { @@ -1058,35 +1066,49 @@ impl ansi::Handler for Term { #[inline] fn save_cursor_position(&mut self) { - trace!("[unimplemented] save_cursor_position"); + trace!("CursorSave"); + let mut holder = if self.alt { + &mut self.cursor_save_alt + } else { + &mut self.cursor_save + }; + + *holder = self.cursor; } #[inline] fn restore_cursor_position(&mut self) { - trace!("[unimplemented] restore_cursor_position"); + trace!("CursorRestore"); + let holder = if self.alt { + &self.cursor_save_alt + } else { + &self.cursor_save + }; + + self.cursor = *holder; } #[inline] fn clear_line(&mut self, mode: ansi::LineClearMode) { trace!("clear_line: {:?}", mode); let template = self.empty_cell; - let col = self.cursor.col; + let col = self.cursor.point.col; match mode { ansi::LineClearMode::Right => { - let row = &mut self.grid[self.cursor.line]; + let row = &mut self.grid[self.cursor.point.line]; for cell in &mut row[col..] { cell.reset(&template); } }, ansi::LineClearMode::Left => { - let row = &mut self.grid[self.cursor.line]; + let row = &mut self.grid[self.cursor.point.line]; for cell in &mut row[..(col + 1)] { cell.reset(&template); } }, ansi::LineClearMode::All => { - let row = &mut self.grid[self.cursor.line]; + let row = &mut self.grid[self.cursor.point.line]; for cell in &mut row[..] { cell.reset(&template); } @@ -1100,7 +1122,7 @@ impl ansi::Handler for Term { let template = self.empty_cell; match mode { ansi::ClearMode::Below => { - for row in &mut self.grid[self.cursor.line..] { + for row in &mut self.grid[self.cursor.point.line..] { for cell in row { cell.reset(&template); } @@ -1129,10 +1151,10 @@ impl ansi::Handler for Term { fn reverse_index(&mut self) { trace!("reverse_index"); // if cursor is at the top - if self.cursor.line == self.scroll_region.start { + if self.cursor.point.line == self.scroll_region.start { self.scroll_down(Line(1)); } else { - self.cursor.line -= min(self.cursor.line, Line(1)); + self.cursor.point.line -= min(self.cursor.point.line, Line(1)); } } @@ -1141,21 +1163,21 @@ impl ansi::Handler for Term { fn terminal_attribute(&mut self, attr: Attr) { trace!("Set Attribute: {:?}", attr); match attr { - Attr::Foreground(color) => self.template_cell.fg = color, - Attr::Background(color) => self.template_cell.bg = color, + Attr::Foreground(color) => self.cursor.template.fg = color, + Attr::Background(color) => self.cursor.template.bg = color, Attr::Reset => { - self.template_cell.fg = Color::Named(NamedColor::Foreground); - self.template_cell.bg = Color::Named(NamedColor::Background); - self.template_cell.flags = cell::Flags::empty(); + self.cursor.template.fg = Color::Named(NamedColor::Foreground); + self.cursor.template.bg = Color::Named(NamedColor::Background); + self.cursor.template.flags = cell::Flags::empty(); }, - Attr::Reverse => self.template_cell.flags.insert(cell::INVERSE), - Attr::CancelReverse => self.template_cell.flags.remove(cell::INVERSE), - Attr::Bold => self.template_cell.flags.insert(cell::BOLD), - Attr::CancelBoldDim => self.template_cell.flags.remove(cell::BOLD), - Attr::Italic => self.template_cell.flags.insert(cell::ITALIC), - Attr::CancelItalic => self.template_cell.flags.remove(cell::ITALIC), - Attr::Underscore => self.template_cell.flags.insert(cell::UNDERLINE), - Attr::CancelUnderline => self.template_cell.flags.remove(cell::UNDERLINE), + Attr::Reverse => self.cursor.template.flags.insert(cell::INVERSE), + Attr::CancelReverse => self.cursor.template.flags.remove(cell::INVERSE), + Attr::Bold => self.cursor.template.flags.insert(cell::BOLD), + Attr::CancelBoldDim => self.cursor.template.flags.remove(cell::BOLD), + Attr::Italic => self.cursor.template.flags.insert(cell::ITALIC), + Attr::CancelItalic => self.cursor.template.flags.remove(cell::ITALIC), + Attr::Underscore => self.cursor.template.flags.insert(cell::UNDERLINE), + Attr::CancelUnderline => self.cursor.template.flags.remove(cell::UNDERLINE), _ => { debug!("Term got unhandled attr: {:?}", attr); } @@ -1166,7 +1188,10 @@ impl ansi::Handler for Term { fn set_mode(&mut self, mode: ansi::Mode) { trace!("set_mode: {:?}", mode); match mode { - ansi::Mode::SwapScreenAndSetRestoreCursor => self.swap_alt(), + ansi::Mode::SwapScreenAndSetRestoreCursor => { + self.save_cursor_position(); + self.swap_alt(); + }, ansi::Mode::ShowCursor => self.mode.insert(mode::SHOW_CURSOR), ansi::Mode::CursorKeys => self.mode.insert(mode::APP_CURSOR), ansi::Mode::ReportMouseClicks => self.mode.insert(mode::MOUSE_REPORT_CLICK), @@ -1184,7 +1209,10 @@ impl ansi::Handler for Term { fn unset_mode(&mut self,mode: ansi::Mode) { trace!("unset_mode: {:?}", mode); match mode { - ansi::Mode::SwapScreenAndSetRestoreCursor => self.swap_alt(), + ansi::Mode::SwapScreenAndSetRestoreCursor => { + self.restore_cursor_position(); + self.swap_alt(); + }, ansi::Mode::ShowCursor => self.mode.remove(mode::SHOW_CURSOR), ansi::Mode::CursorKeys => self.mode.remove(mode::APP_CURSOR), ansi::Mode::ReportMouseClicks => self.mode.remove(mode::MOUSE_REPORT_CLICK), @@ -1221,7 +1249,7 @@ impl ansi::Handler for Term { #[inline] fn configure_charset(&mut self, index: CharsetIndex, charset: StandardCharset) { trace!("designate {:?} character set as {:?}", index, charset); - self.charsets[index] = charset; + self.cursor.charsets[index] = charset; } #[inline]