aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/src/terminal/c/paste.zig
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-04-04 19:22:04 +0300
committerCan Celik <ogulcancelik@gmail.com>2026-04-05 01:23:06 +0300
commit41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch)
tree3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/src/terminal/c/paste.zig
parent55c138263e190a1e79d4b997bfb9397306c0ec1f (diff)
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/src/terminal/c/paste.zig')
-rw-r--r--vendor/libghostty-vt/src/terminal/c/paste.zig129
1 files changed, 129 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/terminal/c/paste.zig b/vendor/libghostty-vt/src/terminal/c/paste.zig
new file mode 100644
index 00000000..bce6a565
--- /dev/null
+++ b/vendor/libghostty-vt/src/terminal/c/paste.zig
@@ -0,0 +1,129 @@
+const std = @import("std");
+const lib = @import("../lib.zig");
+const paste = @import("../../input/paste.zig");
+const Result = @import("result.zig").Result;
+
+pub fn is_safe(data: ?[*]const u8, len: usize) callconv(lib.calling_conv) bool {
+ const slice: []const u8 = if (data) |v| v[0..len] else &.{};
+ return paste.isSafe(slice);
+}
+
+pub fn encode(
+ data: ?[*]u8,
+ data_len: usize,
+ bracketed: bool,
+ out_: ?[*]u8,
+ out_len: usize,
+ out_written: *usize,
+) callconv(lib.calling_conv) Result {
+ const slice: []u8 = if (data) |v| v[0..data_len] else &.{};
+ const result = paste.encode(slice, .{ .bracketed = bracketed });
+
+ const total = result[0].len + result[1].len + result[2].len;
+ out_written.* = total;
+
+ const out: []u8 = if (out_) |o| o[0..out_len] else &.{};
+ if (out.len < total) return .out_of_space;
+
+ var offset: usize = 0;
+ for (result) |segment| {
+ @memcpy(out[offset..][0..segment.len], segment);
+ offset += segment.len;
+ }
+
+ return .success;
+}
+
+test "encode bracketed" {
+ const testing = std.testing;
+ const input = try testing.allocator.dupe(u8, "hello");
+ defer testing.allocator.free(input);
+ var buf: [64]u8 = undefined;
+ var written: usize = 0;
+ const result = encode(input.ptr, input.len, true, &buf, buf.len, &written);
+ try testing.expectEqual(.success, result);
+ try testing.expectEqualStrings("\x1b[200~hello\x1b[201~", buf[0..written]);
+}
+
+test "encode unbracketed no newlines" {
+ const testing = std.testing;
+ const input = try testing.allocator.dupe(u8, "hello");
+ defer testing.allocator.free(input);
+ var buf: [64]u8 = undefined;
+ var written: usize = 0;
+ const result = encode(input.ptr, input.len, false, &buf, buf.len, &written);
+ try testing.expectEqual(.success, result);
+ try testing.expectEqualStrings("hello", buf[0..written]);
+}
+
+test "encode unbracketed newlines" {
+ const testing = std.testing;
+ const input = try testing.allocator.dupe(u8, "hello\nworld");
+ defer testing.allocator.free(input);
+ var buf: [64]u8 = undefined;
+ var written: usize = 0;
+ const result = encode(input.ptr, input.len, false, &buf, buf.len, &written);
+ try testing.expectEqual(.success, result);
+ try testing.expectEqualStrings("hello\rworld", buf[0..written]);
+}
+
+test "encode strip unsafe bytes" {
+ const testing = std.testing;
+ const input = try testing.allocator.dupe(u8, "hel\x1blo\x00world");
+ defer testing.allocator.free(input);
+ var buf: [64]u8 = undefined;
+ var written: usize = 0;
+ const result = encode(input.ptr, input.len, true, &buf, buf.len, &written);
+ try testing.expectEqual(.success, result);
+ try testing.expectEqualStrings("\x1b[200~hel lo world\x1b[201~", buf[0..written]);
+}
+
+test "encode with insufficient buffer" {
+ const testing = std.testing;
+ const input = try testing.allocator.dupe(u8, "hello");
+ defer testing.allocator.free(input);
+ var buf: [1]u8 = undefined;
+ var written: usize = 0;
+ const result = encode(input.ptr, input.len, true, &buf, buf.len, &written);
+ try testing.expectEqual(.out_of_space, result);
+ try testing.expectEqual(17, written);
+}
+
+test "encode with null buffer" {
+ const testing = std.testing;
+ const input = try testing.allocator.dupe(u8, "hello");
+ defer testing.allocator.free(input);
+ var written: usize = 0;
+ const result = encode(input.ptr, input.len, true, null, 0, &written);
+ try testing.expectEqual(.out_of_space, result);
+ try testing.expectEqual(17, written);
+}
+
+test "is_safe with safe data" {
+ const testing = std.testing;
+ const safe = "hello world";
+ try testing.expect(is_safe(safe.ptr, safe.len));
+}
+
+test "is_safe with newline" {
+ const testing = std.testing;
+ const unsafe = "hello\nworld";
+ try testing.expect(!is_safe(unsafe.ptr, unsafe.len));
+}
+
+test "is_safe with bracketed paste end" {
+ const testing = std.testing;
+ const unsafe = "hello\x1b[201~world";
+ try testing.expect(!is_safe(unsafe.ptr, unsafe.len));
+}
+
+test "is_safe with empty data" {
+ const testing = std.testing;
+ const empty = "";
+ try testing.expect(is_safe(empty.ptr, 0));
+}
+
+test "is_safe with null empty data" {
+ const testing = std.testing;
+ try testing.expect(is_safe(null, 0));
+}