chiark / gitweb /
Editor: scroll to keep the cursor in view.
authorSimon Tatham <anakin@pobox.com>
Thu, 4 Jan 2024 20:20:55 +0000 (20:20 +0000)
committerSimon Tatham <anakin@pobox.com>
Thu, 4 Jan 2024 20:20:55 +0000 (20:20 +0000)
src/editor.rs

index 26554a6fc7ebd85625d659e7b269fba28a84e3aa..94be9bdb42e153aa6d87f83b63ee407cc715fe2e 100644 (file)
@@ -760,6 +760,7 @@ struct Composer {
     regions: Vec<ComposeBufferRegion>,
     layout: Vec<ComposeLayoutCell>,
     cursor_pos: Option<(usize, usize)>,
+    ytop: usize,
     scanner: &'static Scan,
     conf: InstanceStatusConfig,
     last_size: Option<(usize, usize)>,
@@ -786,6 +787,7 @@ impl Composer {
             regions: Vec::new(),
             layout: Vec::new(),
             cursor_pos: None,
+            ytop: 0,
             scanner: Scan::get(),
             conf,
             last_size: None,
@@ -1034,6 +1036,12 @@ impl Composer {
             self.layout = self.layout(w);
         }
         self.cursor_pos = self.determine_cursor_pos();
+
+        if let Some((_cx, cy)) = self.cursor_pos {
+            // Scroll to keep the cursor in view
+            self.ytop = min(self.ytop, cy);
+            self.ytop = max(self.ytop, (cy + 1).saturating_sub(self.page_len));
+        }
     }
 
     fn goto_xy(&mut self, x: usize, y: usize) -> bool {
@@ -1391,11 +1399,10 @@ impl ActivityState for Composer {
         }
         lines.extend_from_slice(&self.headersep.render(w));
 
-        let ytop = 0;           // FIXME: vary this to keep cursor in view
         let ystart = lines.len();
 
         while lines.len() < h {
-            let y = ytop + (lines.len() - ystart);
+            let y = self.ytop + (lines.len() - ystart);
             match self.get_coloured_line(y) {
                 Some(line) => lines.push(line),
                 None => break,  // ran out of lines in the buffer
@@ -1404,7 +1411,7 @@ impl ActivityState for Composer {
 
         let mut cursor_pos = CursorPosition::None;
         if let Some((cx, cy)) = self.cursor_pos {
-            if let Some(y) = cy.checked_sub(ytop) {
+            if let Some(y) = cy.checked_sub(self.ytop) {
                 let cy = y + ystart;
                 if cy < h {
                     cursor_pos = CursorPosition::At(cx, cy);