summaryrefslogtreecommitdiff
path: root/alacritty_terminal/src/term/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'alacritty_terminal/src/term/mod.rs')
-rw-r--r--alacritty_terminal/src/term/mod.rs146
1 files changed, 85 insertions, 61 deletions
diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs
index 4aafde1f..acd14e7e 100644
--- a/alacritty_terminal/src/term/mod.rs
+++ b/alacritty_terminal/src/term/mod.rs
@@ -69,7 +69,9 @@ impl<T> Search for Term<T> {
let last_col = self.grid.num_cols() - Column(1);
while let Some(cell) = iter.prev() {
- if self.semantic_escape_chars.contains(cell.c) {
+ if !cell.flags.intersects(Flags::WIDE_CHAR | Flags::WIDE_CHAR_SPACER)
+ && self.semantic_escape_chars.contains(cell.c)
+ {
break;
}
@@ -91,7 +93,9 @@ impl<T> Search for Term<T> {
let last_col = self.grid.num_cols() - 1;
while let Some(cell) = iter.next() {
- if self.semantic_escape_chars.contains(cell.c) {
+ if !cell.flags.intersects(Flags::WIDE_CHAR | Flags::WIDE_CHAR_SPACER)
+ && self.semantic_escape_chars.contains(cell.c)
+ {
break;
}
@@ -1181,6 +1185,42 @@ impl<T> Term<T> {
pub fn clipboard(&mut self) -> &mut Clipboard {
&mut self.clipboard
}
+
+ /// Insert a linebreak at the current cursor position.
+ #[inline]
+ fn wrapline(&mut self)
+ where
+ T: EventListener,
+ {
+ if !self.mode.contains(TermMode::LINE_WRAP) {
+ return;
+ }
+
+ trace!("Wrapping input");
+
+ self.grid[&self.cursor.point].flags.insert(Flags::WRAPLINE);
+
+ if (self.cursor.point.line + 1) >= self.scroll_region.end {
+ self.linefeed();
+ } else {
+ self.cursor.point.line += 1;
+ }
+
+ self.cursor.point.col = Column(0);
+ self.input_needs_wrap = false;
+ }
+
+ /// Write `c` to the cell at the cursor position.
+ #[inline]
+ fn write_at_cursor(&mut self, c: char) -> &mut Cell
+ where
+ T: EventListener,
+ {
+ let cell = &mut self.grid[&self.cursor.point];
+ *cell = self.cursor.template;
+ cell.c = self.cursor.charsets[self.active_charset].map(c);
+ cell
+ }
}
impl<T> TermInfo for Term<T> {
@@ -1195,7 +1235,7 @@ impl<T> TermInfo for Term<T> {
}
}
-impl<T: EventListener> ansi::Handler for Term<T> {
+impl<T: EventListener> Handler for Term<T> {
#[inline]
#[cfg(not(windows))]
fn set_title(&mut self, title: &str) {
@@ -1238,77 +1278,61 @@ impl<T: EventListener> ansi::Handler for Term<T> {
self.scroll_display(Scroll::Bottom);
}
- if self.input_needs_wrap {
- if !self.mode.contains(TermMode::LINE_WRAP) {
- return;
+ // Number of cells the char will occupy
+ let width = match c.width() {
+ Some(width) => width,
+ None => return,
+ };
+
+ // Handle zero-width characters
+ if width == 0 {
+ let mut col = self.cursor.point.col.0.saturating_sub(1);
+ let line = self.cursor.point.line;
+ if self.grid[line][Column(col)].flags.contains(Flags::WIDE_CHAR_SPACER) {
+ col = col.saturating_sub(1);
}
+ self.grid[line][Column(col)].push_extra(c);
+ return;
+ }
- trace!("Wrapping input");
+ // Move cursor to next line
+ if self.input_needs_wrap {
+ self.wrapline();
+ }
- {
- let location = Point { line: self.cursor.point.line, col: self.cursor.point.col };
+ let num_cols = self.grid.num_cols();
- let cell = &mut self.grid[&location];
- cell.flags.insert(Flags::WRAPLINE);
- }
+ // If in insert mode, first shift cells to the right
+ if self.mode.contains(TermMode::INSERT) && self.cursor.point.col + width < num_cols {
+ let line = self.cursor.point.line;
+ let col = self.cursor.point.col;
+ let line = &mut self.grid[line];
- if (self.cursor.point.line + 1) >= self.scroll_region.end {
- self.linefeed();
- } else {
- self.cursor.point.line += 1;
+ let src = line[col..].as_ptr();
+ let dst = line[(col + width)..].as_mut_ptr();
+ unsafe {
+ ptr::copy(src, dst, (num_cols - col - width).0);
}
-
- self.cursor.point.col = Column(0);
- self.input_needs_wrap = false;
}
- // Number of cells the char will occupy
- if let Some(width) = c.width() {
- let num_cols = self.grid.num_cols();
-
- // If in insert mode, first shift cells to the right.
- if self.mode.contains(TermMode::INSERT) && self.cursor.point.col + width < num_cols {
- let line = self.cursor.point.line;
- let col = self.cursor.point.col;
- let line = &mut self.grid[line];
-
- let src = line[col..].as_ptr();
- let dst = line[(col + width)..].as_mut_ptr();
- unsafe {
- // memmove
- ptr::copy(src, dst, (num_cols - col - width).0);
- }
+ if width == 1 {
+ self.write_at_cursor(c);
+ } else {
+ // Insert extra placeholder before wide char if glyph doesn't fit in this row anymore
+ if self.cursor.point.col + 1 >= num_cols {
+ self.write_at_cursor(' ').flags.insert(Flags::WIDE_CHAR_SPACER);
+ self.wrapline();
}
- // Handle zero-width characters
- if width == 0 {
- let mut col = self.cursor.point.col.0.saturating_sub(1);
- let line = self.cursor.point.line;
- if self.grid[line][Column(col)].flags.contains(Flags::WIDE_CHAR_SPACER) {
- col = col.saturating_sub(1);
- }
- self.grid[line][Column(col)].push_extra(c);
- return;
- }
+ // Write full width glyph to current cursor cell
+ self.write_at_cursor(c).flags.insert(Flags::WIDE_CHAR);
- let cell = &mut self.grid[&self.cursor.point];
- *cell = self.cursor.template;
- cell.c = self.cursor.charsets[self.active_charset].map(c);
-
- // Handle wide chars
- if width == 2 {
- cell.flags.insert(Flags::WIDE_CHAR);
-
- if self.cursor.point.col + 1 < num_cols {
- self.cursor.point.col += 1;
- let spacer = &mut self.grid[&self.cursor.point];
- *spacer = self.cursor.template;
- spacer.flags.insert(Flags::WIDE_CHAR_SPACER);
- }
- }
+ // Write spacer to cell following the wide glyph
+ self.cursor.point.col += 1;
+ self.write_at_cursor(' ').flags.insert(Flags::WIDE_CHAR_SPACER);
}
- if (self.cursor.point.col + 1) < self.grid.num_cols() {
+ if self.cursor.point.col + 1 < num_cols {
self.cursor.point.col += 1;
} else {
self.input_needs_wrap = true;