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

Gabriel Ivăncescu gabrielopcode at gmail.com
Tue Feb 19 07:33:59 CST 2019


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 at gmail.com>
---
 dlls/comctl32/listbox.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/dlls/comctl32/listbox.c b/dlls/comctl32/listbox.c
index 31e5f71..db9548d 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>
@@ -135,17 +135,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 ((descr->style & (LBS_NODATA | LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != LBS_NODATA)
         {
-            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 ((descr->style & LBS_NODATA) && descr->items && items_size > descr->nb_items)
     {
         memset(&descr->items[descr->nb_items], 0,
                (items_size - descr->nb_items) * sizeof(LB_ITEMDATA));
@@ -190,6 +193,8 @@ static void insert_item_data(LB_DESCR *descr, UINT index, WCHAR *str, ULONG_PTR
 {
     LB_ITEMDATA *item;
 
+    if (!descr->items) return;
+
     item = &descr->items[index];
     if (index < descr->nb_items)
         RtlMoveMemory(item + 1, item,
@@ -202,6 +207,8 @@ static void insert_item_data(LB_DESCR *descr, UINT index, WCHAR *str, ULONG_PTR
 
 static void remove_item_data(LB_DESCR *descr, UINT index)
 {
+    if (!descr->items) return;
+
     if (index < descr->nb_items)
         RtlMoveMemory(&descr->items[index], &descr->items[index + 1],
                       (descr->nb_items - index) * sizeof(LB_ITEMDATA));
@@ -1760,7 +1767,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;
-- 
2.20.1




More information about the wine-devel mailing list