diff --git a/src/components/contacts.rs b/src/components/contacts.rs index 91907a58..a2028e07 100644 --- a/src/components/contacts.rs +++ b/src/components/contacts.rs @@ -151,6 +151,7 @@ impl Component for ContactManager { clear_area( grid, (upper_left, set_y(bottom_right, get_y(upper_left) + 1)), + Default::default(), ); copy_area_with_break(grid, &self.content, area, ((0, 0), (width - 1, 0))); self.dirty = false; diff --git a/src/components/contacts/contact_list.rs b/src/components/contacts/contact_list.rs index d3156285..66063796 100644 --- a/src/components/contacts/contact_list.rs +++ b/src/components/contacts/contact_list.rs @@ -48,6 +48,7 @@ pub struct ContactList { length: usize, data_columns: DataColumns, initialized: bool, + theme_default: ThemeAttribute, id_positions: Vec, @@ -89,6 +90,7 @@ impl ContactList { id_positions: Vec::new(), mode: ViewMode::List, data_columns: DataColumns::default(), + theme_default: crate::conf::value(context, "theme_default"), initialized: false, dirty: true, movement: None, @@ -156,9 +158,9 @@ impl ContactList { write_string_to_grid( c.name(), &mut self.data_columns.columns[0], - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((0, idx), (min_width.0, idx)), None, ); @@ -166,9 +168,9 @@ impl ContactList { write_string_to_grid( c.email(), &mut self.data_columns.columns[1], - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((0, idx), (min_width.1, idx)), None, ); @@ -176,9 +178,9 @@ impl ContactList { write_string_to_grid( c.url(), &mut self.data_columns.columns[2], - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((0, idx), (min_width.2, idx)), None, ); @@ -190,9 +192,9 @@ impl ContactList { "local" }, &mut self.data_columns.columns[3], - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((0, idx), (min_width.3, idx)), None, ); @@ -209,9 +211,9 @@ impl ContactList { write_string_to_grid( &message, &mut self.data_columns.columns[0], - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((0, 0), (MAX_COLS - 1, 0)), None, ); @@ -221,11 +223,11 @@ impl ContactList { fn highlight_line(&mut self, grid: &mut CellBuffer, area: Area, idx: usize) { /* Reset previously highlighted line */ - let fg_color = Color::Default; + let fg_color = self.theme_default.fg; let bg_color = if idx == self.new_cursor_pos { Color::Byte(246) } else { - Color::Default + self.theme_default.bg }; change_colors(grid, area, fg_color, bg_color); } @@ -234,7 +236,7 @@ impl ContactList { if !self.is_dirty() { return; } - clear_area(grid, area); + clear_area(grid, area, self.theme_default); /* visually divide menu and listing */ area = (area.0, pos_dec(area.1, (1, 0))); let upper_left = upper_left!(area); @@ -271,7 +273,7 @@ impl ContactList { (Color::Byte(15), Color::Byte(233)) } } else { - (Color::Default, Color::Default) + (self.theme_default.fg, self.theme_default.bg) }; let s = format!(" [{}]", context.accounts[a.index].address_book.len()); @@ -348,7 +350,7 @@ impl ContactList { let bottom_right = bottom_right!(area); if self.length == 0 { - clear_area(grid, area); + clear_area(grid, area, self.theme_default); copy_area( grid, &self.data_columns.columns[0], @@ -441,7 +443,7 @@ impl ContactList { width.saturating_sub(self.data_columns.widths[0] + self.data_columns.widths[1] + 4); self.data_columns.widths[2] = remainder / 6; } - clear_area(grid, area); + clear_area(grid, area, self.theme_default); /* Page_no has changed, so draw new page */ let mut x = get_x(upper_left); for i in 0..self.data_columns.columns.len() { @@ -511,6 +513,7 @@ impl ContactList { pos_inc(upper_left, (0, self.length - top_idx + 2)), bottom_right, ), + self.theme_default, ); } self.highlight_line( @@ -552,14 +555,16 @@ impl Component for ContactList { if self.dirty && mid != get_x(upper_left) { if self.show_divider { for i in get_y(upper_left)..=get_y(bottom_right) { - grid[(mid, i)].set_ch(VERT_BOUNDARY); - grid[(mid, i)].set_fg(Color::Default); - grid[(mid, i)].set_bg(Color::Default); + grid[(mid, i)] + .set_ch(VERT_BOUNDARY) + .set_fg(self.theme_default.fg) + .set_bg(self.theme_default.bg); } } else { for i in get_y(upper_left)..=get_y(bottom_right) { - grid[(mid, i)].set_fg(Color::Default); - grid[(mid, i)].set_bg(Color::Default); + grid[(mid, i)] + .set_fg(self.theme_default.fg) + .set_bg(self.theme_default.bg); } } context diff --git a/src/components/mail/compose.rs b/src/components/mail/compose.rs index 1454dba3..4965ac22 100644 --- a/src/components/mail/compose.rs +++ b/src/components/mail/compose.rs @@ -258,7 +258,8 @@ impl Composer { fn draw_attachments(&self, grid: &mut CellBuffer, area: Area, context: &Context) { let attachments_no = self.draft.attachments().len(); - clear_area(grid, area); + let theme_default = crate::conf::value(context, "theme_default"); + clear_area(grid, area, theme_default); if self.sign_mail.is_true() { write_string_to_grid( &format!( @@ -272,9 +273,9 @@ impl Composer { .unwrap_or("default key") ), grid, - Color::Default, - Color::Default, - Attr::Default, + theme_default.fg, + theme_default.bg, + theme_default.attrs, (pos_inc(upper_left!(area), (0, 1)), bottom_right!(area)), None, ); @@ -282,9 +283,9 @@ impl Composer { write_string_to_grid( "☐ don't sign", grid, - Color::Default, - Color::Default, - Attr::Default, + theme_default.fg, + theme_default.bg, + theme_default.attrs, (pos_inc(upper_left!(area), (0, 1)), bottom_right!(area)), None, ); @@ -293,9 +294,9 @@ impl Composer { write_string_to_grid( "no attachments", grid, - Color::Default, - Color::Default, - Attr::Default, + theme_default.fg, + theme_default.bg, + theme_default.attrs, (pos_inc(upper_left!(area), (0, 2)), bottom_right!(area)), None, ); @@ -303,9 +304,9 @@ impl Composer { write_string_to_grid( &format!("{} attachments ", attachments_no), grid, - Color::Default, - Color::Default, - Attr::Default, + theme_default.fg, + theme_default.bg, + theme_default.attrs, (pos_inc(upper_left!(area), (0, 2)), bottom_right!(area)), None, ); @@ -320,9 +321,9 @@ impl Composer { a.raw.len() ), grid, - Color::Default, - Color::Default, - Attr::Default, + theme_default.fg, + theme_default.bg, + theme_default.attrs, (pos_inc(upper_left!(area), (0, 3 + i)), bottom_right!(area)), None, ); @@ -330,9 +331,9 @@ impl Composer { write_string_to_grid( &format!("[{}] {} {} bytes", i, a.content_type(), a.raw.len()), grid, - Color::Default, - Color::Default, - Attr::Default, + theme_default.fg, + theme_default.bg, + theme_default.attrs, (pos_inc(upper_left!(area), (0, 3 + i)), bottom_right!(area)), None, ); @@ -371,6 +372,7 @@ impl Component for Composer { self.initialized = true; } let header_height = self.form.len(); + let theme_default = crate::conf::value(context, "theme_default"); let mid = if width > 80 { let width = width - 80; @@ -379,11 +381,13 @@ impl Component for Composer { if self.dirty { for i in get_y(upper_left)..=get_y(bottom_right) { //set_and_join_box(grid, (mid, i), VERT_BOUNDARY); - grid[(mid, i)].set_fg(Color::Default); - grid[(mid, i)].set_bg(Color::Default); + grid[(mid, i)] + .set_fg(theme_default.fg) + .set_bg(theme_default.bg); //set_and_join_box(grid, (mid + 80, i), VERT_BOUNDARY); - grid[(mid + 80, i)].set_fg(Color::Default); - grid[(mid + 80, i)].set_bg(Color::Default); + grid[(mid + 80, i)] + .set_fg(theme_default.fg) + .set_bg(theme_default.bg); } } mid @@ -425,7 +429,7 @@ impl Component for Composer { ), None, ); - clear_area(grid, ((x, y), (set_y(bottom_right, y)))); + clear_area(grid, ((x, y), (set_y(bottom_right, y))), theme_default); change_colors( grid, ( @@ -442,6 +446,7 @@ impl Component for Composer { pos_dec(upper_left, (0, 1)), set_x(bottom_right, get_x(upper_left) + mid), ), + theme_default, ); clear_area( grid, @@ -452,6 +457,7 @@ impl Component for Composer { ), bottom_right, ), + theme_default, ); } @@ -462,7 +468,7 @@ impl Component for Composer { match embed_pty { EmbedStatus::Running(_, _) => { let mut guard = embed_pty.lock().unwrap(); - clear_area(grid, embed_area); + clear_area(grid, embed_area, theme_default); copy_area( grid, &guard.grid, @@ -475,13 +481,13 @@ impl Component for Composer { return; } EmbedStatus::Stopped(_, _) => { - clear_area(grid, body_area); + clear_area(grid, body_area, theme_default); write_string_to_grid( "process has stopped, press 'e' to re-activate", grid, - Color::Default, - Color::Default, - Attr::Default, + theme_default.fg, + theme_default.bg, + theme_default.attrs, body_area, None, ); @@ -501,7 +507,7 @@ impl Component for Composer { set_y(upper_left!(body_area), get_y(bottom_right!(body_area))), bottom_right!(body_area), ), - Color::Default, + theme_default.fg, Color::Byte(237), ); } else { @@ -511,8 +517,8 @@ impl Component for Composer { set_y(upper_left!(body_area), get_y(bottom_right!(body_area))), bottom_right!(body_area), ), - Color::Default, - Color::Default, + theme_default.fg, + theme_default.bg, ); } diff --git a/src/components/mail/listing.rs b/src/components/mail/listing.rs index 1166c82d..60af1d8f 100644 --- a/src/components/mail/listing.rs +++ b/src/components/mail/listing.rs @@ -366,13 +366,13 @@ impl Component for Listing { if right_component_width == total_cols { if let Err(err) = context.is_online(self.cursor_pos.0) { - clear_area(grid, area); + clear_area(grid, area, self.theme_default); let (x, _) = write_string_to_grid( "offline: ", grid, Color::Byte(243), - Color::Default, - Attr::Default, + self.theme_default.bg, + self.theme_default.attrs, (set_x(upper_left, mid + 1), bottom_right), None, ); @@ -380,8 +380,8 @@ impl Component for Listing { &err.to_string(), grid, Color::Red, - Color::Default, - Attr::Default, + self.theme_default.bg, + self.theme_default.attrs, (set_x(upper_left, x + 1), bottom_right), None, ); @@ -395,13 +395,17 @@ impl Component for Listing { } else { self.draw_menu(grid, (upper_left, (mid, get_y(bottom_right))), context); if let Err(err) = context.is_online(self.cursor_pos.0) { - clear_area(grid, (set_x(upper_left, mid + 1), bottom_right)); + clear_area( + grid, + (set_x(upper_left, mid + 1), bottom_right), + self.theme_default, + ); let (x, _) = write_string_to_grid( "offline: ", grid, Color::Byte(243), - Color::Default, - Attr::Default, + self.theme_default.bg, + self.theme_default.attrs, (set_x(upper_left, mid + 1), bottom_right), None, ); @@ -409,8 +413,8 @@ impl Component for Listing { &err.to_string(), grid, Color::Red, - Color::Default, - Attr::Default, + self.theme_default.bg, + self.theme_default.attrs, (set_x(upper_left, x + 1), bottom_right), None, ); @@ -1069,8 +1073,8 @@ impl Listing { "offline", grid, Color::Byte(243), - Color::Default, - Attr::Default, + self.theme_default.bg, + self.theme_default.attrs, (pos_inc(upper_left, (0, 1)), bottom_right), None, ); diff --git a/src/components/mail/listing/compact.rs b/src/components/mail/listing/compact.rs index 60ebb0d3..f09f6b4b 100644 --- a/src/components/mail/listing/compact.rs +++ b/src/components/mail/listing/compact.rs @@ -133,6 +133,7 @@ impl MailListingTrait for CompactListing { selected: crate::conf::value(context, "mail.listing.compact.selected"), attachment_flag: crate::conf::value(context, "mail.listing.attachment_flag"), thread_snooze_flag: crate::conf::value(context, "mail.listing.thread_snooze_flag"), + theme_default: crate::conf::value(context, "theme_default"), ..self.color_cache }; if std::env::var("NO_COLOR").is_ok() @@ -147,17 +148,24 @@ impl MailListingTrait for CompactListing { match context.accounts[self.cursor_pos.0].status(self.folder_hash) { Ok(()) => {} Err(_) => { + let default_cell = { + let mut ret = Cell::with_char(' '); + ret.set_fg(self.color_cache.theme_default.fg) + .set_bg(self.color_cache.theme_default.bg) + .set_attrs(self.color_cache.theme_default.attrs); + ret + }; let message: String = context.accounts[self.cursor_pos.0][self.folder_hash].to_string(); self.data_columns.columns[0] = - CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context); + CellBuffer::new_with_context(message.len(), 1, default_cell, context); self.length = 0; write_string_to_grid( message.as_str(), &mut self.data_columns.columns[0], - Color::Default, - Color::Default, - Attr::Default, + self.color_cache.theme_default.fg, + self.color_cache.theme_default.bg, + self.color_cache.theme_default.attrs, ((0, 0), (MAX_COLS - 1, 0)), None, ); @@ -283,7 +291,7 @@ impl ListingTrait for CompactListing { let upper_left = upper_left!(area); let bottom_right = bottom_right!(area); if self.length == 0 { - clear_area(grid, area); + clear_area(grid, area, self.color_cache.theme_default); copy_area( grid, &self.data_columns.columns[0], @@ -417,7 +425,7 @@ impl ListingTrait for CompactListing { ); } } - clear_area(grid, area); + clear_area(grid, area, self.color_cache.theme_default); /* Page_no has changed, so draw new page */ let mut x = get_x(upper_left); let mut flag_x = 0; @@ -510,6 +518,7 @@ impl ListingTrait for CompactListing { pos_inc(upper_left, (0, self.length - top_idx)), bottom_right, ), + self.color_cache.theme_default, ); } context.dirty_areas.push_back(area); @@ -563,8 +572,15 @@ impl ListingTrait for CompactListing { self.new_cursor_pos.2 = std::cmp::min(self.filtered_selection.len() - 1, self.cursor_pos.2); } else { + let default_cell = { + let mut ret = Cell::with_char(' '); + ret.set_fg(self.color_cache.theme_default.fg) + .set_bg(self.color_cache.theme_default.bg) + .set_attrs(self.color_cache.theme_default.attrs); + ret + }; self.data_columns.columns[0] = - CellBuffer::new_with_context(0, 0, Cell::with_char(' '), context); + CellBuffer::new_with_context(0, 0, default_cell, context); } self.redraw_list( context, @@ -583,8 +599,15 @@ impl ListingTrait for CompactListing { format!("Failed to search for term {}: {}", &self.filter_term, e), ERROR, ); + let default_cell = { + let mut ret = Cell::with_char(' '); + ret.set_fg(self.color_cache.theme_default.fg) + .set_bg(self.color_cache.theme_default.bg) + .set_attrs(self.color_cache.theme_default.attrs); + ret + }; self.data_columns.columns[0] = - CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context); + CellBuffer::new_with_context(message.len(), 1, default_cell, context); write_string_to_grid( &message, &mut self.data_columns.columns[0], @@ -808,23 +831,30 @@ impl CompactListing { min_width.0 = self.length.saturating_sub(1).to_string().len(); + let default_cell = { + let mut ret = Cell::with_char(' '); + ret.set_fg(self.color_cache.theme_default.fg) + .set_bg(self.color_cache.theme_default.bg) + .set_attrs(self.color_cache.theme_default.attrs); + ret + }; /* index column */ self.data_columns.columns[0] = - CellBuffer::new_with_context(min_width.0, rows.len(), Cell::with_char(' '), context); + CellBuffer::new_with_context(min_width.0, rows.len(), default_cell, context); /* date column */ self.data_columns.columns[1] = - CellBuffer::new_with_context(min_width.1, rows.len(), Cell::with_char(' '), context); + CellBuffer::new_with_context(min_width.1, rows.len(), default_cell, context); /* from column */ self.data_columns.columns[2] = - CellBuffer::new_with_context(min_width.2, rows.len(), Cell::with_char(' '), context); + CellBuffer::new_with_context(min_width.2, rows.len(), default_cell, context); self.data_columns.segment_tree[2] = row_widths.2.into(); /* flags column */ self.data_columns.columns[3] = - CellBuffer::new_with_context(min_width.3, rows.len(), Cell::with_char(' '), context); + CellBuffer::new_with_context(min_width.3, rows.len(), default_cell, context); /* subject column */ self.data_columns.columns[4] = - CellBuffer::new_with_context(min_width.4, rows.len(), Cell::with_char(' '), context); + CellBuffer::new_with_context(min_width.4, rows.len(), default_cell, context); self.data_columns.segment_tree[4] = row_widths.4.into(); for ((idx, (thread, root_env_hash)), strings) in rows { @@ -955,18 +985,14 @@ impl CompactListing { if self.length == 0 && self.filter_term.is_empty() { let mailbox = &account[self.cursor_pos.1]; let message = mailbox.to_string(); - self.data_columns.columns[0] = CellBuffer::new_with_context( - message.len(), - self.length + 1, - Cell::with_char(' '), - context, - ); + self.data_columns.columns[0] = + CellBuffer::new_with_context(message.len(), self.length + 1, default_cell, context); write_string_to_grid( &message, &mut self.data_columns.columns[0], - Color::Default, - Color::Default, - Attr::Default, + self.color_cache.theme_default.fg, + self.color_cache.theme_default.bg, + self.color_cache.theme_default.attrs, ((0, 0), (MAX_COLS - 1, 0)), None, ); @@ -1149,7 +1175,18 @@ impl Component for CompactListing { area, Some(get_x(upper_left)), ); - clear_area(grid, ((x, y), set_y(bottom_right, y))); + let default_cell = { + let mut ret = Cell::with_char(' '); + ret.set_fg(self.color_cache.theme_default.fg) + .set_bg(self.color_cache.theme_default.bg) + .set_attrs(self.color_cache.theme_default.attrs); + ret + }; + for row in grid.bounds_iter(((x, y), set_y(bottom_right, y))) { + for c in row { + grid[c] = default_cell; + } + } context .dirty_areas .push_back((upper_left, set_y(bottom_right, y + 1))); @@ -1187,7 +1224,7 @@ impl Component for CompactListing { } } else { if self.length == 0 && self.dirty { - clear_area(grid, area); + clear_area(grid, area, self.color_cache.theme_default); context.dirty_areas.push_back(area); return; } diff --git a/src/components/mail/listing/conversations.rs b/src/components/mail/listing/conversations.rs index d055dec7..b8d136c7 100644 --- a/src/components/mail/listing/conversations.rs +++ b/src/components/mail/listing/conversations.rs @@ -284,7 +284,7 @@ impl ListingTrait for ConversationsListing { let upper_left = upper_left!(area); let bottom_right = bottom_right!(area); if self.length == 0 { - clear_area(grid, area); + clear_area(grid, area, self.color_cache.theme_default); copy_area( grid, &self.content, @@ -364,7 +364,7 @@ impl ListingTrait for ConversationsListing { self.cursor_pos.2 = self.new_cursor_pos.2; } - clear_area(grid, area); + clear_area(grid, area, self.color_cache.theme_default); /* Page_no has changed, so draw new page */ copy_area( grid, @@ -404,6 +404,7 @@ impl ListingTrait for ConversationsListing { pos_inc(upper_left, (0, 3 * (self.length - top_idx))), bottom_right, ), + self.color_cache.theme_default, ); (0, self.length - top_idx) } else { @@ -1054,6 +1055,7 @@ impl Component for ConversationsListing { pos_inc(upper_left, (width!(area) / 3, 0)), set_x(bottom_right, get_x(upper_left) + width!(area) / 3 + 1), ), + self.color_cache.theme_default, ); context.dirty_areas.push_back(( pos_inc(upper_left, (width!(area) / 3, 0)), @@ -1084,7 +1086,11 @@ impl Component for ConversationsListing { for c in grid.row_iter(x..(get_x(bottom_right) + 1), y) { grid[c] = Cell::default(); } - clear_area(grid, ((x, y), set_y(bottom_right, y))); + clear_area( + grid, + ((x, y), set_y(bottom_right, y)), + self.color_cache.theme_default, + ); context .dirty_areas .push_back((upper_left, set_y(bottom_right, y + 1))); @@ -1125,7 +1131,7 @@ impl Component for ConversationsListing { } if self.unfocused { if self.length == 0 && self.dirty { - clear_area(grid, area); + clear_area(grid, area, self.color_cache.theme_default); context.dirty_areas.push_back(area); return; } diff --git a/src/components/mail/listing/plain.rs b/src/components/mail/listing/plain.rs index 3a0652c8..561124fb 100644 --- a/src/components/mail/listing/plain.rs +++ b/src/components/mail/listing/plain.rs @@ -191,7 +191,7 @@ impl MailListingTrait for PlainListing { if !force && old_cursor_pos == self.new_cursor_pos { self.view.update(temp); } else if self.unfocused { - self.view = MailView::new(temp, None, None); + self.view = MailView::new(temp, None, None, context); } } } @@ -289,7 +289,7 @@ impl ListingTrait for PlainListing { let upper_left = upper_left!(area); let bottom_right = bottom_right!(area); if self.length == 0 { - clear_area(grid, area); + clear_area(grid, area, self.color_cache.theme_default); copy_area( grid, &self.data_columns.columns[0], @@ -405,7 +405,7 @@ impl ListingTrait for PlainListing { self.data_columns.widths[2] = min_col_width; } } - clear_area(grid, area); + clear_area(grid, area, self.color_cache.theme_default); /* Page_no has changed, so draw new page */ let mut x = get_x(upper_left); let mut flag_x = 0; @@ -493,6 +493,7 @@ impl ListingTrait for PlainListing { pos_inc(upper_left, (0, self.length - top_idx)), bottom_right, ), + self.color_cache.theme_default, ); } context.dirty_areas.push_back(area); @@ -995,7 +996,11 @@ impl Component for PlainListing { area, Some(get_x(upper_left)), ); - clear_area(grid, ((x, y), set_y(bottom_right, y))); + clear_area( + grid, + ((x, y), set_y(bottom_right, y)), + self.color_cache.theme_default, + ); context .dirty_areas .push_back((upper_left, set_y(bottom_right, y + 1))); @@ -1031,7 +1036,7 @@ impl Component for PlainListing { } } else { if self.length == 0 && self.dirty { - clear_area(grid, area); + clear_area(grid, area, self.color_cache.theme_default); context.dirty_areas.push_back(area); return; } @@ -1054,7 +1059,7 @@ impl Component for PlainListing { { let env_hash = self.get_env_under_cursor(self.cursor_pos.2, context); let temp = (self.cursor_pos.0, self.cursor_pos.1, env_hash); - self.view = MailView::new(temp, None, None); + self.view = MailView::new(temp, None, None, context); self.unfocused = true; self.dirty = true; return true; diff --git a/src/components/mail/listing/thread.rs b/src/components/mail/listing/thread.rs index 6156a7e4..6efa939c 100644 --- a/src/components/mail/listing/thread.rs +++ b/src/components/mail/listing/thread.rs @@ -37,6 +37,7 @@ pub struct ThreadListing { subsort: (SortField, SortOrder), /// Cache current view. content: CellBuffer, + color_cache: ColorCache, row_updates: SmallVec<[ThreadHash; 8]>, locations: Vec, @@ -219,7 +220,7 @@ impl ListingTrait for ThreadListing { let upper_left = upper_left!(area); let bottom_right = bottom_right!(area); if self.length == 0 { - clear_area(grid, area); + clear_area(grid, area, self.color_cache.theme_default); copy_area(grid, &self.content, area, ((0, 0), (MAX_COLS - 1, 0))); context.dirty_areas.push_back(area); return; @@ -387,6 +388,7 @@ impl ThreadListing { sort: (Default::default(), Default::default()), subsort: (Default::default(), Default::default()), content, + color_cache: ColorCache::default(), row_updates: SmallVec::new(), locations: Vec::new(), dirty: true, @@ -510,7 +512,7 @@ impl Component for ThreadListing { let upper_left = upper_left!(area); let bottom_right = bottom_right!(area); if self.length == 0 && self.dirty { - clear_area(grid, area); + clear_area(grid, area, self.color_cache.theme_default); context.dirty_areas.push_back(area); } @@ -520,7 +522,7 @@ impl Component for ThreadListing { let bottom_entity_rows = (pager_ratio * total_rows) / 100; if bottom_entity_rows > total_rows { - clear_area(grid, area); + clear_area(grid, area, self.color_cache.theme_default); context.dirty_areas.push_back(area); return; } @@ -596,7 +598,7 @@ impl Component for ThreadListing { if let Some(ref mut v) = self.view { v.update(coordinates); } else { - self.view = Some(MailView::new(coordinates, None, None)); + self.view = Some(MailView::new(coordinates, None, None, context)); } self.view.as_mut().unwrap().draw( diff --git a/src/components/mail/status.rs b/src/components/mail/status.rs index 182e664e..de89c0b9 100644 --- a/src/components/mail/status.rs +++ b/src/components/mail/status.rs @@ -131,7 +131,7 @@ impl Component for StatusPanel { std::cmp::min(width.saturating_sub(cols), self.cursor.0), std::cmp::min(height.saturating_sub(rows), self.cursor.1), ); - clear_area(grid, area); + clear_area(grid, area, Default::default()); copy_area( grid, &self.content, @@ -577,7 +577,7 @@ impl Component for AccountStatus { std::cmp::min(width.saturating_sub(cols), self.cursor.0), std::cmp::min(height.saturating_sub(rows), self.cursor.1), ); - clear_area(grid, area); + clear_area(grid, area, Default::default()); copy_area( grid, &self.content, diff --git a/src/components/mail/view.rs b/src/components/mail/view.rs index 29bdc64e..8e76677c 100644 --- a/src/components/mail/view.rs +++ b/src/components/mail/view.rs @@ -89,6 +89,7 @@ pub struct MailView { headers_no: usize, headers_cursor: usize, force_draw_headers: bool, + theme_default: ThemeAttribute, cmd_buf: String, id: ComponentId, @@ -119,6 +120,7 @@ impl MailView { coordinates: (usize, usize, EnvelopeHash), pager: Option, subview: Option>, + context: &Context, ) -> Self { MailView { coordinates, @@ -132,6 +134,8 @@ impl MailView { headers_cursor: 0, force_draw_headers: false, + theme_default: crate::conf::value(context, "mail.view.body"), + cmd_buf: String::with_capacity(4), id: ComponentId::new_v4(), } @@ -373,7 +377,7 @@ impl Component for MailView { let headers = crate::conf::value(context, "mail.view.headers"); if self.mode == ViewMode::Raw { - clear_area(grid, area); + clear_area(grid, area, self.theme_default); context.dirty_areas.push_back(area); get_y(upper_left) } else { @@ -398,7 +402,7 @@ impl Component for MailView { (set_y(upper_left, y), bottom_right), Some(get_x(upper_left)), ); - clear_area(grid, ((_x, _y), (get_x(bottom_right), _y))); + clear_area(grid, ((_x, _y), (get_x(bottom_right), _y)), headers); y = _y + 1; } else { skip_header_ctr -= 1; @@ -440,7 +444,11 @@ impl Component for MailView { let mut x = get_x(upper_left); if let Some(id) = id { if sticky || skip_header_ctr == 0 { - clear_area(grid, (set_y(upper_left, y), set_y(bottom_right, y))); + clear_area( + grid, + (set_y(upper_left, y), set_y(bottom_right, y)), + headers, + ); let (_x, _) = write_string_to_grid( "List-ID: ", grid, @@ -541,7 +549,11 @@ impl Component for MailView { } self.force_draw_headers = false; - clear_area(grid, (set_y(upper_left, y), set_y(bottom_right, y))); + clear_area( + grid, + (set_y(upper_left, y), set_y(bottom_right, y)), + headers, + ); context .dirty_areas .push_back((upper_left, set_y(bottom_right, y + 3))); @@ -575,7 +587,11 @@ impl Component for MailView { Ok(body) => body, Err(e) => { self.dirty = false; - clear_area(grid, (set_y(upper_left, y), bottom_right)); + clear_area( + grid, + (set_y(upper_left, y), bottom_right), + self.theme_default, + ); context .dirty_areas .push_back((set_y(upper_left, y), bottom_right)); diff --git a/src/components/mail/view/envelope.rs b/src/components/mail/view/envelope.rs index d4868a85..187f37d2 100644 --- a/src/components/mail/view/envelope.rs +++ b/src/components/mail/view/envelope.rs @@ -232,7 +232,7 @@ impl Component for EnvelopeView { let envelope: &Envelope = &self.wrapper; if self.mode == ViewMode::Raw { - clear_area(grid, area); + clear_area(grid, area, crate::conf::value(context, "theme_default")); context.dirty_areas.push_back(area); get_y(upper_left) - 1 } else { @@ -306,7 +306,11 @@ impl Component for EnvelopeView { grid[(x, y)].set_bg(Color::Default); grid[(x, y)].set_fg(Color::Default); } - clear_area(grid, (set_y(upper_left, y + 1), set_y(bottom_right, y + 2))); + clear_area( + grid, + (set_y(upper_left, y + 1), set_y(bottom_right, y + 2)), + crate::conf::value(context, "theme_default"), + ); context .dirty_areas .push_back((upper_left, set_y(bottom_right, y + 1))); diff --git a/src/components/mail/view/thread.rs b/src/components/mail/view/thread.rs index 9689297f..1f73c2b0 100644 --- a/src/components/mail/view/thread.rs +++ b/src/components/mail/view/thread.rs @@ -500,7 +500,7 @@ impl ThreadView { if self.dirty || (page_no != prev_page_no) { if page_no != prev_page_no { - clear_area(grid, area); + clear_area(grid, area, crate::conf::value(context, "theme_default")); } let visibles: Vec<&usize> = self .visible_entries @@ -567,6 +567,7 @@ impl ThreadView { upper_left!(area), set_x(bottom_right, get_x(upper_left!(area)) + 1), ), + context, self.cursor_pos, rows, visibles.len(), @@ -620,6 +621,7 @@ impl ThreadView { upper_left!(area), set_x(bottom_right, get_x(upper_left!(area)) + 1), ), + context, self.cursor_pos, rows, visibles.len(), @@ -684,7 +686,11 @@ impl ThreadView { context .dirty_areas .push_back(((mid, y + 1), set_x(bottom_right, mid))); - clear_area(grid, ((mid, y + 1), set_x(bottom_right, mid))); + clear_area( + grid, + ((mid, y + 1), set_x(bottom_right, mid)), + crate::conf::value(context, "theme_default"), + ); y + 2 } else { get_y(upper_left) + 2 @@ -711,7 +717,11 @@ impl ThreadView { .draw(grid, (upper_left, bottom_right), context); } (false, true) => { - clear_area(grid, ((mid + 1, get_y(upper_left) + y - 1), bottom_right)); + clear_area( + grid, + ((mid + 1, get_y(upper_left) + y - 1), bottom_right), + crate::conf::value(context, "theme_default"), + ); self.draw_list(grid, (set_y(upper_left, y), bottom_right), context); } (_, false) => { @@ -728,7 +738,7 @@ impl ThreadView { let bottom_entity_rows = (pager_ratio * total_rows) / 100; if bottom_entity_rows > total_rows { - clear_area(grid, area); + clear_area(grid, area, crate::conf::value(context, "theme_default")); context.dirty_areas.push_back(area); return; } @@ -793,7 +803,11 @@ impl ThreadView { /* if this is the first ever draw, there is nothing on the grid to update so populate it * first */ if !self.initiated { - clear_area(grid, (set_y(upper_left, y), bottom_right)); + clear_area( + grid, + (set_y(upper_left, y), bottom_right), + crate::conf::value(context, "theme_default"), + ); let (width, height) = self.content.size(); match (self.show_mailview, self.show_thread) { diff --git a/src/components/utilities.rs b/src/components/utilities.rs index 4347f8c2..03c04290 100644 --- a/src/components/utilities.rs +++ b/src/components/utilities.rs @@ -179,7 +179,7 @@ impl Component for VSplit { (false, true) => total_cols, (true, false) => 0, (false, false) => { - clear_area(grid, area); + clear_area(grid, area, crate::conf::value(context, "theme_default")); return; } }; @@ -575,7 +575,7 @@ impl Component for Pager { return; } - clear_area(grid, area); + clear_area(grid, area, crate::conf::value(context, "theme_default")); let (width, height) = self.content.size(); let (cols, rows) = (width!(area), height!(area)); self.cursor = ( @@ -808,7 +808,7 @@ impl StatusBar { } fn draw_execute_bar(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) { - clear_area(grid, area); + clear_area(grid, area, crate::conf::value(context, "theme_default")); let (x, y) = write_string_to_grid( self.ex_buffer.as_str(), grid, @@ -938,6 +938,7 @@ impl Component for StatusBar { ), set_y(bottom_right, get_y(bottom_right) - height), ), + context, self.auto_complete.cursor(), hist_height, self.auto_complete.suggestions().len(), @@ -984,7 +985,11 @@ impl Component for StatusBar { } else { self.auto_complete.cursor() }; - clear_area(grid, hist_area); + clear_area( + grid, + hist_area, + crate::conf::value(context, "theme_default"), + ); if hist_height > 0 { change_colors( grid, @@ -1327,11 +1332,11 @@ impl Tabbed { let upper_left = upper_left!(area); let bottom_right = bottom_right!(area); + let tab_bar_attribute = crate::conf::value(context, "tab.bar"); if self.children.is_empty() { - clear_area(grid, area); + clear_area(grid, area, tab_bar_attribute); return; } - let tab_bar_attribute = crate::conf::value(context, "tab.bar"); let tab_unfocused_attribute = crate::conf::value(context, "tab.unfocused"); let mut tab_focused_attribute = crate::conf::value(context, "tab.focused"); if std::env::var("NO_COLOR").is_ok() @@ -1423,6 +1428,7 @@ impl Component for Tabbed { upper_left!(area), set_x(upper_left!(area), get_x(bottom_right!(area))), ), + crate::conf::value(context, "tab.bar"), ); context.dirty_areas.push_back(( upper_left!(area), @@ -1464,7 +1470,7 @@ impl Component for Tabbed { ), ); context.dirty_areas.push_back(area); - clear_area(grid, area); + clear_area(grid, area, crate::conf::value(context, "theme_default")); create_box(grid, area); let area = ( pos_inc(upper_left!(area), (3, 2)), @@ -2327,14 +2333,13 @@ impl fmt::Display for RawBuffer { impl Component for RawBuffer { fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) { if self.dirty { - clear_area(grid, area); let (width, height) = self.buf.size(); let (cols, rows) = (width!(area), height!(area)); self.cursor = ( std::cmp::min(width.saturating_sub(cols), self.cursor.0), std::cmp::min(height.saturating_sub(rows), self.cursor.1), ); - clear_area(grid, area); + clear_area(grid, area, crate::conf::value(context, "theme_default")); copy_area( grid, &self.buf, diff --git a/src/components/utilities/widgets.rs b/src/components/utilities/widgets.rs index 79fd1385..62c548e2 100644 --- a/src/components/utilities/widgets.rs +++ b/src/components/utilities/widgets.rs @@ -388,15 +388,16 @@ impl Component for FormWidget { let bottom_right = bottom_right!(area); if self.dirty { + let label_attrs = crate::conf::value(context, "widgets.form.label"); clear_area( grid, ( upper_left, set_y(bottom_right, get_y(upper_left) + self.layout.len()), ), + label_attrs, ); - let label_attrs = crate::conf::value(context, "widgets.form.label"); for (i, k) in self.layout.iter().enumerate() { let v = self.fields.get_mut(k).unwrap(); /* Write field label */ @@ -472,6 +473,7 @@ impl Component for FormWidget { pos_inc(upper_left, (0, length)), set_y(bottom_right, length + 2 + get_y(upper_left)), ), + label_attrs, ); if !self.hide_buttons { self.buttons.draw( @@ -489,6 +491,7 @@ impl Component for FormWidget { set_y(upper_left, length + 4 + get_y(upper_left)), bottom_right, ), + label_attrs, ); self.dirty = false; } @@ -642,9 +645,9 @@ impl Component for ButtonWidget where T: std::fmt::Debug + Default + Send, { - fn draw(&mut self, grid: &mut CellBuffer, area: Area, _context: &mut Context) { + fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) { if self.dirty { - clear_area(grid, area); + clear_area(grid, area, crate::conf::value(context, "theme_default")); let upper_left = upper_left!(area); let mut len = 0; @@ -927,6 +930,7 @@ impl ScrollBar { self, grid: &mut CellBuffer, area: Area, + context: &Context, pos: usize, visible_rows: usize, length: usize, @@ -941,7 +945,7 @@ impl ScrollBar { if self.show_arrows { height -= height; } - clear_area(grid, area); + clear_area(grid, area, crate::conf::value(context, "theme_default")); let visible_ratio: f32 = (std::cmp::min(visible_rows, length) as f32) / (length as f32); let scrollbar_height = std::cmp::max((visible_ratio * (height as f32)) as usize, 1); diff --git a/src/terminal/cells.rs b/src/terminal/cells.rs index 6d88bcd3..6f6c8c53 100644 --- a/src/terminal/cells.rs +++ b/src/terminal/cells.rs @@ -1595,10 +1595,13 @@ pub fn copy_area(grid_dest: &mut CellBuffer, grid_src: &CellBuffer, dest: Area, src_x = get_x(upper_left!(src)); src_y += 1; if src_y > get_y(bottom_right!(src)) { - clear_area( - grid_dest, - ((get_x(upper_left!(dest)), y + 1), bottom_right!(dest)), - ); + for row in + grid_dest.bounds_iter(((get_x(upper_left!(dest)), y + 1), bottom_right!(dest))) + { + for c in row { + grid_dest[c].set_ch(' '); + } + } ret.1 = y; break; } @@ -1747,13 +1750,17 @@ pub fn write_string_to_grid( } /// Completely clear an `Area` with an empty char and the terminal's default colors. -pub fn clear_area(grid: &mut CellBuffer, area: Area) { +pub fn clear_area(grid: &mut CellBuffer, area: Area, attributes: crate::conf::ThemeAttribute) { if !is_valid_area!(area) { return; } for row in grid.bounds_iter(area) { for c in row { grid[c] = Cell::default(); + grid[c] + .set_fg(attributes.fg) + .set_bg(attributes.bg) + .set_attrs(attributes.attrs); } } } @@ -2364,21 +2371,13 @@ pub mod boundaries { if !grid.ascii_drawing { for x in get_x(upper_left)..get_x(bottom_right) { - grid[(x, get_y(upper_left))] - .set_ch(HORZ_BOUNDARY) - .set_fg(Color::Byte(240)); - grid[(x, get_y(bottom_right))] - .set_ch(HORZ_BOUNDARY) - .set_fg(Color::Byte(240)); + grid[(x, get_y(upper_left))].set_ch(HORZ_BOUNDARY); + grid[(x, get_y(bottom_right))].set_ch(HORZ_BOUNDARY); } for y in get_y(upper_left)..get_y(bottom_right) { - grid[(get_x(upper_left), y)] - .set_ch(VERT_BOUNDARY) - .set_fg(Color::Byte(240)); - grid[(get_x(bottom_right), y)] - .set_ch(VERT_BOUNDARY) - .set_fg(Color::Byte(240)); + grid[(get_x(upper_left), y)].set_ch(VERT_BOUNDARY); + grid[(get_x(bottom_right), y)].set_ch(VERT_BOUNDARY); } set_and_join_box(grid, upper_left, BoxBoundary::Horizontal); set_and_join_box( diff --git a/src/terminal/embed/grid.rs b/src/terminal/embed/grid.rs index 32477ea1..70b56845 100644 --- a/src/terminal/embed/grid.rs +++ b/src/terminal/embed/grid.rs @@ -483,6 +483,7 @@ impl EmbedGrid { terminal_size.1.saturating_sub(1), ), ), + Default::default(), ); debug!("{}", EscCode::from((&(*state), byte))); *state = State::Normal; @@ -565,7 +566,11 @@ impl EmbedGrid { } } debug!("{}", EscCode::from((&(*state), byte))); - clear_area(grid, ((0, 0), pos_dec(*terminal_size, (1, 1)))); + clear_area( + grid, + ((0, 0), pos_dec(*terminal_size, (1, 1))), + Default::default(), + ); *state = State::Normal; } (b'J', State::Csi1(ref buf)) if buf == b"0" => { @@ -586,6 +591,7 @@ impl EmbedGrid { terminal_size.1.saturating_sub(1), ), ), + Default::default(), ); debug!("{}", EscCode::from((&(*state), byte))); *state = State::Normal; @@ -602,6 +608,7 @@ impl EmbedGrid { cursor.1.saturating_sub(1) + scroll_region.top, ), ), + Default::default(), ); debug!("{}", EscCode::from((&(*state), byte))); *state = State::Normal; @@ -609,7 +616,11 @@ impl EmbedGrid { (b'J', State::Csi1(ref buf)) if buf == b"2" => { /* Erase in Display (ED), VT100.*/ /* Erase All */ - clear_area(grid, ((0, 0), pos_dec(*terminal_size, (1, 1)))); + clear_area( + grid, + ((0, 0), pos_dec(*terminal_size, (1, 1))), + Default::default(), + ); debug!("{}", EscCode::from((&(*state), byte))); *state = State::Normal; }