single shift 2/3

This commit is contained in:
Mitchell Hashimoto
2022-08-27 10:16:21 -07:00
parent bee82d58dc
commit 4a247e3bb8
2 changed files with 49 additions and 2 deletions

View File

@ -93,6 +93,9 @@ const CharsetState = struct {
gl: charsets.Slots = .G0, gl: charsets.Slots = .G0,
gr: charsets.Slots = .G2, gr: charsets.Slots = .G2,
/// Single shift where a slot is used for exactly one char.
single_shift: ?charsets.Slots = null,
/// An array to map a charset slot to a lookup table. /// An array to map a charset slot to a lookup table.
const CharsetArray = std.EnumArray(charsets.Slots, charsets.Charset); const CharsetArray = std.EnumArray(charsets.Slots, charsets.Charset);
}; };
@ -407,7 +410,11 @@ pub fn invokeCharset(
slot: charsets.Slots, slot: charsets.Slots,
single: bool, single: bool,
) void { ) void {
assert(!single); // TODO if (single) {
assert(active == .GL);
self.charset.single_shift = slot;
return;
}
switch (active) { switch (active) {
.GL => self.charset.gl = slot, .GL => self.charset.gl = slot,
@ -481,7 +488,11 @@ fn printCell(self: *Terminal, unmapped_c: u21) *Screen.Cell {
const c = c: { const c = c: {
// TODO: non-utf8 handling, gr // TODO: non-utf8 handling, gr
const key = self.charset.gl; // If we're single shifting, then we use the key exactly once.
const key = if (self.charset.single_shift) |key_once| blk: {
self.charset.single_shift = null;
break :blk key_once;
} else self.charset.gl;
const set = self.charset.charsets.get(key); const set = self.charset.charsets.get(key);
// UTF-8 or ASCII is used as-is // UTF-8 or ASCII is used as-is
@ -1342,6 +1353,24 @@ test "Terminal: print invoke charset" {
} }
} }
test "Terminal: print invoke charset single" {
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, true);
try t.print('`');
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" { test "Terminal: linefeed and carriage return" {
var t = try init(testing.allocator, 80, 80); var t = try init(testing.allocator, 80, 80);
defer t.deinit(testing.allocator); defer t.deinit(testing.allocator);

View File

@ -526,6 +526,24 @@ pub fn Stream(comptime Handler: type) type {
}, },
} else log.warn("unimplemented ESC callback: {}", .{action}), } else log.warn("unimplemented ESC callback: {}", .{action}),
// SS2 - Single Shift 2
'N' => if (@hasDecl(T, "invokeCharset")) switch (action.intermediates.len) {
0 => try self.handler.invokeCharset(.GL, .G2, true),
else => {
log.warn("invalid single shift 2 command: {}", .{action});
return;
},
} else log.warn("unimplemented invokeCharset: {}", .{action}),
// SS3 - Single Shift 3
'O' => if (@hasDecl(T, "invokeCharset")) switch (action.intermediates.len) {
0 => try self.handler.invokeCharset(.GL, .G3, true),
else => {
log.warn("invalid single shift 3 command: {}", .{action});
return;
},
} else log.warn("unimplemented invokeCharset: {}", .{action}),
else => if (@hasDecl(T, "escUnimplemented")) else => if (@hasDecl(T, "escUnimplemented"))
try self.handler.escUnimplemented(action) try self.handler.escUnimplemented(action)
else else