Release 960717
[wine.git] / controls / listbox.c
blobb3a5b8dda04bfc007812eeb79125e8a1c7040cbc
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 "win.h"
23 #include "gdi.h"
24 #include "msdos.h"
25 #include "listbox.h"
26 #include "dos_fs.h"
27 #include "drive.h"
28 #include "file.h"
29 #include "heap.h"
30 #include "stddebug.h"
31 #include "debug.h"
32 #include "xmalloc.h"
34 #define LIST_HEAP_ALLOC(lphl,f,size) \
35 LOCAL_Alloc( lphl->HeapSel, LMEM_FIXED, (size) )
36 #define LIST_HEAP_FREE(lphl,handle) \
37 LOCAL_Free( lphl->HeapSel, (handle) )
38 #define LIST_HEAP_ADDR(lphl,handle) \
39 ((handle) ? PTR_SEG_OFF_TO_LIN(lphl->HeapSel, (handle)) : NULL)
41 #define LIST_HEAP_SIZE 0x10000
43 #define LBMM_EDGE 4 /* distance inside box which is same as moving mouse
44 outside box, to trigger scrolling of LB */
46 static void ListBoxInitialize(LPHEADLIST lphl)
48 lphl->lpFirst = NULL;
49 lphl->ItemsCount = 0;
50 lphl->ItemsVisible = 0;
51 lphl->FirstVisible = 0;
52 lphl->ColumnsVisible = 1;
53 lphl->ItemsPerColumn = 0;
54 lphl->ItemFocused = -1;
55 lphl->PrevFocused = -1;
58 void CreateListBoxStruct(HWND hwnd, WORD CtlType, LONG styles, HWND parent)
60 LPHEADLIST lphl;
61 HDC hdc;
63 lphl = (LPHEADLIST)xmalloc(sizeof(HEADLIST));
64 SetWindowLong32A(hwnd, 0, (LONG)lphl);
65 ListBoxInitialize(lphl);
66 lphl->DrawCtlType = CtlType;
67 lphl->CtlID = GetWindowWord(hwnd,GWW_ID);
68 lphl->bRedrawFlag = TRUE;
69 lphl->iNumStops = 0;
70 lphl->TabStops = NULL;
71 lphl->hFont = GetStockObject(SYSTEM_FONT);
72 lphl->hSelf = hwnd;
73 if (CtlType==ODT_COMBOBOX) /* use the "faked" style for COMBOLBOX */
74 /* LBS_SORT instead CBS_SORT e.g. */
75 lphl->dwStyle = MAKELONG(LOWORD(styles),HIWORD(GetWindowLong32A(hwnd,GWL_STYLE)));
76 else
77 lphl->dwStyle = GetWindowLong32A(hwnd,GWL_STYLE); /* use original style dword */
78 lphl->hParent = parent;
79 lphl->StdItemHeight = 15; /* FIXME: should get the font height */
80 lphl->OwnerDrawn = styles & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE);
81 lphl->HasStrings = (styles & LBS_HASSTRINGS) || !lphl->OwnerDrawn;
83 /* create dummy hdc to set text height */
84 if ((hdc = GetDC(0)))
86 TEXTMETRIC16 tm;
87 GetTextMetrics16( hdc, &tm );
88 lphl->StdItemHeight = tm.tmHeight;
89 dprintf_listbox(stddeb,"CreateListBoxStruct: font height %d\n",
90 lphl->StdItemHeight);
91 ReleaseDC( 0, hdc );
94 if (lphl->OwnerDrawn)
96 LISTSTRUCT dummyls;
98 lphl->needMeasure = TRUE;
99 dummyls.mis.CtlType = lphl->DrawCtlType;
100 dummyls.mis.CtlID = lphl->CtlID;
101 dummyls.mis.itemID = -1;
102 dummyls.mis.itemWidth = 0; /* ignored */
103 dummyls.mis.itemData = 0;
105 ListBoxAskMeasure(lphl,&dummyls);
108 lphl->HeapSel = GlobalAlloc16(GMEM_FIXED,LIST_HEAP_SIZE);
109 LocalInit( lphl->HeapSel, 0, LIST_HEAP_SIZE-1);
112 void DestroyListBoxStruct(LPHEADLIST lphl)
114 /* XXX need to free lphl->Heap */
115 GlobalFree16(lphl->HeapSel);
116 free(lphl);
119 static LPHEADLIST ListBoxGetStorageHeader(HWND hwnd)
121 return (LPHEADLIST)GetWindowLong32A(hwnd,0);
124 /* Send notification "code" as part of a WM_COMMAND-message if hwnd
125 has the LBS_NOTIFY style */
126 void ListBoxSendNotification(LPHEADLIST lphl, WORD code)
128 if (lphl->dwStyle & LBS_NOTIFY)
129 SendMessage32A( lphl->hParent, WM_COMMAND,
130 MAKEWPARAM( lphl->CtlID, code), (LPARAM)lphl->hSelf );
134 /* get the maximum value of lphl->FirstVisible */
135 int ListMaxFirstVisible(LPHEADLIST lphl)
137 int m = lphl->ItemsCount-lphl->ItemsVisible;
138 return (m < 0) ? 0 : m;
142 void ListBoxUpdateWindow(HWND hwnd, LPHEADLIST lphl, BOOL repaint)
144 if (lphl->dwStyle & WS_VSCROLL)
145 SetScrollRange(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
146 if ((lphl->dwStyle & WS_HSCROLL) && (lphl->ItemsPerColumn != 0))
147 SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
148 lphl->ItemsPerColumn + 1, TRUE);
150 if (repaint && lphl->bRedrawFlag) InvalidateRect32( hwnd, NULL, TRUE );
153 /* Returns: 0 if nothing needs to be changed */
154 /* 1 if FirstVisible changed */
156 int ListBoxScrollToFocus(LPHEADLIST lphl)
158 short end;
160 if (lphl->ItemsCount == 0) return 0;
161 if (lphl->ItemFocused == -1) return 0;
163 end = lphl->FirstVisible + lphl->ItemsVisible - 1;
165 if (lphl->ItemFocused < lphl->FirstVisible ) {
166 lphl->FirstVisible = lphl->ItemFocused;
167 return 1;
168 } else {
169 if (lphl->ItemFocused > end) {
170 WORD maxFirstVisible = ListMaxFirstVisible(lphl);
172 lphl->FirstVisible = lphl->ItemFocused;
174 if (lphl->FirstVisible > maxFirstVisible) {
175 lphl->FirstVisible = maxFirstVisible;
177 return 1;
180 return 0;
184 LPLISTSTRUCT ListBoxGetItem(LPHEADLIST lphl, UINT uIndex)
186 LPLISTSTRUCT lpls;
187 UINT Count = 0;
189 if (uIndex >= lphl->ItemsCount) return NULL;
191 lpls = lphl->lpFirst;
192 while (Count++ < uIndex) lpls = lpls->lpNext;
193 return lpls;
197 void ListBoxDrawItem (HWND hwnd, LPHEADLIST lphl, HDC hdc, LPLISTSTRUCT lpls,
198 RECT16 *rect, WORD itemAction, WORD itemState)
200 if (lphl->OwnerDrawn)
202 DRAWITEMSTRUCT32 dis;
204 dis.CtlID = lpls->mis.CtlID;
205 dis.CtlType = lpls->mis.CtlType;
206 dis.itemID = lpls->mis.itemID;
207 dis.hDC = hdc;
208 dis.hwndItem = hwnd;
209 dis.itemData = lpls->mis.itemData;
210 dis.itemAction = itemAction;
211 dis.itemState = itemState;
212 CONV_RECT16TO32( rect, &dis.rcItem );
213 SendMessage32A( lphl->hParent, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis );
214 return;
216 if (itemAction == ODA_DRAWENTIRE || itemAction == ODA_SELECT) {
217 int OldBkMode;
218 DWORD dwOldTextColor = 0;
220 OldBkMode = SetBkMode(hdc, TRANSPARENT);
222 if (itemState != 0) {
223 dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
224 FillRect16(hdc, rect, GetStockObject(BLACK_BRUSH));
227 if (lphl->dwStyle & LBS_USETABSTOPS) {
228 TabbedTextOut(hdc, rect->left + 5, rect->top + 2,
229 (char *)lpls->itemText, strlen((char *)lpls->itemText),
230 lphl->iNumStops, lphl->TabStops, 0);
231 } else {
232 TextOut16(hdc, rect->left + 5, rect->top + 2,
233 (char *)lpls->itemText, strlen((char *)lpls->itemText));
236 if (itemState != 0) {
237 SetTextColor(hdc, dwOldTextColor);
240 SetBkMode(hdc, OldBkMode);
242 else DrawFocusRect16(hdc, rect);
246 int ListBoxFindMouse(LPHEADLIST lphl, int X, int Y)
248 LPLISTSTRUCT lpls = lphl->lpFirst;
249 int i, j;
250 POINT16 point;
252 point.x = X; point.y = Y;
253 if (lphl->ItemsCount == 0) return LB_ERR;
255 for(i = 0; i < lphl->FirstVisible; i++) {
256 if (lpls == NULL) return LB_ERR;
257 lpls = lpls->lpNext;
259 for(j = 0; j < lphl->ItemsVisible; i++, j++) {
260 if (lpls == NULL) return LB_ERR;
261 if (PtInRect16(&lpls->itemRect,point)) {
262 return i;
264 lpls = lpls->lpNext;
266 dprintf_listbox(stddeb,"ListBoxFindMouse: not found\n");
267 return LB_ERR;
271 void ListBoxAskMeasure(LPHEADLIST lphl, LPLISTSTRUCT lpls)
273 MEASUREITEMSTRUCT16 *lpmeasure = SEGPTR_NEW(MEASUREITEMSTRUCT16);
274 if (!lpmeasure) return;
275 *lpmeasure = lpls->mis;
276 lpmeasure->itemHeight = lphl->StdItemHeight;
277 SendMessage16( lphl->hParent, WM_MEASUREITEM, lphl->CtlID,
278 (LPARAM)SEGPTR_GET(lpmeasure) );
280 if (lphl->dwStyle & LBS_OWNERDRAWFIXED)
282 if (lpmeasure->itemHeight > lphl->StdItemHeight)
283 lphl->StdItemHeight = lpmeasure->itemHeight;
284 lpls->mis.itemHeight = lpmeasure->itemHeight;
286 SEGPTR_FREE(lpmeasure);
289 /* -------------------- strings and item data ---------------------- */
291 LPLISTSTRUCT ListBoxCreateItem(LPHEADLIST lphl, int id)
293 LPLISTSTRUCT lplsnew = (LPLISTSTRUCT)malloc(sizeof(LISTSTRUCT));
295 if (lplsnew == NULL) return NULL;
297 lplsnew->itemState = 0;
298 lplsnew->mis.CtlType = lphl->DrawCtlType;
299 lplsnew->mis.CtlID = lphl->CtlID;
300 lplsnew->mis.itemID = id;
301 lplsnew->mis.itemHeight = lphl->StdItemHeight;
302 lplsnew->mis.itemWidth = 0; /* ignored */
303 lplsnew->mis.itemData = 0;
304 SetRectEmpty16( &lplsnew->itemRect );
306 return lplsnew;
311 int ListBoxInsertString(LPHEADLIST lphl, UINT uIndex, LPCSTR newstr)
313 LPLISTSTRUCT *lppls, lplsnew, lpls;
314 HANDLE hStr;
315 LPSTR str;
316 UINT Count;
318 dprintf_listbox(stddeb,"ListBoxInsertString(%d, %p);\n", uIndex, newstr);
320 if (!newstr) return -1;
322 if (uIndex == (UINT)-1)
323 uIndex = lphl->ItemsCount;
325 lppls = &lphl->lpFirst;
326 for(Count = 0; Count < uIndex; Count++) {
327 if (*lppls == NULL) return LB_ERR;
328 lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
331 lplsnew = ListBoxCreateItem(lphl, Count);
333 if (lplsnew == NULL) {
334 fprintf(stdnimp,"ListBoxInsertString() out of memory !\n");
335 return LB_ERRSPACE;
338 lplsnew->lpNext = *lppls;
339 *lppls = lplsnew;
340 lphl->ItemsCount++;
342 hStr = 0;
343 if (lphl->HasStrings) {
344 dprintf_listbox(stddeb," string: %s\n", newstr);
345 hStr = LIST_HEAP_ALLOC(lphl, LMEM_MOVEABLE, strlen(newstr) + 1);
346 str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
347 if (str == NULL) return LB_ERRSPACE;
348 strcpy(str, newstr);
349 lplsnew->itemText = str;
350 /* I'm not so sure about the next one */
351 lplsnew->mis.itemData = 0;
352 } else {
353 lplsnew->itemText = NULL;
354 lplsnew->mis.itemData = (DWORD)newstr;
357 lplsnew->mis.itemID = uIndex;
358 lplsnew->hData = hStr;
360 /* adjust the itemID field of the following entries */
361 for(lpls = lplsnew->lpNext; lpls != NULL; lpls = lpls->lpNext) {
362 lpls->mis.itemID++;
365 if (lphl->needMeasure) {
366 ListBoxAskMeasure(lphl, lplsnew);
369 dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
370 return uIndex;
374 int ListBoxAddString(LPHEADLIST lphl, LPCSTR newstr)
376 UINT pos = (UINT) -1;
378 if (lphl->HasStrings && (lphl->dwStyle & LBS_SORT)) {
379 LPLISTSTRUCT lpls = lphl->lpFirst;
380 for (pos = 0; lpls != NULL; lpls = lpls->lpNext, pos++)
381 if (strcmp(lpls->itemText, newstr) >= 0)
382 break;
384 return ListBoxInsertString(lphl, pos, newstr);
388 int ListBoxGetText(LPHEADLIST lphl, UINT uIndex, LPSTR OutStr)
390 LPLISTSTRUCT lpls;
392 if (!OutStr) {
393 dprintf_listbox(stddeb, "ListBoxGetText // OutStr==NULL\n");
394 return 0;
396 *OutStr = '\0';
397 lpls = ListBoxGetItem (lphl, uIndex);
398 if (lpls == NULL) return LB_ERR;
400 if (!lphl->HasStrings) {
401 *((long *)OutStr) = lpls->mis.itemData;
402 return 4;
405 strcpy(OutStr, lpls->itemText);
406 return strlen(OutStr);
410 DWORD ListBoxGetItemData(LPHEADLIST lphl, UINT uIndex)
412 LPLISTSTRUCT lpls;
414 lpls = ListBoxGetItem (lphl, uIndex);
415 if (lpls == NULL) return LB_ERR;
416 return lpls->mis.itemData;
420 int ListBoxSetItemData(LPHEADLIST lphl, UINT uIndex, DWORD ItemData)
422 LPLISTSTRUCT lpls = ListBoxGetItem(lphl, uIndex);
424 if (lpls == NULL) return LB_ERR;
425 lpls->mis.itemData = ItemData;
426 return 1;
430 int ListBoxDeleteString(LPHEADLIST lphl, UINT uIndex)
432 LPLISTSTRUCT lpls, lpls2;
433 UINT Count;
435 if (uIndex >= lphl->ItemsCount) return LB_ERR;
437 lpls = lphl->lpFirst;
438 if (lpls == NULL) return LB_ERR;
440 if (uIndex == 0)
441 lphl->lpFirst = lpls->lpNext;
442 else {
443 LPLISTSTRUCT lpls2 = NULL;
444 for(Count = 0; Count < uIndex; Count++) {
445 if (lpls->lpNext == NULL) return LB_ERR;
447 lpls2 = lpls;
448 lpls = (LPLISTSTRUCT)lpls->lpNext;
450 lpls2->lpNext = lpls->lpNext;
453 /* adjust the itemID field of the following entries */
454 for(lpls2 = lpls->lpNext; lpls2 != NULL; lpls2 = lpls2->lpNext) {
455 lpls2->mis.itemID--;
458 lphl->ItemsCount--;
460 if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
461 free(lpls);
463 return lphl->ItemsCount;
467 int ListBoxFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr)
469 LPLISTSTRUCT lpls;
470 UINT Count;
471 UINT First = nFirst + 1;
472 LPSTR lpMatchStr = (LPSTR)MatchStr;
474 if (First > lphl->ItemsCount) return LB_ERR;
476 if (lphl->HasStrings) lpMatchStr = PTR_SEG_TO_LIN(MatchStr);
478 lpls = ListBoxGetItem(lphl, First);
479 Count = 0;
480 while(lpls != NULL) {
481 if (lphl->HasStrings) {
482 if (strstr(lpls->itemText, lpMatchStr) == lpls->itemText) return Count;
483 } else if (lphl->dwStyle & LBS_SORT) {
484 /* XXX Do a compare item */
486 else
487 if (lpls->mis.itemData == (DWORD)lpMatchStr) return Count;
489 lpls = lpls->lpNext;
490 Count++;
493 /* Start over at top */
494 Count = 0;
495 lpls = lphl->lpFirst;
497 while (Count < First) {
498 if (lphl->HasStrings) {
499 if (strstr(lpls->itemText, lpMatchStr) == lpls->itemText) return Count;
500 } else if (lphl->dwStyle & LBS_SORT) {
501 /* XXX Do a compare item */
502 } else {
503 if (lpls->mis.itemData == (DWORD)lpMatchStr) return Count;
505 lpls = lpls->lpNext;
506 Count++;
509 return LB_ERR;
513 int ListBoxResetContent(LPHEADLIST lphl)
515 LPLISTSTRUCT lpls;
516 int i;
518 if (lphl->ItemsCount == 0) return 0;
520 dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n",
521 lphl->ItemsCount);
523 for(i = 0; i < lphl->ItemsCount; i++) {
524 lpls = lphl->lpFirst;
525 if (lpls == NULL) return LB_ERR;
527 lphl->lpFirst = lpls->lpNext;
528 if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
529 free(lpls);
531 ListBoxInitialize(lphl);
533 return TRUE;
536 /* --------------------- selection ------------------------- */
538 int ListBoxSetCurSel(LPHEADLIST lphl, WORD wIndex)
540 LPLISTSTRUCT lpls;
542 /* use ListBoxSetSel instead */
543 if (lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ) return 0;
545 /* unselect previous item */
546 if (lphl->ItemFocused != -1) {
547 lphl->PrevFocused = lphl->ItemFocused;
548 lpls = ListBoxGetItem(lphl, lphl->ItemFocused);
549 if (lpls == 0) return LB_ERR;
550 lpls->itemState = 0;
553 if ((wIndex != (UINT)-1) && (wIndex < lphl->ItemsCount))
555 lphl->ItemFocused = wIndex;
556 lpls = ListBoxGetItem(lphl, wIndex);
557 if (lpls == 0) return LB_ERR;
558 lpls->itemState = ODS_SELECTED | ODS_FOCUS;
560 return 0;
563 return LB_ERR;
567 int ListBoxSetSel(LPHEADLIST lphl, WORD wIndex, WORD state)
569 LPLISTSTRUCT lpls;
570 int n = 0;
572 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
573 return LB_ERR;
575 if (wIndex == (UINT)-1) {
576 for (lpls = lphl->lpFirst; lpls != NULL; lpls = lpls->lpNext) {
577 if( lpls->itemState & ODS_SELECTED) n++;
578 lpls->itemState = state? lpls->itemState | ODS_SELECTED
579 : lpls->itemState & ~ODS_SELECTED;
581 return n;
584 if (wIndex >= lphl->ItemsCount) return LB_ERR;
586 lpls = ListBoxGetItem(lphl, wIndex);
587 lpls->itemState = state? lpls->itemState | ODS_SELECTED
588 : lpls->itemState & ~ODS_SELECTED;
590 return 0;
594 int ListBoxGetSel(LPHEADLIST lphl, WORD wIndex)
596 LPLISTSTRUCT lpls = ListBoxGetItem(lphl, wIndex);
598 if (lpls == NULL) return LB_ERR;
599 return lpls->itemState & ODS_SELECTED;
602 /* ------------------------- dir listing ------------------------ */
604 LONG ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPCSTR filespec)
606 char temp[16], mask[13];
607 char *path, *p;
608 const char *ptr;
609 int skip, count;
610 LONG ret;
611 DOS_DIRENT entry;
613 dprintf_listbox(stddeb, "ListBoxDirectory: '%s' %04x\n", filespec, attrib);
614 if (!filespec) return LB_ERR;
615 if (!(ptr = DOSFS_GetUnixFileName( filespec, FALSE ))) return LB_ERR;
616 path = xstrdup(ptr);
617 p = strrchr( path, '/' );
618 *p++ = '\0';
619 if (!(ptr = DOSFS_ToDosFCBFormat( p )))
621 free( path );
622 return LB_ERR;
624 strcpy( mask, ptr );
626 dprintf_listbox(stddeb, "ListBoxDirectory: path=%s mask=%s\n", path, mask);
628 skip = ret = 0;
629 attrib &= ~FA_LABEL;
630 while ((count = DOSFS_FindNext( path, mask, 0, attrib, skip, &entry )) > 0)
632 skip += count;
633 if (entry.attr & FA_DIRECTORY)
635 if ((attrib & DDL_DIRECTORY) && strcmp(entry.name, ". "))
637 sprintf(temp, "[%s]", DOSFS_ToDosDTAFormat( entry.name ) );
638 AnsiLower( temp );
639 if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
642 else /* not a directory */
644 if (!(attrib & DDL_EXCLUSIVE) ||
645 ((attrib & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)) ==
646 (entry.attr & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE))))
648 strcpy( temp, DOSFS_ToDosDTAFormat( entry.name ) );
649 AnsiLower( temp );
650 if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
654 if (attrib & DDL_DRIVES)
656 int x;
657 strcpy( temp, "[-a-]" );
658 for (x = 0; x < MAX_DOS_DRIVES; x++, temp[2]++)
660 if (DRIVE_IsValid(x))
661 if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
664 free( path );
665 return ret;
668 /* ------------------------- dimensions ------------------------- */
670 int ListBoxGetItemRect(LPHEADLIST lphl, WORD wIndex, LPRECT16 lprect)
672 LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wIndex);
674 if (lpls == NULL) return LB_ERR;
675 *lprect = lpls->itemRect;
676 return 0;
680 int ListBoxSetItemHeight(LPHEADLIST lphl, WORD wIndex, long height)
682 LPLISTSTRUCT lpls;
684 if (!(lphl->dwStyle & LBS_OWNERDRAWVARIABLE)) {
685 lphl->StdItemHeight = (short)height;
686 return 0;
689 lpls = ListBoxGetItem(lphl, wIndex);
690 if (lpls == NULL) return LB_ERR;
692 lpls->mis.itemHeight = height;
693 return 0;
696 /* -------------------------- string search ------------------------ */
698 int ListBoxFindNextMatch(LPHEADLIST lphl, WORD wChar)
700 LPLISTSTRUCT lpls;
701 UINT count,first;
703 if ((char)wChar < ' ') return LB_ERR;
704 if (!lphl->HasStrings) return LB_ERR;
706 lpls = lphl->lpFirst;
708 for (count = 0; lpls != NULL; lpls = lpls->lpNext, count++) {
709 if (tolower(*lpls->itemText) == tolower((char)wChar)) break;
711 if (lpls == NULL) return LB_ERR;
712 first = count;
713 for(; lpls != NULL; lpls = lpls->lpNext, count++) {
714 if (*lpls->itemText != (char)wChar)
715 break;
716 if ((short) count > lphl->ItemFocused)
717 return count;
719 return first;
722 /***********************************************************************
723 * LBCreate
725 static LONG LBCreate(HWND hwnd, WORD wParam, LONG lParam)
727 LPHEADLIST lphl;
728 LONG dwStyle = GetWindowLong32A(hwnd,GWL_STYLE);
729 RECT16 rect;
731 CreateListBoxStruct(hwnd, ODT_LISTBOX, dwStyle, GetParent(hwnd));
732 lphl = ListBoxGetStorageHeader(hwnd);
733 dprintf_listbox(stddeb,"ListBox created: lphl = %p dwStyle = %04x:%04x\n",
734 lphl, HIWORD(dwStyle), LOWORD(dwStyle));
736 GetClientRect16(hwnd,&rect);
737 lphl->ColumnsWidth = rect.right - rect.left;
739 if (dwStyle & WS_VSCROLL)
740 SetScrollRange(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
741 if (dwStyle & WS_HSCROLL)
742 SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
744 return 0;
748 /***********************************************************************
749 * LBDestroy
751 static LONG LBDestroy(HWND hwnd, WORD wParam, LONG lParam)
753 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
755 ListBoxResetContent(lphl);
757 DestroyListBoxStruct(lphl);
758 dprintf_listbox(stddeb,"ListBox destroyed: lphl = %p\n",lphl);
759 return 0;
762 /***********************************************************************
763 * LBVScroll
765 static LONG LBVScroll(HWND hwnd, WORD wParam, LONG lParam)
767 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
768 int y;
770 dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
771 wParam, lParam);
772 y = lphl->FirstVisible;
774 switch(wParam) {
775 case SB_LINEUP:
776 if (lphl->FirstVisible > 0)
777 lphl->FirstVisible--;
778 break;
780 case SB_LINEDOWN:
781 lphl->FirstVisible++;
782 break;
784 case SB_PAGEUP:
785 if (lphl->FirstVisible > lphl->ItemsVisible) {
786 lphl->FirstVisible -= lphl->ItemsVisible;
787 } else {
788 lphl->FirstVisible = 0;
790 break;
792 case SB_PAGEDOWN:
793 lphl->FirstVisible += lphl->ItemsVisible;
794 break;
796 case SB_THUMBTRACK:
797 lphl->FirstVisible = LOWORD(lParam);
798 break;
801 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
802 lphl->FirstVisible = ListMaxFirstVisible(lphl);
804 if (y != lphl->FirstVisible) {
805 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
806 InvalidateRect32( hwnd, NULL, TRUE );
808 return 0;
811 /***********************************************************************
812 * LBHScroll
814 static LONG LBHScroll(HWND hwnd, WORD wParam, LONG lParam)
816 LPHEADLIST lphl;
817 int y;
819 dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
820 wParam, lParam);
821 lphl = ListBoxGetStorageHeader(hwnd);
822 y = lphl->FirstVisible;
823 switch(wParam) {
824 case SB_LINEUP:
825 if (lphl->FirstVisible > lphl->ItemsPerColumn) {
826 lphl->FirstVisible -= lphl->ItemsPerColumn;
827 } else {
828 lphl->FirstVisible = 0;
830 break;
831 case SB_LINEDOWN:
832 lphl->FirstVisible += lphl->ItemsPerColumn;
833 break;
834 case SB_PAGEUP:
835 if (lphl->ItemsPerColumn != 0) {
836 int lbsub = lphl->ItemsVisible / lphl->ItemsPerColumn * lphl->ItemsPerColumn;
837 if (lphl->FirstVisible > lbsub) {
838 lphl->FirstVisible -= lbsub;
839 } else {
840 lphl->FirstVisible = 0;
843 break;
844 case SB_PAGEDOWN:
845 if (lphl->ItemsPerColumn != 0)
846 lphl->FirstVisible += lphl->ItemsVisible /
847 lphl->ItemsPerColumn * lphl->ItemsPerColumn;
848 break;
849 case SB_THUMBTRACK:
850 lphl->FirstVisible = lphl->ItemsPerColumn * LOWORD(lParam);
851 break;
853 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
854 lphl->FirstVisible = ListMaxFirstVisible(lphl);
856 if (lphl->ItemsPerColumn != 0) {
857 lphl->FirstVisible = lphl->FirstVisible /
858 lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
859 if (y != lphl->FirstVisible) {
860 SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible /
861 lphl->ItemsPerColumn + 1, TRUE);
862 InvalidateRect32( hwnd, NULL, TRUE );
865 return 0;
868 /***********************************************************************
869 * LBLButtonDown
871 static LONG LBLButtonDown(HWND hwnd, WORD wParam, LONG lParam)
873 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
874 WORD wRet;
875 int y,n;
876 RECT16 rectsel;
878 SetFocus(hwnd);
879 SetCapture(hwnd);
881 lphl->PrevFocused = lphl->ItemFocused;
883 y = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
885 if (y == -1) return 0;
887 if (lphl->dwStyle & LBS_NOTIFY && y!= LB_ERR )
888 if( SendMessage16(lphl->hParent, WM_LBTRACKPOINT, y, lParam) )
889 return 0;
892 switch( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )
894 case LBS_MULTIPLESEL:
895 lphl->ItemFocused = y;
896 wRet = ListBoxGetSel(lphl, y);
897 ListBoxSetSel(lphl, y, !wRet);
898 break;
899 case LBS_EXTENDEDSEL:
900 /* should handle extended mode here and in kbd handler
903 if ( lphl->PrevFocused != y && y!= LB_ERR)
905 LPLISTSTRUCT lpls = ListBoxGetItem( lphl, lphl->ItemFocused = y );
906 n = ListBoxSetSel(lphl,-1,FALSE);
908 lpls->itemState = ODS_FOCUS | ODS_SELECTED;
910 if( n > 1 && n != LB_ERR )
911 InvalidateRect32( hwnd,NULL,TRUE );
913 else
914 return 0;
916 break;
917 case 0:
918 if( y!=lphl->ItemFocused )
919 ListBoxSetCurSel(lphl, y);
920 else
921 return 0;
922 break;
923 default:
924 fprintf(stdnimp,"Listbox: LBS_MULTIPLESEL and LBS_EXTENDEDSEL are on!\n");
925 return 0;
928 /* invalidate changed items */
929 if( lphl->dwStyle & LBS_MULTIPLESEL || y!=lphl->PrevFocused )
931 ListBoxGetItemRect(lphl, y, &rectsel);
932 InvalidateRect16( hwnd, &rectsel, TRUE );
934 if( lphl->PrevFocused!=-1 && y!=lphl->PrevFocused )
936 ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
937 InvalidateRect16( hwnd, &rectsel, TRUE );
940 if (GetWindowLong32A(lphl->hSelf,GWL_EXSTYLE) & WS_EX_DRAGDETECT)
941 if( DragDetect(lphl->hSelf,MAKEPOINT16(lParam)) )
942 SendMessage16(lphl->hParent, WM_BEGINDRAG,0,0L);
943 return 0;
946 /***********************************************************************
947 * LBLButtonUp
949 static LONG LBLButtonUp(HWND hwnd, WORD wParam, LONG lParam)
951 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
953 if (GetCapture() == hwnd) ReleaseCapture();
955 if (lphl->PrevFocused != lphl->ItemFocused)
956 ListBoxSendNotification(lphl, LBN_SELCHANGE);
958 return 0;
961 /***********************************************************************
962 * LBRButtonUp
964 static LONG LBRButtonUp(HWND hwnd, WORD wParam, LONG lParam)
966 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
968 SendMessage16(lphl->hParent, WM_COMMAND, GetWindowWord(hwnd,GWW_ID),
969 MAKELONG(hwnd, LBN_DBLCLK));
970 return 0;
973 /***********************************************************************
974 * LBMouseMove
976 static LONG LBMouseMove(HWND hwnd, WORD wParam, LONG lParam)
978 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
979 int y,redraw_prev = 0;
980 int iRet;
981 RECT16 rect, rectsel; /* XXX Broken */
983 dprintf_listbox(stddeb,"LBMouseMove %d %d\n",SLOWORD(lParam),SHIWORD(lParam));
984 if ((wParam & MK_LBUTTON) != 0) {
985 y = SHIWORD(lParam);
986 if (y < LBMM_EDGE) {
987 if (lphl->FirstVisible > 0) {
988 lphl->FirstVisible--;
989 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
990 InvalidateRect32( hwnd, NULL, TRUE );
991 return 0;
994 GetClientRect16(hwnd, &rect);
995 if (y >= (rect.bottom-LBMM_EDGE)) {
996 if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
997 lphl->FirstVisible++;
998 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
999 InvalidateRect32( hwnd, NULL, TRUE );
1000 return 0;
1003 if ((y > 0) && (y < (rect.bottom - LBMM_EDGE))) {
1004 if ((y < rectsel.top) || (y > rectsel.bottom)) {
1005 iRet = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
1006 if (iRet == lphl->ItemFocused || iRet == -1) {
1007 return 0;
1009 if (lphl->dwStyle & LBS_MULTIPLESEL) {
1010 lphl->ItemFocused = iRet;
1011 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1012 } else if ( lphl->dwStyle & LBS_EXTENDEDSEL )
1014 /* Fixme: extended selection mode */
1015 ListBoxSetSel( lphl, lphl->ItemFocused, 0);
1016 lphl->PrevFocused = lphl->ItemFocused;
1017 lphl->ItemFocused = iRet;
1018 ListBoxSetSel( lphl, iRet, TRUE);
1019 redraw_prev = 1;
1021 else
1023 ListBoxSetCurSel(lphl, (WORD)iRet);
1024 redraw_prev = 1;
1026 if( lphl->PrevFocused!=-1 && redraw_prev )
1028 ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
1029 InvalidateRect16( hwnd, &rectsel, TRUE );
1031 ListBoxGetItemRect(lphl, iRet, &rectsel);
1032 InvalidateRect16( hwnd, &rectsel, TRUE );
1037 return 0;
1040 /***********************************************************************
1041 * LBKeyDown
1043 * Doesn't yet handle properly VK_SHIFT with LB_EXTENDEDSEL
1045 static LONG LBKeyDown(HWND hwnd, WORD wParam, LONG lParam)
1047 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1048 WORD newFocused = 0xFFFF;
1049 RECT16 rect;
1051 ListBoxGetItemRect(lphl,lphl->ItemFocused,&rect);
1052 switch(wParam)
1054 case VK_HOME:
1055 case VK_END:
1056 case VK_LEFT:
1057 case VK_RIGHT:
1058 case VK_UP:
1059 case VK_DOWN:
1060 case VK_PRIOR:
1061 case VK_NEXT:
1062 if ( lphl->dwStyle & LBS_WANTKEYBOARDINPUT )
1064 newFocused = (WORD)(INT)SendMessage16(lphl->hParent,WM_VKEYTOITEM,
1065 wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
1066 if ( newFocused == 0xFFFE ) return 0L;
1068 if ( newFocused == 0xFFFF )
1070 newFocused = lphl->ItemFocused;
1072 /* nested switch */
1073 switch(wParam)
1075 case VK_HOME:
1076 newFocused = 0;
1077 break;
1078 case VK_END:
1079 newFocused = lphl->ItemsCount - 1;
1080 break;
1081 case VK_LEFT:
1082 if (lphl->dwStyle & LBS_MULTICOLUMN) {
1083 if (newFocused >= lphl->ItemsPerColumn) {
1084 newFocused -= lphl->ItemsPerColumn;
1085 } else {
1086 newFocused = 0;
1089 break;
1090 case VK_UP:
1091 if (newFocused > 0) newFocused--;
1092 break;
1093 case VK_RIGHT:
1094 if (lphl->dwStyle & LBS_MULTICOLUMN)
1095 newFocused += lphl->ItemsPerColumn;
1096 break;
1097 case VK_DOWN:
1098 newFocused++;
1099 break;
1100 case VK_PRIOR:
1101 if (newFocused > lphl->ItemsVisible)
1102 newFocused -= lphl->ItemsVisible;
1103 else newFocused = 0;
1104 break;
1105 case VK_NEXT:
1106 newFocused += lphl->ItemsVisible;
1107 break;
1108 default:
1109 return 0;
1111 /* end of nested switch */
1113 break;
1114 case VK_SPACE:
1115 if (lphl->dwStyle & LBS_MULTIPLESEL)
1117 WORD wRet = ListBoxGetSel(lphl, lphl->ItemFocused);
1118 ListBoxSetSel(lphl, lphl->ItemFocused, !wRet);
1120 return 0;
1122 /* chars are handled in LBChar */
1123 default:
1124 return 0;
1127 /* at this point newFocused is set up */
1129 if (newFocused >= lphl->ItemsCount)
1130 newFocused = lphl->ItemsCount - 1;
1132 if (!(lphl->dwStyle & LBS_MULTIPLESEL))
1134 ListBoxSetCurSel(lphl, newFocused);
1135 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1138 lphl->ItemFocused = newFocused;
1140 if( ListBoxScrollToFocus(lphl) || (lphl->dwStyle &
1141 (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) )
1142 InvalidateRect32( hwnd, NULL, TRUE );
1143 else
1145 InvalidateRect16( hwnd, &rect, TRUE );
1146 if( newFocused < 0x8000 )
1148 ListBoxGetItemRect(lphl, newFocused, &rect);
1149 InvalidateRect16( hwnd, &rect, TRUE );
1153 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1155 return 0;
1158 /***********************************************************************
1159 * LBChar
1161 static LONG LBChar(HWND hwnd, WORD wParam, LONG lParam)
1163 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1164 WORD newFocused = 0xFFFF;
1166 if ( (lphl->dwStyle & LBS_WANTKEYBOARDINPUT) && !(lphl->HasStrings))
1168 newFocused = (WORD)(INT)SendMessage16(lphl->hParent,WM_CHARTOITEM,
1169 wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
1170 if ( newFocused == 0xFFFE ) return 0L;
1173 if (newFocused == 0xFFFF )
1174 newFocused = ListBoxFindNextMatch(lphl, wParam);
1176 if (newFocused == (WORD)LB_ERR) return 0;
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;
1188 ListBoxScrollToFocus(lphl);
1189 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1191 InvalidateRect32( hwnd, NULL, TRUE );
1193 return 0;
1196 /***********************************************************************
1197 * LBSetRedraw
1199 static LONG LBSetRedraw(HWND hwnd, WORD wParam, LONG lParam)
1201 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1203 dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd=%04x w=%04x !\n",
1204 hwnd, wParam);
1205 lphl->bRedrawFlag = wParam;
1207 return 0;
1210 /***********************************************************************
1211 * LBSetFont
1213 static LONG LBSetFont(HWND hwnd, WPARAM wParam, LPARAM lParam)
1215 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1216 HDC hdc;
1218 if (wParam == 0)
1219 lphl->hFont = GetStockObject(SYSTEM_FONT);
1220 else
1221 lphl->hFont = (HFONT) wParam;
1223 /* a new font means possible new text height */
1224 /* does this mean the height of each entry must be separately changed? */
1225 /* or are we guaranteed to get a LBSetFont before the first insert/add? */
1226 if ((hdc = GetDC(0)))
1228 TEXTMETRIC16 tm;
1229 GetTextMetrics16( hdc, &tm );
1230 lphl->StdItemHeight = tm.tmHeight;
1231 dprintf_listbox(stddeb,"LBSetFont: new font %d with height %d\n",
1232 lphl->hFont, lphl->StdItemHeight);
1233 ReleaseDC( 0, hdc );
1236 return 0;
1239 /***********************************************************************
1240 * LBPaint
1242 static LONG LBPaint(HWND hwnd, WORD wParam, LONG lParam)
1244 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1245 LPLISTSTRUCT lpls;
1246 PAINTSTRUCT16 ps;
1247 HBRUSH hBrush;
1248 HFONT hOldFont;
1249 HDC16 hdc = BeginPaint16( hwnd, &ps );
1250 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
1251 RECT16 rect, paintRect, scratchRect;
1252 int i, top, height, maxwidth, ipc;
1254 top = 0;
1256 if (!IsWindowVisible(hwnd) || !lphl->bRedrawFlag) {
1257 EndPaint16(hwnd, &ps);
1258 return 0;
1261 GetRgnBox16(dc->w.hGCClipRgn,&paintRect);
1262 GetClientRect16(hwnd, &rect);
1263 IntersectRect16(&paintRect,&rect,&paintRect);
1265 hOldFont = SelectObject(hdc, lphl->hFont);
1267 hBrush = (HBRUSH)SendMessage32A( lphl->hParent, WM_CTLCOLORLISTBOX,
1268 (WPARAM)hdc, (LPARAM)hwnd);
1269 if (hBrush == 0) hBrush = GetStockObject(WHITE_BRUSH);
1271 FillRect16(hdc, &rect, hBrush);
1273 maxwidth = rect.right;
1274 if (lphl->dwStyle & LBS_MULTICOLUMN) {
1275 rect.right = lphl->ColumnsWidth;
1277 lpls = lphl->lpFirst;
1279 lphl->ItemsVisible = 0;
1280 lphl->ItemsPerColumn = ipc = 0;
1282 for(i = 0; i < lphl->ItemsCount; i++) {
1283 if (lpls == NULL) break;
1285 if (i >= lphl->FirstVisible) {
1286 height = lpls->mis.itemHeight;
1288 if (top > (rect.bottom-height+1)) {
1289 if (lphl->dwStyle & LBS_MULTICOLUMN) {
1290 lphl->ItemsPerColumn = MAX(lphl->ItemsPerColumn, ipc);
1291 ipc = 0;
1292 top = 0;
1293 rect.left += lphl->ColumnsWidth;
1294 rect.right += lphl->ColumnsWidth;
1295 if (rect.left > maxwidth) break;
1296 } else {
1297 break;
1301 lpls->itemRect.top = top;
1302 lpls->itemRect.bottom = top + height;
1303 lpls->itemRect.left = rect.left;
1304 lpls->itemRect.right = rect.right;
1306 if( IntersectRect16(&scratchRect,&paintRect,&lpls->itemRect) )
1308 dprintf_listbox(stddeb,"LBPaint: drawing item: %d %d %d %d %d\n",
1309 rect.left,top,rect.right,top+height,lpls->itemState);
1311 if (lphl->OwnerDrawn && (lphl->ItemFocused == i) && GetFocus() == hwnd)
1313 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS,
1314 lpls->itemState & ~ODS_FOCUS);
1315 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
1316 lpls->itemState & ~ODS_FOCUS);
1317 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS, lpls->itemState);
1319 else
1320 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
1321 lpls->itemState);
1324 top += height;
1325 lphl->ItemsVisible++;
1326 ipc++;
1329 lpls = lpls->lpNext;
1331 ListBoxUpdateWindow(hwnd,lphl,FALSE);
1332 SelectObject(hdc,hOldFont);
1333 EndPaint16( hwnd, &ps );
1334 return 0;
1337 /***********************************************************************
1338 * LBSetFocus
1340 static LONG LBSetFocus(HWND hwnd, WORD wParam, LONG lParam)
1342 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1344 dprintf_listbox(stddeb,"ListBox WM_SETFOCUS for %04x\n",hwnd);
1345 if(!(lphl->dwStyle & LBS_MULTIPLESEL) )
1346 if( lphl->ItemsCount && lphl->ItemFocused != -1)
1348 HDC hDC = GetDC(hwnd);
1349 HFONT hOldFont = SelectObject(hDC, lphl->hFont);
1350 LPLISTSTRUCT lpls;
1352 lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
1353 lpls->itemState |= ODS_FOCUS;
1355 ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
1356 SelectObject(hDC, hOldFont);
1357 ReleaseDC(hwnd,hDC);
1360 ListBoxSendNotification(lphl, LBN_SETFOCUS);
1362 return 0;
1365 /***********************************************************************
1366 * LBKillFocus
1368 static LONG LBKillFocus(HWND hwnd, WORD wParam, LONG lParam)
1370 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1372 dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS for %04x\n",hwnd);
1373 if (!(lphl->dwStyle & LBS_MULTIPLESEL))
1375 if( lphl->ItemsCount )
1376 if( lphl->ItemFocused != -1 )
1378 HDC hDC = GetDC(hwnd);
1379 HFONT hOldFont = SelectObject(hDC, lphl->hFont);
1380 LPLISTSTRUCT lpls;
1382 lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
1383 lpls->itemState &= ~ODS_FOCUS;
1385 ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
1386 SelectObject(hDC, hOldFont);
1387 ReleaseDC(hwnd,hDC);
1389 else
1390 dprintf_listbox(stddeb,"LBKillFocus: no focused item!\n");
1392 else
1393 InvalidateRect32( hwnd, NULL, TRUE );
1395 ListBoxSendNotification(lphl, LBN_KILLFOCUS);
1397 return 0;
1400 /***********************************************************************
1401 * LBResetContent
1403 static LONG LBResetContent(HWND hwnd, WORD wParam, LONG lParam)
1405 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1407 dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
1408 ListBoxResetContent(lphl);
1409 ListBoxUpdateWindow(hwnd, lphl, TRUE);
1410 return 0;
1413 /***********************************************************************
1414 * LBDir
1416 static LONG LBDir(HWND hwnd, WORD wParam, LONG lParam)
1418 LONG ret;
1419 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1420 dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
1422 ret = ListBoxDirectory(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
1423 ListBoxUpdateWindow(hwnd, lphl, TRUE);
1424 return ret;
1427 /***********************************************************************
1428 * LBAddString
1430 static LONG LBAddString(HWND hwnd, WORD wParam, LONG lParam)
1432 WORD wRet;
1433 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1435 if (lphl->HasStrings)
1436 wRet = ListBoxAddString(lphl, (LPCSTR)PTR_SEG_TO_LIN(lParam));
1437 else
1438 wRet = ListBoxAddString(lphl, (LPCSTR)lParam);
1440 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1441 return wRet;
1444 /***********************************************************************
1445 * LBGetText
1447 static LONG LBGetText(HWND hwnd, WORD wParam, LONG lParam)
1449 LONG wRet;
1450 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1452 dprintf_listbox(stddeb, "LB_GETTEXT wParam=%d\n",wParam);
1453 wRet = ListBoxGetText(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
1455 return wRet;
1458 /***********************************************************************
1459 * LBInsertString
1461 static LONG LBInsertString(HWND hwnd, WORD wParam, LONG lParam)
1463 WORD wRet;
1464 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1466 if (lphl->HasStrings)
1467 wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)PTR_SEG_TO_LIN(lParam));
1468 else
1469 wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)lParam);
1471 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1472 return wRet;
1475 /***********************************************************************
1476 * LBDeleteString
1478 static LONG LBDeleteString(HWND hwnd, WORD wParam, LONG lParam)
1480 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1481 LONG lRet = ListBoxDeleteString(lphl,wParam);
1483 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1484 return lRet;
1487 /***********************************************************************
1488 * LBFindString
1490 static LONG LBFindString(HWND hwnd, WORD wParam, LONG lParam)
1492 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1493 return ListBoxFindString(lphl, wParam, (SEGPTR)lParam);
1496 /***********************************************************************
1497 * LBGetCaretIndex
1499 static LONG LBGetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
1501 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1502 return lphl->ItemFocused;
1505 /***********************************************************************
1506 * LBGetCount
1508 static LONG LBGetCount(HWND hwnd, WORD wParam, LONG lParam)
1510 LPHEADLIST lphl;
1512 lphl = ListBoxGetStorageHeader(hwnd);
1513 return lphl->ItemsCount;
1516 /***********************************************************************
1517 * LBGetCurSel
1519 static LONG LBGetCurSel(HWND hwnd, WORD wParam, LONG lParam)
1521 LPHEADLIST lphl;
1523 lphl = ListBoxGetStorageHeader(hwnd);
1524 dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %i !\n",
1525 lphl->ItemFocused);
1526 return lphl->ItemFocused;
1529 /***********************************************************************
1530 * LBGetHorizontalExtent
1532 static LONG LBGetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
1534 return 0;
1537 /***********************************************************************
1538 * LBGetItemHeight
1540 static LONG LBGetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
1542 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1543 LPLISTSTRUCT lpls = ListBoxGetItem (lphl, wParam);
1545 if (lpls == NULL) return LB_ERR;
1546 return lpls->mis.itemHeight;
1549 /***********************************************************************
1550 * LBGetItemRect
1552 static LONG LBGetItemRect(HWND hwnd, WORD wParam, LONG lParam)
1554 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1555 return ListBoxGetItemRect(lphl, wParam, PTR_SEG_TO_LIN(lParam));
1558 /***********************************************************************
1559 * LBGetSel
1561 static LONG LBGetSel(HWND hwnd, WORD wParam, LONG lParam)
1563 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1564 int iSel = ListBoxGetSel(lphl, wParam);
1566 dprintf_listbox(stdnimp,"LBGetSel: item %u - %i\n",wParam,iSel);
1568 return (iSel)? 1 : 0;
1571 /***********************************************************************
1572 * LBGetSelCount
1574 static LONG LBGetSelCount(HWND hwnd, WORD wParam, LONG lParam)
1576 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1577 LPLISTSTRUCT lpls;
1578 int cnt = 0;
1579 int items = 0;
1581 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1582 return LB_ERR;
1584 for( lpls = lphl->lpFirst;
1585 lpls;
1586 lpls = lpls->lpNext )
1588 items++;
1589 if (lpls->itemState )
1590 cnt++;
1593 return cnt;
1596 /***********************************************************************
1597 * LBGetSelItems
1599 static LONG LBGetSelItems(HWND hwnd, WORD wParam, LONG lParam)
1601 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1602 LPLISTSTRUCT lpls;
1603 int cnt, idx;
1604 int *lpItems = PTR_SEG_TO_LIN(lParam);
1606 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1607 return LB_ERR;
1609 if (wParam == 0) return 0;
1611 lpls = lphl->lpFirst;
1612 cnt = 0; idx = 0;
1614 while (lpls != NULL) {
1615 if (lpls->itemState > 0) lpItems[cnt++] = idx;
1617 if (cnt == wParam) break;
1618 idx++;
1619 lpls = lpls->lpNext;
1622 return cnt;
1625 /***********************************************************************
1626 * LBGetTextLen
1628 static LONG LBGetTextLen(HWND hwnd, WORD wParam, LONG lParam)
1630 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1631 LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wParam);
1633 if (lpls == NULL || !lphl->HasStrings) return LB_ERR;
1634 return strlen(lpls->itemText);
1637 /***********************************************************************
1638 * LBGetDlgCode
1640 static LONG LBGetDlgCode(HWND hwnd, WORD wParam, LONG lParam)
1642 return DLGC_WANTARROWS | DLGC_WANTCHARS;
1645 /***********************************************************************
1646 * LBGetTopIndex
1648 static LONG LBGetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
1650 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1652 return lphl->FirstVisible;
1656 /***********************************************************************
1657 * LBSelectString
1659 static LONG LBSelectString(HWND hwnd, WORD wParam, LONG lParam)
1661 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1662 INT iRet;
1664 iRet = ListBoxFindString(lphl, wParam, (SEGPTR)lParam);
1666 if( iRet != LB_ERR)
1668 if( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )
1669 ListBoxSetSel(lphl,iRet,TRUE);
1670 else
1671 ListBoxSetCurSel(lphl,iRet);
1673 lphl->ItemFocused = iRet;
1674 InvalidateRect32( hwnd, 0, TRUE );
1676 return iRet;
1679 /***********************************************************************
1680 * LBSelItemRange
1682 static LONG LBSelItemRange(HWND hwnd, WORD wParam, LONG lParam)
1684 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1685 LPLISTSTRUCT lpls;
1686 WORD cnt;
1687 WORD first = LOWORD(lParam);
1688 WORD last = HIWORD(lParam);
1689 BOOL select = wParam;
1691 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1692 return LB_ERR;
1694 if (first >= lphl->ItemsCount ||
1695 last >= lphl->ItemsCount) return LB_ERR;
1697 lpls = lphl->lpFirst;
1698 cnt = 0;
1700 while (lpls != NULL) {
1701 if (cnt++ >= first)
1702 lpls->itemState = select ? lpls->itemState | ODS_SELECTED : 0;
1704 if (cnt > last)
1705 break;
1707 lpls = lpls->lpNext;
1710 return 0;
1713 /***********************************************************************
1714 * LBSetCaretIndex
1716 static LONG LBSetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
1718 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1719 int i;
1721 if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )) return 0;
1723 dprintf_listbox(stddeb,"LBSetCaretIndex: hwnd %04x n=%i\n",hwnd,wParam);
1725 if (wParam >= lphl->ItemsCount) return LB_ERR;
1727 lphl->ItemFocused = wParam;
1728 i = ListBoxScrollToFocus (lphl);
1730 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1731 if(i)
1732 InvalidateRect32( hwnd, NULL, TRUE );
1734 return 1;
1737 /***********************************************************************
1738 * LBSetColumnWidth
1740 static LONG LBSetColumnWidth(HWND hwnd, WORD wParam, LONG lParam)
1742 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1743 lphl->ColumnsWidth = wParam;
1744 InvalidateRect32( hwnd, NULL, TRUE );
1745 return 0;
1748 /***********************************************************************
1749 * LBSetHorizontalExtent
1751 static LONG LBSetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
1753 return 0;
1756 /***********************************************************************
1757 * LBGetItemData
1759 static LONG LBGetItemData(HWND hwnd, WORD wParam, LONG lParam)
1761 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1762 dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
1763 return ListBoxGetItemData(lphl, wParam);
1766 /***********************************************************************
1767 * LBSetItemData
1769 static LONG LBSetItemData(HWND hwnd, WORD wParam, LONG lParam)
1771 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1772 dprintf_listbox(stddeb, "LB_SETITEMDATA wParam=%x lParam=%lx\n", wParam, lParam);
1773 return ListBoxSetItemData(lphl, wParam, lParam);
1776 /***********************************************************************
1777 * LBSetTabStops
1779 static LONG LBSetTabStops(HWND hwnd, WORD wParam, LONG lParam)
1781 LPHEADLIST lphl;
1783 lphl = ListBoxGetStorageHeader(hwnd);
1785 if (lphl->TabStops != NULL) {
1786 lphl->iNumStops = 0;
1787 free (lphl->TabStops);
1790 lphl->TabStops = malloc (wParam * sizeof (short));
1791 if (lphl->TabStops) {
1792 lphl->iNumStops = wParam;
1793 memcpy (lphl->TabStops, PTR_SEG_TO_LIN(lParam), wParam * sizeof (short));
1794 return TRUE;
1797 return FALSE;
1800 /***********************************************************************
1801 * LBSetCurSel
1803 static LONG LBSetCurSel(HWND hwnd, WORD wParam, LONG lParam)
1805 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1806 WORD wRet;
1808 dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n",
1809 wParam);
1811 wRet = ListBoxSetCurSel(lphl, wParam);
1813 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1814 InvalidateRect32( hwnd, NULL, TRUE );
1816 return wRet;
1819 /***********************************************************************
1820 * LBSetSel
1822 static LONG LBSetSel(HWND hwnd, WORD wParam, LONG lParam)
1824 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1825 RECT16 rect;
1826 int iRet;
1828 dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
1830 iRet = ListBoxSetSel(lphl, LOWORD(lParam), wParam);
1832 if( iRet > 1 ) InvalidateRect32( hwnd, NULL, TRUE );
1833 else if( iRet != LB_ERR )
1835 if( lphl->dwStyle & LBS_EXTENDEDSEL &&
1836 lphl->ItemFocused != LOWORD(lParam) )
1838 ListBoxGetItemRect(lphl, lphl->ItemFocused , &rect);
1839 InvalidateRect16( hwnd, &rect, TRUE );
1840 lphl->ItemFocused = LOWORD(lParam);
1842 ListBoxGetItemRect(lphl,LOWORD(lParam),&rect);
1843 InvalidateRect16( hwnd, &rect, TRUE );
1846 return (iRet == (WORD)LB_ERR)? LB_ERR: 0;
1849 /***********************************************************************
1850 * LBSetTopIndex
1852 static LONG LBSetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
1854 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1856 dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
1857 wParam);
1858 lphl->FirstVisible = wParam;
1859 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1861 InvalidateRect32( hwnd, NULL, TRUE );
1863 return 0;
1866 /***********************************************************************
1867 * LBSetItemHeight
1869 static LONG LBSetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
1871 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1872 WORD wRet;
1874 dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
1875 wRet = ListBoxSetItemHeight(lphl, wParam, lParam);
1876 InvalidateRect32( hwnd, NULL, TRUE );
1877 return wRet;
1880 /***********************************************************************
1881 * LBPassToParent
1883 static LRESULT LBPassToParent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1885 WND* ptrWnd = WIN_FindWndPtr(hwnd);
1887 if( ptrWnd )
1888 if( /* !(ptrWnd->dwExStyle & WS_EX_NOPARENTNOTIFY) && */
1889 ptrWnd->parent )
1890 return SendMessage16(ptrWnd->parent->hwndSelf,message,wParam,lParam);
1891 return 0;
1894 /***********************************************************************
1895 * ListBoxWndProc
1897 LRESULT ListBoxWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1899 switch (message) {
1900 case WM_CREATE: return LBCreate(hwnd, wParam, lParam);
1901 case WM_DESTROY: return LBDestroy(hwnd, wParam, lParam);
1902 case WM_GETDLGCODE: return LBGetDlgCode(hwnd, wParam, lParam);
1903 case WM_VSCROLL: return LBVScroll(hwnd, wParam, lParam);
1904 case WM_HSCROLL: return LBHScroll(hwnd, wParam, lParam);
1905 case WM_LBUTTONDOWN: return LBLButtonDown(hwnd, wParam, lParam);
1906 case WM_LBUTTONUP: return LBLButtonUp(hwnd, wParam, lParam);
1907 case WM_RBUTTONUP: return LBRButtonUp(hwnd, wParam, lParam);
1908 case WM_LBUTTONDBLCLK: return LBRButtonUp(hwnd, wParam, lParam);
1909 case WM_MOUSEMOVE: return LBMouseMove(hwnd, wParam, lParam);
1910 case WM_KEYDOWN: return LBKeyDown(hwnd, wParam, lParam);
1911 case WM_CHAR: return LBChar(hwnd, wParam, lParam);
1912 case WM_SETFONT: return LBSetFont(hwnd, wParam, lParam);
1913 case WM_SETREDRAW: return LBSetRedraw(hwnd, wParam, lParam);
1914 case WM_PAINT: return LBPaint(hwnd, wParam, lParam);
1915 case WM_SETFOCUS: return LBSetFocus(hwnd, wParam, lParam);
1916 case WM_KILLFOCUS: return LBKillFocus(hwnd, wParam, lParam);
1917 case LB_RESETCONTENT: return LBResetContent(hwnd, wParam, lParam);
1918 case LB_DIR: return LBDir(hwnd, wParam, lParam);
1919 case LB_ADDSTRING: return LBAddString(hwnd, wParam, lParam);
1920 case LB_INSERTSTRING: return LBInsertString(hwnd, wParam, lParam);
1921 case LB_DELETESTRING: return LBDeleteString(hwnd, wParam, lParam);
1922 case LB_FINDSTRING: return LBFindString(hwnd, wParam, lParam);
1923 case LB_GETCARETINDEX: return LBGetCaretIndex(hwnd, wParam, lParam);
1924 case LB_GETCOUNT: return LBGetCount(hwnd, wParam, lParam);
1925 case LB_GETCURSEL: return LBGetCurSel(hwnd, wParam, lParam);
1926 case LB_GETHORIZONTALEXTENT: return LBGetHorizontalExtent(hwnd, wParam, lParam);
1927 case LB_GETITEMDATA: return LBGetItemData(hwnd, wParam, lParam);
1928 case LB_GETITEMHEIGHT: return LBGetItemHeight(hwnd, wParam, lParam);
1929 case LB_GETITEMRECT: return LBGetItemRect(hwnd, wParam, lParam);
1930 case LB_GETSEL: return LBGetSel(hwnd, wParam, lParam);
1931 case LB_GETSELCOUNT: return LBGetSelCount(hwnd, wParam, lParam);
1932 case LB_GETSELITEMS: return LBGetSelItems(hwnd, wParam, lParam);
1933 case LB_GETTEXT: return LBGetText(hwnd, wParam, lParam);
1934 case LB_GETTEXTLEN: return LBGetTextLen(hwnd, wParam, lParam);
1935 case LB_GETTOPINDEX: return LBGetTopIndex(hwnd, wParam, lParam);
1936 case LB_SELECTSTRING: return LBSelectString(hwnd, wParam, lParam);
1937 case LB_SELITEMRANGE: return LBSelItemRange(hwnd, wParam, lParam);
1938 case LB_SETCARETINDEX: return LBSetCaretIndex(hwnd, wParam, lParam);
1939 case LB_SETCOLUMNWIDTH: return LBSetColumnWidth(hwnd, wParam, lParam);
1940 case LB_SETHORIZONTALEXTENT: return LBSetHorizontalExtent(hwnd, wParam, lParam);
1941 case LB_SETITEMDATA: return LBSetItemData(hwnd, wParam, lParam);
1942 case LB_SETTABSTOPS: return LBSetTabStops(hwnd, wParam, lParam);
1943 case LB_SETCURSEL: return LBSetCurSel(hwnd, wParam, lParam);
1944 case LB_SETSEL: return LBSetSel(hwnd, wParam, lParam);
1945 case LB_SETTOPINDEX: return LBSetTopIndex(hwnd, wParam, lParam);
1946 case LB_SETITEMHEIGHT: return LBSetItemHeight(hwnd, wParam, lParam);
1948 case WM_DROPFILES: return LBPassToParent(hwnd, message, wParam, lParam);
1950 /* these will have to be implemented for proper LBS_EXTENDEDSEL -
1952 * anchor item is an item that with caret (focused) item defines a
1953 * range of currently selected items when listbox is in the extended
1954 * selection mode.
1956 case LB_SETANCHORINDEX: return LB_SETANCHORINDEX; /* that's what Windows returns */
1957 case LB_GETANCHORINDEX: return 0;
1959 case WM_DROPOBJECT:
1960 case WM_QUERYDROPOBJECT:
1961 case WM_DRAGSELECT:
1962 case WM_DRAGMOVE:
1964 LPDRAGINFO lpDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN((SEGPTR)lParam);
1965 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1967 lpDragInfo->l = ListBoxFindMouse(lphl,lpDragInfo->pt.x,
1968 lpDragInfo->pt.y);
1970 return LBPassToParent(hwnd, message, wParam, lParam);
1974 return DefWindowProc16(hwnd, message, wParam, lParam);
1978 /**********************************************************************
1979 * DlgDirSelect (USER.99)
1981 BOOL DlgDirSelect( HWND hDlg, LPSTR lpStr, INT id )
1983 char *buffer;
1984 INT i;
1986 dprintf_listbox( stddeb, "DlgDirSelect: %04x '%s' %d\n", hDlg, lpStr, id );
1987 if ((i = SendDlgItemMessage16( hDlg, id, LB_GETCURSEL, 0, 0 )) == LB_ERR)
1988 return FALSE;
1989 if (!(buffer = SEGPTR_ALLOC( 20 * sizeof(char) ))) return FALSE;
1990 SendDlgItemMessage16(hDlg, id, LB_GETTEXT, i, (LPARAM)SEGPTR_GET(buffer) );
1991 if (buffer[0] == '[') /* drive or directory */
1993 if (buffer[1] == '-') /* drive */
1995 lpStr[0] = buffer[2];
1996 lpStr[1] = ':';
1997 lpStr[2] = '\0';
1998 dprintf_listbox( stddeb, "Returning drive '%s'\n", lpStr );
1999 SEGPTR_FREE(buffer);
2000 return TRUE;
2002 strcpy( lpStr, buffer + 1 );
2003 lpStr[strlen(lpStr)-1] = '\\';
2004 dprintf_listbox( stddeb, "Returning directory '%s'\n", lpStr );
2005 SEGPTR_FREE(buffer);
2006 return TRUE;
2008 strcpy( lpStr, buffer );
2009 dprintf_listbox( stddeb, "Returning file '%s'\n", lpStr );
2010 SEGPTR_FREE(buffer);
2011 return FALSE;
2015 /**********************************************************************
2016 * DlgDirList (USER.100)
2018 INT DlgDirList( HWND hDlg, SEGPTR spec, INT idLBox, INT idStatic, UINT attrib )
2020 char *filespec = (char *)PTR_SEG_TO_LIN( spec );
2021 int drive;
2022 HWND hwnd;
2024 #define SENDMSG(msg,wparam,lparam) \
2025 ((attrib & DDL_POSTMSGS) ? PostMessage( hwnd, msg, wparam, lparam ) \
2026 : SendMessage16( hwnd, msg, wparam, lparam ))
2028 dprintf_listbox( stddeb, "DlgDirList: %04x '%s' %d %d %04x\n",
2029 hDlg, filespec ? filespec : "NULL",
2030 idLBox, idStatic, attrib );
2032 if (filespec && filespec[0] && (filespec[1] == ':'))
2034 drive = toupper( filespec[0] ) - 'A';
2035 filespec += 2;
2036 if (!DRIVE_SetCurrentDrive( drive )) return FALSE;
2038 else drive = DRIVE_GetCurrentDrive();
2040 if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
2042 char mask[20];
2044 if (!filespec || !filespec[0]) strcpy( mask, "*.*" );
2045 else
2047 /* If the path exists and is a directory, chdir to it */
2048 if (DRIVE_Chdir( drive, filespec )) strcpy( mask, "*.*" );
2049 else
2051 char *p, *p2;
2052 p = filespec;
2053 if ((p2 = strrchr( p, '\\' ))) p = p2 + 1;
2054 if ((p2 = strrchr( p, '/' ))) p = p2 + 1;
2055 lstrcpyn32A( mask, p, sizeof(mask) );
2056 if (p != filespec)
2058 p[-1] = '\0';
2059 if (!DRIVE_Chdir( drive, filespec )) return FALSE;
2064 strcpy( (char *)PTR_SEG_TO_LIN(spec), mask );
2066 dprintf_listbox(stddeb, "ListBoxDirectory: path=%c:\\%s mask=%s\n",
2067 'A' + drive, DRIVE_GetDosCwd(drive), mask);
2069 SENDMSG( LB_RESETCONTENT, 0, 0 );
2070 if ((attrib & DDL_DIRECTORY) && !(attrib & DDL_EXCLUSIVE))
2072 char *temp;
2073 if (SENDMSG( LB_DIR, attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
2074 (LPARAM)spec ) == LB_ERR) return FALSE;
2075 if (!(temp = SEGPTR_ALLOC( 4*sizeof(char) ))) return FALSE;
2076 strcpy( temp, "*.*" );
2077 /* FIXME: this won't work with PostMessage(), as temp will */
2078 /* have been freed by the time we do a DispatchMessage(). */
2079 if (SENDMSG( LB_DIR, (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
2080 (LPARAM)SEGPTR_GET(temp) ) == LB_ERR)
2082 SEGPTR_FREE(temp);
2083 return FALSE;
2085 SEGPTR_FREE(temp);
2087 else
2089 if (SENDMSG( LB_DIR, attrib, (LPARAM)spec) == LB_ERR) return FALSE;
2093 if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
2095 char temp[512];
2096 int drive = DRIVE_GetCurrentDrive();
2097 strcpy( temp, "A:\\" );
2098 temp[0] += drive;
2099 lstrcpyn32A( temp + 3, DRIVE_GetDosCwd(drive), sizeof(temp)-3 );
2100 AnsiLower( temp );
2101 /* Can't use PostMessage() here, because the string is on the stack */
2102 SetDlgItemText32A( hDlg, idStatic, temp );
2104 return TRUE;
2105 #undef SENDMSG