···2233const Screen = @import("Screen.zig");
44const Cell = @import("cell.zig").Cell;
55+const gw = @import("gwidth.zig");
5667const log = std.log.scoped(.window);
78···7071/// fills the window with the default cell
7172pub fn clear(self: Window) void {
7273 self.fill(.{});
7474+}
7575+7676+/// returns the width of the grapheme. This depends on the terminal capabilities
7777+pub fn gwidth(self: Window, str: []const u8) usize {
7878+ const m: gw.Method = if (self.screen.unicode) .unicode else .wcwidth;
7979+ log.info("using method {any}", .{m});
8080+ return gw.gwidth(str, m) catch 1;
7381}
74827583/// fills the window with the provided cell
+13-7
src/vaxis.zig
···1212const Options = @import("Options.zig");
1313const Style = @import("cell.zig").Style;
1414const strWidth = @import("ziglyph").display_width.strWidth;
1515+const gwidth = @import("gwidth.zig");
15161617/// Vaxis is the entrypoint for a Vaxis application. The provided type T should
1718/// be a tagged union which contains all of the events the application will
···141142 log.debug("resizing screen: width={d} height={d}", .{ winsize.cols, winsize.rows });
142143 self.screen.deinit(alloc);
143144 self.screen = try Screen.init(alloc, winsize.cols, winsize.rows);
145145+ self.screen.unicode = self.caps.unicode;
144146 // try self.screen.int(alloc, winsize.cols, winsize.rows);
145147 // we only init our current screen. This has the effect of redrawing
146148 // every cell
···270272 const cell = self.screen.buf[i];
271273 defer {
272274 // advance by the width of this char mod 1
273273- const width = blk: {
274274- if (cell.char.width > 0) break :blk cell.char.width;
275275- break :blk strWidth(cell.char.grapheme, .half) catch 1;
276276- };
277277- col += width;
278278- i += width;
275275+ const method: gwidth.Method = if (self.caps.unicode) .unicode else .wcwidth;
276276+ const w = gwidth.gwidth(cell.char.grapheme, method) catch 1;
277277+ var j = i + 1;
278278+ while (j < i + w) : (j += 1) {
279279+ self.screen_last.buf[j].skipped = true;
280280+ }
281281+ col += w;
282282+ i += w;
279283 }
280284 if (col >= self.screen.width) {
281285 row += 1;
···283287 }
284288 // If cell is the same as our last frame, we don't need to do
285289 // anything
286286- if (!self.refresh and self.screen_last.buf[i].eql(cell)) {
290290+ const last = self.screen_last.buf[i];
291291+ if (!self.refresh and last.eql(cell) and !last.skipped) {
287292 reposition = true;
288293 // Close any osc8 sequence we might be in before
289294 // repositioning
···292297 }
293298 continue;
294299 }
300300+ self.screen_last.buf[i].skipped = false;
295301 defer cursor = cell.style;
296302 // Set this cell in the last frame
297303 self.screen_last.writeCell(col, row, cell.char.grapheme, cell.style);