mirror of
https://github.com/reactos/wine.git
synced 2024-11-25 04:39:45 +00:00
comctl32/listview: Rework item selection with letter keys, fix some glitches.
This commit is contained in:
parent
fc59d0b2f8
commit
d57247ce39
@ -1751,14 +1751,15 @@ static inline INT LISTVIEW_GetCountPerColumn(const LISTVIEW_INFO *infoPtr)
|
||||
*/
|
||||
static INT LISTVIEW_ProcessLetterKeys(LISTVIEW_INFO *infoPtr, WPARAM charCode, LPARAM keyData)
|
||||
{
|
||||
INT nItem;
|
||||
INT endidx,idx;
|
||||
LVITEMW item;
|
||||
WCHAR buffer[MAX_PATH];
|
||||
DWORD lastKeyPressTimestamp = infoPtr->lastKeyPressTimestamp;
|
||||
INT endidx, startidx;
|
||||
DWORD prevTime;
|
||||
LVITEMW item;
|
||||
INT nItem;
|
||||
INT diff;
|
||||
|
||||
/* simple parameter checking */
|
||||
if (!charCode || !keyData) return 0;
|
||||
if (!charCode || !keyData || infoPtr->nItemCount == 0) return 0;
|
||||
|
||||
/* only allow the valid WM_CHARs through */
|
||||
if (!isalnumW(charCode) &&
|
||||
@ -1773,86 +1774,95 @@ static INT LISTVIEW_ProcessLetterKeys(LISTVIEW_INFO *infoPtr, WPARAM charCode, L
|
||||
charCode != '<' && charCode != ',' && charCode != '~')
|
||||
return 0;
|
||||
|
||||
/* if there's one item or less, there is no where to go */
|
||||
if (infoPtr->nItemCount <= 1) return 0;
|
||||
|
||||
/* update the search parameters */
|
||||
prevTime = infoPtr->lastKeyPressTimestamp;
|
||||
infoPtr->lastKeyPressTimestamp = GetTickCount();
|
||||
if (infoPtr->lastKeyPressTimestamp - lastKeyPressTimestamp < KEY_DELAY) {
|
||||
if (infoPtr->nSearchParamLength < MAX_PATH-1)
|
||||
infoPtr->szSearchParam[infoPtr->nSearchParamLength++]=charCode;
|
||||
diff = infoPtr->lastKeyPressTimestamp - prevTime;
|
||||
|
||||
if (diff >= 0 && diff < KEY_DELAY)
|
||||
{
|
||||
if (infoPtr->nSearchParamLength < MAX_PATH - 1)
|
||||
infoPtr->szSearchParam[infoPtr->nSearchParamLength++] = charCode;
|
||||
|
||||
if (infoPtr->charCode != charCode)
|
||||
infoPtr->charCode = charCode = 0;
|
||||
} else {
|
||||
infoPtr->charCode=charCode;
|
||||
infoPtr->szSearchParam[0]=charCode;
|
||||
infoPtr->nSearchParamLength=1;
|
||||
/* Redundant with the 1 char string */
|
||||
charCode=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
infoPtr->charCode = charCode;
|
||||
infoPtr->szSearchParam[0] = charCode;
|
||||
infoPtr->nSearchParamLength = 1;
|
||||
/* redundant with the 1 char string */
|
||||
charCode = 0;
|
||||
}
|
||||
|
||||
/* and search from the current position */
|
||||
nItem=-1;
|
||||
if (infoPtr->nFocusedItem >= 0) {
|
||||
endidx=infoPtr->nFocusedItem;
|
||||
idx=endidx;
|
||||
/* if looking for single character match,
|
||||
* then we must always move forward
|
||||
*/
|
||||
if (infoPtr->nSearchParamLength == 1)
|
||||
idx++;
|
||||
} else {
|
||||
endidx=infoPtr->nItemCount;
|
||||
idx=0;
|
||||
}
|
||||
nItem = -1;
|
||||
endidx = infoPtr->nItemCount;
|
||||
|
||||
/* Let application handle this for virtual listview */
|
||||
/* should start from next after focused item, so next item that matches
|
||||
will be selected, if there isn't any and focused matches it will be selected
|
||||
on second search stage from beginning of the list */
|
||||
if (infoPtr->nFocusedItem >= 0 && infoPtr->nItemCount > 1)
|
||||
startidx = infoPtr->nFocusedItem + 1;
|
||||
else
|
||||
startidx = 0;
|
||||
|
||||
/* let application handle this for virtual listview */
|
||||
if (infoPtr->dwStyle & LVS_OWNERDATA)
|
||||
{
|
||||
NMLVFINDITEMW nmlv;
|
||||
LVFINDINFOW lvfi;
|
||||
|
||||
ZeroMemory(&lvfi, sizeof(lvfi));
|
||||
lvfi.flags = (LVFI_WRAP | LVFI_PARTIAL);
|
||||
infoPtr->szSearchParam[infoPtr->nSearchParamLength] = '\0';
|
||||
lvfi.psz = infoPtr->szSearchParam;
|
||||
nmlv.iStart = idx;
|
||||
nmlv.lvfi = lvfi;
|
||||
memset(&nmlv.lvfi, 0, sizeof(nmlv.lvfi));
|
||||
nmlv.lvfi.flags = (LVFI_WRAP | LVFI_PARTIAL);
|
||||
nmlv.lvfi.psz = infoPtr->szSearchParam;
|
||||
nmlv.iStart = startidx;
|
||||
|
||||
infoPtr->szSearchParam[infoPtr->nSearchParamLength] = 0;
|
||||
|
||||
nItem = notify_hdr(infoPtr, LVN_ODFINDITEMW, (LPNMHDR)&nmlv.hdr);
|
||||
|
||||
if (nItem != -1)
|
||||
LISTVIEW_KeySelection(infoPtr, nItem, FALSE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
INT i = startidx;
|
||||
|
||||
do {
|
||||
if (idx == infoPtr->nItemCount) {
|
||||
if (endidx == infoPtr->nItemCount || endidx == 0)
|
||||
/* first search in [startidx, endidx), on failure continue in [0, startidx) */
|
||||
while (1)
|
||||
{
|
||||
/* start from first item if not found with >= startidx */
|
||||
if (i == infoPtr->nItemCount && startidx > 0)
|
||||
{
|
||||
endidx = startidx;
|
||||
startidx = 0;
|
||||
}
|
||||
|
||||
for (i = startidx; i < endidx; i++)
|
||||
{
|
||||
/* retrieve text */
|
||||
item.mask = LVIF_TEXT;
|
||||
item.iItem = i;
|
||||
item.iSubItem = 0;
|
||||
item.pszText = buffer;
|
||||
item.cchTextMax = MAX_PATH;
|
||||
if (!LISTVIEW_GetItemW(infoPtr, &item)) return 0;
|
||||
|
||||
if (lstrncmpiW(item.pszText, infoPtr->szSearchParam, infoPtr->nSearchParamLength) == 0)
|
||||
{
|
||||
nItem = i;
|
||||
break;
|
||||
}
|
||||
else if (nItem == -1 && lstrncmpiW(item.pszText, infoPtr->szSearchParam, 1) == 0)
|
||||
{
|
||||
/* this would work but we must keep looking for a longer match */
|
||||
nItem = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* found something or second search completed with any result */
|
||||
if (nItem != -1 || endidx != infoPtr->nItemCount)
|
||||
break;
|
||||
idx=0;
|
||||
}
|
||||
|
||||
/* get item */
|
||||
item.mask = LVIF_TEXT;
|
||||
item.iItem = idx;
|
||||
item.iSubItem = 0;
|
||||
item.pszText = buffer;
|
||||
item.cchTextMax = MAX_PATH;
|
||||
if (!LISTVIEW_GetItemW(infoPtr, &item)) return 0;
|
||||
|
||||
/* check for a match */
|
||||
if (lstrncmpiW(item.pszText,infoPtr->szSearchParam,infoPtr->nSearchParamLength) == 0) {
|
||||
nItem=idx;
|
||||
break;
|
||||
} else if ( (charCode != 0) && (nItem == -1) && (nItem != infoPtr->nFocusedItem) &&
|
||||
(lstrncmpiW(item.pszText,infoPtr->szSearchParam,1) == 0) ) {
|
||||
/* This would work but we must keep looking for a longer match */
|
||||
nItem=idx;
|
||||
}
|
||||
idx++;
|
||||
} while (idx != endidx);
|
||||
};
|
||||
}
|
||||
|
||||
if (nItem != -1)
|
||||
LISTVIEW_KeySelection(infoPtr, nItem, FALSE);
|
||||
|
Loading…
Reference in New Issue
Block a user