Release 960414
[wine/dcerpc.git] / controls / listbox.c
blobdbec947a5786cb37a8f9d6b67385961bc16b9928
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 #if 0
134 HeapHandle = GlobalAlloc(GMEM_FIXED, LIST_HEAP_SIZE);
135 HeapBase = GlobalLock(HeapHandle);
136 HEAP_Init(&lphl->Heap, HeapBase, LIST_HEAP_SIZE);
137 #endif
138 /* WINELIBS list boxes do not operate on local heaps */
139 #ifndef WINELIB
140 lphl->HeapSel = GlobalAlloc(GMEM_FIXED,LIST_HEAP_SIZE);
141 LocalInit( lphl->HeapSel, 0, LIST_HEAP_SIZE-1);
142 #else
143 lphl->HeapSel = 0;
144 #endif
147 void DestroyListBoxStruct(LPHEADLIST lphl)
149 if (lphl->hDrawItemStruct)
150 USER_HEAP_FREE(lphl->hDrawItemStruct);
152 /* XXX need to free lphl->Heap */
153 GlobalFree(lphl->HeapSel);
154 free(lphl);
157 static LPHEADLIST ListBoxGetStorageHeader(HWND hwnd)
159 return (LPHEADLIST)GetWindowLong(hwnd,0);
162 /* Send notification "code" as part of a WM_COMMAND-message if hwnd
163 has the LBS_NOTIFY style */
164 void ListBoxSendNotification(LPHEADLIST lphl, WORD code)
166 if (lphl->dwStyle & LBS_NOTIFY)
167 #ifdef WINELIB32
168 SendMessage(lphl->hParent, WM_COMMAND,
169 MAKEWPARAM(lphl->CtlID,code), (LPARAM)lphl->hSelf);
170 #else
171 SendMessage(lphl->hParent, WM_COMMAND,
172 lphl->CtlID, MAKELONG(lphl->hSelf, code));
173 #endif
177 /* get the maximum value of lphl->FirstVisible */
178 int ListMaxFirstVisible(LPHEADLIST lphl)
180 int m = lphl->ItemsCount-lphl->ItemsVisible;
181 return (m < 0) ? 0 : m;
185 void ListBoxUpdateWindow(HWND hwnd, LPHEADLIST lphl, BOOL repaint)
187 SetScrollRange(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
188 if (lphl->ItemsPerColumn != 0) {
189 SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
190 lphl->ItemsPerColumn + 1, TRUE);
192 if (repaint && lphl->bRedrawFlag) {
193 InvalidateRect(hwnd, NULL, TRUE);
197 /* Returns: 0 if nothing needs to be changed */
198 /* 1 if FirstVisible changed */
200 int ListBoxScrollToFocus(LPHEADLIST lphl)
202 short end;
204 if (lphl->ItemsCount == 0) return 0;
205 if (lphl->ItemFocused == -1) return 0;
207 end = lphl->FirstVisible + lphl->ItemsVisible - 1;
209 if (lphl->ItemFocused < lphl->FirstVisible ) {
210 lphl->FirstVisible = lphl->ItemFocused;
211 return 1;
212 } else {
213 if (lphl->ItemFocused > end) {
214 WORD maxFirstVisible = ListMaxFirstVisible(lphl);
216 lphl->FirstVisible = lphl->ItemFocused;
218 if (lphl->FirstVisible > maxFirstVisible) {
219 lphl->FirstVisible = maxFirstVisible;
221 return 1;
224 return 0;
228 LPLISTSTRUCT ListBoxGetItem(LPHEADLIST lphl, UINT uIndex)
230 LPLISTSTRUCT lpls;
231 UINT Count = 0;
233 if (uIndex >= lphl->ItemsCount) return NULL;
235 lpls = lphl->lpFirst;
236 while (Count++ < uIndex) lpls = lpls->lpNext;
237 return lpls;
241 void ListBoxDrawItem (HWND hwnd, LPHEADLIST lphl, HDC hdc, LPLISTSTRUCT lpls,
242 RECT *rect, WORD itemAction, WORD itemState)
244 if (lphl->OwnerDrawn) {
245 DRAWITEMSTRUCT *dis = USER_HEAP_LIN_ADDR(lphl->hDrawItemStruct);
247 dis->CtlID = lpls->mis.CtlID;
248 dis->CtlType = lpls->mis.CtlType;
249 dis->itemID = lpls->mis.itemID;
250 dis->hDC = hdc;
251 dis->hwndItem = hwnd;
252 dis->itemData = lpls->mis.itemData;
253 dis->itemAction = itemAction;
254 dis->itemState = itemState;
255 dis->rcItem = *rect;
256 SendMessage(lphl->hParent, WM_DRAWITEM,
257 0, (LPARAM)USER_HEAP_SEG_ADDR(lphl->hDrawItemStruct));
258 } else {
259 if (itemAction == ODA_DRAWENTIRE || itemAction == ODA_SELECT) {
260 int OldBkMode;
261 DWORD dwOldTextColor = 0;
263 OldBkMode = SetBkMode(hdc, TRANSPARENT);
265 if (itemState != 0) {
266 dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
267 FillRect(hdc, rect, GetStockObject(BLACK_BRUSH));
270 if (lphl->dwStyle & LBS_USETABSTOPS) {
271 TabbedTextOut(hdc, rect->left + 5, rect->top + 2,
272 (char *)lpls->itemText, strlen((char *)lpls->itemText),
273 lphl->iNumStops, lphl->TabStops, 0);
274 } else {
275 TextOut(hdc, rect->left + 5, rect->top + 2,
276 (char *)lpls->itemText, strlen((char *)lpls->itemText));
279 if (itemState != 0) {
280 SetTextColor(hdc, dwOldTextColor);
283 SetBkMode(hdc, OldBkMode);
284 } else DrawFocusRect(hdc, rect);
287 return;
291 int ListBoxFindMouse(LPHEADLIST lphl, int X, int Y)
293 LPLISTSTRUCT lpls = lphl->lpFirst;
294 int i, j;
295 POINT point;
297 point.x = X; point.y = Y;
298 if (lphl->ItemsCount == 0) return LB_ERR;
300 for(i = 0; i < lphl->FirstVisible; i++) {
301 if (lpls == NULL) return LB_ERR;
302 lpls = lpls->lpNext;
304 for(j = 0; j < lphl->ItemsVisible; i++, j++) {
305 if (lpls == NULL) return LB_ERR;
306 if (PtInRect(&lpls->itemRect,point)) {
307 return i;
309 lpls = lpls->lpNext;
311 dprintf_listbox(stddeb,"ListBoxFindMouse: not found\n");
312 return LB_ERR;
316 void ListBoxAskMeasure(LPHEADLIST lphl, LPLISTSTRUCT lpls)
318 HANDLE hTemp = USER_HEAP_ALLOC( sizeof(MEASUREITEMSTRUCT) );
319 MEASUREITEMSTRUCT *lpmeasure = (MEASUREITEMSTRUCT *) USER_HEAP_LIN_ADDR(hTemp);
321 if (lpmeasure == NULL) {
322 fprintf(stdnimp,"ListBoxAskMeasure() out of memory !\n");
323 return;
326 *lpmeasure = lpls->mis;
327 lpmeasure->itemHeight = lphl->StdItemHeight;
328 SendMessage(lphl->hParent, WM_MEASUREITEM, 0, (LPARAM)USER_HEAP_SEG_ADDR(hTemp));
330 if (lphl->dwStyle & LBS_OWNERDRAWFIXED) {
331 lphl->StdItemHeight = lpmeasure->itemHeight;
332 lpls->mis.itemHeight = lpmeasure->itemHeight;
335 USER_HEAP_FREE(hTemp);
338 /* -------------------- strings and item data ---------------------- */
340 LPLISTSTRUCT ListBoxCreateItem(LPHEADLIST lphl, int id)
342 LPLISTSTRUCT lplsnew = (LPLISTSTRUCT)malloc(sizeof(LISTSTRUCT));
344 if (lplsnew == NULL) return NULL;
346 lplsnew->itemState = 0;
347 lplsnew->mis.CtlType = lphl->DrawCtlType;
348 lplsnew->mis.CtlID = lphl->CtlID;
349 lplsnew->mis.itemID = id;
350 lplsnew->mis.itemHeight = lphl->StdItemHeight;
351 lplsnew->mis.itemWidth = 0; /* ignored */
352 lplsnew->mis.itemData = 0;
353 SetRect(&lplsnew->itemRect, 0, 0, 0, 0);
355 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 SetScrollRange(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
787 SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
789 return 0;
793 /***********************************************************************
794 * LBDestroy
796 static LONG LBDestroy(HWND hwnd, WORD wParam, LONG lParam)
798 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
800 ListBoxResetContent(lphl);
802 DestroyListBoxStruct(lphl);
803 dprintf_listbox(stddeb,"ListBox destroyed: lphl = %p\n",lphl);
804 return 0;
807 /***********************************************************************
808 * LBVScroll
810 static LONG LBVScroll(HWND hwnd, WORD wParam, LONG lParam)
812 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
813 int y;
815 dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
816 wParam, lParam);
817 y = lphl->FirstVisible;
819 switch(wParam) {
820 case SB_LINEUP:
821 if (lphl->FirstVisible > 0)
822 lphl->FirstVisible--;
823 break;
825 case SB_LINEDOWN:
826 lphl->FirstVisible++;
827 break;
829 case SB_PAGEUP:
830 if (lphl->FirstVisible > lphl->ItemsVisible) {
831 lphl->FirstVisible -= lphl->ItemsVisible;
832 } else {
833 lphl->FirstVisible = 0;
835 break;
837 case SB_PAGEDOWN:
838 lphl->FirstVisible += lphl->ItemsVisible;
839 break;
841 case SB_THUMBTRACK:
842 lphl->FirstVisible = LOWORD(lParam);
843 break;
846 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
847 lphl->FirstVisible = ListMaxFirstVisible(lphl);
849 if (y != lphl->FirstVisible) {
850 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
851 InvalidateRect(hwnd, NULL, TRUE);
853 return 0;
856 /***********************************************************************
857 * LBHScroll
859 static LONG LBHScroll(HWND hwnd, WORD wParam, LONG lParam)
861 LPHEADLIST lphl;
862 int y;
864 dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
865 wParam, lParam);
866 lphl = ListBoxGetStorageHeader(hwnd);
867 y = lphl->FirstVisible;
868 switch(wParam) {
869 case SB_LINEUP:
870 if (lphl->FirstVisible > lphl->ItemsPerColumn) {
871 lphl->FirstVisible -= lphl->ItemsPerColumn;
872 } else {
873 lphl->FirstVisible = 0;
875 break;
876 case SB_LINEDOWN:
877 lphl->FirstVisible += lphl->ItemsPerColumn;
878 break;
879 case SB_PAGEUP:
880 if (lphl->ItemsPerColumn != 0) {
881 int lbsub = lphl->ItemsVisible / lphl->ItemsPerColumn * lphl->ItemsPerColumn;
882 if (lphl->FirstVisible > lbsub) {
883 lphl->FirstVisible -= lbsub;
884 } else {
885 lphl->FirstVisible = 0;
888 break;
889 case SB_PAGEDOWN:
890 if (lphl->ItemsPerColumn != 0)
891 lphl->FirstVisible += lphl->ItemsVisible /
892 lphl->ItemsPerColumn * lphl->ItemsPerColumn;
893 break;
894 case SB_THUMBTRACK:
895 lphl->FirstVisible = lphl->ItemsPerColumn * LOWORD(lParam);
896 break;
898 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
899 lphl->FirstVisible = ListMaxFirstVisible(lphl);
901 if (lphl->ItemsPerColumn != 0) {
902 lphl->FirstVisible = lphl->FirstVisible /
903 lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
904 if (y != lphl->FirstVisible) {
905 SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible /
906 lphl->ItemsPerColumn + 1, TRUE);
907 InvalidateRect(hwnd, NULL, TRUE);
910 return 0;
913 /***********************************************************************
914 * LBLButtonDown
916 static LONG LBLButtonDown(HWND hwnd, WORD wParam, LONG lParam)
918 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
919 WORD wRet;
920 int y,n;
921 RECT rectsel;
922 POINT tmpPOINT;
923 tmpPOINT.x = LOWORD(lParam); tmpPOINT.y = HIWORD(lParam);
925 SetFocus(hwnd);
926 SetCapture(hwnd);
928 lphl->PrevFocused = lphl->ItemFocused;
930 y = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
932 if (y == -1) return 0;
934 if (lphl->dwStyle & LBS_NOTIFY && y!= LB_ERR )
935 if( SendMessage(lphl->hParent, WM_LBTRACKPOINT, y, lParam) )
936 return 0;
939 switch( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )
941 case LBS_MULTIPLESEL:
942 lphl->ItemFocused = y;
943 wRet = ListBoxGetSel(lphl, y);
944 ListBoxSetSel(lphl, y, !wRet);
945 break;
946 case LBS_EXTENDEDSEL:
947 /* should handle extended mode here and in kbd handler
950 if ( lphl->PrevFocused != y && y!= LB_ERR)
952 LPLISTSTRUCT lpls = ListBoxGetItem( lphl, lphl->ItemFocused = y );
953 n = ListBoxSetSel(lphl,-1,FALSE);
955 lpls->itemState = ODS_FOCUS | ODS_SELECTED;
957 if( n > 1 && n != LB_ERR )
958 InvalidateRect(hwnd,NULL,TRUE);
960 else
961 return 0;
963 break;
964 case 0:
965 if( y!=lphl->ItemFocused )
966 ListBoxSetCurSel(lphl, y);
967 else
968 return 0;
969 break;
970 default:
971 fprintf(stdnimp,"Listbox: LBS_MULTIPLESEL and LBS_EXTENDEDSEL are on!\n");
972 return 0;
975 /* invalidate changed items */
976 if( lphl->dwStyle & LBS_MULTIPLESEL || y!=lphl->PrevFocused )
978 ListBoxGetItemRect(lphl, y, &rectsel);
979 InvalidateRect(hwnd, &rectsel, TRUE);
981 if( lphl->PrevFocused!=-1 && y!=lphl->PrevFocused )
983 ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
984 InvalidateRect(hwnd, &rectsel, TRUE);
987 #ifndef WINELIB
988 if (GetWindowLong(lphl->hSelf,GWL_EXSTYLE) & WS_EX_DRAGDETECT)
989 if( DragDetect(lphl->hSelf,tmpPOINT) )
990 SendMessage(lphl->hParent, WM_BEGINDRAG,0,0L);
991 #endif
992 return 0;
995 /***********************************************************************
996 * LBLButtonUp
998 static LONG LBLButtonUp(HWND hwnd, WORD wParam, LONG lParam)
1000 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1002 if (GetCapture() == hwnd) ReleaseCapture();
1004 if (lphl->PrevFocused != lphl->ItemFocused)
1005 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1007 return 0;
1010 /***********************************************************************
1011 * LBRButtonUp
1013 static LONG LBRButtonUp(HWND hwnd, WORD wParam, LONG lParam)
1015 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1017 #ifdef WINELIB32
1018 SendMessage(lphl->hParent, WM_COMMAND,
1019 MAKEWPARAM(GetWindowWord(hwnd,GWW_ID),LBN_DBLCLK),
1020 (LPARAM)hwnd);
1021 #else
1022 SendMessage(lphl->hParent, WM_COMMAND, GetWindowWord(hwnd,GWW_ID),
1023 MAKELONG(hwnd, LBN_DBLCLK));
1024 #endif
1026 return 0;
1029 /***********************************************************************
1030 * LBMouseMove
1032 static LONG LBMouseMove(HWND hwnd, WORD wParam, LONG lParam)
1034 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1035 int y,redraw_prev = 0;
1036 int iRet;
1037 RECT rect, rectsel; /* XXX Broken */
1039 dprintf_listbox(stddeb,"LBMouseMove %d %d\n",SLOWORD(lParam),SHIWORD(lParam));
1040 if ((wParam & MK_LBUTTON) != 0) {
1041 y = SHIWORD(lParam);
1042 if (y < LBMM_EDGE) {
1043 if (lphl->FirstVisible > 0) {
1044 lphl->FirstVisible--;
1045 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1046 InvalidateRect(hwnd, NULL, TRUE);
1047 return 0;
1050 GetClientRect(hwnd, &rect);
1051 if (y >= (rect.bottom-LBMM_EDGE)) {
1052 if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
1053 lphl->FirstVisible++;
1054 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1055 InvalidateRect(hwnd, NULL, TRUE);
1056 return 0;
1059 if ((y > 0) && (y < (rect.bottom - LBMM_EDGE))) {
1060 if ((y < rectsel.top) || (y > rectsel.bottom)) {
1061 iRet = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
1062 if (iRet == lphl->ItemFocused || iRet == -1) {
1063 return 0;
1065 if (lphl->dwStyle & LBS_MULTIPLESEL) {
1066 lphl->ItemFocused = iRet;
1067 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1068 } else if ( lphl->dwStyle & LBS_EXTENDEDSEL )
1070 /* Fixme: extended selection mode */
1071 ListBoxSetSel( lphl, lphl->ItemFocused, 0);
1072 lphl->PrevFocused = lphl->ItemFocused;
1073 lphl->ItemFocused = iRet;
1074 ListBoxSetSel( lphl, iRet, TRUE);
1075 redraw_prev = 1;
1077 else
1079 ListBoxSetCurSel(lphl, (WORD)iRet);
1080 redraw_prev = 1;
1082 if( lphl->PrevFocused!=-1 && redraw_prev )
1084 ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
1085 InvalidateRect(hwnd, &rectsel, TRUE);
1087 ListBoxGetItemRect(lphl, iRet, &rectsel);
1088 InvalidateRect(hwnd, &rectsel, TRUE);
1093 return 0;
1096 /***********************************************************************
1097 * LBKeyDown
1099 * Doesn't yet handle properly VK_SHIFT with LB_EXTENDEDSEL
1101 static LONG LBKeyDown(HWND hwnd, WORD wParam, LONG lParam)
1103 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1104 WORD newFocused = 0xFFFF;
1105 RECT rect;
1107 ListBoxGetItemRect(lphl,lphl->ItemFocused,&rect);
1108 switch(wParam)
1110 case VK_HOME:
1111 case VK_END:
1112 case VK_LEFT:
1113 case VK_RIGHT:
1114 case VK_UP:
1115 case VK_DOWN:
1116 case VK_PRIOR:
1117 case VK_NEXT:
1118 if ( lphl->dwStyle & LBS_WANTKEYBOARDINPUT )
1120 newFocused = (WORD)(INT)SendMessage(lphl->hParent,WM_VKEYTOITEM,
1121 wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
1122 if ( newFocused == 0xFFFE ) return 0L;
1124 if ( newFocused == 0xFFFF )
1126 newFocused = lphl->ItemFocused;
1128 /* nested switch */
1129 switch(wParam)
1131 case VK_HOME:
1132 newFocused = 0;
1133 break;
1134 case VK_END:
1135 newFocused = lphl->ItemsCount - 1;
1136 break;
1137 case VK_LEFT:
1138 if (lphl->dwStyle & LBS_MULTICOLUMN) {
1139 if (newFocused >= lphl->ItemsPerColumn) {
1140 newFocused -= lphl->ItemsPerColumn;
1141 } else {
1142 newFocused = 0;
1145 break;
1146 case VK_UP:
1147 if (newFocused > 0) newFocused--;
1148 break;
1149 case VK_RIGHT:
1150 if (lphl->dwStyle & LBS_MULTICOLUMN)
1151 newFocused += lphl->ItemsPerColumn;
1152 break;
1153 case VK_DOWN:
1154 newFocused++;
1155 break;
1156 case VK_PRIOR:
1157 if (newFocused > lphl->ItemsVisible)
1158 newFocused -= lphl->ItemsVisible;
1159 else newFocused = 0;
1160 break;
1161 case VK_NEXT:
1162 newFocused += lphl->ItemsVisible;
1163 break;
1164 default:
1165 return 0;
1167 /* end of nested switch */
1169 break;
1170 case VK_SPACE:
1171 if (lphl->dwStyle & LBS_MULTIPLESEL)
1173 WORD wRet = ListBoxGetSel(lphl, lphl->ItemFocused);
1174 ListBoxSetSel(lphl, lphl->ItemFocused, !wRet);
1176 return 0;
1178 /* chars are handled in LBChar */
1179 default:
1180 return 0;
1183 /* at this point newFocused is set up */
1185 if (newFocused >= lphl->ItemsCount)
1186 newFocused = lphl->ItemsCount - 1;
1188 if (!(lphl->dwStyle & LBS_MULTIPLESEL))
1190 ListBoxSetCurSel(lphl, newFocused);
1191 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1194 lphl->ItemFocused = newFocused;
1196 if( ListBoxScrollToFocus(lphl) || (lphl->dwStyle &
1197 (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) )
1198 InvalidateRect(hwnd, NULL, TRUE);
1199 else
1201 InvalidateRect(hwnd, &rect, TRUE);
1202 if( newFocused < 0x8000 )
1204 ListBoxGetItemRect(lphl, newFocused, &rect);
1205 InvalidateRect(hwnd, &rect, TRUE);
1209 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1211 return 0;
1214 /***********************************************************************
1215 * LBChar
1217 static LONG LBChar(HWND hwnd, WORD wParam, LONG lParam)
1219 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1220 WORD newFocused = 0xFFFF;
1222 if ( (lphl->dwStyle & LBS_WANTKEYBOARDINPUT) && !(lphl->HasStrings))
1224 newFocused = (WORD)(INT)SendMessage(lphl->hParent,WM_CHARTOITEM,
1225 wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
1226 if ( newFocused == 0xFFFE ) return 0L;
1229 if (newFocused == 0xFFFF )
1230 newFocused = ListBoxFindNextMatch(lphl, wParam);
1232 if (newFocused == (WORD)LB_ERR) return 0;
1234 if (newFocused >= lphl->ItemsCount)
1235 newFocused = lphl->ItemsCount - 1;
1237 if (!(lphl->dwStyle & LBS_MULTIPLESEL))
1239 ListBoxSetCurSel(lphl, newFocused);
1240 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1243 lphl->ItemFocused = newFocused;
1244 ListBoxScrollToFocus(lphl);
1245 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1247 InvalidateRect(hwnd, NULL, TRUE);
1249 return 0;
1252 /***********************************************************************
1253 * LBSetRedraw
1255 static LONG LBSetRedraw(HWND hwnd, WORD wParam, LONG lParam)
1257 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1259 dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd=%04x w=%04x !\n",
1260 hwnd, wParam);
1261 lphl->bRedrawFlag = wParam;
1263 return 0;
1266 /***********************************************************************
1267 * LBSetFont
1269 static LONG LBSetFont(HWND hwnd, WPARAM wParam, LPARAM lParam)
1271 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1272 HDC hdc;
1274 if (wParam == 0)
1275 lphl->hFont = GetStockObject(SYSTEM_FONT);
1276 else
1277 lphl->hFont = (HFONT) wParam;
1279 /* a new font means possible new text height */
1280 /* does this mean the height of each entry must be separately changed? */
1281 /* or are we guaranteed to get a LBSetFont before the first insert/add? */
1282 if ((hdc = GetDC(0)))
1284 TEXTMETRIC tm;
1285 GetTextMetrics( hdc, &tm );
1286 lphl->StdItemHeight = tm.tmHeight;
1287 dprintf_listbox(stddeb,"LBSetFont: new font %d with height %d\n",
1288 lphl->hFont, lphl->StdItemHeight);
1289 ReleaseDC( 0, hdc );
1292 return 0;
1295 /***********************************************************************
1296 * LBPaint
1298 static LONG LBPaint(HWND hwnd, WORD wParam, LONG lParam)
1300 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1301 LPLISTSTRUCT lpls;
1302 PAINTSTRUCT ps;
1303 HBRUSH hBrush;
1304 HFONT hOldFont;
1305 HDC hdc = BeginPaint( hwnd, &ps );
1306 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
1307 RECT rect, paintRect, scratchRect;
1308 int i, top, height, maxwidth, ipc;
1311 top = 0;
1313 if (!IsWindowVisible(hwnd) || !lphl->bRedrawFlag) {
1314 EndPaint(hwnd, &ps);
1315 return 0;
1318 GetRgnBox(dc->w.hGCClipRgn,&paintRect);
1319 GetClientRect(hwnd, &rect);
1320 IntersectRect(&paintRect,&rect,&paintRect);
1322 hOldFont = SelectObject(hdc, lphl->hFont);
1324 #ifdef WINELIB32
1325 hBrush = (HBRUSH) SendMessage(lphl->hParent, WM_CTLCOLORLISTBOX, (WPARAM)hdc,
1326 (LPARAM)hwnd);
1327 #else
1328 hBrush = SendMessage(lphl->hParent, WM_CTLCOLOR, hdc,
1329 MAKELONG(hwnd, CTLCOLOR_LISTBOX));
1330 #endif
1332 if (hBrush == 0) hBrush = GetStockObject(WHITE_BRUSH);
1334 FillRect(hdc, &rect, hBrush);
1336 maxwidth = rect.right;
1337 if (lphl->dwStyle & LBS_MULTICOLUMN) {
1338 rect.right = lphl->ColumnsWidth;
1340 lpls = lphl->lpFirst;
1342 lphl->ItemsVisible = 0;
1343 lphl->ItemsPerColumn = ipc = 0;
1345 for(i = 0; i < lphl->ItemsCount; i++) {
1346 if (lpls == NULL) break;
1348 if (i >= lphl->FirstVisible) {
1349 height = lpls->mis.itemHeight;
1351 if (top > (rect.bottom-height+1)) {
1352 if (lphl->dwStyle & LBS_MULTICOLUMN) {
1353 lphl->ItemsPerColumn = MAX(lphl->ItemsPerColumn, ipc);
1354 ipc = 0;
1355 top = 0;
1356 rect.left += lphl->ColumnsWidth;
1357 rect.right += lphl->ColumnsWidth;
1358 if (rect.left > maxwidth) break;
1359 } else {
1360 break;
1364 lpls->itemRect.top = top;
1365 lpls->itemRect.bottom = top + height;
1366 lpls->itemRect.left = rect.left;
1367 lpls->itemRect.right = rect.right;
1369 if( IntersectRect(&scratchRect,&paintRect,&lpls->itemRect) )
1371 dprintf_listbox(stddeb,"LBPaint: drawing item: %d %d %d %d %d\n",
1372 rect.left,top,rect.right,top+height,lpls->itemState);
1374 if (lphl->OwnerDrawn && (lphl->ItemFocused == i) && GetFocus() == hwnd)
1376 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS,
1377 lpls->itemState & ~ODS_FOCUS);
1378 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
1379 lpls->itemState & ~ODS_FOCUS);
1380 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS, lpls->itemState);
1382 else
1383 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
1384 lpls->itemState);
1387 top += height;
1388 lphl->ItemsVisible++;
1389 ipc++;
1392 lpls = lpls->lpNext;
1394 ListBoxUpdateWindow(hwnd,lphl,FALSE);
1395 SelectObject(hdc,hOldFont);
1396 EndPaint( hwnd, &ps );
1397 return 0;
1400 /***********************************************************************
1401 * LBSetFocus
1403 static LONG LBSetFocus(HWND hwnd, WORD wParam, LONG lParam)
1405 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1407 dprintf_listbox(stddeb,"ListBox WM_SETFOCUS for %04x\n",hwnd);
1408 if(!(lphl->dwStyle & LBS_MULTIPLESEL) )
1409 if( lphl->ItemsCount && lphl->ItemFocused != -1)
1411 HDC hDC = GetDC(hwnd);
1412 HFONT hOldFont = SelectObject(hDC, lphl->hFont);
1413 LPLISTSTRUCT lpls;
1415 lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
1416 lpls->itemState |= ODS_FOCUS;
1418 ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
1419 SelectObject(hDC, hOldFont);
1420 ReleaseDC(hwnd,hDC);
1423 ListBoxSendNotification(lphl, LBN_SETFOCUS);
1425 return 0;
1428 /***********************************************************************
1429 * LBKillFocus
1431 static LONG LBKillFocus(HWND hwnd, WORD wParam, LONG lParam)
1433 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1435 dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS for %04x\n",hwnd);
1436 if (!(lphl->dwStyle & LBS_MULTIPLESEL))
1438 if( lphl->ItemsCount )
1439 if( lphl->ItemFocused != -1 )
1441 HDC hDC = GetDC(hwnd);
1442 HFONT hOldFont = SelectObject(hDC, lphl->hFont);
1443 LPLISTSTRUCT lpls;
1445 lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
1446 lpls->itemState &= ~ODS_FOCUS;
1448 ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
1449 SelectObject(hDC, hOldFont);
1450 ReleaseDC(hwnd,hDC);
1452 else
1453 dprintf_listbox(stddeb,"LBKillFocus: no focused item!\n");
1455 else
1456 InvalidateRect(hwnd, NULL, TRUE);
1458 ListBoxSendNotification(lphl, LBN_KILLFOCUS);
1460 return 0;
1463 /***********************************************************************
1464 * LBResetContent
1466 static LONG LBResetContent(HWND hwnd, WORD wParam, LONG lParam)
1468 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1470 dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
1471 ListBoxResetContent(lphl);
1472 ListBoxUpdateWindow(hwnd, lphl, TRUE);
1473 return 0;
1476 /***********************************************************************
1477 * LBDir
1479 static LONG LBDir(HWND hwnd, WORD wParam, LONG lParam)
1481 LONG ret;
1482 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1483 dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
1485 ret = ListBoxDirectory(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
1486 ListBoxUpdateWindow(hwnd, lphl, TRUE);
1487 return ret;
1490 /***********************************************************************
1491 * LBAddString
1493 static LONG LBAddString(HWND hwnd, WORD wParam, LONG lParam)
1495 WORD wRet;
1496 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1498 if (lphl->HasStrings)
1499 wRet = ListBoxAddString(lphl, (LPCSTR)PTR_SEG_TO_LIN(lParam));
1500 else
1501 wRet = ListBoxAddString(lphl, (LPCSTR)lParam);
1503 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1504 return wRet;
1507 /***********************************************************************
1508 * LBGetText
1510 static LONG LBGetText(HWND hwnd, WORD wParam, LONG lParam)
1512 LONG wRet;
1513 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1515 dprintf_listbox(stddeb, "LB_GETTEXT wParam=%d\n",wParam);
1516 wRet = ListBoxGetText(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
1518 return wRet;
1521 /***********************************************************************
1522 * LBInsertString
1524 static LONG LBInsertString(HWND hwnd, WORD wParam, LONG lParam)
1526 WORD wRet;
1527 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1529 if (lphl->HasStrings)
1530 wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)PTR_SEG_TO_LIN(lParam));
1531 else
1532 wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)lParam);
1534 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1535 return wRet;
1538 /***********************************************************************
1539 * LBDeleteString
1541 static LONG LBDeleteString(HWND hwnd, WORD wParam, LONG lParam)
1543 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1544 LONG lRet = ListBoxDeleteString(lphl,wParam);
1546 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1547 return lRet;
1550 /***********************************************************************
1551 * LBFindString
1553 static LONG LBFindString(HWND hwnd, WORD wParam, LONG lParam)
1555 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1556 return ListBoxFindString(lphl, wParam, (SEGPTR)lParam);
1559 /***********************************************************************
1560 * LBGetCaretIndex
1562 static LONG LBGetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
1564 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1565 return lphl->ItemFocused;
1568 /***********************************************************************
1569 * LBGetCount
1571 static LONG LBGetCount(HWND hwnd, WORD wParam, LONG lParam)
1573 LPHEADLIST lphl;
1575 lphl = ListBoxGetStorageHeader(hwnd);
1576 return lphl->ItemsCount;
1579 /***********************************************************************
1580 * LBGetCurSel
1582 static LONG LBGetCurSel(HWND hwnd, WORD wParam, LONG lParam)
1584 LPHEADLIST lphl;
1586 lphl = ListBoxGetStorageHeader(hwnd);
1587 dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %i !\n",
1588 lphl->ItemFocused);
1589 return lphl->ItemFocused;
1592 /***********************************************************************
1593 * LBGetHorizontalExtent
1595 static LONG LBGetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
1597 return 0;
1600 /***********************************************************************
1601 * LBGetItemHeight
1603 static LONG LBGetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
1605 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1606 LPLISTSTRUCT lpls = ListBoxGetItem (lphl, wParam);
1608 if (lpls == NULL) return LB_ERR;
1609 return lpls->mis.itemHeight;
1612 /***********************************************************************
1613 * LBGetItemRect
1615 static LONG LBGetItemRect(HWND hwnd, WORD wParam, LONG lParam)
1617 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1618 return ListBoxGetItemRect(lphl, wParam, PTR_SEG_TO_LIN(lParam));
1621 /***********************************************************************
1622 * LBGetSel
1624 static LONG LBGetSel(HWND hwnd, WORD wParam, LONG lParam)
1626 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1627 int iSel = ListBoxGetSel(lphl, wParam);
1629 dprintf_listbox(stdnimp,"LBGetSel: item %u - %i\n",wParam,iSel);
1631 return (iSel)? 1 : 0;
1634 /***********************************************************************
1635 * LBGetSelCount
1637 static LONG LBGetSelCount(HWND hwnd, WORD wParam, LONG lParam)
1639 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1640 LPLISTSTRUCT lpls;
1641 int cnt = 0;
1642 int items = 0;
1644 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1645 return LB_ERR;
1647 for( lpls = lphl->lpFirst;
1648 lpls;
1649 lpls = lpls->lpNext )
1651 items++;
1652 if (lpls->itemState )
1653 cnt++;
1656 return cnt;
1659 /***********************************************************************
1660 * LBGetSelItems
1662 static LONG LBGetSelItems(HWND hwnd, WORD wParam, LONG lParam)
1664 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1665 LPLISTSTRUCT lpls;
1666 int cnt, idx;
1667 int *lpItems = PTR_SEG_TO_LIN(lParam);
1669 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1670 return LB_ERR;
1672 if (wParam == 0) return 0;
1674 lpls = lphl->lpFirst;
1675 cnt = 0; idx = 0;
1677 while (lpls != NULL) {
1678 if (lpls->itemState > 0) lpItems[cnt++] = idx;
1680 if (cnt == wParam) break;
1681 idx++;
1682 lpls = lpls->lpNext;
1685 return cnt;
1688 /***********************************************************************
1689 * LBGetTextLen
1691 static LONG LBGetTextLen(HWND hwnd, WORD wParam, LONG lParam)
1693 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1694 LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wParam);
1696 if (lpls == NULL || !lphl->HasStrings) return LB_ERR;
1697 return strlen(lpls->itemText);
1700 /***********************************************************************
1701 * LBGetDlgCode
1703 static LONG LBGetDlgCode(HWND hwnd, WORD wParam, LONG lParam)
1705 return DLGC_WANTARROWS | DLGC_WANTCHARS;
1708 /***********************************************************************
1709 * LBGetTopIndex
1711 static LONG LBGetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
1713 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1715 return lphl->FirstVisible;
1719 /***********************************************************************
1720 * LBSelectString
1722 static LONG LBSelectString(HWND hwnd, WORD wParam, LONG lParam)
1724 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1725 INT iRet;
1727 iRet = ListBoxFindString(lphl, wParam, (SEGPTR)lParam);
1729 if( iRet != LB_ERR)
1731 if( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )
1732 ListBoxSetSel(lphl,iRet,TRUE);
1733 else
1734 ListBoxSetCurSel(lphl,iRet);
1736 lphl->ItemFocused = iRet;
1737 InvalidateRect(hwnd,0,TRUE);
1739 return iRet;
1742 /***********************************************************************
1743 * LBSelItemRange
1745 static LONG LBSelItemRange(HWND hwnd, WORD wParam, LONG lParam)
1747 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1748 LPLISTSTRUCT lpls;
1749 WORD cnt;
1750 WORD first = LOWORD(lParam);
1751 WORD last = HIWORD(lParam);
1752 BOOL select = wParam;
1754 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1755 return LB_ERR;
1757 if (first >= lphl->ItemsCount ||
1758 last >= lphl->ItemsCount) return LB_ERR;
1760 lpls = lphl->lpFirst;
1761 cnt = 0;
1763 while (lpls != NULL) {
1764 if (cnt++ >= first)
1765 lpls->itemState = select ? lpls->itemState | ODS_SELECTED : 0;
1767 if (cnt > last)
1768 break;
1770 lpls = lpls->lpNext;
1773 return 0;
1776 /***********************************************************************
1777 * LBSetCaretIndex
1779 static LONG LBSetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
1781 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1782 int i;
1784 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )) return 0;
1786 dprintf_listbox(stddeb,"LBSetCaretIndex: hwnd %04x n=%i\n",hwnd,wParam);
1788 if (wParam >= lphl->ItemsCount) return LB_ERR;
1790 lphl->ItemFocused = wParam;
1791 i = ListBoxScrollToFocus (lphl);
1793 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1794 if(i)
1795 InvalidateRect(hwnd, NULL, TRUE);
1797 return 1;
1800 /***********************************************************************
1801 * LBSetColumnWidth
1803 static LONG LBSetColumnWidth(HWND hwnd, WORD wParam, LONG lParam)
1805 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1806 lphl->ColumnsWidth = wParam;
1807 InvalidateRect(hwnd,NULL,TRUE);
1808 return 0;
1811 /***********************************************************************
1812 * LBSetHorizontalExtent
1814 static LONG LBSetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
1816 return 0;
1819 /***********************************************************************
1820 * LBGetItemData
1822 static LONG LBGetItemData(HWND hwnd, WORD wParam, LONG lParam)
1824 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1825 dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
1826 return ListBoxGetItemData(lphl, wParam);
1829 /***********************************************************************
1830 * LBSetItemData
1832 static LONG LBSetItemData(HWND hwnd, WORD wParam, LONG lParam)
1834 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1835 dprintf_listbox(stddeb, "LB_SETITEMDATA wParam=%x lParam=%lx\n", wParam, lParam);
1836 return ListBoxSetItemData(lphl, wParam, lParam);
1839 /***********************************************************************
1840 * LBSetTabStops
1842 static LONG LBSetTabStops(HWND hwnd, WORD wParam, LONG lParam)
1844 LPHEADLIST lphl;
1846 lphl = ListBoxGetStorageHeader(hwnd);
1848 if (lphl->TabStops != NULL) {
1849 lphl->iNumStops = 0;
1850 free (lphl->TabStops);
1853 lphl->TabStops = malloc (wParam * sizeof (short));
1854 if (lphl->TabStops) {
1855 lphl->iNumStops = wParam;
1856 memcpy (lphl->TabStops, PTR_SEG_TO_LIN(lParam), wParam * sizeof (short));
1857 return TRUE;
1860 return FALSE;
1863 /***********************************************************************
1864 * LBSetCurSel
1866 static LONG LBSetCurSel(HWND hwnd, WORD wParam, LONG lParam)
1868 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1869 WORD wRet;
1871 dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n",
1872 wParam);
1874 wRet = ListBoxSetCurSel(lphl, wParam);
1876 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1877 InvalidateRect(hwnd, NULL, TRUE);
1879 return wRet;
1882 /***********************************************************************
1883 * LBSetSel
1885 static LONG LBSetSel(HWND hwnd, WORD wParam, LONG lParam)
1887 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1888 RECT rect;
1889 int iRet;
1891 dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
1893 iRet = ListBoxSetSel(lphl, LOWORD(lParam), wParam);
1895 if( iRet > 1 )
1896 InvalidateRect(hwnd, NULL, TRUE);
1897 else if( iRet != LB_ERR )
1899 if( lphl->dwStyle & LBS_EXTENDEDSEL &&
1900 lphl->ItemFocused != LOWORD(lParam) )
1902 ListBoxGetItemRect(lphl, lphl->ItemFocused , &rect);
1903 InvalidateRect(hwnd,&rect,TRUE);
1904 lphl->ItemFocused = LOWORD(lParam);
1906 ListBoxGetItemRect(lphl,LOWORD(lParam),&rect);
1907 InvalidateRect(hwnd,&rect,TRUE);
1910 return (iRet == (WORD)LB_ERR)? LB_ERR: 0;
1913 /***********************************************************************
1914 * LBSetTopIndex
1916 static LONG LBSetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
1918 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1920 dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
1921 wParam);
1922 lphl->FirstVisible = wParam;
1923 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1925 InvalidateRect(hwnd, NULL, TRUE);
1927 return 0;
1930 /***********************************************************************
1931 * LBSetItemHeight
1933 static LONG LBSetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
1935 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1936 WORD wRet;
1938 dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
1939 wRet = ListBoxSetItemHeight(lphl, wParam, lParam);
1940 InvalidateRect(hwnd,NULL,TRUE);
1941 return wRet;
1944 /***********************************************************************
1945 * LBPassToParent
1947 static LRESULT LBPassToParent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1949 WND* ptrWnd = WIN_FindWndPtr(hwnd);
1951 if( ptrWnd )
1952 if( /* !(ptrWnd->dwExStyle & WS_EX_NOPARENTNOTIFY) && */
1953 ptrWnd->parent )
1954 return SendMessage(ptrWnd->parent->hwndSelf,message,wParam,lParam);
1955 return 0;
1958 /***********************************************************************
1959 * ListBoxWndProc
1961 LRESULT ListBoxWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1963 switch (message) {
1964 case WM_CREATE: return LBCreate(hwnd, wParam, lParam);
1965 case WM_DESTROY: return LBDestroy(hwnd, wParam, lParam);
1966 case WM_GETDLGCODE: return LBGetDlgCode(hwnd, wParam, lParam);
1967 case WM_VSCROLL: return LBVScroll(hwnd, wParam, lParam);
1968 case WM_HSCROLL: return LBHScroll(hwnd, wParam, lParam);
1969 case WM_LBUTTONDOWN: return LBLButtonDown(hwnd, wParam, lParam);
1970 case WM_LBUTTONUP: return LBLButtonUp(hwnd, wParam, lParam);
1971 case WM_RBUTTONUP: return LBRButtonUp(hwnd, wParam, lParam);
1972 case WM_LBUTTONDBLCLK: return LBRButtonUp(hwnd, wParam, lParam);
1973 case WM_MOUSEMOVE: return LBMouseMove(hwnd, wParam, lParam);
1974 case WM_KEYDOWN: return LBKeyDown(hwnd, wParam, lParam);
1975 case WM_CHAR: return LBChar(hwnd, wParam, lParam);
1976 case WM_SETFONT: return LBSetFont(hwnd, wParam, lParam);
1977 case WM_SETREDRAW: return LBSetRedraw(hwnd, wParam, lParam);
1978 case WM_PAINT: return LBPaint(hwnd, wParam, lParam);
1979 case WM_SETFOCUS: return LBSetFocus(hwnd, wParam, lParam);
1980 case WM_KILLFOCUS: return LBKillFocus(hwnd, wParam, lParam);
1981 case LB_RESETCONTENT: return LBResetContent(hwnd, wParam, lParam);
1982 case LB_DIR: return LBDir(hwnd, wParam, lParam);
1983 case LB_ADDSTRING: return LBAddString(hwnd, wParam, lParam);
1984 case LB_INSERTSTRING: return LBInsertString(hwnd, wParam, lParam);
1985 case LB_DELETESTRING: return LBDeleteString(hwnd, wParam, lParam);
1986 case LB_FINDSTRING: return LBFindString(hwnd, wParam, lParam);
1987 case LB_GETCARETINDEX: return LBGetCaretIndex(hwnd, wParam, lParam);
1988 case LB_GETCOUNT: return LBGetCount(hwnd, wParam, lParam);
1989 case LB_GETCURSEL: return LBGetCurSel(hwnd, wParam, lParam);
1990 case LB_GETHORIZONTALEXTENT: return LBGetHorizontalExtent(hwnd, wParam, lParam);
1991 case LB_GETITEMDATA: return LBGetItemData(hwnd, wParam, lParam);
1992 case LB_GETITEMHEIGHT: return LBGetItemHeight(hwnd, wParam, lParam);
1993 case LB_GETITEMRECT: return LBGetItemRect(hwnd, wParam, lParam);
1994 case LB_GETSEL: return LBGetSel(hwnd, wParam, lParam);
1995 case LB_GETSELCOUNT: return LBGetSelCount(hwnd, wParam, lParam);
1996 case LB_GETSELITEMS: return LBGetSelItems(hwnd, wParam, lParam);
1997 case LB_GETTEXT: return LBGetText(hwnd, wParam, lParam);
1998 case LB_GETTEXTLEN: return LBGetTextLen(hwnd, wParam, lParam);
1999 case LB_GETTOPINDEX: return LBGetTopIndex(hwnd, wParam, lParam);
2000 case LB_SELECTSTRING: return LBSelectString(hwnd, wParam, lParam);
2001 case LB_SELITEMRANGE: return LBSelItemRange(hwnd, wParam, lParam);
2002 case LB_SETCARETINDEX: return LBSetCaretIndex(hwnd, wParam, lParam);
2003 case LB_SETCOLUMNWIDTH: return LBSetColumnWidth(hwnd, wParam, lParam);
2004 case LB_SETHORIZONTALEXTENT: return LBSetHorizontalExtent(hwnd, wParam, lParam);
2005 case LB_SETITEMDATA: return LBSetItemData(hwnd, wParam, lParam);
2006 case LB_SETTABSTOPS: return LBSetTabStops(hwnd, wParam, lParam);
2007 case LB_SETCURSEL: return LBSetCurSel(hwnd, wParam, lParam);
2008 case LB_SETSEL: return LBSetSel(hwnd, wParam, lParam);
2009 case LB_SETTOPINDEX: return LBSetTopIndex(hwnd, wParam, lParam);
2010 case LB_SETITEMHEIGHT: return LBSetItemHeight(hwnd, wParam, lParam);
2012 case WM_DROPFILES: return LBPassToParent(hwnd, message, wParam, lParam);
2014 /* these will have to be implemented for proper LBS_EXTENDEDSEL -
2016 * anchor item is an item that with caret (focused) item defines a
2017 * range of currently selected items when listbox is in the extended
2018 * selection mode.
2020 case LB_SETANCHORINDEX: return LB_SETANCHORINDEX; /* that's what Windows returns */
2021 case LB_GETANCHORINDEX: return 0;
2023 case WM_DROPOBJECT:
2024 case WM_QUERYDROPOBJECT:
2025 case WM_DRAGSELECT:
2026 case WM_DRAGMOVE:
2028 LPDRAGINFO lpDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN((SEGPTR)lParam);
2029 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
2031 lpDragInfo->l = ListBoxFindMouse(lphl,lpDragInfo->pt.x,
2032 lpDragInfo->pt.y);
2034 return LBPassToParent(hwnd, message, wParam, lParam);
2038 return DefWindowProc(hwnd, message, wParam, lParam);
2042 /**********************************************************************
2043 * DlgDirSelect (USER.99)
2045 BOOL DlgDirSelect( HWND hDlg, LPSTR lpStr, INT id )
2047 char buffer[20];
2048 INT i;
2050 dprintf_listbox( stddeb, "DlgDirSelect: %04x '%s' %d\n", hDlg, lpStr, id );
2051 if ((i = SendDlgItemMessage( hDlg, id, LB_GETCURSEL, 0, 0 )) == LB_ERR)
2052 return FALSE;
2053 SendDlgItemMessage( hDlg, id, LB_GETTEXT, i, (LPARAM)MAKE_SEGPTR(buffer) );
2054 if (buffer[0] == '[') /* drive or directory */
2056 if (buffer[1] == '-') /* drive */
2058 lpStr[0] = buffer[2];
2059 lpStr[1] = ':';
2060 lpStr[2] = '\0';
2061 dprintf_listbox( stddeb, "Returning drive '%s'\n", lpStr );
2062 return TRUE;
2064 strcpy( lpStr, buffer + 1 );
2065 lpStr[strlen(lpStr)-1] = '\\';
2066 dprintf_listbox( stddeb, "Returning directory '%s'\n", lpStr );
2067 return TRUE;
2069 strcpy( lpStr, buffer );
2070 dprintf_listbox( stddeb, "Returning file '%s'\n", lpStr );
2071 return FALSE;
2075 /**********************************************************************
2076 * DlgDirList (USER.100)
2078 INT DlgDirList( HWND hDlg, SEGPTR spec, INT idLBox, INT idStatic, UINT attrib )
2080 char *filespec = (char *)PTR_SEG_TO_LIN( spec );
2081 int drive;
2082 HWND hwnd;
2084 #define SENDMSG(msg,wparam,lparam) \
2085 ((attrib & DDL_POSTMSGS) ? PostMessage( hwnd, msg, wparam, lparam ) \
2086 : SendMessage( hwnd, msg, wparam, lparam ))
2088 dprintf_listbox( stddeb, "DlgDirList: %04x '%s' %d %d %04x\n",
2089 hDlg, filespec ? filespec : "NULL",
2090 idLBox, idStatic, attrib );
2092 if (filespec && filespec[0] && (filespec[1] == ':'))
2094 drive = toupper( filespec[0] ) - 'A';
2095 filespec += 2;
2096 if (!DRIVE_SetCurrentDrive( drive )) return FALSE;
2098 else drive = DRIVE_GetCurrentDrive();
2100 if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
2102 char mask[20];
2103 char temp[] = "*.*";
2105 if (!filespec[0]) strcpy( mask, "*.*" );
2106 else
2108 /* If the path exists and is a directory, chdir to it */
2109 if (DRIVE_Chdir( drive, filespec )) strcpy( mask, "*.*" );
2110 else
2112 char *p, *p2;
2113 p = filespec;
2114 if ((p2 = strrchr( p, '\\' ))) p = p2 + 1;
2115 if ((p2 = strrchr( p, '/' ))) p = p2 + 1;
2116 lstrcpyn( mask, p, sizeof(mask) );
2117 if (p != filespec)
2119 p[-1] = '\0';
2120 if (!DRIVE_Chdir( drive, filespec )) return FALSE;
2125 strcpy( (char *)PTR_SEG_TO_LIN(spec), mask );
2127 dprintf_listbox(stddeb, "ListBoxDirectory: path=%c:\\%s mask=%s\n",
2128 'A' + drive, DRIVE_GetDosCwd(drive), mask);
2130 SENDMSG( LB_RESETCONTENT, 0, 0 );
2131 if ((attrib & DDL_DIRECTORY) && !(attrib & DDL_EXCLUSIVE))
2133 if (SENDMSG( LB_DIR, attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
2134 (LPARAM)spec ) == LB_ERR) return FALSE;
2135 if (SENDMSG( LB_DIR, (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
2136 (LPARAM)MAKE_SEGPTR(temp) ) == LB_ERR) return FALSE;
2138 else
2140 if (SENDMSG( LB_DIR, attrib, (LPARAM)spec) == LB_ERR) return FALSE;
2144 if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
2146 char temp[256];
2147 strcpy( temp, "A:\\" );
2148 temp[0] += drive;
2149 lstrcpyn( temp+3, DRIVE_GetDosCwd(drive), 253 );
2150 AnsiLower( temp );
2151 SENDMSG( WM_SETTEXT, 0, (LPARAM)MAKE_SEGPTR(temp) );
2153 return TRUE;
2154 #undef SENDMSG