Repository: osa1/tiny (language: rust)

Issue:
Scrollback limit sometimes causes scrolling too much
It seems like there's currently a bug when removing old lines when scrollback is enabled where I can scroll past the oldest line.

I'm guessing in some cases the same bug would also cause not being able to scroll enough to see the oldest line, but I haven't encountered this case yet.

To reproduce: set the scrollback something small. 100 works fine in my case. Then leave the client running for a while in an active channel. Every once in a while try to scroll to the top using page-up/down. You'll end up with a screen like:

```
---------------
<empty>
<empty>
<empty>
old line
old line
---------------
```

What should happen instead is I should not be able to scroll after the oldest line is at the top:

```
---------------
old line
old line
old line
old line
old line
---------------
```


Discussion / hints:
Resizing the window fixes the issue.

Fix patch:
diff --git a/libtiny_tui/src/msg_area/mod.rs b/libtiny_tui/src/msg_area/mod.rs
index 3f5e66cc..4fc9786c 100644
--- a/libtiny_tui/src/msg_area/mod.rs
+++ b/libtiny_tui/src/msg_area/mod.rs
@@ -160,9 +160,12 @@ impl MsgArea {
     pub(crate) fn flush_line(&mut self) -> usize {
         let line_height = self.line_buf.rendered_height(self.width);
         // Check if we're about to overflow
+        let mut removed_line_height = 0;
         if self.lines.len() == self.scrollback {
             // Remove oldest line
-            self.lines.pop_front();
+            if let Some(mut removed) = self.lines.pop_front() {
+                removed_line_height = removed.rendered_height(self.width);
+            }
         }
         self.lines
             .push_back(mem::replace(&mut self.line_buf, Line::new()));
@@ -170,7 +173,7 @@ impl MsgArea {
             self.scroll += line_height;
         }
         if let Some(ref mut total_height) = self.lines_height {
-            *total_height += line_height;
+            *total_height += line_height - removed_line_height;
         }
         self.lines.len() - 1
     }
@@ -231,5 +234,6 @@ mod tests {
         // Will pop out "first" line
         msg_area.flush_line();
         assert_eq!(msg_area.lines.len(), 3);
+        assert_eq!(msg_area.lines_height(), 3);
     }
 }


Test patch: