Release 960506
[wine/multimedia.git] / controls / listbox.c
blobb6d31c05f02110ce4bc41bb0b2bd3e83a0c95a7f
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 #define LBMM_EDGE 4 /* distance inside box which is same as moving mouse
67 outside box, to trigger scrolling of LB */
69 static void ListBoxInitialize(LPHEADLIST lphl)
71 lphl->lpFirst = NULL;
72 lphl->ItemsCount = 0;
73 lphl->ItemsVisible = 0;
74 lphl->FirstVisible = 0;
75 lphl->ColumnsVisible = 1;
76 lphl->ItemsPerColumn = 0;
77 lphl->ItemFocused = -1;
78 lphl->PrevFocused = -1;
81 void CreateListBoxStruct(HWND hwnd, WORD CtlType, LONG styles, HWND parent)
83 LPHEADLIST lphl;
84 HDC hdc;
86 lphl = (LPHEADLIST)xmalloc(sizeof(HEADLIST));
87 SetWindowLong(hwnd, 0, (LONG)lphl);
88 ListBoxInitialize(lphl);
89 lphl->DrawCtlType = CtlType;
90 lphl->CtlID = GetWindowWord(hwnd,GWW_ID);
91 lphl->bRedrawFlag = TRUE;
92 lphl->iNumStops = 0;
93 lphl->TabStops = NULL;
94 lphl->hFont = GetStockObject(SYSTEM_FONT);
95 lphl->hSelf = hwnd;
96 if (CtlType==ODT_COMBOBOX) /* use the "faked" style for COMBOLBOX */
97 /* LBS_SORT instead CBS_SORT e.g. */
98 lphl->dwStyle = MAKELONG(LOWORD(styles),HIWORD(GetWindowLong(hwnd,GWL_STYLE)));
99 else
100 lphl->dwStyle = GetWindowLong(hwnd,GWL_STYLE); /* use original style dword */
101 lphl->hParent = parent;
102 lphl->StdItemHeight = 15; /* FIXME: should get the font height */
103 lphl->OwnerDrawn = styles & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE);
104 lphl->HasStrings = (styles & LBS_HASSTRINGS) || !lphl->OwnerDrawn;
106 /* create dummy hdc to set text height */
107 if ((hdc = GetDC(0)))
109 TEXTMETRIC tm;
110 GetTextMetrics( hdc, &tm );
111 lphl->StdItemHeight = tm.tmHeight;
112 dprintf_listbox(stddeb,"CreateListBoxStruct: font height %d\n",
113 lphl->StdItemHeight);
114 ReleaseDC( 0, hdc );
117 if (lphl->OwnerDrawn) {
118 LISTSTRUCT dummyls;
120 lphl->hDrawItemStruct = USER_HEAP_ALLOC(sizeof(DRAWITEMSTRUCT));
121 lphl->needMeasure = TRUE;
122 dummyls.mis.CtlType = lphl->DrawCtlType;
123 dummyls.mis.CtlID = lphl->CtlID;
124 dummyls.mis.itemID = -1;
125 dummyls.mis.itemWidth = 0; /* ignored */
126 dummyls.mis.itemData = 0;
128 ListBoxAskMeasure(lphl,&dummyls);
129 } else {
130 lphl->hDrawItemStruct = 0;
133 /* WINELIBS list boxes do not operate on local heaps */
134 #ifndef WINELIB
135 lphl->HeapSel = GlobalAlloc16(GMEM_FIXED,LIST_HEAP_SIZE);
136 LocalInit( lphl->HeapSel, 0, LIST_HEAP_SIZE-1);
137 #else
138 lphl->HeapSel = 0;
139 #endif
142 void DestroyListBoxStruct(LPHEADLIST lphl)
144 if (lphl->hDrawItemStruct)
145 USER_HEAP_FREE(lphl->hDrawItemStruct);
147 /* XXX need to free lphl->Heap */
148 GlobalFree16(lphl->HeapSel);
149 free(lphl);
152 static LPHEADLIST ListBoxGetStorageHeader(HWND hwnd)
154 return (LPHEADLIST)GetWindowLong(hwnd,0);
157 /* Send notification "code" as part of a WM_COMMAND-message if hwnd
158 has the LBS_NOTIFY style */
159 void ListBoxSendNotification(LPHEADLIST lphl, WORD code)
161 if (lphl->dwStyle & LBS_NOTIFY)
162 #ifdef WINELIB32
163 SendMessage(lphl->hParent, WM_COMMAND,
164 MAKEWPARAM(lphl->CtlID,code), (LPARAM)lphl->hSelf);
165 #else
166 SendMessage(lphl->hParent, WM_COMMAND,
167 lphl->CtlID, MAKELONG(lphl->hSelf, code));
168 #endif
172 /* get the maximum value of lphl->FirstVisible */
173 int ListMaxFirstVisible(LPHEADLIST lphl)
175 int m = lphl->ItemsCount-lphl->ItemsVisible;
176 return (m < 0) ? 0 : m;
180 void ListBoxUpdateWindow(HWND hwnd, LPHEADLIST lphl, BOOL repaint)
182 WND *wndPtr = WIN_FindWndPtr(hwnd);
184 if (wndPtr->dwStyle & WS_VSCROLL)
185 SetScrollRange(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
186 if ((wndPtr->dwStyle & WS_HSCROLL) && (lphl->ItemsPerColumn != 0))
187 SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
188 lphl->ItemsPerColumn + 1, TRUE);
190 if (repaint && lphl->bRedrawFlag) {
191 InvalidateRect(hwnd, NULL, TRUE);
195 /* Returns: 0 if nothing needs to be changed */
196 /* 1 if FirstVisible changed */
198 int ListBoxScrollToFocus(LPHEADLIST lphl)
200 short end;
202 if (lphl->ItemsCount == 0) return 0;
203 if (lphl->ItemFocused == -1) return 0;
205 end = lphl->FirstVisible + lphl->ItemsVisible - 1;
207 if (lphl->ItemFocused < lphl->FirstVisible ) {
208 lphl->FirstVisible = lphl->ItemFocused;
209 return 1;
210 } else {
211 if (lphl->ItemFocused > end) {
212 WORD maxFirstVisible = ListMaxFirstVisible(lphl);
214 lphl->FirstVisible = lphl->ItemFocused;
216 if (lphl->FirstVisible > maxFirstVisible) {
217 lphl->FirstVisible = maxFirstVisible;
219 return 1;
222 return 0;
226 LPLISTSTRUCT ListBoxGetItem(LPHEADLIST lphl, UINT uIndex)
228 LPLISTSTRUCT lpls;
229 UINT Count = 0;
231 if (uIndex >= lphl->ItemsCount) return NULL;
233 lpls = lphl->lpFirst;
234 while (Count++ < uIndex) lpls = lpls->lpNext;
235 return lpls;
239 void ListBoxDrawItem (HWND hwnd, LPHEADLIST lphl, HDC hdc, LPLISTSTRUCT lpls,
240 RECT *rect, WORD itemAction, WORD itemState)
242 if (lphl->OwnerDrawn) {
243 DRAWITEMSTRUCT *dis = USER_HEAP_LIN_ADDR(lphl->hDrawItemStruct);
245 dis->CtlID = lpls->mis.CtlID;
246 dis->CtlType = lpls->mis.CtlType;
247 dis->itemID = lpls->mis.itemID;
248 dis->hDC = hdc;
249 dis->hwndItem = hwnd;
250 dis->itemData = lpls->mis.itemData;
251 dis->itemAction = itemAction;
252 dis->itemState = itemState;
253 dis->rcItem = *rect;
254 SendMessage(lphl->hParent, WM_DRAWITEM,
255 0, (LPARAM)USER_HEAP_SEG_ADDR(lphl->hDrawItemStruct));
256 } else {
257 if (itemAction == ODA_DRAWENTIRE || itemAction == ODA_SELECT) {
258 int OldBkMode;
259 DWORD dwOldTextColor = 0;
261 OldBkMode = SetBkMode(hdc, TRANSPARENT);
263 if (itemState != 0) {
264 dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
265 FillRect(hdc, rect, GetStockObject(BLACK_BRUSH));
268 if (lphl->dwStyle & LBS_USETABSTOPS) {
269 TabbedTextOut(hdc, rect->left + 5, rect->top + 2,
270 (char *)lpls->itemText, strlen((char *)lpls->itemText),
271 lphl->iNumStops, lphl->TabStops, 0);
272 } else {
273 TextOut(hdc, rect->left + 5, rect->top + 2,
274 (char *)lpls->itemText, strlen((char *)lpls->itemText));
277 if (itemState != 0) {
278 SetTextColor(hdc, dwOldTextColor);
281 SetBkMode(hdc, OldBkMode);
282 } else DrawFocusRect(hdc, rect);
285 return;
289 int ListBoxFindMouse(LPHEADLIST lphl, int X, int Y)
291 LPLISTSTRUCT lpls = lphl->lpFirst;
292 int i, j;
293 POINT point;
295 point.x = X; point.y = Y;
296 if (lphl->ItemsCount == 0) return LB_ERR;
298 for(i = 0; i < lphl->FirstVisible; i++) {
299 if (lpls == NULL) return LB_ERR;
300 lpls = lpls->lpNext;
302 for(j = 0; j < lphl->ItemsVisible; i++, j++) {
303 if (lpls == NULL) return LB_ERR;
304 if (PtInRect(&lpls->itemRect,point)) {
305 return i;
307 lpls = lpls->lpNext;
309 dprintf_listbox(stddeb,"ListBoxFindMouse: not found\n");
310 return LB_ERR;
314 void ListBoxAskMeasure(LPHEADLIST lphl, LPLISTSTRUCT lpls)
316 HANDLE hTemp = USER_HEAP_ALLOC( sizeof(MEASUREITEMSTRUCT) );
317 MEASUREITEMSTRUCT *lpmeasure = (MEASUREITEMSTRUCT *) USER_HEAP_LIN_ADDR(hTemp);
319 if (lpmeasure == NULL) {
320 fprintf(stdnimp,"ListBoxAskMeasure() out of memory !\n");
321 return;
324 *lpmeasure = lpls->mis;
325 lpmeasure->itemHeight = lphl->StdItemHeight;
326 SendMessage(lphl->hParent, WM_MEASUREITEM, 0, (LPARAM)USER_HEAP_SEG_ADDR(hTemp));
328 if (lphl->dwStyle & LBS_OWNERDRAWFIXED) {
329 if (lpmeasure->itemHeight > lphl->StdItemHeight)
330 lphl->StdItemHeight = lpmeasure->itemHeight;
331 lpls->mis.itemHeight = lpmeasure->itemHeight;
334 USER_HEAP_FREE(hTemp);
337 /* -------------------- strings and item data ---------------------- */
339 LPLISTSTRUCT ListBoxCreateItem(LPHEADLIST lphl, int id)
341 LPLISTSTRUCT lplsnew = (LPLISTSTRUCT)malloc(sizeof(LISTSTRUCT));
343 if (lplsnew == NULL) return NULL;
345 lplsnew->itemState = 0;
346 lplsnew->mis.CtlType = lphl->DrawCtlType;
347 lplsnew->mis.CtlID = lphl->CtlID;
348 lplsnew->mis.itemID = id;
349 lplsnew->mis.itemHeight = lphl->StdItemHeight;
350 lplsnew->mis.itemWidth = 0; /* ignored */
351 lplsnew->mis.itemData = 0;
352 SetRect(&lplsnew->itemRect, 0, 0, 0, 0);
354 return lplsnew;
359 int ListBoxInsertString(LPHEADLIST lphl, UINT uIndex, LPCSTR newstr)
361 LPLISTSTRUCT *lppls, lplsnew, lpls;
362 HANDLE hStr;
363 LPSTR str;
364 UINT Count;
366 dprintf_listbox(stddeb,"ListBoxInsertString(%d, %p);\n", uIndex, newstr);
368 if (!newstr) return -1;
370 if (uIndex == (UINT)-1)
371 uIndex = lphl->ItemsCount;
373 lppls = &lphl->lpFirst;
374 for(Count = 0; Count < uIndex; Count++) {
375 if (*lppls == NULL) return LB_ERR;
376 lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
379 lplsnew = ListBoxCreateItem(lphl, Count);
381 if (lplsnew == NULL) {
382 fprintf(stdnimp,"ListBoxInsertString() out of memory !\n");
383 return LB_ERRSPACE;
386 lplsnew->lpNext = *lppls;
387 *lppls = lplsnew;
388 lphl->ItemsCount++;
390 hStr = 0;
391 if (lphl->HasStrings) {
392 dprintf_listbox(stddeb," string: %s\n", newstr);
393 hStr = LIST_HEAP_ALLOC(lphl, LMEM_MOVEABLE, strlen(newstr) + 1);
394 str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
395 if (str == NULL) return LB_ERRSPACE;
396 strcpy(str, newstr);
397 lplsnew->itemText = str;
398 /* I'm not so sure about the next one */
399 lplsnew->mis.itemData = 0;
400 } else {
401 lplsnew->itemText = NULL;
402 lplsnew->mis.itemData = (DWORD)newstr;
405 lplsnew->mis.itemID = uIndex;
406 lplsnew->hData = hStr;
408 /* adjust the itemID field of the following entries */
409 for(lpls = lplsnew->lpNext; lpls != NULL; lpls = lpls->lpNext) {
410 lpls->mis.itemID++;
413 if (lphl->needMeasure) {
414 ListBoxAskMeasure(lphl, lplsnew);
417 dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
418 return uIndex;
422 int ListBoxAddString(LPHEADLIST lphl, LPCSTR newstr)
424 UINT pos = (UINT) -1;
426 if (lphl->HasStrings && (lphl->dwStyle & LBS_SORT)) {
427 LPLISTSTRUCT lpls = lphl->lpFirst;
428 for (pos = 0; lpls != NULL; lpls = lpls->lpNext, pos++)
429 if (strcmp(lpls->itemText, newstr) >= 0)
430 break;
432 return ListBoxInsertString(lphl, pos, newstr);
436 int ListBoxGetText(LPHEADLIST lphl, UINT uIndex, LPSTR OutStr)
438 LPLISTSTRUCT lpls;
440 if (!OutStr) {
441 dprintf_listbox(stddeb, "ListBoxGetText // OutStr==NULL\n");
442 return 0;
444 *OutStr = '\0';
445 lpls = ListBoxGetItem (lphl, uIndex);
446 if (lpls == NULL) return LB_ERR;
448 if (!lphl->HasStrings) {
449 *((long *)OutStr) = lpls->mis.itemData;
450 return 4;
453 strcpy(OutStr, lpls->itemText);
454 return strlen(OutStr);
458 DWORD ListBoxGetItemData(LPHEADLIST lphl, UINT uIndex)
460 LPLISTSTRUCT lpls;
462 lpls = ListBoxGetItem (lphl, uIndex);
463 if (lpls == NULL) return LB_ERR;
464 return lpls->mis.itemData;
468 int ListBoxSetItemData(LPHEADLIST lphl, UINT uIndex, DWORD ItemData)
470 LPLISTSTRUCT lpls = ListBoxGetItem(lphl, uIndex);
472 if (lpls == NULL) return LB_ERR;
473 lpls->mis.itemData = ItemData;
474 return 1;
478 int ListBoxDeleteString(LPHEADLIST lphl, UINT uIndex)
480 LPLISTSTRUCT lpls, lpls2;
481 UINT Count;
483 if (uIndex >= lphl->ItemsCount) return LB_ERR;
485 lpls = lphl->lpFirst;
486 if (lpls == NULL) return LB_ERR;
488 if (uIndex == 0)
489 lphl->lpFirst = lpls->lpNext;
490 else {
491 LPLISTSTRUCT lpls2 = NULL;
492 for(Count = 0; Count < uIndex; Count++) {
493 if (lpls->lpNext == NULL) return LB_ERR;
495 lpls2 = lpls;
496 lpls = (LPLISTSTRUCT)lpls->lpNext;
498 lpls2->lpNext = lpls->lpNext;
501 /* adjust the itemID field of the following entries */
502 for(lpls2 = lpls->lpNext; lpls2 != NULL; lpls2 = lpls2->lpNext) {
503 lpls2->mis.itemID--;
506 lphl->ItemsCount--;
508 if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
509 free(lpls);
511 return lphl->ItemsCount;
515 int ListBoxFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr)
517 LPLISTSTRUCT lpls;
518 UINT Count;
519 UINT First = nFirst + 1;
520 LPSTR lpMatchStr = (LPSTR)MatchStr;
522 if (First > lphl->ItemsCount) return LB_ERR;
524 if (lphl->HasStrings) lpMatchStr = PTR_SEG_TO_LIN(MatchStr);
526 lpls = ListBoxGetItem(lphl, First);
527 Count = 0;
528 while(lpls != NULL) {
529 if (lphl->HasStrings) {
530 if (strstr(lpls->itemText, lpMatchStr) == lpls->itemText) return Count;
531 } else if (lphl->dwStyle & LBS_SORT) {
532 /* XXX Do a compare item */
534 else
535 if (lpls->mis.itemData == (DWORD)lpMatchStr) return Count;
537 lpls = lpls->lpNext;
538 Count++;
541 /* Start over at top */
542 Count = 0;
543 lpls = lphl->lpFirst;
545 while (Count < First) {
546 if (lphl->HasStrings) {
547 if (strstr(lpls->itemText, lpMatchStr) == lpls->itemText) return Count;
548 } else if (lphl->dwStyle & LBS_SORT) {
549 /* XXX Do a compare item */
550 } else {
551 if (lpls->mis.itemData == (DWORD)lpMatchStr) return Count;
553 lpls = lpls->lpNext;
554 Count++;
557 return LB_ERR;
561 int ListBoxResetContent(LPHEADLIST lphl)
563 LPLISTSTRUCT lpls;
564 int i;
566 if (lphl->ItemsCount == 0) return 0;
568 dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n",
569 lphl->ItemsCount);
571 for(i = 0; i < lphl->ItemsCount; i++) {
572 lpls = lphl->lpFirst;
573 if (lpls == NULL) return LB_ERR;
575 lphl->lpFirst = lpls->lpNext;
576 if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
577 free(lpls);
579 ListBoxInitialize(lphl);
581 return TRUE;
584 /* --------------------- selection ------------------------- */
586 int ListBoxSetCurSel(LPHEADLIST lphl, WORD wIndex)
588 LPLISTSTRUCT lpls;
590 /* use ListBoxSetSel instead */
591 if (lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ) return 0;
593 /* unselect previous item */
594 if (lphl->ItemFocused != -1) {
595 lphl->PrevFocused = lphl->ItemFocused;
596 lpls = ListBoxGetItem(lphl, lphl->ItemFocused);
597 if (lpls == 0) return LB_ERR;
598 lpls->itemState = 0;
601 if (wIndex != (UINT)-1) {
602 lphl->ItemFocused = wIndex;
603 lpls = ListBoxGetItem(lphl, wIndex);
604 if (lpls == 0) return LB_ERR;
605 lpls->itemState = ODS_SELECTED | ODS_FOCUS;
607 return 0;
610 return LB_ERR;
614 int ListBoxSetSel(LPHEADLIST lphl, WORD wIndex, WORD state)
616 LPLISTSTRUCT lpls;
617 int n = 0;
619 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
620 return LB_ERR;
622 if (wIndex == (UINT)-1) {
623 for (lpls = lphl->lpFirst; lpls != NULL; lpls = lpls->lpNext) {
624 if( lpls->itemState & ODS_SELECTED) n++;
625 lpls->itemState = state? lpls->itemState | ODS_SELECTED
626 : lpls->itemState & ~ODS_SELECTED;
628 return n;
631 if (wIndex >= lphl->ItemsCount) return LB_ERR;
633 lpls = ListBoxGetItem(lphl, wIndex);
634 lpls->itemState = state? lpls->itemState | ODS_SELECTED
635 : lpls->itemState & ~ODS_SELECTED;
637 return 0;
641 int ListBoxGetSel(LPHEADLIST lphl, WORD wIndex)
643 LPLISTSTRUCT lpls = ListBoxGetItem(lphl, wIndex);
645 if (lpls == NULL) return LB_ERR;
646 return lpls->itemState & ODS_SELECTED;
649 /* ------------------------- dir listing ------------------------ */
651 LONG ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPCSTR filespec)
653 char temp[16], mask[13];
654 char *path, *p;
655 const char *ptr;
656 int skip, count;
657 LONG ret;
658 DOS_DIRENT entry;
660 dprintf_listbox(stddeb, "ListBoxDirectory: '%s' %04x\n", filespec, attrib);
661 if (!filespec) return LB_ERR;
662 if (!(ptr = DOSFS_GetUnixFileName( filespec, FALSE ))) return LB_ERR;
663 path = xstrdup(ptr);
664 p = strrchr( path, '/' );
665 *p++ = '\0';
666 if (!(ptr = DOSFS_ToDosFCBFormat( p )))
668 free( path );
669 return LB_ERR;
671 strcpy( mask, ptr );
673 dprintf_listbox(stddeb, "ListBoxDirectory: path=%s mask=%s\n", path, mask);
675 skip = ret = 0;
676 attrib &= ~FA_LABEL;
677 while ((count = DOSFS_FindNext( path, mask, 0, attrib, skip, &entry )) > 0)
679 skip += count;
680 if (entry.attr & FA_DIRECTORY)
682 if ((attrib & DDL_DIRECTORY) && strcmp(entry.name, ". "))
684 sprintf(temp, "[%s]", DOSFS_ToDosDTAFormat( entry.name ) );
685 AnsiLower( temp );
686 if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
689 else /* not a directory */
691 if (!(attrib & DDL_EXCLUSIVE) ||
692 ((attrib & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)) ==
693 (entry.attr & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE))))
695 strcpy( temp, DOSFS_ToDosDTAFormat( entry.name ) );
696 AnsiLower( temp );
697 if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
701 if (attrib & DDL_DRIVES)
703 int x;
704 strcpy( temp, "[-a-]" );
705 for (x = 0; x < MAX_DOS_DRIVES; x++, temp[2]++)
707 if (DRIVE_IsValid(x))
708 if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
711 free( path );
712 return ret;
715 /* ------------------------- dimensions ------------------------- */
717 int ListBoxGetItemRect(LPHEADLIST lphl, WORD wIndex, LPRECT lprect)
719 LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wIndex);
721 if (lpls == NULL) return LB_ERR;
722 *lprect = lpls->itemRect;
723 return 0;
727 int ListBoxSetItemHeight(LPHEADLIST lphl, WORD wIndex, long height)
729 LPLISTSTRUCT lpls;
731 if (!(lphl->dwStyle & LBS_OWNERDRAWVARIABLE)) {
732 lphl->StdItemHeight = (short)height;
733 return 0;
736 lpls = ListBoxGetItem(lphl, wIndex);
737 if (lpls == NULL) return LB_ERR;
739 lpls->mis.itemHeight = height;
740 return 0;
743 /* -------------------------- string search ------------------------ */
745 int ListBoxFindNextMatch(LPHEADLIST lphl, WORD wChar)
747 LPLISTSTRUCT lpls;
748 UINT count,first;
750 if ((char)wChar < ' ') return LB_ERR;
751 if (!lphl->HasStrings) return LB_ERR;
753 lpls = lphl->lpFirst;
755 for (count = 0; lpls != NULL; lpls = lpls->lpNext, count++) {
756 if (tolower(*lpls->itemText) == tolower((char)wChar)) break;
758 if (lpls == NULL) return LB_ERR;
759 first = count;
760 for(; lpls != NULL; lpls = lpls->lpNext, count++) {
761 if (*lpls->itemText != (char)wChar)
762 break;
763 if ((short) count > lphl->ItemFocused)
764 return count;
766 return first;
769 /***********************************************************************
770 * LBCreate
772 static LONG LBCreate(HWND hwnd, WORD wParam, LONG lParam)
774 LPHEADLIST lphl;
775 LONG dwStyle = GetWindowLong(hwnd,GWL_STYLE);
776 RECT rect;
778 CreateListBoxStruct(hwnd, ODT_LISTBOX, dwStyle, GetParent(hwnd));
779 lphl = ListBoxGetStorageHeader(hwnd);
780 dprintf_listbox(stddeb,"ListBox created: lphl = %p dwStyle = %04x:%04x\n",
781 lphl, HIWORD(dwStyle), LOWORD(dwStyle));
783 GetClientRect(hwnd,&rect);
784 lphl->ColumnsWidth = rect.right - rect.left;
786 if (dwStyle & WS_VSCROLL)
787 SetScrollRange(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
788 if (dwStyle & WS_HSCROLL)
789 SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
791 return 0;
795 /***********************************************************************
796 * LBDestroy
798 static LONG LBDestroy(HWND hwnd, WORD wParam, LONG lParam)
800 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
802 ListBoxResetContent(lphl);
804 DestroyListBoxStruct(lphl);
805 dprintf_listbox(stddeb,"ListBox destroyed: lphl = %p\n",lphl);
806 return 0;
809 /***********************************************************************
810 * LBVScroll
812 static LONG LBVScroll(HWND hwnd, WORD wParam, LONG lParam)
814 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
815 int y;
817 dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
818 wParam, lParam);
819 y = lphl->FirstVisible;
821 switch(wParam) {
822 case SB_LINEUP:
823 if (lphl->FirstVisible > 0)
824 lphl->FirstVisible--;
825 break;
827 case SB_LINEDOWN:
828 lphl->FirstVisible++;
829 break;
831 case SB_PAGEUP:
832 if (lphl->FirstVisible > lphl->ItemsVisible) {
833 lphl->FirstVisible -= lphl->ItemsVisible;
834 } else {
835 lphl->FirstVisible = 0;
837 break;
839 case SB_PAGEDOWN:
840 lphl->FirstVisible += lphl->ItemsVisible;
841 break;
843 case SB_THUMBTRACK:
844 lphl->FirstVisible = LOWORD(lParam);
845 break;
848 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
849 lphl->FirstVisible = ListMaxFirstVisible(lphl);
851 if (y != lphl->FirstVisible) {
852 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
853 InvalidateRect(hwnd, NULL, TRUE);
855 return 0;
858 /***********************************************************************
859 * LBHScroll
861 static LONG LBHScroll(HWND hwnd, WORD wParam, LONG lParam)
863 LPHEADLIST lphl;
864 int y;
866 dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
867 wParam, lParam);
868 lphl = ListBoxGetStorageHeader(hwnd);
869 y = lphl->FirstVisible;
870 switch(wParam) {
871 case SB_LINEUP:
872 if (lphl->FirstVisible > lphl->ItemsPerColumn) {
873 lphl->FirstVisible -= lphl->ItemsPerColumn;
874 } else {
875 lphl->FirstVisible = 0;
877 break;
878 case SB_LINEDOWN:
879 lphl->FirstVisible += lphl->ItemsPerColumn;
880 break;
881 case SB_PAGEUP:
882 if (lphl->ItemsPerColumn != 0) {
883 int lbsub = lphl->ItemsVisible / lphl->ItemsPerColumn * lphl->ItemsPerColumn;
884 if (lphl->FirstVisible > lbsub) {
885 lphl->FirstVisible -= lbsub;
886 } else {
887 lphl->FirstVisible = 0;
890 break;
891 case SB_PAGEDOWN:
892 if (lphl->ItemsPerColumn != 0)
893 lphl->FirstVisible += lphl->ItemsVisible /
894 lphl->ItemsPerColumn * lphl->ItemsPerColumn;
895 break;
896 case SB_THUMBTRACK:
897 lphl->FirstVisible = lphl->ItemsPerColumn * LOWORD(lParam);
898 break;
900 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
901 lphl->FirstVisible = ListMaxFirstVisible(lphl);
903 if (lphl->ItemsPerColumn != 0) {
904 lphl->FirstVisible = lphl->FirstVisible /
905 lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
906 if (y != lphl->FirstVisible) {
907 SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible /
908 lphl->ItemsPerColumn + 1, TRUE);
909 InvalidateRect(hwnd, NULL, TRUE);
912 return 0;
915 /***********************************************************************
916 * LBLButtonDown
918 static LONG LBLButtonDown(HWND hwnd, WORD wParam, LONG lParam)
920 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
921 WORD wRet;
922 int y,n;
923 RECT rectsel;
924 POINT tmpPOINT;
925 tmpPOINT.x = LOWORD(lParam); tmpPOINT.y = HIWORD(lParam);
927 SetFocus(hwnd);
928 SetCapture(hwnd);
930 lphl->PrevFocused = lphl->ItemFocused;
932 y = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
934 if (y == -1) return 0;
936 if (lphl->dwStyle & LBS_NOTIFY && y!= LB_ERR )
937 if( SendMessage(lphl->hParent, WM_LBTRACKPOINT, y, lParam) )
938 return 0;
941 switch( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )
943 case LBS_MULTIPLESEL:
944 lphl->ItemFocused = y;
945 wRet = ListBoxGetSel(lphl, y);
946 ListBoxSetSel(lphl, y, !wRet);
947 break;
948 case LBS_EXTENDEDSEL:
949 /* should handle extended mode here and in kbd handler
952 if ( lphl->PrevFocused != y && y!= LB_ERR)
954 LPLISTSTRUCT lpls = ListBoxGetItem( lphl, lphl->ItemFocused = y );
955 n = ListBoxSetSel(lphl,-1,FALSE);
957 lpls->itemState = ODS_FOCUS | ODS_SELECTED;
959 if( n > 1 && n != LB_ERR )
960 InvalidateRect(hwnd,NULL,TRUE);
962 else
963 return 0;
965 break;
966 case 0:
967 if( y!=lphl->ItemFocused )
968 ListBoxSetCurSel(lphl, y);
969 else
970 return 0;
971 break;
972 default:
973 fprintf(stdnimp,"Listbox: LBS_MULTIPLESEL and LBS_EXTENDEDSEL are on!\n");
974 return 0;
977 /* invalidate changed items */
978 if( lphl->dwStyle & LBS_MULTIPLESEL || y!=lphl->PrevFocused )
980 ListBoxGetItemRect(lphl, y, &rectsel);
981 InvalidateRect(hwnd, &rectsel, TRUE);
983 if( lphl->PrevFocused!=-1 && y!=lphl->PrevFocused )
985 ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
986 InvalidateRect(hwnd, &rectsel, TRUE);
989 #ifndef WINELIB
990 if (GetWindowLong(lphl->hSelf,GWL_EXSTYLE) & WS_EX_DRAGDETECT)
991 if( DragDetect(lphl->hSelf,tmpPOINT) )
992 SendMessage(lphl->hParent, WM_BEGINDRAG,0,0L);
993 #endif
994 return 0;
997 /***********************************************************************
998 * LBLButtonUp
1000 static LONG LBLButtonUp(HWND hwnd, WORD wParam, LONG lParam)
1002 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1004 if (GetCapture() == hwnd) ReleaseCapture();
1006 if (lphl->PrevFocused != lphl->ItemFocused)
1007 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1009 return 0;
1012 /***********************************************************************
1013 * LBRButtonUp
1015 static LONG LBRButtonUp(HWND hwnd, WORD wParam, LONG lParam)
1017 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1019 #ifdef WINELIB32
1020 SendMessage(lphl->hParent, WM_COMMAND,
1021 MAKEWPARAM(GetWindowWord(hwnd,GWW_ID),LBN_DBLCLK),
1022 (LPARAM)hwnd);
1023 #else
1024 SendMessage(lphl->hParent, WM_COMMAND, GetWindowWord(hwnd,GWW_ID),
1025 MAKELONG(hwnd, LBN_DBLCLK));
1026 #endif
1028 return 0;
1031 /***********************************************************************
1032 * LBMouseMove
1034 static LONG LBMouseMove(HWND hwnd, WORD wParam, LONG lParam)
1036 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1037 int y,redraw_prev = 0;
1038 int iRet;
1039 RECT rect, rectsel; /* XXX Broken */
1041 dprintf_listbox(stddeb,"LBMouseMove %d %d\n",SLOWORD(lParam),SHIWORD(lParam));
1042 if ((wParam & MK_LBUTTON) != 0) {
1043 y = SHIWORD(lParam);
1044 if (y < LBMM_EDGE) {
1045 if (lphl->FirstVisible > 0) {
1046 lphl->FirstVisible--;
1047 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1048 InvalidateRect(hwnd, NULL, TRUE);
1049 return 0;
1052 GetClientRect(hwnd, &rect);
1053 if (y >= (rect.bottom-LBMM_EDGE)) {
1054 if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
1055 lphl->FirstVisible++;
1056 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1057 InvalidateRect(hwnd, NULL, TRUE);
1058 return 0;
1061 if ((y > 0) && (y < (rect.bottom - LBMM_EDGE))) {
1062 if ((y < rectsel.top) || (y > rectsel.bottom)) {
1063 iRet = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
1064 if (iRet == lphl->ItemFocused || iRet == -1) {
1065 return 0;
1067 if (lphl->dwStyle & LBS_MULTIPLESEL) {
1068 lphl->ItemFocused = iRet;
1069 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1070 } else if ( lphl->dwStyle & LBS_EXTENDEDSEL )
1072 /* Fixme: extended selection mode */
1073 ListBoxSetSel( lphl, lphl->ItemFocused, 0);
1074 lphl->PrevFocused = lphl->ItemFocused;
1075 lphl->ItemFocused = iRet;
1076 ListBoxSetSel( lphl, iRet, TRUE);
1077 redraw_prev = 1;
1079 else
1081 ListBoxSetCurSel(lphl, (WORD)iRet);
1082 redraw_prev = 1;
1084 if( lphl->PrevFocused!=-1 && redraw_prev )
1086 ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
1087 InvalidateRect(hwnd, &rectsel, TRUE);
1089 ListBoxGetItemRect(lphl, iRet, &rectsel);
1090 InvalidateRect(hwnd, &rectsel, TRUE);
1095 return 0;
1098 /***********************************************************************
1099 * LBKeyDown
1101 * Doesn't yet handle properly VK_SHIFT with LB_EXTENDEDSEL
1103 static LONG LBKeyDown(HWND hwnd, WORD wParam, LONG lParam)
1105 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1106 WORD newFocused = 0xFFFF;
1107 RECT rect;
1109 ListBoxGetItemRect(lphl,lphl->ItemFocused,&rect);
1110 switch(wParam)
1112 case VK_HOME:
1113 case VK_END:
1114 case VK_LEFT:
1115 case VK_RIGHT:
1116 case VK_UP:
1117 case VK_DOWN:
1118 case VK_PRIOR:
1119 case VK_NEXT:
1120 if ( lphl->dwStyle & LBS_WANTKEYBOARDINPUT )
1122 newFocused = (WORD)(INT)SendMessage(lphl->hParent,WM_VKEYTOITEM,
1123 wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
1124 if ( newFocused == 0xFFFE ) return 0L;
1126 if ( newFocused == 0xFFFF )
1128 newFocused = lphl->ItemFocused;
1130 /* nested switch */
1131 switch(wParam)
1133 case VK_HOME:
1134 newFocused = 0;
1135 break;
1136 case VK_END:
1137 newFocused = lphl->ItemsCount - 1;
1138 break;
1139 case VK_LEFT:
1140 if (lphl->dwStyle & LBS_MULTICOLUMN) {
1141 if (newFocused >= lphl->ItemsPerColumn) {
1142 newFocused -= lphl->ItemsPerColumn;
1143 } else {
1144 newFocused = 0;
1147 break;
1148 case VK_UP:
1149 if (newFocused > 0) newFocused--;
1150 break;
1151 case VK_RIGHT:
1152 if (lphl->dwStyle & LBS_MULTICOLUMN)
1153 newFocused += lphl->ItemsPerColumn;
1154 break;
1155 case VK_DOWN:
1156 newFocused++;
1157 break;
1158 case VK_PRIOR:
1159 if (newFocused > lphl->ItemsVisible)
1160 newFocused -= lphl->ItemsVisible;
1161 else newFocused = 0;
1162 break;
1163 case VK_NEXT:
1164 newFocused += lphl->ItemsVisible;
1165 break;
1166 default:
1167 return 0;
1169 /* end of nested switch */
1171 break;
1172 case VK_SPACE:
1173 if (lphl->dwStyle & LBS_MULTIPLESEL)
1175 WORD wRet = ListBoxGetSel(lphl, lphl->ItemFocused);
1176 ListBoxSetSel(lphl, lphl->ItemFocused, !wRet);
1178 return 0;
1180 /* chars are handled in LBChar */
1181 default:
1182 return 0;
1185 /* at this point newFocused is set up */
1187 if (newFocused >= lphl->ItemsCount)
1188 newFocused = lphl->ItemsCount - 1;
1190 if (!(lphl->dwStyle & LBS_MULTIPLESEL))
1192 ListBoxSetCurSel(lphl, newFocused);
1193 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1196 lphl->ItemFocused = newFocused;
1198 if( ListBoxScrollToFocus(lphl) || (lphl->dwStyle &
1199 (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) )
1200 InvalidateRect(hwnd, NULL, TRUE);
1201 else
1203 InvalidateRect(hwnd, &rect, TRUE);
1204 if( newFocused < 0x8000 )
1206 ListBoxGetItemRect(lphl, newFocused, &rect);
1207 InvalidateRect(hwnd, &rect, TRUE);
1211 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1213 return 0;
1216 /***********************************************************************
1217 * LBChar
1219 static LONG LBChar(HWND hwnd, WORD wParam, LONG lParam)
1221 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1222 WORD newFocused = 0xFFFF;
1224 if ( (lphl->dwStyle & LBS_WANTKEYBOARDINPUT) && !(lphl->HasStrings))
1226 newFocused = (WORD)(INT)SendMessage(lphl->hParent,WM_CHARTOITEM,
1227 wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
1228 if ( newFocused == 0xFFFE ) return 0L;
1231 if (newFocused == 0xFFFF )
1232 newFocused = ListBoxFindNextMatch(lphl, wParam);
1234 if (newFocused == (WORD)LB_ERR) return 0;
1236 if (newFocused >= lphl->ItemsCount)
1237 newFocused = lphl->ItemsCount - 1;
1239 if (!(lphl->dwStyle & LBS_MULTIPLESEL))
1241 ListBoxSetCurSel(lphl, newFocused);
1242 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1245 lphl->ItemFocused = newFocused;
1246 ListBoxScrollToFocus(lphl);
1247 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1249 InvalidateRect(hwnd, NULL, TRUE);
1251 return 0;
1254 /***********************************************************************
1255 * LBSetRedraw
1257 static LONG LBSetRedraw(HWND hwnd, WORD wParam, LONG lParam)
1259 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1261 dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd=%04x w=%04x !\n",
1262 hwnd, wParam);
1263 lphl->bRedrawFlag = wParam;
1265 return 0;
1268 /***********************************************************************
1269 * LBSetFont
1271 static LONG LBSetFont(HWND hwnd, WPARAM wParam, LPARAM lParam)
1273 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1274 HDC hdc;
1276 if (wParam == 0)
1277 lphl->hFont = GetStockObject(SYSTEM_FONT);
1278 else
1279 lphl->hFont = (HFONT) wParam;
1281 /* a new font means possible new text height */
1282 /* does this mean the height of each entry must be separately changed? */
1283 /* or are we guaranteed to get a LBSetFont before the first insert/add? */
1284 if ((hdc = GetDC(0)))
1286 TEXTMETRIC tm;
1287 GetTextMetrics( hdc, &tm );
1288 lphl->StdItemHeight = tm.tmHeight;
1289 dprintf_listbox(stddeb,"LBSetFont: new font %d with height %d\n",
1290 lphl->hFont, lphl->StdItemHeight);
1291 ReleaseDC( 0, hdc );
1294 return 0;
1297 /***********************************************************************
1298 * LBPaint
1300 static LONG LBPaint(HWND hwnd, WORD wParam, LONG lParam)
1302 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1303 LPLISTSTRUCT lpls;
1304 PAINTSTRUCT ps;
1305 HBRUSH hBrush;
1306 HFONT hOldFont;
1307 HDC hdc = BeginPaint( hwnd, &ps );
1308 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
1309 RECT rect, paintRect, scratchRect;
1310 int i, top, height, maxwidth, ipc;
1312 top = 0;
1314 if (!IsWindowVisible(hwnd) || !lphl->bRedrawFlag) {
1315 EndPaint(hwnd, &ps);
1316 return 0;
1319 GetRgnBox(dc->w.hGCClipRgn,&paintRect);
1320 GetClientRect(hwnd, &rect);
1321 IntersectRect(&paintRect,&rect,&paintRect);
1323 hOldFont = SelectObject(hdc, lphl->hFont);
1325 #ifdef WINELIB32
1326 hBrush = (HBRUSH) SendMessage(lphl->hParent, WM_CTLCOLORLISTBOX, (WPARAM)hdc,
1327 (LPARAM)hwnd);
1328 #else
1329 hBrush = SendMessage(lphl->hParent, WM_CTLCOLOR, hdc,
1330 MAKELONG(hwnd, CTLCOLOR_LISTBOX));
1331 #endif
1333 if (hBrush == 0) hBrush = GetStockObject(WHITE_BRUSH);
1335 FillRect(hdc, &rect, hBrush);
1337 maxwidth = rect.right;
1338 if (lphl->dwStyle & LBS_MULTICOLUMN) {
1339 rect.right = lphl->ColumnsWidth;
1341 lpls = lphl->lpFirst;
1343 lphl->ItemsVisible = 0;
1344 lphl->ItemsPerColumn = ipc = 0;
1346 for(i = 0; i < lphl->ItemsCount; i++) {
1347 if (lpls == NULL) break;
1349 if (i >= lphl->FirstVisible) {
1350 height = lpls->mis.itemHeight;
1352 if (top > (rect.bottom-height+1)) {
1353 if (lphl->dwStyle & LBS_MULTICOLUMN) {
1354 lphl->ItemsPerColumn = MAX(lphl->ItemsPerColumn, ipc);
1355 ipc = 0;
1356 top = 0;
1357 rect.left += lphl->ColumnsWidth;
1358 rect.right += lphl->ColumnsWidth;
1359 if (rect.left > maxwidth) break;
1360 } else {
1361 break;
1365 lpls->itemRect.top = top;
1366 lpls->itemRect.bottom = top + height;
1367 lpls->itemRect.left = rect.left;
1368 lpls->itemRect.right = rect.right;
1370 if( IntersectRect(&scratchRect,&paintRect,&lpls->itemRect) )
1372 dprintf_listbox(stddeb,"LBPaint: drawing item: %d %d %d %d %d\n",
1373 rect.left,top,rect.right,top+height,lpls->itemState);
1375 if (lphl->OwnerDrawn && (lphl->ItemFocused == i) && GetFocus() == hwnd)
1377 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS,
1378 lpls->itemState & ~ODS_FOCUS);
1379 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
1380 lpls->itemState & ~ODS_FOCUS);
1381 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS, lpls->itemState);
1383 else
1384 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
1385 lpls->itemState);
1388 top += height;
1389 lphl->ItemsVisible++;
1390 ipc++;
1393 lpls = lpls->lpNext;
1395 ListBoxUpdateWindow(hwnd,lphl,FALSE);
1396 SelectObject(hdc,hOldFont);
1397 EndPaint( hwnd, &ps );
1398 return 0;
1401 /***********************************************************************
1402 * LBSetFocus
1404 static LONG LBSetFocus(HWND hwnd, WORD wParam, LONG lParam)
1406 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1408 dprintf_listbox(stddeb,"ListBox WM_SETFOCUS for %04x\n",hwnd);
1409 if(!(lphl->dwStyle & LBS_MULTIPLESEL) )
1410 if( lphl->ItemsCount && lphl->ItemFocused != -1)
1412 HDC hDC = GetDC(hwnd);
1413 HFONT hOldFont = SelectObject(hDC, lphl->hFont);
1414 LPLISTSTRUCT lpls;
1416 lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
1417 lpls->itemState |= ODS_FOCUS;
1419 ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
1420 SelectObject(hDC, hOldFont);
1421 ReleaseDC(hwnd,hDC);
1424 ListBoxSendNotification(lphl, LBN_SETFOCUS);
1426 return 0;
1429 /***********************************************************************
1430 * LBKillFocus
1432 static LONG LBKillFocus(HWND hwnd, WORD wParam, LONG lParam)
1434 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1436 dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS for %04x\n",hwnd);
1437 if (!(lphl->dwStyle & LBS_MULTIPLESEL))
1439 if( lphl->ItemsCount )
1440 if( lphl->ItemFocused != -1 )
1442 HDC hDC = GetDC(hwnd);
1443 HFONT hOldFont = SelectObject(hDC, lphl->hFont);
1444 LPLISTSTRUCT lpls;
1446 lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
1447 lpls->itemState &= ~ODS_FOCUS;
1449 ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
1450 SelectObject(hDC, hOldFont);
1451 ReleaseDC(hwnd,hDC);
1453 else
1454 dprintf_listbox(stddeb,"LBKillFocus: no focused item!\n");
1456 else
1457 InvalidateRect(hwnd, NULL, TRUE);
1459 ListBoxSendNotification(lphl, LBN_KILLFOCUS);
1461 return 0;
1464 /***********************************************************************
1465 * LBResetContent
1467 static LONG LBResetContent(HWND hwnd, WORD wParam, LONG lParam)
1469 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1471 dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
1472 ListBoxResetContent(lphl);
1473 ListBoxUpdateWindow(hwnd, lphl, TRUE);
1474 return 0;
1477 /***********************************************************************
1478 * LBDir
1480 static LONG LBDir(HWND hwnd, WORD wParam, LONG lParam)
1482 LONG ret;
1483 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1484 dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
1486 ret = ListBoxDirectory(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
1487 ListBoxUpdateWindow(hwnd, lphl, TRUE);
1488 return ret;
1491 /***********************************************************************
1492 * LBAddString
1494 static LONG LBAddString(HWND hwnd, WORD wParam, LONG lParam)
1496 WORD wRet;
1497 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1499 if (lphl->HasStrings)
1500 wRet = ListBoxAddString(lphl, (LPCSTR)PTR_SEG_TO_LIN(lParam));
1501 else
1502 wRet = ListBoxAddString(lphl, (LPCSTR)lParam);
1504 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1505 return wRet;
1508 /***********************************************************************
1509 * LBGetText
1511 static LONG LBGetText(HWND hwnd, WORD wParam, LONG lParam)
1513 LONG wRet;
1514 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1516 dprintf_listbox(stddeb, "LB_GETTEXT wParam=%d\n",wParam);
1517 wRet = ListBoxGetText(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
1519 return wRet;
1522 /***********************************************************************
1523 * LBInsertString
1525 static LONG LBInsertString(HWND hwnd, WORD wParam, LONG lParam)
1527 WORD wRet;
1528 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1530 if (lphl->HasStrings)
1531 wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)PTR_SEG_TO_LIN(lParam));
1532 else
1533 wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)lParam);
1535 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1536 return wRet;
1539 /***********************************************************************
1540 * LBDeleteString
1542 static LONG LBDeleteString(HWND hwnd, WORD wParam, LONG lParam)
1544 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1545 LONG lRet = ListBoxDeleteString(lphl,wParam);
1547 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1548 return lRet;
1551 /***********************************************************************
1552 * LBFindString
1554 static LONG LBFindString(HWND hwnd, WORD wParam, LONG lParam)
1556 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1557 return ListBoxFindString(lphl, wParam, (SEGPTR)lParam);
1560 /***********************************************************************
1561 * LBGetCaretIndex
1563 static LONG LBGetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
1565 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1566 return lphl->ItemFocused;
1569 /***********************************************************************
1570 * LBGetCount
1572 static LONG LBGetCount(HWND hwnd, WORD wParam, LONG lParam)
1574 LPHEADLIST lphl;
1576 lphl = ListBoxGetStorageHeader(hwnd);
1577 return lphl->ItemsCount;
1580 /***********************************************************************
1581 * LBGetCurSel
1583 static LONG LBGetCurSel(HWND hwnd, WORD wParam, LONG lParam)
1585 LPHEADLIST lphl;
1587 lphl = ListBoxGetStorageHeader(hwnd);
1588 dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %i !\n",
1589 lphl->ItemFocused);
1590 return lphl->ItemFocused;
1593 /***********************************************************************
1594 * LBGetHorizontalExtent
1596 static LONG LBGetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
1598 return 0;
1601 /***********************************************************************
1602 * LBGetItemHeight
1604 static LONG LBGetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
1606 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1607 LPLISTSTRUCT lpls = ListBoxGetItem (lphl, wParam);
1609 if (lpls == NULL) return LB_ERR;
1610 return lpls->mis.itemHeight;
1613 /***********************************************************************
1614 * LBGetItemRect
1616 static LONG LBGetItemRect(HWND hwnd, WORD wParam, LONG lParam)
1618 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1619 return ListBoxGetItemRect(lphl, wParam, PTR_SEG_TO_LIN(lParam));
1622 /***********************************************************************
1623 * LBGetSel
1625 static LONG LBGetSel(HWND hwnd, WORD wParam, LONG lParam)
1627 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1628 int iSel = ListBoxGetSel(lphl, wParam);
1630 dprintf_listbox(stdnimp,"LBGetSel: item %u - %i\n",wParam,iSel);
1632 return (iSel)? 1 : 0;
1635 /***********************************************************************
1636 * LBGetSelCount
1638 static LONG LBGetSelCount(HWND hwnd, WORD wParam, LONG lParam)
1640 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1641 LPLISTSTRUCT lpls;
1642 int cnt = 0;
1643 int items = 0;
1645 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1646 return LB_ERR;
1648 for( lpls = lphl->lpFirst;
1649 lpls;
1650 lpls = lpls->lpNext )
1652 items++;
1653 if (lpls->itemState )
1654 cnt++;
1657 return cnt;
1660 /***********************************************************************
1661 * LBGetSelItems
1663 static LONG LBGetSelItems(HWND hwnd, WORD wParam, LONG lParam)
1665 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1666 LPLISTSTRUCT lpls;
1667 int cnt, idx;
1668 int *lpItems = PTR_SEG_TO_LIN(lParam);
1670 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1671 return LB_ERR;
1673 if (wParam == 0) return 0;
1675 lpls = lphl->lpFirst;
1676 cnt = 0; idx = 0;
1678 while (lpls != NULL) {
1679 if (lpls->itemState > 0) lpItems[cnt++] = idx;
1681 if (cnt == wParam) break;
1682 idx++;
1683 lpls = lpls->lpNext;
1686 return cnt;
1689 /***********************************************************************
1690 * LBGetTextLen
1692 static LONG LBGetTextLen(HWND hwnd, WORD wParam, LONG lParam)
1694 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1695 LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wParam);
1697 if (lpls == NULL || !lphl->HasStrings) return LB_ERR;
1698 return strlen(lpls->itemText);
1701 /***********************************************************************
1702 * LBGetDlgCode
1704 static LONG LBGetDlgCode(HWND hwnd, WORD wParam, LONG lParam)
1706 return DLGC_WANTARROWS | DLGC_WANTCHARS;
1709 /***********************************************************************
1710 * LBGetTopIndex
1712 static LONG LBGetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
1714 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1716 return lphl->FirstVisible;
1720 /***********************************************************************
1721 * LBSelectString
1723 static LONG LBSelectString(HWND hwnd, WORD wParam, LONG lParam)
1725 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1726 INT iRet;
1728 iRet = ListBoxFindString(lphl, wParam, (SEGPTR)lParam);
1730 if( iRet != LB_ERR)
1732 if( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )
1733 ListBoxSetSel(lphl,iRet,TRUE);
1734 else
1735 ListBoxSetCurSel(lphl,iRet);
1737 lphl->ItemFocused = iRet;
1738 InvalidateRect(hwnd,0,TRUE);
1740 return iRet;
1743 /***********************************************************************
1744 * LBSelItemRange
1746 static LONG LBSelItemRange(HWND hwnd, WORD wParam, LONG lParam)
1748 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1749 LPLISTSTRUCT lpls;
1750 WORD cnt;
1751 WORD first = LOWORD(lParam);
1752 WORD last = HIWORD(lParam);
1753 BOOL select = wParam;
1755 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1756 return LB_ERR;
1758 if (first >= lphl->ItemsCount ||
1759 last >= lphl->ItemsCount) return LB_ERR;
1761 lpls = lphl->lpFirst;
1762 cnt = 0;
1764 while (lpls != NULL) {
1765 if (cnt++ >= first)
1766 lpls->itemState = select ? lpls->itemState | ODS_SELECTED : 0;
1768 if (cnt > last)
1769 break;
1771 lpls = lpls->lpNext;
1774 return 0;
1777 /***********************************************************************
1778 * LBSetCaretIndex
1780 static LONG LBSetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
1782 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1783 int i;
1785 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )) return 0;
1787 dprintf_listbox(stddeb,"LBSetCaretIndex: hwnd %04x n=%i\n",hwnd,wParam);
1789 if (wParam >= lphl->ItemsCount) return LB_ERR;
1791 lphl->ItemFocused = wParam;
1792 i = ListBoxScrollToFocus (lphl);
1794 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1795 if(i)
1796 InvalidateRect(hwnd, NULL, TRUE);
1798 return 1;
1801 /***********************************************************************
1802 * LBSetColumnWidth
1804 static LONG LBSetColumnWidth(HWND hwnd, WORD wParam, LONG lParam)
1806 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1807 lphl->ColumnsWidth = wParam;
1808 InvalidateRect(hwnd,NULL,TRUE);
1809 return 0;
1812 /***********************************************************************
1813 * LBSetHorizontalExtent
1815 static LONG LBSetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
1817 return 0;
1820 /***********************************************************************
1821 * LBGetItemData
1823 static LONG LBGetItemData(HWND hwnd, WORD wParam, LONG lParam)
1825 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1826 dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
1827 return ListBoxGetItemData(lphl, wParam);
1830 /***********************************************************************
1831 * LBSetItemData
1833 static LONG LBSetItemData(HWND hwnd, WORD wParam, LONG lParam)
1835 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1836 dprintf_listbox(stddeb, "LB_SETITEMDATA wParam=%x lParam=%lx\n", wParam, lParam);
1837 return ListBoxSetItemData(lphl, wParam, lParam);
1840 /***********************************************************************
1841 * LBSetTabStops
1843 static LONG LBSetTabStops(HWND hwnd, WORD wParam, LONG lParam)
1845 LPHEADLIST lphl;
1847 lphl = ListBoxGetStorageHeader(hwnd);
1849 if (lphl->TabStops != NULL) {
1850 lphl->iNumStops = 0;
1851 free (lphl->TabStops);
1854 lphl->TabStops = malloc (wParam * sizeof (short));
1855 if (lphl->TabStops) {
1856 lphl->iNumStops = wParam;
1857 memcpy (lphl->TabStops, PTR_SEG_TO_LIN(lParam), wParam * sizeof (short));
1858 return TRUE;
1861 return FALSE;
1864 /***********************************************************************
1865 * LBSetCurSel
1867 static LONG LBSetCurSel(HWND hwnd, WORD wParam, LONG lParam)
1869 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1870 WORD wRet;
1872 dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n",
1873 wParam);
1875 wRet = ListBoxSetCurSel(lphl, wParam);
1877 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1878 InvalidateRect(hwnd, NULL, TRUE);
1880 return wRet;
1883 /***********************************************************************
1884 * LBSetSel
1886 static LONG LBSetSel(HWND hwnd, WORD wParam, LONG lParam)
1888 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1889 RECT rect;
1890 int iRet;
1892 dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
1894 iRet = ListBoxSetSel(lphl, LOWORD(lParam), wParam);
1896 if( iRet > 1 )
1897 InvalidateRect(hwnd, NULL, TRUE);
1898 else if( iRet != LB_ERR )
1900 if( lphl->dwStyle & LBS_EXTENDEDSEL &&
1901 lphl->ItemFocused != LOWORD(lParam) )
1903 ListBoxGetItemRect(lphl, lphl->ItemFocused , &rect);
1904 InvalidateRect(hwnd,&rect,TRUE);
1905 lphl->ItemFocused = LOWORD(lParam);
1907 ListBoxGetItemRect(lphl,LOWORD(lParam),&rect);
1908 InvalidateRect(hwnd,&rect,TRUE);
1911 return (iRet == (WORD)LB_ERR)? LB_ERR: 0;
1914 /***********************************************************************
1915 * LBSetTopIndex
1917 static LONG LBSetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
1919 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1921 dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
1922 wParam);
1923 lphl->FirstVisible = wParam;
1924 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1926 InvalidateRect(hwnd, NULL, TRUE);
1928 return 0;
1931 /***********************************************************************
1932 * LBSetItemHeight
1934 static LONG LBSetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
1936 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1937 WORD wRet;
1939 dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
1940 wRet = ListBoxSetItemHeight(lphl, wParam, lParam);
1941 InvalidateRect(hwnd,NULL,TRUE);
1942 return wRet;
1945 /***********************************************************************
1946 * LBPassToParent
1948 static LRESULT LBPassToParent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1950 WND* ptrWnd = WIN_FindWndPtr(hwnd);
1952 if( ptrWnd )
1953 if( /* !(ptrWnd->dwExStyle & WS_EX_NOPARENTNOTIFY) && */
1954 ptrWnd->parent )
1955 return SendMessage(ptrWnd->parent->hwndSelf,message,wParam,lParam);
1956 return 0;
1959 /***********************************************************************
1960 * ListBoxWndProc
1962 LRESULT ListBoxWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1964 switch (message) {
1965 case WM_CREATE: return LBCreate(hwnd, wParam, lParam);
1966 case WM_DESTROY: return LBDestroy(hwnd, wParam, lParam);
1967 case WM_GETDLGCODE: return LBGetDlgCode(hwnd, wParam, lParam);
1968 case WM_VSCROLL: return LBVScroll(hwnd, wParam, lParam);
1969 case WM_HSCROLL: return LBHScroll(hwnd, wParam, lParam);
1970 case WM_LBUTTONDOWN: return LBLButtonDown(hwnd, wParam, lParam);
1971 case WM_LBUTTONUP: return LBLButtonUp(hwnd, wParam, lParam);
1972 case WM_RBUTTONUP: return LBRButtonUp(hwnd, wParam, lParam);
1973 case WM_LBUTTONDBLCLK: return LBRButtonUp(hwnd, wParam, lParam);
1974 case WM_MOUSEMOVE: return LBMouseMove(hwnd, wParam, lParam);
1975 case WM_KEYDOWN: return LBKeyDown(hwnd, wParam, lParam);
1976 case WM_CHAR: return LBChar(hwnd, wParam, lParam);
1977 case WM_SETFONT: return LBSetFont(hwnd, wParam, lParam);
1978 case WM_SETREDRAW: return LBSetRedraw(hwnd, wParam, lParam);
1979 case WM_PAINT: return LBPaint(hwnd, wParam, lParam);
1980 case WM_SETFOCUS: return LBSetFocus(hwnd, wParam, lParam);
1981 case WM_KILLFOCUS: return LBKillFocus(hwnd, wParam, lParam);
1982 case LB_RESETCONTENT: return LBResetContent(hwnd, wParam, lParam);
1983 case LB_DIR: return LBDir(hwnd, wParam, lParam);
1984 case LB_ADDSTRING: return LBAddString(hwnd, wParam, lParam);
1985 case LB_INSERTSTRING: return LBInsertString(hwnd, wParam, lParam);
1986 case LB_DELETESTRING: return LBDeleteString(hwnd, wParam, lParam);
1987 case LB_FINDSTRING: return LBFindString(hwnd, wParam, lParam);
1988 case LB_GETCARETINDEX: return LBGetCaretIndex(hwnd, wParam, lParam);
1989 case LB_GETCOUNT: return LBGetCount(hwnd, wParam, lParam);
1990 case LB_GETCURSEL: return LBGetCurSel(hwnd, wParam, lParam);
1991 case LB_GETHORIZONTALEXTENT: return LBGetHorizontalExtent(hwnd, wParam, lParam);
1992 case LB_GETITEMDATA: return LBGetItemData(hwnd, wParam, lParam);
1993 case LB_GETITEMHEIGHT: return LBGetItemHeight(hwnd, wParam, lParam);
1994 case LB_GETITEMRECT: return LBGetItemRect(hwnd, wParam, lParam);
1995 case LB_GETSEL: return LBGetSel(hwnd, wParam, lParam);
1996 case LB_GETSELCOUNT: return LBGetSelCount(hwnd, wParam, lParam);
1997 case LB_GETSELITEMS: return LBGetSelItems(hwnd, wParam, lParam);
1998 case LB_GETTEXT: return LBGetText(hwnd, wParam, lParam);
1999 case LB_GETTEXTLEN: return LBGetTextLen(hwnd, wParam, lParam);
2000 case LB_GETTOPINDEX: return LBGetTopIndex(hwnd, wParam, lParam);
2001 case LB_SELECTSTRING: return LBSelectString(hwnd, wParam, lParam);
2002 case LB_SELITEMRANGE: return LBSelItemRange(hwnd, wParam, lParam);
2003 case LB_SETCARETINDEX: return LBSetCaretIndex(hwnd, wParam, lParam);
2004 case LB_SETCOLUMNWIDTH: return LBSetColumnWidth(hwnd, wParam, lParam);
2005 case LB_SETHORIZONTALEXTENT: return LBSetHorizontalExtent(hwnd, wParam, lParam);
2006 case LB_SETITEMDATA: return LBSetItemData(hwnd, wParam, lParam);
2007 case LB_SETTABSTOPS: return LBSetTabStops(hwnd, wParam, lParam);
2008 case LB_SETCURSEL: return LBSetCurSel(hwnd, wParam, lParam);
2009 case LB_SETSEL: return LBSetSel(hwnd, wParam, lParam);
2010 case LB_SETTOPINDEX: return LBSetTopIndex(hwnd, wParam, lParam);
2011 case LB_SETITEMHEIGHT: return LBSetItemHeight(hwnd, wParam, lParam);
2013 case WM_DROPFILES: return LBPassToParent(hwnd, message, wParam, lParam);
2015 /* these will have to be implemented for proper LBS_EXTENDEDSEL -
2017 * anchor item is an item that with caret (focused) item defines a
2018 * range of currently selected items when listbox is in the extended
2019 * selection mode.
2021 case LB_SETANCHORINDEX: return LB_SETANCHORINDEX; /* that's what Windows returns */
2022 case LB_GETANCHORINDEX: return 0;
2024 case WM_DROPOBJECT:
2025 case WM_QUERYDROPOBJECT:
2026 case WM_DRAGSELECT:
2027 case WM_DRAGMOVE:
2029 LPDRAGINFO lpDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN((SEGPTR)lParam);
2030 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
2032 lpDragInfo->l = ListBoxFindMouse(lphl,lpDragInfo->pt.x,
2033 lpDragInfo->pt.y);
2035 return LBPassToParent(hwnd, message, wParam, lParam);
2039 return DefWindowProc(hwnd, message, wParam, lParam);
2043 /**********************************************************************
2044 * DlgDirSelect (USER.99)
2046 BOOL DlgDirSelect( HWND hDlg, LPSTR lpStr, INT id )
2048 char buffer[20];
2049 INT i;
2051 dprintf_listbox( stddeb, "DlgDirSelect: %04x '%s' %d\n", hDlg, lpStr, id );
2052 if ((i = SendDlgItemMessage( hDlg, id, LB_GETCURSEL, 0, 0 )) == LB_ERR)
2053 return FALSE;
2054 SendDlgItemMessage( hDlg, id, LB_GETTEXT, i, (LPARAM)MAKE_SEGPTR(buffer) );
2055 if (buffer[0] == '[') /* drive or directory */
2057 if (buffer[1] == '-') /* drive */
2059 lpStr[0] = buffer[2];
2060 lpStr[1] = ':';
2061 lpStr[2] = '\0';
2062 dprintf_listbox( stddeb, "Returning drive '%s'\n", lpStr );
2063 return TRUE;
2065 strcpy( lpStr, buffer + 1 );
2066 lpStr[strlen(lpStr)-1] = '\\';
2067 dprintf_listbox( stddeb, "Returning directory '%s'\n", lpStr );
2068 return TRUE;
2070 strcpy( lpStr, buffer );
2071 dprintf_listbox( stddeb, "Returning file '%s'\n", lpStr );
2072 return FALSE;
2076 /**********************************************************************
2077 * DlgDirList (USER.100)
2079 INT DlgDirList( HWND hDlg, SEGPTR spec, INT idLBox, INT idStatic, UINT attrib )
2081 char *filespec = (char *)PTR_SEG_TO_LIN( spec );
2082 int drive;
2083 HWND hwnd;
2085 #define SENDMSG(msg,wparam,lparam) \
2086 ((attrib & DDL_POSTMSGS) ? PostMessage( hwnd, msg, wparam, lparam ) \
2087 : SendMessage( hwnd, msg, wparam, lparam ))
2089 dprintf_listbox( stddeb, "DlgDirList: %04x '%s' %d %d %04x\n",
2090 hDlg, filespec ? filespec : "NULL",
2091 idLBox, idStatic, attrib );
2093 if (filespec && filespec[0] && (filespec[1] == ':'))
2095 drive = toupper( filespec[0] ) - 'A';
2096 filespec += 2;
2097 if (!DRIVE_SetCurrentDrive( drive )) return FALSE;
2099 else drive = DRIVE_GetCurrentDrive();
2101 if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
2103 char mask[20];
2104 char temp[] = "*.*";
2106 if (!filespec[0]) strcpy( mask, "*.*" );
2107 else
2109 /* If the path exists and is a directory, chdir to it */
2110 if (DRIVE_Chdir( drive, filespec )) strcpy( mask, "*.*" );
2111 else
2113 char *p, *p2;
2114 p = filespec;
2115 if ((p2 = strrchr( p, '\\' ))) p = p2 + 1;
2116 if ((p2 = strrchr( p, '/' ))) p = p2 + 1;
2117 lstrcpyn( mask, p, sizeof(mask) );
2118 if (p != filespec)
2120 p[-1] = '\0';
2121 if (!DRIVE_Chdir( drive, filespec )) return FALSE;
2126 strcpy( (char *)PTR_SEG_TO_LIN(spec), mask );
2128 dprintf_listbox(stddeb, "ListBoxDirectory: path=%c:\\%s mask=%s\n",
2129 'A' + drive, DRIVE_GetDosCwd(drive), mask);
2131 SENDMSG( LB_RESETCONTENT, 0, 0 );
2132 if ((attrib & DDL_DIRECTORY) && !(attrib & DDL_EXCLUSIVE))
2134 if (SENDMSG( LB_DIR, attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
2135 (LPARAM)spec ) == LB_ERR) return FALSE;
2136 if (SENDMSG( LB_DIR, (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
2137 (LPARAM)MAKE_SEGPTR(temp) ) == LB_ERR) return FALSE;
2139 else
2141 if (SENDMSG( LB_DIR, attrib, (LPARAM)spec) == LB_ERR) return FALSE;
2145 if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
2147 char temp[256];
2148 strcpy( temp, "A:\\" );
2149 temp[0] += drive;
2150 lstrcpyn( temp+3, DRIVE_GetDosCwd(drive), 253 );
2151 AnsiLower( temp );
2152 SENDMSG( WM_SETTEXT, 0, (LPARAM)MAKE_SEGPTR(temp) );
2154 return TRUE;
2155 #undef SENDMSG