diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index bbc117a19..3c97da02e 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -3600,58 +3600,63 @@ pub fn printAttributes(self: *Terminal, buf: []u8) ![]const u8 { try writer.writeByte('0'); const pen = self.screens.active.cursor.style; - var attrs: [8]u8 = @splat(0); + var attrs: [9]u8 = @splat(0); var i: usize = 0; if (pen.flags.bold) { - attrs[i] = '1'; + attrs[i] = 1; i += 1; } if (pen.flags.faint) { - attrs[i] = '2'; + attrs[i] = 2; i += 1; } if (pen.flags.italic) { - attrs[i] = '3'; + attrs[i] = 3; i += 1; } if (pen.flags.underline != .none) { - attrs[i] = '4'; + attrs[i] = 4; + i += 1; + } + + if (pen.flags.overline) { + attrs[i] = 53; i += 1; } if (pen.flags.blink) { - attrs[i] = '5'; + attrs[i] = 5; i += 1; } if (pen.flags.inverse) { - attrs[i] = '7'; + attrs[i] = 7; i += 1; } if (pen.flags.invisible) { - attrs[i] = '8'; + attrs[i] = 8; i += 1; } if (pen.flags.strikethrough) { - attrs[i] = '9'; + attrs[i] = 9; i += 1; } - for (attrs[0..i]) |c| { - // Preserve underline styles. Kind of a hack to special case '4' + for (attrs[0..i]) |attr| { + // Preserve underline styles. Kind of a hack to special case 4 // here but its easier than changing how we do all attributes. - if (c == '4' and pen.flags.underline != .single) { + if (attr == 4 and pen.flags.underline != .single) { try writer.print(";4:{}", .{@intFromEnum(pen.flags.underline)}); continue; } - try writer.print(";{c}", .{c}); + try writer.print(";{}", .{attr}); } switch (pen.fg_color) { @@ -14057,11 +14062,12 @@ test "Terminal: printAttributes" { try t.setAttribute(.inverse); try t.setAttribute(.invisible); try t.setAttribute(.strikethrough); + try t.setAttribute(.overline); try t.setAttribute(.{ .direct_color_fg = .{ .r = 100, .g = 200, .b = 255 } }); try t.setAttribute(.{ .direct_color_bg = .{ .r = 101, .g = 102, .b = 103 } }); defer t.setAttribute(.unset) catch unreachable; const buf = try t.printAttributes(&storage); - try testing.expectEqualStrings("0;1;2;3;4;5;7;8;9;38:2::100:200:255;48:2::101:102:103", buf); + try testing.expectEqualStrings("0;1;2;3;4;53;5;7;8;9;38:2::100:200:255;48:2::101:102:103", buf); } const Case = struct { diff --git a/src/terminal/dcs.zig b/src/terminal/dcs.zig index bc183dcf5..a76ab31ba 100644 --- a/src/terminal/dcs.zig +++ b/src/terminal/dcs.zig @@ -523,6 +523,7 @@ test "DECRQSS largest response fits fixed buffer" { try t.setAttribute(.inverse); try t.setAttribute(.invisible); try t.setAttribute(.strikethrough); + try t.setAttribute(.overline); try t.setAttribute(.{ .direct_color_fg = .{ .r = 255, .g = 255, @@ -538,7 +539,7 @@ test "DECRQSS largest response fits fixed buffer" { const encoded = try Command.DECRQSS.sgr.encode(&t, &buf); const expected = - "\x1BP1$r0;1;2;3;4:5;5;7;8;9" ++ + "\x1BP1$r0;1;2;3;4:5;53;5;7;8;9" ++ ";38:2::255:255:255" ++ ";48:2::255:255:255m\x1B\\"; try testing.expectEqualStrings(expected, encoded); diff --git a/src/terminal/stream_terminal.zig b/src/terminal/stream_terminal.zig index 0b2940d1c..1aa8f5579 100644 --- a/src/terminal/stream_terminal.zig +++ b/src/terminal/stream_terminal.zig @@ -1449,13 +1449,17 @@ test "DECRQSS responses" { s.nextSlice("\x1B[1m\x1BP$qm\x1B\\"); try S.expectResponse("\x1BP1$r0;1m\x1B\\"); + // Overline + s.nextSlice("\x1B[0;53m\x1BP$qm\x1B\\"); + try S.expectResponse("\x1BP1$r0;53m\x1B\\"); + // Requests larger than the parser's fixed request buffer are ignored, // and the next DCS command must still be processed normally. s.nextSlice("\x1BP$qfoo\x1B\\"); try testing.expectEqual(@as(usize, 0), S.calls); try testing.expect(!s.handler.semantic_failure); s.nextSlice("\x1BP$qm\x1B\\"); - try S.expectResponse("\x1BP1$r0;1m\x1B\\"); + try S.expectResponse("\x1BP1$r0;53m\x1B\\"); } test "DECRQSS without write effect is ignored" {