From 83377c747018542157c17095c17cf04ac6f9e95b Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 24 Jun 2022 09:31:55 -0700 Subject: [PATCH] decaln --- conformance/esc_decaln.zig | 10 +++++++++ src/Window.zig | 4 ++++ src/terminal/Terminal.zig | 43 ++++++++++++++++++++++++++++++++++++++ src/terminal/stream.zig | 18 ++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 conformance/esc_decaln.zig diff --git a/conformance/esc_decaln.zig b/conformance/esc_decaln.zig new file mode 100644 index 000000000..aeb1887a4 --- /dev/null +++ b/conformance/esc_decaln.zig @@ -0,0 +1,10 @@ +//! DECALN - ESC # 8 +const std = @import("std"); + +pub fn main() !void { + const stdout = std.io.getStdOut().writer(); + try stdout.print("\x1B#8", .{}); + + // const stdin = std.io.getStdIn().reader(); + // _ = try stdin.readByte(); +} diff --git a/src/Window.zig b/src/Window.zig index bb905f664..aaa2c4dce 100644 --- a/src/Window.zig +++ b/src/Window.zig @@ -761,3 +761,7 @@ pub fn setCursorStyle( // it'll be updated the next time the window comes into focus. if (self.focused) try self.updateCursorStyle(grid_style, style.blinking()); } + +pub fn decaln(self: *Window) !void { + self.terminal.decaln(); +} diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index fe1bbc2d3..6c93206ea 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -174,6 +174,27 @@ pub fn print(self: *Terminal, c: u21) !void { } } +/// Resets all margins and fills the whole screen with the character 'E' +/// +/// Sets the cursor to the top left corner. +pub fn decaln(self: *Terminal) void { + // Reset margins, also sets cursor to top-left + self.setScrollingRegion(0, 0); + + // Fill with Es, does not move cursor. We reset fg/bg so we can just + // optimize here by doing row copies. + const filled = self.screen.getRow(0); + var col: usize = 0; + while (col < self.cols) : (col += 1) { + filled[col] = .{ .char = 'E' }; + } + + var row: usize = 1; + while (row < self.rows) : (row += 1) { + std.mem.copy(Screen.Cell, self.screen.getRow(row), filled); + } +} + /// Move the cursor to the previous line in the scrolling region, possibly /// scrolling. /// @@ -950,3 +971,25 @@ test "Terminal: reverseIndex from the top" { try testing.expectEqualStrings("E\nD\nA\nB", str); } } + +test "Terminal: DECALN" { + const alloc = testing.allocator; + var t = try init(alloc, 2, 2); + defer t.deinit(alloc); + + // Initial value + try t.print('A'); + t.carriageReturn(); + t.linefeed(); + try t.print('B'); + t.decaln(); + + try testing.expectEqual(@as(usize, 0), t.cursor.y); + try testing.expectEqual(@as(usize, 0), t.cursor.x); + + { + var str = try t.plainString(testing.allocator); + defer testing.allocator.free(str); + try testing.expectEqualStrings("EE\nEE", str); + } +} diff --git a/src/terminal/stream.zig b/src/terminal/stream.zig index 06c9ecd56..65c759ddc 100644 --- a/src/terminal/stream.zig +++ b/src/terminal/stream.zig @@ -345,6 +345,24 @@ pub fn Stream(comptime Handler: type) type { action: Parser.Action.ESC, ) !void { switch (action.final) { + '8' => blk: { + switch (action.intermediates.len) { + 1 => switch (action.intermediates[0]) { + // DECALN - Fill Screen with E + '#' => if (@hasDecl(T, "decaln")) { + try self.handler.decaln(); + break :blk {}; + } else log.warn("unimplemented ESC callback: {}", .{action}), + + else => {}, + }, + + else => {}, // fall through + } + + log.warn("unimplemented ESC action: {}", .{action}); + }, + // RI - Reverse Index 'M' => if (@hasDecl(T, "reverseIndex")) switch (action.intermediates.len) { 0 => try self.handler.reverseIndex(),