From bc319843621d24fce736db22c9c25083d30c1ef5 Mon Sep 17 00:00:00 2001
From: daa84 <daa84@inbox.ru>
Date: Tue, 5 Sep 2017 17:03:20 +0300
Subject: [PATCH] Fix text coloring

---
 src/color.rs         | 51 +++++++++++++++++++++++++++++++-------------
 src/shell.rs         | 19 ++++++-----------
 src/ui_model/line.rs | 11 +++++++++-
 3 files changed, 52 insertions(+), 29 deletions(-)

diff --git a/src/color.rs b/src/color.rs
index f7c868f..b2de55b 100644
--- a/src/color.rs
+++ b/src/color.rs
@@ -1,14 +1,15 @@
+use std;
 use gdk;
 use ui_model::Cell;
 
-#[derive(Clone, PartialEq)]
+#[derive(Clone, PartialEq, Debug)]
 pub struct Color(pub f64, pub f64, pub f64);
 
 pub const COLOR_BLACK: Color = Color(0.0, 0.0, 0.0);
 pub const COLOR_WHITE: Color = Color(1.0, 1.0, 1.0);
 pub const COLOR_RED: Color = Color(1.0, 0.0, 0.0);
 
-impl <'a> Into<gdk::RGBA> for &'a Color {
+impl<'a> Into<gdk::RGBA> for &'a Color {
     fn into(self) -> gdk::RGBA {
         gdk::RGBA {
             red: self.0,
@@ -19,6 +20,23 @@ impl <'a> Into<gdk::RGBA> for &'a Color {
     }
 }
 
+impl Color {
+    pub fn from_indexed_color(indexed_color: u64) -> Color {
+        let r = ((indexed_color >> 16) & 0xff) as f64;
+        let g = ((indexed_color >> 8) & 0xff) as f64;
+        let b = (indexed_color & 0xff) as f64;
+        Color(r / 255.0, g / 255.0, b / 255.0)
+    }
+
+    pub fn to_u16(&self) -> (u16, u16, u16) {
+        (
+            (std::u16::MAX as f64 * self.0) as u16,
+            (std::u16::MAX as f64 * self.1) as u16,
+            (std::u16::MAX as f64 * self.2) as u16,
+        )
+    }
+}
+
 pub struct ColorModel {
     pub bg_color: Color,
     pub fg_color: Color,
@@ -27,7 +45,7 @@ pub struct ColorModel {
 
 impl ColorModel {
     pub fn new() -> Self {
-        ColorModel { 
+        ColorModel {
             bg_color: COLOR_BLACK,
             fg_color: COLOR_WHITE,
             sp_color: COLOR_RED,
@@ -35,21 +53,24 @@ impl ColorModel {
     }
 
     pub fn cell_colors<'a>(&'a self, cell: &'a Cell) -> (&'a Color, &'a Color) {
-        let bg = if let Some(ref bg) = cell.attrs.background {
-            bg
+        if !cell.attrs.reverse {
+            (
+                cell.attrs.background.as_ref().unwrap_or(&self.bg_color),
+                cell.attrs.foreground.as_ref().unwrap_or(&self.fg_color),
+            )
         } else {
-            &self.bg_color
-        };
-        let fg = if let Some(ref fg) = cell.attrs.foreground {
-            fg
-        } else {
-            &self.fg_color
-        };
+            (
+                cell.attrs.foreground.as_ref().unwrap_or(&self.fg_color),
+                cell.attrs.background.as_ref().unwrap_or(&self.bg_color),
+            )
+        }
+    }
 
-        if cell.attrs.reverse {
-            (fg, bg)
+    pub fn cell_fg<'a>(&'a self, cell: &'a Cell) -> Option<&'a Color> {
+        if !cell.attrs.reverse {
+            cell.attrs.foreground.as_ref()
         } else {
-            (bg, fg)
+            cell.attrs.background.as_ref().or(Some(&self.bg_color))
         }
     }
 }
diff --git a/src/shell.rs b/src/shell.rs
index f6685f8..82712d0 100644
--- a/src/shell.rs
+++ b/src/shell.rs
@@ -985,13 +985,6 @@ fn request_window_resize(state: &mut State) {
     }
 }
 
-fn split_color(indexed_color: u64) -> Color {
-    let r = ((indexed_color >> 16) & 0xff) as f64;
-    let g = ((indexed_color >> 8) & 0xff) as f64;
-    let b = (indexed_color & 0xff) as f64;
-    Color(r / 255.0, g / 255.0, b / 255.0)
-}
-
 fn try_nvim_resize(state: &Arc<UiMutex<State>>) {
     let mut state_ref = state.borrow_mut();
 
@@ -1074,17 +1067,17 @@ impl RedrawEvents for State {
                 match key {
                     "foreground" => {
                         if let Some(fg) = val.as_u64() {
-                            model_attrs.foreground = Some(split_color(fg));
+                            model_attrs.foreground = Some(Color::from_indexed_color(fg));
                         }
                     }
                     "background" => {
                         if let Some(bg) = val.as_u64() {
-                            model_attrs.background = Some(split_color(bg));
+                            model_attrs.background = Some(Color::from_indexed_color(bg));
                         }
                     }
                     "special" => {
                         if let Some(bg) = val.as_u64() {
-                            model_attrs.special = Some(split_color(bg));
+                            model_attrs.special = Some(Color::from_indexed_color(bg));
                         }
                     }
                     "reverse" => model_attrs.reverse = true,
@@ -1105,7 +1098,7 @@ impl RedrawEvents for State {
 
     fn on_update_bg(&mut self, bg: i64) -> RepaintMode {
         if bg >= 0 {
-            self.color_model.bg_color = split_color(bg as u64);
+            self.color_model.bg_color = Color::from_indexed_color(bg as u64);
         } else {
             self.color_model.bg_color = COLOR_BLACK;
         }
@@ -1114,7 +1107,7 @@ impl RedrawEvents for State {
 
     fn on_update_fg(&mut self, fg: i64) -> RepaintMode {
         if fg >= 0 {
-            self.color_model.fg_color = split_color(fg as u64);
+            self.color_model.fg_color = Color::from_indexed_color(fg as u64);
         } else {
             self.color_model.fg_color = COLOR_WHITE;
         }
@@ -1123,7 +1116,7 @@ impl RedrawEvents for State {
 
     fn on_update_sp(&mut self, sp: i64) -> RepaintMode {
         if sp >= 0 {
-            self.color_model.sp_color = split_color(sp as u64);
+            self.color_model.sp_color = Color::from_indexed_color(sp as u64);
         } else {
             self.color_model.sp_color = COLOR_RED;
         }
diff --git a/src/ui_model/line.rs b/src/ui_model/line.rs
index cff25bb..42a107c 100644
--- a/src/ui_model/line.rs
+++ b/src/ui_model/line.rs
@@ -314,12 +314,21 @@ fn insert_attrs(
         attr.set_end_index(end_idx);
         attr_list.insert(attr);
     }
+
     if cell.attrs.bold {
         let mut attr = pango::Attribute::new_weight(pango::Weight::Bold).unwrap();
         attr.set_start_index(start_idx);
         attr.set_end_index(end_idx);
         attr_list.insert(attr);
     }
+
+    if let Some(fg) = color_model.cell_fg(cell) {
+        let (r, g, b) = fg.to_u16();
+        let mut attr = pango::Attribute::new_foreground(r, g, b).unwrap();
+        attr.set_start_index(start_idx);
+        attr.set_end_index(end_idx);
+        attr_list.insert(attr);
+    }
 }
 
 #[cfg(test)]
@@ -333,7 +342,7 @@ mod tests {
         line[1].ch = 'b';
         line[2].ch = 'c';
 
-        let styled_line = StyledLine::from(&line);
+        let styled_line = StyledLine::from(&line, &color::ColorModel::new());
         assert_eq!("abc", styled_line.line_str);
         assert_eq!(3, styled_line.cell_to_byte.len());
         assert_eq!(0, styled_line.cell_to_byte[0]);