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
32 #include "stackframe.h"
37 #define LIST_HEAP_ALLOC(lphl,f,size) \
38 LOCAL_Alloc( lphl->HeapSel, LMEM_FIXED, (size) )
39 #define LIST_HEAP_FREE(lphl,handle) \
40 LOCAL_Free( lphl->HeapSel, (handle) )
41 #define LIST_HEAP_ADDR(lphl,handle) \
42 ((handle) ? PTR_SEG_OFF_TO_LIN(lphl->HeapSel, (handle)) : NULL)
44 #define LIST_HEAP_SIZE 0x10000
46 #define LBMM_EDGE 4 /* distance inside box which is same as moving mouse
47 outside box, to trigger scrolling of LB */
49 #define MATCH_SUBSTR 2
51 #define MATCH_NEAREST 0
53 static void ListBoxInitialize(LPHEADLIST lphl
)
57 lphl
->ItemsVisible
= 0;
58 lphl
->FirstVisible
= 0;
59 lphl
->ColumnsVisible
= 1;
60 lphl
->ItemsPerColumn
= 0;
61 lphl
->ItemFocused
= -1;
62 lphl
->PrevFocused
= -1;
65 void CreateListBoxStruct(HWND hwnd
, WORD CtlType
, LONG styles
, HWND parent
)
70 lphl
= (LPHEADLIST
)xmalloc(sizeof(HEADLIST
));
71 SetWindowLong32A(hwnd
, 0, (LONG
)lphl
);
72 ListBoxInitialize(lphl
);
73 lphl
->DrawCtlType
= CtlType
;
74 lphl
->CtlID
= GetWindowWord(hwnd
,GWW_ID
);
75 lphl
->bRedrawFlag
= TRUE
;
77 lphl
->TabStops
= NULL
;
78 lphl
->hFont
= GetStockObject(SYSTEM_FONT
);
80 if (CtlType
==ODT_COMBOBOX
) /* use the "faked" style for COMBOLBOX */
81 /* LBS_SORT instead CBS_SORT e.g. */
82 lphl
->dwStyle
= MAKELONG(LOWORD(styles
),HIWORD(GetWindowLong32A(hwnd
,GWL_STYLE
)));
84 lphl
->dwStyle
= GetWindowLong32A(hwnd
,GWL_STYLE
); /* use original style dword */
85 lphl
->hParent
= parent
;
86 lphl
->StdItemHeight
= 15; /* FIXME: should get the font height */
87 lphl
->OwnerDrawn
= styles
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
);
88 lphl
->HasStrings
= (styles
& LBS_HASSTRINGS
) || !lphl
->OwnerDrawn
;
90 /* create dummy hdc to set text height */
94 GetTextMetrics16( hdc
, &tm
);
95 lphl
->StdItemHeight
= tm
.tmHeight
;
96 dprintf_listbox(stddeb
,"CreateListBoxStruct: font height %d\n",
101 if (lphl
->OwnerDrawn
)
105 lphl
->needMeasure
= TRUE
;
106 dummyls
.mis
.CtlType
= lphl
->DrawCtlType
;
107 dummyls
.mis
.CtlID
= lphl
->CtlID
;
108 dummyls
.mis
.itemID
= -1;
109 dummyls
.mis
.itemWidth
= 0; /* ignored */
110 dummyls
.mis
.itemData
= 0;
112 ListBoxAskMeasure(lphl
,&dummyls
);
115 lphl
->HeapSel
= GlobalAlloc16(GMEM_FIXED
,LIST_HEAP_SIZE
);
116 LocalInit( lphl
->HeapSel
, 0, LIST_HEAP_SIZE
-1);
119 void DestroyListBoxStruct(LPHEADLIST lphl
)
121 /* XXX need to free lphl->Heap */
122 GlobalFree16(lphl
->HeapSel
);
126 static LPHEADLIST
ListBoxGetStorageHeader(HWND hwnd
)
128 return (LPHEADLIST
)GetWindowLong32A(hwnd
,0);
131 /* Send notification "code" as part of a WM_COMMAND-message if hwnd
132 has the LBS_NOTIFY style */
133 void ListBoxSendNotification(LPHEADLIST lphl
, WORD code
)
135 if (lphl
->dwStyle
& LBS_NOTIFY
)
136 SendMessage32A( lphl
->hParent
, WM_COMMAND
,
137 MAKEWPARAM( lphl
->CtlID
, code
), (LPARAM
)lphl
->hSelf
);
141 /* get the maximum value of lphl->FirstVisible */
142 int ListMaxFirstVisible(LPHEADLIST lphl
)
144 int m
= lphl
->ItemsCount
-lphl
->ItemsVisible
;
145 return (m
< 0) ? 0 : m
;
149 void ListBoxUpdateWindow(HWND hwnd
, LPHEADLIST lphl
, BOOL repaint
)
151 if (lphl
->dwStyle
& WS_VSCROLL
)
152 SetScrollRange(hwnd
, SB_VERT
, 0, ListMaxFirstVisible(lphl
), TRUE
);
153 if ((lphl
->dwStyle
& WS_HSCROLL
) && (lphl
->ItemsPerColumn
!= 0))
154 SetScrollRange(hwnd
, SB_HORZ
, 1, lphl
->ItemsVisible
/
155 lphl
->ItemsPerColumn
+ 1, TRUE
);
157 if (repaint
&& lphl
->bRedrawFlag
) InvalidateRect32( hwnd
, NULL
, TRUE
);
160 /* Returns: 0 if nothing needs to be changed */
161 /* 1 if FirstVisible changed */
163 int ListBoxScrollToFocus(LPHEADLIST lphl
)
167 if (lphl
->ItemsCount
== 0) return 0;
168 if (lphl
->ItemFocused
== -1) return 0;
170 end
= lphl
->FirstVisible
+ lphl
->ItemsVisible
- 1;
172 if (lphl
->ItemFocused
< lphl
->FirstVisible
) {
173 lphl
->FirstVisible
= lphl
->ItemFocused
;
176 if (lphl
->ItemFocused
> end
) {
177 WORD maxFirstVisible
= ListMaxFirstVisible(lphl
);
179 lphl
->FirstVisible
= lphl
->ItemFocused
;
181 if (lphl
->FirstVisible
> maxFirstVisible
) {
182 lphl
->FirstVisible
= maxFirstVisible
;
191 LPLISTSTRUCT
ListBoxGetItem(LPHEADLIST lphl
, UINT uIndex
)
196 if (uIndex
>= lphl
->ItemsCount
) return NULL
;
198 lpls
= lphl
->lpFirst
;
199 while (Count
++ < uIndex
) lpls
= lpls
->lpNext
;
204 void ListBoxDrawItem (HWND hwnd
, LPHEADLIST lphl
, HDC hdc
, LPLISTSTRUCT lpls
,
205 RECT16
*rect
, WORD itemAction
, WORD itemState
)
207 if (lphl
->OwnerDrawn
)
209 DRAWITEMSTRUCT32 dis
;
211 dis
.CtlID
= lpls
->mis
.CtlID
;
212 dis
.CtlType
= lpls
->mis
.CtlType
;
213 dis
.itemID
= lpls
->mis
.itemID
;
216 dis
.itemData
= lpls
->mis
.itemData
;
217 dis
.itemAction
= itemAction
;
218 dis
.itemState
= itemState
;
219 CONV_RECT16TO32( rect
, &dis
.rcItem
);
220 SendMessage32A( lphl
->hParent
, WM_DRAWITEM
, dis
.CtlID
, (LPARAM
)&dis
);
223 if (itemAction
== ODA_DRAWENTIRE
|| itemAction
== ODA_SELECT
) {
225 DWORD dwOldTextColor
= 0;
227 OldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
229 if (itemState
!= 0) {
230 dwOldTextColor
= SetTextColor(hdc
, 0x00FFFFFFL
);
231 FillRect16(hdc
, rect
, GetStockObject(BLACK_BRUSH
));
234 if (lphl
->dwStyle
& LBS_USETABSTOPS
) {
235 TabbedTextOut(hdc
, rect
->left
+ 5, rect
->top
+ 2,
236 (char *)lpls
->itemText
, strlen((char *)lpls
->itemText
),
237 lphl
->iNumStops
, lphl
->TabStops
, 0);
239 TextOut16(hdc
, rect
->left
+ 5, rect
->top
+ 2,
240 (char *)lpls
->itemText
, strlen((char *)lpls
->itemText
));
243 if (itemState
!= 0) {
244 SetTextColor(hdc
, dwOldTextColor
);
247 SetBkMode(hdc
, OldBkMode
);
249 else DrawFocusRect16(hdc
, rect
);
253 int ListBoxFindMouse(LPHEADLIST lphl
, int X
, int Y
)
255 LPLISTSTRUCT lpls
= lphl
->lpFirst
;
259 point
.x
= X
; point
.y
= Y
;
260 if (lphl
->ItemsCount
== 0) return LB_ERR
;
262 for(i
= 0; i
< lphl
->FirstVisible
; i
++) {
263 if (lpls
== NULL
) return LB_ERR
;
266 for(j
= 0; j
< lphl
->ItemsVisible
; i
++, j
++) {
267 if (lpls
== NULL
) return LB_ERR
;
268 if (PtInRect16(&lpls
->itemRect
,point
)) {
273 dprintf_listbox(stddeb
,"ListBoxFindMouse: not found\n");
277 BOOL
lbDeleteItemNotify(LPHEADLIST lphl
, LPLISTSTRUCT lpls
)
279 /* called only for owner drawn listboxes */
281 DELETEITEMSTRUCT16 delItem
;
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 return (BOOL
) SendMessage16(lphl
->hParent
, WM_DELETEITEM
, (WPARAM
)lphl
->CtlID
,
290 (LPARAM
)MAKE_SEGPTR(&delItem
));
293 void ListBoxAskMeasure(LPHEADLIST lphl
, LPLISTSTRUCT lpls
)
295 MEASUREITEMSTRUCT16
*lpmeasure
= SEGPTR_NEW(MEASUREITEMSTRUCT16
);
296 if (!lpmeasure
) return;
297 *lpmeasure
= lpls
->mis
;
298 lpmeasure
->itemHeight
= lphl
->StdItemHeight
;
299 SendMessage16( lphl
->hParent
, WM_MEASUREITEM
, lphl
->CtlID
,
300 (LPARAM
)SEGPTR_GET(lpmeasure
) );
302 if (lphl
->dwStyle
& LBS_OWNERDRAWFIXED
)
304 if (lpmeasure
->itemHeight
> lphl
->StdItemHeight
)
305 lphl
->StdItemHeight
= lpmeasure
->itemHeight
;
306 lpls
->mis
.itemHeight
= lpmeasure
->itemHeight
;
308 SEGPTR_FREE(lpmeasure
);
311 /* -------------------- strings and item data ---------------------- */
313 LPLISTSTRUCT
ListBoxCreateItem(LPHEADLIST lphl
, int id
)
315 LPLISTSTRUCT lplsnew
= (LPLISTSTRUCT
)malloc(sizeof(LISTSTRUCT
));
317 if (lplsnew
== NULL
) return NULL
;
319 lplsnew
->itemState
= 0;
320 lplsnew
->mis
.CtlType
= lphl
->DrawCtlType
;
321 lplsnew
->mis
.CtlID
= lphl
->CtlID
;
322 lplsnew
->mis
.itemID
= id
;
323 lplsnew
->mis
.itemHeight
= lphl
->StdItemHeight
;
324 lplsnew
->mis
.itemWidth
= 0; /* ignored */
325 lplsnew
->mis
.itemData
= 0;
326 SetRectEmpty16( &lplsnew
->itemRect
);
331 int ListBoxAskCompare(LPHEADLIST lphl
, int startItem
, SEGPTR matchData
, BOOL exactMatch
)
333 /* Do binary search for sorted listboxes. Linked list item storage sort of
334 * defeats the purpose ( forces to traverse item list all the time ) but M$ does it this way...
336 * MATCH_NEAREST (0) - return position for insertion - for all styles
337 * MATCH_EXACT (1) - search for an item, return index or LB_ERR
338 * MATCH_SUBSTR (2) - same as exact match but with strncmp for string comparision
341 COMPAREITEMSTRUCT16 itemCmp
;
342 LPLISTSTRUCT currentItem
= NULL
;
343 LPCSTR matchStr
= (lphl
->HasStrings
)?(LPCSTR
)PTR_SEG_TO_LIN(matchData
):NULL
;
344 int head
, pos
= -1, tail
, loop
= 1;
345 short b
= 0, s_length
= 0;
349 if( !lphl
->ItemsCount
)
350 return (exactMatch
)? LB_ERR
: 0;
352 /* set up variables */
354 if( exactMatch
== MATCH_NEAREST
)
356 else if( ++startItem
)
359 if( startItem
>= lphl
->ItemsCount
) startItem
= lphl
->ItemsCount
- 1;
362 if( exactMatch
== MATCH_SUBSTR
&& lphl
->HasStrings
)
364 s_length
= strlen( matchStr
);
365 if( !s_length
) return 0; /* head of the list - empty string */
368 head
= startItem
; tail
= lphl
->ItemsCount
- 1;
370 dprintf_listbox(stddeb
,"AskCompare: head = %i, tail = %i, data = %08x\n", head
, tail
, (unsigned)matchData
);
372 itemCmp
.CtlType
= lphl
->DrawCtlType
;
373 itemCmp
.CtlID
= lphl
->CtlID
;
374 itemCmp
.hwndItem
= lphl
->hSelf
;
376 /* search from startItem */
380 while( head
<= tail
)
382 pos
= (tail
+ head
)/2;
383 currentItem
= ListBoxGetItem( lphl
, pos
);
385 if( lphl
->HasStrings
)
387 b
= ( s_length
)? strncasecmp( currentItem
->itemText
, matchStr
, s_length
)
388 : strcasecmp( currentItem
->itemText
, matchStr
);
392 itemCmp
.itemID1
= pos
;
393 itemCmp
.itemData1
= currentItem
->mis
.itemData
;
394 itemCmp
.itemID2
= -1;
395 itemCmp
.itemData2
= matchData
;
397 b
= SendMessage16( lphl
->hParent
, WM_COMPAREITEM
, (WPARAM
)lphl
->CtlID
,
398 (LPARAM
)MAKE_SEGPTR(&itemCmp
) );
402 return pos
; /* found exact match */
404 if( b
< 0 ) head
= ++pos
;
406 if( b
> 0 ) tail
= pos
- 1;
409 /* reset to search from the first item */
410 head
= 0; tail
= startItem
- 1;
413 dprintf_listbox(stddeb
,"\t-> pos = %i\n", pos
);
415 /* if we got here match is not exact */
417 if( pos
< 0 ) pos
= 0;
418 else if( pos
> lphl
->ItemsCount
) pos
= lphl
->ItemsCount
;
420 return (exactMatch
)? LB_ERR
: pos
;
423 int ListBoxInsertString(LPHEADLIST lphl
, UINT uIndex
, LPCSTR newstr
)
425 LPLISTSTRUCT
*lppls
, lplsnew
, lpls
;
430 dprintf_listbox(stddeb
,"ListBoxInsertString(%d, %p);\n", uIndex
, newstr
);
432 if (!newstr
) return -1;
434 if (uIndex
== (UINT
)-1)
435 uIndex
= lphl
->ItemsCount
;
437 lppls
= &lphl
->lpFirst
;
438 for(Count
= 0; Count
< uIndex
; Count
++) {
439 if (*lppls
== NULL
) return LB_ERR
;
440 lppls
= (LPLISTSTRUCT
*) &(*lppls
)->lpNext
;
443 lplsnew
= ListBoxCreateItem(lphl
, Count
);
445 if (lplsnew
== NULL
) {
446 fprintf(stdnimp
,"ListBoxInsertString() out of memory !\n");
450 lplsnew
->lpNext
= *lppls
;
455 if (lphl
->HasStrings
) {
456 dprintf_listbox(stddeb
," string: %s\n", newstr
);
457 hStr
= LIST_HEAP_ALLOC(lphl
, LMEM_MOVEABLE
, strlen(newstr
) + 1);
458 str
= (LPSTR
)LIST_HEAP_ADDR(lphl
, hStr
);
459 if (str
== NULL
) return LB_ERRSPACE
;
461 lplsnew
->itemText
= str
;
462 /* I'm not so sure about the next one */
463 lplsnew
->mis
.itemData
= 0;
465 lplsnew
->itemText
= NULL
;
466 lplsnew
->mis
.itemData
= (DWORD
)newstr
;
469 lplsnew
->mis
.itemID
= uIndex
;
470 lplsnew
->hData
= hStr
;
472 /* adjust the itemID field of the following entries */
473 for(lpls
= lplsnew
->lpNext
; lpls
!= NULL
; lpls
= lpls
->lpNext
) {
477 if (lphl
->needMeasure
) {
478 ListBoxAskMeasure(lphl
, lplsnew
);
481 dprintf_listbox(stddeb
,"ListBoxInsertString // count=%d\n", lphl
->ItemsCount
);
486 int ListBoxAddString(LPHEADLIST lphl
, SEGPTR itemData
)
488 UINT pos
= (UINT
) -1;
489 LPCSTR newstr
= (lphl
->HasStrings
)?(LPCSTR
)PTR_SEG_TO_LIN(itemData
):(LPCSTR
)itemData
;
491 if ( lphl
->dwStyle
& LBS_SORT
)
492 pos
= ListBoxAskCompare( lphl
, -1, itemData
, MATCH_NEAREST
);
494 return ListBoxInsertString(lphl
, pos
, newstr
);
498 int ListBoxGetText(LPHEADLIST lphl
, UINT uIndex
, LPSTR OutStr
)
503 dprintf_listbox(stddeb
, "ListBoxGetText // OutStr==NULL\n");
507 lpls
= ListBoxGetItem (lphl
, uIndex
);
508 if (lpls
== NULL
) return LB_ERR
;
510 if (!lphl
->HasStrings
) {
511 *((long *)OutStr
) = lpls
->mis
.itemData
;
515 strcpy(OutStr
, lpls
->itemText
);
516 return strlen(OutStr
);
520 DWORD
ListBoxGetItemData(LPHEADLIST lphl
, UINT uIndex
)
524 lpls
= ListBoxGetItem (lphl
, uIndex
);
525 if (lpls
== NULL
) return LB_ERR
;
526 return lpls
->mis
.itemData
;
530 int ListBoxSetItemData(LPHEADLIST lphl
, UINT uIndex
, DWORD ItemData
)
532 LPLISTSTRUCT lpls
= ListBoxGetItem(lphl
, uIndex
);
534 if (lpls
== NULL
) return LB_ERR
;
535 lpls
->mis
.itemData
= ItemData
;
540 int ListBoxDeleteString(LPHEADLIST lphl
, UINT uIndex
)
542 LPLISTSTRUCT lpls
, lpls2
;
545 if (uIndex
>= lphl
->ItemsCount
) return LB_ERR
;
547 lpls
= lphl
->lpFirst
;
548 if (lpls
== NULL
) return LB_ERR
;
552 if( lphl
->OwnerDrawn
)
553 lbDeleteItemNotify( lphl
, lpls
);
554 lphl
->lpFirst
= lpls
->lpNext
;
558 LPLISTSTRUCT lpls2
= NULL
;
559 for(Count
= 0; Count
< uIndex
; Count
++) {
560 if (lpls
->lpNext
== NULL
) return LB_ERR
;
563 lpls
= (LPLISTSTRUCT
)lpls
->lpNext
;
565 if( lphl
->OwnerDrawn
)
566 lbDeleteItemNotify( lphl
, lpls
);
567 lpls2
->lpNext
= lpls
->lpNext
;
570 /* adjust the itemID field of the following entries */
571 for(lpls2
= lpls
->lpNext
; lpls2
!= NULL
; lpls2
= lpls2
->lpNext
) {
577 if (lpls
->hData
!= 0) LIST_HEAP_FREE(lphl
, lpls
->hData
);
580 return lphl
->ItemsCount
;
583 int lbFindString(LPHEADLIST lphl
, UINT nFirst
, SEGPTR MatchStr
, BOOL match
)
585 /* match is either MATCH_SUBSTR or MATCH_EXACT */
589 UINT First
= nFirst
+ 1;
591 LPSTR lpMatchStr
= (LPSTR
)MatchStr
;
593 if (First
> lphl
->ItemsCount
) return LB_ERR
;
595 if (lphl
->dwStyle
& LBS_SORT
)
596 return ListBoxAskCompare( lphl
, nFirst
, MatchStr
, match
);
598 if (lphl
->HasStrings
)
600 lpMatchStr
= PTR_SEG_TO_LIN(MatchStr
);
602 if( match
== MATCH_SUBSTR
)
604 s_length
= strlen(lpMatchStr
);
605 if( !s_length
) return (lphl
->ItemsCount
)?0:LB_ERR
;
609 lpls
= ListBoxGetItem(lphl
, First
);
613 if (lphl
->HasStrings
)
615 if ( ( s_length
)? !strncasecmp(lpls
->itemText
, lpMatchStr
, s_length
)
616 : !strcasecmp(lpls
->itemText
, lpMatchStr
) ) return Count
;
619 if ( lpls
->mis
.itemData
== (DWORD
)lpMatchStr
) return Count
;
625 /* Start over at top */
627 lpls
= lphl
->lpFirst
;
629 while (Count
< First
)
631 if (lphl
->HasStrings
)
633 if ( ( s_length
)? !strncasecmp(lpls
->itemText
, lpMatchStr
, s_length
)
634 : !strcasecmp(lpls
->itemText
, lpMatchStr
) ) return Count
;
637 if ( lpls
->mis
.itemData
== (DWORD
)lpMatchStr
) return Count
;
646 int ListBoxFindString(LPHEADLIST lphl
, UINT nFirst
, SEGPTR MatchStr
)
648 return lbFindString(lphl
, nFirst
, MatchStr
, MATCH_SUBSTR
);
651 int ListBoxFindStringExact(LPHEADLIST lphl
, UINT nFirst
, SEGPTR MatchStr
)
653 return lbFindString(lphl
, nFirst
, MatchStr
, MATCH_EXACT
);
656 int ListBoxResetContent(LPHEADLIST lphl
)
661 if (lphl
->ItemsCount
== 0) return 0;
663 dprintf_listbox(stddeb
, "ListBoxResetContent // ItemCount = %d\n",
666 for(i
= 0; i
< lphl
->ItemsCount
; i
++) {
667 lpls
= lphl
->lpFirst
;
668 if (lpls
== NULL
) return LB_ERR
;
670 if (lphl
->OwnerDrawn
) lbDeleteItemNotify(lphl
, lpls
);
672 lphl
->lpFirst
= lpls
->lpNext
;
673 if (lpls
->hData
!= 0) LIST_HEAP_FREE(lphl
, lpls
->hData
);
676 ListBoxInitialize(lphl
);
681 /* --------------------- selection ------------------------- */
683 int ListBoxSetCurSel(LPHEADLIST lphl
, WORD wIndex
)
687 /* use ListBoxSetSel instead */
688 if (lphl
->dwStyle
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
) ) return 0;
690 /* unselect previous item */
691 if (lphl
->ItemFocused
!= -1) {
692 lphl
->PrevFocused
= lphl
->ItemFocused
;
693 lpls
= ListBoxGetItem(lphl
, lphl
->ItemFocused
);
694 if (lpls
== 0) return LB_ERR
;
698 if ((wIndex
!= (UINT
)-1) && (wIndex
< lphl
->ItemsCount
))
700 lphl
->ItemFocused
= wIndex
;
701 lpls
= ListBoxGetItem(lphl
, wIndex
);
702 if (lpls
== 0) return LB_ERR
;
703 lpls
->itemState
= ODS_SELECTED
| ODS_FOCUS
;
712 int ListBoxSetSel(LPHEADLIST lphl
, WORD wIndex
, WORD state
)
717 if (!(lphl
->dwStyle
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
) ))
720 if (wIndex
== (UINT
)-1) {
721 for (lpls
= lphl
->lpFirst
; lpls
!= NULL
; lpls
= lpls
->lpNext
) {
722 if( lpls
->itemState
& ODS_SELECTED
) n
++;
723 lpls
->itemState
= state
? lpls
->itemState
| ODS_SELECTED
724 : lpls
->itemState
& ~ODS_SELECTED
;
729 if (wIndex
>= lphl
->ItemsCount
) return LB_ERR
;
731 lpls
= ListBoxGetItem(lphl
, wIndex
);
732 lpls
->itemState
= state
? lpls
->itemState
| ODS_SELECTED
733 : lpls
->itemState
& ~ODS_SELECTED
;
739 int ListBoxGetSel(LPHEADLIST lphl
, WORD wIndex
)
741 LPLISTSTRUCT lpls
= ListBoxGetItem(lphl
, wIndex
);
743 if (lpls
== NULL
) return LB_ERR
;
744 return lpls
->itemState
& ODS_SELECTED
;
747 /* ------------------------- dir listing ------------------------ */
749 LONG
ListBoxDirectory(LPHEADLIST lphl
, UINT attrib
, LPCSTR filespec
)
759 dprintf_listbox(stddeb
, "ListBoxDirectory: '%s' %04x\n", filespec
, attrib
);
760 if (!filespec
) return LB_ERR
;
761 if (!(ptr
= DOSFS_GetUnixFileName( filespec
, FALSE
))) return LB_ERR
;
763 p
= strrchr( path
, '/' );
765 if (!(ptr
= DOSFS_ToDosFCBFormat( p
)) ||
766 !(temp
= SEGPTR_ALLOC( sizeof(char) * 16 )) )
774 dprintf_listbox(stddeb
, "ListBoxDirectory: path=%s mask=%s\n", path
, mask
);
778 while ((count
= DOSFS_FindNext( path
, mask
, 0, attrib
, skip
, &entry
)) > 0)
781 if (entry
.attr
& FA_DIRECTORY
)
783 if ((attrib
& DDL_DIRECTORY
) && strcmp(entry
.name
, ". "))
785 sprintf(temp
, "[%s]", DOSFS_ToDosDTAFormat( entry
.name
) );
787 if ((ret
= ListBoxAddString(lphl
, SEGPTR_GET(temp
))) == LB_ERR
) break;
790 else /* not a directory */
792 if (!(attrib
& DDL_EXCLUSIVE
) ||
793 ((attrib
& (FA_RDONLY
|FA_HIDDEN
|FA_SYSTEM
|FA_ARCHIVE
)) ==
794 (entry
.attr
& (FA_RDONLY
|FA_HIDDEN
|FA_SYSTEM
|FA_ARCHIVE
))))
796 strcpy( temp
, DOSFS_ToDosDTAFormat( entry
.name
) );
798 if ((ret
= ListBoxAddString(lphl
, SEGPTR_GET(temp
))) == LB_ERR
) break;
802 dprintf_listbox(stddeb
,"\tn - %i, file '%s'\n", count
, temp
);
804 if (attrib
& DDL_DRIVES
)
807 strcpy( temp
, "[-a-]" );
808 for (x
= 0; x
< MAX_DOS_DRIVES
; x
++, temp
[2]++)
810 if (DRIVE_IsValid(x
))
811 if ((ret
= ListBoxAddString(lphl
, SEGPTR_GET(temp
))) == LB_ERR
) break;
821 /* ------------------------- dimensions ------------------------- */
823 int ListBoxGetItemRect(LPHEADLIST lphl
, WORD wIndex
, LPRECT16 lprect
)
825 LPLISTSTRUCT lpls
= ListBoxGetItem(lphl
,wIndex
);
827 if (lpls
== NULL
) return LB_ERR
;
828 *lprect
= lpls
->itemRect
;
833 int ListBoxSetItemHeight(LPHEADLIST lphl
, WORD wIndex
, long height
)
837 if (!(lphl
->dwStyle
& LBS_OWNERDRAWVARIABLE
)) {
838 lphl
->StdItemHeight
= (short)height
;
842 lpls
= ListBoxGetItem(lphl
, wIndex
);
843 if (lpls
== NULL
) return LB_ERR
;
845 lpls
->mis
.itemHeight
= height
;
849 /* -------------------------- string search ------------------------ */
851 int ListBoxFindNextMatch(LPHEADLIST lphl
, WORD wChar
)
856 if ((char)wChar
< ' ') return LB_ERR
;
857 if (!lphl
->HasStrings
) return LB_ERR
;
859 lpls
= lphl
->lpFirst
;
861 for (count
= 0; lpls
!= NULL
; lpls
= lpls
->lpNext
, count
++) {
862 if (tolower(*lpls
->itemText
) == tolower((char)wChar
)) break;
864 if (lpls
== NULL
) return LB_ERR
;
866 for(; lpls
!= NULL
; lpls
= lpls
->lpNext
, count
++) {
867 if (*lpls
->itemText
!= (char)wChar
)
869 if ((short) count
> lphl
->ItemFocused
)
875 /***********************************************************************
878 static LONG
LBCreate(HWND hwnd
, WORD wParam
, LONG lParam
)
881 LONG dwStyle
= GetWindowLong32A(hwnd
,GWL_STYLE
);
884 CreateListBoxStruct(hwnd
, ODT_LISTBOX
, dwStyle
, GetParent(hwnd
));
885 lphl
= ListBoxGetStorageHeader(hwnd
);
886 dprintf_listbox(stddeb
,"ListBox created: lphl = %p dwStyle = %04x:%04x\n",
887 lphl
, HIWORD(dwStyle
), LOWORD(dwStyle
));
889 GetClientRect16(hwnd
,&rect
);
890 lphl
->ColumnsWidth
= rect
.right
- rect
.left
;
892 if (dwStyle
& WS_VSCROLL
)
893 SetScrollRange(hwnd
, SB_VERT
, 0, ListMaxFirstVisible(lphl
), TRUE
);
894 if (dwStyle
& WS_HSCROLL
)
895 SetScrollRange(hwnd
, SB_HORZ
, 1, 1, TRUE
);
901 /***********************************************************************
904 static LONG
LBDestroy(HWND hwnd
, WORD wParam
, LONG lParam
)
906 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
908 ListBoxResetContent(lphl
);
910 DestroyListBoxStruct(lphl
);
911 dprintf_listbox(stddeb
,"ListBox destroyed: lphl = %p\n",lphl
);
915 /***********************************************************************
918 static LONG
LBVScroll(HWND hwnd
, WORD wParam
, LONG lParam
)
920 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
923 dprintf_listbox(stddeb
,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
925 y
= lphl
->FirstVisible
;
929 if (lphl
->FirstVisible
> 0)
930 lphl
->FirstVisible
--;
934 lphl
->FirstVisible
++;
938 if (lphl
->FirstVisible
> lphl
->ItemsVisible
) {
939 lphl
->FirstVisible
-= lphl
->ItemsVisible
;
941 lphl
->FirstVisible
= 0;
946 lphl
->FirstVisible
+= lphl
->ItemsVisible
;
950 lphl
->FirstVisible
= LOWORD(lParam
);
954 if (lphl
->FirstVisible
> ListMaxFirstVisible(lphl
))
955 lphl
->FirstVisible
= ListMaxFirstVisible(lphl
);
957 if (y
!= lphl
->FirstVisible
) {
958 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
959 InvalidateRect32( hwnd
, NULL
, TRUE
);
964 /***********************************************************************
967 static LONG
LBHScroll(HWND hwnd
, WORD wParam
, LONG lParam
)
972 dprintf_listbox(stddeb
,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
974 lphl
= ListBoxGetStorageHeader(hwnd
);
975 y
= lphl
->FirstVisible
;
978 if (lphl
->FirstVisible
> lphl
->ItemsPerColumn
) {
979 lphl
->FirstVisible
-= lphl
->ItemsPerColumn
;
981 lphl
->FirstVisible
= 0;
985 lphl
->FirstVisible
+= lphl
->ItemsPerColumn
;
988 if (lphl
->ItemsPerColumn
!= 0) {
989 int lbsub
= lphl
->ItemsVisible
/ lphl
->ItemsPerColumn
* lphl
->ItemsPerColumn
;
990 if (lphl
->FirstVisible
> lbsub
) {
991 lphl
->FirstVisible
-= lbsub
;
993 lphl
->FirstVisible
= 0;
998 if (lphl
->ItemsPerColumn
!= 0)
999 lphl
->FirstVisible
+= lphl
->ItemsVisible
/
1000 lphl
->ItemsPerColumn
* lphl
->ItemsPerColumn
;
1003 lphl
->FirstVisible
= lphl
->ItemsPerColumn
* LOWORD(lParam
);
1006 if (lphl
->FirstVisible
> ListMaxFirstVisible(lphl
))
1007 lphl
->FirstVisible
= ListMaxFirstVisible(lphl
);
1009 if (lphl
->ItemsPerColumn
!= 0) {
1010 lphl
->FirstVisible
= lphl
->FirstVisible
/
1011 lphl
->ItemsPerColumn
* lphl
->ItemsPerColumn
+ 1;
1012 if (y
!= lphl
->FirstVisible
) {
1013 SetScrollPos(hwnd
, SB_HORZ
, lphl
->FirstVisible
/
1014 lphl
->ItemsPerColumn
+ 1, TRUE
);
1015 InvalidateRect32( hwnd
, NULL
, TRUE
);
1021 /***********************************************************************
1024 static LONG
LBLButtonDown(HWND hwnd
, WORD wParam
, LONG lParam
)
1026 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1034 lphl
->PrevFocused
= lphl
->ItemFocused
;
1036 y
= ListBoxFindMouse(lphl
, LOWORD(lParam
), HIWORD(lParam
));
1038 if (y
== -1) return 0;
1040 if (lphl
->dwStyle
& LBS_NOTIFY
&& y
!= LB_ERR
)
1041 if( SendMessage16(lphl
->hParent
, WM_LBTRACKPOINT
, y
, lParam
) )
1045 switch( lphl
->dwStyle
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
) )
1047 case LBS_MULTIPLESEL
:
1048 lphl
->ItemFocused
= y
;
1049 wRet
= ListBoxGetSel(lphl
, y
);
1050 ListBoxSetSel(lphl
, y
, !wRet
);
1052 case LBS_EXTENDEDSEL
:
1053 /* should handle extended mode here and in kbd handler
1056 if ( lphl
->PrevFocused
!= y
&& y
!= LB_ERR
)
1058 LPLISTSTRUCT lpls
= ListBoxGetItem( lphl
, lphl
->ItemFocused
= y
);
1059 n
= ListBoxSetSel(lphl
,-1,FALSE
);
1061 lpls
->itemState
= ODS_FOCUS
| ODS_SELECTED
;
1063 if( n
> 1 && n
!= LB_ERR
)
1064 InvalidateRect32( hwnd
,NULL
,TRUE
);
1071 if( y
!=lphl
->ItemFocused
)
1072 ListBoxSetCurSel(lphl
, y
);
1077 fprintf(stdnimp
,"Listbox: LBS_MULTIPLESEL and LBS_EXTENDEDSEL are on!\n");
1081 /* invalidate changed items */
1082 if( lphl
->dwStyle
& LBS_MULTIPLESEL
|| y
!=lphl
->PrevFocused
)
1084 ListBoxGetItemRect(lphl
, y
, &rectsel
);
1085 InvalidateRect16( hwnd
, &rectsel
, TRUE
);
1087 if( lphl
->PrevFocused
!=-1 && y
!=lphl
->PrevFocused
)
1089 ListBoxGetItemRect(lphl
, lphl
->PrevFocused
, &rectsel
);
1090 InvalidateRect16( hwnd
, &rectsel
, TRUE
);
1093 if (GetWindowLong32A(lphl
->hSelf
,GWL_EXSTYLE
) & WS_EX_DRAGDETECT
)
1094 if( DragDetect(lphl
->hSelf
,MAKEPOINT16(lParam
)) )
1095 SendMessage16(lphl
->hParent
, WM_BEGINDRAG
,0,0L);
1099 /***********************************************************************
1102 static LONG
LBLButtonUp(HWND hwnd
, WORD wParam
, LONG lParam
)
1104 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1106 if (GetCapture() == hwnd
) ReleaseCapture();
1108 if (lphl
->PrevFocused
!= lphl
->ItemFocused
)
1109 ListBoxSendNotification(lphl
, LBN_SELCHANGE
);
1114 /***********************************************************************
1117 static LONG
LBRButtonUp(HWND hwnd
, WORD wParam
, LONG lParam
)
1119 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1121 SendMessage16(lphl
->hParent
, WM_COMMAND
, GetWindowWord(hwnd
,GWW_ID
),
1122 MAKELONG(hwnd
, LBN_DBLCLK
));
1126 /***********************************************************************
1129 static LONG
LBMouseMove(HWND hwnd
, WORD wParam
, LONG lParam
)
1131 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1132 int y
,redraw_prev
= 0;
1134 RECT16 rect
, rectsel
; /* XXX Broken */
1136 dprintf_listbox(stddeb
,"LBMouseMove %d %d\n",SLOWORD(lParam
),SHIWORD(lParam
));
1137 if ((wParam
& MK_LBUTTON
) != 0) {
1138 y
= SHIWORD(lParam
);
1139 if (y
< LBMM_EDGE
) {
1140 if (lphl
->FirstVisible
> 0) {
1141 lphl
->FirstVisible
--;
1142 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
1143 InvalidateRect32( hwnd
, NULL
, TRUE
);
1147 GetClientRect16(hwnd
, &rect
);
1148 if (y
>= (rect
.bottom
-LBMM_EDGE
)) {
1149 if (lphl
->FirstVisible
< ListMaxFirstVisible(lphl
)) {
1150 lphl
->FirstVisible
++;
1151 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
1152 InvalidateRect32( hwnd
, NULL
, TRUE
);
1156 if ((y
> 0) && (y
< (rect
.bottom
- LBMM_EDGE
))) {
1157 if ((y
< rectsel
.top
) || (y
> rectsel
.bottom
)) {
1158 iRet
= ListBoxFindMouse(lphl
, LOWORD(lParam
), HIWORD(lParam
));
1159 if (iRet
== lphl
->ItemFocused
|| iRet
== -1) {
1162 if (lphl
->dwStyle
& LBS_MULTIPLESEL
) {
1163 lphl
->ItemFocused
= iRet
;
1164 ListBoxSendNotification(lphl
, LBN_SELCHANGE
);
1165 } else if ( lphl
->dwStyle
& LBS_EXTENDEDSEL
)
1167 /* Fixme: extended selection mode */
1168 ListBoxSetSel( lphl
, lphl
->ItemFocused
, 0);
1169 lphl
->PrevFocused
= lphl
->ItemFocused
;
1170 lphl
->ItemFocused
= iRet
;
1171 ListBoxSetSel( lphl
, iRet
, TRUE
);
1176 ListBoxSetCurSel(lphl
, (WORD
)iRet
);
1179 if( lphl
->PrevFocused
!=-1 && redraw_prev
)
1181 ListBoxGetItemRect(lphl
, lphl
->PrevFocused
, &rectsel
);
1182 InvalidateRect16( hwnd
, &rectsel
, TRUE
);
1184 ListBoxGetItemRect(lphl
, iRet
, &rectsel
);
1185 InvalidateRect16( hwnd
, &rectsel
, TRUE
);
1193 /***********************************************************************
1196 * Doesn't yet handle properly VK_SHIFT with LB_EXTENDEDSEL
1198 static LONG
LBKeyDown(HWND hwnd
, WORD wParam
, LONG lParam
)
1200 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1201 WORD newFocused
= 0xFFFF;
1204 ListBoxGetItemRect(lphl
,lphl
->ItemFocused
,&rect
);
1215 if ( lphl
->dwStyle
& LBS_WANTKEYBOARDINPUT
)
1217 newFocused
= (WORD
)(INT
)SendMessage16(lphl
->hParent
,WM_VKEYTOITEM
,
1218 wParam
,MAKELPARAM(lphl
->ItemFocused
,hwnd
));
1219 if ( newFocused
== 0xFFFE ) return 0L;
1221 if ( newFocused
== 0xFFFF )
1223 newFocused
= lphl
->ItemFocused
;
1232 newFocused
= lphl
->ItemsCount
- 1;
1235 if (lphl
->dwStyle
& LBS_MULTICOLUMN
) {
1236 if (newFocused
>= lphl
->ItemsPerColumn
) {
1237 newFocused
-= lphl
->ItemsPerColumn
;
1244 if (newFocused
> 0) newFocused
--;
1247 if (lphl
->dwStyle
& LBS_MULTICOLUMN
)
1248 newFocused
+= lphl
->ItemsPerColumn
;
1254 if (newFocused
> lphl
->ItemsVisible
)
1255 newFocused
-= lphl
->ItemsVisible
;
1256 else newFocused
= 0;
1259 newFocused
+= lphl
->ItemsVisible
;
1264 /* end of nested switch */
1268 if (lphl
->dwStyle
& LBS_MULTIPLESEL
)
1270 WORD wRet
= ListBoxGetSel(lphl
, lphl
->ItemFocused
);
1271 ListBoxSetSel(lphl
, lphl
->ItemFocused
, !wRet
);
1275 /* chars are handled in LBChar */
1280 /* at this point newFocused is set up */
1282 if (newFocused
>= lphl
->ItemsCount
)
1283 newFocused
= lphl
->ItemsCount
- 1;
1285 if (!(lphl
->dwStyle
& LBS_MULTIPLESEL
))
1287 ListBoxSetCurSel(lphl
, newFocused
);
1288 ListBoxSendNotification(lphl
, LBN_SELCHANGE
);
1291 lphl
->ItemFocused
= newFocused
;
1293 if( ListBoxScrollToFocus(lphl
) || (lphl
->dwStyle
&
1294 (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
)) )
1295 InvalidateRect32( hwnd
, NULL
, TRUE
);
1298 InvalidateRect16( hwnd
, &rect
, TRUE
);
1299 if( newFocused
< 0x8000 )
1301 ListBoxGetItemRect(lphl
, newFocused
, &rect
);
1302 InvalidateRect16( hwnd
, &rect
, TRUE
);
1306 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
1311 /***********************************************************************
1314 static LONG
LBChar(HWND hwnd
, WORD wParam
, LONG lParam
)
1316 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1317 WORD newFocused
= 0xFFFF;
1319 if ( (lphl
->dwStyle
& LBS_WANTKEYBOARDINPUT
) && !(lphl
->HasStrings
))
1321 newFocused
= (WORD
)(INT
)SendMessage16(lphl
->hParent
,WM_CHARTOITEM
,
1322 wParam
,MAKELPARAM(lphl
->ItemFocused
,hwnd
));
1323 if ( newFocused
== 0xFFFE ) return 0L;
1326 if (newFocused
== 0xFFFF )
1327 newFocused
= ListBoxFindNextMatch(lphl
, wParam
);
1329 if (newFocused
== (WORD
)LB_ERR
) return 0;
1331 if (newFocused
>= lphl
->ItemsCount
)
1332 newFocused
= lphl
->ItemsCount
- 1;
1334 if (!(lphl
->dwStyle
& LBS_MULTIPLESEL
))
1336 ListBoxSetCurSel(lphl
, newFocused
);
1337 ListBoxSendNotification(lphl
, LBN_SELCHANGE
);
1340 lphl
->ItemFocused
= newFocused
;
1341 ListBoxScrollToFocus(lphl
);
1342 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
1344 InvalidateRect32( hwnd
, NULL
, TRUE
);
1349 /***********************************************************************
1352 static LONG
LBSetRedraw(HWND hwnd
, WORD wParam
, LONG lParam
)
1354 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1356 dprintf_listbox(stddeb
,"ListBox WM_SETREDRAW hWnd=%04x w=%04x !\n",
1358 lphl
->bRedrawFlag
= wParam
;
1363 /***********************************************************************
1366 static LONG
LBSetFont(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1368 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1372 lphl
->hFont
= GetStockObject(SYSTEM_FONT
);
1374 lphl
->hFont
= (HFONT
) wParam
;
1376 /* a new font means possible new text height */
1377 /* does this mean the height of each entry must be separately changed? */
1378 /* or are we guaranteed to get a LBSetFont before the first insert/add? */
1379 if ((hdc
= GetDC(0)))
1382 GetTextMetrics16( hdc
, &tm
);
1383 lphl
->StdItemHeight
= tm
.tmHeight
;
1384 dprintf_listbox(stddeb
,"LBSetFont: new font %d with height %d\n",
1385 lphl
->hFont
, lphl
->StdItemHeight
);
1386 ReleaseDC( 0, hdc
);
1392 /***********************************************************************
1395 static LONG
LBPaint(HWND hwnd
, WORD wParam
, LONG lParam
)
1397 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1402 HDC16 hdc
= BeginPaint16( hwnd
, &ps
);
1403 DC
*dc
= (DC
*)GDI_GetObjPtr(hdc
, DC_MAGIC
);
1404 RECT16 rect
, paintRect
, scratchRect
;
1405 int i
, top
, height
, maxwidth
, ipc
;
1409 if (!IsWindowVisible(hwnd
) || !lphl
->bRedrawFlag
) {
1410 EndPaint16(hwnd
, &ps
);
1414 GetRgnBox16(dc
->w
.hGCClipRgn
,&paintRect
);
1415 GetClientRect16(hwnd
, &rect
);
1416 IntersectRect16(&paintRect
,&rect
,&paintRect
);
1418 hOldFont
= SelectObject(hdc
, lphl
->hFont
);
1420 hBrush
= (HBRUSH
)SendMessage32A( lphl
->hParent
, WM_CTLCOLORLISTBOX
,
1421 (WPARAM
)hdc
, (LPARAM
)hwnd
);
1422 if (hBrush
== 0) hBrush
= GetStockObject(WHITE_BRUSH
);
1424 FillRect16(hdc
, &rect
, hBrush
);
1426 maxwidth
= rect
.right
;
1427 if (lphl
->dwStyle
& LBS_MULTICOLUMN
) {
1428 rect
.right
= lphl
->ColumnsWidth
;
1430 lpls
= lphl
->lpFirst
;
1432 lphl
->ItemsVisible
= 0;
1433 lphl
->ItemsPerColumn
= ipc
= 0;
1435 for(i
= 0; i
< lphl
->ItemsCount
; i
++) {
1436 if (lpls
== NULL
) break;
1438 if (i
>= lphl
->FirstVisible
) {
1439 height
= lpls
->mis
.itemHeight
;
1441 if (top
> (rect
.bottom
-height
+1)) {
1442 if (lphl
->dwStyle
& LBS_MULTICOLUMN
) {
1443 lphl
->ItemsPerColumn
= MAX(lphl
->ItemsPerColumn
, ipc
);
1446 rect
.left
+= lphl
->ColumnsWidth
;
1447 rect
.right
+= lphl
->ColumnsWidth
;
1448 if (rect
.left
> maxwidth
) break;
1454 lpls
->itemRect
.top
= top
;
1455 lpls
->itemRect
.bottom
= top
+ height
;
1456 lpls
->itemRect
.left
= rect
.left
;
1457 lpls
->itemRect
.right
= rect
.right
;
1459 if( IntersectRect16(&scratchRect
,&paintRect
,&lpls
->itemRect
) )
1461 dprintf_listbox(stddeb
,"LBPaint: drawing item: %d %d %d %d %d\n",
1462 rect
.left
,top
,rect
.right
,top
+height
,lpls
->itemState
);
1464 if (lphl
->OwnerDrawn
&& (lphl
->ItemFocused
== i
) && GetFocus() == hwnd
)
1466 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_FOCUS
,
1467 lpls
->itemState
& ~ODS_FOCUS
);
1468 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_DRAWENTIRE
,
1469 lpls
->itemState
& ~ODS_FOCUS
);
1470 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_FOCUS
, lpls
->itemState
);
1473 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_DRAWENTIRE
,
1478 lphl
->ItemsVisible
++;
1482 lpls
= lpls
->lpNext
;
1484 ListBoxUpdateWindow(hwnd
,lphl
,FALSE
);
1485 SelectObject(hdc
,hOldFont
);
1486 EndPaint16( hwnd
, &ps
);
1490 /***********************************************************************
1493 static LONG
LBSetFocus(HWND hwnd
, WORD wParam
, LONG lParam
)
1495 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1497 dprintf_listbox(stddeb
,"ListBox WM_SETFOCUS for %04x\n",hwnd
);
1498 if(!(lphl
->dwStyle
& LBS_MULTIPLESEL
) )
1499 if( lphl
->ItemsCount
&& lphl
->ItemFocused
!= -1)
1501 HDC hDC
= GetDC(hwnd
);
1502 HFONT hOldFont
= SelectObject(hDC
, lphl
->hFont
);
1505 lpls
= ListBoxGetItem(lphl
,lphl
->ItemFocused
);
1506 lpls
->itemState
|= ODS_FOCUS
;
1508 ListBoxDrawItem(hwnd
,lphl
,hDC
,lpls
,&lpls
->itemRect
, ODA_FOCUS
, lpls
->itemState
);
1509 SelectObject(hDC
, hOldFont
);
1510 ReleaseDC(hwnd
,hDC
);
1513 ListBoxSendNotification(lphl
, LBN_SETFOCUS
);
1518 /***********************************************************************
1521 static LONG
LBKillFocus(HWND hwnd
, WORD wParam
, LONG lParam
)
1523 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1525 dprintf_listbox(stddeb
,"ListBox WM_KILLFOCUS for %04x\n",hwnd
);
1526 if (!(lphl
->dwStyle
& LBS_MULTIPLESEL
))
1528 if( lphl
->ItemsCount
)
1529 if( lphl
->ItemFocused
!= -1 )
1531 HDC hDC
= GetDC(hwnd
);
1532 HFONT hOldFont
= SelectObject(hDC
, lphl
->hFont
);
1535 lpls
= ListBoxGetItem(lphl
,lphl
->ItemFocused
);
1536 lpls
->itemState
&= ~ODS_FOCUS
;
1538 ListBoxDrawItem(hwnd
,lphl
,hDC
,lpls
,&lpls
->itemRect
, ODA_FOCUS
, lpls
->itemState
);
1539 SelectObject(hDC
, hOldFont
);
1540 ReleaseDC(hwnd
,hDC
);
1543 dprintf_listbox(stddeb
,"LBKillFocus: no focused item!\n");
1546 InvalidateRect32( hwnd
, NULL
, TRUE
);
1548 ListBoxSendNotification(lphl
, LBN_KILLFOCUS
);
1553 /***********************************************************************
1556 static LONG
LBResetContent(HWND hwnd
, WORD wParam
, LONG lParam
)
1558 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1560 dprintf_listbox(stddeb
,"ListBox LB_RESETCONTENT !\n");
1561 ListBoxResetContent(lphl
);
1562 ListBoxUpdateWindow(hwnd
, lphl
, TRUE
);
1566 /***********************************************************************
1569 static LONG
LBDir(HWND hwnd
, WORD wParam
, LONG lParam
)
1572 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1573 dprintf_listbox(stddeb
,"ListBox LB_DIR !\n");
1575 ret
= ListBoxDirectory(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
1576 ListBoxUpdateWindow(hwnd
, lphl
, TRUE
);
1580 /***********************************************************************
1583 static LONG
LBAddString(HWND hwnd
, WORD wParam
, LONG lParam
)
1586 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1588 wRet
= ListBoxAddString(lphl
, (SEGPTR
)lParam
);
1590 ListBoxUpdateWindow(hwnd
,lphl
,TRUE
);
1594 /***********************************************************************
1597 static LONG
LBGetText(HWND hwnd
, WORD wParam
, LONG lParam
)
1600 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1602 dprintf_listbox(stddeb
, "LB_GETTEXT wParam=%d\n",wParam
);
1603 wRet
= ListBoxGetText(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
1608 /***********************************************************************
1611 static LONG
LBInsertString(HWND hwnd
, WORD wParam
, LONG lParam
)
1614 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1616 if (lphl
->HasStrings
)
1617 wRet
= ListBoxInsertString(lphl
, wParam
, (LPCSTR
)PTR_SEG_TO_LIN(lParam
));
1619 wRet
= ListBoxInsertString(lphl
, wParam
, (LPCSTR
)lParam
);
1621 ListBoxUpdateWindow(hwnd
,lphl
,TRUE
);
1625 /***********************************************************************
1628 static LONG
LBDeleteString(HWND hwnd
, WORD wParam
, LONG lParam
)
1630 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1631 LONG lRet
= ListBoxDeleteString(lphl
,wParam
);
1633 ListBoxUpdateWindow(hwnd
,lphl
,TRUE
);
1637 /***********************************************************************
1640 static LONG
LBFindString(HWND hwnd
, WORD wParam
, LONG lParam
)
1642 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1643 return lbFindString(lphl
, wParam
, (SEGPTR
)lParam
, MATCH_SUBSTR
);
1646 /***********************************************************************
1649 static LONG
LBFindStringExact(HWND hwnd
, WORD wParam
, LONG lParam
)
1651 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1652 return lbFindString(lphl
, wParam
, (SEGPTR
)lParam
, MATCH_EXACT
);
1655 /***********************************************************************
1658 static LONG
LBGetCaretIndex(HWND hwnd
, WORD wParam
, LONG lParam
)
1660 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1661 return lphl
->ItemFocused
;
1664 /***********************************************************************
1667 static LONG
LBGetCount(HWND hwnd
, WORD wParam
, LONG lParam
)
1671 lphl
= ListBoxGetStorageHeader(hwnd
);
1672 return lphl
->ItemsCount
;
1675 /***********************************************************************
1678 static LONG
LBGetCurSel(HWND hwnd
, WORD wParam
, LONG lParam
)
1682 lphl
= ListBoxGetStorageHeader(hwnd
);
1683 dprintf_listbox(stddeb
,"ListBox LB_GETCURSEL %i !\n",
1685 return lphl
->ItemFocused
;
1688 /***********************************************************************
1689 * LBGetHorizontalExtent
1691 static LONG
LBGetHorizontalExtent(HWND hwnd
, WORD wParam
, LONG lParam
)
1696 /***********************************************************************
1699 static LONG
LBGetItemHeight(HWND hwnd
, WORD wParam
, LONG lParam
)
1701 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1702 LPLISTSTRUCT lpls
= ListBoxGetItem (lphl
, wParam
);
1704 if (lpls
== NULL
) return LB_ERR
;
1705 return lpls
->mis
.itemHeight
;
1708 /***********************************************************************
1711 static LONG
LBGetItemRect(HWND hwnd
, WORD wParam
, LONG lParam
)
1713 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1714 return ListBoxGetItemRect(lphl
, wParam
, PTR_SEG_TO_LIN(lParam
));
1717 /***********************************************************************
1720 static LONG
LBGetSel(HWND hwnd
, WORD wParam
, LONG lParam
)
1722 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1723 int iSel
= ListBoxGetSel(lphl
, wParam
);
1725 dprintf_listbox(stdnimp
,"LBGetSel: item %u - %i\n",wParam
,iSel
);
1727 return (iSel
)? 1 : 0;
1730 /***********************************************************************
1733 static LONG
LBGetSelCount(HWND hwnd
, WORD wParam
, LONG lParam
)
1735 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1740 if (!(lphl
->dwStyle
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
) ))
1743 for( lpls
= lphl
->lpFirst
;
1745 lpls
= lpls
->lpNext
)
1748 if (lpls
->itemState
)
1755 /***********************************************************************
1758 static LONG
LBGetSelItems(HWND hwnd
, WORD wParam
, LONG lParam
)
1760 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1763 int *lpItems
= PTR_SEG_TO_LIN(lParam
);
1765 if (!(lphl
->dwStyle
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
) ))
1768 if (wParam
== 0) return 0;
1770 lpls
= lphl
->lpFirst
;
1773 while (lpls
!= NULL
) {
1774 if (lpls
->itemState
> 0) lpItems
[cnt
++] = idx
;
1776 if (cnt
== wParam
) break;
1778 lpls
= lpls
->lpNext
;
1784 /***********************************************************************
1787 static LONG
LBGetTextLen(HWND hwnd
, WORD wParam
, LONG lParam
)
1789 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1790 LPLISTSTRUCT lpls
= ListBoxGetItem(lphl
,wParam
);
1792 if (lpls
== NULL
|| !lphl
->HasStrings
) return LB_ERR
;
1793 return strlen(lpls
->itemText
);
1796 /***********************************************************************
1799 static LONG
LBGetDlgCode(HWND hwnd
, WORD wParam
, LONG lParam
)
1801 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
1804 /***********************************************************************
1807 static LONG
LBGetTopIndex(HWND hwnd
, WORD wParam
, LONG lParam
)
1809 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1811 return lphl
->FirstVisible
;
1815 /***********************************************************************
1818 static LONG
LBSelectString(HWND hwnd
, WORD wParam
, LONG lParam
)
1820 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1823 iRet
= lbFindString(lphl
, wParam
, (SEGPTR
)lParam
, MATCH_SUBSTR
);
1827 if( lphl
->dwStyle
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
) )
1828 ListBoxSetSel(lphl
,iRet
,TRUE
);
1830 ListBoxSetCurSel(lphl
,iRet
);
1832 lphl
->ItemFocused
= iRet
;
1833 InvalidateRect32( hwnd
, 0, TRUE
);
1838 /***********************************************************************
1841 static LONG
LBSelItemRange(HWND hwnd
, WORD wParam
, LONG lParam
)
1843 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1846 WORD first
= LOWORD(lParam
);
1847 WORD last
= HIWORD(lParam
);
1848 BOOL select
= wParam
;
1850 if (!(lphl
->dwStyle
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
) ))
1853 if (first
>= lphl
->ItemsCount
||
1854 last
>= lphl
->ItemsCount
) return LB_ERR
;
1856 lpls
= lphl
->lpFirst
;
1859 while (lpls
!= NULL
) {
1861 lpls
->itemState
= select
? lpls
->itemState
| ODS_SELECTED
: 0;
1866 lpls
= lpls
->lpNext
;
1872 /***********************************************************************
1875 static LONG
LBSetCaretIndex(HWND hwnd
, WORD wParam
, LONG lParam
)
1877 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1880 if (!(lphl
->dwStyle
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
) )) return 0;
1882 dprintf_listbox(stddeb
,"LBSetCaretIndex: hwnd %04x n=%i\n",hwnd
,wParam
);
1884 if (wParam
>= lphl
->ItemsCount
) return LB_ERR
;
1886 lphl
->ItemFocused
= wParam
;
1887 i
= ListBoxScrollToFocus (lphl
);
1889 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
1891 InvalidateRect32( hwnd
, NULL
, TRUE
);
1896 /***********************************************************************
1899 static LONG
LBSetColumnWidth(HWND hwnd
, WORD wParam
, LONG lParam
)
1901 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1902 lphl
->ColumnsWidth
= wParam
;
1903 InvalidateRect32( hwnd
, NULL
, TRUE
);
1907 /***********************************************************************
1908 * LBSetHorizontalExtent
1910 static LONG
LBSetHorizontalExtent(HWND hwnd
, WORD wParam
, LONG lParam
)
1915 /***********************************************************************
1918 static LONG
LBGetItemData(HWND hwnd
, WORD wParam
, LONG lParam
)
1920 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1921 dprintf_listbox(stddeb
, "LB_GETITEMDATA wParam=%x\n", wParam
);
1922 return ListBoxGetItemData(lphl
, wParam
);
1925 /***********************************************************************
1928 static LONG
LBSetItemData(HWND hwnd
, WORD wParam
, LONG lParam
)
1930 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1931 dprintf_listbox(stddeb
, "LB_SETITEMDATA wParam=%x lParam=%lx\n", wParam
, lParam
);
1932 return ListBoxSetItemData(lphl
, wParam
, lParam
);
1935 /***********************************************************************
1938 static LONG
LBSetTabStops(HWND hwnd
, WORD wParam
, LONG lParam
)
1942 lphl
= ListBoxGetStorageHeader(hwnd
);
1944 if (lphl
->TabStops
!= NULL
) {
1945 lphl
->iNumStops
= 0;
1946 free (lphl
->TabStops
);
1949 lphl
->TabStops
= malloc (wParam
* sizeof (short));
1950 if (lphl
->TabStops
) {
1951 lphl
->iNumStops
= wParam
;
1952 memcpy (lphl
->TabStops
, PTR_SEG_TO_LIN(lParam
), wParam
* sizeof (short));
1959 /***********************************************************************
1962 static LONG
LBSetCurSel(HWND hwnd
, WORD wParam
, LONG lParam
)
1964 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1967 dprintf_listbox(stddeb
,"ListBox LB_SETCURSEL wParam=%x !\n",
1970 wRet
= ListBoxSetCurSel(lphl
, wParam
);
1972 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
1973 InvalidateRect32( hwnd
, NULL
, TRUE
);
1978 /***********************************************************************
1981 static LONG
LBSetSel(HWND hwnd
, WORD wParam
, LONG lParam
)
1983 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
1987 dprintf_listbox(stddeb
,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam
, lParam
);
1989 iRet
= ListBoxSetSel(lphl
, LOWORD(lParam
), wParam
);
1991 if( iRet
> 1 ) InvalidateRect32( hwnd
, NULL
, TRUE
);
1992 else if( iRet
!= LB_ERR
)
1994 if( lphl
->dwStyle
& LBS_EXTENDEDSEL
&&
1995 lphl
->ItemFocused
!= LOWORD(lParam
) )
1997 ListBoxGetItemRect(lphl
, lphl
->ItemFocused
, &rect
);
1998 InvalidateRect16( hwnd
, &rect
, TRUE
);
1999 lphl
->ItemFocused
= LOWORD(lParam
);
2001 ListBoxGetItemRect(lphl
,LOWORD(lParam
),&rect
);
2002 InvalidateRect16( hwnd
, &rect
, TRUE
);
2005 return (iRet
== (WORD
)LB_ERR
)? LB_ERR
: 0;
2008 /***********************************************************************
2011 static LONG
LBSetTopIndex(HWND hwnd
, WORD wParam
, LONG lParam
)
2013 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
2015 dprintf_listbox(stddeb
,"ListBox LB_SETTOPINDEX wParam=%x !\n",
2017 lphl
->FirstVisible
= wParam
;
2018 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
2020 InvalidateRect32( hwnd
, NULL
, TRUE
);
2025 /***********************************************************************
2028 static LONG
LBSetItemHeight(HWND hwnd
, WORD wParam
, LONG lParam
)
2030 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
2033 dprintf_listbox(stddeb
,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam
, lParam
);
2034 wRet
= ListBoxSetItemHeight(lphl
, wParam
, lParam
);
2035 InvalidateRect32( hwnd
, NULL
, TRUE
);
2039 /***********************************************************************
2042 static LRESULT
LBPassToParent(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2044 WND
* ptrWnd
= WIN_FindWndPtr(hwnd
);
2047 if( /* !(ptrWnd->dwExStyle & WS_EX_NOPARENTNOTIFY) && */
2049 return SendMessage16(ptrWnd
->parent
->hwndSelf
,message
,wParam
,lParam
);
2053 /***********************************************************************
2056 LRESULT
ListBoxWndProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2059 case WM_CREATE
: return LBCreate(hwnd
, wParam
, lParam
);
2060 case WM_DESTROY
: return LBDestroy(hwnd
, wParam
, lParam
);
2061 case WM_GETDLGCODE
: return LBGetDlgCode(hwnd
, wParam
, lParam
);
2062 case WM_VSCROLL
: return LBVScroll(hwnd
, wParam
, lParam
);
2063 case WM_HSCROLL
: return LBHScroll(hwnd
, wParam
, lParam
);
2064 case WM_LBUTTONDOWN
: return LBLButtonDown(hwnd
, wParam
, lParam
);
2065 case WM_LBUTTONUP
: return LBLButtonUp(hwnd
, wParam
, lParam
);
2066 case WM_RBUTTONUP
: return LBRButtonUp(hwnd
, wParam
, lParam
);
2067 case WM_LBUTTONDBLCLK
: return LBRButtonUp(hwnd
, wParam
, lParam
);
2068 case WM_MOUSEMOVE
: return LBMouseMove(hwnd
, wParam
, lParam
);
2069 case WM_KEYDOWN
: return LBKeyDown(hwnd
, wParam
, lParam
);
2070 case WM_CHAR
: return LBChar(hwnd
, wParam
, lParam
);
2071 case WM_SETFONT
: return LBSetFont(hwnd
, wParam
, lParam
);
2072 case WM_SETREDRAW
: return LBSetRedraw(hwnd
, wParam
, lParam
);
2073 case WM_PAINT
: return LBPaint(hwnd
, wParam
, lParam
);
2074 case WM_SETFOCUS
: return LBSetFocus(hwnd
, wParam
, lParam
);
2075 case WM_KILLFOCUS
: return LBKillFocus(hwnd
, wParam
, lParam
);
2076 case LB_RESETCONTENT
: return LBResetContent(hwnd
, wParam
, lParam
);
2077 case LB_DIR
: return LBDir(hwnd
, wParam
, lParam
);
2078 case LB_ADDSTRING
: return LBAddString(hwnd
, wParam
, lParam
);
2079 case LB_INSERTSTRING
: return LBInsertString(hwnd
, wParam
, lParam
);
2080 case LB_DELETESTRING
: return LBDeleteString(hwnd
, wParam
, lParam
);
2081 case LB_FINDSTRING
: return LBFindString(hwnd
, wParam
, lParam
);
2082 case LB_FINDSTRINGEXACT
: return LBFindStringExact(hwnd
, wParam
, lParam
);
2083 case LB_GETCARETINDEX
: return LBGetCaretIndex(hwnd
, wParam
, lParam
);
2084 case LB_GETCOUNT
: return LBGetCount(hwnd
, wParam
, lParam
);
2085 case LB_GETCURSEL
: return LBGetCurSel(hwnd
, wParam
, lParam
);
2086 case LB_GETHORIZONTALEXTENT
: return LBGetHorizontalExtent(hwnd
, wParam
, lParam
);
2087 case LB_GETITEMDATA
: return LBGetItemData(hwnd
, wParam
, lParam
);
2088 case LB_GETITEMHEIGHT
: return LBGetItemHeight(hwnd
, wParam
, lParam
);
2089 case LB_GETITEMRECT
: return LBGetItemRect(hwnd
, wParam
, lParam
);
2090 case LB_GETSEL
: return LBGetSel(hwnd
, wParam
, lParam
);
2091 case LB_GETSELCOUNT
: return LBGetSelCount(hwnd
, wParam
, lParam
);
2092 case LB_GETSELITEMS
: return LBGetSelItems(hwnd
, wParam
, lParam
);
2093 case LB_GETTEXT
: return LBGetText(hwnd
, wParam
, lParam
);
2094 case LB_GETTEXTLEN
: return LBGetTextLen(hwnd
, wParam
, lParam
);
2095 case LB_GETTOPINDEX
: return LBGetTopIndex(hwnd
, wParam
, lParam
);
2096 case LB_SELECTSTRING
: return LBSelectString(hwnd
, wParam
, lParam
);
2097 case LB_SELITEMRANGE
: return LBSelItemRange(hwnd
, wParam
, lParam
);
2098 case LB_SETCARETINDEX
: return LBSetCaretIndex(hwnd
, wParam
, lParam
);
2099 case LB_SETCOLUMNWIDTH
: return LBSetColumnWidth(hwnd
, wParam
, lParam
);
2100 case LB_SETHORIZONTALEXTENT
: return LBSetHorizontalExtent(hwnd
, wParam
, lParam
);
2101 case LB_SETITEMDATA
: return LBSetItemData(hwnd
, wParam
, lParam
);
2102 case LB_SETTABSTOPS
: return LBSetTabStops(hwnd
, wParam
, lParam
);
2103 case LB_SETCURSEL
: return LBSetCurSel(hwnd
, wParam
, lParam
);
2104 case LB_SETSEL
: return LBSetSel(hwnd
, wParam
, lParam
);
2105 case LB_SETTOPINDEX
: return LBSetTopIndex(hwnd
, wParam
, lParam
);
2106 case LB_SETITEMHEIGHT
: return LBSetItemHeight(hwnd
, wParam
, lParam
);
2108 case WM_DROPFILES
: return LBPassToParent(hwnd
, message
, wParam
, lParam
);
2110 /* these will have to be implemented for proper LBS_EXTENDEDSEL -
2112 * anchor item is an item that with caret (focused) item defines a
2113 * range of currently selected items when listbox is in the extended
2116 case LB_SETANCHORINDEX
: return LB_SETANCHORINDEX
; /* that's what Windows returns */
2117 case LB_GETANCHORINDEX
: return 0;
2120 case WM_QUERYDROPOBJECT
:
2124 LPDRAGINFO lpDragInfo
= (LPDRAGINFO
) PTR_SEG_TO_LIN((SEGPTR
)lParam
);
2125 LPHEADLIST lphl
= ListBoxGetStorageHeader(hwnd
);
2127 lpDragInfo
->l
= ListBoxFindMouse(lphl
,lpDragInfo
->pt
.x
,
2130 return LBPassToParent(hwnd
, message
, wParam
, lParam
);
2134 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
2138 /**********************************************************************
2139 * DlgDirSelect (USER.99)
2141 BOOL
DlgDirSelect( HWND hDlg
, LPSTR lpStr
, INT id
)
2146 dprintf_listbox( stddeb
, "DlgDirSelect: %04x '%s' %d\n", hDlg
, lpStr
, id
);
2147 if ((i
= SendDlgItemMessage16( hDlg
, id
, LB_GETCURSEL
, 0, 0 )) == LB_ERR
)
2149 if (!(buffer
= SEGPTR_ALLOC( 20 * sizeof(char) ))) return FALSE
;
2150 SendDlgItemMessage16(hDlg
, id
, LB_GETTEXT
, i
, (LPARAM
)SEGPTR_GET(buffer
) );
2151 if (buffer
[0] == '[') /* drive or directory */
2153 if (buffer
[1] == '-') /* drive */
2155 lpStr
[0] = buffer
[2];
2158 dprintf_listbox( stddeb
, "Returning drive '%s'\n", lpStr
);
2159 SEGPTR_FREE(buffer
);
2162 strcpy( lpStr
, buffer
+ 1 );
2163 lpStr
[strlen(lpStr
)-1] = '\\';
2164 dprintf_listbox( stddeb
, "Returning directory '%s'\n", lpStr
);
2165 SEGPTR_FREE(buffer
);
2168 strcpy( lpStr
, buffer
);
2169 dprintf_listbox( stddeb
, "Returning file '%s'\n", lpStr
);
2170 SEGPTR_FREE(buffer
);
2175 /**********************************************************************
2176 * DlgDirList (USER.100)
2178 INT
DlgDirList( HWND hDlg
, SEGPTR spec
, INT idLBox
, INT idStatic
, UINT attrib
)
2180 char *filespec
= (char *)PTR_SEG_TO_LIN( spec
);
2184 #define SENDMSG(msg,wparam,lparam) \
2185 ((attrib & DDL_POSTMSGS) ? PostMessage( hwnd, msg, wparam, lparam ) \
2186 : SendMessage16( hwnd, msg, wparam, lparam ))
2188 dprintf_listbox( stddeb
, "DlgDirList: %04x '%s' %d %d %04x\n",
2189 hDlg
, filespec
? filespec
: "NULL",
2190 idLBox
, idStatic
, attrib
);
2192 if (filespec
&& filespec
[0] && (filespec
[1] == ':'))
2194 drive
= toupper( filespec
[0] ) - 'A';
2196 if (!DRIVE_SetCurrentDrive( drive
)) return FALSE
;
2198 else drive
= DRIVE_GetCurrentDrive();
2200 if (idLBox
&& ((hwnd
= GetDlgItem( hDlg
, idLBox
)) != 0))
2204 if (!filespec
|| !filespec
[0]) strcpy( mask
, "*.*" );
2207 /* If the path exists and is a directory, chdir to it */
2208 if (DRIVE_Chdir( drive
, filespec
)) strcpy( mask
, "*.*" );
2213 if ((p2
= strrchr( p
, '\\' ))) p
= p2
+ 1;
2214 if ((p2
= strrchr( p
, '/' ))) p
= p2
+ 1;
2215 lstrcpyn32A( mask
, p
, sizeof(mask
) );
2219 if (!DRIVE_Chdir( drive
, filespec
)) return FALSE
;
2224 strcpy( (char *)PTR_SEG_TO_LIN(spec
), mask
);
2226 dprintf_listbox(stddeb
, "ListBoxDirectory: path=%c:\\%s mask=%s\n",
2227 'A' + drive
, DRIVE_GetDosCwd(drive
), mask
);
2229 SENDMSG( LB_RESETCONTENT
, 0, 0 );
2230 if ((attrib
& DDL_DIRECTORY
) && !(attrib
& DDL_EXCLUSIVE
))
2233 if (SENDMSG( LB_DIR
, attrib
& ~(DDL_DIRECTORY
| DDL_DRIVES
),
2234 (LPARAM
)spec
) == LB_ERR
) return FALSE
;
2235 if (!(temp
= SEGPTR_ALLOC( 4*sizeof(char) ))) return FALSE
;
2236 strcpy( temp
, "*.*" );
2237 /* FIXME: this won't work with PostMessage(), as temp will */
2238 /* have been freed by the time we do a DispatchMessage(). */
2239 if (SENDMSG( LB_DIR
, (attrib
& (DDL_DIRECTORY
| DDL_DRIVES
)) | DDL_EXCLUSIVE
,
2240 (LPARAM
)SEGPTR_GET(temp
) ) == LB_ERR
)
2249 if (SENDMSG( LB_DIR
, attrib
, (LPARAM
)spec
) == LB_ERR
) return FALSE
;
2253 if (idStatic
&& ((hwnd
= GetDlgItem( hDlg
, idStatic
)) != 0))
2256 int drive
= DRIVE_GetCurrentDrive();
2257 strcpy( temp
, "A:\\" );
2259 lstrcpyn32A( temp
+ 3, DRIVE_GetDosCwd(drive
), sizeof(temp
)-3 );
2261 /* Can't use PostMessage() here, because the string is on the stack */
2262 SetDlgItemText32A( hDlg
, idStatic
, temp
);