widgets(terminal): implement many more CSI seqs

This commit is contained in:
Tim Culverhouse 2024-06-10 08:59:00 -05:00
parent 24ad3bf3da
commit 0cd57fe0f5
2 changed files with 134 additions and 6 deletions

View file

@ -368,7 +368,27 @@ pub fn eraseRight(self: *Screen) void {
}
}
/// delete n lines from te bottom of te scrolling region
pub fn eraseLeft(self: *Screen) void {
self.cursor.pending_wrap = false;
const start = self.cursor.row * self.width;
const end = start + self.cursor.col;
var i = start;
while (i < end) : (i += 1) {
self.buf[i].erase(self.cursor.style.bg);
}
}
pub fn eraseLine(self: *Screen) void {
self.cursor.pending_wrap = false;
const start = self.cursor.row * self.width;
const end = start + self.width;
var i = start;
while (i < end) : (i += 1) {
self.buf[i].erase(self.cursor.style.bg);
}
}
/// delete n lines from the bottom of the scrolling region
pub fn deleteLine(self: *Screen, n: usize) !void {
if (n == 0) return;
@ -419,3 +439,44 @@ pub fn insertLine(self: *Screen, n: usize) !void {
}
}
}
pub fn eraseBelow(self: *Screen) void {
self.eraseRight();
// start is the first column of the row below us
const start = (self.cursor.row * self.width) + (self.width);
var i = start;
while (i < self.buf.len) : (i += 1) {
self.buf[i].erase(self.cursor.style.bg);
}
}
pub fn eraseAbove(self: *Screen) void {
self.eraseLeft();
// start is the first column of the row below us
const start: usize = 0;
const end = self.cursor.row * self.width;
var i = start;
while (i < end) : (i += 1) {
self.buf[i].erase(self.cursor.style.bg);
}
}
pub fn eraseAll(self: *Screen) void {
var i: usize = 0;
while (i < self.buf.len) : (i += 1) {
self.buf[i].erase(self.cursor.style.bg);
}
}
pub fn deleteCharacters(self: *Screen, n: usize) !void {
if (!self.withinScrollingRegion()) return;
self.cursor.pending_wrap = false;
var col = self.cursor.col;
while (col <= self.scrolling_region.right) : (col += 1) {
if (col + n <= self.scrolling_region.right)
try self.buf[col].copyFrom(self.buf[col + n])
else
self.buf[col].erase(self.cursor.style.bg);
}
}

View file

@ -332,9 +332,9 @@ fn run(self: *Terminal) !void {
var iter = seq.iterator(u16);
const kind = iter.next() orelse 0;
switch (kind) {
0 => {},
1 => {},
2 => {},
0 => self.back_screen.eraseBelow(),
1 => self.back_screen.eraseAbove(),
2 => self.back_screen.eraseAll(),
3 => {},
else => {},
}
@ -346,21 +346,88 @@ fn run(self: *Terminal) !void {
const ps = iter.next() orelse 0;
switch (ps) {
0 => self.back_screen.eraseRight(),
1 => {},
2 => {},
1 => self.back_screen.eraseLeft(),
2 => self.back_screen.eraseLine(),
else => continue,
}
},
// Insert Lines
'L' => {
var iter = seq.iterator(u16);
const n = iter.next() orelse 1;
try self.back_screen.insertLine(n);
},
// Delete Lines
'M' => {
var iter = seq.iterator(u16);
const n = iter.next() orelse 1;
try self.back_screen.deleteLine(n);
},
// Delete Character
'P' => {
var iter = seq.iterator(u16);
const n = iter.next() orelse 1;
try self.back_screen.deleteCharacters(n);
},
// Scroll Up
'S' => {
var iter = seq.iterator(u16);
const n = iter.next() orelse 1;
const cur_row = self.back_screen.cursor.row;
const cur_col = self.back_screen.cursor.col;
const wrap = self.back_screen.cursor.pending_wrap;
defer {
self.back_screen.cursor.row = cur_row;
self.back_screen.cursor.col = cur_col;
self.back_screen.cursor.pending_wrap = wrap;
}
self.back_screen.cursor.col = self.back_screen.scrolling_region.left;
self.back_screen.cursor.row = self.back_screen.scrolling_region.top;
try self.back_screen.deleteLine(n);
},
// Scroll Down
'T' => {
var iter = seq.iterator(u16);
const n = iter.next() orelse 1;
const cur_row = self.back_screen.cursor.row;
const cur_col = self.back_screen.cursor.col;
const wrap = self.back_screen.cursor.pending_wrap;
defer {
self.back_screen.cursor.row = cur_row;
self.back_screen.cursor.col = cur_col;
self.back_screen.cursor.pending_wrap = wrap;
}
self.back_screen.cursor.col = self.back_screen.scrolling_region.left;
self.back_screen.cursor.row = self.back_screen.scrolling_region.top;
try self.back_screen.insertLine(n);
},
'W' => {}, // TODO: Tab control
'X' => {
self.back_screen.cursor.pending_wrap = false;
var iter = seq.iterator(u16);
const n = iter.next() orelse 1;
const start = self.back_screen.cursor.row * self.back_screen.width + self.back_screen.cursor.col;
const end = @max(
self.back_screen.cursor.row * self.back_screen.width + self.back_screen.width,
n,
);
var i: usize = start;
while (i < end) : (i += 1) {
self.back_screen.buf[i].erase(self.back_screen.cursor.style.bg);
}
},
'Z' => {}, // TODO: Back tab
//
// Cursor Vertial Position Aboslute
'd' => {
var iter = seq.iterator(u16);
const n = iter.next() orelse 1;
self.back_screen.cursor.pending_wrap = false;
self.back_screen.cursor.row = @min(
self.back_screen.height -| 1,
n -| 1,
);
},
'h', 'l' => {
var iter = seq.iterator(u16);
const mode = iter.next() orelse continue;