chiark / gitweb /
Fix panic when extending an empty feed.
authorSimon Tatham <anakin@pobox.com>
Thu, 11 Jan 2024 07:59:02 +0000 (07:59 +0000)
committerSimon Tatham <anakin@pobox.com>
Thu, 11 Jan 2024 08:04:10 +0000 (08:04 +0000)
If a file contains nothing but a header and an extensible indicator,
and you press [0] to extend, and that attempt to fetch more items
fails, then the extensible indicator vanishes, and is removed from the
file's list of items. So the 2-line header moves forward one index
slot, into the place where the 3-line indicator was. But on any but
the tiniest screen, your current position was surely on the last line
of the indicator - so now it's out of range of the item now in that
position.

To fix this, I've added a new position fixup function, which is called
whenever we fear our line position might be outside the bounds of the
item it's in. This is called after try_extend, where the problem
actually showed up; it's also called on resize(), in case a file is
newly constructed but one of the statuses in it has been updated from
the server since we last visited.

src/file.rs

index a11d9b17847de93ca5723244559624632a0c5810..bfffdbabeea12b581f2d2ce2b87d706452b16408 100644 (file)
@@ -530,6 +530,18 @@ impl<Type: FileType, Source: FileDataSource> File<Type, Source> {
         };
     }
 
+    fn clip_pos_within_item(&mut self) {
+        let (w, _h) = self.last_size.expect(
+            "clip_pos_within_item before setting pos");
+        // If something has just changed the sizes of rendered items,
+        // we need to make sure self.pos doesn't specify a line
+        // position outside the current item.
+        let nlines = self.ensure_item_rendered(self.pos.item, w).len();
+        if self.pos.width.is_some() {
+            self.pos.line = min(self.pos.line, nlines);
+        }
+    }
+
     fn fix_overshoot_at_top(&mut self) {
         // If an attempt to move up the document left us with no line
         // to display at the top of the screen, move down again to fix
@@ -625,6 +637,7 @@ impl<Type: FileType, Source: FileDataSource> File<Type, Source> {
                 }
 
                 self.contents.update_items(client);
+                self.clip_pos_within_item();
                 self.fix_overshoot_at_top(); // in case the extender vanished
                 Ok(())
             }
@@ -938,6 +951,7 @@ impl<Type: FileType, Source: FileDataSource>
             self.update_pos_for_size(w, h);
             self.fix_overshoot_at_top();
         }
+        self.clip_pos_within_item();
         self.ensure_enough_rendered();
         self.after_setting_pos();
     }