The LBS_NODATA style's purpose is to drastically improve performance and memory usage on very large lists, since they should function as virtual lists. Thus, don't store any data for single-selection listboxes (descr->items always NULL).
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=32374 Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
remove_item is part of this patch because it would otherwise have to be rewritten due to indentation, amounting to same amount of changes, and it's just moving the small part into a helper. The patch should be small enough now, hopefully.
dlls/comctl32/listbox.c | 59 +++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 20 deletions(-)
diff --git a/dlls/comctl32/listbox.c b/dlls/comctl32/listbox.c index 1f56c99..1b8f874 100644 --- a/dlls/comctl32/listbox.c +++ b/dlls/comctl32/listbox.c @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * TODO: - * - LBS_NODATA + * - LBS_NODATA for multi-selection listboxes */
#include <string.h> @@ -126,6 +126,17 @@ typedef enum static TIMER_DIRECTION LISTBOX_Timer = LB_TIMER_NONE;
static LRESULT LISTBOX_GetItemRect( const LB_DESCR *descr, INT index, RECT *rect ); +static void LISTBOX_DeleteItem( LB_DESCR *descr, INT index ); + +static BOOL is_singlesel_NODATA(const LB_DESCR *descr) +{ + return (descr->style & (LBS_NODATA | LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == LBS_NODATA; +} + +static BOOL is_multisel_NODATA(const LB_DESCR *descr) +{ + return (descr->style & LBS_NODATA) && (descr->style & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)); +}
static BOOL resize_storage(LB_DESCR *descr, UINT items_size) { @@ -135,17 +146,20 @@ static BOOL resize_storage(LB_DESCR *descr, UINT items_size) items_size + LB_ARRAY_GRANULARITY * 2 < descr->items_size) { items_size = (items_size + LB_ARRAY_GRANULARITY - 1) & ~(LB_ARRAY_GRANULARITY - 1); - items = heap_realloc(descr->items, items_size * sizeof(LB_ITEMDATA)); - if (!items) + if (!is_singlesel_NODATA(descr)) { - SEND_NOTIFICATION(descr, LBN_ERRSPACE); - return FALSE; + items = heap_realloc(descr->items, items_size * sizeof(LB_ITEMDATA)); + if (!items) + { + SEND_NOTIFICATION(descr, LBN_ERRSPACE); + return FALSE; + } + descr->items = items; } descr->items_size = items_size; - descr->items = items; }
- if ((descr->style & LBS_NODATA) && items_size > descr->nb_items) + if (is_multisel_NODATA(descr) && items_size > descr->nb_items) { memset(&descr->items[descr->nb_items], 0, (items_size - descr->nb_items) * sizeof(LB_ITEMDATA)); @@ -186,6 +200,7 @@ static void insert_item(LB_DESCR *descr, INT index, WCHAR *str, ULONG_PTR data) { LB_ITEMDATA *item;
+ if (is_singlesel_NODATA(descr)) return; item = &descr->items[index];
if (index < descr->nb_items - 1) @@ -214,6 +229,20 @@ static void insert_item(LB_DESCR *descr, INT index, WCHAR *str, ULONG_PTR data) } }
+static void remove_item(LB_DESCR *descr, INT index) +{ + if (!is_singlesel_NODATA(descr)) + { + LB_ITEMDATA *item = &descr->items[index]; + + LISTBOX_DeleteItem(descr, index); + if (index < descr->nb_items) + RtlMoveMemory(item, item + 1, + (descr->nb_items - index) * sizeof(LB_ITEMDATA)); + } + descr->anchor_item = min(descr->anchor_item, descr->nb_items - 1); +} + /*********************************************************************** * LISTBOX_GetCurrentPageSize * @@ -1696,8 +1725,6 @@ static void LISTBOX_DeleteItem( LB_DESCR *descr, INT index ) */ static LRESULT LISTBOX_RemoveItem( LB_DESCR *descr, INT index ) { - LB_ITEMDATA *item; - if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
/* We need to invalidate the original rect instead of the updated one. */ @@ -1709,16 +1736,7 @@ static LRESULT LISTBOX_RemoveItem( LB_DESCR *descr, INT index ) return LB_OKAY; } descr->nb_items--; - LISTBOX_DeleteItem( descr, index ); - - /* Remove the item */ - - item = &descr->items[index]; - if (index < descr->nb_items) - RtlMoveMemory( item, item + 1, - (descr->nb_items - index) * sizeof(LB_ITEMDATA) ); - if (descr->anchor_item == descr->nb_items) descr->anchor_item--; - + remove_item(descr, index); resize_storage(descr, descr->nb_items);
/* Repaint the items */ @@ -1758,7 +1776,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->style & LBS_NODATA)) + for(i = descr->nb_items - 1; i >= 0; i--) LISTBOX_DeleteItem(descr, i); HeapFree( GetProcessHeap(), 0, descr->items ); descr->nb_items = 0; descr->top_item = 0;