From 5129612f9f34cee3dc3c0fceaae17f13f6aa688a Mon Sep 17 00:00:00 2001 From: Zacharias-Brohn Date: Thu, 9 Apr 2026 23:49:32 +0200 Subject: [PATCH] terminal is fixed and im not happy about it --- src/main.rs | 12 ++++++++++-- src/renderer.rs | 19 ++++++++++--------- src/terminal.rs | 47 +++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2dee859..08d721d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2536,8 +2536,16 @@ impl App { } } - text.push_str(line.trim_end()); - if content_row < end.row { + let is_wrapped = + row_cells.first().map(|c| c.wrapped).unwrap_or(false); + + if is_wrapped { + text.push_str(&line); + } else { + text.push_str(line.trim_end()); + } + + if content_row < end.row && !is_wrapped { text.push('\n'); } } diff --git a/src/renderer.rs b/src/renderer.rs index 55a9061..2a6efd9 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -13,7 +13,7 @@ use crate::gpu_types::{ EdgeGlowUniforms, QuadParams, StatuslineParams, ATLAS_SIZE, MAX_ATLAS_LAYERS, ATLAS_BPP, MAX_EDGE_GLOWS, COLOR_TYPE_DEFAULT, COLOR_TYPE_INDEXED, COLOR_TYPE_RGB, - ATTR_BOLD, ATTR_ITALIC, ATTR_STRIKE, + ATTR_BOLD, ATTR_ITALIC, ATTR_STRIKE, ATTR_REVERSE, COLORED_GLYPH_FLAG, CURSOR_SPRITE_BEAM, CURSOR_SPRITE_UNDERLINE, CURSOR_SPRITE_HOLLOW, DECORATION_SPRITE_STRIKETHROUGH, DECORATION_SPRITE_UNDERLINE, DECORATION_SPRITE_DOUBLE_UNDERLINE, @@ -1718,11 +1718,12 @@ impl Renderer { /// Pack cell attributes into u32 format for GPU. /// underline_style: 0=none, 1=single, 2=double, 3=curly, 4=dotted, 5=dashed #[inline] - fn pack_attrs(bold: bool, italic: bool, underline_style: u8, strikethrough: bool) -> u32 { + fn pack_attrs(bold: bool, italic: bool, underline_style: u8, strikethrough: bool, reverse: bool) -> u32 { let mut attrs = (underline_style as u32) & 0x7; // 3 bits for decoration type if bold { attrs |= ATTR_BOLD; } if italic { attrs |= ATTR_ITALIC; } if strikethrough { attrs |= ATTR_STRIKE; } + if reverse { attrs |= ATTR_REVERSE; } attrs } @@ -1899,7 +1900,7 @@ impl Renderer { bg: Self::pack_color(&cell.bg_color), decoration_fg: 0, sprite_idx: 0, // No glyph for continuation - attrs: Self::pack_attrs(cell.bold, cell.italic, cell.underline_style, cell.strikethrough), + attrs: Self::pack_attrs(cell.bold, cell.italic, cell.underline_style, cell.strikethrough, cell.reverse), }; col += 1; continue; @@ -1972,7 +1973,7 @@ impl Renderer { bg: Self::pack_color(¤t_cell.bg_color), decoration_fg: 0, sprite_idx: final_sprite_idx, - attrs: Self::pack_attrs(cell.bold, cell.italic, cell.underline_style, cell.strikethrough), + attrs: Self::pack_attrs(cell.bold, cell.italic, cell.underline_style, cell.strikethrough, cell.reverse), }; } @@ -2023,7 +2024,7 @@ impl Renderer { bg: Self::pack_color(¤t_cell.bg_color), decoration_fg: 0, sprite_idx: sprite_idx | COLORED_GLYPH_FLAG, - attrs: Self::pack_attrs(cell.bold, cell.italic, cell.underline_style, cell.strikethrough), + attrs: Self::pack_attrs(cell.bold, cell.italic, cell.underline_style, cell.strikethrough, cell.reverse), }; } @@ -2052,7 +2053,7 @@ impl Renderer { bg: Self::pack_color(&cell.bg_color), decoration_fg: 0, sprite_idx, - attrs: Self::pack_attrs(cell.bold, cell.italic, cell.underline_style, cell.strikethrough), + attrs: Self::pack_attrs(cell.bold, cell.italic, cell.underline_style, cell.strikethrough, cell.reverse), }; col += 1; } @@ -2628,7 +2629,7 @@ impl Renderer { let fg = Self::pack_statusline_color(*fg_color); let bg = Self::pack_statusline_color(*bg_color); let style = if *bold { FontStyle::Bold } else { FontStyle::Regular }; - let attrs = Self::pack_attrs(*bold, false, 0, false); + let attrs = Self::pack_attrs(*bold, false, 0, false, false); let (sprite_idx, is_colored) = if *c == ' ' || *c == '\0' { (0, false) @@ -2677,7 +2678,7 @@ impl Renderer { let fg = Self::pack_statusline_color(fg_color); let bg = Self::pack_statusline_color(bg_color); let style = if bold { FontStyle::Bold } else { FontStyle::Regular }; - let attrs = Self::pack_attrs(bold, false, 0, false); + let attrs = Self::pack_attrs(bold, false, 0, false, false); let (sprite_idx, is_colored) = if c == ' ' || c == '\0' { (0, false) @@ -2715,7 +2716,7 @@ impl Renderer { for component in section.components.iter() { let component_fg = Self::pack_statusline_color(component.fg); let style = if component.bold { FontStyle::Bold } else { FontStyle::Regular }; - let attrs = Self::pack_attrs(component.bold, false, 0, false); + let attrs = Self::pack_attrs(component.bold, false, 0, false, false); // Process characters with lookahead for multi-cell symbols let chars: Vec = component.text.chars().collect(); diff --git a/src/terminal.rs b/src/terminal.rs index 2fd0aaf..07d6a86 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -38,6 +38,7 @@ pub struct Cell { pub bg_color: Color, pub bold: bool, pub italic: bool, + pub reverse: bool, /// Underline style: 0=none, 1=single, 2=double, 3=curly, 4=dotted, 5=dashed pub underline_style: u8, /// Strikethrough decoration @@ -45,6 +46,8 @@ pub struct Cell { /// If true, this cell is the continuation of a wide (double-width) character. /// The actual character is stored in the previous cell. pub wide_continuation: bool, + /// Indicates if the line wrapped after this cell. + pub wrapped: bool, } impl Default for Cell { @@ -55,9 +58,11 @@ impl Default for Cell { bg_color: Color::Default, bold: false, italic: false, + reverse: false, underline_style: 0, strikethrough: false, wide_continuation: false, + wrapped: false, } } } @@ -269,6 +274,7 @@ struct SavedCursor { strikethrough: bool, origin_mode: bool, auto_wrap: bool, + reverse: bool, } /// Alternate screen buffer state. @@ -509,6 +515,8 @@ pub struct Terminal { pub current_underline_style: u8, /// Current strikethrough state. pub current_strikethrough: bool, + /// Current reverse video state. + pub current_reverse: bool, /// Whether the terminal content has changed. pub dirty: bool, /// Bitmap of dirty lines - bit N is set if line N needs redrawing. @@ -594,6 +602,7 @@ impl Terminal { current_italic: false, current_underline_style: 0, current_strikethrough: false, + current_reverse: false, dirty: true, dirty_lines: [!0u64; 4], // All lines dirty initially scroll_top: 0, @@ -697,9 +706,11 @@ impl Terminal { bg_color: self.current_bg, bold: self.current_bold, italic: self.current_italic, + reverse: self.current_reverse, underline_style: self.current_underline_style, strikethrough: self.current_strikethrough, wide_continuation, + wrapped: false, } } @@ -741,9 +752,11 @@ impl Terminal { bg_color: self.current_bg, bold: false, italic: false, + reverse: false, underline_style: 0, strikethrough: false, wide_continuation: false, + wrapped: false, } } @@ -1459,6 +1472,9 @@ impl Handler for Terminal { // Handle wrap if self.cursor_col >= self.cols { if self.auto_wrap { + if self.cols > 0 { + self.grid[grid_row][0].wrapped = true; + } self.cursor_col = 0; self.advance_row(); cached_row = self.cursor_row; @@ -1970,6 +1986,10 @@ impl Handler for Terminal { // Handle wrap if self.cursor_col >= self.cols { if self.auto_wrap { + let gr = self.line_map[self.cursor_row]; + if self.cols > 0 { + self.grid[gr][0].wrapped = true; + } self.cursor_col = 0; self.advance_row(); self.mark_line_dirty(self.cursor_row); @@ -2167,15 +2187,17 @@ impl Handler for Terminal { italic: self.current_italic, underline_style: self.current_underline_style, strikethrough: self.current_strikethrough, + reverse: self.current_reverse, origin_mode: self.origin_mode, auto_wrap: self.auto_wrap, }; log::debug!( - "ESC 7: Cursor saved at ({}, {}), origin_mode={}, auto_wrap={}", + "ESC 7: Cursor saved at ({}, {}), origin_mode={}, auto_wrap={}, reverse={}", self.cursor_col, self.cursor_row, self.origin_mode, - self.auto_wrap + self.auto_wrap, + self.current_reverse ); } @@ -2190,14 +2212,16 @@ impl Handler for Terminal { self.current_italic = self.saved_cursor.italic; self.current_underline_style = self.saved_cursor.underline_style; self.current_strikethrough = self.saved_cursor.strikethrough; + self.current_reverse = self.saved_cursor.reverse; self.origin_mode = self.saved_cursor.origin_mode; self.auto_wrap = self.saved_cursor.auto_wrap; log::debug!( - "ESC 8: Cursor restored to ({}, {}), origin_mode={}, auto_wrap={}", + "ESC 8: Cursor restored to ({}, {}), origin_mode={}, auto_wrap={}, reverse={}", self.cursor_col, self.cursor_row, self.origin_mode, - self.auto_wrap + self.auto_wrap, + self.current_reverse ); } @@ -2285,9 +2309,11 @@ impl Handler for Terminal { bg_color: Color::Default, bold: false, italic: false, + reverse: false, underline_style: 0, strikethrough: false, wide_continuation: false, + wrapped: false, }; } self.mark_line_dirty(visual_row); @@ -2324,6 +2350,10 @@ impl Terminal { // Check if we need to wrap before printing if self.cursor_col >= self.cols { if self.auto_wrap { + let grid_row = self.line_map[self.cursor_row]; + if self.cols > 0 { + self.grid[grid_row][0].wrapped = true; + } self.cursor_col = 0; self.advance_row(); } else { @@ -2338,6 +2368,7 @@ impl Terminal { // Write a space in the last column and wrap let grid_row = self.line_map[self.cursor_row]; self.grid[grid_row][self.cursor_col] = Cell::default(); + self.grid[grid_row][0].wrapped = true; self.cursor_col = 0; self.advance_row(); } else { @@ -2460,15 +2491,14 @@ impl Terminal { self.current_underline_style = 1; } } - 7 => std::mem::swap(&mut self.current_fg, &mut self.current_bg), + 7 => self.current_reverse = true, 9 => self.current_strikethrough = true, 21 => self.current_underline_style = 2, // Double underline 22 => self.current_bold = false, 23 => self.current_italic = false, 24 => self.current_underline_style = 0, - 27 => { - std::mem::swap(&mut self.current_fg, &mut self.current_bg) - } + 27 => self.current_reverse = false, + 28 => self.current_reverse = false, 29 => self.current_strikethrough = false, // Standard foreground colors (30-37) 30..=37 => self.current_fg = Color::Indexed((code - 30) as u8), @@ -2517,6 +2547,7 @@ impl Terminal { self.current_italic = false; self.current_underline_style = 0; self.current_strikethrough = false; + self.current_reverse = false; } /// Handle Kitty keyboard protocol CSI sequences.