f_setcellwidths(typval_T *argvars, typval_T *rettv UNUSED)
{
    list_T	    *l;
    listitem_T	    *li;
    int		    item;
    int		    i;
    listitem_T	    **ptrs;
    cw_interval_T   *table;
    cw_interval_T   *cw_table_save;
    size_t	    cw_table_size_save;
    char	    *error = NULL;

    if (in_vim9script() && check_for_list_arg(argvars, 0) == FAIL)
	return;

    if (argvars[0].v_type != VAR_LIST || argvars[0].vval.v_list == NULL)
    {
	emsg(_(e_list_required));
	return;
    }
    l = argvars[0].vval.v_list;
    if (l->lv_len == 0)
    {
	// Clearing the table.
	vim_free(cw_table);
	cw_table = NULL;
	cw_table_size = 0;
	return;
    }

    ptrs = ALLOC_MULT(listitem_T *, l->lv_len);
    if (ptrs == NULL)
	return;

    // Check that all entries are a list with three numbers, the range is
    // valid and the cell width is valid.
    item = 0;
    for (li = l->lv_first; li != NULL; li = li->li_next)
    {
	listitem_T *lili;
	varnumber_T n1;

	if (li->li_tv.v_type != VAR_LIST || li->li_tv.vval.v_list == NULL)
	{
	    semsg(_(e_list_item_nr_is_not_list), item);
	    vim_free(ptrs);
	    return;
	}

	lili = li->li_tv.vval.v_list->lv_first;
	ptrs[item] = lili;
	for (i = 0; lili != NULL; lili = lili->li_next, ++i)
	{
	    if (lili->li_tv.v_type != VAR_NUMBER)
		break;
	    if (i == 0)
	    {
		n1 = lili->li_tv.vval.v_number;
		if (n1 < 0x100)
		{
		    emsg(_(e_only_values_of_0x100_and_higher_supported));
		    vim_free(ptrs);
		    return;
		}
	    }
	    else if (i == 1 && lili->li_tv.vval.v_number < n1)
	    {
		semsg(_(e_list_item_nr_range_invalid), item);
		vim_free(ptrs);
		return;
	    }
	    else if (i == 2 && (lili->li_tv.vval.v_number < 1
					     || lili->li_tv.vval.v_number > 2))
	    {
		semsg(_(e_list_item_nr_cell_width_invalid), item);
		vim_free(ptrs);
		return;
	    }
	}
	if (i != 3)
	{
	    semsg(_(e_list_item_nr_does_not_contain_3_numbers), item);
	    vim_free(ptrs);
	    return;
	}
	++item;
    }

    // Sort the list on the first number.
    qsort((void *)ptrs, (size_t)l->lv_len, sizeof(listitem_T *), tv_nr_compare);

    table = ALLOC_MULT(cw_interval_T, l->lv_len);
    if (table == NULL)
    {
	vim_free(ptrs);
	return;
    }

    // Store the items in the new table.
    item = 0;
    for (item = 0; item < l->lv_len; ++item)
    {
	listitem_T	*lili = ptrs[item];
	varnumber_T	n1;

	n1 = lili->li_tv.vval.v_number;
	if (item > 0 && n1 <= table[item - 1].last)
	{
	    semsg(_(e_overlapping_ranges_for_nr), (long)n1);
	    vim_free(ptrs);
	    vim_free(table);
	    return;
	}
	table[item].first = n1;
	lili = lili->li_next;
	table[item].last = lili->li_tv.vval.v_number;
	lili = lili->li_next;
	table[item].width = lili->li_tv.vval.v_number;
    }

    vim_free(ptrs);

    cw_table_save = cw_table;
    cw_table_size_save = cw_table_size;
    cw_table = table;
    cw_table_size = l->lv_len;

    // Check that the new value does not conflict with 'listchars' or
    // 'fillchars'.
    error = check_chars_options();
    if (error != NULL)
    {
	emsg(_(error));
	cw_table = cw_table_save;
	cw_table_size = cw_table_size_save;
	vim_free(table);
	return;
    }

    vim_free(cw_table_save);
}
f_setcellwidths(typval_T *argvars, typval_T *rettv UNUSED)
{
    list_T	    *l;
    listitem_T	    *li;
    int		    item;
    int		    i;
    listitem_T	    **ptrs;
    cw_interval_T   *table;
    cw_interval_T   *cw_table_save;
    size_t	    cw_table_size_save;
    char	    *error = NULL;

    if (in_vim9script() && check_for_list_arg(argvars, 0) == FAIL)
	return;

    if (argvars[0].v_type != VAR_LIST || argvars[0].vval.v_list == NULL)
    {
	emsg(_(e_list_required));
	return;
    }
    l = argvars[0].vval.v_list;
    if (l->lv_len == 0)
    {
	 
	vim_free(cw_table);
	cw_table = NULL;
	cw_table_size = 0;
	return;
    }

    ptrs = ALLOC_MULT(listitem_T *, l->lv_len);
    if (ptrs == NULL)
	return;

     
     
    item = 0;
    for (li = l->lv_first; li != NULL; li = li->li_next)
    {
	listitem_T *lili;
	varnumber_T n1;

	if (li->li_tv.v_type != VAR_LIST || li->li_tv.vval.v_list == NULL)
	{
	    semsg(_(e_list_item_nr_is_not_list), item);
	    vim_free(ptrs);
	    return;
	}

	lili = li->li_tv.vval.v_list->lv_first;
	ptrs[item] = lili;
	for (i = 0; lili != NULL; lili = lili->li_next, ++i)
	{
	    if (lili->li_tv.v_type != VAR_NUMBER)
		break;
	    if (i == 0)
	    {
		n1 = lili->li_tv.vval.v_number;
		if (n1 < 0x100)
		{
		    emsg(_(e_only_values_of_0x100_and_higher_supported));
		    vim_free(ptrs);
		    return;
		}
	    }
	    else if (i == 1 && lili->li_tv.vval.v_number < n1)
	    {
		semsg(_(e_list_item_nr_range_invalid), item);
		vim_free(ptrs);
		return;
	    }
	    else if (i == 2 && (lili->li_tv.vval.v_number < 1
					     || lili->li_tv.vval.v_number > 2))
	    {
		semsg(_(e_list_item_nr_cell_width_invalid), item);
		vim_free(ptrs);
		return;
	    }
	}
	if (i != 3)
	{
	    semsg(_(e_list_item_nr_does_not_contain_3_numbers), item);
	    vim_free(ptrs);
	    return;
	}
	++item;
    }

     
    qsort((void *)ptrs, (size_t)l->lv_len, sizeof(listitem_T *), tv_nr_compare);

    table = ALLOC_MULT(cw_interval_T, l->lv_len);
    if (table == NULL)
    {
	vim_free(ptrs);
	return;
    }

     
    item = 0;
    for (item = 0; item < l->lv_len; ++item)
    {
	listitem_T	*lili = ptrs[item];
	varnumber_T	n1;

	n1 = lili->li_tv.vval.v_number;
	if (item > 0 && n1 <= table[item - 1].last)
	{
	    semsg(_(e_overlapping_ranges_for_nr), (long)n1);
	    vim_free(ptrs);
	    vim_free(table);
	    return;
	}
	table[item].first = n1;
	lili = lili->li_next;
	table[item].last = lili->li_tv.vval.v_number;
	lili = lili->li_next;
	table[item].width = lili->li_tv.vval.v_number;
    }

    vim_free(ptrs);

    cw_table_save = cw_table;
    cw_table_size_save = cw_table_size;
    cw_table = table;
    cw_table_size = l->lv_len;

     
     
    error = check_chars_options();
    if (error != NULL)
    {
	emsg(_(error));
	cw_table = cw_table_save;
	cw_table_size = cw_table_size_save;
	vim_free(table);
	return;
    }

    vim_free(cw_table_save);
}