Treeview typing completion
François Gouget
fgouget at codeweavers.com
Sun Feb 11 13:32:35 CST 2001
This is the same as the listview completion patch except that
treeviews did not have this implemented at all before.
Changelog:
François Gouget <fgouget at codeweavers.com>
* dlls/comctl32/treeview.c
Handle WM_CHARs and pass them to TREEVIEW_ProcessLetterKeys
See also LISTVIEW_ProcessLetterKeys in listview.c
--
François Gouget
fgouget at codeweavers.com
-------------- next part --------------
Index: dlls/comctl32/treeview.c
===================================================================
RCS file: /home/cvs/wine/wine/dlls/comctl32/treeview.c,v
retrieving revision 1.87
diff -u -r1.87 treeview.c
--- dlls/comctl32/treeview.c 2000/11/28 22:40:56 1.87
+++ dlls/comctl32/treeview.c 2001/02/11 18:55:47
@@ -25,6 +25,7 @@
*/
#include <assert.h>
+#include <ctype.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
@@ -119,9 +120,16 @@
int stateImageHeight;
int stateImageWidth;
HDPA items;
+
+ DWORD lastKeyPressTimestamp; /* Added */
+ WPARAM charCode; /* Added */
+ INT nSearchParamLength; /* Added */
+ CHAR szSearchParam[ MAX_PATH ]; /* Added */
} TREEVIEW_INFO;
+/******** Defines that TREEVIEW_ProcessLetterKeys uses ****************/
+#define KEY_DELAY 450
/* bitflags for infoPtr->uInternalStatus */
@@ -3976,6 +3984,156 @@
return TRUE;
}
+/*************************************************************************
+ * TREEVIEW_ProcessLetterKeys
+ *
+ * Processes keyboard messages generated by pressing the letter keys
+ * on the keyboard.
+ * What this does is perform a case insensitive search from the
+ * current position with the following quirks:
+ * - If two chars or more are pressed in quick succession we search
+ * for the corresponding string (e.g. 'abc').
+ * - If there is a delay we wipe away the current search string and
+ * restart with just that char.
+ * - If the user keeps pressing the same character, whether slowly or
+ * fast, so that the search string is entirely composed of this
+ * character ('aaaaa' for instance), then we search for first item
+ * that starting with that character.
+ * - If the user types the above character in quick succession, then
+ * we must also search for the corresponding string ('aaaaa'), and
+ * go to that string if there is a match.
+ *
+ * RETURNS
+ *
+ * Zero.
+ *
+ * BUGS
+ *
+ * - The current implementation has a list of characters it will
+ * accept and it ignores averything else. In particular it will
+ * ignore accentuated characters which seems to match what
+ * Windows does. But I'm not sure it makes sense to follow
+ * Windows there.
+ * - We don't sound a beep when the search fails.
+ * - The search should start from the focused item, not from the selected
+ * item. One reason for this is to allow for multiple selections in trees.
+ * But currently infoPtr->focusedItem does not seem very usable.
+ *
+ * SEE ALSO
+ *
+ * TREEVIEW_ProcessLetterKeys
+ */
+static INT TREEVIEW_ProcessLetterKeys(
+ HWND hwnd, /* handle to the window */
+ WPARAM charCode, /* the character code, the actual character */
+ LPARAM keyData /* key data */
+ )
+{
+ TREEVIEW_INFO *infoPtr;
+ HTREEITEM nItem;
+ HTREEITEM endidx,idx;
+ TVITEMEXA item;
+ CHAR buffer[MAX_PATH];
+ DWORD timestamp,elapsed;
+
+ /* simple parameter checking */
+ if (!hwnd || !charCode || !keyData)
+ return 0;
+
+ infoPtr=(TREEVIEW_INFO*)GetWindowLongA(hwnd, 0);
+ if (!infoPtr)
+ return 0;
+
+ /* only allow the valid WM_CHARs through */
+ if (!isalnum(charCode) &&
+ charCode != '.' && charCode != '`' && charCode != '!' &&
+ charCode != '@' && charCode != '#' && charCode != '$' &&
+ charCode != '%' && charCode != '^' && charCode != '&' &&
+ charCode != '*' && charCode != '(' && charCode != ')' &&
+ charCode != '-' && charCode != '_' && charCode != '+' &&
+ charCode != '=' && charCode != '\\'&& charCode != ']' &&
+ charCode != '}' && charCode != '[' && charCode != '{' &&
+ charCode != '/' && charCode != '?' && charCode != '>' &&
+ charCode != '<' && charCode != ',' && charCode != '~')
+ return 0;
+
+ /* compute how much time elapsed since last keypress */
+ timestamp = GetTickCount();
+ if (timestamp > infoPtr->lastKeyPressTimestamp) {
+ elapsed=timestamp-infoPtr->lastKeyPressTimestamp;
+ } else {
+ elapsed=infoPtr->lastKeyPressTimestamp-timestamp;
+ }
+
+ /* update the search parameters */
+ infoPtr->lastKeyPressTimestamp=timestamp;
+ if (elapsed < KEY_DELAY) {
+ if (infoPtr->nSearchParamLength < sizeof(infoPtr->szSearchParam)) {
+ 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;
+ }
+
+ /* and search from the current position */
+ nItem=NULL;
+ if (infoPtr->selectedItem != NULL) {
+ endidx=infoPtr->selectedItem;
+ /* if looking for single character match,
+ * then we must always move forward
+ */
+ if (infoPtr->nSearchParamLength == 1)
+ idx=TREEVIEW_GetNextListItem(infoPtr,endidx);
+ else
+ idx=endidx;
+ } else {
+ endidx=NULL;
+ idx=infoPtr->root->firstChild;
+ }
+ do {
+ if (idx == NULL) {
+ if (endidx == NULL)
+ break;
+ idx=infoPtr->root->firstChild;
+ }
+
+ /* get item */
+ ZeroMemory(&item, sizeof(item));
+ item.mask = TVIF_TEXT;
+ item.hItem = idx;
+ item.pszText = buffer;
+ item.cchTextMax = sizeof(buffer);
+ TREEVIEW_GetItemA( infoPtr, &item );
+
+ /* check for a match */
+ if (strncasecmp(item.pszText,infoPtr->szSearchParam,infoPtr->nSearchParamLength) == 0) {
+ nItem=idx;
+ break;
+ } else if ( (charCode != 0) && (nItem == NULL) &&
+ (nItem != infoPtr->selectedItem) &&
+ (strncasecmp(item.pszText,infoPtr->szSearchParam,1) == 0) ) {
+ /* This would work but we must keep looking for a longer match */
+ nItem=idx;
+ }
+ idx=TREEVIEW_GetNextListItem(infoPtr,idx);
+ } while (idx != endidx);
+
+ if (nItem != NULL) {
+ if (TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, nItem, TVC_BYKEYBOARD)) {
+ TREEVIEW_EnsureVisible(infoPtr, nItem, FALSE);
+ }
+ }
+
+ return 0;
+}
+
/* Scrolling ************************************************************/
static LRESULT
@@ -4874,7 +5032,8 @@
case TVM_SORTCHILDRENCB:
return TREEVIEW_SortChildrenCB(infoPtr, wParam, (LPTVSORTCB)lParam);
- /* WM_CHAR */
+ case WM_CHAR:
+ return TREEVIEW_ProcessLetterKeys( hwnd, wParam, lParam );
case WM_COMMAND:
return TREEVIEW_Command(infoPtr, wParam, lParam);
More information about the wine-patches
mailing list