From 497b544c59955478a2b3f2ca6c5903fbb55ab991 Mon Sep 17 00:00:00 2001 From: Tim Culverhouse Date: Wed, 18 Dec 2024 08:43:09 -0600 Subject: [PATCH] vxfw(RichText): fix softwrap of long words The trimmed_width calculation of softwrapped long words was incorrect. Fix the calculation and add a test for the case. --- src/vxfw/RichText.zig | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/vxfw/RichText.zig b/src/vxfw/RichText.zig index 41f029a..58c29ab 100644 --- a/src/vxfw/RichText.zig +++ b/src/vxfw/RichText.zig @@ -288,7 +288,10 @@ pub const SoftwrapIterator = struct { if (cur_width + next_width > max_width) { // Trim the word to see if it can fit on a line by itself const trimmed = trimWSPLeft(word); - const trimmed_width = next_width - trimmed.len; + // New width is the previous width minus the number of cells we trimmed because we + // are only trimming cells that would have been 1 wide (' ' and '\t' both measure as + // 1 wide) + const trimmed_width = next_width -| (word.len - trimmed.len); if (trimmed_width > max_width) { // Won't fit on line by itself, so fit as much on this line as we can for (word) |cell| { @@ -379,6 +382,34 @@ test RichText { } } +test "long word wrapping" { + var rich_text: RichText = .{ + .text = &.{ + .{ .text = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, + }, + }; + + const rich_widget = rich_text.widget(); + + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const ucd = try vaxis.Unicode.init(arena.allocator()); + vxfw.DrawContext.init(&ucd, .unicode); + + const len = rich_text.text[0].text.len; + const width: u16 = 8; + + const ctx: vxfw.DrawContext = .{ + .arena = arena.allocator(), + .min = .{}, + .max = .{ .width = width, .height = null }, + }; + + const surface = try rich_widget.draw(ctx); + // Height should be length / width + try std.testing.expectEqual(len / width, surface.size.height); +} + test "refAllDecls" { std.testing.refAllDecls(@This()); }