mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 16:26:08 +03:00
@ -81,12 +81,14 @@ pub const Shaper = struct {
|
|||||||
group: *GroupCache,
|
group: *GroupCache,
|
||||||
row: terminal.Screen.Row,
|
row: terminal.Screen.Row,
|
||||||
selection: ?terminal.Selection,
|
selection: ?terminal.Selection,
|
||||||
|
cursor_x: ?usize,
|
||||||
) font.shape.RunIterator {
|
) font.shape.RunIterator {
|
||||||
return .{
|
return .{
|
||||||
.hooks = .{ .shaper = self },
|
.hooks = .{ .shaper = self },
|
||||||
.group = group,
|
.group = group,
|
||||||
.row = row,
|
.row = row,
|
||||||
.selection = selection,
|
.selection = selection,
|
||||||
|
.cursor_x = cursor_x,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +171,7 @@ test "run iterator" {
|
|||||||
|
|
||||||
// Get our run iterator
|
// Get our run iterator
|
||||||
var shaper = testdata.shaper;
|
var shaper = testdata.shaper;
|
||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null);
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |_| count += 1;
|
while (try it.next(alloc)) |_| count += 1;
|
||||||
try testing.expectEqual(@as(usize, 1), count);
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
@ -182,7 +184,7 @@ test "run iterator" {
|
|||||||
try screen.testWriteString("ABCD EFG");
|
try screen.testWriteString("ABCD EFG");
|
||||||
|
|
||||||
var shaper = testdata.shaper;
|
var shaper = testdata.shaper;
|
||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null);
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |_| count += 1;
|
while (try it.next(alloc)) |_| count += 1;
|
||||||
try testing.expectEqual(@as(usize, 1), count);
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
@ -196,7 +198,7 @@ test "run iterator" {
|
|||||||
|
|
||||||
// Get our run iterator
|
// Get our run iterator
|
||||||
var shaper = testdata.shaper;
|
var shaper = testdata.shaper;
|
||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null);
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |_| {
|
while (try it.next(alloc)) |_| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -230,7 +232,7 @@ test "run iterator: empty cells with background set" {
|
|||||||
|
|
||||||
// Get our run iterator
|
// Get our run iterator
|
||||||
var shaper = testdata.shaper;
|
var shaper = testdata.shaper;
|
||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null);
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -265,7 +267,7 @@ test "shape" {
|
|||||||
|
|
||||||
// Get our run iterator
|
// Get our run iterator
|
||||||
var shaper = testdata.shaper;
|
var shaper = testdata.shaper;
|
||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null);
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -288,7 +290,7 @@ test "shape inconsolata ligs" {
|
|||||||
try screen.testWriteString(">=");
|
try screen.testWriteString(">=");
|
||||||
|
|
||||||
var shaper = testdata.shaper;
|
var shaper = testdata.shaper;
|
||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null);
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -305,7 +307,7 @@ test "shape inconsolata ligs" {
|
|||||||
try screen.testWriteString("===");
|
try screen.testWriteString("===");
|
||||||
|
|
||||||
var shaper = testdata.shaper;
|
var shaper = testdata.shaper;
|
||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null);
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -330,7 +332,7 @@ test "shape emoji width" {
|
|||||||
try screen.testWriteString("👍");
|
try screen.testWriteString("👍");
|
||||||
|
|
||||||
var shaper = testdata.shaper;
|
var shaper = testdata.shaper;
|
||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null);
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -364,7 +366,7 @@ test "shape emoji width long" {
|
|||||||
|
|
||||||
// Get our run iterator
|
// Get our run iterator
|
||||||
var shaper = testdata.shaper;
|
var shaper = testdata.shaper;
|
||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null);
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -395,7 +397,7 @@ test "shape variation selector VS15" {
|
|||||||
|
|
||||||
// Get our run iterator
|
// Get our run iterator
|
||||||
var shaper = testdata.shaper;
|
var shaper = testdata.shaper;
|
||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null);
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -426,7 +428,7 @@ test "shape variation selector VS16" {
|
|||||||
|
|
||||||
// Get our run iterator
|
// Get our run iterator
|
||||||
var shaper = testdata.shaper;
|
var shaper = testdata.shaper;
|
||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null);
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -454,7 +456,7 @@ test "shape with empty cells in between" {
|
|||||||
|
|
||||||
// Get our run iterator
|
// Get our run iterator
|
||||||
var shaper = testdata.shaper;
|
var shaper = testdata.shaper;
|
||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null);
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -486,7 +488,7 @@ test "shape Chinese characters" {
|
|||||||
|
|
||||||
// Get our run iterator
|
// Get our run iterator
|
||||||
var shaper = testdata.shaper;
|
var shaper = testdata.shaper;
|
||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null);
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -527,7 +529,7 @@ test "shape box glyphs" {
|
|||||||
|
|
||||||
// Get our run iterator
|
// Get our run iterator
|
||||||
var shaper = testdata.shaper;
|
var shaper = testdata.shaper;
|
||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null);
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -561,7 +563,7 @@ test "shape selection boundary" {
|
|||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), .{
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), .{
|
||||||
.start = .{ .x = 0, .y = 0 },
|
.start = .{ .x = 0, .y = 0 },
|
||||||
.end = .{ .x = screen.cols - 1, .y = 0 },
|
.end = .{ .x = screen.cols - 1, .y = 0 },
|
||||||
});
|
}, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -577,7 +579,7 @@ test "shape selection boundary" {
|
|||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), .{
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), .{
|
||||||
.start = .{ .x = 2, .y = 0 },
|
.start = .{ .x = 2, .y = 0 },
|
||||||
.end = .{ .x = screen.cols - 1, .y = 0 },
|
.end = .{ .x = screen.cols - 1, .y = 0 },
|
||||||
});
|
}, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -593,7 +595,7 @@ test "shape selection boundary" {
|
|||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), .{
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), .{
|
||||||
.start = .{ .x = 0, .y = 0 },
|
.start = .{ .x = 0, .y = 0 },
|
||||||
.end = .{ .x = 3, .y = 0 },
|
.end = .{ .x = 3, .y = 0 },
|
||||||
});
|
}, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -609,7 +611,7 @@ test "shape selection boundary" {
|
|||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), .{
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), .{
|
||||||
.start = .{ .x = 1, .y = 0 },
|
.start = .{ .x = 1, .y = 0 },
|
||||||
.end = .{ .x = 3, .y = 0 },
|
.end = .{ .x = 3, .y = 0 },
|
||||||
});
|
}, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -625,7 +627,7 @@ test "shape selection boundary" {
|
|||||||
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), .{
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), .{
|
||||||
.start = .{ .x = 1, .y = 0 },
|
.start = .{ .x = 1, .y = 0 },
|
||||||
.end = .{ .x = 1, .y = 0 },
|
.end = .{ .x = 1, .y = 0 },
|
||||||
});
|
}, null);
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -635,6 +637,71 @@ test "shape selection boundary" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "shape cursor boundary" {
|
||||||
|
const testing = std.testing;
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
|
var testdata = try testShaper(alloc);
|
||||||
|
defer testdata.deinit();
|
||||||
|
|
||||||
|
// Make a screen with some data
|
||||||
|
var screen = try terminal.Screen.init(alloc, 3, 10, 0);
|
||||||
|
defer screen.deinit();
|
||||||
|
try screen.testWriteString("a1b2c3d4e5");
|
||||||
|
|
||||||
|
// No cursor is full line
|
||||||
|
{
|
||||||
|
// Get our run iterator
|
||||||
|
var shaper = testdata.shaper;
|
||||||
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, null);
|
||||||
|
var count: usize = 0;
|
||||||
|
while (try it.next(alloc)) |run| {
|
||||||
|
count += 1;
|
||||||
|
_ = try shaper.shape(run);
|
||||||
|
}
|
||||||
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cursor at index 0 is two runs
|
||||||
|
{
|
||||||
|
// Get our run iterator
|
||||||
|
var shaper = testdata.shaper;
|
||||||
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, 0);
|
||||||
|
var count: usize = 0;
|
||||||
|
while (try it.next(alloc)) |run| {
|
||||||
|
count += 1;
|
||||||
|
_ = try shaper.shape(run);
|
||||||
|
}
|
||||||
|
try testing.expectEqual(@as(usize, 2), count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cursor at index 1 is three runs
|
||||||
|
{
|
||||||
|
// Get our run iterator
|
||||||
|
var shaper = testdata.shaper;
|
||||||
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, 1);
|
||||||
|
var count: usize = 0;
|
||||||
|
while (try it.next(alloc)) |run| {
|
||||||
|
count += 1;
|
||||||
|
_ = try shaper.shape(run);
|
||||||
|
}
|
||||||
|
try testing.expectEqual(@as(usize, 3), count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cursor at last col is two runs
|
||||||
|
{
|
||||||
|
// Get our run iterator
|
||||||
|
var shaper = testdata.shaper;
|
||||||
|
var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, 9);
|
||||||
|
var count: usize = 0;
|
||||||
|
while (try it.next(alloc)) |run| {
|
||||||
|
count += 1;
|
||||||
|
_ = try shaper.shape(run);
|
||||||
|
}
|
||||||
|
try testing.expectEqual(@as(usize, 2), count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const TestShaper = struct {
|
const TestShaper = struct {
|
||||||
alloc: Allocator,
|
alloc: Allocator,
|
||||||
shaper: Shaper,
|
shaper: Shaper,
|
||||||
|
@ -29,6 +29,7 @@ pub const RunIterator = struct {
|
|||||||
group: *font.GroupCache,
|
group: *font.GroupCache,
|
||||||
row: terminal.Screen.Row,
|
row: terminal.Screen.Row,
|
||||||
selection: ?terminal.Selection = null,
|
selection: ?terminal.Selection = null,
|
||||||
|
cursor_x: ?usize = null,
|
||||||
i: usize = 0,
|
i: usize = 0,
|
||||||
|
|
||||||
pub fn next(self: *RunIterator, alloc: Allocator) !?TextRun {
|
pub fn next(self: *RunIterator, alloc: Allocator) !?TextRun {
|
||||||
@ -67,6 +68,32 @@ pub const RunIterator = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If our cursor is on this line then we break the run around the
|
||||||
|
// cursor. This means that any row with a cursor has at least
|
||||||
|
// three breaks: before, exactly the cursor, and after.
|
||||||
|
if (self.cursor_x) |cursor_x| {
|
||||||
|
// Exactly: self.i is the cursor and we iterated once. This
|
||||||
|
// means that we started exactly at the cursor and did at
|
||||||
|
// least one (probably exactly one) iteration. That is
|
||||||
|
// exactly one character.
|
||||||
|
if (self.i == cursor_x and j > self.i) {
|
||||||
|
assert(j == self.i + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Before: up to and not including the cursor. This means
|
||||||
|
// that we started before the cursor (self.i < cursor_x)
|
||||||
|
// and j is now at the cursor meaning we haven't yet processed
|
||||||
|
// the cursor.
|
||||||
|
if (self.i < cursor_x and j == cursor_x) {
|
||||||
|
assert(j > 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// After: after the cursor. We don't need to do anything
|
||||||
|
// special, we just let the run complete.
|
||||||
|
}
|
||||||
|
|
||||||
// If we're a spacer, then we ignore it
|
// If we're a spacer, then we ignore it
|
||||||
if (cell.attrs.wide_spacer_tail) continue;
|
if (cell.attrs.wide_spacer_tail) continue;
|
||||||
|
|
||||||
|
@ -60,12 +60,14 @@ pub const Shaper = struct {
|
|||||||
group: *font.GroupCache,
|
group: *font.GroupCache,
|
||||||
row: terminal.Screen.Row,
|
row: terminal.Screen.Row,
|
||||||
selection: ?terminal.Selection,
|
selection: ?terminal.Selection,
|
||||||
|
cursor_x: ?usize,
|
||||||
) font.shape.RunIterator {
|
) font.shape.RunIterator {
|
||||||
return .{
|
return .{
|
||||||
.hooks = .{ .shaper = self },
|
.hooks = .{ .shaper = self },
|
||||||
.group = group,
|
.group = group,
|
||||||
.row = row,
|
.row = row,
|
||||||
.selection = selection,
|
.selection = selection,
|
||||||
|
.cursor_x = cursor_x,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,7 +291,7 @@ pub const Wasm = struct {
|
|||||||
while (rowIter.next()) |row| {
|
while (rowIter.next()) |row| {
|
||||||
defer y += 1;
|
defer y += 1;
|
||||||
|
|
||||||
var iter = self.runIterator(group, row, null);
|
var iter = self.runIterator(group, row, null, null);
|
||||||
while (try iter.next(alloc)) |run| {
|
while (try iter.next(alloc)) |run| {
|
||||||
const cells = try self.shape(run);
|
const cells = try self.shape(run);
|
||||||
log.info("y={} run={d} shape={any} idx={}", .{
|
log.info("y={} run={d} shape={any} idx={}", .{
|
||||||
|
@ -871,15 +871,31 @@ fn rebuildCells(
|
|||||||
while (rowIter.next()) |row| {
|
while (rowIter.next()) |row| {
|
||||||
defer y += 1;
|
defer y += 1;
|
||||||
|
|
||||||
// If this is the row with our cursor, then we may have to modify
|
// True if this is the row with our cursor. There are a lot of conditions
|
||||||
// the cell with the cursor.
|
// here because the reasons we need to know this are primarily to invert.
|
||||||
const start_i: usize = self.cells.items.len;
|
//
|
||||||
defer if (draw_cursor and
|
// - If we aren't drawing the cursor (draw_cursor), then we don't need
|
||||||
|
// to change our rendering.
|
||||||
|
// - If the cursor is not visible, then we don't need to change rendering.
|
||||||
|
// - If the cursor style is not a box, then we don't need to change
|
||||||
|
// rendering because it'll never fully overlap a glyph.
|
||||||
|
// - If the viewport is not at the bottom, then we don't need to
|
||||||
|
// change rendering because the cursor is not visible.
|
||||||
|
// (NOTE: this may not be fully correct, we may be scrolled
|
||||||
|
// slightly up and the cursor may be visible)
|
||||||
|
// - If this y doesn't match our cursor y then we don't need to
|
||||||
|
// change rendering.
|
||||||
|
//
|
||||||
|
const cursor_row = draw_cursor and
|
||||||
self.cursor_visible and
|
self.cursor_visible and
|
||||||
self.cursor_style == .box and
|
self.cursor_style == .box and
|
||||||
screen.viewportIsBottom() and
|
screen.viewportIsBottom() and
|
||||||
y == screen.cursor.y)
|
y == screen.cursor.y;
|
||||||
{
|
|
||||||
|
// If this is the row with our cursor, then we may have to modify
|
||||||
|
// the cell with the cursor.
|
||||||
|
const start_i: usize = self.cells.items.len;
|
||||||
|
defer if (cursor_row) {
|
||||||
for (self.cells.items[start_i..]) |cell| {
|
for (self.cells.items[start_i..]) |cell| {
|
||||||
if (cell.grid_pos[0] == @as(f32, @floatFromInt(screen.cursor.x)) and
|
if (cell.grid_pos[0] == @as(f32, @floatFromInt(screen.cursor.x)) and
|
||||||
cell.mode == .fg)
|
cell.mode == .fg)
|
||||||
@ -907,7 +923,12 @@ fn rebuildCells(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Split our row into runs and shape each one.
|
// Split our row into runs and shape each one.
|
||||||
var iter = self.font_shaper.runIterator(self.font_group, row, row_selection);
|
var iter = self.font_shaper.runIterator(
|
||||||
|
self.font_group,
|
||||||
|
row,
|
||||||
|
row_selection,
|
||||||
|
if (cursor_row) screen.cursor.x else null,
|
||||||
|
);
|
||||||
while (try iter.next(self.alloc)) |run| {
|
while (try iter.next(self.alloc)) |run| {
|
||||||
for (try self.font_shaper.shape(run)) |shaper_cell| {
|
for (try self.font_shaper.shape(run)) |shaper_cell| {
|
||||||
if (self.updateCell(
|
if (self.updateCell(
|
||||||
|
@ -903,15 +903,17 @@ pub fn rebuildCells(
|
|||||||
break :sel null;
|
break :sel null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// If this is the row with our cursor, then we may have to modify
|
// See Metal.zig
|
||||||
// the cell with the cursor.
|
const cursor_row = draw_cursor and
|
||||||
const start_i: usize = self.cells.items.len;
|
|
||||||
defer if (draw_cursor and
|
|
||||||
self.cursor_visible and
|
self.cursor_visible and
|
||||||
self.cursor_style == .box and
|
self.cursor_style == .box and
|
||||||
screen.viewportIsBottom() and
|
screen.viewportIsBottom() and
|
||||||
y == screen.cursor.y)
|
y == screen.cursor.y;
|
||||||
{
|
|
||||||
|
// If this is the row with our cursor, then we may have to modify
|
||||||
|
// the cell with the cursor.
|
||||||
|
const start_i: usize = self.cells.items.len;
|
||||||
|
defer if (cursor_row) {
|
||||||
for (self.cells.items[start_i..]) |cell| {
|
for (self.cells.items[start_i..]) |cell| {
|
||||||
if (cell.grid_col == screen.cursor.x and
|
if (cell.grid_col == screen.cursor.x and
|
||||||
cell.mode == .fg)
|
cell.mode == .fg)
|
||||||
@ -942,7 +944,12 @@ pub fn rebuildCells(
|
|||||||
const start = self.cells.items.len;
|
const start = self.cells.items.len;
|
||||||
|
|
||||||
// Split our row into runs and shape each one.
|
// Split our row into runs and shape each one.
|
||||||
var iter = self.font_shaper.runIterator(self.font_group, row, selection);
|
var iter = self.font_shaper.runIterator(
|
||||||
|
self.font_group,
|
||||||
|
row,
|
||||||
|
selection,
|
||||||
|
if (cursor_row) screen.cursor.x else null,
|
||||||
|
);
|
||||||
while (try iter.next(self.alloc)) |run| {
|
while (try iter.next(self.alloc)) |run| {
|
||||||
for (try self.font_shaper.shape(run)) |shaper_cell| {
|
for (try self.font_shaper.shape(run)) |shaper_cell| {
|
||||||
if (self.updateCell(
|
if (self.updateCell(
|
||||||
|
Reference in New Issue
Block a user