setLen
Sets the new length and does fixups:
- add null terminator if there is space
- shrink allocation if needed
- fixup array_list backing
Parameters
- self:*TextEntryWidget
- *TextEntryWidget
- newlen:usize
- usize
Source
Implementation
pub fn setLen(self: *TextEntryWidget, newlen: usize) void {
self.len = newlen;
// add null terminator if there is space
if (self.len < self.text.len) {
self.text[self.len] = 0;
}
// shrink allocation if needed
const needed_binds = @divTrunc(self.len, realloc_bin_size) + 1;
const current_bins = @divTrunc(self.text.len, realloc_bin_size);
// dvui.log.debug("TextEntry {x} needs {d} bins, has {d}", .{ self.data().id, needed_binds, current_bins });
if (self.len == 0 or needed_binds < current_bins) {
// we want to shrink the allocation
const new_len = if (self.len == 0) 0 else realloc_bin_size * needed_binds;
switch (self.init_opts.text) {
.buffer => {},
.buffer_dynamic => |b| {
if (b.allocator.resize(self.text, new_len)) {
b.backing.*.len = new_len;
self.text.len = new_len;
} else {
dvui.logError(@src(), std.mem.Allocator.Error.OutOfMemory, "{x} TextEntryWidget.textTyped failed to realloc backing (current size {d}, new size {d})", .{ self.data().id, self.text.len, new_len });
}
},
.array_list => |al| {
if (new_len < al.backing.capacity / 2) {
al.backing.items.len = al.backing.capacity;
al.backing.shrinkAndFree(al.allocator, new_len);
self.text = al.backing.items.ptr[0..@min(al.limit, al.backing.capacity)];
}
},
.internal => {
// NOTE: Using prev_text is safe because data is trashed and stays valid until the end of the frame
const prev_text = self.text;
dvui.dataSetSliceCopies(null, self.data().id, "_buffer", &[_]u8{0}, new_len);
self.text = dvui.dataGetSlice(null, self.data().id, "_buffer", []u8).?;
const min_len = @min(prev_text.len, self.text.len);
@memcpy(self.text[0..min_len], prev_text[0..min_len]);
},
}
}
// fixup array_list backing
switch (self.init_opts.text) {
.array_list => |al| {
al.backing.items.len = self.len;
},
else => {},
}
}