Skip to content
Snippets Groups Projects
Commit c9a6d50c authored by Gerard Patel's avatar Gerard Patel Committed by Alexandre Julliard
Browse files

Several focus and selection problems in listboxes.

parent 278d0586
No related branches found
No related tags found
No related merge requests found
......@@ -16,6 +16,7 @@
#include "combo.h"
#include "debugtools.h"
#include "tweak.h"
#include "winversion.h"
DEFAULT_DEBUG_CHANNEL(listbox)
DECLARE_DEBUG_CHANNEL(combo)
......@@ -80,10 +81,16 @@ typedef struct
#define HAS_STRINGS(descr) \
(!IS_OWNERDRAW(descr) || ((descr)->style & LBS_HASSTRINGS))
#define IS_MULTISELECT(descr) \
((descr)->style & LBS_MULTIPLESEL || ((descr)->style & LBS_EXTENDEDSEL))
#define SEND_NOTIFICATION(wnd,descr,code) \
(SendMessageA( (descr)->owner, WM_COMMAND, \
MAKEWPARAM((((descr)->lphc)?ID_CB_LISTBOX:(wnd)->wIDmenu), (code) ), (wnd)->hwndSelf ))
#define ISWIN31 (LOWORD(GetVersion()) == 0x0a03)
/* Current timer status */
typedef enum
{
......@@ -1250,7 +1257,7 @@ static LRESULT LISTBOX_SetSelection( WND *wnd, LB_DESCR *descr, INT index,
descr->selected_item = index;
if (oldsel != -1) LISTBOX_RepaintItem( wnd, descr, oldsel, ODA_SELECT);
if (index != -1) LISTBOX_RepaintItem( wnd, descr, index, ODA_SELECT );
if (send_notify) SEND_NOTIFICATION( wnd, descr,
if (send_notify && descr->nb_items) SEND_NOTIFICATION( wnd, descr,
(index != -1) ? LBN_SELCHANGE : LBN_SELCANCEL );
else
if( descr->lphc ) /* set selection change flag for parent combo */
......@@ -1297,6 +1304,7 @@ static LRESULT LISTBOX_InsertItem( WND *wnd, LB_DESCR *descr, INT index,
{
LB_ITEMDATA *item;
INT max_items;
INT oldfocus = descr->focus_item;
if (index == -1) index = descr->nb_items;
else if ((index < 0) || (index > descr->nb_items)) return LB_ERR;
......@@ -1351,17 +1359,23 @@ static LRESULT LISTBOX_InsertItem( WND *wnd, LB_DESCR *descr, INT index,
LISTBOX_InvalidateItems( wnd, descr, index );
/* Move selection and focused item */
if (index <= descr->selected_item) descr->selected_item++;
if (index <= descr->focus_item)
/* If listbox was empty, set focus to the first item */
if (descr->nb_items == 1)
LISTBOX_SetCaretIndex( wnd, descr, 0, FALSE );
/* single select don't change selection index in win31 */
else if ((ISWIN31) && !(IS_MULTISELECT(descr)))
{
descr->focus_item++;
LISTBOX_MoveCaret( wnd, descr, descr->focus_item, FALSE );
descr->selected_item++;
LISTBOX_SetSelection( wnd, descr, descr->selected_item-1, TRUE, FALSE );
}
else
{
if (index <= descr->selected_item)
{
descr->selected_item++;
descr->focus_item = oldfocus; /* focus not changed */
}
}
/* If listbox was empty, set focus to the first item */
if (descr->nb_items == 1) LISTBOX_SetCaretIndex( wnd, descr, 0, FALSE );
return LB_OKAY;
}
......@@ -1378,6 +1392,7 @@ static LRESULT LISTBOX_InsertString( WND *wnd, LB_DESCR *descr, INT index,
if (HAS_STRINGS(descr))
{
if (!str) str="";
if (!(new_str = HEAP_strdupA( descr->heap, 0, str )))
{
SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE );
......@@ -1461,19 +1476,31 @@ static LRESULT LISTBOX_RemoveItem( WND *wnd, LB_DESCR *descr, INT index )
max_items * sizeof(LB_ITEMDATA) );
if (item) descr->items = item;
}
/* Repaint the items */
LISTBOX_UpdateScroll( wnd, descr );
LISTBOX_InvalidateItems( wnd, descr, index );
/* if we removed the scrollbar, reset the top of the list
(correct for owner-drawn ???) */
if (descr->nb_items == descr->page_size)
LISTBOX_SetTopItem( wnd, descr, 0, TRUE );
/* Move selection and focused item */
if (index <= descr->selected_item) descr->selected_item--;
if (index <= descr->focus_item)
if (!IS_MULTISELECT(descr))
{
descr->focus_item--;
LISTBOX_MoveCaret( wnd, descr, descr->focus_item, FALSE );
if (index == descr->selected_item)
descr->selected_item = -1;
else if (index < descr->selected_item)
{
descr->selected_item--;
if (ISWIN31) /* win 31 do not change the selected item number */
LISTBOX_SetSelection( wnd, descr, descr->selected_item + 1, TRUE, FALSE);
}
}
LISTBOX_InvalidateItems( wnd, descr, index );
if (descr->focus_item >= descr->nb_items)
{
descr->focus_item = descr->nb_items - 1;
if (descr->focus_item < 0) descr->focus_item = 0;
}
return LB_OKAY;
}
......@@ -1793,7 +1820,7 @@ static LRESULT LISTBOX_HandleLButtonUp( WND *wnd, LB_DESCR *descr )
{
descr->captured = FALSE;
if (GetCapture() == wnd->hwndSelf) ReleaseCapture();
if (descr->style & LBS_NOTIFY)
if ((descr->style & LBS_NOTIFY) && descr->nb_items)
SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
}
return 0;
......@@ -1910,6 +1937,10 @@ static void LISTBOX_HandleMouseMove( WND *wnd, LB_DESCR *descr,
static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr, WPARAM wParam )
{
INT caret = -1;
BOOL bForceSelection = TRUE; /* select item pointed to by focus_item */
if ((IS_MULTISELECT(descr)) || (descr->selected_item == descr->focus_item))
bForceSelection = FALSE; /* only for single select list */
if (descr->style & LBS_WANTKEYBOARDINPUT)
{
caret = SendMessageA( descr->owner, WM_VKEYTOITEM,
......@@ -1922,6 +1953,7 @@ static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr, WPARAM wParam )
case VK_LEFT:
if (descr->style & LBS_MULTICOLUMN)
{
bForceSelection = FALSE;
if (descr->focus_item >= descr->page_size)
caret = descr->focus_item - descr->page_size;
break;
......@@ -1934,6 +1966,7 @@ static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr, WPARAM wParam )
case VK_RIGHT:
if (descr->style & LBS_MULTICOLUMN)
{
bForceSelection = FALSE;
if (descr->focus_item + descr->page_size < descr->nb_items)
caret = descr->focus_item + descr->page_size;
break;
......@@ -1943,6 +1976,7 @@ static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr, WPARAM wParam )
caret = descr->focus_item + 1;
if (caret >= descr->nb_items) caret = descr->nb_items - 1;
break;
case VK_PRIOR:
if (descr->style & LBS_MULTICOLUMN)
{
......@@ -1977,19 +2011,19 @@ static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr, WPARAM wParam )
!descr->items[descr->focus_item].selected,
(descr->style & LBS_NOTIFY) != 0 );
}
else if (descr->selected_item == -1)
{
LISTBOX_SetSelection( wnd, descr, descr->focus_item, TRUE,
(descr->style & LBS_NOTIFY) != 0 );
}
break;
default:
bForceSelection = FALSE;
}
if (bForceSelection) /* focused item is used instead of key */
caret = descr->focus_item;
if (caret >= 0)
{
if ((descr->style & LBS_EXTENDEDSEL) &&
!(GetKeyState( VK_SHIFT ) & 0x8000))
descr->anchor_item = caret;
LISTBOX_MoveCaret( wnd, descr, caret, TRUE );
LISTBOX_SetSelection( wnd, descr, caret, TRUE, FALSE);
if (descr->style & LBS_NOTIFY)
{
if( descr->lphc && CB_GETTYPE(descr->lphc) != CBS_SIMPLE )
......@@ -1997,7 +2031,7 @@ static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr, WPARAM wParam )
/* make sure that combo parent doesn't hide us */
descr->lphc->wState |= CBF_NOROLLUP;
}
SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
if (descr->nb_items) SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
}
}
return 0;
......@@ -2027,8 +2061,10 @@ static LRESULT LISTBOX_HandleChar( WND *wnd, LB_DESCR *descr,
caret = LISTBOX_FindString( wnd, descr, descr->focus_item, str, FALSE);
if (caret != -1)
{
if ((!IS_MULTISELECT(descr)) && descr->selected_item == -1)
LISTBOX_SetSelection( wnd, descr, caret, TRUE, FALSE);
LISTBOX_MoveCaret( wnd, descr, caret, TRUE );
if (descr->style & LBS_NOTIFY)
if ((descr->style & LBS_NOTIFY) && descr->nb_items)
SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
}
return 0;
......@@ -2187,7 +2223,10 @@ static inline LRESULT WINAPI ListBoxWndProc_locked( WND* wnd, UINT msg,
case LB_DELETESTRING16:
case LB_DELETESTRING:
return LISTBOX_RemoveItem( wnd, descr, wParam );
if (LISTBOX_RemoveItem( wnd, descr, wParam) != LB_ERR)
return descr->nb_items;
else
return LB_ERR;
case LB_GETITEMDATA16:
case LB_GETITEMDATA:
......@@ -2224,6 +2263,8 @@ static inline LRESULT WINAPI ListBoxWndProc_locked( WND* wnd, UINT msg,
case LB_GETCURSEL:
if (descr->nb_items==0)
return LB_ERR;
if (!IS_MULTISELECT(descr))
return descr->selected_item;
/* else */
if (descr->selected_item!=-1)
return descr->selected_item;
......@@ -2263,7 +2304,13 @@ static inline LRESULT WINAPI ListBoxWndProc_locked( WND* wnd, UINT msg,
case LB_SETCARETINDEX16:
case LB_SETCARETINDEX:
return LISTBOX_SetCaretIndex( wnd, descr, wParam, !lParam );
if ((!IS_MULTISELECT(descr)) && (descr->selected_item != -1)) return LB_ERR;
if (LISTBOX_SetCaretIndex( wnd, descr, wParam, !lParam ) == LB_ERR)
return LB_ERR;
else if (ISWIN31)
return wParam;
else
return LB_OKAY;
case LB_GETCARETINDEX16:
case LB_GETCARETINDEX:
......@@ -2334,6 +2381,7 @@ static inline LRESULT WINAPI ListBoxWndProc_locked( WND* wnd, UINT msg,
wParam = (INT)(INT16)wParam;
/* fall through */
case LB_SETCURSEL:
if (IS_MULTISELECT(descr)) return LB_ERR;
LISTBOX_SetCaretIndex( wnd, descr, wParam, TRUE );
return LISTBOX_SetSelection( wnd, descr, wParam, TRUE, FALSE );
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment