DVUI

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 => {},
    }
}