Release 950430
[wine/multimedia.git] / controls / listbox.c
blobd20e568658a4d44626f9f3faef8545e45e5c9e7c
1 /*
2 * Interface code to listbox widgets
4 * Copyright Martin Ayotte, 1993
5 * Copyright Constantine Sapuntzakis, 1995
7 static char Copyright[] = "Copyright Martin Ayotte, 1993";
8 */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include "windows.h"
17 #include "user.h"
18 #include "win.h"
19 #include "msdos.h"
20 #include "listbox.h"
21 #include "dos_fs.h"
22 #include "stddebug.h"
23 #include "debug.h"
25 #define GMEM_ZEROINIT 0x0040
27 LPLISTSTRUCT ListBoxGetItem (HWND hwnd, UINT uIndex);
28 int ListBoxScrolltoFocus(HWND hwnd);
29 LPHEADLIST ListBoxGetWindowAndStorage(HWND hwnd, WND **wndPtr);
30 LPHEADLIST ListBoxGetStorageHeader(HWND hwnd);
31 void RepaintListBox(HWND hwnd);
32 int ListBoxFindMouse(HWND hwnd, int X, int Y);
33 int CreateListBoxStruct(HWND hwnd);
34 void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls);
35 int ListBoxAddString(HWND hwnd, LPSTR newstr);
36 int ListBoxInsertString(HWND hwnd, UINT uIndex, LPSTR newstr);
37 int ListBoxGetText(HWND hwnd, UINT uIndex, LPSTR OutStr, BOOL bItemData);
38 int ListBoxSetItemData(HWND hwnd, UINT uIndex, DWORD ItemData);
39 int ListBoxDeleteString(HWND hwnd, UINT uIndex);
40 int ListBoxFindString(HWND hwnd, UINT nFirst, LPSTR MatchStr);
41 int ListBoxResetContent(HWND hwnd);
42 int ListBoxSetCurSel(HWND hwnd, WORD wIndex);
43 int ListBoxSetSel(HWND hwnd, WORD wIndex, WORD state);
44 int ListBoxGetSel(HWND hwnd, WORD wIndex);
45 int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec);
46 int ListBoxGetItemRect(HWND hwnd, WORD wIndex, LPRECT rect);
47 int ListBoxSetItemHeight(HWND hwnd, WORD wIndex, long height);
48 int ListBoxDefaultItem(HWND hwnd, WND *wndPtr,
49 LPHEADLIST lphl, LPLISTSTRUCT lpls);
50 int ListBoxFindNextMatch(HWND hwnd, WORD wChar);
51 int ListMaxFirstVisible(LPHEADLIST lphl);
52 void ListBoxSendNotification(HWND hwnd, WORD code);
54 #define OWNER_DRAWN(wndPtr) \
55 ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) || \
56 (wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE))
58 #define HasStrings(wndPtr) ( \
59 (! OWNER_DRAWN (wndPtr)) || \
60 (wndPtr->dwStyle & LBS_HASSTRINGS))
62 #if 0
63 #define LIST_HEAP_ALLOC(lphl,f,size) ((int)HEAP_Alloc(&lphl->Heap,f,size) & 0xffff)
64 #define LIST_HEAP_FREE(lphl,handle) (HEAP_Free(&lphl->Heap,LIST_HEAP_ADDR(lphl,handle)))
65 #define LIST_HEAP_ADDR(lphl,handle) \
66 ((void *)((handle) ? ((handle) | ((int)lphl->Heap & 0xffff0000)) : 0))
67 #else
68 /* FIXME: shouldn't each listbox have its own heap? */
69 #define LIST_HEAP_ALLOC(lphl,f,size) USER_HEAP_ALLOC(size)
70 #define LIST_HEAP_FREE(lphl,handle) USER_HEAP_FREE(handle)
71 #define LIST_HEAP_ADDR(lphl,handle) USER_HEAP_LIN_ADDR(handle)
72 #define LIST_HEAP_SEG_ADDR(lphl,handle) USER_HEAP_SEG_ADDR(handle)
73 #endif
75 #define LIST_HEAP_SIZE 0x10000
77 /* Design notes go here */
79 LONG LBCreate( HWND hwnd, WORD message, WORD wParam, LONG lParam );
80 LONG LBGetDlgCode( HWND hwnd, WORD message, WORD wParam, LONG lParam );
81 LONG LBDestroy( HWND hwnd, WORD message, WORD wParam, LONG lParam );
82 LONG LBVScroll( HWND hwnd, WORD message, WORD wParam, LONG lParam );
83 LONG LBHScroll( HWND hwnd, WORD message, WORD wParam, LONG lParam );
84 LONG LBLButtonDown( HWND hwnd, WORD message, WORD wParam, LONG lParam );
85 LONG LBLButtonUp( HWND hwnd, WORD message, WORD wParam, LONG lParam );
86 LONG LBRButtonUp( HWND hwnd, WORD message, WORD wParam, LONG lParam );
87 LONG LBMouseMove( HWND hwnd, WORD message, WORD wParam, LONG lParam );
88 LONG LBKeyDown( HWND hwnd, WORD message, WORD wParam, LONG lParam );
89 LONG LBSetFont( HWND hwnd, WORD message, WORD wParam, LONG lParam );
90 LONG LBSetRedraw( HWND hwnd, WORD message, WORD wParam, LONG lParam );
91 LONG LBPaint( HWND hwnd, WORD message, WORD wParam, LONG lParam );
92 LONG LBSetFocus( HWND hwnd, WORD message, WORD wParam, LONG lParam );
93 LONG LBKillFocus( HWND hwnd, WORD message, WORD wParam, LONG lParam );
94 LONG LBResetContent( HWND hwnd, WORD message, WORD wParam, LONG lParam );
95 LONG LBDir( HWND hwnd, WORD message, WORD wParam, LONG lParam );
96 LONG LBAddString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
97 LONG LBGetText( HWND hwnd, WORD message, WORD wParam, LONG lParam );
98 LONG LBInsertString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
99 LONG LBDeleteString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
100 LONG LBFindString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
101 LONG LBGetCaretIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam );
102 LONG LBGetCount( HWND hwnd, WORD message, WORD wParam, LONG lParam );
103 LONG LBGetCurSel( HWND hwnd, WORD message, WORD wParam, LONG lParam );
104 LONG LBGetHorizontalExtent(HWND hwnd, WORD message, WORD wParam, LONG lParam );
105 LONG LBGetItemData( HWND hwnd, WORD message, WORD wParam, LONG lParam );
106 LONG LBGetItemHeight( HWND hwnd, WORD message, WORD wParam, LONG lParam );
107 LONG LBGetItemRect( HWND hwnd, WORD message, WORD wParam, LONG lParam );
108 LONG LBGetSel( HWND hwnd, WORD message, WORD wParam, LONG lParam );
109 LONG LBGetSelCount( HWND hwnd, WORD message, WORD wParam, LONG lParam );
110 LONG LBGetSelItems( HWND hwnd, WORD message, WORD wParam, LONG lParam );
111 LONG LBGetTextLen( HWND hwnd, WORD message, WORD wParam, LONG lParam );
112 LONG LBGetTopIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam );
113 LONG LBSelectString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
114 LONG LBSelItemRange( HWND hwnd, WORD message, WORD wParam, LONG lParam );
115 LONG LBSetCaretIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam );
116 LONG LBSetColumnWidth( HWND hwnd, WORD message, WORD wParam, LONG lParam );
117 LONG LBSetHorizontalExtent(HWND hwnd, WORD message, WORD wParam, LONG lParam );
118 LONG LBSetItemData( HWND hwnd, WORD message, WORD wParam, LONG lParam );
119 LONG LBSetTabStops( HWND hwnd, WORD message, WORD wParam, LONG lParam );
120 LONG LBSetCurSel( HWND hwnd, WORD message, WORD wParam, LONG lParam );
121 LONG LBSetSel( HWND hwnd, WORD message, WORD wParam, LONG lParam );
122 LONG LBSetTopIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam );
123 LONG LBSetItemHeight( HWND hwnd, WORD message, WORD wParam, LONG lParam );
126 typedef struct {
127 WORD message;
128 LONG (*handler)(HWND, WORD, WPARAM, LPARAM);
129 } msg_tbl;
131 static msg_tbl methods[] = {
132 {WM_CREATE, LBCreate},
133 {WM_DESTROY, LBDestroy},
134 {WM_GETDLGCODE, LBGetDlgCode},
135 {WM_VSCROLL, LBVScroll},
136 {WM_HSCROLL, LBHScroll},
137 {WM_LBUTTONDOWN, LBLButtonDown},
138 {WM_LBUTTONUP, LBLButtonUp},
139 {WM_RBUTTONUP, LBRButtonUp},
140 {WM_LBUTTONDBLCLK, LBRButtonUp},
141 {WM_MOUSEMOVE, LBMouseMove},
142 {WM_KEYDOWN, LBKeyDown},
143 {WM_SETFONT, LBSetFont},
144 {WM_SETREDRAW, LBSetRedraw},
145 {WM_PAINT, LBPaint},
146 {WM_SETFOCUS, LBSetFocus},
147 {WM_KILLFOCUS, LBKillFocus},
148 {LB_RESETCONTENT, LBResetContent},
149 {LB_DIR, LBDir},
150 {LB_ADDSTRING, LBAddString},
151 {LB_INSERTSTRING, LBInsertString},
152 {LB_DELETESTRING, LBDeleteString},
153 {LB_FINDSTRING, LBFindString},
154 {LB_GETCARETINDEX, LBGetCaretIndex},
155 {LB_GETCOUNT, LBGetCount},
156 {LB_GETCURSEL, LBGetCurSel},
157 {LB_GETHORIZONTALEXTENT, LBGetHorizontalExtent},
158 {LB_GETITEMDATA, LBGetItemData},
159 {LB_GETITEMHEIGHT, LBGetItemHeight},
160 {LB_GETITEMRECT, LBGetItemRect},
161 {LB_GETSEL, LBGetSel},
162 {LB_GETSELCOUNT, LBGetSelCount},
163 {LB_GETSELITEMS, LBGetSelItems},
164 {LB_GETTEXT, LBGetText},
165 {LB_GETTEXTLEN, LBGetTextLen},
166 {LB_GETTOPINDEX, LBGetTopIndex},
167 {LB_SELECTSTRING, LBSelectString},
168 {LB_SELITEMRANGE, LBSelItemRange},
169 {LB_SETCARETINDEX, LBSetCaretIndex},
170 {LB_SETCOLUMNWIDTH, LBSetColumnWidth},
171 {LB_SETHORIZONTALEXTENT, LBSetHorizontalExtent},
172 {LB_SETITEMDATA, LBSetItemData},
173 {LB_SETTABSTOPS, LBSetTabStops},
174 {LB_SETCURSEL, LBSetCurSel},
175 {LB_SETSEL, LBSetSel},
176 {LB_SETTOPINDEX, LBSetTopIndex},
177 {LB_SETITEMHEIGHT, LBSetItemHeight}
180 /***********************************************************************
181 * LBCreate
183 LONG LBCreate( HWND hwnd, WORD message, WORD wParam, LONG lParam )
186 LPHEADLIST lphl;
187 CREATESTRUCT *createStruct;
188 WND *wndPtr;
190 CreateListBoxStruct(hwnd);
191 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
193 dprintf_listbox(stddeb,"ListBox WM_CREATE %p !\n", lphl);
195 if (lphl == NULL) return 0;
197 createStruct = (CREATESTRUCT *)PTR_SEG_TO_LIN(lParam);
199 if (HIWORD(createStruct->lpCreateParams) != 0)
200 lphl->hWndLogicParent = (HWND)HIWORD(createStruct->lpCreateParams);
201 else
202 lphl->hWndLogicParent = GetParent(hwnd);
204 lphl->hFont = GetStockObject(SYSTEM_FONT);
205 lphl->ColumnsWidth = wndPtr->rectClient.right - wndPtr->rectClient.left;
207 SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
208 SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
210 return 0;
213 int CreateListBoxStruct(HWND hwnd)
216 WND *wndPtr;
217 LPHEADLIST lphl;
219 wndPtr = WIN_FindWndPtr(hwnd);
221 lphl = (LPHEADLIST)malloc(sizeof(HEADLIST));
222 *((LPHEADLIST *)&wndPtr->wExtra[1]) = lphl;
224 lphl->lpFirst = NULL;
225 lphl->ItemsCount = 0;
226 lphl->ItemsVisible = 0;
227 lphl->FirstVisible = 1;
228 lphl->ColumnsVisible = 1;
229 lphl->ItemsPerColumn = 0;
230 lphl->StdItemHeight = 15;
231 lphl->ItemFocused = -1;
232 lphl->PrevFocused = -1;
233 lphl->DrawCtlType = ODT_LISTBOX;
234 lphl->bRedrawFlag = TRUE;
235 lphl->iNumStops = 0;
236 lphl->TabStops = NULL;
238 if (OWNER_DRAWN(wndPtr))
239 lphl->hDrawItemStruct = USER_HEAP_ALLOC(sizeof(DRAWITEMSTRUCT));
240 else
241 lphl->hDrawItemStruct = 0;
243 #if 0
244 HeapHandle = GlobalAlloc(GMEM_FIXED, LIST_HEAP_SIZE);
245 HeapBase = GlobalLock(HeapHandle);
246 HEAP_Init(&lphl->Heap, HeapBase, LIST_HEAP_SIZE);
247 #endif
248 return TRUE;
252 /***********************************************************************
253 * LBDestroy
255 LONG LBDestroy( HWND hwnd, WORD message, WORD wParam, LONG lParam )
258 LPHEADLIST lphl;
259 WND *wndPtr;
261 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
263 if (lphl == NULL) return 0;
264 ListBoxResetContent(hwnd);
266 if (lphl->hDrawItemStruct)
267 USER_HEAP_FREE(lphl->hDrawItemStruct);
269 /* XXX need to free lphl->Heap */
270 free(lphl);
271 *((LPHEADLIST *)&wndPtr->wExtra[1]) = 0;
272 dprintf_listbox(stddeb,"ListBox WM_DESTROY %p !\n", lphl);
273 return 0;
276 /* get the maximum value of lphl->FirstVisible */
277 int ListMaxFirstVisible(LPHEADLIST lphl)
279 int m = lphl->ItemsCount-lphl->ItemsVisible+1;
280 return (m < 1) ? 1 : m;
284 /***********************************************************************
285 * LBVScroll
287 LONG LBVScroll( HWND hwnd, WORD message, WORD wParam, LONG lParam )
290 LPHEADLIST lphl;
291 int y;
293 dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
294 wParam, lParam);
295 lphl = ListBoxGetStorageHeader(hwnd);
296 if (lphl == NULL) return 0;
297 y = lphl->FirstVisible;
299 switch(wParam) {
300 case SB_LINEUP:
301 if (lphl->FirstVisible > 1)
302 lphl->FirstVisible--;
303 break;
305 case SB_LINEDOWN:
306 if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
307 lphl->FirstVisible++;
308 break;
310 case SB_PAGEUP:
311 if (lphl->FirstVisible > 1)
312 lphl->FirstVisible -= lphl->ItemsVisible;
313 break;
315 case SB_PAGEDOWN:
316 if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
317 lphl->FirstVisible += lphl->ItemsVisible;
318 break;
320 case SB_THUMBTRACK:
321 lphl->FirstVisible = LOWORD(lParam);
322 break;
325 if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
326 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
327 lphl->FirstVisible = ListMaxFirstVisible(lphl);
329 if (y != lphl->FirstVisible) {
330 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
331 InvalidateRect(hwnd, NULL, TRUE);
332 UpdateWindow(hwnd);
334 return 0;
337 /***********************************************************************
338 * LBHScroll
340 LONG LBHScroll( HWND hwnd, WORD message, WORD wParam, LONG lParam )
343 LPHEADLIST lphl;
344 int y;
346 dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
347 wParam, lParam);
348 lphl = ListBoxGetStorageHeader(hwnd);
349 if (lphl == NULL) return 0;
350 y = lphl->FirstVisible;
351 switch(wParam) {
352 case SB_LINEUP:
353 if (lphl->FirstVisible > 1)
354 lphl->FirstVisible -= lphl->ItemsPerColumn;
355 break;
356 case SB_LINEDOWN:
357 if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
358 lphl->FirstVisible += lphl->ItemsPerColumn;
359 break;
360 case SB_PAGEUP:
361 if (lphl->FirstVisible > 1 && lphl->ItemsPerColumn != 0)
362 lphl->FirstVisible -= lphl->ItemsVisible /
363 lphl->ItemsPerColumn * lphl->ItemsPerColumn;
364 break;
365 case SB_PAGEDOWN:
366 if (lphl->FirstVisible < ListMaxFirstVisible(lphl) &&
367 lphl->ItemsPerColumn != 0)
368 lphl->FirstVisible += lphl->ItemsVisible /
369 lphl->ItemsPerColumn * lphl->ItemsPerColumn;
370 break;
371 case SB_THUMBTRACK:
372 lphl->FirstVisible = lphl->ItemsPerColumn *
373 (LOWORD(lParam) - 1) + 1;
374 break;
376 if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
377 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
378 lphl->FirstVisible = ListMaxFirstVisible(lphl);
380 if (lphl->ItemsPerColumn != 0) {
381 lphl->FirstVisible = lphl->FirstVisible /
382 lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
383 if (y != lphl->FirstVisible) {
384 SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible /
385 lphl->ItemsPerColumn + 1, TRUE);
386 InvalidateRect(hwnd, NULL, TRUE);
387 UpdateWindow(hwnd);
390 return 0;
393 /***********************************************************************
394 * LBLButtonDown
396 LONG LBLButtonDown( HWND hwnd, WORD message, WORD wParam, LONG lParam )
399 LPHEADLIST lphl;
400 WND *wndPtr;
401 WORD wRet;
402 int y;
403 RECT rectsel;
405 SetFocus(hwnd);
406 SetCapture(hwnd);
408 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
409 if (lphl == NULL) return 0;
411 lphl->PrevFocused = lphl->ItemFocused;
413 y = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
414 if (y==-1)
415 return 0;
417 if (wndPtr->dwStyle & LBS_MULTIPLESEL) {
418 lphl->ItemFocused = y;
419 wRet = ListBoxGetSel(hwnd, y);
420 ListBoxSetSel(hwnd, y, !wRet);
422 else
423 ListBoxSetCurSel(hwnd, y);
425 if (wndPtr->dwStyle & LBS_MULTIPLESEL)
426 ListBoxSendNotification( hwnd, LBN_SELCHANGE );
428 ListBoxGetItemRect(hwnd, y, &rectsel);
430 InvalidateRect(hwnd, NULL, TRUE);
431 UpdateWindow(hwnd);
433 return 0;
436 /***********************************************************************
437 * LBLButtonUp
439 LONG LBLButtonUp( HWND hwnd, WORD message, WORD wParam, LONG lParam )
442 LPHEADLIST lphl;
443 WND *wndPtr;
445 if (GetCapture() == hwnd) ReleaseCapture();
447 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
448 if (lphl == NULL) return 0;
449 if (lphl->PrevFocused != lphl->ItemFocused)
450 ListBoxSendNotification( hwnd, LBN_SELCHANGE );
452 return 0;
455 /***********************************************************************
456 * LBRButtonUp
458 LONG LBRButtonUp( HWND hwnd, WORD message, WORD wParam, LONG lParam )
461 LPHEADLIST lphl;
462 WND *wndPtr;
464 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
465 if (lphl == NULL) return 0;
466 SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
467 MAKELONG(hwnd, LBN_DBLCLK));
469 return 0;
472 /***********************************************************************
473 * LBMouseMove
475 LONG LBMouseMove( HWND hwnd, WORD message, WORD wParam, LONG lParam )
478 LPHEADLIST lphl;
479 WND *wndPtr;
480 int y;
481 WORD wRet;
482 RECT rect, rectsel; /* XXX Broken */
484 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
485 if (lphl == NULL) return 0;
486 if ((wParam & MK_LBUTTON) != 0) {
487 y = HIWORD(lParam);
488 if (y < 4) {
489 if (lphl->FirstVisible > 1) {
490 lphl->FirstVisible--;
491 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
492 InvalidateRect(hwnd, NULL, TRUE);
493 UpdateWindow(hwnd);
494 return 0;
497 GetClientRect(hwnd, &rect);
498 if (y > (rect.bottom - 4)) {
499 if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
500 lphl->FirstVisible++;
501 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
502 InvalidateRect(hwnd, NULL, TRUE);
503 UpdateWindow(hwnd);
504 return 0;
507 if ((y > 0) && (y < (rect.bottom - 4))) {
508 if ((y < rectsel.top) || (y > rectsel.bottom)) {
509 wRet = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
510 if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
511 lphl->ItemFocused = wRet;
512 ListBoxSendNotification(hwnd, LBN_SELCHANGE);
514 else
515 ListBoxSetCurSel(hwnd, wRet);
516 ListBoxGetItemRect(hwnd, wRet, &rectsel);
517 InvalidateRect(hwnd, NULL, TRUE);
518 UpdateWindow(hwnd);
523 return 0;
526 /***********************************************************************
527 * LBKeyDown
529 LONG LBKeyDown( HWND hwnd, WORD message, WORD wParam, LONG lParam )
532 LPHEADLIST lphl;
533 WND *wndPtr;
534 HWND hWndCtl;
535 WORD wRet;
537 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
538 if (lphl == NULL) return 0;
539 switch(wParam) {
540 case VK_TAB:
541 hWndCtl = GetNextDlgTabItem(lphl->hWndLogicParent,
542 hwnd, !(GetKeyState(VK_SHIFT) < 0));
543 SetFocus(hWndCtl);
544 if(debugging_listbox){
545 if ((GetKeyState(VK_SHIFT) < 0))
546 dprintf_listbox(stddeb,"ListBox PreviousDlgTabItem %04X !\n", hWndCtl);
547 else
548 dprintf_listbox(stddeb,"ListBox NextDlgTabItem %04X !\n", hWndCtl);
550 break;
551 case VK_HOME:
552 lphl->ItemFocused = 0;
553 break;
554 case VK_END:
555 lphl->ItemFocused = lphl->ItemsCount - 1;
556 break;
557 case VK_LEFT:
558 if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
559 lphl->ItemFocused -= lphl->ItemsPerColumn;
561 break;
562 case VK_UP:
563 lphl->ItemFocused--;
564 break;
565 case VK_RIGHT:
566 if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
567 lphl->ItemFocused += lphl->ItemsPerColumn;
569 break;
570 case VK_DOWN:
571 lphl->ItemFocused++;
572 break;
573 case VK_PRIOR:
574 lphl->ItemFocused -= lphl->ItemsVisible;
575 break;
576 case VK_NEXT:
577 lphl->ItemFocused += lphl->ItemsVisible;
578 break;
579 case VK_SPACE:
580 wRet = ListBoxGetSel(hwnd, lphl->ItemFocused);
581 ListBoxSetSel(hwnd, lphl->ItemFocused, !wRet);
582 break;
583 default:
584 ListBoxFindNextMatch(hwnd, wParam);
585 return 0;
588 if (lphl->ItemFocused < 0) lphl->ItemFocused = 0;
589 if (lphl->ItemFocused >= lphl->ItemsCount)
590 lphl->ItemFocused = lphl->ItemsCount - 1;
592 if (lphl->ItemsVisible != 0)
593 lphl->FirstVisible = lphl->ItemFocused / lphl->ItemsVisible *
594 lphl->ItemsVisible + 1;
596 if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
597 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
598 lphl->FirstVisible = ListMaxFirstVisible(lphl);
600 if ((wndPtr->dwStyle & LBS_MULTIPLESEL) != LBS_MULTIPLESEL) {
601 ListBoxSetCurSel(hwnd, lphl->ItemFocused);
602 ListBoxSendNotification(hwnd, LBN_SELCHANGE);
605 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
606 InvalidateRect(hwnd, NULL, TRUE);
607 UpdateWindow(hwnd);
609 return 0;
612 /***********************************************************************
613 * LBSetRedraw
615 LONG LBSetRedraw( HWND hwnd, WORD message, WORD wParam, LONG lParam )
618 LPHEADLIST lphl;
619 WND *wndPtr;
621 dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd=%04X w=%04X !\n", hwnd, wParam);
622 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
623 if (lphl == NULL) return 0;
624 lphl->bRedrawFlag = wParam;
626 return 0;
629 /***********************************************************************
630 * LBSetFont
633 LONG LBSetFont( HWND hwnd, WORD message, WORD wParam, LONG lParam )
636 LPHEADLIST lphl;
637 WND *wndPtr;
639 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
640 if (lphl == NULL) return 0;
642 if (wParam == 0)
643 lphl->hFont = GetStockObject(SYSTEM_FONT);
644 else
645 lphl->hFont = wParam;
647 return 0;
650 /***********************************************************************
651 * LBPaint
653 LONG LBPaint( HWND hwnd, WORD message, WORD wParam, LONG lParam )
656 RepaintListBox(hwnd);
657 return 0;
660 /***********************************************************************
661 * LBSetFocus
663 LONG LBSetFocus( HWND hwnd, WORD message, WORD wParam, LONG lParam )
666 LPHEADLIST lphl;
667 WND *wndPtr;
669 dprintf_listbox(stddeb,"ListBox WM_SETFOCUS !\n");
670 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
672 return 0;
675 /***********************************************************************
676 * LBKillFocus
678 LONG LBKillFocus( HWND hwnd, WORD message, WORD wParam, LONG lParam )
681 dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS !\n");
683 InvalidateRect(hwnd, NULL, TRUE);
684 UpdateWindow(hwnd);
686 return 0;
689 /***********************************************************************
690 * LBResetContent
692 LONG LBResetContent( HWND hwnd, WORD message, WORD wParam, LONG lParam )
695 dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
696 ListBoxResetContent(hwnd);
698 return 0;
701 /***********************************************************************
702 * LBDir
704 LONG LBDir( HWND hwnd, WORD message, WORD wParam, LONG lParam )
707 WORD wRet;
708 dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
710 wRet = ListBoxDirectory(hwnd, wParam,
711 (LPSTR)PTR_SEG_TO_LIN(lParam));
712 InvalidateRect(hwnd, NULL, TRUE);
713 UpdateWindow(hwnd);
714 return wRet;
717 /***********************************************************************
718 * LBAddString
720 LONG LBAddString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
723 WORD wRet;
724 WND *wndPtr;
726 wndPtr = WIN_FindWndPtr(hwnd);
728 if (HasStrings(wndPtr))
729 wRet = ListBoxAddString(hwnd, (LPSTR)PTR_SEG_TO_LIN(lParam));
730 else
731 wRet = ListBoxAddString(hwnd, (LPSTR)lParam);
733 return wRet;
736 /***********************************************************************
737 * LBGetText
739 LONG LBGetText( HWND hwnd, WORD message, WORD wParam, LONG lParam )
742 LONG wRet;
744 dprintf_listbox(stddeb, "LB_GETTEXT wParam=%d\n",wParam);
745 wRet = ListBoxGetText(hwnd, wParam,
746 (LPSTR)PTR_SEG_TO_LIN(lParam), FALSE);
748 return wRet;
751 /***********************************************************************
752 * LBInsertString
754 LONG LBInsertString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
757 WORD wRet;
758 WND *wndPtr;
760 wndPtr = WIN_FindWndPtr(hwnd);
762 if (HasStrings(wndPtr))
763 wRet = ListBoxInsertString(hwnd, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
764 else
765 wRet = ListBoxInsertString(hwnd, wParam, (LPSTR)lParam);
767 return wRet;
770 /***********************************************************************
771 * LBDeleteString
773 LONG LBDeleteString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
776 return ListBoxDeleteString(hwnd, wParam);
779 /***********************************************************************
780 * LBFindString
782 LONG LBFindString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
785 return ListBoxFindString(hwnd, wParam,
786 (LPSTR)PTR_SEG_TO_LIN(lParam));
789 /***********************************************************************
790 * LBGetCaretIndex
792 LONG LBGetCaretIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam )
795 LPHEADLIST lphl;
797 lphl = ListBoxGetStorageHeader(hwnd);
798 if (lphl == NULL) return LB_ERR;
800 return lphl->ItemFocused;
803 /***********************************************************************
804 * LBGetCount
806 LONG LBGetCount( HWND hwnd, WORD message, WORD wParam, LONG lParam )
809 LPHEADLIST lphl;
811 lphl = ListBoxGetStorageHeader(hwnd);
812 return lphl->ItemsCount;
815 /***********************************************************************
816 * LBGetCurSel
818 LONG LBGetCurSel( HWND hwnd, WORD message, WORD wParam, LONG lParam )
821 LPHEADLIST lphl;
823 lphl = ListBoxGetStorageHeader(hwnd);
824 dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %u !\n",
825 lphl->ItemFocused);
826 return lphl->ItemFocused;
829 /***********************************************************************
830 * LBGetHorizontalExtent
832 LONG LBGetHorizontalExtent( HWND hwnd, WORD message, WORD wParam, LONG lParam )
835 return 0;
838 /***********************************************************************
839 * LBGetItemData
841 LONG LBGetItemData( HWND hwnd, WORD message, WORD wParam, LONG lParam )
844 dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
845 return ListBoxGetText(hwnd, wParam,
846 (LPSTR)PTR_SEG_TO_LIN(lParam), TRUE);
849 /***********************************************************************
850 * LBGetItemHeight
852 LONG LBGetItemHeight( HWND hwnd, WORD message, WORD wParam, LONG lParam )
855 RECT rect;
857 ListBoxGetItemRect(hwnd, wParam, &rect);
858 return (rect.bottom - rect.top);
861 /***********************************************************************
862 * LBGetItemRect
864 LONG LBGetItemRect( HWND hwnd, WORD message, WORD wParam, LONG lParam )
867 return ListBoxGetItemRect (hwnd, wParam, PTR_SEG_TO_LIN(lParam));
870 /***********************************************************************
871 * LBGetSel
873 LONG LBGetSel( HWND hwnd, WORD message, WORD wParam, LONG lParam )
876 return ListBoxGetSel (hwnd, wParam);
879 /***********************************************************************
880 * LBGetSelCount
882 LONG LBGetSelCount( HWND hwnd, WORD message, WORD wParam, LONG lParam )
885 LPHEADLIST lphl;
886 LPLISTSTRUCT lpls;
887 int cnt = 0;
888 WND *wndPtr;
890 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
891 if (lphl == NULL) return LB_ERR;
893 if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return LB_ERR;
895 lpls = lphl->lpFirst;
897 while (lpls != NULL) {
898 if (lpls->dis.itemState > 0) cnt++;
900 lpls = lpls->lpNext;
903 return cnt;
906 /***********************************************************************
907 * LBGetSelItems
909 LONG LBGetSelItems( HWND hwnd, WORD message, WORD wParam, LONG lParam )
912 LPHEADLIST lphl;
913 LPLISTSTRUCT lpls;
914 int cnt, idx;
915 WND *wndPtr;
916 int *lpItems = PTR_SEG_TO_LIN(lParam);
918 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
919 if (lphl == NULL) return LB_ERR;
921 if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return LB_ERR;
923 if (wParam == 0) return 0;
925 lpls = lphl->lpFirst;
926 cnt = 0; idx = 0;
928 while (lpls != NULL) {
929 if (lpls->dis.itemState > 0) lpItems[cnt++] = idx;
931 if (cnt == wParam) break;
932 idx++;
933 lpls = lpls->lpNext;
936 return cnt;
939 /***********************************************************************
940 * LBGetTextLen
942 LONG LBGetTextLen( HWND hwnd, WORD message, WORD wParam, LONG lParam )
945 LPHEADLIST lphl;
946 LPLISTSTRUCT lpls;
947 WND *wndPtr;
948 int cnt = 0;
950 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
951 if (lphl == NULL) return LB_ERR;
953 if (!HasStrings(wndPtr)) return LB_ERR;
955 if (wParam >= lphl->ItemsCount) return LB_ERR;
957 lpls = lphl->lpFirst;
959 while (cnt++ < wParam) lpls = lpls->lpNext;
961 return strlen(lpls->itemText);
964 /***********************************************************************
965 * LBGetDlgCode
967 LONG LBGetDlgCode( HWND hwnd, WORD message, WORD wParam, LONG lParam )
970 return DLGC_WANTALLKEYS;
973 /***********************************************************************
974 * LBGetTopIndex
976 LONG LBGetTopIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam )
979 LPHEADLIST lphl;
981 lphl = ListBoxGetStorageHeader(hwnd);
982 if (lphl == NULL) return LB_ERR;
984 return (lphl->FirstVisible - 1);
988 /***********************************************************************
989 * LBSelectString
991 LONG LBSelectString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
994 WND *wndPtr;
995 WORD wRet;
997 wndPtr = WIN_FindWndPtr(hwnd);
999 wRet = ListBoxFindString(hwnd, wParam,
1000 (LPSTR)PTR_SEG_TO_LIN(lParam));
1002 /* XXX add functionality here */
1004 return 0;
1007 /***********************************************************************
1008 * LBSelItemRange
1010 LONG LBSelItemRange( HWND hwnd, WORD message, WORD wParam, LONG lParam )
1013 LPHEADLIST lphl;
1014 LPLISTSTRUCT lpls;
1015 WND *wndPtr;
1016 WORD cnt;
1017 WORD first = LOWORD(lParam);
1018 WORD last = HIWORD(lParam);
1019 BOOL select = wParam;
1021 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1022 if (lphl == NULL) return LB_ERR;
1024 if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return LB_ERR;
1026 if (first >= lphl->ItemsCount ||
1027 last >= lphl->ItemsCount) return LB_ERR;
1029 lpls = lphl->lpFirst;
1030 cnt = 0;
1032 while (lpls != NULL) {
1033 if (cnt++ >= first)
1034 lpls->dis.itemState = select ? ODS_SELECTED : 0;
1036 if (cnt > last)
1037 break;
1039 lpls = lpls->lpNext;
1042 return 0;
1045 /***********************************************************************
1046 * LBSetCaretIndex
1048 LONG LBSetCaretIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam )
1051 LPHEADLIST lphl;
1052 WND *wndPtr;
1054 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1055 if (lphl == NULL) return LB_ERR;
1057 if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return 0;
1058 if (wParam >= lphl->ItemsCount) return LB_ERR;
1060 lphl->ItemFocused = wParam;
1061 ListBoxScrolltoFocus (hwnd);
1063 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1064 InvalidateRect(hwnd, NULL, TRUE);
1065 UpdateWindow(hwnd);
1066 return 0;
1069 /***********************************************************************
1070 * LBSetColumnWidth
1072 LONG LBSetColumnWidth( HWND hwnd, WORD message, WORD wParam, LONG lParam )
1075 LPHEADLIST lphl;
1077 lphl = ListBoxGetStorageHeader(hwnd);
1078 if (lphl == NULL) return LB_ERR;
1079 lphl->ColumnsWidth = wParam;
1081 return 0;
1084 /***********************************************************************
1085 * LBSetHorizontalExtent
1087 LONG LBSetHorizontalExtent( HWND hwnd, WORD message, WORD wParam, LONG lParam )
1090 return 0;
1093 /***********************************************************************
1094 * LBSetItemData
1096 LONG LBSetItemData( HWND hwnd, WORD message, WORD wParam, LONG lParam )
1099 dprintf_listbox(stddeb, "LB_SETITEMDATA wParam=%x lParam=%lx\n", wParam, lParam);
1100 return ListBoxSetItemData(hwnd, wParam, lParam);
1103 /***********************************************************************
1104 * LBSetTabStops
1106 LONG LBSetTabStops( HWND hwnd, WORD message, WORD wParam, LONG lParam )
1109 LPHEADLIST lphl;
1111 lphl = ListBoxGetStorageHeader(hwnd);
1113 if (lphl->TabStops != NULL) {
1114 lphl->iNumStops = 0;
1115 free (lphl->TabStops);
1118 lphl->TabStops = malloc (wParam * sizeof (short));
1119 if (lphl->TabStops) {
1120 lphl->iNumStops = wParam;
1121 memcpy (lphl->TabStops, PTR_SEG_TO_LIN(lParam), wParam * sizeof (short));
1122 return TRUE;
1125 return FALSE;
1128 /***********************************************************************
1129 * LBSetCurSel
1131 LONG LBSetCurSel( HWND hwnd, WORD message, WORD wParam, LONG lParam )
1134 LPHEADLIST lphl;
1135 WORD wRet;
1137 lphl = ListBoxGetStorageHeader(hwnd);
1138 if (lphl == NULL) return LB_ERR;
1140 dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n",
1141 wParam);
1143 wRet = ListBoxSetCurSel(hwnd, wParam);
1145 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1146 InvalidateRect(hwnd, NULL, TRUE);
1147 UpdateWindow(hwnd);
1149 return wRet;
1152 /***********************************************************************
1153 * LBSetSel
1155 LONG LBSetSel( HWND hwnd, WORD message, WORD wParam, LONG lParam )
1158 WORD wRet;
1160 dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
1162 wRet = ListBoxSetSel(hwnd, LOWORD(lParam), wParam);
1163 InvalidateRect(hwnd, NULL, TRUE);
1164 UpdateWindow(hwnd);
1166 return wRet;
1169 /***********************************************************************
1170 * LBSetTopIndex
1172 LONG LBSetTopIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam )
1175 LPHEADLIST lphl;
1177 dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
1178 wParam);
1179 lphl = ListBoxGetStorageHeader(hwnd);
1180 lphl->FirstVisible = wParam;
1181 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1183 InvalidateRect(hwnd, NULL, TRUE);
1184 UpdateWindow(hwnd);
1186 return 0;
1189 /***********************************************************************
1190 * LBSetItemHeight
1192 LONG LBSetItemHeight( HWND hwnd, WORD message, WORD wParam, LONG lParam)
1195 WORD wRet;
1197 dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
1198 wRet = ListBoxSetItemHeight(hwnd, wParam, lParam);
1199 return wRet;
1203 /***********************************************************************
1204 * ListBoxWndProc
1207 LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
1210 int idx = 0;
1211 int table_size = sizeof (methods) / sizeof (msg_tbl);
1213 while (idx < table_size) {
1214 if (message == methods[idx].message) {
1215 return (*(methods[idx].handler))(hwnd, message, wParam, lParam);
1217 idx++;
1219 return DefWindowProc (hwnd, message, wParam, lParam);
1223 LPLISTSTRUCT ListBoxGetItem(HWND hwnd, UINT uIndex)
1226 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1227 LPLISTSTRUCT lpls;
1228 UINT Count = 0;
1230 if (uIndex >= lphl->ItemsCount) return NULL;
1232 lpls = lphl->lpFirst;
1234 while (Count++ < uIndex) lpls = lpls->lpNext;
1236 return lpls;
1240 LPHEADLIST ListBoxGetWindowAndStorage(HWND hwnd, WND **wndPtr)
1242 WND *Ptr;
1243 LPHEADLIST lphl;
1244 *(wndPtr) = Ptr = WIN_FindWndPtr(hwnd);
1245 lphl = *((LPHEADLIST *)&Ptr->wExtra[1]);
1246 return lphl;
1250 LPHEADLIST ListBoxGetStorageHeader(HWND hwnd)
1252 WND *wndPtr;
1253 LPHEADLIST lphl;
1254 wndPtr = WIN_FindWndPtr(hwnd);
1255 lphl = *((LPHEADLIST *)&wndPtr->wExtra[1]);
1256 return lphl;
1260 void ListBoxDrawItem (HWND hwnd, HDC hdc, LPLISTSTRUCT lpls,
1261 WORD itemAction, WORD itemState)
1264 LPHEADLIST lphl;
1265 WND *wndPtr;
1267 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1269 if (OWNER_DRAWN(wndPtr)) {
1270 DRAWITEMSTRUCT *dis = USER_HEAP_LIN_ADDR(lphl->hDrawItemStruct);
1272 memcpy (dis, &lpls->dis, sizeof(DRAWITEMSTRUCT));
1274 dis->CtlType = ODT_LISTBOX;
1275 dis->hDC = hdc;
1277 if ((!dis->CtlID) && lphl->hWndLogicParent) {
1278 WND *ParentWndPtr;
1280 ParentWndPtr = WIN_FindWndPtr(lphl->hWndLogicParent);
1281 dis->CtlID = ParentWndPtr->wIDmenu;
1284 if (HasStrings(wndPtr)) dis->itemData = LIST_HEAP_SEG_ADDR(lpls,lpls->hData);
1286 dis->itemAction = itemAction;
1287 dis->itemState = itemState;
1289 SendMessage(lphl->hWndLogicParent, WM_DRAWITEM,
1290 0, (LPARAM)USER_HEAP_SEG_ADDR(lphl->hDrawItemStruct));
1291 } else {
1293 if (itemAction == ODA_DRAWENTIRE ||
1294 itemAction == ODA_SELECT) {
1295 int OldBkMode;
1296 DWORD dwOldTextColor;
1298 OldBkMode = SetBkMode(hdc, TRANSPARENT);
1300 if (itemState != 0) {
1301 dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
1302 FillRect(hdc, &lpls->dis.rcItem, GetStockObject(BLACK_BRUSH));
1305 if (wndPtr->dwStyle & LBS_USETABSTOPS)
1306 TabbedTextOut(hdc, lpls->dis.rcItem.left + 5,
1307 lpls->dis.rcItem.top + 2,
1308 (char *)lpls->itemText,
1309 strlen((char *)lpls->itemText), lphl->iNumStops,
1310 lphl->TabStops, 0);
1311 else
1312 TextOut(hdc, lpls->dis.rcItem.left + 5, lpls->dis.rcItem.top + 2,
1313 (char *)lpls->itemText, strlen((char *)lpls->itemText));
1315 if (itemState != 0) {
1316 SetTextColor(hdc, dwOldTextColor);
1319 SetBkMode(hdc, OldBkMode);
1320 } else DrawFocusRect(hdc, &lpls->dis.rcItem);
1323 return;
1326 void RepaintListBox(HWND hwnd)
1329 WND *wndPtr;
1330 LPHEADLIST lphl;
1331 LPLISTSTRUCT lpls;
1332 PAINTSTRUCT ps;
1333 HBRUSH hBrush;
1335 HDC hdc;
1336 RECT rect;
1337 int i, top, height, maxwidth, ipc;
1339 top = 0;
1341 hdc = BeginPaint( hwnd, &ps );
1343 if (!IsWindowVisible(hwnd)) {
1344 EndPaint( hwnd, &ps );
1345 return;
1348 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1349 if (lphl == NULL) goto EndOfPaint;
1350 if (!lphl->bRedrawFlag) goto EndOfPaint;
1352 SelectObject(hdc, lphl->hFont);
1354 hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
1355 MAKELONG(hwnd, CTLCOLOR_LISTBOX));
1357 if (hBrush == (HBRUSH)NULL) hBrush = GetStockObject(WHITE_BRUSH);
1359 GetClientRect(hwnd, &rect);
1360 FillRect(hdc, &rect, hBrush);
1362 maxwidth = rect.right;
1363 rect.right = lphl->ColumnsWidth;
1365 if (lphl->ItemsCount == 0) goto EndOfPaint;
1367 lpls = lphl->lpFirst;
1369 lphl->ItemsVisible = 0;
1370 lphl->ItemsPerColumn = ipc = 0;
1372 for(i = 0; i < lphl->ItemsCount; i++) {
1373 if (lpls == NULL) goto EndOfPaint;
1375 if (i >= lphl->FirstVisible - 1) {
1376 height = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
1378 if (top > rect.bottom) {
1379 if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
1380 lphl->ItemsPerColumn = max(lphl->ItemsPerColumn, ipc);
1381 ipc = 0;
1382 top = 0;
1383 rect.left += lphl->ColumnsWidth;
1384 rect.right += lphl->ColumnsWidth;
1385 if (rect.left > maxwidth) break;
1387 else
1388 break;
1391 lpls->dis.rcItem.top = top;
1392 lpls->dis.rcItem.bottom = top + height;
1393 lpls->dis.rcItem.left = rect.left;
1394 lpls->dis.rcItem.right = rect.right;
1396 if (OWNER_DRAWN(wndPtr)) {
1397 ListBoxDrawItem (hwnd, hdc, lpls, ODA_DRAWENTIRE, 0);
1398 if (lpls->dis.itemState)
1399 ListBoxDrawItem (hwnd, hdc, lpls, ODA_SELECT, ODS_SELECTED);
1401 else
1402 ListBoxDrawItem (hwnd, hdc, lpls, ODA_DRAWENTIRE, lpls->dis.itemState);
1404 if ((lphl->ItemFocused == i) && GetFocus() == hwnd)
1405 ListBoxDrawItem (hwnd, hdc, lpls, ODA_FOCUS, ODS_FOCUS);
1407 top += height;
1408 lphl->ItemsVisible++;
1409 ipc++;
1412 lpls = lpls->lpNext;
1414 EndOfPaint:
1415 EndPaint( hwnd, &ps );
1418 int ListBoxFindMouse(HWND hwnd, int X, int Y)
1421 WND *wndPtr;
1422 LPHEADLIST lphl;
1423 LPLISTSTRUCT lpls;
1424 RECT rect;
1425 int i, h, h2, w, w2;
1427 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1429 if (lphl == NULL) return LB_ERR;
1430 if (lphl->ItemsCount == 0) return LB_ERR;
1432 lpls = lphl->lpFirst;
1433 if (lpls == NULL) return LB_ERR;
1434 GetClientRect(hwnd, &rect);
1435 h = w2 = 0;
1436 w = lphl->ColumnsWidth;
1438 for(i = 1; i <= lphl->ItemsCount; i++) {
1439 if (i >= lphl->FirstVisible) {
1440 h2 = h;
1441 h += lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
1442 if ((Y > h2) && (Y < h) &&
1443 (X > w2) && (X < w)) return(i - 1);
1444 if (h > rect.bottom) {
1445 if ((wndPtr->dwStyle & LBS_MULTICOLUMN) != LBS_MULTICOLUMN) return LB_ERR;
1446 h = 0;
1447 w2 = w;
1448 w += lphl->ColumnsWidth;
1449 if (w2 > rect.right) return LB_ERR;
1452 if (lpls->lpNext == NULL) return LB_ERR;
1453 lpls = (LPLISTSTRUCT)lpls->lpNext;
1455 return(LB_ERR);
1458 void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls)
1461 MEASUREITEMSTRUCT *lpmeasure;
1463 HANDLE hTemp = USER_HEAP_ALLOC( sizeof(MEASUREITEMSTRUCT) );
1465 lpmeasure = (MEASUREITEMSTRUCT *) USER_HEAP_LIN_ADDR(hTemp);
1467 if (lpmeasure == NULL) {
1468 fprintf(stderr,"ListBoxAskMeasure() // Bad allocation of Measure struct !\n");
1469 return;
1472 lpmeasure->CtlType = ODT_LISTBOX;
1473 lpmeasure->CtlID = wndPtr->wIDmenu;
1474 lpmeasure->itemID = lpls->dis.itemID;
1475 lpmeasure->itemWidth = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
1476 lpmeasure->itemHeight = 0;
1478 if (HasStrings(wndPtr))
1479 lpmeasure->itemData = LIST_HEAP_SEG_ADDR(lpls,lpls->hData);
1480 else
1481 lpmeasure->itemData = lpls->dis.itemData;
1483 SendMessage(lphl->hWndLogicParent, WM_MEASUREITEM,
1484 0, USER_HEAP_SEG_ADDR(hTemp));
1486 if (wndPtr->dwStyle & LBS_OWNERDRAWFIXED) {
1487 lphl->StdItemHeight = lpmeasure->itemHeight;
1490 lpls->dis.rcItem.right = lpls->dis.rcItem.left + lpmeasure->itemWidth;
1491 lpls->dis.rcItem.bottom = lpls->dis.rcItem.top + lpmeasure->itemHeight;
1492 USER_HEAP_FREE(hTemp);
1496 int ListBoxAddString(HWND hwnd, LPSTR newstr)
1498 LPHEADLIST lphl;
1499 UINT pos = (UINT) -1;
1500 WND *wndPtr;
1502 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1503 if (lphl == NULL) return LB_ERR;
1505 if (HasStrings(wndPtr) && (wndPtr->dwStyle & LBS_SORT)) {
1506 LPLISTSTRUCT lpls = lphl->lpFirst;
1507 for (pos = 0; lpls; lpls = lpls->lpNext, pos++)
1508 if (strcmp(lpls->itemText, newstr) >= 0)
1509 break;
1511 return ListBoxInsertString(hwnd, pos, newstr);
1514 int ListBoxInsertString(HWND hwnd, UINT uIndex, LPSTR newstr)
1517 WND *wndPtr;
1518 LPHEADLIST lphl;
1519 LPLISTSTRUCT *lppls, lplsnew;
1520 HANDLE hItem;
1521 HANDLE hStr;
1522 LPSTR str;
1523 UINT Count;
1525 dprintf_listbox(stddeb,"ListBoxInsertString(%04X, %d, %p);\n",
1526 hwnd, uIndex, newstr);
1528 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1529 if (lphl == NULL) return LB_ERR;
1531 if (uIndex == (UINT)-1)
1532 uIndex = lphl->ItemsCount;
1534 if (uIndex > lphl->ItemsCount) return LB_ERR;
1536 lppls = (LPLISTSTRUCT *) &lphl->lpFirst;
1538 for(Count = 0; Count < uIndex; Count++) {
1539 if (*lppls == NULL) return LB_ERR;
1540 lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
1543 hItem = LIST_HEAP_ALLOC(lphl, GMEM_MOVEABLE, sizeof(LISTSTRUCT));
1544 lplsnew = (LPLISTSTRUCT) LIST_HEAP_ADDR(lphl, hItem);
1546 if (lplsnew == NULL) {
1547 printf("ListBoxInsertString() // Bad allocation of new item !\n");
1548 return LB_ERRSPACE;
1551 ListBoxDefaultItem(hwnd, wndPtr, lphl, lplsnew);
1552 lplsnew->hMem = hItem;
1553 lplsnew->lpNext = *lppls;
1554 *lppls = lplsnew;
1555 lphl->ItemsCount++;
1556 hStr = 0;
1558 if (HasStrings(wndPtr)) {
1559 hStr = LIST_HEAP_ALLOC(lphl, GMEM_MOVEABLE, strlen(newstr) + 1);
1560 str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
1561 if (str == NULL) return LB_ERRSPACE;
1562 strcpy(str, newstr);
1563 newstr = str;
1564 lplsnew->itemText = str;
1565 dprintf_listbox(stddeb,"ListBoxInsertString // LBS_HASSTRINGS after strcpy '%s'\n", str);
1566 } else {
1567 lplsnew->itemText = NULL;
1568 lplsnew->dis.itemData = (DWORD)newstr;
1571 lplsnew->dis.itemID = lphl->ItemsCount;
1572 lplsnew->hData = hStr;
1574 if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) && (lphl->ItemsCount == 1)) {
1575 ListBoxAskMeasure(wndPtr, lphl, lplsnew);
1578 if (wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE)
1579 ListBoxAskMeasure(wndPtr, lphl, lplsnew);
1581 SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl),
1582 (lphl->FirstVisible != 1 && lphl->bRedrawFlag));
1584 if (lphl->ItemsPerColumn != 0)
1585 SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
1586 lphl->ItemsPerColumn + 1,
1587 (lphl->FirstVisible != 1 && lphl->bRedrawFlag));
1589 if ((lphl->FirstVisible <= uIndex) &&
1590 ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
1591 InvalidateRect(hwnd, NULL, TRUE);
1592 UpdateWindow(hwnd);
1595 dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
1596 return uIndex;
1600 int ListBoxGetText(HWND hwnd, UINT uIndex, LPSTR OutStr, BOOL bItemData)
1603 WND *wndPtr;
1604 LPLISTSTRUCT lpls;
1606 wndPtr = WIN_FindWndPtr(hwnd);
1608 if (!OutStr && !bItemData) {
1609 dprintf_listbox(stddeb, "ListBoxGetText // OutStr==NULL\n");
1610 return 0;
1613 if (!bItemData) *OutStr=0;
1615 if ((lpls = ListBoxGetItem (hwnd, uIndex)) == NULL)
1616 return LB_ERR;
1618 if (bItemData)
1619 return lpls->dis.itemData;
1621 if (!HasStrings(wndPtr)) {
1622 *((long *)OutStr) = lpls->dis.itemData;
1623 return 4;
1626 strcpy(OutStr, lpls->itemText);
1627 return strlen(OutStr);
1630 int ListBoxSetItemData(HWND hwnd, UINT uIndex, DWORD ItemData)
1633 LPLISTSTRUCT lpls;
1635 if ((lpls = ListBoxGetItem(hwnd, uIndex)) == NULL)
1636 return LB_ERR;
1638 lpls->dis.itemData = ItemData;
1639 return 1;
1643 int ListBoxDeleteString(HWND hwnd, UINT uIndex)
1646 WND *wndPtr;
1647 LPHEADLIST lphl;
1648 LPLISTSTRUCT lpls, lpls2;
1649 UINT Count;
1651 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1652 if (lphl == NULL) return LB_ERR;
1654 if (uIndex >= lphl->ItemsCount) return LB_ERR;
1656 lpls = lphl->lpFirst;
1657 if (lpls == NULL) return LB_ERR;
1659 if( uIndex == 0 )
1660 lphl->lpFirst = lpls->lpNext;
1661 else {
1662 for(Count = 0; Count < uIndex; Count++) {
1663 if (lpls->lpNext == NULL) return LB_ERR;
1665 lpls2 = lpls;
1666 lpls = (LPLISTSTRUCT)lpls->lpNext;
1668 lpls2->lpNext = (LPLISTSTRUCT)lpls->lpNext;
1671 lphl->ItemsCount--;
1673 if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
1674 if (lpls->hMem != 0) LIST_HEAP_FREE(lphl, lpls->hMem);
1676 SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
1677 if (lphl->ItemsPerColumn != 0)
1678 SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
1679 lphl->ItemsPerColumn + 1, TRUE);
1681 if ((lphl->FirstVisible <= uIndex) &&
1682 ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
1683 InvalidateRect(hwnd, NULL, TRUE);
1684 UpdateWindow(hwnd);
1687 return lphl->ItemsCount;
1691 int ListBoxFindString(HWND hwnd, UINT nFirst, LPSTR MatchStr)
1693 WND *wndPtr;
1694 LPHEADLIST lphl;
1695 LPLISTSTRUCT lpls;
1696 UINT Count;
1697 UINT First = nFirst + 1;
1699 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1701 if (lphl == NULL) return LB_ERR;
1703 if (First > lphl->ItemsCount) return LB_ERR;
1705 lpls = ListBoxGetItem(hwnd, First);
1706 Count = 0;
1707 while(lpls != NULL) {
1708 if (HasStrings(wndPtr)) {
1709 if (strstr(lpls->itemText, MatchStr) == lpls->itemText) return Count;
1710 } else if (wndPtr->dwStyle & LBS_SORT) {
1711 /* XXX Do a compare item */
1713 else
1714 if (lpls->dis.itemData == (DWORD)MatchStr) return Count;
1716 lpls = lpls->lpNext;
1717 Count++;
1720 /* Start over at top */
1721 Count = 0;
1722 lpls = lphl->lpFirst;
1724 while (Count < First) {
1725 if (HasStrings(wndPtr)) {
1726 if (strstr(lpls->itemText, MatchStr) == lpls->itemText) return Count;
1727 } else if (wndPtr->dwStyle & LBS_SORT) {
1728 /* XXX Do a compare item */
1730 else
1731 if (lpls->dis.itemData == (DWORD)MatchStr) return Count;
1733 lpls = lpls->lpNext;
1734 Count++;
1737 return LB_ERR;
1741 int ListBoxResetContent(HWND hwnd)
1743 WND *wndPtr;
1744 LPHEADLIST lphl;
1745 LPLISTSTRUCT lpls;
1746 UINT i;
1748 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1749 if (lphl == NULL) return LB_ERR;
1751 if (lphl->ItemsCount == 0) return 0;
1753 lpls = lphl->lpFirst;
1755 dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n",
1756 lphl->ItemsCount);
1758 for(i = 0; i < lphl->ItemsCount; i++) {
1759 LPLISTSTRUCT lpls2;
1761 if (lpls == NULL) return LB_ERR;
1763 lpls2 = lpls->lpNext;
1765 if (i != 0) {
1766 dprintf_listbox(stddeb,"ResetContent #%u\n", i);
1767 if (lpls->hData != 0 && lpls->hData != lpls->hMem)
1768 LIST_HEAP_FREE(lphl, lpls->hData);
1770 if (lpls->hMem != 0) LIST_HEAP_FREE(lphl, lpls->hMem);
1773 lpls = lpls2;
1776 lphl->lpFirst = NULL;
1777 lphl->FirstVisible = 1;
1778 lphl->ItemsCount = 0;
1779 lphl->ItemFocused = -1;
1780 lphl->PrevFocused = -1;
1782 SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
1784 if (lphl->ItemsPerColumn != 0)
1785 SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
1786 lphl->ItemsPerColumn + 1, TRUE);
1788 InvalidateRect(hwnd, NULL, TRUE);
1789 UpdateWindow(hwnd);
1791 return TRUE;
1795 int ListBoxSetCurSel(HWND hwnd, WORD wIndex)
1798 WND *wndPtr;
1799 LPHEADLIST lphl;
1800 LPLISTSTRUCT lpls;
1802 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1803 if (lphl == NULL) return LB_ERR;
1805 if (wndPtr->dwStyle & LBS_MULTIPLESEL) return 0;
1807 if (lphl->ItemFocused != -1) {
1808 lpls = ListBoxGetItem(hwnd, lphl->ItemFocused);
1809 if (lpls == 0) return LB_ERR;
1810 lpls->dis.itemState = 0;
1813 if (wIndex != (UINT)-1) {
1814 lphl->ItemFocused = wIndex;
1815 lpls = ListBoxGetItem(hwnd, wIndex);
1816 if (lpls == 0) return LB_ERR;
1817 lpls->dis.itemState = ODS_SELECTED | ODS_FOCUS;
1819 return 0;
1822 return LB_ERR;
1825 int ListBoxSetSel(HWND hwnd, WORD wIndex, WORD state)
1828 LPHEADLIST lphl;
1829 LPLISTSTRUCT lpls;
1830 WND *wndPtr;
1832 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1833 if (lphl == NULL) return LB_ERR;
1835 if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return 0;
1837 if (wIndex == (UINT)-1) {
1838 lpls = lphl->lpFirst;
1840 while (lpls != NULL) {
1841 lpls->dis.itemState = state;
1842 lpls = lpls->lpNext;
1845 return 0;
1848 if (wIndex >= lphl->ItemsCount) return LB_ERR;
1850 lpls = ListBoxGetItem(hwnd, wIndex);
1851 lpls->dis.itemState = state;
1853 return 0;
1857 int ListBoxGetSel(HWND hwnd, WORD wIndex)
1859 LPLISTSTRUCT lpls;
1861 if ((lpls = ListBoxGetItem(hwnd, wIndex)) == NULL) return LB_ERR;
1863 return lpls->dis.itemState;
1867 int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec)
1869 struct dosdirent *dp, *dp_old;
1870 int x, wRet = LB_OKAY;
1871 BOOL OldFlag;
1872 char temp[256];
1873 LPHEADLIST lphl;
1874 int drive;
1875 LPSTR tstr;
1877 dprintf_listbox(stddeb,"ListBoxDirectory: %s, %4x\n",filespec,attrib);
1879 if( strchr( filespec, '\\' ) || strchr( filespec, ':' ) ) {
1880 drive = DOS_GetDefaultDrive();
1881 if( filespec[1] == ':' ) {
1882 drive = toupper(filespec[0]) - 'A';
1883 filespec += 2;
1885 strcpy(temp,filespec);
1886 tstr = strrchr(temp, '\\');
1887 if( tstr == NULL )
1888 DOS_SetDefaultDrive( drive );
1889 else {
1890 *tstr = 0;
1891 filespec = tstr + 1;
1892 DOS_ChangeDir( drive, temp );
1893 if (!DOS_ChangeDir( drive, temp )) return 0;
1895 dprintf_listbox(stddeb,"Changing directory to %c:%s, filemask is %s\n",
1896 drive+'A', temp, filespec );
1898 lphl = ListBoxGetStorageHeader(hwnd);
1899 if (lphl == NULL) return LB_ERR;
1900 if ((dp = (struct dosdirent *)DOS_opendir(filespec)) ==NULL) return 0;
1901 dp_old = dp;
1902 OldFlag = lphl->bRedrawFlag;
1903 lphl->bRedrawFlag = FALSE;
1904 while ((dp = (struct dosdirent *)DOS_readdir(dp))) {
1905 if (!dp->inuse) break;
1906 dprintf_listbox( stddeb, "ListBoxDirectory %p '%s' !\n", dp->filename,
1907 dp->filename);
1908 if (dp->attribute & FA_DIREC) {
1909 if (attrib & DDL_DIRECTORY && strcmp(dp->filename, ".") != 0) {
1910 sprintf(temp, "[%s]", dp->filename);
1911 if ( (wRet = ListBoxAddString(hwnd, temp)) == LB_ERR) break;
1914 else {
1915 if (attrib & DDL_EXCLUSIVE) {
1916 if (attrib & (DDL_READWRITE | DDL_READONLY | DDL_HIDDEN |
1917 DDL_SYSTEM) )
1918 if ( (wRet = ListBoxAddString(hwnd, dp->filename))
1919 == LB_ERR) break;
1921 else {
1922 if ( (wRet = ListBoxAddString(hwnd, dp->filename))
1923 == LB_ERR) break;
1927 DOS_closedir(dp_old);
1929 if (attrib & DDL_DRIVES) {
1930 for (x=0;x!=MAX_DOS_DRIVES;x++) {
1931 if (DOS_ValidDrive(x)) {
1932 sprintf(temp, "[-%c-]", 'a'+x);
1933 if((wRet = ListBoxInsertString(hwnd, (UINT)-1, temp)) == LB_ERR) break;
1937 lphl->bRedrawFlag = OldFlag;
1938 if (OldFlag) {
1939 InvalidateRect(hwnd, NULL, TRUE);
1940 UpdateWindow(hwnd);
1942 dprintf_listbox(stddeb,"End of ListBoxDirectory !\n");
1943 return 1; /* FIXME: Should be 0 if "filespec" is invalid */
1947 int ListBoxGetItemRect(HWND hwnd, WORD wIndex, LPRECT lprect)
1950 LPLISTSTRUCT lpls;
1952 if ((lpls = ListBoxGetItem(hwnd, wIndex)) == NULL) return LB_ERR;
1954 *(lprect) = lpls->dis.rcItem;
1956 return 0;
1960 int ListBoxSetItemHeight(HWND hwnd, WORD wIndex, long height)
1963 LPHEADLIST lphl;
1964 WND *wndPtr;
1965 LPLISTSTRUCT lpls;
1967 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1968 if (lphl == NULL) return LB_ERR;
1970 if (!(wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE)) {
1971 lphl->StdItemHeight = (short)height;
1972 InvalidateRect(hwnd, NULL, TRUE);
1973 UpdateWindow(hwnd);
1975 return 0;
1978 if ((lpls = ListBoxGetItem(hwnd, wIndex)) == NULL) return LB_ERR;
1980 lpls->dis.rcItem.bottom = lpls->dis.rcItem.top + (short)height;
1981 InvalidateRect(hwnd, NULL, TRUE);
1982 UpdateWindow(hwnd);
1984 return 0;
1987 int ListBoxDefaultItem(HWND hwnd, WND *wndPtr,
1988 LPHEADLIST lphl, LPLISTSTRUCT lpls)
1991 RECT rect;
1993 if (wndPtr == NULL || lphl == NULL || lpls == NULL) {
1994 fprintf(stderr,"ListBoxDefaultItem() // Bad Pointers !\n");
1995 return FALSE;
1998 GetClientRect(hwnd, &rect);
1999 SetRect(&lpls->dis.rcItem, 0, 0, rect.right, lphl->StdItemHeight);
2001 lpls->dis.CtlType = lphl->DrawCtlType;
2002 lpls->dis.CtlID = wndPtr->wIDmenu;
2003 lpls->dis.itemID = 0;
2004 lpls->dis.itemAction = 0;
2005 lpls->dis.itemState = 0;
2006 lpls->dis.hwndItem = hwnd;
2007 lpls->dis.hDC = 0;
2008 lpls->dis.itemData = 0;
2010 return TRUE;
2015 int ListBoxFindNextMatch(HWND hwnd, WORD wChar)
2018 WND *wndPtr;
2019 LPHEADLIST lphl;
2020 LPLISTSTRUCT lpls;
2021 UINT Count;
2023 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
2024 if (lphl == NULL) return LB_ERR;
2025 lpls = lphl->lpFirst;
2026 if (lpls == NULL) return LB_ERR;
2027 if (wChar < ' ') return LB_ERR;
2029 if (!HasStrings(wndPtr)) return LB_ERR;
2031 Count = 0;
2032 while(lpls != NULL) {
2033 if (Count > lphl->ItemFocused) {
2034 if (*(lpls->itemText) == (char)wChar) {
2035 if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
2036 lphl->ItemFocused = Count;
2037 ListBoxScrolltoFocus(hwnd);
2039 else {
2040 ListBoxSetCurSel(hwnd, Count);
2042 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
2043 InvalidateRect(hwnd, NULL, TRUE);
2044 UpdateWindow(hwnd);
2045 return Count;
2048 lpls = (LPLISTSTRUCT)lpls->lpNext;
2049 Count++;
2051 Count = 0;
2052 lpls = lphl->lpFirst;
2053 while(lpls != NULL) {
2054 if (*(lpls->itemText) == (char)wChar) {
2055 if (Count == lphl->ItemFocused) return LB_ERR;
2057 if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
2058 lphl->ItemFocused = Count;
2059 ListBoxScrolltoFocus(hwnd);
2061 else {
2062 ListBoxSetCurSel(hwnd, Count);
2064 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
2065 InvalidateRect(hwnd, NULL, TRUE);
2066 UpdateWindow(hwnd);
2067 return Count;
2069 lpls = lpls->lpNext;
2070 Count++;
2072 return LB_ERR;
2076 /************************************************************************
2077 * DlgDirSelect [USER.99]
2079 BOOL DlgDirSelect(HWND hDlg, LPSTR lpStr, int nIDLBox)
2081 HWND hwnd;
2082 LPHEADLIST lphl;
2083 char s[130];
2085 dprintf_listbox( stddeb, "DlgDirSelect(%04X, '%s', %d) \n", hDlg, lpStr,
2086 nIDLBox );
2088 hwnd = GetDlgItem(hDlg, nIDLBox);
2089 lphl = ListBoxGetStorageHeader(hwnd);
2090 if( lphl->ItemFocused == -1 ) {
2091 dprintf_listbox( stddeb, "Nothing selected!\n" );
2092 return FALSE;
2094 ListBoxGetText(hwnd, lphl->ItemFocused, (LPSTR)s, FALSE);
2095 dprintf_listbox( stddeb, "Selection is %s\n", s );
2096 if( s[0] == '[' ) {
2097 if( s[1] == '-' ) {
2098 strncpy( lpStr, s+2, strlen(s)-4 ); /* device name */
2099 lpStr[ strlen(s)-4 ] = 0;
2100 strcat( lpStr, ":" );
2102 else {
2103 strncpy( lpStr, s+1, strlen(s)-2 ); /* directory name */
2104 lpStr[ strlen(s)-2 ] = 0;
2105 strcat( lpStr, "\\" );
2107 dprintf_listbox( stddeb, "Returning %s\n", lpStr );
2108 return TRUE;
2110 else {
2111 strcpy( lpStr, s ); /* file name */
2112 dprintf_listbox( stddeb, "Returning %s\n", lpStr );
2113 return FALSE;
2118 /************************************************************************
2119 * DlgDirList [USER.100]
2121 int DlgDirList(HWND hDlg, LPSTR lpPathSpec,
2122 int nIDLBox, int nIDStat, WORD wType)
2124 HWND hWnd;
2125 int ret;
2126 dprintf_listbox(stddeb,"DlgDirList(%04X, '%s', %d, %d, %04X) \n",
2127 hDlg, lpPathSpec, nIDLBox, nIDStat, wType);
2128 if (nIDLBox)
2129 hWnd = GetDlgItem(hDlg, nIDLBox);
2130 else
2131 hWnd = 0;
2132 if (hWnd)
2133 ListBoxResetContent(hWnd);
2134 if (hWnd)
2135 ret=ListBoxDirectory(hWnd, wType, lpPathSpec);
2136 else
2137 ret=0;
2138 if (nIDStat)
2140 int drive;
2141 HANDLE hTemp;
2142 char *temp;
2143 drive = DOS_GetDefaultDrive();
2144 hTemp = USER_HEAP_ALLOC( 256 );
2145 temp = (char *) USER_HEAP_LIN_ADDR( hTemp );
2146 strcpy( temp+3, DOS_GetCurrentDir(drive) );
2147 if( temp[3] == '\\' ) {
2148 temp[1] = 'A'+drive;
2149 temp[2] = ':';
2150 SendDlgItemMessage( hDlg, nIDStat, WM_SETTEXT, 0,
2151 USER_HEAP_SEG_ADDR(hTemp) + 1 );
2153 else {
2154 temp[0] = 'A'+drive;
2155 temp[1] = ':';
2156 temp[2] = '\\';
2157 SendDlgItemMessage( hDlg, nIDStat, WM_SETTEXT, 0,
2158 USER_HEAP_SEG_ADDR(hTemp) );
2160 USER_HEAP_FREE( hTemp );
2162 return ret;
2166 /* Returns: 0 if nothing needs to be changed */
2167 /* 1 if FirstVisible changed */
2169 int ListBoxScrolltoFocus(HWND hwnd)
2172 WND *wndPtr;
2173 LPHEADLIST lphl;
2174 short end;
2176 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
2178 if (lphl->ItemsCount == 0) return 0;
2179 if (lphl->ItemFocused == -1) return 0;
2181 end = lphl->FirstVisible + lphl->ItemsVisible - 2;
2183 if (lphl->ItemFocused < lphl->FirstVisible - 1) {
2184 lphl->FirstVisible = lphl->ItemFocused + 1;
2186 else if (lphl->ItemFocused > end) {
2187 UINT maxFirstVisible = ListMaxFirstVisible(lphl);
2189 lphl->FirstVisible = lphl->ItemFocused;
2191 if (lphl->FirstVisible > maxFirstVisible) {
2192 lphl->FirstVisible = maxFirstVisible;
2194 } else return 0;
2196 return 1;
2199 /* Send notification "code" as part of a WM_COMMAND-message if hwnd
2200 has the LBS_NOTIFY style */
2201 void ListBoxSendNotification(HWND hwnd, WORD code)
2203 WND *wndPtr;
2204 LPHEADLIST lphl;
2205 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
2207 if (wndPtr && (wndPtr->dwStyle & LBS_NOTIFY))
2208 SendMessage(lphl->hWndLogicParent, WM_COMMAND,
2209 wndPtr->wIDmenu, MAKELONG(hwnd, code));