Release 960521
[wine.git] / controls / listbox.c
blob25d4bfb0071280a44a9f859b3dd98a073660ffdb
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 "heap.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 SetWindowLong32A(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)
119 LISTSTRUCT dummyls;
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);
131 /* WINELIBS list boxes do not operate on local heaps */
132 #ifndef WINELIB
133 lphl->HeapSel = GlobalAlloc16(GMEM_FIXED,LIST_HEAP_SIZE);
134 LocalInit( lphl->HeapSel, 0, LIST_HEAP_SIZE-1);
135 #else
136 lphl->HeapSel = 0;
137 #endif
140 void DestroyListBoxStruct(LPHEADLIST lphl)
142 /* XXX need to free lphl->Heap */
143 GlobalFree16(lphl->HeapSel);
144 free(lphl);
147 static LPHEADLIST ListBoxGetStorageHeader(HWND hwnd)
149 return (LPHEADLIST)GetWindowLong(hwnd,0);
152 /* Send notification "code" as part of a WM_COMMAND-message if hwnd
153 has the LBS_NOTIFY style */
154 void ListBoxSendNotification(LPHEADLIST lphl, WORD code)
156 if (lphl->dwStyle & LBS_NOTIFY)
157 #ifdef WINELIB32
158 SendMessage32A(lphl->hParent, WM_COMMAND,
159 MAKEWPARAM(lphl->CtlID,code), (LPARAM)lphl->hSelf);
160 #else
161 SendMessage16(lphl->hParent, WM_COMMAND,
162 lphl->CtlID, MAKELONG(lphl->hSelf, code));
163 #endif
167 /* get the maximum value of lphl->FirstVisible */
168 int ListMaxFirstVisible(LPHEADLIST lphl)
170 int m = lphl->ItemsCount-lphl->ItemsVisible;
171 return (m < 0) ? 0 : m;
175 void ListBoxUpdateWindow(HWND hwnd, LPHEADLIST lphl, BOOL repaint)
177 WND *wndPtr = WIN_FindWndPtr(hwnd);
179 if (wndPtr->dwStyle & WS_VSCROLL)
180 SetScrollRange(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
181 if ((wndPtr->dwStyle & WS_HSCROLL) && (lphl->ItemsPerColumn != 0))
182 SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
183 lphl->ItemsPerColumn + 1, TRUE);
185 if (repaint && lphl->bRedrawFlag) InvalidateRect32( hwnd, NULL, TRUE );
188 /* Returns: 0 if nothing needs to be changed */
189 /* 1 if FirstVisible changed */
191 int ListBoxScrollToFocus(LPHEADLIST lphl)
193 short end;
195 if (lphl->ItemsCount == 0) return 0;
196 if (lphl->ItemFocused == -1) return 0;
198 end = lphl->FirstVisible + lphl->ItemsVisible - 1;
200 if (lphl->ItemFocused < lphl->FirstVisible ) {
201 lphl->FirstVisible = lphl->ItemFocused;
202 return 1;
203 } else {
204 if (lphl->ItemFocused > end) {
205 WORD maxFirstVisible = ListMaxFirstVisible(lphl);
207 lphl->FirstVisible = lphl->ItemFocused;
209 if (lphl->FirstVisible > maxFirstVisible) {
210 lphl->FirstVisible = maxFirstVisible;
212 return 1;
215 return 0;
219 LPLISTSTRUCT ListBoxGetItem(LPHEADLIST lphl, UINT uIndex)
221 LPLISTSTRUCT lpls;
222 UINT Count = 0;
224 if (uIndex >= lphl->ItemsCount) return NULL;
226 lpls = lphl->lpFirst;
227 while (Count++ < uIndex) lpls = lpls->lpNext;
228 return lpls;
232 void ListBoxDrawItem (HWND hwnd, LPHEADLIST lphl, HDC hdc, LPLISTSTRUCT lpls,
233 RECT16 *rect, WORD itemAction, WORD itemState)
235 if (lphl->OwnerDrawn)
237 DRAWITEMSTRUCT32 dis;
239 dis.CtlID = lpls->mis.CtlID;
240 dis.CtlType = lpls->mis.CtlType;
241 dis.itemID = lpls->mis.itemID;
242 dis.hDC = hdc;
243 dis.hwndItem = hwnd;
244 dis.itemData = lpls->mis.itemData;
245 dis.itemAction = itemAction;
246 dis.itemState = itemState;
247 CONV_RECT16TO32( rect, &dis.rcItem );
248 SendMessage32A( lphl->hParent, WM_DRAWITEM, 0, (LPARAM)&dis );
249 return;
251 if (itemAction == ODA_DRAWENTIRE || itemAction == ODA_SELECT) {
252 int OldBkMode;
253 DWORD dwOldTextColor = 0;
255 OldBkMode = SetBkMode(hdc, TRANSPARENT);
257 if (itemState != 0) {
258 dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
259 FillRect16(hdc, rect, GetStockObject(BLACK_BRUSH));
262 if (lphl->dwStyle & LBS_USETABSTOPS) {
263 TabbedTextOut(hdc, rect->left + 5, rect->top + 2,
264 (char *)lpls->itemText, strlen((char *)lpls->itemText),
265 lphl->iNumStops, lphl->TabStops, 0);
266 } else {
267 TextOut16(hdc, rect->left + 5, rect->top + 2,
268 (char *)lpls->itemText, strlen((char *)lpls->itemText));
271 if (itemState != 0) {
272 SetTextColor(hdc, dwOldTextColor);
275 SetBkMode(hdc, OldBkMode);
277 else DrawFocusRect16(hdc, rect);
281 int ListBoxFindMouse(LPHEADLIST lphl, int X, int Y)
283 LPLISTSTRUCT lpls = lphl->lpFirst;
284 int i, j;
285 POINT16 point;
287 point.x = X; point.y = Y;
288 if (lphl->ItemsCount == 0) return LB_ERR;
290 for(i = 0; i < lphl->FirstVisible; i++) {
291 if (lpls == NULL) return LB_ERR;
292 lpls = lpls->lpNext;
294 for(j = 0; j < lphl->ItemsVisible; i++, j++) {
295 if (lpls == NULL) return LB_ERR;
296 if (PtInRect16(&lpls->itemRect,point)) {
297 return i;
299 lpls = lpls->lpNext;
301 dprintf_listbox(stddeb,"ListBoxFindMouse: not found\n");
302 return LB_ERR;
306 void ListBoxAskMeasure(LPHEADLIST lphl, LPLISTSTRUCT lpls)
308 HANDLE hTemp = USER_HEAP_ALLOC( sizeof(MEASUREITEMSTRUCT) );
309 MEASUREITEMSTRUCT *lpmeasure = (MEASUREITEMSTRUCT *) USER_HEAP_LIN_ADDR(hTemp);
311 if (lpmeasure == NULL) {
312 fprintf(stdnimp,"ListBoxAskMeasure() out of memory !\n");
313 return;
316 *lpmeasure = lpls->mis;
317 lpmeasure->itemHeight = lphl->StdItemHeight;
318 SendMessage16(lphl->hParent, WM_MEASUREITEM, 0, (LPARAM)USER_HEAP_SEG_ADDR(hTemp));
320 if (lphl->dwStyle & LBS_OWNERDRAWFIXED) {
321 if (lpmeasure->itemHeight > lphl->StdItemHeight)
322 lphl->StdItemHeight = lpmeasure->itemHeight;
323 lpls->mis.itemHeight = lpmeasure->itemHeight;
326 USER_HEAP_FREE(hTemp);
329 /* -------------------- strings and item data ---------------------- */
331 LPLISTSTRUCT ListBoxCreateItem(LPHEADLIST lphl, int id)
333 LPLISTSTRUCT lplsnew = (LPLISTSTRUCT)malloc(sizeof(LISTSTRUCT));
335 if (lplsnew == NULL) return NULL;
337 lplsnew->itemState = 0;
338 lplsnew->mis.CtlType = lphl->DrawCtlType;
339 lplsnew->mis.CtlID = lphl->CtlID;
340 lplsnew->mis.itemID = id;
341 lplsnew->mis.itemHeight = lphl->StdItemHeight;
342 lplsnew->mis.itemWidth = 0; /* ignored */
343 lplsnew->mis.itemData = 0;
344 SetRectEmpty16( &lplsnew->itemRect );
346 return lplsnew;
351 int ListBoxInsertString(LPHEADLIST lphl, UINT uIndex, LPCSTR newstr)
353 LPLISTSTRUCT *lppls, lplsnew, lpls;
354 HANDLE hStr;
355 LPSTR str;
356 UINT Count;
358 dprintf_listbox(stddeb,"ListBoxInsertString(%d, %p);\n", uIndex, newstr);
360 if (!newstr) return -1;
362 if (uIndex == (UINT)-1)
363 uIndex = lphl->ItemsCount;
365 lppls = &lphl->lpFirst;
366 for(Count = 0; Count < uIndex; Count++) {
367 if (*lppls == NULL) return LB_ERR;
368 lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
371 lplsnew = ListBoxCreateItem(lphl, Count);
373 if (lplsnew == NULL) {
374 fprintf(stdnimp,"ListBoxInsertString() out of memory !\n");
375 return LB_ERRSPACE;
378 lplsnew->lpNext = *lppls;
379 *lppls = lplsnew;
380 lphl->ItemsCount++;
382 hStr = 0;
383 if (lphl->HasStrings) {
384 dprintf_listbox(stddeb," string: %s\n", newstr);
385 hStr = LIST_HEAP_ALLOC(lphl, LMEM_MOVEABLE, strlen(newstr) + 1);
386 str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
387 if (str == NULL) return LB_ERRSPACE;
388 strcpy(str, newstr);
389 lplsnew->itemText = str;
390 /* I'm not so sure about the next one */
391 lplsnew->mis.itemData = 0;
392 } else {
393 lplsnew->itemText = NULL;
394 lplsnew->mis.itemData = (DWORD)newstr;
397 lplsnew->mis.itemID = uIndex;
398 lplsnew->hData = hStr;
400 /* adjust the itemID field of the following entries */
401 for(lpls = lplsnew->lpNext; lpls != NULL; lpls = lpls->lpNext) {
402 lpls->mis.itemID++;
405 if (lphl->needMeasure) {
406 ListBoxAskMeasure(lphl, lplsnew);
409 dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
410 return uIndex;
414 int ListBoxAddString(LPHEADLIST lphl, LPCSTR newstr)
416 UINT pos = (UINT) -1;
418 if (lphl->HasStrings && (lphl->dwStyle & LBS_SORT)) {
419 LPLISTSTRUCT lpls = lphl->lpFirst;
420 for (pos = 0; lpls != NULL; lpls = lpls->lpNext, pos++)
421 if (strcmp(lpls->itemText, newstr) >= 0)
422 break;
424 return ListBoxInsertString(lphl, pos, newstr);
428 int ListBoxGetText(LPHEADLIST lphl, UINT uIndex, LPSTR OutStr)
430 LPLISTSTRUCT lpls;
432 if (!OutStr) {
433 dprintf_listbox(stddeb, "ListBoxGetText // OutStr==NULL\n");
434 return 0;
436 *OutStr = '\0';
437 lpls = ListBoxGetItem (lphl, uIndex);
438 if (lpls == NULL) return LB_ERR;
440 if (!lphl->HasStrings) {
441 *((long *)OutStr) = lpls->mis.itemData;
442 return 4;
445 strcpy(OutStr, lpls->itemText);
446 return strlen(OutStr);
450 DWORD ListBoxGetItemData(LPHEADLIST lphl, UINT uIndex)
452 LPLISTSTRUCT lpls;
454 lpls = ListBoxGetItem (lphl, uIndex);
455 if (lpls == NULL) return LB_ERR;
456 return lpls->mis.itemData;
460 int ListBoxSetItemData(LPHEADLIST lphl, UINT uIndex, DWORD ItemData)
462 LPLISTSTRUCT lpls = ListBoxGetItem(lphl, uIndex);
464 if (lpls == NULL) return LB_ERR;
465 lpls->mis.itemData = ItemData;
466 return 1;
470 int ListBoxDeleteString(LPHEADLIST lphl, UINT uIndex)
472 LPLISTSTRUCT lpls, lpls2;
473 UINT Count;
475 if (uIndex >= lphl->ItemsCount) return LB_ERR;
477 lpls = lphl->lpFirst;
478 if (lpls == NULL) return LB_ERR;
480 if (uIndex == 0)
481 lphl->lpFirst = lpls->lpNext;
482 else {
483 LPLISTSTRUCT lpls2 = NULL;
484 for(Count = 0; Count < uIndex; Count++) {
485 if (lpls->lpNext == NULL) return LB_ERR;
487 lpls2 = lpls;
488 lpls = (LPLISTSTRUCT)lpls->lpNext;
490 lpls2->lpNext = lpls->lpNext;
493 /* adjust the itemID field of the following entries */
494 for(lpls2 = lpls->lpNext; lpls2 != NULL; lpls2 = lpls2->lpNext) {
495 lpls2->mis.itemID--;
498 lphl->ItemsCount--;
500 if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
501 free(lpls);
503 return lphl->ItemsCount;
507 int ListBoxFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr)
509 LPLISTSTRUCT lpls;
510 UINT Count;
511 UINT First = nFirst + 1;
512 LPSTR lpMatchStr = (LPSTR)MatchStr;
514 if (First > lphl->ItemsCount) return LB_ERR;
516 if (lphl->HasStrings) lpMatchStr = PTR_SEG_TO_LIN(MatchStr);
518 lpls = ListBoxGetItem(lphl, First);
519 Count = 0;
520 while(lpls != NULL) {
521 if (lphl->HasStrings) {
522 if (strstr(lpls->itemText, lpMatchStr) == lpls->itemText) return Count;
523 } else if (lphl->dwStyle & LBS_SORT) {
524 /* XXX Do a compare item */
526 else
527 if (lpls->mis.itemData == (DWORD)lpMatchStr) return Count;
529 lpls = lpls->lpNext;
530 Count++;
533 /* Start over at top */
534 Count = 0;
535 lpls = lphl->lpFirst;
537 while (Count < First) {
538 if (lphl->HasStrings) {
539 if (strstr(lpls->itemText, lpMatchStr) == lpls->itemText) return Count;
540 } else if (lphl->dwStyle & LBS_SORT) {
541 /* XXX Do a compare item */
542 } else {
543 if (lpls->mis.itemData == (DWORD)lpMatchStr) return Count;
545 lpls = lpls->lpNext;
546 Count++;
549 return LB_ERR;
553 int ListBoxResetContent(LPHEADLIST lphl)
555 LPLISTSTRUCT lpls;
556 int i;
558 if (lphl->ItemsCount == 0) return 0;
560 dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n",
561 lphl->ItemsCount);
563 for(i = 0; i < lphl->ItemsCount; i++) {
564 lpls = lphl->lpFirst;
565 if (lpls == NULL) return LB_ERR;
567 lphl->lpFirst = lpls->lpNext;
568 if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
569 free(lpls);
571 ListBoxInitialize(lphl);
573 return TRUE;
576 /* --------------------- selection ------------------------- */
578 int ListBoxSetCurSel(LPHEADLIST lphl, WORD wIndex)
580 LPLISTSTRUCT lpls;
582 /* use ListBoxSetSel instead */
583 if (lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ) return 0;
585 /* unselect previous item */
586 if (lphl->ItemFocused != -1) {
587 lphl->PrevFocused = lphl->ItemFocused;
588 lpls = ListBoxGetItem(lphl, lphl->ItemFocused);
589 if (lpls == 0) return LB_ERR;
590 lpls->itemState = 0;
593 if ((wIndex != (UINT)-1) && (wIndex < lphl->ItemsCount))
595 lphl->ItemFocused = wIndex;
596 lpls = ListBoxGetItem(lphl, wIndex);
597 if (lpls == 0) return LB_ERR;
598 lpls->itemState = ODS_SELECTED | ODS_FOCUS;
600 return 0;
603 return LB_ERR;
607 int ListBoxSetSel(LPHEADLIST lphl, WORD wIndex, WORD state)
609 LPLISTSTRUCT lpls;
610 int n = 0;
612 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
613 return LB_ERR;
615 if (wIndex == (UINT)-1) {
616 for (lpls = lphl->lpFirst; lpls != NULL; lpls = lpls->lpNext) {
617 if( lpls->itemState & ODS_SELECTED) n++;
618 lpls->itemState = state? lpls->itemState | ODS_SELECTED
619 : lpls->itemState & ~ODS_SELECTED;
621 return n;
624 if (wIndex >= lphl->ItemsCount) return LB_ERR;
626 lpls = ListBoxGetItem(lphl, wIndex);
627 lpls->itemState = state? lpls->itemState | ODS_SELECTED
628 : lpls->itemState & ~ODS_SELECTED;
630 return 0;
634 int ListBoxGetSel(LPHEADLIST lphl, WORD wIndex)
636 LPLISTSTRUCT lpls = ListBoxGetItem(lphl, wIndex);
638 if (lpls == NULL) return LB_ERR;
639 return lpls->itemState & ODS_SELECTED;
642 /* ------------------------- dir listing ------------------------ */
644 LONG ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPCSTR filespec)
646 char temp[16], mask[13];
647 char *path, *p;
648 const char *ptr;
649 int skip, count;
650 LONG ret;
651 DOS_DIRENT entry;
653 dprintf_listbox(stddeb, "ListBoxDirectory: '%s' %04x\n", filespec, attrib);
654 if (!filespec) return LB_ERR;
655 if (!(ptr = DOSFS_GetUnixFileName( filespec, FALSE ))) return LB_ERR;
656 path = xstrdup(ptr);
657 p = strrchr( path, '/' );
658 *p++ = '\0';
659 if (!(ptr = DOSFS_ToDosFCBFormat( p )))
661 free( path );
662 return LB_ERR;
664 strcpy( mask, ptr );
666 dprintf_listbox(stddeb, "ListBoxDirectory: path=%s mask=%s\n", path, mask);
668 skip = ret = 0;
669 attrib &= ~FA_LABEL;
670 while ((count = DOSFS_FindNext( path, mask, 0, attrib, skip, &entry )) > 0)
672 skip += count;
673 if (entry.attr & FA_DIRECTORY)
675 if ((attrib & DDL_DIRECTORY) && strcmp(entry.name, ". "))
677 sprintf(temp, "[%s]", DOSFS_ToDosDTAFormat( entry.name ) );
678 AnsiLower( temp );
679 if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
682 else /* not a directory */
684 if (!(attrib & DDL_EXCLUSIVE) ||
685 ((attrib & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)) ==
686 (entry.attr & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE))))
688 strcpy( temp, DOSFS_ToDosDTAFormat( entry.name ) );
689 AnsiLower( temp );
690 if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
694 if (attrib & DDL_DRIVES)
696 int x;
697 strcpy( temp, "[-a-]" );
698 for (x = 0; x < MAX_DOS_DRIVES; x++, temp[2]++)
700 if (DRIVE_IsValid(x))
701 if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
704 free( path );
705 return ret;
708 /* ------------------------- dimensions ------------------------- */
710 int ListBoxGetItemRect(LPHEADLIST lphl, WORD wIndex, LPRECT16 lprect)
712 LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wIndex);
714 if (lpls == NULL) return LB_ERR;
715 *lprect = lpls->itemRect;
716 return 0;
720 int ListBoxSetItemHeight(LPHEADLIST lphl, WORD wIndex, long height)
722 LPLISTSTRUCT lpls;
724 if (!(lphl->dwStyle & LBS_OWNERDRAWVARIABLE)) {
725 lphl->StdItemHeight = (short)height;
726 return 0;
729 lpls = ListBoxGetItem(lphl, wIndex);
730 if (lpls == NULL) return LB_ERR;
732 lpls->mis.itemHeight = height;
733 return 0;
736 /* -------------------------- string search ------------------------ */
738 int ListBoxFindNextMatch(LPHEADLIST lphl, WORD wChar)
740 LPLISTSTRUCT lpls;
741 UINT count,first;
743 if ((char)wChar < ' ') return LB_ERR;
744 if (!lphl->HasStrings) return LB_ERR;
746 lpls = lphl->lpFirst;
748 for (count = 0; lpls != NULL; lpls = lpls->lpNext, count++) {
749 if (tolower(*lpls->itemText) == tolower((char)wChar)) break;
751 if (lpls == NULL) return LB_ERR;
752 first = count;
753 for(; lpls != NULL; lpls = lpls->lpNext, count++) {
754 if (*lpls->itemText != (char)wChar)
755 break;
756 if ((short) count > lphl->ItemFocused)
757 return count;
759 return first;
762 /***********************************************************************
763 * LBCreate
765 static LONG LBCreate(HWND hwnd, WORD wParam, LONG lParam)
767 LPHEADLIST lphl;
768 LONG dwStyle = GetWindowLong(hwnd,GWL_STYLE);
769 RECT16 rect;
771 CreateListBoxStruct(hwnd, ODT_LISTBOX, dwStyle, GetParent(hwnd));
772 lphl = ListBoxGetStorageHeader(hwnd);
773 dprintf_listbox(stddeb,"ListBox created: lphl = %p dwStyle = %04x:%04x\n",
774 lphl, HIWORD(dwStyle), LOWORD(dwStyle));
776 GetClientRect16(hwnd,&rect);
777 lphl->ColumnsWidth = rect.right - rect.left;
779 if (dwStyle & WS_VSCROLL)
780 SetScrollRange(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
781 if (dwStyle & WS_HSCROLL)
782 SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
784 return 0;
788 /***********************************************************************
789 * LBDestroy
791 static LONG LBDestroy(HWND hwnd, WORD wParam, LONG lParam)
793 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
795 ListBoxResetContent(lphl);
797 DestroyListBoxStruct(lphl);
798 dprintf_listbox(stddeb,"ListBox destroyed: lphl = %p\n",lphl);
799 return 0;
802 /***********************************************************************
803 * LBVScroll
805 static LONG LBVScroll(HWND hwnd, WORD wParam, LONG lParam)
807 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
808 int y;
810 dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
811 wParam, lParam);
812 y = lphl->FirstVisible;
814 switch(wParam) {
815 case SB_LINEUP:
816 if (lphl->FirstVisible > 0)
817 lphl->FirstVisible--;
818 break;
820 case SB_LINEDOWN:
821 lphl->FirstVisible++;
822 break;
824 case SB_PAGEUP:
825 if (lphl->FirstVisible > lphl->ItemsVisible) {
826 lphl->FirstVisible -= lphl->ItemsVisible;
827 } else {
828 lphl->FirstVisible = 0;
830 break;
832 case SB_PAGEDOWN:
833 lphl->FirstVisible += lphl->ItemsVisible;
834 break;
836 case SB_THUMBTRACK:
837 lphl->FirstVisible = LOWORD(lParam);
838 break;
841 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
842 lphl->FirstVisible = ListMaxFirstVisible(lphl);
844 if (y != lphl->FirstVisible) {
845 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
846 InvalidateRect32( hwnd, NULL, TRUE );
848 return 0;
851 /***********************************************************************
852 * LBHScroll
854 static LONG LBHScroll(HWND hwnd, WORD wParam, LONG lParam)
856 LPHEADLIST lphl;
857 int y;
859 dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
860 wParam, lParam);
861 lphl = ListBoxGetStorageHeader(hwnd);
862 y = lphl->FirstVisible;
863 switch(wParam) {
864 case SB_LINEUP:
865 if (lphl->FirstVisible > lphl->ItemsPerColumn) {
866 lphl->FirstVisible -= lphl->ItemsPerColumn;
867 } else {
868 lphl->FirstVisible = 0;
870 break;
871 case SB_LINEDOWN:
872 lphl->FirstVisible += lphl->ItemsPerColumn;
873 break;
874 case SB_PAGEUP:
875 if (lphl->ItemsPerColumn != 0) {
876 int lbsub = lphl->ItemsVisible / lphl->ItemsPerColumn * lphl->ItemsPerColumn;
877 if (lphl->FirstVisible > lbsub) {
878 lphl->FirstVisible -= lbsub;
879 } else {
880 lphl->FirstVisible = 0;
883 break;
884 case SB_PAGEDOWN:
885 if (lphl->ItemsPerColumn != 0)
886 lphl->FirstVisible += lphl->ItemsVisible /
887 lphl->ItemsPerColumn * lphl->ItemsPerColumn;
888 break;
889 case SB_THUMBTRACK:
890 lphl->FirstVisible = lphl->ItemsPerColumn * LOWORD(lParam);
891 break;
893 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
894 lphl->FirstVisible = ListMaxFirstVisible(lphl);
896 if (lphl->ItemsPerColumn != 0) {
897 lphl->FirstVisible = lphl->FirstVisible /
898 lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
899 if (y != lphl->FirstVisible) {
900 SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible /
901 lphl->ItemsPerColumn + 1, TRUE);
902 InvalidateRect32( hwnd, NULL, TRUE );
905 return 0;
908 /***********************************************************************
909 * LBLButtonDown
911 static LONG LBLButtonDown(HWND hwnd, WORD wParam, LONG lParam)
913 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
914 WORD wRet;
915 int y,n;
916 RECT16 rectsel;
918 SetFocus(hwnd);
919 SetCapture(hwnd);
921 lphl->PrevFocused = lphl->ItemFocused;
923 y = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
925 if (y == -1) return 0;
927 if (lphl->dwStyle & LBS_NOTIFY && y!= LB_ERR )
928 if( SendMessage16(lphl->hParent, WM_LBTRACKPOINT, y, lParam) )
929 return 0;
932 switch( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )
934 case LBS_MULTIPLESEL:
935 lphl->ItemFocused = y;
936 wRet = ListBoxGetSel(lphl, y);
937 ListBoxSetSel(lphl, y, !wRet);
938 break;
939 case LBS_EXTENDEDSEL:
940 /* should handle extended mode here and in kbd handler
943 if ( lphl->PrevFocused != y && y!= LB_ERR)
945 LPLISTSTRUCT lpls = ListBoxGetItem( lphl, lphl->ItemFocused = y );
946 n = ListBoxSetSel(lphl,-1,FALSE);
948 lpls->itemState = ODS_FOCUS | ODS_SELECTED;
950 if( n > 1 && n != LB_ERR )
951 InvalidateRect32( hwnd,NULL,TRUE );
953 else
954 return 0;
956 break;
957 case 0:
958 if( y!=lphl->ItemFocused )
959 ListBoxSetCurSel(lphl, y);
960 else
961 return 0;
962 break;
963 default:
964 fprintf(stdnimp,"Listbox: LBS_MULTIPLESEL and LBS_EXTENDEDSEL are on!\n");
965 return 0;
968 /* invalidate changed items */
969 if( lphl->dwStyle & LBS_MULTIPLESEL || y!=lphl->PrevFocused )
971 ListBoxGetItemRect(lphl, y, &rectsel);
972 InvalidateRect16( hwnd, &rectsel, TRUE );
974 if( lphl->PrevFocused!=-1 && y!=lphl->PrevFocused )
976 ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
977 InvalidateRect16( hwnd, &rectsel, TRUE );
980 #ifndef WINELIB
981 if (GetWindowLong(lphl->hSelf,GWL_EXSTYLE) & WS_EX_DRAGDETECT)
982 if( DragDetect(lphl->hSelf,MAKEPOINT16(lParam)) )
983 SendMessage16(lphl->hParent, WM_BEGINDRAG,0,0L);
984 #endif
985 return 0;
988 /***********************************************************************
989 * LBLButtonUp
991 static LONG LBLButtonUp(HWND hwnd, WORD wParam, LONG lParam)
993 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
995 if (GetCapture() == hwnd) ReleaseCapture();
997 if (lphl->PrevFocused != lphl->ItemFocused)
998 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1000 return 0;
1003 /***********************************************************************
1004 * LBRButtonUp
1006 static LONG LBRButtonUp(HWND hwnd, WORD wParam, LONG lParam)
1008 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1010 #ifdef WINELIB32
1011 SendMessage32A(lphl->hParent, WM_COMMAND,
1012 MAKEWPARAM(GetWindowWord(hwnd,GWW_ID),LBN_DBLCLK),
1013 (LPARAM)hwnd);
1014 #else
1015 SendMessage16(lphl->hParent, WM_COMMAND, GetWindowWord(hwnd,GWW_ID),
1016 MAKELONG(hwnd, LBN_DBLCLK));
1017 #endif
1019 return 0;
1022 /***********************************************************************
1023 * LBMouseMove
1025 static LONG LBMouseMove(HWND hwnd, WORD wParam, LONG lParam)
1027 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1028 int y,redraw_prev = 0;
1029 int iRet;
1030 RECT16 rect, rectsel; /* XXX Broken */
1032 dprintf_listbox(stddeb,"LBMouseMove %d %d\n",SLOWORD(lParam),SHIWORD(lParam));
1033 if ((wParam & MK_LBUTTON) != 0) {
1034 y = SHIWORD(lParam);
1035 if (y < LBMM_EDGE) {
1036 if (lphl->FirstVisible > 0) {
1037 lphl->FirstVisible--;
1038 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1039 InvalidateRect32( hwnd, NULL, TRUE );
1040 return 0;
1043 GetClientRect16(hwnd, &rect);
1044 if (y >= (rect.bottom-LBMM_EDGE)) {
1045 if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
1046 lphl->FirstVisible++;
1047 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1048 InvalidateRect32( hwnd, NULL, TRUE );
1049 return 0;
1052 if ((y > 0) && (y < (rect.bottom - LBMM_EDGE))) {
1053 if ((y < rectsel.top) || (y > rectsel.bottom)) {
1054 iRet = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
1055 if (iRet == lphl->ItemFocused || iRet == -1) {
1056 return 0;
1058 if (lphl->dwStyle & LBS_MULTIPLESEL) {
1059 lphl->ItemFocused = iRet;
1060 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1061 } else if ( lphl->dwStyle & LBS_EXTENDEDSEL )
1063 /* Fixme: extended selection mode */
1064 ListBoxSetSel( lphl, lphl->ItemFocused, 0);
1065 lphl->PrevFocused = lphl->ItemFocused;
1066 lphl->ItemFocused = iRet;
1067 ListBoxSetSel( lphl, iRet, TRUE);
1068 redraw_prev = 1;
1070 else
1072 ListBoxSetCurSel(lphl, (WORD)iRet);
1073 redraw_prev = 1;
1075 if( lphl->PrevFocused!=-1 && redraw_prev )
1077 ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
1078 InvalidateRect16( hwnd, &rectsel, TRUE );
1080 ListBoxGetItemRect(lphl, iRet, &rectsel);
1081 InvalidateRect16( hwnd, &rectsel, TRUE );
1086 return 0;
1089 /***********************************************************************
1090 * LBKeyDown
1092 * Doesn't yet handle properly VK_SHIFT with LB_EXTENDEDSEL
1094 static LONG LBKeyDown(HWND hwnd, WORD wParam, LONG lParam)
1096 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1097 WORD newFocused = 0xFFFF;
1098 RECT16 rect;
1100 ListBoxGetItemRect(lphl,lphl->ItemFocused,&rect);
1101 switch(wParam)
1103 case VK_HOME:
1104 case VK_END:
1105 case VK_LEFT:
1106 case VK_RIGHT:
1107 case VK_UP:
1108 case VK_DOWN:
1109 case VK_PRIOR:
1110 case VK_NEXT:
1111 if ( lphl->dwStyle & LBS_WANTKEYBOARDINPUT )
1113 newFocused = (WORD)(INT)SendMessage16(lphl->hParent,WM_VKEYTOITEM,
1114 wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
1115 if ( newFocused == 0xFFFE ) return 0L;
1117 if ( newFocused == 0xFFFF )
1119 newFocused = lphl->ItemFocused;
1121 /* nested switch */
1122 switch(wParam)
1124 case VK_HOME:
1125 newFocused = 0;
1126 break;
1127 case VK_END:
1128 newFocused = lphl->ItemsCount - 1;
1129 break;
1130 case VK_LEFT:
1131 if (lphl->dwStyle & LBS_MULTICOLUMN) {
1132 if (newFocused >= lphl->ItemsPerColumn) {
1133 newFocused -= lphl->ItemsPerColumn;
1134 } else {
1135 newFocused = 0;
1138 break;
1139 case VK_UP:
1140 if (newFocused > 0) newFocused--;
1141 break;
1142 case VK_RIGHT:
1143 if (lphl->dwStyle & LBS_MULTICOLUMN)
1144 newFocused += lphl->ItemsPerColumn;
1145 break;
1146 case VK_DOWN:
1147 newFocused++;
1148 break;
1149 case VK_PRIOR:
1150 if (newFocused > lphl->ItemsVisible)
1151 newFocused -= lphl->ItemsVisible;
1152 else newFocused = 0;
1153 break;
1154 case VK_NEXT:
1155 newFocused += lphl->ItemsVisible;
1156 break;
1157 default:
1158 return 0;
1160 /* end of nested switch */
1162 break;
1163 case VK_SPACE:
1164 if (lphl->dwStyle & LBS_MULTIPLESEL)
1166 WORD wRet = ListBoxGetSel(lphl, lphl->ItemFocused);
1167 ListBoxSetSel(lphl, lphl->ItemFocused, !wRet);
1169 return 0;
1171 /* chars are handled in LBChar */
1172 default:
1173 return 0;
1176 /* at this point newFocused is set up */
1178 if (newFocused >= lphl->ItemsCount)
1179 newFocused = lphl->ItemsCount - 1;
1181 if (!(lphl->dwStyle & LBS_MULTIPLESEL))
1183 ListBoxSetCurSel(lphl, newFocused);
1184 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1187 lphl->ItemFocused = newFocused;
1189 if( ListBoxScrollToFocus(lphl) || (lphl->dwStyle &
1190 (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) )
1191 InvalidateRect32( hwnd, NULL, TRUE );
1192 else
1194 InvalidateRect16( hwnd, &rect, TRUE );
1195 if( newFocused < 0x8000 )
1197 ListBoxGetItemRect(lphl, newFocused, &rect);
1198 InvalidateRect16( hwnd, &rect, TRUE );
1202 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1204 return 0;
1207 /***********************************************************************
1208 * LBChar
1210 static LONG LBChar(HWND hwnd, WORD wParam, LONG lParam)
1212 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1213 WORD newFocused = 0xFFFF;
1215 if ( (lphl->dwStyle & LBS_WANTKEYBOARDINPUT) && !(lphl->HasStrings))
1217 newFocused = (WORD)(INT)SendMessage16(lphl->hParent,WM_CHARTOITEM,
1218 wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
1219 if ( newFocused == 0xFFFE ) return 0L;
1222 if (newFocused == 0xFFFF )
1223 newFocused = ListBoxFindNextMatch(lphl, wParam);
1225 if (newFocused == (WORD)LB_ERR) return 0;
1227 if (newFocused >= lphl->ItemsCount)
1228 newFocused = lphl->ItemsCount - 1;
1230 if (!(lphl->dwStyle & LBS_MULTIPLESEL))
1232 ListBoxSetCurSel(lphl, newFocused);
1233 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1236 lphl->ItemFocused = newFocused;
1237 ListBoxScrollToFocus(lphl);
1238 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1240 InvalidateRect32( hwnd, NULL, TRUE );
1242 return 0;
1245 /***********************************************************************
1246 * LBSetRedraw
1248 static LONG LBSetRedraw(HWND hwnd, WORD wParam, LONG lParam)
1250 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1252 dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd=%04x w=%04x !\n",
1253 hwnd, wParam);
1254 lphl->bRedrawFlag = wParam;
1256 return 0;
1259 /***********************************************************************
1260 * LBSetFont
1262 static LONG LBSetFont(HWND hwnd, WPARAM wParam, LPARAM lParam)
1264 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1265 HDC hdc;
1267 if (wParam == 0)
1268 lphl->hFont = GetStockObject(SYSTEM_FONT);
1269 else
1270 lphl->hFont = (HFONT) wParam;
1272 /* a new font means possible new text height */
1273 /* does this mean the height of each entry must be separately changed? */
1274 /* or are we guaranteed to get a LBSetFont before the first insert/add? */
1275 if ((hdc = GetDC(0)))
1277 TEXTMETRIC tm;
1278 GetTextMetrics( hdc, &tm );
1279 lphl->StdItemHeight = tm.tmHeight;
1280 dprintf_listbox(stddeb,"LBSetFont: new font %d with height %d\n",
1281 lphl->hFont, lphl->StdItemHeight);
1282 ReleaseDC( 0, hdc );
1285 return 0;
1288 /***********************************************************************
1289 * LBPaint
1291 static LONG LBPaint(HWND hwnd, WORD wParam, LONG lParam)
1293 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1294 LPLISTSTRUCT lpls;
1295 PAINTSTRUCT16 ps;
1296 HBRUSH hBrush;
1297 HFONT hOldFont;
1298 HDC16 hdc = BeginPaint16( hwnd, &ps );
1299 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
1300 RECT16 rect, paintRect, scratchRect;
1301 int i, top, height, maxwidth, ipc;
1303 top = 0;
1305 if (!IsWindowVisible(hwnd) || !lphl->bRedrawFlag) {
1306 EndPaint16(hwnd, &ps);
1307 return 0;
1310 GetRgnBox16(dc->w.hGCClipRgn,&paintRect);
1311 GetClientRect16(hwnd, &rect);
1312 IntersectRect16(&paintRect,&rect,&paintRect);
1314 hOldFont = SelectObject(hdc, lphl->hFont);
1316 #ifdef WINELIB32
1317 hBrush = (HBRUSH) SendMessage16(lphl->hParent, WM_CTLCOLORLISTBOX, (WPARAM)hdc,
1318 (LPARAM)hwnd);
1319 #else
1320 hBrush = SendMessage16(lphl->hParent, WM_CTLCOLOR, hdc,
1321 MAKELONG(hwnd, CTLCOLOR_LISTBOX));
1322 #endif
1324 if (hBrush == 0) hBrush = GetStockObject(WHITE_BRUSH);
1326 FillRect16(hdc, &rect, hBrush);
1328 maxwidth = rect.right;
1329 if (lphl->dwStyle & LBS_MULTICOLUMN) {
1330 rect.right = lphl->ColumnsWidth;
1332 lpls = lphl->lpFirst;
1334 lphl->ItemsVisible = 0;
1335 lphl->ItemsPerColumn = ipc = 0;
1337 for(i = 0; i < lphl->ItemsCount; i++) {
1338 if (lpls == NULL) break;
1340 if (i >= lphl->FirstVisible) {
1341 height = lpls->mis.itemHeight;
1343 if (top > (rect.bottom-height+1)) {
1344 if (lphl->dwStyle & LBS_MULTICOLUMN) {
1345 lphl->ItemsPerColumn = MAX(lphl->ItemsPerColumn, ipc);
1346 ipc = 0;
1347 top = 0;
1348 rect.left += lphl->ColumnsWidth;
1349 rect.right += lphl->ColumnsWidth;
1350 if (rect.left > maxwidth) break;
1351 } else {
1352 break;
1356 lpls->itemRect.top = top;
1357 lpls->itemRect.bottom = top + height;
1358 lpls->itemRect.left = rect.left;
1359 lpls->itemRect.right = rect.right;
1361 if( IntersectRect16(&scratchRect,&paintRect,&lpls->itemRect) )
1363 dprintf_listbox(stddeb,"LBPaint: drawing item: %d %d %d %d %d\n",
1364 rect.left,top,rect.right,top+height,lpls->itemState);
1366 if (lphl->OwnerDrawn && (lphl->ItemFocused == i) && GetFocus() == hwnd)
1368 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS,
1369 lpls->itemState & ~ODS_FOCUS);
1370 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
1371 lpls->itemState & ~ODS_FOCUS);
1372 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS, lpls->itemState);
1374 else
1375 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
1376 lpls->itemState);
1379 top += height;
1380 lphl->ItemsVisible++;
1381 ipc++;
1384 lpls = lpls->lpNext;
1386 ListBoxUpdateWindow(hwnd,lphl,FALSE);
1387 SelectObject(hdc,hOldFont);
1388 EndPaint16( hwnd, &ps );
1389 return 0;
1392 /***********************************************************************
1393 * LBSetFocus
1395 static LONG LBSetFocus(HWND hwnd, WORD wParam, LONG lParam)
1397 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1399 dprintf_listbox(stddeb,"ListBox WM_SETFOCUS for %04x\n",hwnd);
1400 if(!(lphl->dwStyle & LBS_MULTIPLESEL) )
1401 if( lphl->ItemsCount && lphl->ItemFocused != -1)
1403 HDC hDC = GetDC(hwnd);
1404 HFONT hOldFont = SelectObject(hDC, lphl->hFont);
1405 LPLISTSTRUCT lpls;
1407 lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
1408 lpls->itemState |= ODS_FOCUS;
1410 ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
1411 SelectObject(hDC, hOldFont);
1412 ReleaseDC(hwnd,hDC);
1415 ListBoxSendNotification(lphl, LBN_SETFOCUS);
1417 return 0;
1420 /***********************************************************************
1421 * LBKillFocus
1423 static LONG LBKillFocus(HWND hwnd, WORD wParam, LONG lParam)
1425 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1427 dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS for %04x\n",hwnd);
1428 if (!(lphl->dwStyle & LBS_MULTIPLESEL))
1430 if( lphl->ItemsCount )
1431 if( lphl->ItemFocused != -1 )
1433 HDC hDC = GetDC(hwnd);
1434 HFONT hOldFont = SelectObject(hDC, lphl->hFont);
1435 LPLISTSTRUCT lpls;
1437 lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
1438 lpls->itemState &= ~ODS_FOCUS;
1440 ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
1441 SelectObject(hDC, hOldFont);
1442 ReleaseDC(hwnd,hDC);
1444 else
1445 dprintf_listbox(stddeb,"LBKillFocus: no focused item!\n");
1447 else
1448 InvalidateRect32( hwnd, NULL, TRUE );
1450 ListBoxSendNotification(lphl, LBN_KILLFOCUS);
1452 return 0;
1455 /***********************************************************************
1456 * LBResetContent
1458 static LONG LBResetContent(HWND hwnd, WORD wParam, LONG lParam)
1460 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1462 dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
1463 ListBoxResetContent(lphl);
1464 ListBoxUpdateWindow(hwnd, lphl, TRUE);
1465 return 0;
1468 /***********************************************************************
1469 * LBDir
1471 static LONG LBDir(HWND hwnd, WORD wParam, LONG lParam)
1473 LONG ret;
1474 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1475 dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
1477 ret = ListBoxDirectory(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
1478 ListBoxUpdateWindow(hwnd, lphl, TRUE);
1479 return ret;
1482 /***********************************************************************
1483 * LBAddString
1485 static LONG LBAddString(HWND hwnd, WORD wParam, LONG lParam)
1487 WORD wRet;
1488 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1490 if (lphl->HasStrings)
1491 wRet = ListBoxAddString(lphl, (LPCSTR)PTR_SEG_TO_LIN(lParam));
1492 else
1493 wRet = ListBoxAddString(lphl, (LPCSTR)lParam);
1495 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1496 return wRet;
1499 /***********************************************************************
1500 * LBGetText
1502 static LONG LBGetText(HWND hwnd, WORD wParam, LONG lParam)
1504 LONG wRet;
1505 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1507 dprintf_listbox(stddeb, "LB_GETTEXT wParam=%d\n",wParam);
1508 wRet = ListBoxGetText(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
1510 return wRet;
1513 /***********************************************************************
1514 * LBInsertString
1516 static LONG LBInsertString(HWND hwnd, WORD wParam, LONG lParam)
1518 WORD wRet;
1519 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1521 if (lphl->HasStrings)
1522 wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)PTR_SEG_TO_LIN(lParam));
1523 else
1524 wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)lParam);
1526 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1527 return wRet;
1530 /***********************************************************************
1531 * LBDeleteString
1533 static LONG LBDeleteString(HWND hwnd, WORD wParam, LONG lParam)
1535 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1536 LONG lRet = ListBoxDeleteString(lphl,wParam);
1538 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1539 return lRet;
1542 /***********************************************************************
1543 * LBFindString
1545 static LONG LBFindString(HWND hwnd, WORD wParam, LONG lParam)
1547 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1548 return ListBoxFindString(lphl, wParam, (SEGPTR)lParam);
1551 /***********************************************************************
1552 * LBGetCaretIndex
1554 static LONG LBGetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
1556 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1557 return lphl->ItemFocused;
1560 /***********************************************************************
1561 * LBGetCount
1563 static LONG LBGetCount(HWND hwnd, WORD wParam, LONG lParam)
1565 LPHEADLIST lphl;
1567 lphl = ListBoxGetStorageHeader(hwnd);
1568 return lphl->ItemsCount;
1571 /***********************************************************************
1572 * LBGetCurSel
1574 static LONG LBGetCurSel(HWND hwnd, WORD wParam, LONG lParam)
1576 LPHEADLIST lphl;
1578 lphl = ListBoxGetStorageHeader(hwnd);
1579 dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %i !\n",
1580 lphl->ItemFocused);
1581 return lphl->ItemFocused;
1584 /***********************************************************************
1585 * LBGetHorizontalExtent
1587 static LONG LBGetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
1589 return 0;
1592 /***********************************************************************
1593 * LBGetItemHeight
1595 static LONG LBGetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
1597 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1598 LPLISTSTRUCT lpls = ListBoxGetItem (lphl, wParam);
1600 if (lpls == NULL) return LB_ERR;
1601 return lpls->mis.itemHeight;
1604 /***********************************************************************
1605 * LBGetItemRect
1607 static LONG LBGetItemRect(HWND hwnd, WORD wParam, LONG lParam)
1609 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1610 return ListBoxGetItemRect(lphl, wParam, PTR_SEG_TO_LIN(lParam));
1613 /***********************************************************************
1614 * LBGetSel
1616 static LONG LBGetSel(HWND hwnd, WORD wParam, LONG lParam)
1618 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1619 int iSel = ListBoxGetSel(lphl, wParam);
1621 dprintf_listbox(stdnimp,"LBGetSel: item %u - %i\n",wParam,iSel);
1623 return (iSel)? 1 : 0;
1626 /***********************************************************************
1627 * LBGetSelCount
1629 static LONG LBGetSelCount(HWND hwnd, WORD wParam, LONG lParam)
1631 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1632 LPLISTSTRUCT lpls;
1633 int cnt = 0;
1634 int items = 0;
1636 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1637 return LB_ERR;
1639 for( lpls = lphl->lpFirst;
1640 lpls;
1641 lpls = lpls->lpNext )
1643 items++;
1644 if (lpls->itemState )
1645 cnt++;
1648 return cnt;
1651 /***********************************************************************
1652 * LBGetSelItems
1654 static LONG LBGetSelItems(HWND hwnd, WORD wParam, LONG lParam)
1656 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1657 LPLISTSTRUCT lpls;
1658 int cnt, idx;
1659 int *lpItems = PTR_SEG_TO_LIN(lParam);
1661 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1662 return LB_ERR;
1664 if (wParam == 0) return 0;
1666 lpls = lphl->lpFirst;
1667 cnt = 0; idx = 0;
1669 while (lpls != NULL) {
1670 if (lpls->itemState > 0) lpItems[cnt++] = idx;
1672 if (cnt == wParam) break;
1673 idx++;
1674 lpls = lpls->lpNext;
1677 return cnt;
1680 /***********************************************************************
1681 * LBGetTextLen
1683 static LONG LBGetTextLen(HWND hwnd, WORD wParam, LONG lParam)
1685 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1686 LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wParam);
1688 if (lpls == NULL || !lphl->HasStrings) return LB_ERR;
1689 return strlen(lpls->itemText);
1692 /***********************************************************************
1693 * LBGetDlgCode
1695 static LONG LBGetDlgCode(HWND hwnd, WORD wParam, LONG lParam)
1697 return DLGC_WANTARROWS | DLGC_WANTCHARS;
1700 /***********************************************************************
1701 * LBGetTopIndex
1703 static LONG LBGetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
1705 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1707 return lphl->FirstVisible;
1711 /***********************************************************************
1712 * LBSelectString
1714 static LONG LBSelectString(HWND hwnd, WORD wParam, LONG lParam)
1716 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1717 INT iRet;
1719 iRet = ListBoxFindString(lphl, wParam, (SEGPTR)lParam);
1721 if( iRet != LB_ERR)
1723 if( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )
1724 ListBoxSetSel(lphl,iRet,TRUE);
1725 else
1726 ListBoxSetCurSel(lphl,iRet);
1728 lphl->ItemFocused = iRet;
1729 InvalidateRect32( hwnd, 0, TRUE );
1731 return iRet;
1734 /***********************************************************************
1735 * LBSelItemRange
1737 static LONG LBSelItemRange(HWND hwnd, WORD wParam, LONG lParam)
1739 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1740 LPLISTSTRUCT lpls;
1741 WORD cnt;
1742 WORD first = LOWORD(lParam);
1743 WORD last = HIWORD(lParam);
1744 BOOL select = wParam;
1746 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1747 return LB_ERR;
1749 if (first >= lphl->ItemsCount ||
1750 last >= lphl->ItemsCount) return LB_ERR;
1752 lpls = lphl->lpFirst;
1753 cnt = 0;
1755 while (lpls != NULL) {
1756 if (cnt++ >= first)
1757 lpls->itemState = select ? lpls->itemState | ODS_SELECTED : 0;
1759 if (cnt > last)
1760 break;
1762 lpls = lpls->lpNext;
1765 return 0;
1768 /***********************************************************************
1769 * LBSetCaretIndex
1771 static LONG LBSetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
1773 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1774 int i;
1776 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )) return 0;
1778 dprintf_listbox(stddeb,"LBSetCaretIndex: hwnd %04x n=%i\n",hwnd,wParam);
1780 if (wParam >= lphl->ItemsCount) return LB_ERR;
1782 lphl->ItemFocused = wParam;
1783 i = ListBoxScrollToFocus (lphl);
1785 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1786 if(i)
1787 InvalidateRect32( hwnd, NULL, TRUE );
1789 return 1;
1792 /***********************************************************************
1793 * LBSetColumnWidth
1795 static LONG LBSetColumnWidth(HWND hwnd, WORD wParam, LONG lParam)
1797 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1798 lphl->ColumnsWidth = wParam;
1799 InvalidateRect32( hwnd, NULL, TRUE );
1800 return 0;
1803 /***********************************************************************
1804 * LBSetHorizontalExtent
1806 static LONG LBSetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
1808 return 0;
1811 /***********************************************************************
1812 * LBGetItemData
1814 static LONG LBGetItemData(HWND hwnd, WORD wParam, LONG lParam)
1816 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1817 dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
1818 return ListBoxGetItemData(lphl, wParam);
1821 /***********************************************************************
1822 * LBSetItemData
1824 static LONG LBSetItemData(HWND hwnd, WORD wParam, LONG lParam)
1826 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1827 dprintf_listbox(stddeb, "LB_SETITEMDATA wParam=%x lParam=%lx\n", wParam, lParam);
1828 return ListBoxSetItemData(lphl, wParam, lParam);
1831 /***********************************************************************
1832 * LBSetTabStops
1834 static LONG LBSetTabStops(HWND hwnd, WORD wParam, LONG lParam)
1836 LPHEADLIST lphl;
1838 lphl = ListBoxGetStorageHeader(hwnd);
1840 if (lphl->TabStops != NULL) {
1841 lphl->iNumStops = 0;
1842 free (lphl->TabStops);
1845 lphl->TabStops = malloc (wParam * sizeof (short));
1846 if (lphl->TabStops) {
1847 lphl->iNumStops = wParam;
1848 memcpy (lphl->TabStops, PTR_SEG_TO_LIN(lParam), wParam * sizeof (short));
1849 return TRUE;
1852 return FALSE;
1855 /***********************************************************************
1856 * LBSetCurSel
1858 static LONG LBSetCurSel(HWND hwnd, WORD wParam, LONG lParam)
1860 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1861 WORD wRet;
1863 dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n",
1864 wParam);
1866 wRet = ListBoxSetCurSel(lphl, wParam);
1868 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1869 InvalidateRect32( hwnd, NULL, TRUE );
1871 return wRet;
1874 /***********************************************************************
1875 * LBSetSel
1877 static LONG LBSetSel(HWND hwnd, WORD wParam, LONG lParam)
1879 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1880 RECT16 rect;
1881 int iRet;
1883 dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
1885 iRet = ListBoxSetSel(lphl, LOWORD(lParam), wParam);
1887 if( iRet > 1 ) InvalidateRect32( hwnd, NULL, TRUE );
1888 else if( iRet != LB_ERR )
1890 if( lphl->dwStyle & LBS_EXTENDEDSEL &&
1891 lphl->ItemFocused != LOWORD(lParam) )
1893 ListBoxGetItemRect(lphl, lphl->ItemFocused , &rect);
1894 InvalidateRect16( hwnd, &rect, TRUE );
1895 lphl->ItemFocused = LOWORD(lParam);
1897 ListBoxGetItemRect(lphl,LOWORD(lParam),&rect);
1898 InvalidateRect16( hwnd, &rect, TRUE );
1901 return (iRet == (WORD)LB_ERR)? LB_ERR: 0;
1904 /***********************************************************************
1905 * LBSetTopIndex
1907 static LONG LBSetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
1909 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1911 dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
1912 wParam);
1913 lphl->FirstVisible = wParam;
1914 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1916 InvalidateRect32( hwnd, NULL, TRUE );
1918 return 0;
1921 /***********************************************************************
1922 * LBSetItemHeight
1924 static LONG LBSetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
1926 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1927 WORD wRet;
1929 dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
1930 wRet = ListBoxSetItemHeight(lphl, wParam, lParam);
1931 InvalidateRect32( hwnd, NULL, TRUE );
1932 return wRet;
1935 /***********************************************************************
1936 * LBPassToParent
1938 static LRESULT LBPassToParent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1940 WND* ptrWnd = WIN_FindWndPtr(hwnd);
1942 if( ptrWnd )
1943 if( /* !(ptrWnd->dwExStyle & WS_EX_NOPARENTNOTIFY) && */
1944 ptrWnd->parent )
1945 return SendMessage16(ptrWnd->parent->hwndSelf,message,wParam,lParam);
1946 return 0;
1949 /***********************************************************************
1950 * ListBoxWndProc
1952 LRESULT ListBoxWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1954 switch (message) {
1955 case WM_CREATE: return LBCreate(hwnd, wParam, lParam);
1956 case WM_DESTROY: return LBDestroy(hwnd, wParam, lParam);
1957 case WM_GETDLGCODE: return LBGetDlgCode(hwnd, wParam, lParam);
1958 case WM_VSCROLL: return LBVScroll(hwnd, wParam, lParam);
1959 case WM_HSCROLL: return LBHScroll(hwnd, wParam, lParam);
1960 case WM_LBUTTONDOWN: return LBLButtonDown(hwnd, wParam, lParam);
1961 case WM_LBUTTONUP: return LBLButtonUp(hwnd, wParam, lParam);
1962 case WM_RBUTTONUP: return LBRButtonUp(hwnd, wParam, lParam);
1963 case WM_LBUTTONDBLCLK: return LBRButtonUp(hwnd, wParam, lParam);
1964 case WM_MOUSEMOVE: return LBMouseMove(hwnd, wParam, lParam);
1965 case WM_KEYDOWN: return LBKeyDown(hwnd, wParam, lParam);
1966 case WM_CHAR: return LBChar(hwnd, wParam, lParam);
1967 case WM_SETFONT: return LBSetFont(hwnd, wParam, lParam);
1968 case WM_SETREDRAW: return LBSetRedraw(hwnd, wParam, lParam);
1969 case WM_PAINT: return LBPaint(hwnd, wParam, lParam);
1970 case WM_SETFOCUS: return LBSetFocus(hwnd, wParam, lParam);
1971 case WM_KILLFOCUS: return LBKillFocus(hwnd, wParam, lParam);
1972 case LB_RESETCONTENT: return LBResetContent(hwnd, wParam, lParam);
1973 case LB_DIR: return LBDir(hwnd, wParam, lParam);
1974 case LB_ADDSTRING: return LBAddString(hwnd, wParam, lParam);
1975 case LB_INSERTSTRING: return LBInsertString(hwnd, wParam, lParam);
1976 case LB_DELETESTRING: return LBDeleteString(hwnd, wParam, lParam);
1977 case LB_FINDSTRING: return LBFindString(hwnd, wParam, lParam);
1978 case LB_GETCARETINDEX: return LBGetCaretIndex(hwnd, wParam, lParam);
1979 case LB_GETCOUNT: return LBGetCount(hwnd, wParam, lParam);
1980 case LB_GETCURSEL: return LBGetCurSel(hwnd, wParam, lParam);
1981 case LB_GETHORIZONTALEXTENT: return LBGetHorizontalExtent(hwnd, wParam, lParam);
1982 case LB_GETITEMDATA: return LBGetItemData(hwnd, wParam, lParam);
1983 case LB_GETITEMHEIGHT: return LBGetItemHeight(hwnd, wParam, lParam);
1984 case LB_GETITEMRECT: return LBGetItemRect(hwnd, wParam, lParam);
1985 case LB_GETSEL: return LBGetSel(hwnd, wParam, lParam);
1986 case LB_GETSELCOUNT: return LBGetSelCount(hwnd, wParam, lParam);
1987 case LB_GETSELITEMS: return LBGetSelItems(hwnd, wParam, lParam);
1988 case LB_GETTEXT: return LBGetText(hwnd, wParam, lParam);
1989 case LB_GETTEXTLEN: return LBGetTextLen(hwnd, wParam, lParam);
1990 case LB_GETTOPINDEX: return LBGetTopIndex(hwnd, wParam, lParam);
1991 case LB_SELECTSTRING: return LBSelectString(hwnd, wParam, lParam);
1992 case LB_SELITEMRANGE: return LBSelItemRange(hwnd, wParam, lParam);
1993 case LB_SETCARETINDEX: return LBSetCaretIndex(hwnd, wParam, lParam);
1994 case LB_SETCOLUMNWIDTH: return LBSetColumnWidth(hwnd, wParam, lParam);
1995 case LB_SETHORIZONTALEXTENT: return LBSetHorizontalExtent(hwnd, wParam, lParam);
1996 case LB_SETITEMDATA: return LBSetItemData(hwnd, wParam, lParam);
1997 case LB_SETTABSTOPS: return LBSetTabStops(hwnd, wParam, lParam);
1998 case LB_SETCURSEL: return LBSetCurSel(hwnd, wParam, lParam);
1999 case LB_SETSEL: return LBSetSel(hwnd, wParam, lParam);
2000 case LB_SETTOPINDEX: return LBSetTopIndex(hwnd, wParam, lParam);
2001 case LB_SETITEMHEIGHT: return LBSetItemHeight(hwnd, wParam, lParam);
2003 case WM_DROPFILES: return LBPassToParent(hwnd, message, wParam, lParam);
2005 /* these will have to be implemented for proper LBS_EXTENDEDSEL -
2007 * anchor item is an item that with caret (focused) item defines a
2008 * range of currently selected items when listbox is in the extended
2009 * selection mode.
2011 case LB_SETANCHORINDEX: return LB_SETANCHORINDEX; /* that's what Windows returns */
2012 case LB_GETANCHORINDEX: return 0;
2014 case WM_DROPOBJECT:
2015 case WM_QUERYDROPOBJECT:
2016 case WM_DRAGSELECT:
2017 case WM_DRAGMOVE:
2019 LPDRAGINFO lpDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN((SEGPTR)lParam);
2020 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
2022 lpDragInfo->l = ListBoxFindMouse(lphl,lpDragInfo->pt.x,
2023 lpDragInfo->pt.y);
2025 return LBPassToParent(hwnd, message, wParam, lParam);
2029 return DefWindowProc16(hwnd, message, wParam, lParam);
2033 /**********************************************************************
2034 * DlgDirSelect (USER.99)
2036 BOOL DlgDirSelect( HWND hDlg, LPSTR lpStr, INT id )
2038 char *buffer;
2039 INT i;
2041 dprintf_listbox( stddeb, "DlgDirSelect: %04x '%s' %d\n", hDlg, lpStr, id );
2042 if ((i = SendDlgItemMessage16( hDlg, id, LB_GETCURSEL, 0, 0 )) == LB_ERR)
2043 return FALSE;
2044 if (!(buffer = SEGPTR_ALLOC( 20 * sizeof(char) ))) return FALSE;
2045 SendDlgItemMessage16(hDlg, id, LB_GETTEXT, i, (LPARAM)SEGPTR_GET(buffer) );
2046 if (buffer[0] == '[') /* drive or directory */
2048 if (buffer[1] == '-') /* drive */
2050 lpStr[0] = buffer[2];
2051 lpStr[1] = ':';
2052 lpStr[2] = '\0';
2053 dprintf_listbox( stddeb, "Returning drive '%s'\n", lpStr );
2054 SEGPTR_FREE(buffer);
2055 return TRUE;
2057 strcpy( lpStr, buffer + 1 );
2058 lpStr[strlen(lpStr)-1] = '\\';
2059 dprintf_listbox( stddeb, "Returning directory '%s'\n", lpStr );
2060 SEGPTR_FREE(buffer);
2061 return TRUE;
2063 strcpy( lpStr, buffer );
2064 dprintf_listbox( stddeb, "Returning file '%s'\n", lpStr );
2065 SEGPTR_FREE(buffer);
2066 return FALSE;
2070 /**********************************************************************
2071 * DlgDirList (USER.100)
2073 INT DlgDirList( HWND hDlg, SEGPTR spec, INT idLBox, INT idStatic, UINT attrib )
2075 char *filespec = (char *)PTR_SEG_TO_LIN( spec );
2076 int drive;
2077 HWND hwnd;
2079 #define SENDMSG(msg,wparam,lparam) \
2080 ((attrib & DDL_POSTMSGS) ? PostMessage( hwnd, msg, wparam, lparam ) \
2081 : SendMessage16( hwnd, msg, wparam, lparam ))
2083 dprintf_listbox( stddeb, "DlgDirList: %04x '%s' %d %d %04x\n",
2084 hDlg, filespec ? filespec : "NULL",
2085 idLBox, idStatic, attrib );
2087 if (filespec && filespec[0] && (filespec[1] == ':'))
2089 drive = toupper( filespec[0] ) - 'A';
2090 filespec += 2;
2091 if (!DRIVE_SetCurrentDrive( drive )) return FALSE;
2093 else drive = DRIVE_GetCurrentDrive();
2095 if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
2097 char mask[20];
2099 if (!filespec[0]) strcpy( mask, "*.*" );
2100 else
2102 /* If the path exists and is a directory, chdir to it */
2103 if (DRIVE_Chdir( drive, filespec )) strcpy( mask, "*.*" );
2104 else
2106 char *p, *p2;
2107 p = filespec;
2108 if ((p2 = strrchr( p, '\\' ))) p = p2 + 1;
2109 if ((p2 = strrchr( p, '/' ))) p = p2 + 1;
2110 lstrcpyn( mask, p, sizeof(mask) );
2111 if (p != filespec)
2113 p[-1] = '\0';
2114 if (!DRIVE_Chdir( drive, filespec )) return FALSE;
2119 strcpy( (char *)PTR_SEG_TO_LIN(spec), mask );
2121 dprintf_listbox(stddeb, "ListBoxDirectory: path=%c:\\%s mask=%s\n",
2122 'A' + drive, DRIVE_GetDosCwd(drive), mask);
2124 SENDMSG( LB_RESETCONTENT, 0, 0 );
2125 if ((attrib & DDL_DIRECTORY) && !(attrib & DDL_EXCLUSIVE))
2127 char *temp;
2128 if (SENDMSG( LB_DIR, attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
2129 (LPARAM)spec ) == LB_ERR) return FALSE;
2130 if (!(temp = SEGPTR_ALLOC( 4*sizeof(char) ))) return FALSE;
2131 strcpy( temp, "*.*" );
2132 /* FIXME: this won't work with PostMessage(), as temp will */
2133 /* have been freed by the time we do a DispatchMessage(). */
2134 if (SENDMSG( LB_DIR, (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
2135 (LPARAM)SEGPTR_GET(temp) ) == LB_ERR)
2137 SEGPTR_FREE(temp);
2138 return FALSE;
2140 SEGPTR_FREE(temp);
2142 else
2144 if (SENDMSG( LB_DIR, attrib, (LPARAM)spec) == LB_ERR) return FALSE;
2148 if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
2150 char temp[512];
2151 int drive = DRIVE_GetCurrentDrive();
2152 strcpy( temp, "A:\\" );
2153 temp[0] += drive;
2154 lstrcpyn( temp + 3, DRIVE_GetDosCwd(drive), sizeof(temp)-3 );
2155 AnsiLower( temp );
2156 /* Can't use PostMessage() here, because the string is on the stack */
2157 SetDlgItemText32A( hDlg, idStatic, temp );
2159 return TRUE;
2160 #undef SENDMSG