From c0332bd935bb7c016278d43a526e588558a0cab1 Mon Sep 17 00:00:00 2001
From: Blaž Hrastnik
Date: Thu, 3 Jun 2021 10:28:49 +0900
Subject: Fix split sizes getting out of sync with the terminal size, refs #69

---
 helix-term/src/compositor.rs | 10 ++++++++--
 helix-term/src/ui/editor.rs  |  8 ++++++--
 helix-term/src/ui/prompt.rs  |  8 +++++++-
 helix-tui/src/terminal.rs    |  4 ++--
 helix-view/src/editor.rs     |  5 +++--
 helix-view/src/tree.rs       | 10 +++++++---
 6 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/helix-term/src/compositor.rs b/helix-term/src/compositor.rs
index 7753e0a5..967ea034 100644
--- a/helix-term/src/compositor.rs
+++ b/helix-term/src/compositor.rs
@@ -122,11 +122,17 @@ impl Compositor {
     }
 
     pub fn render(&mut self, cx: &mut Context) {
-        self.terminal.autoresize().unwrap();
-        let area = self.size();
+        let area = self
+            .terminal
+            .autoresize()
+            .expect("Unable to determine terminal size");
+
+        // TODO: need to recalculate view tree if necessary
 
         let surface = self.terminal.current_buffer_mut();
 
+        let area = surface.area().clone();
+
         for layer in &self.layers {
             layer.render(area, surface, cx)
         }
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index 47770ebd..e92cf4f1 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -240,7 +240,7 @@ impl EditorView {
             for selection in doc
                 .selection(view.id)
                 .iter()
-                .filter(|range| range.overlaps(&screen))
+                .filter(|range| screen.overlaps(&range))
             {
                 // TODO: render also if only one of the ranges is in viewport
                 let mut start = view.screen_coords_at_pos(doc, text, selection.anchor);
@@ -261,7 +261,7 @@ impl EditorView {
                         Rect::new(
                             viewport.x + start.col as u16,
                             viewport.y + start.row as u16,
-                            (end.col - start.col) as u16 + 1,
+                            ((end.col - start.col) as u16 + 1).min(viewport.width),
                             1,
                         ),
                         selection_style,
@@ -633,6 +633,10 @@ impl Component for EditorView {
         // clear with background color
         surface.set_style(area, cx.editor.theme.get("ui.background"));
 
+        // if the terminal size suddenly changed, we need to trigger a resize
+        cx.editor
+            .resize(Rect::new(area.x, area.y, area.width, area.height - 1)); // - 1 to account for commandline
+
         for (view, is_focused) in cx.editor.tree.views() {
             let doc = cx.editor.document(view.doc).unwrap();
             self.render_view(doc, view, area, surface, &cx.editor.theme, is_focused);
diff --git a/helix-term/src/ui/prompt.rs b/helix-term/src/ui/prompt.rs
index 8bb6ba93..1f424878 100644
--- a/helix-term/src/ui/prompt.rs
+++ b/helix-term/src/ui/prompt.rs
@@ -160,7 +160,13 @@ impl Prompt {
         if let Some(doc) = (self.doc_fn)(&self.line) {
             let text = ui::Text::new(doc.to_string());
 
-            let area = Rect::new(completion_area.x, completion_area.y - 3, BASE_WIDTH * 3, 3);
+            let viewport = area;
+            let area = viewport.intersection(Rect::new(
+                completion_area.x,
+                completion_area.y - 3,
+                BASE_WIDTH * 3,
+                3,
+            ));
 
             let background = theme.get("ui.help");
             surface.clear_with(area, background);
diff --git a/helix-tui/src/terminal.rs b/helix-tui/src/terminal.rs
index 1a0cae3e..ad1e8da3 100644
--- a/helix-tui/src/terminal.rs
+++ b/helix-tui/src/terminal.rs
@@ -137,12 +137,12 @@ where
     }
 
     /// Queries the backend for size and resizes if it doesn't match the previous size.
-    pub fn autoresize(&mut self) -> io::Result<()> {
+    pub fn autoresize(&mut self) -> io::Result<Rect> {
         let size = self.size()?;
         if size != self.viewport.area {
             self.resize(size)?;
         };
-        Ok(())
+        Ok(size)
     }
 
     /// Synchronizes terminal size, calls the rendering closure, flushes the current internal state
diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs
index e9f8b5a1..e7b25814 100644
--- a/helix-view/src/editor.rs
+++ b/helix-view/src/editor.rs
@@ -194,8 +194,9 @@ impl Editor {
     }
 
     pub fn resize(&mut self, area: Rect) {
-        self.tree.resize(area);
-        self._refresh();
+        if self.tree.resize(area) {
+            self._refresh();
+        };
     }
 
     pub fn focus_next(&mut self) {
diff --git a/helix-view/src/tree.rs b/helix-view/src/tree.rs
index b7c99e16..5b56156f 100644
--- a/helix-view/src/tree.rs
+++ b/helix-view/src/tree.rs
@@ -293,9 +293,13 @@ impl Tree {
         }
     }
 
-    pub fn resize(&mut self, area: Rect) {
-        self.area = area;
-        self.recalculate();
+    pub fn resize(&mut self, area: Rect) -> bool {
+        if self.area != area {
+            self.area = area;
+            self.recalculate();
+            return true;
+        }
+        false
     }
 
     pub fn recalculate(&mut self) {
-- 
cgit v1.2.3-70-g09d2