terminal: on print, adjust page size if we need to grow for hyperlinks

This commit is contained in:
Mitchell Hashimoto
2024-07-05 18:25:34 -07:00
parent a6051b931e
commit 251ec0c9f3
2 changed files with 46 additions and 22 deletions

View File

@ -1524,6 +1524,35 @@ pub fn endHyperlink(self: *Screen) void {
self.cursor.hyperlink = null;
}
/// Set the current hyperlink state on the current cell.
pub fn cursorSetHyperlink(self: *Screen) !void {
assert(self.cursor.hyperlink_id != 0);
var page = &self.cursor.page_pin.page.data;
if (page.setHyperlink(
self.cursor.page_row,
self.cursor.page_cell,
self.cursor.hyperlink_id,
)) {
// Success!
return;
} else |err| switch (err) {
// hyperlink_map is out of space, realloc the page to be larger
error.OutOfMemory => {
_ = try self.pages.adjustCapacity(
self.cursor.page_pin.page,
.{ .hyperlink_bytes = page.capacity.hyperlink_bytes * 2 },
);
// Reload cursor since our cursor page has changed.
self.cursorReload();
// Retry
return try self.cursorSetHyperlink();
},
}
}
/// Set the selection to the given selection. If this is a tracked selection
/// then the screen will take overnship of the selection. If this is untracked
/// then the screen will convert it to tracked internally. This will automatically

View File

@ -601,27 +601,6 @@ fn printCell(
);
}
// We check for an active hyperlink first because setHyperlink
// handles clearing the old hyperlink and an optimization if we're
// overwriting the same hyperlink.
if (self.screen.cursor.hyperlink_id > 0) {
// If we have a hyperlink configured, apply it to this cell
var page = &self.screen.cursor.page_pin.page.data;
page.setHyperlink(
self.screen.cursor.page_row,
cell,
self.screen.cursor.hyperlink_id,
) catch |err| {
// TODO: an error can only happen if our page is out of space
// so realloc the page here.
log.err("failed to set hyperlink, ignoring err={}", .{err});
};
} else if (cell.hyperlink) {
// If the previous cell had a hyperlink then we need to clear it.
var page = &self.screen.cursor.page_pin.page.data;
page.clearHyperlink(self.screen.cursor.page_row, cell);
}
// We don't need to update the style refs unless the
// cell's new style will be different after writing.
const style_changed = cell.style_id != self.screen.cursor.style_id;
@ -635,6 +614,9 @@ fn printCell(
}
}
// Keep track if we had a hyperlink so we can unset it.
const had_hyperlink = cell.hyperlink;
// Write
cell.* = .{
.content_tag = .codepoint,
@ -642,7 +624,6 @@ fn printCell(
.style_id = self.screen.cursor.style_id,
.wide = wide,
.protected = self.screen.cursor.protected,
.hyperlink = self.screen.cursor.hyperlink_id > 0,
};
if (style_changed) {
@ -654,6 +635,20 @@ fn printCell(
self.screen.cursor.page_row.styled = true;
}
}
// We check for an active hyperlink first because setHyperlink
// handles clearing the old hyperlink and an optimization if we're
// overwriting the same hyperlink.
if (self.screen.cursor.hyperlink_id > 0) {
self.screen.cursorSetHyperlink() catch |err| {
log.warn("error reallocating for more hyperlink space, ignoring hyperlink err={}", .{err});
assert(!cell.hyperlink);
};
} else if (had_hyperlink) {
// If the previous cell had a hyperlink then we need to clear it.
var page = &self.screen.cursor.page_pin.page.data;
page.clearHyperlink(self.screen.cursor.page_row, cell);
}
}
fn printWrap(self: *Terminal) !void {