terminal: cursorChangePin needs to migrate hyperlink state

Fixes #2007
This commit is contained in:
Mitchell Hashimoto
2024-07-28 14:14:07 -07:00
parent 4bbb5d9c86
commit 6d2e97a2f1

View File

@ -797,35 +797,63 @@ fn cursorChangePin(self: *Screen, new: Pin) void {
new.markDirty(); new.markDirty();
} }
// If we have a style set, then we need to migrate it over to the // If our pin is on the same page, then we can just update the pin.
// new page. This is expensive so we do everything we can with cheap // We don't need to migrate any state.
// ops to avoid it. if (self.cursor.page_pin.page == new.page) {
if (self.cursor.style_id == style.default_id or
self.cursor.page_pin.page == new.page)
{
self.cursor.page_pin.* = new; self.cursor.page_pin.* = new;
return; return;
} }
// Store our old full style so we can reapply it in the new page. // If we have a old style then we need to release it from the old page.
const old_style = self.cursor.style; const old_style_: ?style.Style = if (self.cursor.style_id == style.default_id)
null
else
self.cursor.style;
if (old_style_ != null) {
self.cursor.style = .{};
self.manualStyleUpdate() catch unreachable; // Removing a style should never fail
}
// Clear our old style in the current pin // If we have a hyperlink then we need to release it from the old page.
self.cursor.style = .{}; if (self.cursor.hyperlink != null) {
self.manualStyleUpdate() catch unreachable; // Removing a style should never fail const old_page = &self.cursor.page_pin.page.data;
old_page.hyperlink_set.release(old_page.memory, self.cursor.hyperlink_id);
}
// Update our pin to the new page // Update our pin to the new page
self.cursor.page_pin.* = new; self.cursor.page_pin.* = new;
self.cursor.style = old_style;
self.manualStyleUpdate() catch |err| { // On the new page, we need to migrate our style
// This failure should not happen because manualStyleUpdate if (old_style_) |old_style| {
// handles page splitting, overflow, and more. This should only self.cursor.style = old_style;
// happen if we're out of RAM. In this case, we'll just degrade self.manualStyleUpdate() catch |err| {
// gracefully back to the default style. // This failure should not happen because manualStyleUpdate
log.err("failed to update style on cursor change err={}", .{err}); // handles page splitting, overflow, and more. This should only
self.cursor.style = .{}; // happen if we're out of RAM. In this case, we'll just degrade
self.cursor.style_id = 0; // gracefully back to the default style.
}; log.err("failed to update style on cursor change err={}", .{err});
self.cursor.style = .{};
self.cursor.style_id = 0;
};
}
// On the new page, we need to migrate our hyperlink
if (self.cursor.hyperlink) |link| {
// So we don't attempt to free any memory in the replaced page.
self.cursor.hyperlink_id = 0;
self.cursor.hyperlink = null;
// Re-add
self.startHyperlink(link.uri, link.id) catch |err| {
// This shouldn't happen because startHyperlink should handle
// resizing. This only happens if we're truly out of RAM. Degrade
// to forgetting the hyperlink.
log.err("failed to update hyperlink on cursor change err={}", .{err});
};
// Remove our old link
link.destroy(self.alloc);
}
} }
/// Mark the cursor position as dirty. /// Mark the cursor position as dirty.