Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/user32/listbox.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-)
diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c index 118f564..9cecd00 100644 --- a/dlls/user32/listbox.c +++ b/dlls/user32/listbox.c @@ -158,6 +158,11 @@ static WCHAR *get_item_string( const LB_DESCR *descr, UINT index ) return HAS_STRINGS(descr) ? descr->items[index].str : NULL; }
+static UINT get_item_height( const LB_DESCR *descr, UINT index ) +{ + return (descr->style & LBS_NODATA) ? 0 : descr->items[index].height; +} + static BOOL is_item_selected( const LB_DESCR *descr, UINT index ) { if (!(descr->style & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))) @@ -212,7 +217,7 @@ static INT LISTBOX_GetCurrentPageSize( const LB_DESCR *descr ) if (!(descr->style & LBS_OWNERDRAWVARIABLE)) return descr->page_size; for (i = descr->top_item, height = 0; i < descr->nb_items; i++) { - if ((height += descr->items[i].height) > descr->height) break; + if ((height += get_item_height(descr, i)) > descr->height) break; } if (i == descr->top_item) return 1; else return i - descr->top_item; @@ -232,7 +237,7 @@ static INT LISTBOX_GetMaxTopIndex( const LB_DESCR *descr ) { page = descr->height; for (max = descr->nb_items - 1; max >= 0; max--) - if ((page -= descr->items[max].height) < 0) break; + if ((page -= get_item_height(descr, max)) < 0) break; if (max < descr->nb_items - 1) max++; } else if (descr->style & LBS_MULTICOLUMN) @@ -360,12 +365,12 @@ static LRESULT LISTBOX_SetTopItem( LB_DESCR *descr, INT index, BOOL scroll ) if (index > descr->top_item) { for (i = index - 1; i >= descr->top_item; i--) - dy -= descr->items[i].height; + dy -= get_item_height(descr, i); } else { for (i = index; i < descr->top_item; i++) - dy += descr->items[i].height; + dy += get_item_height(descr, i); } } else @@ -481,14 +486,14 @@ static LRESULT LISTBOX_GetItemRect( const LB_DESCR *descr, INT index, RECT *rect if (index < descr->top_item) { for (i = descr->top_item-1; i >= index; i--) - rect->top -= descr->items[i].height; + rect->top -= get_item_height(descr, i); } else { for (i = descr->top_item; i < index; i++) - rect->top += descr->items[i].height; + rect->top += get_item_height(descr, i); } - rect->bottom = rect->top + descr->items[index].height; + rect->bottom = rect->top + get_item_height(descr, index);
} } @@ -523,7 +528,7 @@ static INT LISTBOX_GetItemFromPoint( const LB_DESCR *descr, INT x, INT y ) { while (index < descr->nb_items) { - if ((pos += descr->items[index].height) > y) break; + if ((pos += get_item_height(descr, index)) > y) break; index++; } } @@ -532,7 +537,7 @@ static INT LISTBOX_GetItemFromPoint( const LB_DESCR *descr, INT x, INT y ) while (index > 0) { index--; - if ((pos -= descr->items[index].height) <= y) break; + if ((pos -= get_item_height(descr, index)) <= y) break; } } } @@ -1099,7 +1104,7 @@ static LRESULT LISTBOX_Paint( LB_DESCR *descr, HDC hdc ) if (!(descr->style & LBS_OWNERDRAWVARIABLE)) rect.bottom = rect.top + descr->item_height; else - rect.bottom = rect.top + descr->items[i].height; + rect.bottom = rect.top + get_item_height(descr, i);
/* keep the focus rect, to paint the focus item after */ if (i == descr->focus_item) @@ -1214,7 +1219,7 @@ static LRESULT LISTBOX_GetItemHeight( const LB_DESCR *descr, INT index ) SetLastError(ERROR_INVALID_INDEX); return LB_ERR; } - return descr->items[index].height; + return get_item_height(descr, index); } else return descr->item_height; } @@ -1384,9 +1389,9 @@ static void LISTBOX_MakeItemVisible( LB_DESCR *descr, INT index, BOOL fully ) } else if (descr->style & LBS_OWNERDRAWVARIABLE) { - INT height = fully ? descr->items[index].height : 1; + INT height = fully ? get_item_height(descr, index) : 1; for (top = index; top > descr->top_item; top--) - if ((height += descr->items[top-1].height) > descr->height) break; + if ((height += get_item_height(descr, top - 1)) > descr->height) break; } else { @@ -1597,7 +1602,7 @@ static LRESULT LISTBOX_InsertItem( LB_DESCR *descr, INT index, SendMessageW( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis ); item->height = mis.itemHeight ? mis.itemHeight : 1; TRACE("[%p]: measure item %d (%s) = %d\n", - descr->self, index, str ? debugstr_w(str) : "", item->height ); + descr->self, index, str ? debugstr_w(str) : "", get_item_height(descr, index)); }
/* Repaint the items */
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/user32/listbox.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c index 9cecd00..7dc3e66 100644 --- a/dlls/user32/listbox.c +++ b/dlls/user32/listbox.c @@ -163,6 +163,11 @@ static UINT get_item_height( const LB_DESCR *descr, UINT index ) return (descr->style & LBS_NODATA) ? 0 : descr->items[index].height; }
+static void set_item_height( LB_DESCR *descr, UINT index, UINT height ) +{ + if (!(descr->style & LBS_NODATA)) descr->items[index].height = height; +} + static BOOL is_item_selected( const LB_DESCR *descr, UINT index ) { if (!(descr->style & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))) @@ -1243,7 +1248,7 @@ static LRESULT LISTBOX_SetItemHeight( LB_DESCR *descr, INT index, INT height, BO return LB_ERR; } TRACE("[%p]: item %d height = %d\n", descr->self, index, height ); - descr->items[index].height = height; + set_item_height(descr, index, height); LISTBOX_UpdateScroll( descr ); if (repaint) LISTBOX_InvalidateItems( descr, index ); @@ -1600,7 +1605,7 @@ static LRESULT LISTBOX_InsertItem( LB_DESCR *descr, INT index, mis.itemData = str ? (ULONG_PTR)str : data; mis.itemHeight = descr->item_height; SendMessageW( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis ); - item->height = mis.itemHeight ? mis.itemHeight : 1; + set_item_height(descr, index, mis.itemHeight ? mis.itemHeight : 1); TRACE("[%p]: measure item %d (%s) = %d\n", descr->self, index, str ? debugstr_w(str) : "", get_item_height(descr, index)); }
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=47987
Your paranoid android.
=== debian9 (32 bit Chinese:China report) ===
user32: input.c:2133: Test failed: expected WM_NCHITTEST message
=== debian9 (64 bit WoW report) ===
user32: clipboard.c:833: Test failed: 2: gle 5 clipboard.c:838: Test failed: 2.0: got 0000 instead of 000d clipboard.c:868: Test failed: 2: gle 1418 clipboard.c:717: Test failed: 3: gle 5 clipboard.c:719: Test failed: 3: gle 1418 clipboard.c:746: Test failed: 3: count 5 clipboard.c:749: Test failed: 3: gle 1418 clipboard.c:755: Test failed: 3: 0003 not available clipboard.c:757: Test failed: 3: count 5 instead of 2 clipboard.c:760: Test failed: 3: gle 5 clipboard.c:765: Test failed: 3.0: got 0000 instead of 000e clipboard.c:805: Test failed: 3: gle 1418 clipboard.c:815: Test failed: 3: count 5 clipboard.c:818: Test failed: 3: gle 1418 clipboard.c:826: Test failed: 3: 0003 not available clipboard.c:828: Test failed: 3: count 5 instead of 2 clipboard.c:833: Test failed: 3: gle 5 clipboard.c:838: Test failed: 3.0: got 0000 instead of 000e clipboard.c:868: Test failed: 3: gle 1418 clipboard.c:717: Test failed: 4: gle 5 clipboard.c:719: Test failed: 4: gle 1418 clipboard.c:746: Test failed: 4: count 6 clipboard.c:749: Test failed: 4: gle 1418 clipboard.c:757: Test failed: 4: count 6 instead of 2 clipboard.c:760: Test failed: 4: gle 5 clipboard.c:765: Test failed: 4.0: got 0000 instead of 0003 clipboard.c:805: Test failed: 4: gle 1418 clipboard.c:815: Test failed: 4: count 6 clipboard.c:818: Test failed: 4: gle 1418 clipboard.c:828: Test failed: 4: count 6 instead of 2 clipboard.c:833: Test failed: 4: gle 5 clipboard.c:838: Test failed: 4.0: got 0000 instead of 0003 clipboard.c:868: Test failed: 4: gle 1418 clipboard.c:717: Test failed: 5: gle 5 clipboard.c:719: Test failed: 5: gle 1418 clipboard.c:746: Test failed: 5: count 7 clipboard.c:749: Test failed: 5: gle 1418 clipboard.c:755: Test failed: 5: 0008 not available clipboard.c:755: Test failed: 5: 0011 not available clipboard.c:757: Test failed: 5: count 7 instead of 3 clipboard.c:760: Test failed: 5: gle 5 clipboard.c:765: Test failed: 5.0: got 0000 instead of 0002 clipboard.c:805: Test failed: 5: gle 1418 clipboard.c:815: Test failed: 5: count 7 clipboard.c:818: Test failed: 5: gle 1418 clipboard.c:826: Test failed: 5: 0008 not available clipboard.c:826: Test failed: 5: 0011 not available clipboard.c:828: Test failed: 5: count 7 instead of 3 clipboard.c:833: Test failed: 5: gle 5 clipboard.c:838: Test failed: 5.0: got 0000 instead of 0002 clipboard.c:868: Test failed: 5: gle 1418 clipboard.c:717: Test failed: 6: gle 5 clipboard.c:719: Test failed: 6: gle 1418 clipboard.c:746: Test failed: 6: count 8 clipboard.c:749: Test failed: 6: gle 1418 clipboard.c:755: Test failed: 6: 0011 not available clipboard.c:757: Test failed: 6: count 8 instead of 3 clipboard.c:760: Test failed: 6: gle 5 clipboard.c:765: Test failed: 6.0: got 0000 instead of 0008 clipboard.c:805: Test failed: 6: gle 1418 clipboard.c:815: Test failed: 6: count 8 clipboard.c:818: Test failed: 6: gle 1418 clipboard.c:826: Test failed: 6: 0011 not available clipboard.c:828: Test failed: 6: count 8 instead of 3 clipboard.c:833: Test failed: 6: gle 5 clipboard.c:838: Test failed: 6.0: got 0000 instead of 0008 clipboard.c:868: Test failed: 6: gle 1418 clipboard.c:717: Test failed: 7: gle 5 clipboard.c:719: Test failed: 7: gle 1418 clipboard.c:746: Test failed: 7: count 9 clipboard.c:749: Test failed: 7: gle 1418 clipboard.c:757: Test failed: 7: count 9 instead of 3 clipboard.c:760: Test failed: 7: gle 5 clipboard.c:765: Test failed: 7.0: got 0000 instead of 0011 clipboard.c:805: Test failed: 7: gle 1418 clipboard.c:815: Test failed: 7: count 9 clipboard.c:818: Test failed: 7: gle 1418 clipboard.c:828: Test failed: 7: count 9 instead of 3 clipboard.c:833: Test failed: 7: gle 5 clipboard.c:838: Test failed: 7.0: got 0000 instead of 0011 clipboard.c:868: Test failed: 7: gle 1418 clipboard.c:874: Test failed: gle 5 clipboard.c:876: Test failed: gle 1418 clipboard.c:878: Test failed: gle 1418
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/user32/listbox.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c index 7dc3e66..7caf24c 100644 --- a/dlls/user32/listbox.c +++ b/dlls/user32/listbox.c @@ -181,6 +181,20 @@ static void set_item_selected_state(LB_DESCR *descr, UINT index, BOOL state) descr->items[index].selected = state; }
+static void insert_item_data(LB_DESCR *descr, UINT index, WCHAR *str, ULONG_PTR data) +{ + LB_ITEMDATA *item; + + item = descr->items + index; + if (index < descr->nb_items) + memmove(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; +} + /********************************************************************* * listbox class descriptor */ @@ -1573,23 +1587,13 @@ static void LISTBOX_MoveCaret( LB_DESCR *descr, INT index, BOOL fully_visible ) static LRESULT LISTBOX_InsertItem( LB_DESCR *descr, INT index, LPWSTR str, ULONG_PTR data ) { - LB_ITEMDATA *item; INT oldfocus = descr->focus_item;
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; + insert_item_data(descr, index, str, data); descr->nb_items++;
/* Get item height */
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=47988
Your paranoid android.
=== debian9 (32 bit report) ===
user32: msg.c:8713: Test failed: WaitForSingleObject failed 102 msg.c:8719: Test failed: destroy child on thread exit: 0: the msg 0x0082 was expected, but got msg 0x000f instead msg.c:8719: Test failed: destroy child on thread exit: 1: the msg 0x000f was expected, but got msg 0x0014 instead msg.c:8719: Test failed: destroy child on thread exit: 2: the msg sequence is not complete: expected 0014 - actual 0000
=== debian9 (32 bit Chinese:China report) ===
user32: msg.c:8713: Test failed: WaitForSingleObject failed 102 msg.c:8719: Test failed: destroy child on thread exit: 0: the msg 0x0082 was expected, but got msg 0x000f instead msg.c:8719: Test failed: destroy child on thread exit: 1: the msg 0x000f was expected, but got msg 0x0014 instead msg.c:8719: Test failed: destroy child on thread exit: 2: the msg sequence is not complete: expected 0014 - actual 0000
=== debian9 (64 bit WoW report) ===
user32: clipboard.c:833: Test failed: 5: gle 5 clipboard.c:838: Test failed: 5.0: got 0000 instead of 0002 clipboard.c:868: Test failed: 5: gle 1418
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/user32/listbox.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c index 7caf24c..87404c6 100644 --- a/dlls/user32/listbox.c +++ b/dlls/user32/listbox.c @@ -195,6 +195,15 @@ static void insert_item_data(LB_DESCR *descr, UINT index, WCHAR *str, ULONG_PTR item->selected = FALSE; }
+static void remove_item_data(LB_DESCR *descr, UINT index) +{ + LB_ITEMDATA *item; + + item = descr->items + index; + if (index < descr->nb_items) + memmove(item, item + 1, (descr->nb_items - index) * sizeof(LB_ITEMDATA)); +} + /********************************************************************* * listbox class descriptor */ @@ -1709,8 +1718,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. */ @@ -1723,15 +1730,9 @@ static LRESULT LISTBOX_RemoveItem( LB_DESCR *descr, INT index ) } descr->nb_items--; LISTBOX_DeleteItem( descr, index ); + remove_item_data(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--; - resize_storage(descr, descr->nb_items);
/* Repaint the items */
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=47989
Your paranoid android.
=== debian9 (32 bit Chinese:China report) ===
user32: msg.c:8713: Test failed: WaitForSingleObject failed 102 msg.c:8719: Test failed: destroy child on thread exit: 0: the msg 0x0082 was expected, but got msg 0x000f instead msg.c:8719: Test failed: destroy child on thread exit: 1: the msg 0x000f was expected, but got msg 0x0014 instead msg.c:8719: Test failed: destroy child on thread exit: 2: the msg sequence is not complete: expected 0014 - actual 0000
Signed-off-by: Huw Davies huw@codeweavers.com
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 --- dlls/user32/listbox.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c index 87404c6..0be4867 100644 --- a/dlls/user32/listbox.c +++ b/dlls/user32/listbox.c @@ -18,7 +18,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> @@ -130,17 +130,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)); @@ -185,6 +188,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) memmove(item + 1, item, (descr->nb_items - index) * sizeof(LB_ITEMDATA)); @@ -199,6 +204,8 @@ static void remove_item_data(LB_DESCR *descr, UINT index) { LB_ITEMDATA *item;
+ if (!descr->items) return; + item = descr->items + index; if (index < descr->nb_items) memmove(item, item + 1, (descr->nb_items - index) * sizeof(LB_ITEMDATA)); @@ -1772,7 +1779,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;
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/user32/tests/listbox.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/dlls/user32/tests/listbox.c b/dlls/user32/tests/listbox.c index 5bdffc5..d15b18a 100644 --- a/dlls/user32/tests/listbox.c +++ b/dlls/user32/tests/listbox.c @@ -1893,6 +1893,11 @@ static void test_set_count( void ) GetUpdateRect( listbox, &r, TRUE ); ok( !IsRectEmpty( &r ), "got empty rect\n");
+ ret = SendMessageA( listbox, LB_SETCOUNT, -5, 0 ); + ok( ret == 0, "got %d\n", ret ); + ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 ); + ok( ret == -5, "got %d\n", ret ); + DestroyWindow( listbox );
for (i = 0; i < ARRAY_SIZE(styles); ++i)
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=47991
Your paranoid android.
=== debian9 (32 bit report) ===
user32: msg.c:8713: Test failed: WaitForSingleObject failed 102 msg.c:8719: Test failed: destroy child on thread exit: 0: the msg 0x0082 was expected, but got msg 0x000f instead msg.c:8719: Test failed: destroy child on thread exit: 1: the msg 0x000f was expected, but got msg 0x0014 instead msg.c:8719: Test failed: destroy child on thread exit: 2: the msg sequence is not complete: expected 0014 - actual 0000
=== debian9 (32 bit Chinese:China report) ===
user32: msg.c:8713: Test failed: WaitForSingleObject failed 102 msg.c:8719: Test failed: destroy child on thread exit: 0: the msg 0x0082 was expected, but got msg 0x000f instead msg.c:8719: Test failed: destroy child on thread exit: 1: the msg 0x000f was expected, but got msg 0x0014 instead msg.c:8719: Test failed: destroy child on thread exit: 2: the msg sequence is not complete: expected 0014 - actual 0000
Signed-off-by: Huw Davies huw@codeweavers.com