terminal: convert C0
parent
f7189d14b9
commit
2ef89c153a
|
|
@ -145,6 +145,7 @@ const Handler = struct {
|
|||
) !void {
|
||||
switch (action) {
|
||||
.print => try self.t.print(value.cp),
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,16 +1,19 @@
|
|||
const std = @import("std");
|
||||
const build_options = @import("terminal_options");
|
||||
const assert = std.debug.assert;
|
||||
const LibEnum = @import("../lib/enum.zig").Enum;
|
||||
|
||||
/// The available charset slots for a terminal.
|
||||
pub const Slots = enum(u3) {
|
||||
G0 = 0,
|
||||
G1 = 1,
|
||||
G2 = 2,
|
||||
G3 = 3,
|
||||
};
|
||||
pub const Slots = LibEnum(
|
||||
if (build_options.c_abi) .c else .zig,
|
||||
&.{ "G0", "G1", "G2", "G3" },
|
||||
);
|
||||
|
||||
/// The name of the active slots.
|
||||
pub const ActiveSlot = enum { GL, GR };
|
||||
pub const ActiveSlot = LibEnum(
|
||||
if (build_options.c_abi) .c else .zig,
|
||||
&.{ "GL", "GR" },
|
||||
);
|
||||
|
||||
/// The list of supported character sets and their associated tables.
|
||||
pub const Charset = enum {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ const build_options = @import("terminal_options");
|
|||
const assert = std.debug.assert;
|
||||
const testing = std.testing;
|
||||
const simd = @import("../simd/main.zig");
|
||||
const LibEnum = @import("../lib/enum.zig").Enum;
|
||||
const LibUnion = @import("../lib/union.zig").TaggedUnion;
|
||||
const lib = @import("../lib/main.zig");
|
||||
const Parser = @import("Parser.zig");
|
||||
const ansi = @import("ansi.zig");
|
||||
const charsets = @import("charsets.zig");
|
||||
|
|
@ -28,20 +27,40 @@ const log = std.log.scoped(.stream);
|
|||
/// do something else.
|
||||
const debug = false;
|
||||
|
||||
const lib_target: lib.Target = if (build_options.c_abi) .c else .zig;
|
||||
|
||||
pub const Action = union(Key) {
|
||||
print: Print,
|
||||
bell,
|
||||
backspace,
|
||||
horizontal_tab: HorizontalTab,
|
||||
linefeed,
|
||||
carriage_return,
|
||||
enquiry,
|
||||
invoke_charset: InvokeCharset,
|
||||
|
||||
pub const Key = LibEnum(
|
||||
if (build_options.c_abi) .c else .zig,
|
||||
pub const Key = lib.Enum(
|
||||
lib_target,
|
||||
&.{
|
||||
"print",
|
||||
"bell",
|
||||
"backspace",
|
||||
"horizontal_tab",
|
||||
"linefeed",
|
||||
"carriage_return",
|
||||
"enquiry",
|
||||
"invoke_charset",
|
||||
},
|
||||
);
|
||||
|
||||
/// C ABI functions.
|
||||
const c_union = LibUnion(@This(), extern struct {
|
||||
x: u64,
|
||||
});
|
||||
const c_union = lib.TaggedUnion(
|
||||
lib_target,
|
||||
@This(),
|
||||
// TODO: Before shipping an ABI-compatible libghostty, verify this.
|
||||
// This was just arbitrarily chosen for now.
|
||||
[8]u64,
|
||||
);
|
||||
pub const Tag = c_union.Tag;
|
||||
pub const Value = c_union.Value;
|
||||
pub const C = c_union.C;
|
||||
|
|
@ -60,6 +79,16 @@ pub const Action = union(Key) {
|
|||
return .{ .cp = @intCast(self.cp) };
|
||||
}
|
||||
};
|
||||
|
||||
pub const HorizontalTab = lib.Struct(lib_target, struct {
|
||||
count: u16,
|
||||
});
|
||||
|
||||
pub const InvokeCharset = lib.Struct(lib_target, struct {
|
||||
bank: charsets.ActiveSlot,
|
||||
charset: charsets.Slots,
|
||||
locking: bool,
|
||||
});
|
||||
};
|
||||
|
||||
/// Returns a type that can process a stream of tty control characters.
|
||||
|
|
@ -383,45 +412,14 @@ pub fn Stream(comptime Handler: type) type {
|
|||
// We ignore SOH/STX: https://github.com/microsoft/terminal/issues/10786
|
||||
.NUL, .SOH, .STX => {},
|
||||
|
||||
.ENQ => if (@hasDecl(T, "enquiry"))
|
||||
try self.handler.enquiry()
|
||||
else
|
||||
log.warn("unimplemented execute: {x}", .{c}),
|
||||
|
||||
.BEL => if (@hasDecl(T, "bell"))
|
||||
try self.handler.bell()
|
||||
else
|
||||
log.warn("unimplemented execute: {x}", .{c}),
|
||||
|
||||
.BS => if (@hasDecl(T, "backspace"))
|
||||
try self.handler.backspace()
|
||||
else
|
||||
log.warn("unimplemented execute: {x}", .{c}),
|
||||
|
||||
.HT => if (@hasDecl(T, "horizontalTab"))
|
||||
try self.handler.horizontalTab(1)
|
||||
else
|
||||
log.warn("unimplemented execute: {x}", .{c}),
|
||||
|
||||
.LF, .VT, .FF => if (@hasDecl(T, "linefeed"))
|
||||
try self.handler.linefeed()
|
||||
else
|
||||
log.warn("unimplemented execute: {x}", .{c}),
|
||||
|
||||
.CR => if (@hasDecl(T, "carriageReturn"))
|
||||
try self.handler.carriageReturn()
|
||||
else
|
||||
log.warn("unimplemented execute: {x}", .{c}),
|
||||
|
||||
.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}),
|
||||
.ENQ => try self.handler.vt(.enquiry, {}),
|
||||
.BEL => try self.handler.vt(.bell, {}),
|
||||
.BS => try self.handler.vt(.backspace, {}),
|
||||
.HT => try self.handler.vt(.horizontal_tab, .{ .count = 1 }),
|
||||
.LF, .VT, .FF => try self.handler.vt(.linefeed, {}),
|
||||
.CR => try self.handler.vt(.carriage_return, {}),
|
||||
.SO => try self.handler.vt(.invoke_charset, .{ .bank = .GL, .charset = .G1, .locking = false }),
|
||||
.SI => try self.handler.vt(.invoke_charset, .{ .bank = .GL, .charset = .G0, .locking = false }),
|
||||
|
||||
else => log.warn("invalid C0 character, ignoring: 0x{x}", .{c}),
|
||||
}
|
||||
|
|
@ -1902,6 +1900,12 @@ pub fn Stream(comptime Handler: type) type {
|
|||
};
|
||||
}
|
||||
|
||||
test Action {
|
||||
// Forces the C type to be reified when the target is C, ensuring
|
||||
// all our types are C ABI compatible.
|
||||
_ = Action.C;
|
||||
}
|
||||
|
||||
test "stream: print" {
|
||||
const H = struct {
|
||||
c: ?u21 = 0,
|
||||
|
|
|
|||
|
|
@ -195,6 +195,13 @@ pub const StreamHandler = struct {
|
|||
) !void {
|
||||
switch (action) {
|
||||
.print => try self.terminal.print(value.cp),
|
||||
.bell => self.bell(),
|
||||
.backspace => self.terminal.backspace(),
|
||||
.horizontal_tab => try self.horizontalTab(value.count),
|
||||
.linefeed => try self.linefeed(),
|
||||
.carriage_return => self.terminal.carriageReturn(),
|
||||
.enquiry => try self.enquiry(),
|
||||
.invoke_charset => self.terminal.invokeCharset(value.bank, value.charset, value.locking),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -338,15 +345,11 @@ pub const StreamHandler = struct {
|
|||
try self.terminal.printRepeat(count);
|
||||
}
|
||||
|
||||
pub inline fn bell(self: *StreamHandler) !void {
|
||||
inline fn bell(self: *StreamHandler) void {
|
||||
self.surfaceMessageWriter(.ring_bell);
|
||||
}
|
||||
|
||||
pub inline fn backspace(self: *StreamHandler) !void {
|
||||
self.terminal.backspace();
|
||||
}
|
||||
|
||||
pub inline fn horizontalTab(self: *StreamHandler, count: u16) !void {
|
||||
inline fn horizontalTab(self: *StreamHandler, count: u16) !void {
|
||||
for (0..count) |_| {
|
||||
const x = self.terminal.screen.cursor.x;
|
||||
try self.terminal.horizontalTab();
|
||||
|
|
@ -362,16 +365,12 @@ pub const StreamHandler = struct {
|
|||
}
|
||||
}
|
||||
|
||||
pub inline fn linefeed(self: *StreamHandler) !void {
|
||||
inline fn linefeed(self: *StreamHandler) !void {
|
||||
// Small optimization: call index instead of linefeed because they're
|
||||
// identical and this avoids one layer of function call overhead.
|
||||
try self.terminal.index();
|
||||
}
|
||||
|
||||
pub inline fn carriageReturn(self: *StreamHandler) !void {
|
||||
self.terminal.carriageReturn();
|
||||
}
|
||||
|
||||
pub inline fn setCursorLeft(self: *StreamHandler, amount: u16) !void {
|
||||
self.terminal.cursorLeft(amount);
|
||||
}
|
||||
|
|
@ -896,15 +895,6 @@ pub const StreamHandler = struct {
|
|||
self.terminal.configureCharset(slot, set);
|
||||
}
|
||||
|
||||
pub fn invokeCharset(
|
||||
self: *StreamHandler,
|
||||
active: terminal.CharsetActiveSlot,
|
||||
slot: terminal.CharsetSlot,
|
||||
single: bool,
|
||||
) !void {
|
||||
self.terminal.invokeCharset(active, slot, single);
|
||||
}
|
||||
|
||||
pub fn fullReset(
|
||||
self: *StreamHandler,
|
||||
) !void {
|
||||
|
|
|
|||
Loading…
Reference in New Issue