[PATCH 4/5] comctl32/listbox: Implement LBS_NODATA for single-selection listboxes

Huw Davies huw at codeweavers.com
Mon Feb 11 05:22:31 CST 2019


On Mon, Feb 11, 2019 at 01:09:14PM +0200, Gabriel Ivăncescu wrote:
> On 2/11/19 12:10 PM, Huw Davies wrote:
> > On Fri, Feb 08, 2019 at 02:41:45PM +0200, Gabriel Ivăncescu wrote:
> > > @@ -1535,36 +1552,42 @@ static LRESULT LISTBOX_InsertItem( LB_DESCR *descr, INT index,
> > >       if (index == -1) index = descr->nb_items;
> > >       else if ((index < 0) || (index > descr->nb_items)) return LB_ERR;
> > > -    if (!resize_storage(descr, descr->nb_items + 1)) return LB_ERR;
> > > -
> > > -    /* Insert the item structure */
> > > -
> > > -    item = &descr->items[index];
> > > -    if (index < descr->nb_items)
> > > -        RtlMoveMemory( item + 1, item,
> > > -                       (descr->nb_items - index) * sizeof(LB_ITEMDATA) );
> > > -    item->str      = str;
> > > -    item->data     = HAS_STRINGS(descr) ? 0 : data;
> > > -    item->height   = 0;
> > > -    item->selected = FALSE;
> > > -    descr->nb_items++;
> > > -
> > > -    /* Get item height */
> > > -
> > > -    if (descr->style & LBS_OWNERDRAWVARIABLE)
> > > +    if (is_singlesel_NODATA(descr))
> > >       {
> > > -        MEASUREITEMSTRUCT mis;
> > > -        UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
> > > +        descr->nb_items++;
> > > +        descr->items_size = max(descr->items_size, descr->nb_items);
> > > +    }
> > > +    else
> > > +    {
> > > +        if (!resize_storage(descr, descr->nb_items + 1)) return LB_ERR;
> > 
> > Again, resize_storage will handle the no_data case.  Then add a helper to
> > actually insert the item.
> > 
> 
> But in the insert helper, I'd have to ignore everything if it's
> single-selection LBS_NODATA (because there's nothing to do), so there is no
> difference to currently except just moving most of the function into a
> helper (instead of indenting it).
> 
> Is that what you had in mind?

Yes.

> > > @@ -1678,19 +1701,29 @@ static LRESULT LISTBOX_RemoveItem( LB_DESCR *descr, INT index )
> > >       LISTBOX_InvalidateItems( descr, index );
> > >       descr->nb_items--;
> > > -    LISTBOX_DeleteItem( descr, index );
> > 
> > LB_DeleteItem should again handle the no_data case, it'll send LB_RESETCONTENT
> > as required.
> > 
> 
> Shouldn't that be RemoveItem? DeleteItem, AFAIK, has to not be called with
> LBS_NODATA (unless you simply mean an early exit if so) nor send any
> messages at all.

It's an earlish exit after sending the LB_RESETCONTENT message if appropriate.
 
> > > @@ -1729,7 +1762,8 @@ static void LISTBOX_ResetContent( LB_DESCR *descr )
> > >   {
> > >       INT i;
> > > -    for(i = descr->nb_items - 1; i>=0; i--) LISTBOX_DeleteItem( descr, i);
> > > +    if (descr->items)
> > > +        for (i = descr->nb_items - 1; i >= 0; i--) LISTBOX_DeleteItem(descr, i);
> > 
> > LB_DeleteItems() will cope.
> > 
> 
> I don't like this solution. That would be slower than needed for large lists
> (which LBS_NODATA is for) when resetting them, for an operation that should
> basically be instant and not dependent on the list's size. i.e. from O(1) to
> O(n)

We'll revisit it if performance turns out to be an issue.

Huw.



More information about the wine-devel mailing list