terminal: decaln

This commit is contained in:
Mitchell Hashimoto
2023-10-09 20:33:52 -07:00
parent 7cc0bbe211
commit be99d8ffe1
2 changed files with 118 additions and 8 deletions

View File

@ -866,16 +866,37 @@ pub fn decaln(self: *Terminal) !void {
defer tracy.end(); defer tracy.end();
// Reset margins, also sets cursor to top-left // Reset margins, also sets cursor to top-left
self.setTopAndBottomMargin(0, 0); self.scrolling_region = .{
.top = 0,
.bottom = self.rows - 1,
.left = 0,
.right = self.cols - 1,
};
// Fill with Es, does not move cursor. We reset fg/bg so we can just // Origin mode is disabled
// optimize here by doing row copies. self.modes.set(.origin, false);
const filled = self.screen.getRow(.{ .active = 0 });
filled.fill(.{ .char = 'E' });
var row: usize = 1; // Move our cursor to the top-left
while (row < self.rows) : (row += 1) { self.setCursorPos(1, 1);
try self.screen.getRow(.{ .active = row }).copyRow(filled);
// Clear our stylistic attributes
self.screen.cursor.pen = .{
.bg = self.screen.cursor.pen.bg,
.fg = self.screen.cursor.pen.fg,
.attrs = .{
.has_bg = self.screen.cursor.pen.attrs.has_bg,
.has_fg = self.screen.cursor.pen.attrs.has_fg,
.protected = self.screen.cursor.pen.attrs.protected,
},
};
// Our pen has the letter E
var pen: Screen.Cell = .{ .char = 'E' };
// Fill with Es, does not move cursor.
for (0..self.rows) |y| {
const filled = self.screen.getRow(.{ .active = y });
filled.fill(pen);
} }
} }
@ -3397,6 +3418,50 @@ test "Terminal: DECALN" {
} }
} }
test "Terminal: decaln reset margins" {
const alloc = testing.allocator;
var t = try init(alloc, 3, 3);
defer t.deinit(alloc);
// Initial value
t.modes.set(.origin, true);
t.setTopAndBottomMargin(2, 3);
try t.decaln();
try t.scrollDown(1);
{
var str = try t.plainString(testing.allocator);
defer testing.allocator.free(str);
try testing.expectEqualStrings("\nEEE\nEEE", str);
}
}
test "Terminal: decaln preserves color" {
const alloc = testing.allocator;
var t = try init(alloc, 3, 3);
defer t.deinit(alloc);
const pen: Screen.Cell = .{
.bg = .{ .r = 0xFF, .g = 0x00, .b = 0x00 },
.attrs = .{ .has_bg = true },
};
// Initial value
t.screen.cursor.pen = pen;
t.modes.set(.origin, true);
t.setTopAndBottomMargin(2, 3);
try t.decaln();
try t.scrollDown(1);
{
var str = try t.plainString(testing.allocator);
defer testing.allocator.free(str);
try testing.expectEqualStrings("\nEEE\nEEE", str);
const cell = t.screen.getCell(.active, 0, 0);
try testing.expectEqual(pen, cell);
}
}
test "Terminal: insertBlanks" { test "Terminal: insertBlanks" {
// NOTE: this is not verified with conformance tests, so these // NOTE: this is not verified with conformance tests, so these
// tests might actually be verifying wrong behavior. // tests might actually be verifying wrong behavior.

View File

@ -0,0 +1,45 @@
import VTSequence from "@/components/VTSequence";
# Screen Alignment Test (DECALN)
<VTSequence sequence={["ESC", "#", "8"]} />
Reset margins, move cursor to the top left, and fill the screen with `E`.
Reset the top, bottom, left, and right margins and unset [origin mode](#TODO).
The cursor is moved to the top-left corner of the screen.
All stylistic SGR attributes are unset, such as bold, blink, etc.
SGR foreground and background colors are preserved.
The [protected attribute](#TODO) is not unset.
The entire screen is filled with the character `E`. The letter `E` ignores
the current SGR settings and is written with no styling.
## Validation
### DECALN V-1: Simple Usage
```bash
printf "\033#8"
```
```
|EEEEEEEE|
|EEEEEEEE|
|EEEEEEEE|
```
### DECALN V-2: Reset Margins
```bash
printf "\033[2;3r" # scroll region top/bottom
printf "\033#8"
printf "\033[T"
```
```
|c_______|
|EEEEEEEE|
|EEEEEEEE|
```