diff --git a/src/Window.zig b/src/Window.zig index 7b533a0ee..575680dc4 100644 --- a/src/Window.zig +++ b/src/Window.zig @@ -1552,7 +1552,8 @@ pub fn deviceAttributes( _ = params; switch (req) { - .primary => self.queueWrite("\x1B[?6c") catch |err| + // VT220 + .primary => self.queueWrite("\x1B[?62;c") catch |err| log.warn("error queueing device attr response: {}", .{err}), else => log.warn("unimplemented device attributes req: {}", .{req}), } @@ -1640,3 +1641,12 @@ pub fn configureCharset( ) !void { self.terminal.configureCharset(slot, set); } + +pub fn invokeCharset( + self: *Window, + active: terminal.CharsetActiveSlot, + slot: terminal.CharsetSlot, + single: bool, +) !void { + self.terminal.invokeCharset(active, slot, single); +} diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index ba40fb19a..f733f1f17 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -399,6 +399,22 @@ pub fn configureCharset(self: *Terminal, slot: charsets.Slots, set: charsets.Cha self.charset.charsets.set(slot, set); } +/// Invoke the charset in slot into the active slot. If single is true, +/// then this will only be invoked for a single character. +pub fn invokeCharset( + self: *Terminal, + active: charsets.ActiveSlot, + slot: charsets.Slots, + single: bool, +) void { + assert(!single); // TODO + + switch (active) { + .GL => self.charset.gl = slot, + .GR => self.charset.gr = slot, + } +} + pub fn print(self: *Terminal, c: u21) !void { const tracy = trace(@src()); defer tracy.end(); @@ -1306,6 +1322,26 @@ test "Terminal: print charset" { } } +test "Terminal: print invoke charset" { + var t = try init(testing.allocator, 80, 80); + defer t.deinit(testing.allocator); + + t.configureCharset(.G1, .dec_special); + + // Basic grid writing + try t.print('`'); + t.invokeCharset(.GL, .G1, false); + try t.print('`'); + try t.print('`'); + t.invokeCharset(.GL, .G0, false); + try t.print('`'); + { + var str = try t.plainString(testing.allocator); + defer testing.allocator.free(str); + try testing.expectEqualStrings("`◆◆`", str); + } +} + test "Terminal: linefeed and carriage return" { var t = try init(testing.allocator, 80, 80); defer t.deinit(testing.allocator); diff --git a/src/terminal/charsets.zig b/src/terminal/charsets.zig index 798adb326..e6ebe21aa 100644 --- a/src/terminal/charsets.zig +++ b/src/terminal/charsets.zig @@ -9,6 +9,9 @@ pub const Slots = enum(u3) { G3 = 3, }; +/// The name of the active slots. +pub const ActiveSlot = enum { GL, GR }; + /// The list of supported character sets and their associated tables. pub const Charset = enum { utf8, diff --git a/src/terminal/main.zig b/src/terminal/main.zig index ae10f8e7c..a1a1d0d34 100644 --- a/src/terminal/main.zig +++ b/src/terminal/main.zig @@ -10,6 +10,7 @@ pub const color = @import("color.zig"); pub const Charset = charsets.Charset; pub const CharsetSlot = charsets.Slots; +pub const CharsetActiveSlot = charsets.ActiveSlot; pub const Terminal = @import("Terminal.zig"); pub const Parser = @import("Parser.zig"); pub const Selection = @import("Selection.zig"); diff --git a/src/terminal/stream.zig b/src/terminal/stream.zig index 4219f9551..f6778b575 100644 --- a/src/terminal/stream.zig +++ b/src/terminal/stream.zig @@ -109,8 +109,15 @@ pub fn Stream(comptime Handler: type) type { else log.warn("unimplemented execute: {x}", .{c}), - // TODO - .SO, .SI => log.warn("TODO: Shift out/Shift in", .{}), + .SO => if (@hasDecl(T, "invokeCharset")) + try self.handler.invokeCharset(.GL, .G1, false) + else + log.warn("unimplemented invokeCharset: {x}", .{c}), + + .SI => if (@hasDecl(T, "invokeCharset")) + try self.handler.invokeCharset(.GL, .G0, false) + else + log.warn("unimplemented invokeCharset: {x}", .{c}), } }