4 * Copyright Martin Ayotte, 1993
5 * Constantine Sapuntzakis, 1995
6 * Alex Korobka, 1995, 1996
12 * - proper scrolling for multicolumn style
13 * - anchor and caret for LBS_EXTENDEDSEL
14 * - proper selection with keyboard
15 * - how to handle (LBS_EXTENDEDSEL | LBS_MULTIPLESEL) style
16 * - support for LBS_NOINTEGRALHEIGHT and LBS_OWNERDRAWVARIABLE styles
36 #define LIST_HEAP_ALLOC(lphl,f,size) \
37 LOCAL_Alloc( lphl->HeapSel, LMEM_FIXED, (size) )
38 #define LIST_HEAP_FREE(lphl,handle) \
39 LOCAL_Free( lphl->HeapSel, (handle) )
40 #define LIST_HEAP_ADDR(lphl,handle) \
41 ((handle) ? PTR_SEG_OFF_TO_LIN(lphl->HeapSel, (handle)) : NULL)
43 #define LIST_HEAP_SIZE 0x10000
45 #define LBMM_EDGE 4 /* distance inside box which is same as moving mouse
46 outside box, to trigger scrolling of LB */
48 #define MATCH_SUBSTR 2
50 #define MATCH_NEAREST 0
52 static void ListBoxInitialize(LPHEADLIST lphl
)
56 lphl
->ItemsVisible
= 0;
57 lphl
->FirstVisible
= 0;
58 lphl
->ColumnsVisible
= 1;
59 lphl
->ItemsPerColumn
= 0;
60 lphl
->ItemFocused
= -1;
61 lphl
->PrevFocused
= -1;
64 void CreateListBoxStruct(HWND hwnd
, WORD CtlType
, LONG styles
, HWND parent
)
69 lphl
= (LPHEADLIST
)xmalloc(sizeof(HEADLIST
));
70 SetWindowLong32A(hwnd
, 0, (LONG
)lphl
);
71 ListBoxInitialize(lphl
);
72 lphl
->DrawCtlType
= CtlType
;
73 lphl
->CtlID
= GetWindowWord(hwnd
,GWW_ID
);
74 lphl
->bRedrawFlag
= TRUE
;
76 lphl
->TabStops
= NULL
;
77 lphl
->hFont
= GetStockObject(SYSTEM_FONT
);
79 if (CtlType
==ODT_COMBOBOX
) /* use the "faked" style for COMBOLBOX */
80 /* LBS_SORT instead CBS_SORT e.g. */
81 lphl
->dwStyle
= MAKELONG(LOWORD(styles
),HIWORD(GetWindowLong32A(hwnd
,GWL_STYLE
)));
83 lphl
->dwStyle
= GetWindowLong32A(hwnd
,GWL_STYLE
); /* use original style dword */
84 lphl
->hParent
= parent
;
85 lphl
->StdItemHeight
= 15; /* FIXME: should get the font height */
86 lphl
->OwnerDrawn
= styles
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
);
87 lphl
->HasStrings
= (styles
& LBS_HASSTRINGS
) || !lphl
->OwnerDrawn
;
89 /* create dummy hdc to set text height */
90 if ((hdc
= GetDC32(0)))
93 GetTextMetrics16( hdc
, &tm
);
94 lphl
->StdItemHeight
= tm
.tmHeight
;
95 dprintf_listbox(stddeb
,"CreateListBoxStruct: font height %d\n",
97 ReleaseDC32( 0, hdc
);
100 if (lphl
->OwnerDrawn
)
104 lphl
->needMeasure
= TRUE
;
105 dummyls
.mis
.CtlType
= lphl
->DrawCtlType
;
106 dummyls
.mis
.CtlID
= lphl
->CtlID
;
107 dummyls
.mis
.itemID
= -1;
108 dummyls
.mis
.itemWidth
= 0; /* ignored */
109 dummyls
.mis
.itemData
= 0;
111 ListBoxAskMeasure(lphl
,&dummyls
);
114 lphl
->HeapSel
= GlobalAlloc16(GMEM_FIXED
,LIST_HEAP_SIZE
);
115 LocalInit( lphl
->HeapSel
, 0, LIST_HEAP_SIZE
-1);
118 void DestroyListBoxStruct(LPHEADLIST lphl
)
120 /* XXX need to free lphl->Heap */
121 GlobalFree16(lphl
->HeapSel
);
125 static LPHEADLIST
ListBoxGetStorageHeader(HWND hwnd
)
127 return (LPHEADLIST
)GetWindowLong32A(hwnd
,0);
130 /* Send notification "code" as part of a WM_COMMAND-message if hwnd
131 has the LBS_NOTIFY style */
132 void ListBoxSendNotification(LPHEADLIST lphl
, WORD code
)
134 if (lphl
->dwStyle
& LBS_NOTIFY
)
135 SendMessage32A( lphl
->hParent
, WM_COMMAND
,
136 MAKEWPARAM( lphl
->CtlID
, code
), (LPARAM
)lphl
->hSelf
);
140 /* get the maximum value of lphl->FirstVisible */
141 int ListMaxFirstVisible(LPHEADLIST lphl
)
143 int m
= lphl
->ItemsCount
-lphl
->ItemsVisible
;
144 return (m
< 0) ? 0 : m
;
148 void ListBoxUpdateWindow(HWND hwnd
, LPHEADLIST lphl
, BOOL repaint
)
150 if (lphl
->dwStyle
& WS_VSCROLL
)
151 SetScrollRange32(hwnd
, SB_VERT
, 0, ListMaxFirstVisible(lphl
), TRUE
);
152 if ((lphl
->dwStyle
& WS_HSCROLL
) && (lphl
->ItemsPerColumn
!= 0))
153 SetScrollRange32(hwnd
, SB_HORZ
, 1, lphl
->ItemsVisible
/
154 lphl
->ItemsPerColumn
+ 1, TRUE
);
156 if (repaint
&& lphl
->bRedrawFlag
) InvalidateRect32( hwnd
, NULL
, TRUE
);
159 /* Returns: 0 if nothing needs to be changed */
160 /* 1 if FirstVisible changed */
162 int ListBoxScrollToFocus(LPHEADLIST lphl
)
166 if (lphl
->ItemsCount
== 0) return 0;
167 if (lphl
->ItemFocused
== -1) return 0;
169 end
= lphl
->FirstVisible
+ lphl
->ItemsVisible
- 1;
171 if (lphl
->ItemFocused
< lphl
->FirstVisible
) {
172 lphl
->FirstVisible
= lphl
->ItemFocused
;
175 if (lphl
->ItemFocused
> end
) {
176 WORD maxFirstVisible
= ListMaxFirstVisible(lphl
);
178 lphl
->FirstVisible
= lphl
->ItemFocused
;
180 if (lphl
->FirstVisible
> maxFirstVisible
) {
181 lphl
->FirstVisible
= maxFirstVisible
;
190 LPLISTSTRUCT
ListBoxGetItem(LPHEADLIST lphl
, UINT uIndex
)
195 if (uIndex
>= lphl
->ItemsCount
) return NULL
;
197 lpls
= lphl
->lpFirst
;
198 while (Count
++ < uIndex
) lpls
= lpls
->lpNext
;
203 void ListBoxDrawItem (HWND hwnd
, LPHEADLIST lphl
, HDC hdc
, LPLISTSTRUCT lpls
,
204 RECT16
*rect
, WORD itemAction
, WORD itemState
)
206 if (lphl
->OwnerDrawn
)
208 DRAWITEMSTRUCT32 dis
;
210 dis
.CtlID
= lpls
->mis
.CtlID
;
211 dis
.CtlType
= lpls
->mis
.CtlType
;
212 dis
.itemID
= lpls
->mis
.itemID
;
215 dis
.itemData
= lpls
->mis
.itemData
;
216 dis
.itemAction
= itemAction
;
217 dis
.itemState
= itemState
;
218 CONV_RECT16TO32( rect
, &dis
.rcItem
);
219 SendMessage32A( lphl
->hParent
, WM_DRAWITEM
, dis
.CtlID
, (LPARAM
)&dis
);
222 if (itemAction
== ODA_DRAWENTIRE
|| itemAction
== ODA_SELECT
) {
224 DWORD dwOldTextColor
= 0;
226 OldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
228 if (itemState
!= 0) {
229 dwOldTextColor
= SetTextColor(hdc
, 0x00FFFFFFL
);
230 FillRect16(hdc
, rect
, GetStockObject(BLACK_BRUSH
));
233 if (lphl
->dwStyle
& LBS_USETABSTOPS
) {
234 TabbedTextOut(hdc
, rect
->left
+ 5, rect
->top
+ 2,
235 (char *)lpls
->itemText
, strlen((char *)lpls
->itemText
),
236 lphl
->iNumStops
, lphl
->TabStops
, 0);
238 TextOut16(hdc
, rect
->left
+ 5, rect
->top
+ 2,
239 (char *)lpls
->itemText
, strlen((char *)lpls
->itemText
));
242 if (itemState
!= 0) {
243 SetTextColor(hdc
, dwOldTextColor
);
246 SetBkMode(hdc
, OldBkMode
);
248 else DrawFocusRect16(hdc
, rect
);
252 int ListBoxFindMouse(LPHEADLIST lphl
, int X
, int Y
)
254 LPLISTSTRUCT lpls
= lphl
->lpFirst
;
258 point
.x
= X
; point
.y
= Y
;
259 if (lphl
->ItemsCount
== 0) return LB_ERR
;
261 for(i
= 0; i
< lphl
->FirstVisible
; i
++) {
262 if (lpls
== NULL
) return LB_ERR
;
265 for(j
= 0; j
< lphl
->ItemsVisible
; i
++, j
++) {
266 if (lpls
== NULL
) return LB_ERR
;
267 if (PtInRect16(&lpls
->itemRect
,point
)) {
272 dprintf_listbox(stddeb
,"ListBoxFindMouse: not found\n");
276 BOOL32
lbDeleteItemNotify(LPHEADLIST lphl
, LPLISTSTRUCT lpls
)
278 /* called only for owner drawn listboxes */
280 DELETEITEMSTRUCT16
*delItem
= SEGPTR_NEW(DELETEITEMSTRUCT16
);
281 if (!delItem
) return FALSE
;
283 delItem
->CtlType
= lphl
->DrawCtlType
;
284 delItem
->CtlID
= lphl
->CtlID
;
285 delItem
->itemID
= lpls
->mis
.itemID
;
286 delItem
->hwndItem
= lphl
->hSelf
;
287 delItem
->itemData
= lpls
->mis
.itemData
;
289 ret
= SendMessage16( lphl
->hParent
, WM_DELETEITEM
, (WPARAM
)lphl
->CtlID
,
290 (LPARAM
)SEGPTR_GET(delItem
) );
291 SEGPTR_FREE(delItem
);
295 void ListBoxAskMeasure(LPHEADLIST lphl
, LPLISTSTRUCT lpls
)
297 MEASUREITEMSTRUCT16
*lpmeasure
= SEGPTR_NEW(MEASUREITEMSTRUCT16
);
298 if (!lpmeasure
) return;
299 *lpmeasure
= lpls
->mis
;
300 lpmeasure
->itemHeight
= lphl
->StdItemHeight
;
301 SendMessage16( lphl
->hParent
, WM_MEASUREITEM
, lphl
->CtlID
,
302 (LPARAM
)SEGPTR_GET(lpmeasure
) );
304 if (lphl
->dwStyle
& LBS_OWNERDRAWFIXED
)
306 if (lpmeasure
->itemHeight
> lphl
->StdItemHeight
)
307 lphl
->StdItemHeight
= lpmeasure
->itemHeight
;
308 lpls
->mis
.itemHeight
= lpmeasure
->itemHeight
;
310 SEGPTR_FREE(lpmeasure
);
313 /* -------------------- strings and item data ---------------------- */
315 LPLISTSTRUCT
ListBoxCreateItem(LPHEADLIST lphl
, int id
)
317 LPLISTSTRUCT lplsnew
= (LPLISTSTRUCT
)malloc(sizeof(LISTSTRUCT
));
319 if (lplsnew
== NULL
) return NULL
;
321 lplsnew
->itemState
= 0;
322 lplsnew
->mis
.CtlType
= lphl
->DrawCtlType
;
323 lplsnew
->mis
.CtlID
= lphl
->CtlID
;
324 lplsnew
->mis
.itemID
= id
;
325 lplsnew
->mis
.itemHeight
= lphl
->StdItemHeight
;
326 lplsnew
->mis
.itemWidth
= 0; /* ignored */
327 lplsnew
->mis
.itemData
= 0;
328 SetRectEmpty16( &lplsnew
->itemRect
);
333 int ListBoxAskCompare(LPHEADLIST lphl
, int startItem
, SEGPTR matchData
, BOOL exactMatch
)
335 /* Do binary search for sorted listboxes. Linked list item storage sort of
336 * defeats the purpose ( forces to traverse item list all the time ) but M$ does it this way...
338 * MATCH_NEAREST (0) - return position for insertion - for all styles
339 * MATCH_EXACT (1) - search for an item, return index or LB_ERR
340 * MATCH_SUBSTR (2) - same as exact match but with strncmp for string comparision
343 COMPAREITEMSTRUCT16
*itemCmp
;
344 LPLISTSTRUCT currentItem
= NULL
;
345 LPCSTR matchStr
= (lphl
->HasStrings
)?(LPCSTR
)PTR_SEG_TO_LIN(matchData
):NULL
;
346 int head
, pos
= -1, tail
, loop
= 1;
347 short b
= 0, s_length
= 0;
351 if( !lphl
->ItemsCount
)
352 return (exactMatch
)? LB_ERR
: 0;
354 /* set up variables */
356 if( exactMatch
== MATCH_NEAREST
)
358 else if( ++startItem
)
361 if( startItem
>= lphl
->ItemsCount
) startItem
= lphl
->ItemsCount
- 1;
364 if( exactMatch
== MATCH_SUBSTR
&& lphl
->HasStrings
)
366 s_length
= strlen( matchStr
);
367 if( !s_length
) return 0; /* head of the list - empty string */
370 head
= startItem
; tail
= lphl
->ItemsCount
- 1;
372 dprintf_listbox(stddeb
,"AskCompare: head = %i, tail = %i, data = %08x\n", head
, tail
, (unsigned)matchData
);
374 if (!(itemCmp
= SEGPTR_NEW(COMPAREITEMSTRUCT16
))) return 0;
375 itemCmp
->CtlType
= lphl
->DrawCtlType
;
376 itemCmp
->CtlID
= lphl
->CtlID
;
377 itemCmp
->hwndItem
= lphl
->hSelf
;
379 /* search from startItem */
383 while( head
<= tail
)
385 pos
= (tail
+ head
)/2;
386 currentItem
= ListBoxGetItem( lphl
, pos
);
388 if( lphl
->HasStrings
)
390 b
= ( s_length
)? lstrncmpi32A( currentItem
->itemText
, matchStr
, s_length
)
391 : lstrcmpi32A( currentItem
->itemText
, matchStr
);
395 itemCmp
->itemID1
= pos
;
396 itemCmp
->itemData1
= currentItem
->mis
.itemData
;
397 itemCmp
->itemID2
= -1;
398 itemCmp
->itemData2
= matchData
;
400 b
= SendMessage16( lphl
->hParent
, WM_COMPAREITEM
, (WPARAM
)lphl
->CtlID
,
401 (LPARAM
)SEGPTR_GET(itemCmp
) );
406 SEGPTR_FREE(itemCmp
);
407 return pos
; /* found exact match */
410 if( b
< 0 ) head
= ++pos
;
412 if( b
> 0 ) tail
= pos
- 1;
415 /* reset to search from the first item */
416 head
= 0; tail
= startItem
- 1;
419 dprintf_listbox(stddeb
,"\t-> pos = %i\n", pos
);
420 SEGPTR_FREE(itemCmp
);
422 /* if we got here match is not exact */
424 if( pos
< 0 ) pos
= 0;
425 else if( pos
> lphl
->ItemsCount
) pos
= lphl
->ItemsCount
;
427 return (exactMatch
)? LB_ERR
: pos
;
430 int ListBoxInsertString(LPHEADLIST lphl
, UINT uIndex
, LPCSTR newstr
)
432 LPLISTSTRUCT
*lppls
, lplsnew
, lpls
;
437 dprintf_listbox(stddeb
,"ListBoxInsertString(%d, %p);\n", uIndex
, newstr
);
439 if (!newstr
) return -1;
441 if (uIndex
== (UINT
)-1)
442 uIndex
= lphl
->ItemsCount
;
444 lppls
= &lphl
->lpFirst
;
445 for(Count
= 0; Count
< uIndex
; Count
++) {
446 if (*lppls
== NULL
) return LB_ERR
;
447 lppls
= (LPLISTSTRUCT
*) &(*lppls
)->lpNext
;
450 lplsnew
= ListBoxCreateItem(lphl
, Count
);
452 if (lplsnew
== NULL
) {
453 fprintf(stdnimp
,"ListBoxInsertString() out of memory !\n");
457 lplsnew
->lpNext
= *lppls
;
462 if (lphl
->HasStrings
) {
463 dprintf_listbox(stddeb
," string: %s\n", newstr
);
464 hStr
= LIST_HEAP_ALLOC(lphl
, LMEM_MOVEABLE
, strlen(newstr
) + 1);
465 str
= (LPSTR
)LIST_HEAP_ADDR(lphl
, hStr
);
466 if (str
== NULL
) return LB_ERRSPACE
;
468 lplsnew
->itemText
= str
;
469 /* I'm not so sure about the next one */
470 lplsnew
->mis
.itemData
= 0;
472 lplsnew
->itemText
= NULL
;
473 lplsnew
->mis
.itemData
= (DWORD
)newstr
;
476 lplsnew
->mis
.itemID
= uIndex
;
477 lplsnew
->hData
= hStr
;
479 /* adjust the itemID field of the following entries */
480 for(lpls
= lplsnew
->lpNext
; lpls
!= NULL
; lpls
= lpls
->lpNext
) {
484 if (lphl
->needMeasure
) {
485 ListBoxAskMeasure(lphl
, lplsnew
);
488 dprintf_listbox(stddeb
,"ListBoxInsertString // count=%d\n", lphl
->ItemsCount
);
493 int ListBoxAddString(LPHEADLIST lphl
, SEGPTR itemData
)
495 UINT pos
= (UINT
) -1;
496 LPCSTR newstr
= (lphl
->HasStrings
)?(LPCSTR
)PTR_SEG_TO_LIN(itemData
):(LPCSTR
)itemData
;
498 if ( lphl
->dwStyle
& LBS_SORT
)
499 pos
= ListBoxAskCompare( lphl
, -1, itemData
, MATCH_NEAREST
);
501 return ListBoxInsertString(lphl
, pos
, newstr
);
505 int ListBoxGetText(LPHEADLIST lphl
, UINT uIndex
, LPSTR OutStr
)
510 dprintf_listbox(stddeb
, "ListBoxGetText // OutStr==NULL\n");
514 lpls
= ListBoxGetItem (lphl
, uIndex
);
515 if (lpls
== NULL
) return LB_ERR
;
517 if (!lphl
->HasStrings
) {
518 *((long *)OutStr
) = lpls
->mis
.itemData
;
522 strcpy(OutStr
, lpls
->itemText
);
523 return strlen(OutStr
);
527 DWORD
ListBoxGetItemData(LPHEADLIST lphl
, UINT uIndex
)
531 lpls
= ListBoxGetItem (lphl
, uIndex
);
532 if (lpls
== NULL
) return LB_ERR
;
533 return lpls
->mis
.itemData
;
537 int ListBoxSetItemData(LPHEADLIST lphl
, UINT uIndex
, DWORD ItemData
)
539 LPLISTSTRUCT lpls
= ListBoxGetItem(lphl
, uIndex
);
541 if (lpls
== NULL
) return LB_ERR
;
542 lpls
->mis
.itemData
= ItemData
;
547 int ListBoxDeleteString(LPHEADLIST lphl
, UINT uIndex
)
549 LPLISTSTRUCT lpls
, lpls2
;
552 if (uIndex
>= lphl
->ItemsCount
) return LB_ERR
;
554 lpls
= lphl
->lpFirst
;
555 if (lpls
== NULL
) return LB_ERR
;
559 if( lphl
->OwnerDrawn
)
560 lbDeleteItemNotify( lphl
, lpls
);
561 lphl
->lpFirst
= lpls
->lpNext
;
565 LPLISTSTRUCT lpls2
= NULL
;
566 for(Count
= 0; Count
< uIndex
; Count
++) {
567 if (lpls
->lpNext
== NULL
) return LB_ERR
;
570 lpls
= (LPLISTSTRUCT
)lpls
->lpNext
;
572 if( lphl
->OwnerDrawn
)
573 lbDeleteItemNotify( lphl
, lpls
);
574 lpls2
->lpNext
= lpls
->lpNext
;
577 /* adjust the itemID field of the following entries */
578 for(lpls2
= lpls
->lpNext
; lpls2
!= NULL
; lpls2
= lpls2
->lpNext
) {
584 if (lpls
->hData
!= 0) LIST_HEAP_FREE(lphl
, lpls
->hData
);
587 return lphl
->ItemsCount
;
590 int lbFindString(LPHEADLIST lphl
, UINT nFirst
, SEGPTR MatchStr
, BOOL match
)
592 /* match is either MATCH_SUBSTR or MATCH_EXACT */
596 UINT First
= nFirst
+ 1;
598 LPSTR lpMatchStr
= (LPSTR
)MatchStr
;
600 if (First
> lphl
->ItemsCount
) return LB_ERR
;
602 if (lphl
->dwStyle
& LBS_SORT
)
603 return ListBoxAskCompare( lphl
, nFirst
, MatchStr
, match
);
605 if (lphl
->HasStrings
)
607 lpMatchStr
= PTR_SEG_TO_LIN(MatchStr
);
609 if( match
== MATCH_SUBSTR
)
611 s_length
= strlen(lpMatchStr
);
612 if( !s_length
) return (lphl
->ItemsCount
)?0:LB_ERR
;
616 lpls
= ListBoxGetItem(lphl
, First
);
620 if (lphl
->HasStrings
)
622 if ( ( s_length
)? !lstrncmpi32A(lpls
->itemText
, lpMatchStr
, s_length
)
623 : !lstrcmpi32A(lpls
->itemText
, lpMatchStr
) ) return Count
;
626 if ( lpls
->mis
.itemData
== (DWORD
)lpMatchStr
) return Count
;
632 /* Start over at top */
634 lpls
= lphl
->lpFirst
;
636 while (Count
< First
)
638 if (lphl
->HasStrings
)
640 if ( ( s_length
)? !lstrncmpi32A(lpls
->itemText
, lpMatchStr
, s_length
)
641 : !lstrcmpi32A(lpls
->itemText
, lpMatchStr
) ) return Count
;
644 if ( lpls
->mis
.itemData
== (DWORD
)lpMatchStr
) return Count
;
653 int ListBoxFindString(LPHEADLIST lphl
, UINT nFirst
, SEGPTR MatchStr
)
655 return lbFindString(lphl
, nFirst
, MatchStr
, MATCH_SUBSTR
);
658 int ListBoxFindStringExact(LPHEADLIST lphl
, UINT nFirst
, SEGPTR MatchStr
)
660 return lbFindString(lphl
, nFirst
, MatchStr
, MATCH_EXACT
);
663 int ListBoxResetContent(LPHEADLIST lphl
)
668 if (lphl
->ItemsCount
== 0) return 0;
670 dprintf_listbox(stddeb
, "ListBoxResetContent // ItemCount = %d\n",
673 for(i
= 0; i
< lphl
->ItemsCount
; i
++) {
674 lpls
= lphl
->lpFirst
;
675 if (lpls
== NULL
) return LB_ERR
;
677 if (lphl
->OwnerDrawn
) lbDeleteItemNotify(lphl
, lpls
);
679 lphl
->lpFirst
= lpls
->lpNext
;
680 if (lpls
->hData
!= 0) LIST_HEAP_FREE(lphl
, lpls
->hData
);
683 ListBoxInitialize(lphl
);
688 /* --------------------- selection ------------------------- */
690 int ListBoxSetCurSel(LPHEADLIST lphl
, WORD wIndex
)
694 /* use ListBoxSetSel instead */
695 if (lphl
->dwStyle
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
) ) return 0;
697 /* unselect previous item */
698 if (lphl
->ItemFocused
!= -1) {
699 lphl
->PrevFocused
= lphl
->ItemFocused
;
700 lpls
= ListBoxGetItem(lphl
, lphl
->ItemFocused
);
701 if (lpls
== 0) return LB_ERR
;
705 if ((wIndex
!= (UINT
)-1) && (wIndex
< lphl
->ItemsCount
))
707 lphl
->ItemFocused
= wIndex
;
708 lpls
= ListBoxGetItem(lphl
, wIndex
);
709 if (lpls
== 0) return LB_ERR
;
710 lpls
->itemState
= ODS_SELECTED
| ODS_FOCUS
;
719 int ListBoxSetSel(LPHEADLIST lphl
, WORD wIndex
, WORD state
)
724 if (!(lphl
->dwStyle
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
) ))
727 if (wIndex
== (UINT
)-1) {
728 for (lpls
= lphl
->lpFirst
; lpls
!= NULL
; lpls
= lpls
->lpNext
) {
729 if( lpls
->itemState
& ODS_SELECTED
) n
++;
730 lpls
->itemState
= state
? lpls
->itemState
| ODS_SELECTED
731 : lpls
->itemState
& ~ODS_SELECTED
;
736 if (wIndex
>= lphl
->ItemsCount
) return LB_ERR
;
738 lpls
= ListBoxGetItem(lphl
, wIndex
);
739 lpls
->itemState
= state
? lpls
->itemState
| ODS_SELECTED
740 : lpls
->itemState
& ~ODS_SELECTED
;
746 int ListBoxGetSel(LPHEADLIST lphl
, WORD wIndex
)
748 LPLISTSTRUCT lpls
= ListBoxGetItem(lphl
, wIndex
);
750 if (lpls
== NULL
) return LB_ERR
;
751 return lpls
->itemState
& ODS_SELECTED
;
754 /* ------------------------- dir listing ------------------------ */
756 LONG
ListBoxDirectory(LPHEADLIST lphl
, UINT attrib
, LPCSTR filespec
)
766 dprintf_listbox(stddeb
, "ListBoxDirectory: '%s' %04x\n", filespec
, attrib
);
767 if (!filespec
) return LB_ERR
;
768 if (!(ptr
= DOSFS_GetUnixFileName( filespec
, FALSE
))) return LB_ERR
;
770 p
= strrchr( path
, '/' );
772 if (!(ptr
= DOSFS_ToDosFCBFormat( p
)) ||
773 !(temp
= SEGPTR_ALLOC( sizeof(char) * 16 )) )
781 dprintf_listbox(stddeb
, "ListBoxDirectory: path=%s mask=%s\n", path
, mask
);
785 while ((count
= DOSFS_FindNext( path
, mask
, 0, attrib
, skip
, &entry
)) > 0)
788 if (entry
.attr
& FA_DIRECTORY
)
790 if ((attrib
& DDL_DIRECTORY
) && strcmp(entry
.name
, ". "))
792 sprintf(temp
, "[%s]", DOSFS_ToDosDTAFormat( entry
.name
) );
794 if ((ret
= ListBoxAddString(lphl
, SEGPTR_GET(temp
))) == LB_ERR
) break;
797 else /* not a directory */
799 if (!(attrib
& DDL_EXCLUSIVE
) ||
800 ((attrib
& (FA_RDONLY
|FA_HIDDEN
|FA_SYSTEM
|FA_ARCHIVE
)) ==
801 (entry
.attr
& (FA_RDONLY
|FA_HIDDEN
|FA_SYSTEM
|FA_ARCHIVE
))))
803 strcpy( temp
, DOSFS_ToDosDTAFormat( entry
.name
) );
805 if ((ret
= ListBoxAddString(lphl
, SEGPTR_GET(temp
))) == LB_ERR
) break;
809 dprintf_listbox(stddeb
,"\tn - %i, file '%s'\n", count
, temp
);
811 if (attrib
& DDL_DRIVES
)
814 DWORD oldstyle
= lphl
->dwStyle
;
816 lphl
->dwStyle
&= ~LBS_SORT
;
817 strcpy( temp
, "[-a-]" );
818 for (x
= 0; x
< MAX_DOS_DRIVES
; x
++, temp
[2]++)
820 if (DRIVE_IsValid(x
))
821 if ((ret
= ListBoxAddString(lphl
, SEGPTR_GET(temp
))) == LB_ERR
) break;
823 lphl
->dwStyle
= oldstyle
;
832 /* ------------------------- dimensions ------------------------- */
834 int ListBoxGetItemRect(LPHEADLIST lphl
, WORD wIndex
, LPRECT16 lprect
)
836 LPLISTSTRUCT lpls
= ListBoxGetItem(lphl
,wIndex
);
838 dprintf_listbox(stddeb
,"ListBox LB_GETITEMRECT %i %p", wIndex
,lpls
);
841 if (lphl
->dwStyle
& LBS_OWNERDRAWVARIABLE
)
845 GetClientRect16(lphl
->hSelf
,lprect
);
846 lprect
->bottom
=lphl
->StdItemHeight
;
847 if (lprect
->right
<0) lprect
->right
=0;
851 *lprect
= lpls
->itemRect
;
852 dprintf_listbox(stddeb
," = %d,%d %d,%d\n", lprect
->left
,lprect
->top
,
853 lprect
->right
,lprect
->bottom
);
858 int ListBoxSetItemHeight(LPHEADLIST lphl
, WORD wIndex
, long height
)
862 if (!(lphl
->dwStyle
& LBS_OWNERDRAWVARIABLE
)) {
863 lphl
->StdItemHeight
= (short)height
;
867 lpls
= ListBoxGetItem(lphl
, wIndex
);
868 if (lpls
== NULL
) return LB_ERR
;
870 lpls
->mis
.itemHeight
= height
;
874 /* -------------------------- string search ------------------------ */
876 int ListBoxFindNextMatch(LPHEADLIST lphl
, WORD wChar
)
881 if ((char)wChar
< ' ') return LB_ERR
;
882 if (!lphl
->HasStrings
) return LB_ERR
;
884 lpls
= lphl
->lpFirst
;
886 for (count
= 0; lpls
!= NULL
; lpls
= lpls
->lpNext
, count
++) {
887 if (tolower(*lpls
->itemText
) == tolower((char)wChar
)) break;
889 if (lpls
== NULL
) return LB_ERR
;
891 for(; lpls
!= NULL
; lpls
= lpls
->lpNext
, count
++) {
892 if (*lpls
->itemText
!= (char)wChar
)
894 if ((short) count
> lphl
->ItemFocused
)
900 /***********************************************************************
903 static LONG
LBCreate(HWND hwnd
, WORD wParam
, LONG lParam
)
906 LONG dwStyle
= GetWindowLong32A(hwnd
,GWL_STYLE
);
909 CreateListBoxStruct(hwnd
, ODT_LISTBOX
, dwStyle
, GetParent16(hwnd
));
910 lphl
= ListBoxGetStorageHeader(hwnd
);
911 dprintf_listbox(stddeb
,"ListBox created: lphl = %p dwStyle = %04x:%04x\n",
912 lphl
, HIWORD(dwStyle
), LOWORD(dwStyle
));
914 GetClientRect16(hwnd
,&rect
);
915 lphl
->ColumnsWidth
= rect
.right
- rect
.left
;
917 if (dwStyle
& WS_VSCROLL
)
918 SetScrollRange32(hwnd
, SB_VERT
, 0, ListMaxFirstVisible(lphl
), TRUE
);
919 if (dwStyle
& WS_HSCROLL
)
920 SetScrollRange32(hwnd
, SB_HORZ
, 1, 1, TRUE
);
926 /***********************************************************************
929 static LONG
LBDestroy(HWND hwnd
, WORD wParam
, LONG lParam
)
931 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
933 ListBoxResetContent(lphl
);
935 DestroyListBoxStruct(lphl
);
936 dprintf_listbox(stddeb
,"ListBox destroyed: lphl = %p\n",lphl
);
941 /***********************************************************************
944 static LONG
LBNCCalcSize(HWND hwnd
, WORD wParam
, LONG lParam
)
946 LONG ret
= DefWindowProc16(hwnd
, WM_NCCALCSIZE
, wParam
, lParam
);
948 return (GetWindowLong32A(hwnd
,GWL_STYLE
) & LBS_MULTICOLUMN
)? WVR_VREDRAW
: ret
;
952 /***********************************************************************
955 static LONG
LBVScroll(HWND hwnd
, WORD wParam
, LONG lParam
)
957 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
960 dprintf_listbox(stddeb
,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
962 y
= lphl
->FirstVisible
;
966 if (lphl
->FirstVisible
> 0)
967 lphl
->FirstVisible
--;
971 lphl
->FirstVisible
++;
975 if (lphl
->FirstVisible
> lphl
->ItemsVisible
) {
976 lphl
->FirstVisible
-= lphl
->ItemsVisible
;
978 lphl
->FirstVisible
= 0;
983 lphl
->FirstVisible
+= lphl
->ItemsVisible
;
987 lphl
->FirstVisible
= LOWORD(lParam
);
991 if (lphl
->FirstVisible
> ListMaxFirstVisible(lphl
))
992 lphl
->FirstVisible
= ListMaxFirstVisible(lphl
);
994 if (y
!= lphl
->FirstVisible
) {
995 SetScrollPos32(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
996 InvalidateRect32( hwnd
, NULL
, TRUE
);
1001 /***********************************************************************
1004 static LONG
LBHScroll(HWND hwnd
, WORD wParam
, LONG lParam
)
1009 dprintf_listbox(stddeb
,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
1011 lphl
= ListBoxGetStorageHeader(hwnd
);
1012 y
= lphl
->FirstVisible
;
1015 if (lphl
->FirstVisible
> lphl
->ItemsPerColumn
) {
1016 lphl
->FirstVisible
-= lphl
->ItemsPerColumn
;
1018 lphl
->FirstVisible
= 0;
1022 lphl
->FirstVisible
+= lphl
->ItemsPerColumn
;
1025 if (lphl
->ItemsPerColumn
!= 0) {
1026 int lbsub
= lphl
->ItemsVisible
/ lphl
->ItemsPerColumn
* lphl
->ItemsPerColumn
;
1027 if (lphl
->FirstVisible
> lbsub
) {
1028 lphl
->FirstVisible
-= lbsub
;
1030 lphl
->FirstVisible
= 0;
1035 if (lphl
->ItemsPerColumn
!= 0)
1036 lphl
->FirstVisible
+= lphl
->ItemsVisible
/
1037 lphl
->ItemsPerColumn
* lphl
->ItemsPerColumn
;
1040 lphl
->FirstVisible
= lphl
->ItemsPerColumn
* LOWORD(lParam
);
1043 if (lphl
->FirstVisible
> ListMaxFirstVisible(lphl
))
1044 lphl
->FirstVisible
= ListMaxFirstVisible(lphl
);
1046 if (lphl
->ItemsPerColumn
!= 0) {
1047 lphl
->FirstVisible
= lphl
->FirstVisible
/
1048 lphl
->ItemsPerColumn
* lphl
->ItemsPerColumn
+ 1;
1049 if (y
!= lphl
->FirstVisible
) {
1050 SetScrollPos32(hwnd
, SB_HORZ
, lphl
->FirstVisible
/
1051 lphl
->ItemsPerColumn
+ 1, TRUE
);
1052 InvalidateRect32( hwnd
, NULL
, TRUE
);
1058 /***********************************************************************
1061 static LONG
LBLButtonDown(HWND hwnd
, WORD wParam
, LONG lParam
)
1063 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1071 lphl
->PrevFocused
= lphl
->ItemFocused
;
1073 y
= ListBoxFindMouse(lphl
, LOWORD(lParam
), HIWORD(lParam
));
1075 if (y
== -1) return 0;
1077 if (lphl
->dwStyle
& LBS_NOTIFY
&& y
!= LB_ERR
)
1078 if( SendMessage16(lphl
->hParent
, WM_LBTRACKPOINT
, y
, lParam
) )
1082 switch( lphl
->dwStyle
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
) )
1084 case LBS_MULTIPLESEL
:
1085 lphl
->ItemFocused
= y
;
1086 wRet
= ListBoxGetSel(lphl
, y
);
1087 ListBoxSetSel(lphl
, y
, !wRet
);
1089 case LBS_EXTENDEDSEL
:
1090 /* should handle extended mode here and in kbd handler
1093 if ( lphl
->PrevFocused
!= y
&& y
!= LB_ERR
)
1095 LPLISTSTRUCT lpls
= ListBoxGetItem( lphl
, lphl
->ItemFocused
= y
);
1096 n
= ListBoxSetSel(lphl
,-1,FALSE
);
1098 lpls
->itemState
= ODS_FOCUS
| ODS_SELECTED
;
1100 if( n
> 1 && n
!= LB_ERR
)
1101 InvalidateRect32( hwnd
,NULL
,TRUE
);
1108 if( y
!=lphl
->ItemFocused
)
1109 ListBoxSetCurSel(lphl
, y
);
1114 fprintf(stdnimp
,"Listbox: LBS_MULTIPLESEL and LBS_EXTENDEDSEL are on!\n");
1118 /* invalidate changed items */
1119 if( lphl
->dwStyle
& LBS_MULTIPLESEL
|| y
!=lphl
->PrevFocused
)
1121 ListBoxGetItemRect(lphl
, y
, &rectsel
);
1122 InvalidateRect16( hwnd
, &rectsel
, TRUE
);
1124 if( lphl
->PrevFocused
!=-1 && y
!=lphl
->PrevFocused
)
1126 ListBoxGetItemRect(lphl
, lphl
->PrevFocused
, &rectsel
);
1127 InvalidateRect16( hwnd
, &rectsel
, TRUE
);
1130 if (GetWindowLong32A(lphl
->hSelf
,GWL_EXSTYLE
) & WS_EX_DRAGDETECT
)
1131 if( DragDetect(lphl
->hSelf
,MAKEPOINT16(lParam
)) )
1132 SendMessage16(lphl
->hParent
, WM_BEGINDRAG
,0,0L);
1136 /***********************************************************************
1139 static LONG
LBLButtonUp(HWND hwnd
, WORD wParam
, LONG lParam
)
1141 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1143 if (GetCapture32() == hwnd
) ReleaseCapture();
1145 if (lphl
->PrevFocused
!= lphl
->ItemFocused
)
1146 ListBoxSendNotification(lphl
, LBN_SELCHANGE
);
1151 /***********************************************************************
1154 static LONG
LBRButtonUp(HWND hwnd
, WORD wParam
, LONG lParam
)
1156 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1158 SendMessage16(lphl
->hParent
, WM_COMMAND
, GetWindowWord(hwnd
,GWW_ID
),
1159 MAKELONG(hwnd
, LBN_DBLCLK
));
1163 /***********************************************************************
1166 static LONG
LBMouseMove(HWND hwnd
, WORD wParam
, LONG lParam
)
1168 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1169 int y
,redraw_prev
= 0;
1171 RECT16 rect
, rectsel
; /* XXX Broken */
1173 dprintf_listbox(stddeb
,"LBMouseMove %d %d\n",SLOWORD(lParam
),SHIWORD(lParam
));
1174 if ((wParam
& MK_LBUTTON
) != 0) {
1175 y
= SHIWORD(lParam
);
1176 if (y
< LBMM_EDGE
) {
1177 if (lphl
->FirstVisible
> 0) {
1178 lphl
->FirstVisible
--;
1179 SetScrollPos32(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
1180 InvalidateRect32( hwnd
, NULL
, TRUE
);
1184 GetClientRect16(hwnd
, &rect
);
1185 if (y
>= (rect
.bottom
-LBMM_EDGE
)) {
1186 if (lphl
->FirstVisible
< ListMaxFirstVisible(lphl
)) {
1187 lphl
->FirstVisible
++;
1188 SetScrollPos32(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
1189 InvalidateRect32( hwnd
, NULL
, TRUE
);
1193 if ((y
> 0) && (y
< (rect
.bottom
- LBMM_EDGE
))) {
1194 if ((y
< rectsel
.top
) || (y
> rectsel
.bottom
)) {
1195 iRet
= ListBoxFindMouse(lphl
, LOWORD(lParam
), HIWORD(lParam
));
1196 if (iRet
== lphl
->ItemFocused
|| iRet
== -1) {
1199 if (lphl
->dwStyle
& LBS_MULTIPLESEL
) {
1200 lphl
->ItemFocused
= iRet
;
1201 ListBoxSendNotification(lphl
, LBN_SELCHANGE
);
1202 } else if ( lphl
->dwStyle
& LBS_EXTENDEDSEL
)
1204 /* Fixme: extended selection mode */
1205 ListBoxSetSel( lphl
, lphl
->ItemFocused
, 0);
1206 lphl
->PrevFocused
= lphl
->ItemFocused
;
1207 lphl
->ItemFocused
= iRet
;
1208 ListBoxSetSel( lphl
, iRet
, TRUE
);
1213 ListBoxSetCurSel(lphl
, (WORD
)iRet
);
1216 if( lphl
->PrevFocused
!=-1 && redraw_prev
)
1218 ListBoxGetItemRect(lphl
, lphl
->PrevFocused
, &rectsel
);
1219 InvalidateRect16( hwnd
, &rectsel
, TRUE
);
1221 ListBoxGetItemRect(lphl
, iRet
, &rectsel
);
1222 InvalidateRect16( hwnd
, &rectsel
, TRUE
);
1230 /***********************************************************************
1233 * Doesn't yet handle properly VK_SHIFT with LB_EXTENDEDSEL
1235 static LONG
LBKeyDown(HWND hwnd
, WORD wParam
, LONG lParam
)
1237 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1238 WORD newFocused
= 0xFFFF;
1241 ListBoxGetItemRect(lphl
,lphl
->ItemFocused
,&rect
);
1252 if ( lphl
->dwStyle
& LBS_WANTKEYBOARDINPUT
)
1254 newFocused
= (WORD
)(INT
)SendMessage16(lphl
->hParent
,WM_VKEYTOITEM
,
1255 wParam
,MAKELPARAM(lphl
->ItemFocused
,hwnd
));
1256 if ( newFocused
== 0xFFFE ) return 0L;
1258 if ( newFocused
== 0xFFFF )
1260 newFocused
= lphl
->ItemFocused
;
1269 newFocused
= lphl
->ItemsCount
- 1;
1272 if (lphl
->dwStyle
& LBS_MULTICOLUMN
) {
1273 if (newFocused
>= lphl
->ItemsPerColumn
) {
1274 newFocused
-= lphl
->ItemsPerColumn
;
1281 if (newFocused
> 0) newFocused
--;
1284 if (lphl
->dwStyle
& LBS_MULTICOLUMN
)
1285 newFocused
+= lphl
->ItemsPerColumn
;
1291 if (newFocused
> lphl
->ItemsVisible
)
1292 newFocused
-= lphl
->ItemsVisible
;
1293 else newFocused
= 0;
1296 newFocused
+= lphl
->ItemsVisible
;
1301 /* end of nested switch */
1305 if (lphl
->dwStyle
& LBS_MULTIPLESEL
)
1307 WORD wRet
= ListBoxGetSel(lphl
, lphl
->ItemFocused
);
1308 ListBoxSetSel(lphl
, lphl
->ItemFocused
, !wRet
);
1312 /* chars are handled in LBChar */
1317 /* at this point newFocused is set up */
1319 if (newFocused
>= lphl
->ItemsCount
)
1320 newFocused
= lphl
->ItemsCount
- 1;
1322 if (!(lphl
->dwStyle
& LBS_MULTIPLESEL
))
1324 ListBoxSetCurSel(lphl
, newFocused
);
1325 ListBoxSendNotification(lphl
, LBN_SELCHANGE
);
1328 lphl
->ItemFocused
= newFocused
;
1330 if( ListBoxScrollToFocus(lphl
) || (lphl
->dwStyle
&
1331 (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
)) )
1332 InvalidateRect32( hwnd
, NULL
, TRUE
);
1335 InvalidateRect16( hwnd
, &rect
, TRUE
);
1336 if( newFocused
< 0x8000 )
1338 ListBoxGetItemRect(lphl
, newFocused
, &rect
);
1339 InvalidateRect16( hwnd
, &rect
, TRUE
);
1343 SetScrollPos32(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
1348 /***********************************************************************
1351 static LONG
LBChar(HWND hwnd
, WORD wParam
, LONG lParam
)
1353 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1354 WORD newFocused
= 0xFFFF;
1356 if ( (lphl
->dwStyle
& LBS_WANTKEYBOARDINPUT
) && !(lphl
->HasStrings
))
1358 newFocused
= (WORD
)(INT
)SendMessage16(lphl
->hParent
,WM_CHARTOITEM
,
1359 wParam
,MAKELPARAM(lphl
->ItemFocused
,hwnd
));
1360 if ( newFocused
== 0xFFFE ) return 0L;
1363 if (newFocused
== 0xFFFF )
1364 newFocused
= ListBoxFindNextMatch(lphl
, wParam
);
1366 if (newFocused
== (WORD
)LB_ERR
) return 0;
1368 if (newFocused
>= lphl
->ItemsCount
)
1369 newFocused
= lphl
->ItemsCount
- 1;
1371 if (!(lphl
->dwStyle
& LBS_MULTIPLESEL
))
1373 ListBoxSetCurSel(lphl
, newFocused
);
1374 ListBoxSendNotification(lphl
, LBN_SELCHANGE
);
1377 lphl
->ItemFocused
= newFocused
;
1378 ListBoxScrollToFocus(lphl
);
1379 SetScrollPos32(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
1381 InvalidateRect32( hwnd
, NULL
, TRUE
);
1386 /***********************************************************************
1389 static LONG
LBSetRedraw(HWND hwnd
, WORD wParam
, LONG lParam
)
1391 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1393 dprintf_listbox(stddeb
,"ListBox WM_SETREDRAW hWnd=%04x w=%04x !\n",
1395 lphl
->bRedrawFlag
= wParam
;
1400 /***********************************************************************
1403 static LONG
LBSetFont(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1405 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1409 lphl
->hFont
= GetStockObject(SYSTEM_FONT
);
1411 lphl
->hFont
= (HFONT
) wParam
;
1413 /* a new font means possible new text height */
1414 /* does this mean the height of each entry must be separately changed? */
1415 /* or are we guaranteed to get a LBSetFont before the first insert/add? */
1416 if ((hdc
= GetDC32(0)))
1419 GetTextMetrics16( hdc
, &tm
);
1420 lphl
->StdItemHeight
= tm
.tmHeight
;
1421 dprintf_listbox(stddeb
,"LBSetFont: new font %d with height %d\n",
1422 lphl
->hFont
, lphl
->StdItemHeight
);
1423 ReleaseDC32( 0, hdc
);
1429 /***********************************************************************
1432 static LONG
LBPaint(HWND hwnd
, WORD wParam
, LONG lParam
)
1434 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1439 HDC16 hdc
= BeginPaint16( hwnd
, &ps
);
1440 DC
*dc
= (DC
*)GDI_GetObjPtr(hdc
, DC_MAGIC
);
1441 RECT16 rect
, paintRect
, scratchRect
;
1442 int i
, top
, height
, maxwidth
, ipc
;
1446 if (!IsWindowVisible(hwnd
) || !lphl
->bRedrawFlag
) {
1447 EndPaint16(hwnd
, &ps
);
1451 GetRgnBox16(dc
->w
.hGCClipRgn
,&paintRect
);
1452 GetClientRect16(hwnd
, &rect
);
1453 IntersectRect16(&paintRect
,&rect
,&paintRect
);
1455 hOldFont
= SelectObject(hdc
, lphl
->hFont
);
1457 hBrush
= (HBRUSH
)SendMessage32A( lphl
->hParent
, WM_CTLCOLORLISTBOX
,
1458 (WPARAM
)hdc
, (LPARAM
)hwnd
);
1459 if (hBrush
== 0) hBrush
= GetStockObject(WHITE_BRUSH
);
1461 FillRect16(hdc
, &rect
, hBrush
);
1463 maxwidth
= rect
.right
;
1464 if (lphl
->dwStyle
& LBS_MULTICOLUMN
) {
1465 rect
.right
= lphl
->ColumnsWidth
;
1467 lpls
= lphl
->lpFirst
;
1469 lphl
->ItemsVisible
= 0;
1470 lphl
->ItemsPerColumn
= ipc
= 0;
1472 for(i
= 0; i
< lphl
->ItemsCount
; i
++) {
1473 if (lpls
== NULL
) break;
1475 if (i
>= lphl
->FirstVisible
) {
1476 height
= lpls
->mis
.itemHeight
;
1478 if (top
> (rect
.bottom
-height
+1)) {
1479 if (lphl
->dwStyle
& LBS_MULTICOLUMN
) {
1480 lphl
->ItemsPerColumn
= MAX(lphl
->ItemsPerColumn
, ipc
);
1483 rect
.left
+= lphl
->ColumnsWidth
;
1484 rect
.right
+= lphl
->ColumnsWidth
;
1485 if (rect
.left
> maxwidth
) break;
1491 lpls
->itemRect
.top
= top
;
1492 lpls
->itemRect
.bottom
= top
+ height
;
1493 lpls
->itemRect
.left
= rect
.left
;
1494 lpls
->itemRect
.right
= rect
.right
;
1496 if( IntersectRect16(&scratchRect
,&paintRect
,&lpls
->itemRect
) )
1498 dprintf_listbox(stddeb
,"LBPaint: drawing item: %d %d %d %d %d\n",
1499 rect
.left
,top
,rect
.right
,top
+height
,lpls
->itemState
);
1501 if (lphl
->OwnerDrawn
&& (lphl
->ItemFocused
== i
) && GetFocus32() == hwnd
)
1503 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_FOCUS
,
1504 lpls
->itemState
& ~ODS_FOCUS
);
1505 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_DRAWENTIRE
,
1506 lpls
->itemState
& ~ODS_FOCUS
);
1507 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_FOCUS
, lpls
->itemState
);
1510 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_DRAWENTIRE
,
1515 lphl
->ItemsVisible
++;
1519 lpls
= lpls
->lpNext
;
1521 ListBoxUpdateWindow(hwnd
,lphl
,FALSE
);
1522 SelectObject(hdc
,hOldFont
);
1523 EndPaint16( hwnd
, &ps
);
1527 /***********************************************************************
1530 static LONG
LBSetFocus(HWND hwnd
, WORD wParam
, LONG lParam
)
1532 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1534 dprintf_listbox(stddeb
,"ListBox WM_SETFOCUS for %04x\n",hwnd
);
1535 if(!(lphl
->dwStyle
& LBS_MULTIPLESEL
) )
1536 if( lphl
->ItemsCount
&& lphl
->ItemFocused
!= -1)
1538 HDC32 hDC
= GetDC32(hwnd
);
1539 HFONT hOldFont
= SelectObject(hDC
, lphl
->hFont
);
1542 lpls
= ListBoxGetItem(lphl
,lphl
->ItemFocused
);
1543 lpls
->itemState
|= ODS_FOCUS
;
1545 ListBoxDrawItem(hwnd
,lphl
,hDC
,lpls
,&lpls
->itemRect
, ODA_FOCUS
, lpls
->itemState
);
1546 SelectObject(hDC
, hOldFont
);
1547 ReleaseDC32(hwnd
,hDC
);
1550 ListBoxSendNotification(lphl
, LBN_SETFOCUS
);
1555 /***********************************************************************
1558 static LONG
LBKillFocus(HWND hwnd
, WORD wParam
, LONG lParam
)
1560 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1562 dprintf_listbox(stddeb
,"ListBox WM_KILLFOCUS for %04x\n",hwnd
);
1563 if (!(lphl
->dwStyle
& LBS_MULTIPLESEL
))
1565 if( lphl
->ItemsCount
)
1566 if( lphl
->ItemFocused
!= -1 )
1568 HDC32 hDC
= GetDC32(hwnd
);
1569 HFONT hOldFont
= SelectObject(hDC
, lphl
->hFont
);
1572 lpls
= ListBoxGetItem(lphl
,lphl
->ItemFocused
);
1573 lpls
->itemState
&= ~ODS_FOCUS
;
1575 ListBoxDrawItem(hwnd
,lphl
,hDC
,lpls
,&lpls
->itemRect
, ODA_FOCUS
, lpls
->itemState
);
1576 SelectObject(hDC
, hOldFont
);
1577 ReleaseDC32(hwnd
,hDC
);
1580 dprintf_listbox(stddeb
,"LBKillFocus: no focused item!\n");
1583 InvalidateRect32( hwnd
, NULL
, TRUE
);
1585 ListBoxSendNotification(lphl
, LBN_KILLFOCUS
);
1590 /***********************************************************************
1593 static LONG
LBResetContent(HWND hwnd
, WORD wParam
, LONG lParam
)
1595 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1597 dprintf_listbox(stddeb
,"ListBox LB_RESETCONTENT !\n");
1598 ListBoxResetContent(lphl
);
1599 ListBoxUpdateWindow(hwnd
, lphl
, TRUE
);
1603 /***********************************************************************
1606 static LONG
LBDir(HWND hwnd
, WORD wParam
, LONG lParam
)
1609 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1610 dprintf_listbox(stddeb
,"ListBox LB_DIR !\n");
1612 ret
= ListBoxDirectory(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
1613 ListBoxUpdateWindow(hwnd
, lphl
, TRUE
);
1617 /***********************************************************************
1620 static LONG
LBAddString(HWND hwnd
, WORD wParam
, LONG lParam
)
1623 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1625 wRet
= ListBoxAddString(lphl
, (SEGPTR
)lParam
);
1627 ListBoxUpdateWindow(hwnd
,lphl
,TRUE
);
1631 /***********************************************************************
1634 static LONG
LBGetText(HWND hwnd
, WORD wParam
, LONG lParam
)
1637 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1639 dprintf_listbox(stddeb
, "LB_GETTEXT wParam=%d\n",wParam
);
1640 wRet
= ListBoxGetText(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
1645 /***********************************************************************
1648 static LONG
LBInsertString(HWND hwnd
, WORD wParam
, LONG lParam
)
1651 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1653 if (lphl
->HasStrings
)
1654 wRet
= ListBoxInsertString(lphl
, wParam
, (LPCSTR
)PTR_SEG_TO_LIN(lParam
));
1656 wRet
= ListBoxInsertString(lphl
, wParam
, (LPCSTR
)lParam
);
1658 ListBoxUpdateWindow(hwnd
,lphl
,TRUE
);
1662 /***********************************************************************
1665 static LONG
LBDeleteString(HWND hwnd
, WORD wParam
, LONG lParam
)
1667 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1668 LONG lRet
= ListBoxDeleteString(lphl
,wParam
);
1670 ListBoxUpdateWindow(hwnd
,lphl
,TRUE
);
1674 /***********************************************************************
1677 static LONG
LBFindString(HWND hwnd
, WORD wParam
, LONG lParam
)
1679 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1680 return lbFindString(lphl
, wParam
, (SEGPTR
)lParam
, MATCH_SUBSTR
);
1683 /***********************************************************************
1686 static LONG
LBFindStringExact(HWND hwnd
, WORD wParam
, LONG lParam
)
1688 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1689 return lbFindString(lphl
, wParam
, (SEGPTR
)lParam
, MATCH_EXACT
);
1692 /***********************************************************************
1695 static LONG
LBGetCaretIndex(HWND hwnd
, WORD wParam
, LONG lParam
)
1697 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1698 return lphl
->ItemFocused
;
1701 /***********************************************************************
1704 static LONG
LBGetCount(HWND hwnd
, WORD wParam
, LONG lParam
)
1708 lphl
= ListBoxGetStorageHeader(hwnd
);
1709 return lphl
->ItemsCount
;
1712 /***********************************************************************
1715 static LONG
LBGetCurSel(HWND hwnd
, WORD wParam
, LONG lParam
)
1719 lphl
= ListBoxGetStorageHeader(hwnd
);
1720 dprintf_listbox(stddeb
,"ListBox LB_GETCURSEL %i !\n",
1722 return lphl
->ItemFocused
;
1725 /***********************************************************************
1726 * LBGetHorizontalExtent
1728 static LONG
LBGetHorizontalExtent(HWND hwnd
, WORD wParam
, LONG lParam
)
1733 /***********************************************************************
1736 static LONG
LBGetItemHeight(HWND hwnd
, WORD wParam
, LONG lParam
)
1738 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1739 LPLISTSTRUCT lpls
= ListBoxGetItem (lphl
, wParam
);
1741 if (lpls
== NULL
) return LB_ERR
;
1742 return lpls
->mis
.itemHeight
;
1745 /***********************************************************************
1748 static LONG
LBGetItemRect(HWND hwnd
, WORD wParam
, LONG lParam
)
1750 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1751 return ListBoxGetItemRect(lphl
, wParam
, PTR_SEG_TO_LIN(lParam
));
1754 /***********************************************************************
1757 static LONG
LBGetSel(HWND hwnd
, WORD wParam
, LONG lParam
)
1759 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1760 int iSel
= ListBoxGetSel(lphl
, wParam
);
1762 dprintf_listbox(stdnimp
,"LBGetSel: item %u - %i\n",wParam
,iSel
);
1764 return (iSel
)? 1 : 0;
1767 /***********************************************************************
1770 static LONG
LBGetSelCount(HWND hwnd
, WORD wParam
, LONG lParam
)
1772 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1777 if (!(lphl
->dwStyle
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
) ))
1780 for( lpls
= lphl
->lpFirst
;
1782 lpls
= lpls
->lpNext
)
1785 if (lpls
->itemState
)
1792 /***********************************************************************
1795 static LONG
LBGetSelItems(HWND hwnd
, WORD wParam
, LONG lParam
)
1797 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1800 int *lpItems
= PTR_SEG_TO_LIN(lParam
);
1802 if (!(lphl
->dwStyle
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
) ))
1805 if (wParam
== 0) return 0;
1807 lpls
= lphl
->lpFirst
;
1810 while (lpls
!= NULL
) {
1811 if (lpls
->itemState
> 0) lpItems
[cnt
++] = idx
;
1813 if (cnt
== wParam
) break;
1815 lpls
= lpls
->lpNext
;
1821 /***********************************************************************
1824 static LONG
LBGetTextLen(HWND hwnd
, WORD wParam
, LONG lParam
)
1826 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1827 LPLISTSTRUCT lpls
= ListBoxGetItem(lphl
,wParam
);
1829 if (lpls
== NULL
|| !lphl
->HasStrings
) return LB_ERR
;
1830 return strlen(lpls
->itemText
);
1833 /***********************************************************************
1836 static LONG
LBGetDlgCode(HWND hwnd
, WORD wParam
, LONG lParam
)
1838 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
1841 /***********************************************************************
1844 static LONG
LBGetTopIndex(HWND hwnd
, WORD wParam
, LONG lParam
)
1846 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1848 return lphl
->FirstVisible
;
1852 /***********************************************************************
1855 static LONG
LBSelectString(HWND hwnd
, WORD wParam
, LONG lParam
)
1857 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1860 iRet
= lbFindString(lphl
, wParam
, (SEGPTR
)lParam
, MATCH_SUBSTR
);
1864 if( lphl
->dwStyle
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
) )
1865 ListBoxSetSel(lphl
,iRet
,TRUE
);
1867 ListBoxSetCurSel(lphl
,iRet
);
1869 lphl
->ItemFocused
= iRet
;
1870 InvalidateRect32( hwnd
, 0, TRUE
);
1875 /***********************************************************************
1878 static LONG
LBSelItemRange(HWND hwnd
, WORD wParam
, LONG lParam
)
1880 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1883 WORD first
= LOWORD(lParam
);
1884 WORD last
= HIWORD(lParam
);
1885 BOOL select
= wParam
;
1887 if (!(lphl
->dwStyle
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
) ))
1890 if (first
>= lphl
->ItemsCount
||
1891 last
>= lphl
->ItemsCount
) return LB_ERR
;
1893 lpls
= lphl
->lpFirst
;
1896 while (lpls
!= NULL
) {
1898 lpls
->itemState
= select
? lpls
->itemState
| ODS_SELECTED
: 0;
1903 lpls
= lpls
->lpNext
;
1909 /***********************************************************************
1912 static LONG
LBSetCaretIndex(HWND hwnd
, WORD wParam
, LONG lParam
)
1914 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1917 if (!(lphl
->dwStyle
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
) )) return 0;
1919 dprintf_listbox(stddeb
,"LBSetCaretIndex: hwnd %04x n=%i\n",hwnd
,wParam
);
1921 if (wParam
>= lphl
->ItemsCount
) return LB_ERR
;
1923 lphl
->ItemFocused
= wParam
;
1924 i
= ListBoxScrollToFocus (lphl
);
1926 SetScrollPos32(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
1928 InvalidateRect32( hwnd
, NULL
, TRUE
);
1933 /***********************************************************************
1936 static LONG
LBSetColumnWidth(HWND hwnd
, WORD wParam
, LONG lParam
)
1938 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1939 lphl
->ColumnsWidth
= wParam
;
1940 InvalidateRect32( hwnd
, NULL
, TRUE
);
1944 /***********************************************************************
1945 * LBSetHorizontalExtent
1947 static LONG
LBSetHorizontalExtent(HWND hwnd
, WORD wParam
, LONG lParam
)
1952 /***********************************************************************
1955 static LONG
LBGetItemData(HWND hwnd
, WORD wParam
, LONG lParam
)
1957 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1958 dprintf_listbox(stddeb
, "LB_GETITEMDATA wParam=%x\n", wParam
);
1959 return ListBoxGetItemData(lphl
, wParam
);
1962 /***********************************************************************
1965 static LONG
LBSetItemData(HWND hwnd
, WORD wParam
, LONG lParam
)
1967 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1968 dprintf_listbox(stddeb
, "LB_SETITEMDATA wParam=%x lParam=%lx\n", wParam
, lParam
);
1969 return ListBoxSetItemData(lphl
, wParam
, lParam
);
1972 /***********************************************************************
1975 static LONG
LBSetTabStops(HWND hwnd
, WORD wParam
, LONG lParam
)
1979 lphl
= ListBoxGetStorageHeader(hwnd
);
1981 if (lphl
->TabStops
!= NULL
) {
1982 lphl
->iNumStops
= 0;
1983 free (lphl
->TabStops
);
1986 lphl
->TabStops
= malloc (wParam
* sizeof (short));
1987 if (lphl
->TabStops
) {
1988 lphl
->iNumStops
= wParam
;
1989 memcpy (lphl
->TabStops
, PTR_SEG_TO_LIN(lParam
), wParam
* sizeof (short));
1996 /***********************************************************************
1999 static LONG
LBSetCurSel(HWND hwnd
, WORD wParam
, LONG lParam
)
2001 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
2004 dprintf_listbox(stddeb
,"ListBox LB_SETCURSEL wParam=%x !\n",
2007 wRet
= ListBoxSetCurSel(lphl
, wParam
);
2009 SetScrollPos32(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
2010 InvalidateRect32( hwnd
, NULL
, TRUE
);
2015 /***********************************************************************
2018 static LONG
LBSetSel(HWND hwnd
, WORD wParam
, LONG lParam
)
2020 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
2024 dprintf_listbox(stddeb
,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam
, lParam
);
2026 iRet
= ListBoxSetSel(lphl
, LOWORD(lParam
), wParam
);
2028 if( iRet
> 1 ) InvalidateRect32( hwnd
, NULL
, TRUE
);
2029 else if( iRet
!= LB_ERR
)
2031 if( lphl
->dwStyle
& LBS_EXTENDEDSEL
&&
2032 lphl
->ItemFocused
!= LOWORD(lParam
) )
2034 ListBoxGetItemRect(lphl
, lphl
->ItemFocused
, &rect
);
2035 InvalidateRect16( hwnd
, &rect
, TRUE
);
2036 lphl
->ItemFocused
= LOWORD(lParam
);
2038 ListBoxGetItemRect(lphl
,LOWORD(lParam
),&rect
);
2039 InvalidateRect16( hwnd
, &rect
, TRUE
);
2042 return (iRet
== (WORD
)LB_ERR
)? LB_ERR
: 0;
2045 /***********************************************************************
2048 static LONG
LBSetTopIndex(HWND hwnd
, WORD wParam
, LONG lParam
)
2050 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
2052 dprintf_listbox(stddeb
,"ListBox LB_SETTOPINDEX wParam=%x !\n",
2054 lphl
->FirstVisible
= wParam
;
2055 SetScrollPos32(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
2057 InvalidateRect32( hwnd
, NULL
, TRUE
);
2062 /***********************************************************************
2065 static LONG
LBSetItemHeight(HWND hwnd
, WORD wParam
, LONG lParam
)
2067 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
2070 dprintf_listbox(stddeb
,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam
, lParam
);
2071 wRet
= ListBoxSetItemHeight(lphl
, wParam
, lParam
);
2072 InvalidateRect32( hwnd
, NULL
, TRUE
);
2076 /***********************************************************************
2079 static LRESULT
LBPassToParent(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2081 WND
* ptrWnd
= WIN_FindWndPtr(hwnd
);
2084 if( /* !(ptrWnd->dwExStyle & WS_EX_NOPARENTNOTIFY) && */
2086 return SendMessage16(ptrWnd
->parent
->hwndSelf
,message
,wParam
,lParam
);
2090 /***********************************************************************
2093 LRESULT
ListBoxWndProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2096 case WM_CREATE
: return LBCreate(hwnd
, wParam
, lParam
);
2097 case WM_DESTROY
: return LBDestroy(hwnd
, wParam
, lParam
);
2098 case WM_GETDLGCODE
: return LBGetDlgCode(hwnd
, wParam
, lParam
);
2099 case WM_VSCROLL
: return LBVScroll(hwnd
, wParam
, lParam
);
2100 case WM_HSCROLL
: return LBHScroll(hwnd
, wParam
, lParam
);
2101 case WM_LBUTTONDOWN
: return LBLButtonDown(hwnd
, wParam
, lParam
);
2102 case WM_LBUTTONUP
: return LBLButtonUp(hwnd
, wParam
, lParam
);
2103 case WM_RBUTTONUP
: return LBRButtonUp(hwnd
, wParam
, lParam
);
2104 case WM_LBUTTONDBLCLK
: return LBRButtonUp(hwnd
, wParam
, lParam
);
2105 case WM_MOUSEMOVE
: return LBMouseMove(hwnd
, wParam
, lParam
);
2106 case WM_KEYDOWN
: return LBKeyDown(hwnd
, wParam
, lParam
);
2107 case WM_CHAR
: return LBChar(hwnd
, wParam
, lParam
);
2108 case WM_SETFONT
: return LBSetFont(hwnd
, wParam
, lParam
);
2109 case WM_SETREDRAW
: return LBSetRedraw(hwnd
, wParam
, lParam
);
2110 case WM_PAINT
: return LBPaint(hwnd
, wParam
, lParam
);
2111 case WM_SETFOCUS
: return LBSetFocus(hwnd
, wParam
, lParam
);
2112 case WM_KILLFOCUS
: return LBKillFocus(hwnd
, wParam
, lParam
);
2113 case WM_NCCALCSIZE
: return LBNCCalcSize(hwnd
, wParam
, lParam
);
2114 case LB_RESETCONTENT16
: return LBResetContent(hwnd
, wParam
, lParam
);
2115 case LB_DIR16
: return LBDir(hwnd
, wParam
, lParam
);
2116 case LB_ADDSTRING16
: return LBAddString(hwnd
, wParam
, lParam
);
2117 case LB_INSERTSTRING16
: return LBInsertString(hwnd
, wParam
, lParam
);
2118 case LB_DELETESTRING16
: return LBDeleteString(hwnd
, wParam
, lParam
);
2119 case LB_FINDSTRING16
: return LBFindString(hwnd
, wParam
, lParam
);
2120 case LB_FINDSTRINGEXACT16
: return LBFindStringExact(hwnd
, wParam
, lParam
);
2121 case LB_GETCARETINDEX16
: return LBGetCaretIndex(hwnd
, wParam
, lParam
);
2122 case LB_GETCOUNT16
: return LBGetCount(hwnd
, wParam
, lParam
);
2123 case LB_GETCURSEL16
: return LBGetCurSel(hwnd
, wParam
, lParam
);
2124 case LB_GETHORIZONTALEXTENT16
: return LBGetHorizontalExtent(hwnd
, wParam
, lParam
);
2125 case LB_GETITEMDATA16
: return LBGetItemData(hwnd
, wParam
, lParam
);
2126 case LB_GETITEMHEIGHT16
: return LBGetItemHeight(hwnd
, wParam
, lParam
);
2127 case LB_GETITEMRECT16
: return LBGetItemRect(hwnd
, wParam
, lParam
);
2128 case LB_GETSEL16
: return LBGetSel(hwnd
, wParam
, lParam
);
2129 case LB_GETSELCOUNT16
: return LBGetSelCount(hwnd
, wParam
, lParam
);
2130 case LB_GETSELITEMS16
: return LBGetSelItems(hwnd
, wParam
, lParam
);
2131 case LB_GETTEXT16
: return LBGetText(hwnd
, wParam
, lParam
);
2132 case LB_GETTEXTLEN16
: return LBGetTextLen(hwnd
, wParam
, lParam
);
2133 case LB_GETTOPINDEX16
: return LBGetTopIndex(hwnd
, wParam
, lParam
);
2134 case LB_SELECTSTRING16
: return LBSelectString(hwnd
, wParam
, lParam
);
2135 case LB_SELITEMRANGE16
: return LBSelItemRange(hwnd
, wParam
, lParam
);
2136 case LB_SETCARETINDEX16
: return LBSetCaretIndex(hwnd
, wParam
, lParam
);
2137 case LB_SETCOLUMNWIDTH16
: return LBSetColumnWidth(hwnd
, wParam
, lParam
);
2138 case LB_SETHORIZONTALEXTENT16
: return LBSetHorizontalExtent(hwnd
, wParam
, lParam
);
2139 case LB_SETITEMDATA16
: return LBSetItemData(hwnd
, wParam
, lParam
);
2140 case LB_SETTABSTOPS16
: return LBSetTabStops(hwnd
, wParam
, lParam
);
2141 case LB_SETCURSEL16
: return LBSetCurSel(hwnd
, wParam
, lParam
);
2142 case LB_SETSEL16
: return LBSetSel(hwnd
, wParam
, lParam
);
2143 case LB_SETTOPINDEX16
: return LBSetTopIndex(hwnd
, wParam
, lParam
);
2144 case LB_SETITEMHEIGHT16
: return LBSetItemHeight(hwnd
, wParam
, lParam
);
2146 case WM_DROPFILES
: return LBPassToParent(hwnd
, message
, wParam
, lParam
);
2148 /* these will have to be implemented for proper LBS_EXTENDEDSEL -
2150 * anchor item is an item that with caret (focused) item defines a
2151 * range of currently selected items when listbox is in the extended
2154 case LB_SETANCHORINDEX16
: return LB_SETANCHORINDEX16
; /* that's what Windows returns */
2155 case LB_GETANCHORINDEX16
: return 0;
2158 case WM_QUERYDROPOBJECT
:
2162 LPDRAGINFO lpDragInfo
= (LPDRAGINFO
) PTR_SEG_TO_LIN((SEGPTR
)lParam
);
2163 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
2165 lpDragInfo
->l
= ListBoxFindMouse(lphl
,lpDragInfo
->pt
.x
,
2168 return LBPassToParent(hwnd
, message
, wParam
, lParam
);
2172 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
2176 /**********************************************************************
2177 * DlgDirSelect (USER.99)
2179 BOOL
DlgDirSelect( HWND hDlg
, LPSTR lpStr
, INT id
)
2184 dprintf_listbox( stddeb
, "DlgDirSelect: %04x '%s' %d\n", hDlg
, lpStr
, id
);
2185 if ((i
= SendDlgItemMessage16( hDlg
, id
, LB_GETCURSEL16
, 0, 0 )) == LB_ERR
)
2187 if (!(buffer
= SEGPTR_ALLOC( 20 * sizeof(char) ))) return FALSE
;
2188 SendDlgItemMessage16(hDlg
, id
, LB_GETTEXT16
, i
, (LPARAM
)SEGPTR_GET(buffer
) );
2189 if (buffer
[0] == '[') /* drive or directory */
2191 if (buffer
[1] == '-') /* drive */
2193 lpStr
[0] = buffer
[2];
2196 dprintf_listbox( stddeb
, "Returning drive '%s'\n", lpStr
);
2197 SEGPTR_FREE(buffer
);
2200 strcpy( lpStr
, buffer
+ 1 );
2201 lpStr
[strlen(lpStr
)-1] = '\\';
2202 dprintf_listbox( stddeb
, "Returning directory '%s'\n", lpStr
);
2203 SEGPTR_FREE(buffer
);
2206 strcpy( lpStr
, buffer
);
2207 dprintf_listbox( stddeb
, "Returning file '%s'\n", lpStr
);
2208 SEGPTR_FREE(buffer
);
2213 /**********************************************************************
2214 * DlgDirList (USER.100)
2216 INT
DlgDirList( HWND hDlg
, SEGPTR spec
, INT idLBox
, INT idStatic
, UINT attrib
)
2218 char *filespec
= (char *)PTR_SEG_TO_LIN( spec
);
2222 #define SENDMSG(msg,wparam,lparam) \
2223 ((attrib & DDL_POSTMSGS) ? PostMessage( hwnd, msg, wparam, lparam ) \
2224 : SendMessage16( hwnd, msg, wparam, lparam ))
2226 dprintf_listbox( stddeb
, "DlgDirList: %04x '%s' %d %d %04x\n",
2227 hDlg
, filespec
? filespec
: "NULL",
2228 idLBox
, idStatic
, attrib
);
2230 if (filespec
&& filespec
[0] && (filespec
[1] == ':'))
2232 drive
= toupper( filespec
[0] ) - 'A';
2234 if (!DRIVE_SetCurrentDrive( drive
)) return FALSE
;
2236 else drive
= DRIVE_GetCurrentDrive();
2238 if (idLBox
&& ((hwnd
= GetDlgItem( hDlg
, idLBox
)) != 0))
2242 if (!filespec
|| !filespec
[0]) strcpy( mask
, "*.*" );
2245 /* If the path exists and is a directory, chdir to it */
2246 if (DRIVE_Chdir( drive
, filespec
)) strcpy( mask
, "*.*" );
2251 if ((p2
= strrchr( p
, '\\' ))) p
= p2
+ 1;
2252 if ((p2
= strrchr( p
, '/' ))) p
= p2
+ 1;
2253 lstrcpyn32A( mask
, p
, sizeof(mask
) );
2257 if (!DRIVE_Chdir( drive
, filespec
)) return FALSE
;
2262 strcpy( (char *)PTR_SEG_TO_LIN(spec
), mask
);
2264 dprintf_listbox(stddeb
, "ListBoxDirectory: path=%c:\\%s mask=%s\n",
2265 'A' + drive
, DRIVE_GetDosCwd(drive
), mask
);
2267 SENDMSG( LB_RESETCONTENT16
, 0, 0 );
2268 if ((attrib
& DDL_DIRECTORY
) && !(attrib
& DDL_EXCLUSIVE
))
2271 if (SENDMSG( LB_DIR16
, attrib
& ~(DDL_DIRECTORY
| DDL_DRIVES
),
2272 (LPARAM
)spec
) == LB_ERR
) return FALSE
;
2273 if (!(temp
= SEGPTR_ALLOC( 4*sizeof(char) ))) return FALSE
;
2274 strcpy( temp
, "*.*" );
2275 /* FIXME: this won't work with PostMessage(), as temp will */
2276 /* have been freed by the time we do a DispatchMessage(). */
2277 if (SENDMSG( LB_DIR16
, (attrib
& (DDL_DIRECTORY
| DDL_DRIVES
)) | DDL_EXCLUSIVE
,
2278 (LPARAM
)SEGPTR_GET(temp
) ) == LB_ERR
)
2287 if (SENDMSG( LB_DIR16
, attrib
, (LPARAM
)spec
) == LB_ERR
) return FALSE
;
2291 if (idStatic
&& ((hwnd
= GetDlgItem( hDlg
, idStatic
)) != 0))
2294 int drive
= DRIVE_GetCurrentDrive();
2295 strcpy( temp
, "A:\\" );
2297 lstrcpyn32A( temp
+ 3, DRIVE_GetDosCwd(drive
), sizeof(temp
)-3 );
2299 /* Can't use PostMessage() here, because the string is on the stack */
2300 SetDlgItemText32A( hDlg
, idStatic
, temp
);