terminal: adjust page capacity for graphemes if necessary
parent
c0ed1fa370
commit
a59d4286c7
5
TODO.md
5
TODO.md
|
|
@ -20,8 +20,3 @@ Major Features:
|
|||
|
||||
- Bell
|
||||
- Sixels: https://saitoha.github.io/libsixel/
|
||||
|
||||
paged-terminal branch:
|
||||
|
||||
- tests and logic for overflowing page capacities:
|
||||
- graphemes
|
||||
|
|
|
|||
|
|
@ -1033,6 +1033,48 @@ pub fn manualStyleUpdate(self: *Screen) !void {
|
|||
self.cursor.style_ref = &md.ref;
|
||||
}
|
||||
|
||||
/// Append a grapheme to the given cell within the current cursor row.
|
||||
pub fn appendGrapheme(self: *Screen, cell: *Cell, cp: u21) !void {
|
||||
self.cursor.page_pin.page.data.appendGrapheme(
|
||||
self.cursor.page_row,
|
||||
cell,
|
||||
cp,
|
||||
) catch |err| switch (err) {
|
||||
error.OutOfMemory => {
|
||||
// We need to determine the actual cell index of the cell so
|
||||
// that after we adjust the capacity we can reload the cell.
|
||||
const cell_idx: usize = cell_idx: {
|
||||
const cells: [*]Cell = @ptrCast(self.cursor.page_cell);
|
||||
const zero: [*]Cell = cells - self.cursor.x;
|
||||
const target: [*]Cell = @ptrCast(cell);
|
||||
const cell_idx = (@intFromPtr(target) - @intFromPtr(zero)) / @sizeOf(Cell);
|
||||
break :cell_idx cell_idx;
|
||||
};
|
||||
|
||||
// Adjust our capacity. This will update our cursor page pin and
|
||||
// force us to reload.
|
||||
const original_node = self.cursor.page_pin.page;
|
||||
const new_bytes = original_node.data.capacity.grapheme_bytes * 2;
|
||||
_ = try self.pages.adjustCapacity(original_node, .{ .grapheme_bytes = new_bytes });
|
||||
self.cursorReload();
|
||||
|
||||
// The cell pointer is now invalid, so we need to get it from
|
||||
// the reloaded cursor pointers.
|
||||
const reloaded_cell: *Cell = switch (std.math.order(cell_idx, self.cursor.x)) {
|
||||
.eq => self.cursor.page_cell,
|
||||
.lt => self.cursorCellLeft(@intCast(self.cursor.x - cell_idx)),
|
||||
.gt => self.cursorCellRight(@intCast(cell_idx - self.cursor.x)),
|
||||
};
|
||||
|
||||
try self.cursor.page_pin.page.data.appendGrapheme(
|
||||
self.cursor.page_row,
|
||||
reloaded_cell,
|
||||
cp,
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
|
|
|||
|
|
@ -351,11 +351,7 @@ pub fn print(self: *Terminal, c: u21) !void {
|
|||
}
|
||||
|
||||
log.debug("c={x} grapheme attach to left={}", .{ c, prev.left });
|
||||
try self.screen.cursor.page_pin.page.data.appendGrapheme(
|
||||
self.screen.cursor.page_row,
|
||||
prev.cell,
|
||||
c,
|
||||
);
|
||||
try self.screen.appendGrapheme(prev.cell, c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -408,11 +404,7 @@ pub fn print(self: *Terminal, c: u21) !void {
|
|||
if (!emoji) return;
|
||||
}
|
||||
|
||||
try self.screen.cursor.page_pin.page.data.appendGrapheme(
|
||||
self.screen.cursor.page_row,
|
||||
prev,
|
||||
c,
|
||||
);
|
||||
try self.screen.appendGrapheme(prev, c);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2299,6 +2291,17 @@ test "Terminal: input unique style per cell" {
|
|||
}
|
||||
}
|
||||
|
||||
test "Terminal: input glitch text" {
|
||||
const glitch = @embedFile("res/glitch.txt");
|
||||
const alloc = testing.allocator;
|
||||
var t = try init(alloc, .{ .cols = 30, .rows = 30 });
|
||||
defer t.deinit(alloc);
|
||||
|
||||
for (0..100) |_| {
|
||||
try t.printString(glitch);
|
||||
}
|
||||
}
|
||||
|
||||
test "Terminal: zero-width character at start" {
|
||||
var t = try init(testing.allocator, .{ .cols = 80, .rows = 80 });
|
||||
defer t.deinit(testing.allocator);
|
||||
|
|
|
|||
|
|
@ -373,7 +373,7 @@ pub const Page = struct {
|
|||
}
|
||||
|
||||
/// Append a codepoint to the given cell as a grapheme.
|
||||
pub fn appendGrapheme(self: *Page, row: *Row, cell: *Cell, cp: u21) !void {
|
||||
pub fn appendGrapheme(self: *Page, row: *Row, cell: *Cell, cp: u21) Allocator.Error!void {
|
||||
if (comptime std.debug.runtime_safety) assert(cell.hasText());
|
||||
|
||||
const cell_offset = getOffset(Cell, self.memory, cell);
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
Ḡ̴͎͍̜͎͔͕̩̗͕͖̟̜͑̊̌̇̑͒͋͑̄̈́͐̈́́̽͌͂̎̀̔͋̓́̅̌̇͘̕͜͝͝h̶̡̞̫͉̳̬̜̱̥͕͑̾͛̒̆̒̉̒̑͂̄͘ͅǫ̷̨̥͔͔͖̭͚͙̯̟̭̘͇̫̰͚̺̳̙̳̟͚̫̱̹̱͒̂̑͒͜͠ͅş̴̖̰̜̱̹͙̅͒̀̏͆̐̋͂̓͋̃̈̔̂̈͛̐̿̔́̔̄͑̇͑̋̈́͌͋̾̃̽̈́̕͘̚͘͘͘͠͠t̵̢̜̱̦͇͉̬̮̼͖̳̗̥̝̬͇͕̥̜͕̳̱̥̮͉̮̩̘̰̪̤͉͎̲͈͍̳̟̠͈̝̫͋̊̀͐̍̅̀̄̃̈́̔̇̈́̄̃̽̂̌̅̄̋͒̃̈́̍̀̍̇̽̐͊̾̆̅̈̿̓͒̄̾͌̚͝͝͝͝͝t̴̥̼̳̗̬̬͔͎̯͉͇̮̰͖͇̝͔̳̳̗̰͇͎͉̬͇̝̺̯͎͖͔̍͆͒̊̒̔̊̈́̿̊̅͂̐͋̿͂̈̒̄͜͠͠ÿ̴̢̗̜̥͇͖̰͎̝̹̗̪̙̞̣̳͎̯̹͚̲̝̗̳̳̗̖͎̗̬͈͙̝̟͍̥̤͖͇̰͈̺͛̒̂͌̌̏̈̾̓̈́̿͐̂̓̔̓̂̈́͑͛͊͋̔̿̊͑͌̊̏͘͘̕͘͠͝
|
||||
Loading…
Reference in New Issue