diff --git a/src/Window.zig b/src/Window.zig index 513ac44ee..d073d56cf 100644 --- a/src/Window.zig +++ b/src/Window.zig @@ -644,3 +644,28 @@ pub fn deviceAttributes( else => log.warn("unimplemented device attributes req: {}", .{req}), } } + +pub fn deviceStatusReport( + self: *Window, + req: terminal.DeviceStatusReq, +) !void { + switch (req) { + .operating_status => self.queueWrite("\x1B[0n") catch |err| + log.warn("error queueing device attr response: {}", .{err}), + + .cursor_position => { + // Response always is at least 4 chars, so this leaves the + // remainder for the row/column as base-10 numbers. This + // will support a very large terminal. + var buf: [32]u8 = undefined; + const resp = try std.fmt.bufPrint(&buf, "\x1B[{};{}R", .{ + self.terminal.cursor.y + 1, + self.terminal.cursor.x + 1, + }); + + try self.queueWrite(resp); + }, + + else => log.warn("unimplemented device status req: {}", .{req}), + } +} diff --git a/src/terminal/ansi.zig b/src/terminal/ansi.zig index d1d581f4c..15097196d 100644 --- a/src/terminal/ansi.zig +++ b/src/terminal/ansi.zig @@ -49,3 +49,12 @@ pub const DeviceAttributeReq = enum { secondary, // > tertiary, // = }; + +/// The device status request type (ESC [ n). +pub const DeviceStatusReq = enum(u16) { + operating_status = 5, + cursor_position = 6, + + // Non-exhaustive so that @intToEnum never fails for unsupported modes. + _, +}; diff --git a/src/terminal/main.zig b/src/terminal/main.zig index b559e53e3..e1cc8269e 100644 --- a/src/terminal/main.zig +++ b/src/terminal/main.zig @@ -7,6 +7,7 @@ pub const Terminal = @import("Terminal.zig"); pub const Parser = @import("Parser.zig"); pub const Stream = stream.Stream; pub const DeviceAttributeReq = ansi.DeviceAttributeReq; +pub const DeviceStatusReq = ansi.DeviceStatusReq; pub const Mode = ansi.Mode; pub const EraseDisplay = csi.EraseDisplay; pub const EraseLine = csi.EraseLine; diff --git a/src/terminal/stream.zig b/src/terminal/stream.zig index 9f539fa00..5bf796a76 100644 --- a/src/terminal/stream.zig +++ b/src/terminal/stream.zig @@ -295,12 +295,22 @@ pub fn Stream(comptime Handler: type) type { while (p.next()) |attr| try self.handler.setAttribute(attr); } else log.warn("unimplemented CSI callback: {}", .{action}), + // CPR - Request Cursor Postion Report + // TODO: test + 'n' => if (@hasDecl(T, "deviceStatusReport")) try self.handler.deviceStatusReport( + switch (action.params.len) { + 1 => @intToEnum(ansi.DeviceStatusReq, action.params[0]), + else => { + log.warn("invalid erase characters command: {}", .{action}); + return; + }, + }, + ) else log.warn("unimplemented CSI callback: {}", .{action}), + // DECSTBM - Set Top and Bottom Margins // TODO: test 'r' => if (@hasDecl(T, "setTopAndBottomMargin")) switch (action.params.len) { - 0 => try self.handler.setTopAndBottomMargin(1, 0), 1 => try self.handler.setTopAndBottomMargin(action.params[0], 0), - 2 => try self.handler.setTopAndBottomMargin(action.params[0], action.params[1]), else => log.warn("invalid DECSTBM command: {}", .{action}), } else log.warn("unimplemented CSI callback: {}", .{action}),