Release 960314
[wine/multimedia.git] / controls / listbox.c
blobe255cbd036561d8cfceb44b2c1e284d24f45d9fb
1 /*
2 * Listbox controls
3 *
4 * Copyright Martin Ayotte, 1993
5 * Constantine Sapuntzakis, 1995
6 * Alex Korobka, 1995
7 *
8 */
11 * FIXME:
12 * - check if multi-column listboxes work
13 * - implement more messages and styles
14 * - implement caret for LBS_EXTENDEDSEL
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <ctype.h>
21 #include "windows.h"
22 #include "user.h"
23 #include "win.h"
24 #include "gdi.h"
25 #include "msdos.h"
26 #include "listbox.h"
27 #include "dos_fs.h"
28 #include "drive.h"
29 #include "file.h"
30 #include "stackframe.h"
31 #include "stddebug.h"
32 #include "debug.h"
33 #include "xmalloc.h"
35 #if 0
36 #define LIST_HEAP_ALLOC(lphl,f,size) ((int)HEAP_Alloc(&lphl->Heap,f,size) & 0xffff)
37 #define LIST_HEAP_FREE(lphl,handle) (HEAP_Free(&lphl->Heap,LIST_HEAP_ADDR(lphl,handle)))
38 #define LIST_HEAP_ADDR(lphl,handle) \
39 ((void *)((handle) ? ((handle) | ((int)lphl->Heap & 0xffff0000)) : 0))
40 #else
41 /* FIXME: shouldn't each listbox have its own heap? */
42 #if 0
43 #define LIST_HEAP_ALLOC(lphl,f,size) USER_HEAP_ALLOC(size)
44 #define LIST_HEAP_FREE(lphl,handle) USER_HEAP_FREE(handle)
45 #define LIST_HEAP_ADDR(lphl,handle) USER_HEAP_LIN_ADDR(handle)
46 #define LIST_HEAP_SEG_ADDR(lphl,handle) USER_HEAP_SEG_ADDR(handle)
47 #else
48 /* Something like this maybe ? */
49 #define LIST_HEAP_ALLOC(lphl,f,size) \
50 LOCAL_Alloc( lphl->HeapSel, LMEM_FIXED, (size) )
51 #if 0
52 #define LIST_HEAP_REALLOC(handle,size) \
53 LOCAL_ReAlloc( USER_HeapSel, (handle), (size), LMEM_FIXED )
54 #endif
55 #define LIST_HEAP_FREE(lphl,handle) \
56 LOCAL_Free( lphl->HeapSel, (handle) )
57 #define LIST_HEAP_ADDR(lphl,handle) \
58 ((handle) ? PTR_SEG_OFF_TO_LIN(lphl->HeapSel, (handle)) : NULL)
59 #define LIST_HEAP_SEG_ADDR(lphl,handle) \
60 ((handle) ? MAKELONG((handle), lphl->HeapSel) : 0)
61 #endif
62 #endif
64 #define LIST_HEAP_SIZE 0x10000
66 static void ListBoxInitialize(LPHEADLIST lphl)
68 lphl->lpFirst = NULL;
69 lphl->ItemsCount = 0;
70 lphl->ItemsVisible = 0;
71 lphl->FirstVisible = 0;
72 lphl->ColumnsVisible = 1;
73 lphl->ItemsPerColumn = 0;
74 lphl->ItemFocused = -1;
75 lphl->PrevFocused = -1;
78 void CreateListBoxStruct(HWND hwnd, WORD CtlType, LONG styles, HWND parent)
80 LPHEADLIST lphl;
81 HDC hdc;
83 lphl = (LPHEADLIST)xmalloc(sizeof(HEADLIST));
84 SetWindowLong(hwnd, 0, (LONG)lphl);
85 ListBoxInitialize(lphl);
86 lphl->DrawCtlType = CtlType;
87 lphl->CtlID = GetWindowWord(hwnd,GWW_ID);
88 lphl->bRedrawFlag = TRUE;
89 lphl->iNumStops = 0;
90 lphl->TabStops = NULL;
91 lphl->hFont = GetStockObject(SYSTEM_FONT);
92 lphl->hSelf = hwnd;
93 if (CtlType==ODT_COMBOBOX) /* use the "faked" style for COMBOLBOX */
94 /* LBS_SORT instead CBS_SORT e.g. */
95 lphl->dwStyle = MAKELONG(LOWORD(styles),HIWORD(GetWindowLong(hwnd,GWL_STYLE)));
96 else
97 lphl->dwStyle = GetWindowLong(hwnd,GWL_STYLE); /* use original style dword */
98 lphl->hParent = parent;
99 lphl->StdItemHeight = 15; /* FIXME: should get the font height */
100 lphl->OwnerDrawn = styles & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE);
101 lphl->HasStrings = (styles & LBS_HASSTRINGS) || !lphl->OwnerDrawn;
103 /* create dummy hdc to set text height */
104 if ((hdc = GetDC(0)))
106 TEXTMETRIC tm;
107 GetTextMetrics( hdc, &tm );
108 lphl->StdItemHeight = tm.tmHeight;
109 dprintf_listbox(stddeb,"CreateListBoxStruct: font height %d\n",
110 lphl->StdItemHeight);
111 ReleaseDC( 0, hdc );
114 if (lphl->OwnerDrawn) {
115 LISTSTRUCT dummyls;
117 lphl->hDrawItemStruct = USER_HEAP_ALLOC(sizeof(DRAWITEMSTRUCT));
118 lphl->needMeasure = TRUE;
119 dummyls.mis.CtlType = lphl->DrawCtlType;
120 dummyls.mis.CtlID = lphl->CtlID;
121 dummyls.mis.itemID = -1;
122 dummyls.mis.itemWidth = 0; /* ignored */
123 dummyls.mis.itemData = 0;
125 ListBoxAskMeasure(lphl,&dummyls);
126 } else {
127 lphl->hDrawItemStruct = 0;
130 #if 0
131 HeapHandle = GlobalAlloc(GMEM_FIXED, LIST_HEAP_SIZE);
132 HeapBase = GlobalLock(HeapHandle);
133 HEAP_Init(&lphl->Heap, HeapBase, LIST_HEAP_SIZE);
134 #endif
135 /* WINELIBS list boxes do not operate on local heaps */
136 #ifndef WINELIB
137 lphl->HeapSel = GlobalAlloc(GMEM_FIXED,LIST_HEAP_SIZE);
138 LocalInit( lphl->HeapSel, 0, LIST_HEAP_SIZE-1);
139 #else
140 lphl->HeapSel = 0;
141 #endif
144 void DestroyListBoxStruct(LPHEADLIST lphl)
146 if (lphl->hDrawItemStruct)
147 USER_HEAP_FREE(lphl->hDrawItemStruct);
149 /* XXX need to free lphl->Heap */
150 GlobalFree(lphl->HeapSel);
151 free(lphl);
154 static LPHEADLIST ListBoxGetStorageHeader(HWND hwnd)
156 return (LPHEADLIST)GetWindowLong(hwnd,0);
159 /* Send notification "code" as part of a WM_COMMAND-message if hwnd
160 has the LBS_NOTIFY style */
161 void ListBoxSendNotification(LPHEADLIST lphl, WORD code)
163 if (lphl->dwStyle & LBS_NOTIFY)
164 #ifdef WINELIB32
165 SendMessage(lphl->hParent, WM_COMMAND,
166 MAKEWPARAM(lphl->CtlID,code), (LPARAM)lphl->hSelf);
167 #else
168 SendMessage(lphl->hParent, WM_COMMAND,
169 lphl->CtlID, MAKELONG(lphl->hSelf, code));
170 #endif
174 /* get the maximum value of lphl->FirstVisible */
175 int ListMaxFirstVisible(LPHEADLIST lphl)
177 int m = lphl->ItemsCount-lphl->ItemsVisible;
178 return (m < 0) ? 0 : m;
182 void ListBoxUpdateWindow(HWND hwnd, LPHEADLIST lphl, BOOL repaint)
184 SetScrollRange(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
185 if (lphl->ItemsPerColumn != 0) {
186 SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
187 lphl->ItemsPerColumn + 1, TRUE);
189 if (repaint && lphl->bRedrawFlag) {
190 InvalidateRect(hwnd, NULL, TRUE);
194 /* Returns: 0 if nothing needs to be changed */
195 /* 1 if FirstVisible changed */
197 int ListBoxScrollToFocus(LPHEADLIST lphl)
199 short end;
201 if (lphl->ItemsCount == 0) return 0;
202 if (lphl->ItemFocused == -1) return 0;
204 end = lphl->FirstVisible + lphl->ItemsVisible - 1;
206 if (lphl->ItemFocused < lphl->FirstVisible ) {
207 lphl->FirstVisible = lphl->ItemFocused;
208 return 1;
209 } else {
210 if (lphl->ItemFocused > end) {
211 WORD maxFirstVisible = ListMaxFirstVisible(lphl);
213 lphl->FirstVisible = lphl->ItemFocused;
215 if (lphl->FirstVisible > maxFirstVisible) {
216 lphl->FirstVisible = maxFirstVisible;
218 return 1;
221 return 0;
225 LPLISTSTRUCT ListBoxGetItem(LPHEADLIST lphl, UINT uIndex)
227 LPLISTSTRUCT lpls;
228 UINT Count = 0;
230 if (uIndex >= lphl->ItemsCount) return NULL;
232 lpls = lphl->lpFirst;
233 while (Count++ < uIndex) lpls = lpls->lpNext;
234 return lpls;
238 void ListBoxDrawItem (HWND hwnd, LPHEADLIST lphl, HDC hdc, LPLISTSTRUCT lpls,
239 RECT *rect, WORD itemAction, WORD itemState)
241 if (lphl->OwnerDrawn) {
242 DRAWITEMSTRUCT *dis = USER_HEAP_LIN_ADDR(lphl->hDrawItemStruct);
244 dis->CtlID = lpls->mis.CtlID;
245 dis->CtlType = lpls->mis.CtlType;
246 dis->itemID = lpls->mis.itemID;
247 dis->hDC = hdc;
248 dis->hwndItem = hwnd;
249 dis->itemData = lpls->mis.itemData;
250 dis->itemAction = itemAction;
251 dis->itemState = itemState;
252 dis->rcItem = *rect;
253 SendMessage(lphl->hParent, WM_DRAWITEM,
254 0, (LPARAM)USER_HEAP_SEG_ADDR(lphl->hDrawItemStruct));
255 } else {
256 if (itemAction == ODA_DRAWENTIRE || itemAction == ODA_SELECT) {
257 int OldBkMode;
258 DWORD dwOldTextColor = 0;
260 OldBkMode = SetBkMode(hdc, TRANSPARENT);
262 if (itemState != 0) {
263 dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
264 FillRect(hdc, rect, GetStockObject(BLACK_BRUSH));
267 if (lphl->dwStyle & LBS_USETABSTOPS) {
268 TabbedTextOut(hdc, rect->left + 5, rect->top + 2,
269 (char *)lpls->itemText, strlen((char *)lpls->itemText),
270 lphl->iNumStops, lphl->TabStops, 0);
271 } else {
272 TextOut(hdc, rect->left + 5, rect->top + 2,
273 (char *)lpls->itemText, strlen((char *)lpls->itemText));
276 if (itemState != 0) {
277 SetTextColor(hdc, dwOldTextColor);
280 SetBkMode(hdc, OldBkMode);
281 } else DrawFocusRect(hdc, rect);
284 return;
288 int ListBoxFindMouse(LPHEADLIST lphl, int X, int Y)
290 LPLISTSTRUCT lpls = lphl->lpFirst;
291 int i, j;
292 POINT point;
294 point.x = X; point.y = Y;
295 if (lphl->ItemsCount == 0) return LB_ERR;
297 for(i = 0; i < lphl->FirstVisible; i++) {
298 if (lpls == NULL) return LB_ERR;
299 lpls = lpls->lpNext;
301 for(j = 0; j < lphl->ItemsVisible; i++, j++) {
302 if (lpls == NULL) return LB_ERR;
303 if (PtInRect(&lpls->itemRect,point)) {
304 return i;
306 lpls = lpls->lpNext;
308 dprintf_listbox(stddeb,"ListBoxFindMouse: not found\n");
309 return LB_ERR;
313 void ListBoxAskMeasure(LPHEADLIST lphl, LPLISTSTRUCT lpls)
315 HANDLE hTemp = USER_HEAP_ALLOC( sizeof(MEASUREITEMSTRUCT) );
316 MEASUREITEMSTRUCT *lpmeasure = (MEASUREITEMSTRUCT *) USER_HEAP_LIN_ADDR(hTemp);
318 if (lpmeasure == NULL) {
319 fprintf(stdnimp,"ListBoxAskMeasure() out of memory !\n");
320 return;
323 *lpmeasure = lpls->mis;
324 lpmeasure->itemHeight = lphl->StdItemHeight;
325 SendMessage(lphl->hParent, WM_MEASUREITEM, 0, (LPARAM)USER_HEAP_SEG_ADDR(hTemp));
327 if (lphl->dwStyle & LBS_OWNERDRAWFIXED) {
328 lphl->StdItemHeight = lpmeasure->itemHeight;
329 lphl->needMeasure = FALSE;
332 USER_HEAP_FREE(hTemp);
335 /* -------------------- strings and item data ---------------------- */
337 LPLISTSTRUCT ListBoxCreateItem(LPHEADLIST lphl, int id)
339 LPLISTSTRUCT lplsnew = (LPLISTSTRUCT)malloc(sizeof(LISTSTRUCT));
341 if (lplsnew == NULL) return NULL;
343 lplsnew->itemState = 0;
344 lplsnew->mis.CtlType = lphl->DrawCtlType;
345 lplsnew->mis.CtlID = lphl->CtlID;
346 lplsnew->mis.itemID = id;
347 lplsnew->mis.itemHeight = lphl->StdItemHeight;
348 lplsnew->mis.itemWidth = 0; /* ignored */
349 lplsnew->mis.itemData = 0;
350 SetRect(&lplsnew->itemRect, 0, 0, 0, 0);
352 return lplsnew;
356 int ListBoxInsertString(LPHEADLIST lphl, UINT uIndex, LPCSTR newstr)
358 LPLISTSTRUCT *lppls, lplsnew, lpls;
359 HANDLE hStr;
360 LPSTR str;
361 UINT Count;
363 dprintf_listbox(stddeb,"ListBoxInsertString(%d, %p);\n", uIndex, newstr);
365 if (!newstr) return -1;
367 if (uIndex == (UINT)-1)
368 uIndex = lphl->ItemsCount;
370 lppls = &lphl->lpFirst;
371 for(Count = 0; Count < uIndex; Count++) {
372 if (*lppls == NULL) return LB_ERR;
373 lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
376 lplsnew = ListBoxCreateItem(lphl, Count);
378 if (lplsnew == NULL) {
379 fprintf(stdnimp,"ListBoxInsertString() out of memory !\n");
380 return LB_ERRSPACE;
383 lplsnew->lpNext = *lppls;
384 *lppls = lplsnew;
385 lphl->ItemsCount++;
387 hStr = 0;
388 if (lphl->HasStrings) {
389 dprintf_listbox(stddeb," string: %s\n", newstr);
390 hStr = LIST_HEAP_ALLOC(lphl, LMEM_MOVEABLE, strlen(newstr) + 1);
391 str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
392 if (str == NULL) return LB_ERRSPACE;
393 strcpy(str, newstr);
394 lplsnew->itemText = str;
395 /* I'm not so sure about the next one */
396 lplsnew->mis.itemData = 0;
397 } else {
398 lplsnew->itemText = NULL;
399 lplsnew->mis.itemData = (DWORD)newstr;
402 lplsnew->mis.itemID = uIndex;
403 lplsnew->hData = hStr;
405 /* adjust the itemID field of the following entries */
406 for(lpls = lplsnew->lpNext; lpls != NULL; lpls = lpls->lpNext) {
407 lpls->mis.itemID++;
410 if (lphl->needMeasure) {
411 ListBoxAskMeasure(lphl, lplsnew);
414 dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
415 return uIndex;
419 int ListBoxAddString(LPHEADLIST lphl, LPCSTR newstr)
421 UINT pos = (UINT) -1;
423 if (lphl->HasStrings && (lphl->dwStyle & LBS_SORT)) {
424 LPLISTSTRUCT lpls = lphl->lpFirst;
425 for (pos = 0; lpls != NULL; lpls = lpls->lpNext, pos++)
426 if (strcmp(lpls->itemText, newstr) >= 0)
427 break;
429 return ListBoxInsertString(lphl, pos, newstr);
433 int ListBoxGetText(LPHEADLIST lphl, UINT uIndex, LPSTR OutStr)
435 LPLISTSTRUCT lpls;
437 if (!OutStr) {
438 dprintf_listbox(stddeb, "ListBoxGetText // OutStr==NULL\n");
439 return 0;
441 *OutStr = '\0';
442 lpls = ListBoxGetItem (lphl, uIndex);
443 if (lpls == NULL) return LB_ERR;
445 if (!lphl->HasStrings) {
446 *((long *)OutStr) = lpls->mis.itemData;
447 return 4;
450 strcpy(OutStr, lpls->itemText);
451 return strlen(OutStr);
455 DWORD ListBoxGetItemData(LPHEADLIST lphl, UINT uIndex)
457 LPLISTSTRUCT lpls;
459 lpls = ListBoxGetItem (lphl, uIndex);
460 if (lpls == NULL) return LB_ERR;
461 return lpls->mis.itemData;
465 int ListBoxSetItemData(LPHEADLIST lphl, UINT uIndex, DWORD ItemData)
467 LPLISTSTRUCT lpls = ListBoxGetItem(lphl, uIndex);
469 if (lpls == NULL) return LB_ERR;
470 lpls->mis.itemData = ItemData;
471 return 1;
475 int ListBoxDeleteString(LPHEADLIST lphl, UINT uIndex)
477 LPLISTSTRUCT lpls, lpls2;
478 UINT Count;
480 if (uIndex >= lphl->ItemsCount) return LB_ERR;
482 lpls = lphl->lpFirst;
483 if (lpls == NULL) return LB_ERR;
485 if (uIndex == 0)
486 lphl->lpFirst = lpls->lpNext;
487 else {
488 LPLISTSTRUCT lpls2 = NULL;
489 for(Count = 0; Count < uIndex; Count++) {
490 if (lpls->lpNext == NULL) return LB_ERR;
492 lpls2 = lpls;
493 lpls = (LPLISTSTRUCT)lpls->lpNext;
495 lpls2->lpNext = lpls->lpNext;
498 /* adjust the itemID field of the following entries */
499 for(lpls2 = lpls->lpNext; lpls2 != NULL; lpls2 = lpls2->lpNext) {
500 lpls2->mis.itemID--;
503 lphl->ItemsCount--;
505 if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
506 free(lpls);
508 return lphl->ItemsCount;
512 int ListBoxFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr)
514 LPLISTSTRUCT lpls;
515 UINT Count;
516 UINT First = nFirst + 1;
517 LPSTR lpMatchStr = (LPSTR)MatchStr;
519 if (First > lphl->ItemsCount) return LB_ERR;
521 if (lphl->HasStrings) lpMatchStr = PTR_SEG_TO_LIN(MatchStr);
523 lpls = ListBoxGetItem(lphl, First);
524 Count = 0;
525 while(lpls != NULL) {
526 if (lphl->HasStrings) {
527 if (strstr(lpls->itemText, lpMatchStr) == lpls->itemText) return Count;
528 } else if (lphl->dwStyle & LBS_SORT) {
529 /* XXX Do a compare item */
531 else
532 if (lpls->mis.itemData == (DWORD)lpMatchStr) return Count;
534 lpls = lpls->lpNext;
535 Count++;
538 /* Start over at top */
539 Count = 0;
540 lpls = lphl->lpFirst;
542 while (Count < First) {
543 if (lphl->HasStrings) {
544 if (strstr(lpls->itemText, lpMatchStr) == lpls->itemText) return Count;
545 } else if (lphl->dwStyle & LBS_SORT) {
546 /* XXX Do a compare item */
547 } else {
548 if (lpls->mis.itemData == (DWORD)lpMatchStr) return Count;
550 lpls = lpls->lpNext;
551 Count++;
554 return LB_ERR;
558 int ListBoxResetContent(LPHEADLIST lphl)
560 LPLISTSTRUCT lpls;
561 int i;
563 if (lphl->ItemsCount == 0) return 0;
565 dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n",
566 lphl->ItemsCount);
568 for(i = 0; i < lphl->ItemsCount; i++) {
569 lpls = lphl->lpFirst;
570 if (lpls == NULL) return LB_ERR;
572 lphl->lpFirst = lpls->lpNext;
573 if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
574 free(lpls);
576 ListBoxInitialize(lphl);
578 return TRUE;
581 /* --------------------- selection ------------------------- */
583 int ListBoxSetCurSel(LPHEADLIST lphl, WORD wIndex)
585 LPLISTSTRUCT lpls;
587 /* use ListBoxSetSel instead */
588 if (lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ) return 0;
590 /* unselect previous item */
591 if (lphl->ItemFocused != -1) {
592 lphl->PrevFocused = lphl->ItemFocused;
593 lpls = ListBoxGetItem(lphl, lphl->ItemFocused);
594 if (lpls == 0) return LB_ERR;
595 lpls->itemState = 0;
598 if (wIndex != (UINT)-1) {
599 lphl->ItemFocused = wIndex;
600 lpls = ListBoxGetItem(lphl, wIndex);
601 if (lpls == 0) return LB_ERR;
602 lpls->itemState = ODS_SELECTED | ODS_FOCUS;
604 return 0;
607 return LB_ERR;
611 int ListBoxSetSel(LPHEADLIST lphl, WORD wIndex, WORD state)
613 LPLISTSTRUCT lpls;
614 int n = 0;
616 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
617 return LB_ERR;
619 if (wIndex == (UINT)-1) {
620 for (lpls = lphl->lpFirst; lpls != NULL; lpls = lpls->lpNext) {
621 if( lpls->itemState & ODS_SELECTED) n++;
622 lpls->itemState = state? lpls->itemState | ODS_SELECTED
623 : lpls->itemState & ~ODS_SELECTED;
625 return n;
628 if (wIndex >= lphl->ItemsCount) return LB_ERR;
630 lpls = ListBoxGetItem(lphl, wIndex);
631 lpls->itemState = state? lpls->itemState | ODS_SELECTED
632 : lpls->itemState & ~ODS_SELECTED;
634 return 0;
638 int ListBoxGetSel(LPHEADLIST lphl, WORD wIndex)
640 LPLISTSTRUCT lpls = ListBoxGetItem(lphl, wIndex);
642 if (lpls == NULL) return LB_ERR;
643 return lpls->itemState & ODS_SELECTED;
646 /* ------------------------- dir listing ------------------------ */
648 LONG ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPCSTR filespec)
650 char temp[16], mask[13];
651 char *path, *p;
652 const char *ptr;
653 int skip, count;
654 LONG ret;
655 DOS_DIRENT entry;
657 dprintf_listbox(stddeb, "ListBoxDirectory: '%s' %04x\n", filespec, attrib);
658 if (!filespec) return LB_ERR;
659 if (!(ptr = DOSFS_GetUnixFileName( filespec, FALSE ))) return LB_ERR;
660 path = xstrdup(ptr);
661 p = strrchr( path, '/' );
662 *p++ = '\0';
663 if (!(ptr = DOSFS_ToDosFCBFormat( p )))
665 free( path );
666 return LB_ERR;
668 strcpy( mask, ptr );
670 dprintf_listbox(stddeb, "ListBoxDirectory: path=%s mask=%s\n", path, mask);
672 skip = ret = 0;
673 attrib &= ~FA_LABEL;
674 while ((count = DOSFS_FindNext( path, mask, 0, attrib, skip, &entry )) > 0)
676 skip += count;
677 if (entry.attr & FA_DIRECTORY)
679 if ((attrib & DDL_DIRECTORY) && strcmp(entry.name, ". "))
681 sprintf(temp, "[%s]", DOSFS_ToDosDTAFormat( entry.name ) );
682 AnsiLower( temp );
683 if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
686 else /* not a directory */
688 if (!(attrib & DDL_EXCLUSIVE) ||
689 ((attrib & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)) ==
690 (entry.attr & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE))))
692 strcpy( temp, DOSFS_ToDosDTAFormat( entry.name ) );
693 AnsiLower( temp );
694 if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
698 if (attrib & DDL_DRIVES)
700 int x;
701 strcpy( temp, "[-a-]" );
702 for (x = 0; x < MAX_DOS_DRIVES; x++, temp[2]++)
704 if (DRIVE_IsValid(x))
705 if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
708 free( path );
709 return ret;
712 /* ------------------------- dimensions ------------------------- */
714 int ListBoxGetItemRect(LPHEADLIST lphl, WORD wIndex, LPRECT lprect)
716 LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wIndex);
718 if (lpls == NULL) return LB_ERR;
719 *lprect = lpls->itemRect;
720 return 0;
724 int ListBoxSetItemHeight(LPHEADLIST lphl, WORD wIndex, long height)
726 LPLISTSTRUCT lpls;
728 if (!(lphl->dwStyle & LBS_OWNERDRAWVARIABLE)) {
729 lphl->StdItemHeight = (short)height;
730 return 0;
733 lpls = ListBoxGetItem(lphl, wIndex);
734 if (lpls == NULL) return LB_ERR;
736 lpls->mis.itemHeight = height;
737 return 0;
740 /* -------------------------- string search ------------------------ */
742 int ListBoxFindNextMatch(LPHEADLIST lphl, WORD wChar)
744 LPLISTSTRUCT lpls;
745 UINT count,first;
747 if ((char)wChar < ' ') return LB_ERR;
748 if (!lphl->HasStrings) return LB_ERR;
750 lpls = lphl->lpFirst;
752 for (count = 0; lpls != NULL; lpls = lpls->lpNext, count++) {
753 if (tolower(*lpls->itemText) == tolower((char)wChar)) break;
755 if (lpls == NULL) return LB_ERR;
756 first = count;
757 for(; lpls != NULL; lpls = lpls->lpNext, count++) {
758 if (*lpls->itemText != (char)wChar)
759 break;
760 if ((short) count > lphl->ItemFocused)
761 return count;
763 return first;
766 /***********************************************************************
767 * LBCreate
769 static LONG LBCreate(HWND hwnd, WORD wParam, LONG lParam)
771 LPHEADLIST lphl;
772 LONG dwStyle = GetWindowLong(hwnd,GWL_STYLE);
773 RECT rect;
775 CreateListBoxStruct(hwnd, ODT_LISTBOX, dwStyle, GetParent(hwnd));
776 lphl = ListBoxGetStorageHeader(hwnd);
777 dprintf_listbox(stddeb,"ListBox created: lphl = %p dwStyle = %04x:%04x\n",
778 lphl, HIWORD(dwStyle), LOWORD(dwStyle));
780 GetClientRect(hwnd,&rect);
781 lphl->ColumnsWidth = rect.right - rect.left;
783 SetScrollRange(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
784 SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
786 return 0;
790 /***********************************************************************
791 * LBDestroy
793 static LONG LBDestroy(HWND hwnd, WORD wParam, LONG lParam)
795 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
797 ListBoxResetContent(lphl);
799 DestroyListBoxStruct(lphl);
800 dprintf_listbox(stddeb,"ListBox destroyed: lphl = %p\n",lphl);
801 return 0;
804 /***********************************************************************
805 * LBVScroll
807 static LONG LBVScroll(HWND hwnd, WORD wParam, LONG lParam)
809 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
810 int y;
812 dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
813 wParam, lParam);
814 y = lphl->FirstVisible;
816 switch(wParam) {
817 case SB_LINEUP:
818 if (lphl->FirstVisible > 0)
819 lphl->FirstVisible--;
820 break;
822 case SB_LINEDOWN:
823 lphl->FirstVisible++;
824 break;
826 case SB_PAGEUP:
827 if (lphl->FirstVisible > lphl->ItemsVisible) {
828 lphl->FirstVisible -= lphl->ItemsVisible;
829 } else {
830 lphl->FirstVisible = 0;
832 break;
834 case SB_PAGEDOWN:
835 lphl->FirstVisible += lphl->ItemsVisible;
836 break;
838 case SB_THUMBTRACK:
839 lphl->FirstVisible = LOWORD(lParam);
840 break;
843 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
844 lphl->FirstVisible = ListMaxFirstVisible(lphl);
846 if (y != lphl->FirstVisible) {
847 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
848 InvalidateRect(hwnd, NULL, TRUE);
850 return 0;
853 /***********************************************************************
854 * LBHScroll
856 static LONG LBHScroll(HWND hwnd, WORD wParam, LONG lParam)
858 LPHEADLIST lphl;
859 int y;
861 dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
862 wParam, lParam);
863 lphl = ListBoxGetStorageHeader(hwnd);
864 y = lphl->FirstVisible;
865 switch(wParam) {
866 case SB_LINEUP:
867 if (lphl->FirstVisible > lphl->ItemsPerColumn) {
868 lphl->FirstVisible -= lphl->ItemsPerColumn;
869 } else {
870 lphl->FirstVisible = 0;
872 break;
873 case SB_LINEDOWN:
874 lphl->FirstVisible += lphl->ItemsPerColumn;
875 break;
876 case SB_PAGEUP:
877 if (lphl->ItemsPerColumn != 0) {
878 int lbsub = lphl->ItemsVisible / lphl->ItemsPerColumn * lphl->ItemsPerColumn;
879 if (lphl->FirstVisible > lbsub) {
880 lphl->FirstVisible -= lbsub;
881 } else {
882 lphl->FirstVisible = 0;
885 break;
886 case SB_PAGEDOWN:
887 if (lphl->ItemsPerColumn != 0)
888 lphl->FirstVisible += lphl->ItemsVisible /
889 lphl->ItemsPerColumn * lphl->ItemsPerColumn;
890 break;
891 case SB_THUMBTRACK:
892 lphl->FirstVisible = lphl->ItemsPerColumn * LOWORD(lParam);
893 break;
895 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
896 lphl->FirstVisible = ListMaxFirstVisible(lphl);
898 if (lphl->ItemsPerColumn != 0) {
899 lphl->FirstVisible = lphl->FirstVisible /
900 lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
901 if (y != lphl->FirstVisible) {
902 SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible /
903 lphl->ItemsPerColumn + 1, TRUE);
904 InvalidateRect(hwnd, NULL, TRUE);
907 return 0;
910 /***********************************************************************
911 * LBLButtonDown
913 static LONG LBLButtonDown(HWND hwnd, WORD wParam, LONG lParam)
915 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
916 WORD wRet;
917 int y,n;
918 RECT rectsel;
919 POINT tmpPOINT;
920 tmpPOINT.x = LOWORD(lParam); tmpPOINT.y = HIWORD(lParam);
922 SetFocus(hwnd);
923 SetCapture(hwnd);
925 lphl->PrevFocused = lphl->ItemFocused;
927 y = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
929 if (y == -1) return 0;
931 if (lphl->dwStyle & LBS_NOTIFY && y!= LB_ERR )
932 if( SendMessage(lphl->hParent, WM_LBTRACKPOINT, y, lParam) )
933 return 0;
936 switch( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )
938 case LBS_MULTIPLESEL:
939 lphl->ItemFocused = y;
940 wRet = ListBoxGetSel(lphl, y);
941 ListBoxSetSel(lphl, y, !wRet);
942 break;
943 case LBS_EXTENDEDSEL:
944 /* should handle extended mode here and in kbd handler
947 if ( lphl->PrevFocused != y && y!= LB_ERR)
949 LPLISTSTRUCT lpls = ListBoxGetItem( lphl, lphl->ItemFocused = y );
950 n = ListBoxSetSel(lphl,-1,FALSE);
952 lpls->itemState = ODS_FOCUS | ODS_SELECTED;
954 if( n > 1 && n != LB_ERR )
955 InvalidateRect(hwnd,NULL,TRUE);
957 else
958 return 0;
960 break;
961 case 0:
962 if( y!=lphl->ItemFocused )
963 ListBoxSetCurSel(lphl, y);
964 else
965 return 0;
966 break;
967 default:
968 fprintf(stdnimp,"Listbox: LBS_MULTIPLESEL and LBS_EXTENDEDSEL are on!\n");
969 return 0;
972 /* invalidate changed items */
973 if( lphl->dwStyle & LBS_MULTIPLESEL || y!=lphl->PrevFocused )
975 ListBoxGetItemRect(lphl, y, &rectsel);
976 InvalidateRect(hwnd, &rectsel, TRUE);
978 if( lphl->PrevFocused!=-1 && y!=lphl->PrevFocused )
980 ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
981 InvalidateRect(hwnd, &rectsel, TRUE);
984 #ifndef WINELIB
985 if (GetWindowLong(lphl->hSelf,GWL_EXSTYLE) & WS_EX_DRAGDETECT)
986 if( DragDetect(lphl->hSelf,tmpPOINT) )
987 SendMessage(lphl->hParent, WM_BEGINDRAG,0,0L);
988 #endif
989 return 0;
992 /***********************************************************************
993 * LBLButtonUp
995 static LONG LBLButtonUp(HWND hwnd, WORD wParam, LONG lParam)
997 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
999 if (GetCapture() == hwnd) ReleaseCapture();
1001 if (lphl->PrevFocused != lphl->ItemFocused)
1002 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1004 return 0;
1007 /***********************************************************************
1008 * LBRButtonUp
1010 static LONG LBRButtonUp(HWND hwnd, WORD wParam, LONG lParam)
1012 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1014 #ifdef WINELIB32
1015 SendMessage(lphl->hParent, WM_COMMAND,
1016 MAKEWPARAM(GetWindowWord(hwnd,GWW_ID),LBN_DBLCLK),
1017 (LPARAM)hwnd);
1018 #else
1019 SendMessage(lphl->hParent, WM_COMMAND, GetWindowWord(hwnd,GWW_ID),
1020 MAKELONG(hwnd, LBN_DBLCLK));
1021 #endif
1023 return 0;
1026 /***********************************************************************
1027 * LBMouseMove
1029 static LONG LBMouseMove(HWND hwnd, WORD wParam, LONG lParam)
1031 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1032 int y,redraw_prev = 0;
1033 int iRet;
1034 RECT rect, rectsel; /* XXX Broken */
1036 dprintf_listbox(stddeb,"LBMouseMove %d %d\n",SLOWORD(lParam),SHIWORD(lParam));
1037 if ((wParam & MK_LBUTTON) != 0) {
1038 y = SHIWORD(lParam);
1039 if (y < 0) {
1040 if (lphl->FirstVisible > 0) {
1041 lphl->FirstVisible--;
1042 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1043 InvalidateRect(hwnd, NULL, TRUE);
1044 return 0;
1047 GetClientRect(hwnd, &rect);
1048 if (y >= rect.bottom) {
1049 if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
1050 lphl->FirstVisible++;
1051 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1052 InvalidateRect(hwnd, NULL, TRUE);
1053 return 0;
1056 if ((y > 0) && (y < (rect.bottom - 4))) {
1057 if ((y < rectsel.top) || (y > rectsel.bottom)) {
1058 iRet = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
1059 if (iRet == lphl->ItemFocused || iRet == -1) {
1060 return 0;
1062 if (lphl->dwStyle & LBS_MULTIPLESEL) {
1063 lphl->ItemFocused = iRet;
1064 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1065 } else if ( lphl->dwStyle & LBS_EXTENDEDSEL )
1067 /* Fixme: extended selection mode */
1068 ListBoxSetSel( lphl, lphl->ItemFocused, 0);
1069 lphl->PrevFocused = lphl->ItemFocused;
1070 lphl->ItemFocused = iRet;
1071 ListBoxSetSel( lphl, iRet, TRUE);
1072 redraw_prev = 1;
1074 else
1076 ListBoxSetCurSel(lphl, (WORD)iRet);
1077 redraw_prev = 1;
1079 if( lphl->PrevFocused!=-1 && redraw_prev )
1081 ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
1082 InvalidateRect(hwnd, &rectsel, TRUE);
1084 ListBoxGetItemRect(lphl, iRet, &rectsel);
1085 InvalidateRect(hwnd, &rectsel, TRUE);
1090 return 0;
1093 /***********************************************************************
1094 * LBKeyDown
1096 * Doesn't yet handle properly VK_SHIFT with LB_EXTENDEDSEL
1098 static LONG LBKeyDown(HWND hwnd, WORD wParam, LONG lParam)
1100 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1101 WORD newFocused = 0xFFFF;
1102 RECT rect;
1104 ListBoxGetItemRect(lphl,lphl->ItemFocused,&rect);
1105 switch(wParam)
1107 case VK_HOME:
1108 case VK_END:
1109 case VK_LEFT:
1110 case VK_RIGHT:
1111 case VK_UP:
1112 case VK_DOWN:
1113 case VK_PRIOR:
1114 case VK_NEXT:
1115 if ( lphl->dwStyle & LBS_WANTKEYBOARDINPUT )
1117 newFocused = (WORD)(INT)SendMessage(lphl->hParent,WM_VKEYTOITEM,
1118 wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
1119 if ( newFocused == 0xFFFE ) return 0L;
1121 if ( newFocused == 0xFFFF )
1123 newFocused = lphl->ItemFocused;
1125 /* nested switch */
1126 switch(wParam)
1128 case VK_HOME:
1129 newFocused = 0;
1130 break;
1131 case VK_END:
1132 newFocused = lphl->ItemsCount - 1;
1133 break;
1134 case VK_LEFT:
1135 if (lphl->dwStyle & LBS_MULTICOLUMN) {
1136 if (newFocused >= lphl->ItemsPerColumn) {
1137 newFocused -= lphl->ItemsPerColumn;
1138 } else {
1139 newFocused = 0;
1142 break;
1143 case VK_UP:
1144 if (newFocused > 0) newFocused--;
1145 break;
1146 case VK_RIGHT:
1147 if (lphl->dwStyle & LBS_MULTICOLUMN)
1148 newFocused += lphl->ItemsPerColumn;
1149 break;
1150 case VK_DOWN:
1151 newFocused++;
1152 break;
1153 case VK_PRIOR:
1154 if (newFocused > lphl->ItemsVisible)
1155 newFocused -= lphl->ItemsVisible;
1156 else newFocused = 0;
1157 break;
1158 case VK_NEXT:
1159 newFocused += lphl->ItemsVisible;
1160 break;
1161 default:
1162 return 0;
1164 /* end of nested switch */
1166 break;
1167 case VK_SPACE:
1168 if (lphl->dwStyle & LBS_MULTIPLESEL)
1170 WORD wRet = ListBoxGetSel(lphl, lphl->ItemFocused);
1171 ListBoxSetSel(lphl, lphl->ItemFocused, !wRet);
1173 return 0;
1175 /* chars are handled in LBChar */
1176 default:
1177 return 0;
1180 /* at this point newFocused is set up */
1182 if (newFocused >= lphl->ItemsCount)
1183 newFocused = lphl->ItemsCount - 1;
1185 if (!(lphl->dwStyle & LBS_MULTIPLESEL))
1187 ListBoxSetCurSel(lphl, newFocused);
1188 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1191 lphl->ItemFocused = newFocused;
1193 if( ListBoxScrollToFocus(lphl) || (lphl->dwStyle &
1194 (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) )
1195 InvalidateRect(hwnd, NULL, TRUE);
1196 else
1198 InvalidateRect(hwnd, &rect, TRUE);
1199 if( newFocused < 0x8000 )
1201 ListBoxGetItemRect(lphl, newFocused, &rect);
1202 InvalidateRect(hwnd, &rect, TRUE);
1206 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1208 return 0;
1211 /***********************************************************************
1212 * LBChar
1214 static LONG LBChar(HWND hwnd, WORD wParam, LONG lParam)
1216 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1217 WORD newFocused = 0xFFFF;
1219 if ( (lphl->dwStyle & LBS_WANTKEYBOARDINPUT) && !(lphl->HasStrings))
1221 newFocused = (WORD)(INT)SendMessage(lphl->hParent,WM_CHARTOITEM,
1222 wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
1223 if ( newFocused == 0xFFFE ) return 0L;
1226 if (newFocused == 0xFFFF )
1227 newFocused = ListBoxFindNextMatch(lphl, wParam);
1229 if (newFocused == (WORD)LB_ERR) return 0;
1231 if (newFocused >= lphl->ItemsCount)
1232 newFocused = lphl->ItemsCount - 1;
1234 if (!(lphl->dwStyle & LBS_MULTIPLESEL))
1236 ListBoxSetCurSel(lphl, newFocused);
1237 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1240 lphl->ItemFocused = newFocused;
1241 ListBoxScrollToFocus(lphl);
1242 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1244 InvalidateRect(hwnd, NULL, TRUE);
1246 return 0;
1249 /***********************************************************************
1250 * LBSetRedraw
1252 static LONG LBSetRedraw(HWND hwnd, WORD wParam, LONG lParam)
1254 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1256 dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd="NPFMT" w=%04X !\n",
1257 hwnd, wParam);
1258 lphl->bRedrawFlag = wParam;
1260 return 0;
1263 /***********************************************************************
1264 * LBSetFont
1266 static LONG LBSetFont(HWND hwnd, WPARAM wParam, LPARAM lParam)
1268 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1269 HDC hdc;
1271 if (wParam == 0)
1272 lphl->hFont = GetStockObject(SYSTEM_FONT);
1273 else
1274 lphl->hFont = (HFONT) wParam;
1276 /* a new font means possible new text height */
1277 /* does this mean the height of each entry must be separately changed? */
1278 /* or are we guaranteed to get a LBSetFont before the first insert/add? */
1279 if ((hdc = GetDC(0)))
1281 TEXTMETRIC tm;
1282 GetTextMetrics( hdc, &tm );
1283 lphl->StdItemHeight = tm.tmHeight;
1284 dprintf_listbox(stddeb,"LBSetFont: new font %d with height %d",
1285 lphl->hFont, lphl->StdItemHeight);
1286 ReleaseDC( 0, hdc );
1289 return 0;
1292 /***********************************************************************
1293 * LBPaint
1295 static LONG LBPaint(HWND hwnd, WORD wParam, LONG lParam)
1297 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1298 LPLISTSTRUCT lpls;
1299 PAINTSTRUCT ps;
1300 HBRUSH hBrush;
1301 HFONT hOldFont;
1302 HDC hdc = BeginPaint( hwnd, &ps );
1303 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
1304 RECT rect, paintRect, scratchRect;
1305 int i, top, height, maxwidth, ipc;
1308 top = 0;
1310 if (!IsWindowVisible(hwnd) || !lphl->bRedrawFlag) {
1311 EndPaint(hwnd, &ps);
1312 return 0;
1315 GetRgnBox(dc->w.hGCClipRgn,&paintRect);
1316 GetClientRect(hwnd, &rect);
1317 IntersectRect(&paintRect,&rect,&paintRect);
1319 hOldFont = SelectObject(hdc, lphl->hFont);
1321 #ifdef WINELIB32
1322 hBrush = (HBRUSH) SendMessage(lphl->hParent, WM_CTLCOLORLISTBOX, (WPARAM)hdc,
1323 (LPARAM)hwnd);
1324 #else
1325 hBrush = SendMessage(lphl->hParent, WM_CTLCOLOR, hdc,
1326 MAKELONG(hwnd, CTLCOLOR_LISTBOX));
1327 #endif
1329 if (hBrush == 0) hBrush = GetStockObject(WHITE_BRUSH);
1331 FillRect(hdc, &rect, hBrush);
1333 maxwidth = rect.right;
1334 if (lphl->dwStyle & LBS_MULTICOLUMN) {
1335 rect.right = lphl->ColumnsWidth;
1337 lpls = lphl->lpFirst;
1339 lphl->ItemsVisible = 0;
1340 lphl->ItemsPerColumn = ipc = 0;
1342 for(i = 0; i < lphl->ItemsCount; i++) {
1343 if (lpls == NULL) break;
1345 if (i >= lphl->FirstVisible) {
1346 height = lpls->mis.itemHeight;
1348 if (top > rect.bottom) {
1349 if (lphl->dwStyle & LBS_MULTICOLUMN) {
1350 lphl->ItemsPerColumn = MAX(lphl->ItemsPerColumn, ipc);
1351 ipc = 0;
1352 top = 0;
1353 rect.left += lphl->ColumnsWidth;
1354 rect.right += lphl->ColumnsWidth;
1355 if (rect.left > maxwidth) break;
1356 } else {
1357 break;
1361 lpls->itemRect.top = top;
1362 lpls->itemRect.bottom = top + height;
1363 lpls->itemRect.left = rect.left;
1364 lpls->itemRect.right = rect.right;
1366 if( IntersectRect(&scratchRect,&paintRect,&lpls->itemRect) )
1368 dprintf_listbox(stddeb,"LBPaint: drawing item: %ld %d %ld %d %d\n",(LONG)rect.left,top,
1369 (LONG)rect.right,top+height,lpls->itemState);
1371 if (lphl->OwnerDrawn && (lphl->ItemFocused == i) && GetFocus() == hwnd)
1373 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS,
1374 lpls->itemState & ~ODS_FOCUS);
1375 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
1376 lpls->itemState & ~ODS_FOCUS);
1377 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS, lpls->itemState);
1379 else
1380 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
1381 lpls->itemState);
1384 top += height;
1385 lphl->ItemsVisible++;
1386 ipc++;
1389 lpls = lpls->lpNext;
1391 ListBoxUpdateWindow(hwnd,lphl,FALSE);
1392 SelectObject(hdc,hOldFont);
1393 EndPaint( hwnd, &ps );
1394 return 0;
1397 /***********************************************************************
1398 * LBSetFocus
1400 static LONG LBSetFocus(HWND hwnd, WORD wParam, LONG lParam)
1402 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1404 dprintf_listbox(stddeb,"ListBox WM_SETFOCUS for "NPFMT"\n",hwnd);
1405 if(!(lphl->dwStyle & LBS_MULTIPLESEL) )
1406 if( lphl->ItemsCount && lphl->ItemFocused != -1)
1408 HDC hDC = GetDC(hwnd);
1409 HFONT hOldFont = SelectObject(hDC, lphl->hFont);
1410 LPLISTSTRUCT lpls;
1412 lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
1413 lpls->itemState |= ODS_FOCUS;
1415 ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
1416 SelectObject(hDC, hOldFont);
1417 ReleaseDC(hwnd,hDC);
1420 ListBoxSendNotification(lphl, LBN_SETFOCUS);
1422 return 0;
1425 /***********************************************************************
1426 * LBKillFocus
1428 static LONG LBKillFocus(HWND hwnd, WORD wParam, LONG lParam)
1430 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1432 dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS for "NPFMT"\n",hwnd);
1433 if (!(lphl->dwStyle & LBS_MULTIPLESEL))
1435 if( lphl->ItemsCount )
1436 if( lphl->ItemFocused != -1 )
1438 HDC hDC = GetDC(hwnd);
1439 HFONT hOldFont = SelectObject(hDC, lphl->hFont);
1440 LPLISTSTRUCT lpls;
1442 lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
1443 lpls->itemState &= ~ODS_FOCUS;
1445 ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
1446 SelectObject(hDC, hOldFont);
1447 ReleaseDC(hwnd,hDC);
1449 else
1450 dprintf_listbox(stddeb,"LBKillFocus: no focused item!\n");
1452 else
1453 InvalidateRect(hwnd, NULL, TRUE);
1455 ListBoxSendNotification(lphl, LBN_KILLFOCUS);
1457 return 0;
1460 /***********************************************************************
1461 * LBResetContent
1463 static LONG LBResetContent(HWND hwnd, WORD wParam, LONG lParam)
1465 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1467 dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
1468 ListBoxResetContent(lphl);
1469 ListBoxUpdateWindow(hwnd, lphl, TRUE);
1470 return 0;
1473 /***********************************************************************
1474 * LBDir
1476 static LONG LBDir(HWND hwnd, WORD wParam, LONG lParam)
1478 LONG ret;
1479 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1480 dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
1482 ret = ListBoxDirectory(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
1483 ListBoxUpdateWindow(hwnd, lphl, TRUE);
1484 return ret;
1487 /***********************************************************************
1488 * LBAddString
1490 static LONG LBAddString(HWND hwnd, WORD wParam, LONG lParam)
1492 WORD wRet;
1493 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1495 if (lphl->HasStrings)
1496 wRet = ListBoxAddString(lphl, (LPCSTR)PTR_SEG_TO_LIN(lParam));
1497 else
1498 wRet = ListBoxAddString(lphl, (LPCSTR)lParam);
1500 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1501 return wRet;
1504 /***********************************************************************
1505 * LBGetText
1507 static LONG LBGetText(HWND hwnd, WORD wParam, LONG lParam)
1509 LONG wRet;
1510 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1512 dprintf_listbox(stddeb, "LB_GETTEXT wParam=%d\n",wParam);
1513 wRet = ListBoxGetText(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
1515 return wRet;
1518 /***********************************************************************
1519 * LBInsertString
1521 static LONG LBInsertString(HWND hwnd, WORD wParam, LONG lParam)
1523 WORD wRet;
1524 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1526 if (lphl->HasStrings)
1527 wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)PTR_SEG_TO_LIN(lParam));
1528 else
1529 wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)lParam);
1531 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1532 return wRet;
1535 /***********************************************************************
1536 * LBDeleteString
1538 static LONG LBDeleteString(HWND hwnd, WORD wParam, LONG lParam)
1540 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1541 LONG lRet = ListBoxDeleteString(lphl,wParam);
1543 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1544 return lRet;
1547 /***********************************************************************
1548 * LBFindString
1550 static LONG LBFindString(HWND hwnd, WORD wParam, LONG lParam)
1552 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1553 return ListBoxFindString(lphl, wParam, (SEGPTR)lParam);
1556 /***********************************************************************
1557 * LBGetCaretIndex
1559 static LONG LBGetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
1561 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1562 return lphl->ItemFocused;
1565 /***********************************************************************
1566 * LBGetCount
1568 static LONG LBGetCount(HWND hwnd, WORD wParam, LONG lParam)
1570 LPHEADLIST lphl;
1572 lphl = ListBoxGetStorageHeader(hwnd);
1573 return lphl->ItemsCount;
1576 /***********************************************************************
1577 * LBGetCurSel
1579 static LONG LBGetCurSel(HWND hwnd, WORD wParam, LONG lParam)
1581 LPHEADLIST lphl;
1583 lphl = ListBoxGetStorageHeader(hwnd);
1584 dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %i !\n",
1585 lphl->ItemFocused);
1586 return lphl->ItemFocused;
1589 /***********************************************************************
1590 * LBGetHorizontalExtent
1592 static LONG LBGetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
1594 return 0;
1597 /***********************************************************************
1598 * LBGetItemHeight
1600 static LONG LBGetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
1602 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1603 LPLISTSTRUCT lpls = ListBoxGetItem (lphl, wParam);
1605 if (lpls == NULL) return LB_ERR;
1606 return lpls->mis.itemHeight;
1609 /***********************************************************************
1610 * LBGetItemRect
1612 static LONG LBGetItemRect(HWND hwnd, WORD wParam, LONG lParam)
1614 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1615 return ListBoxGetItemRect(lphl, wParam, PTR_SEG_TO_LIN(lParam));
1618 /***********************************************************************
1619 * LBGetSel
1621 static LONG LBGetSel(HWND hwnd, WORD wParam, LONG lParam)
1623 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1624 int iSel = ListBoxGetSel(lphl, wParam);
1626 dprintf_listbox(stdnimp,"LBGetSel: item %u - %i\n",wParam,iSel);
1628 return (iSel)? 1 : 0;
1631 /***********************************************************************
1632 * LBGetSelCount
1634 static LONG LBGetSelCount(HWND hwnd, WORD wParam, LONG lParam)
1636 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1637 LPLISTSTRUCT lpls;
1638 int cnt = 0;
1639 int items = 0;
1641 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1642 return LB_ERR;
1644 for( lpls = lphl->lpFirst;
1645 lpls;
1646 lpls = lpls->lpNext )
1648 items++;
1649 if (lpls->itemState )
1650 cnt++;
1653 return cnt;
1656 /***********************************************************************
1657 * LBGetSelItems
1659 static LONG LBGetSelItems(HWND hwnd, WORD wParam, LONG lParam)
1661 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1662 LPLISTSTRUCT lpls;
1663 int cnt, idx;
1664 int *lpItems = PTR_SEG_TO_LIN(lParam);
1666 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1667 return LB_ERR;
1669 if (wParam == 0) return 0;
1671 lpls = lphl->lpFirst;
1672 cnt = 0; idx = 0;
1674 while (lpls != NULL) {
1675 if (lpls->itemState > 0) lpItems[cnt++] = idx;
1677 if (cnt == wParam) break;
1678 idx++;
1679 lpls = lpls->lpNext;
1682 return cnt;
1685 /***********************************************************************
1686 * LBGetTextLen
1688 static LONG LBGetTextLen(HWND hwnd, WORD wParam, LONG lParam)
1690 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1691 LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wParam);
1693 if (lpls == NULL || !lphl->HasStrings) return LB_ERR;
1694 return strlen(lpls->itemText);
1697 /***********************************************************************
1698 * LBGetDlgCode
1700 static LONG LBGetDlgCode(HWND hwnd, WORD wParam, LONG lParam)
1702 return DLGC_WANTARROWS | DLGC_WANTCHARS;
1705 /***********************************************************************
1706 * LBGetTopIndex
1708 static LONG LBGetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
1710 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1712 return lphl->FirstVisible;
1716 /***********************************************************************
1717 * LBSelectString
1719 static LONG LBSelectString(HWND hwnd, WORD wParam, LONG lParam)
1721 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1722 INT iRet;
1724 iRet = ListBoxFindString(lphl, wParam, (SEGPTR)lParam);
1726 if( iRet != LB_ERR)
1728 if( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )
1729 ListBoxSetSel(lphl,iRet,TRUE);
1730 else
1731 ListBoxSetCurSel(lphl,iRet);
1733 lphl->ItemFocused = iRet;
1734 InvalidateRect(hwnd,0,TRUE);
1736 return iRet;
1739 /***********************************************************************
1740 * LBSelItemRange
1742 static LONG LBSelItemRange(HWND hwnd, WORD wParam, LONG lParam)
1744 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1745 LPLISTSTRUCT lpls;
1746 WORD cnt;
1747 WORD first = LOWORD(lParam);
1748 WORD last = HIWORD(lParam);
1749 BOOL select = wParam;
1751 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1752 return LB_ERR;
1754 if (first >= lphl->ItemsCount ||
1755 last >= lphl->ItemsCount) return LB_ERR;
1757 lpls = lphl->lpFirst;
1758 cnt = 0;
1760 while (lpls != NULL) {
1761 if (cnt++ >= first)
1762 lpls->itemState = select ? lpls->itemState | ODS_SELECTED : 0;
1764 if (cnt > last)
1765 break;
1767 lpls = lpls->lpNext;
1770 return 0;
1773 /***********************************************************************
1774 * LBSetCaretIndex
1776 static LONG LBSetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
1778 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1779 int i;
1781 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )) return 0;
1783 dprintf_listbox(stddeb,"LBSetCaretIndex: hwnd "NPFMT" n=%i\n",hwnd,wParam);
1785 if (wParam >= lphl->ItemsCount) return LB_ERR;
1787 lphl->ItemFocused = wParam;
1788 i = ListBoxScrollToFocus (lphl);
1790 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1791 if(i)
1792 InvalidateRect(hwnd, NULL, TRUE);
1794 return 1;
1797 /***********************************************************************
1798 * LBSetColumnWidth
1800 static LONG LBSetColumnWidth(HWND hwnd, WORD wParam, LONG lParam)
1802 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1803 lphl->ColumnsWidth = wParam;
1804 InvalidateRect(hwnd,NULL,TRUE);
1805 return 0;
1808 /***********************************************************************
1809 * LBSetHorizontalExtent
1811 static LONG LBSetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
1813 return 0;
1816 /***********************************************************************
1817 * LBGetItemData
1819 static LONG LBGetItemData(HWND hwnd, WORD wParam, LONG lParam)
1821 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1822 dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
1823 return ListBoxGetItemData(lphl, wParam);
1826 /***********************************************************************
1827 * LBSetItemData
1829 static LONG LBSetItemData(HWND hwnd, WORD wParam, LONG lParam)
1831 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1832 dprintf_listbox(stddeb, "LB_SETITEMDATA wParam=%x lParam=%lx\n", wParam, lParam);
1833 return ListBoxSetItemData(lphl, wParam, lParam);
1836 /***********************************************************************
1837 * LBSetTabStops
1839 static LONG LBSetTabStops(HWND hwnd, WORD wParam, LONG lParam)
1841 LPHEADLIST lphl;
1843 lphl = ListBoxGetStorageHeader(hwnd);
1845 if (lphl->TabStops != NULL) {
1846 lphl->iNumStops = 0;
1847 free (lphl->TabStops);
1850 lphl->TabStops = malloc (wParam * sizeof (short));
1851 if (lphl->TabStops) {
1852 lphl->iNumStops = wParam;
1853 memcpy (lphl->TabStops, PTR_SEG_TO_LIN(lParam), wParam * sizeof (short));
1854 return TRUE;
1857 return FALSE;
1860 /***********************************************************************
1861 * LBSetCurSel
1863 static LONG LBSetCurSel(HWND hwnd, WORD wParam, LONG lParam)
1865 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1866 WORD wRet;
1868 dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n",
1869 wParam);
1871 wRet = ListBoxSetCurSel(lphl, wParam);
1873 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1874 InvalidateRect(hwnd, NULL, TRUE);
1876 return wRet;
1879 /***********************************************************************
1880 * LBSetSel
1882 static LONG LBSetSel(HWND hwnd, WORD wParam, LONG lParam)
1884 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1885 RECT rect;
1886 int iRet;
1888 dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
1890 iRet = ListBoxSetSel(lphl, LOWORD(lParam), wParam);
1892 if( iRet > 1 )
1893 InvalidateRect(hwnd, NULL, TRUE);
1894 else if( iRet != LB_ERR )
1896 if( lphl->dwStyle & LBS_EXTENDEDSEL &&
1897 lphl->ItemFocused != LOWORD(lParam) )
1899 ListBoxGetItemRect(lphl, lphl->ItemFocused , &rect);
1900 InvalidateRect(hwnd,&rect,TRUE);
1901 lphl->ItemFocused = LOWORD(lParam);
1903 ListBoxGetItemRect(lphl,LOWORD(lParam),&rect);
1904 InvalidateRect(hwnd,&rect,TRUE);
1907 return (iRet == (WORD)LB_ERR)? LB_ERR: 0;
1910 /***********************************************************************
1911 * LBSetTopIndex
1913 static LONG LBSetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
1915 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1917 dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
1918 wParam);
1919 lphl->FirstVisible = wParam;
1920 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1922 InvalidateRect(hwnd, NULL, TRUE);
1924 return 0;
1927 /***********************************************************************
1928 * LBSetItemHeight
1930 static LONG LBSetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
1932 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1933 WORD wRet;
1935 dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
1936 wRet = ListBoxSetItemHeight(lphl, wParam, lParam);
1937 InvalidateRect(hwnd,NULL,TRUE);
1938 return wRet;
1941 /***********************************************************************
1942 * LBPassToParent
1944 static LRESULT LBPassToParent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1946 WND* ptrWnd = WIN_FindWndPtr(hwnd);
1948 if( ptrWnd )
1949 if( /* !(ptrWnd->dwExStyle & WS_EX_NOPARENTNOTIFY) && */
1950 ptrWnd->hwndParent )
1951 return SendMessage(ptrWnd->hwndParent,message,wParam,lParam);
1952 return 0;
1955 /***********************************************************************
1956 * ListBoxWndProc
1958 LRESULT ListBoxWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1960 switch (message) {
1961 case WM_CREATE: return LBCreate(hwnd, wParam, lParam);
1962 case WM_DESTROY: return LBDestroy(hwnd, wParam, lParam);
1963 case WM_GETDLGCODE: return LBGetDlgCode(hwnd, wParam, lParam);
1964 case WM_VSCROLL: return LBVScroll(hwnd, wParam, lParam);
1965 case WM_HSCROLL: return LBHScroll(hwnd, wParam, lParam);
1966 case WM_LBUTTONDOWN: return LBLButtonDown(hwnd, wParam, lParam);
1967 case WM_LBUTTONUP: return LBLButtonUp(hwnd, wParam, lParam);
1968 case WM_RBUTTONUP: return LBRButtonUp(hwnd, wParam, lParam);
1969 case WM_LBUTTONDBLCLK: return LBRButtonUp(hwnd, wParam, lParam);
1970 case WM_MOUSEMOVE: return LBMouseMove(hwnd, wParam, lParam);
1971 case WM_KEYDOWN: return LBKeyDown(hwnd, wParam, lParam);
1972 case WM_CHAR: return LBChar(hwnd, wParam, lParam);
1973 case WM_SETFONT: return LBSetFont(hwnd, wParam, lParam);
1974 case WM_SETREDRAW: return LBSetRedraw(hwnd, wParam, lParam);
1975 case WM_PAINT: return LBPaint(hwnd, wParam, lParam);
1976 case WM_SETFOCUS: return LBSetFocus(hwnd, wParam, lParam);
1977 case WM_KILLFOCUS: return LBKillFocus(hwnd, wParam, lParam);
1978 case LB_RESETCONTENT: return LBResetContent(hwnd, wParam, lParam);
1979 case LB_DIR: return LBDir(hwnd, wParam, lParam);
1980 case LB_ADDSTRING: return LBAddString(hwnd, wParam, lParam);
1981 case LB_INSERTSTRING: return LBInsertString(hwnd, wParam, lParam);
1982 case LB_DELETESTRING: return LBDeleteString(hwnd, wParam, lParam);
1983 case LB_FINDSTRING: return LBFindString(hwnd, wParam, lParam);
1984 case LB_GETCARETINDEX: return LBGetCaretIndex(hwnd, wParam, lParam);
1985 case LB_GETCOUNT: return LBGetCount(hwnd, wParam, lParam);
1986 case LB_GETCURSEL: return LBGetCurSel(hwnd, wParam, lParam);
1987 case LB_GETHORIZONTALEXTENT: return LBGetHorizontalExtent(hwnd, wParam, lParam);
1988 case LB_GETITEMDATA: return LBGetItemData(hwnd, wParam, lParam);
1989 case LB_GETITEMHEIGHT: return LBGetItemHeight(hwnd, wParam, lParam);
1990 case LB_GETITEMRECT: return LBGetItemRect(hwnd, wParam, lParam);
1991 case LB_GETSEL: return LBGetSel(hwnd, wParam, lParam);
1992 case LB_GETSELCOUNT: return LBGetSelCount(hwnd, wParam, lParam);
1993 case LB_GETSELITEMS: return LBGetSelItems(hwnd, wParam, lParam);
1994 case LB_GETTEXT: return LBGetText(hwnd, wParam, lParam);
1995 case LB_GETTEXTLEN: return LBGetTextLen(hwnd, wParam, lParam);
1996 case LB_GETTOPINDEX: return LBGetTopIndex(hwnd, wParam, lParam);
1997 case LB_SELECTSTRING: return LBSelectString(hwnd, wParam, lParam);
1998 case LB_SELITEMRANGE: return LBSelItemRange(hwnd, wParam, lParam);
1999 case LB_SETCARETINDEX: return LBSetCaretIndex(hwnd, wParam, lParam);
2000 case LB_SETCOLUMNWIDTH: return LBSetColumnWidth(hwnd, wParam, lParam);
2001 case LB_SETHORIZONTALEXTENT: return LBSetHorizontalExtent(hwnd, wParam, lParam);
2002 case LB_SETITEMDATA: return LBSetItemData(hwnd, wParam, lParam);
2003 case LB_SETTABSTOPS: return LBSetTabStops(hwnd, wParam, lParam);
2004 case LB_SETCURSEL: return LBSetCurSel(hwnd, wParam, lParam);
2005 case LB_SETSEL: return LBSetSel(hwnd, wParam, lParam);
2006 case LB_SETTOPINDEX: return LBSetTopIndex(hwnd, wParam, lParam);
2007 case LB_SETITEMHEIGHT: return LBSetItemHeight(hwnd, wParam, lParam);
2009 case WM_DROPFILES: return LBPassToParent(hwnd, message, wParam, lParam);
2011 /* these will have to be implemented for proper LBS_EXTENDEDSEL -
2013 * anchor item is an item that with caret (focused) item defines a
2014 * range of currently selected items when listbox is in the extended
2015 * selection mode.
2017 case LB_SETANCHORINDEX: return LB_SETANCHORINDEX; /* that's what Windows returns */
2018 case LB_GETANCHORINDEX: return 0;
2020 case WM_DROPOBJECT:
2021 case WM_QUERYDROPOBJECT:
2022 case WM_DRAGSELECT:
2023 case WM_DRAGMOVE:
2025 LPDRAGINFO lpDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN((SEGPTR)lParam);
2026 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
2028 lpDragInfo->l = ListBoxFindMouse(lphl,lpDragInfo->pt.x,
2029 lpDragInfo->pt.y);
2031 return LBPassToParent(hwnd, message, wParam, lParam);
2035 return DefWindowProc(hwnd, message, wParam, lParam);
2039 /**********************************************************************
2040 * DlgDirSelect (USER.99)
2042 BOOL DlgDirSelect( HWND hDlg, LPSTR lpStr, INT id )
2044 char buffer[20];
2045 INT i;
2047 dprintf_listbox( stddeb, "DlgDirSelect: "NPFMT" '%s' %d\n",
2048 hDlg, lpStr, id );
2049 if ((i = SendDlgItemMessage( hDlg, id, LB_GETCURSEL, 0, 0 )) == LB_ERR)
2050 return FALSE;
2051 SendDlgItemMessage( hDlg, id, LB_GETTEXT, i, MAKE_SEGPTR(buffer) );
2052 if (buffer[0] == '[') /* drive or directory */
2054 if (buffer[1] == '-') /* drive */
2056 lpStr[0] = buffer[2];
2057 lpStr[1] = ':';
2058 lpStr[2] = '\0';
2059 dprintf_listbox( stddeb, "Returning drive '%s'\n", lpStr );
2060 return TRUE;
2062 strcpy( lpStr, buffer + 1 );
2063 lpStr[strlen(lpStr)-1] = '\\';
2064 dprintf_listbox( stddeb, "Returning directory '%s'\n", lpStr );
2065 return TRUE;
2067 strcpy( lpStr, buffer );
2068 dprintf_listbox( stddeb, "Returning file '%s'\n", lpStr );
2069 return FALSE;
2073 /**********************************************************************
2074 * DlgDirList (USER.100)
2076 INT DlgDirList( HWND hDlg, SEGPTR spec, INT idLBox, INT idStatic, UINT attrib )
2078 char *filespec = (char *)PTR_SEG_TO_LIN( spec );
2079 int drive;
2080 HWND hwnd;
2082 #define SENDMSG(msg,wparam,lparam) \
2083 ((attrib & DDL_POSTMSGS) ? PostMessage( hwnd, msg, wparam, lparam ) \
2084 : SendMessage( hwnd, msg, wparam, lparam ))
2086 dprintf_listbox( stddeb, "DlgDirList: "NPFMT" '%s' %d %d %04x\n",
2087 hDlg, filespec ? filespec : "NULL",
2088 idLBox, idStatic, attrib );
2090 if (filespec && filespec[0] && (filespec[1] == ':'))
2092 drive = toupper( filespec[0] ) - 'A';
2093 filespec += 2;
2094 if (!DRIVE_SetCurrentDrive( drive )) return FALSE;
2096 else drive = DRIVE_GetCurrentDrive();
2098 if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
2100 char mask[20];
2101 char temp[] = "*.*";
2103 if (!filespec[0]) strcpy( mask, "*.*" );
2104 else
2106 /* If the path exists and is a directory, chdir to it */
2107 if (DRIVE_Chdir( drive, filespec )) strcpy( mask, "*.*" );
2108 else
2110 char *p, *p2;
2111 p = filespec;
2112 if ((p2 = strrchr( p, '\\' ))) p = p2 + 1;
2113 if ((p2 = strrchr( p, '/' ))) p = p2 + 1;
2114 lstrcpyn( mask, p, sizeof(mask) );
2115 if (p != filespec)
2117 p[-1] = '\0';
2118 if (!DRIVE_Chdir( drive, filespec )) return FALSE;
2123 strcpy( (char *)PTR_SEG_TO_LIN(spec), mask );
2125 dprintf_listbox(stddeb, "ListBoxDirectory: path=%c:\\%s mask=%s\n",
2126 'A' + drive, DRIVE_GetDosCwd(drive), mask);
2128 SENDMSG( LB_RESETCONTENT, 0, 0 );
2129 if ((attrib & DDL_DIRECTORY) && !(attrib & DDL_EXCLUSIVE))
2131 if (SENDMSG( LB_DIR, attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
2132 (LPARAM)spec ) == LB_ERR) return FALSE;
2133 if (SENDMSG( LB_DIR, (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
2134 (LPARAM)MAKE_SEGPTR(temp) ) == LB_ERR) return FALSE;
2136 else
2138 if (SENDMSG( LB_DIR, attrib, (LPARAM)spec) == LB_ERR) return FALSE;
2142 if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
2144 char temp[256];
2145 strcpy( temp, "A:\\" );
2146 temp[0] += drive;
2147 lstrcpyn( temp+3, DRIVE_GetDosCwd(drive), 253 );
2148 AnsiLower( temp );
2149 SENDMSG( WM_SETTEXT, 0, (LPARAM)MAKE_SEGPTR(temp) );
2151 return TRUE;
2152 #undef SENDMSG