Release 941122
[wine/multimedia.git] / controls / listbox.c
blob185142b20768e3f4c69879c91b40252199837477
1 /*
2 * Interface code to listbox widgets
4 * Copyright Martin Ayotte, 1993
6 */
9 static char Copyright[] = "Copyright Martin Ayotte, 1993";
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include "windows.h"
16 #include "user.h"
17 #include "heap.h"
18 #include "win.h"
19 #include "msdos.h"
20 #include "wine.h"
21 #include "listbox.h"
22 #include "prototypes.h"
23 #include "stddebug.h"
24 /* #define DEBUG_LISTBOX */
25 /* #undef DEBUG_LISTBOX */
26 #include "debug.h"
28 #define GMEM_ZEROINIT 0x0040
31 LPHEADLIST ListBoxGetWindowAndStorage(HWND hwnd, WND **wndPtr);
32 LPHEADLIST ListBoxGetStorageHeader(HWND hwnd);
33 void StdDrawListBox(HWND hwnd);
34 void OwnerDrawListBox(HWND hwnd);
35 int ListBoxFindMouse(HWND hwnd, int X, int Y);
36 int CreateListBoxStruct(HWND hwnd);
37 void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls);
38 int ListBoxAddString(HWND hwnd, LPSTR newstr);
39 int ListBoxInsertString(HWND hwnd, UINT uIndex, LPSTR newstr);
40 int ListBoxGetText(HWND hwnd, UINT uIndex, LPSTR OutStr, BOOL bItemData);
41 int ListBoxSetItemData(HWND hwnd, UINT uIndex, DWORD ItemData);
42 int ListBoxDeleteString(HWND hwnd, UINT uIndex);
43 int ListBoxFindString(HWND hwnd, UINT nFirst, LPSTR MatchStr);
44 int ListBoxResetContent(HWND hwnd);
45 int ListBoxSetCurSel(HWND hwnd, WORD wIndex);
46 int ListBoxSetSel(HWND hwnd, WORD wIndex, WORD state);
47 int ListBoxGetSel(HWND hwnd, WORD wIndex);
48 int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec);
49 int ListBoxGetItemRect(HWND hwnd, WORD wIndex, LPRECT rect);
50 int ListBoxSetItemHeight(HWND hwnd, WORD wIndex, long height);
51 int ListBoxDefaultItem(HWND hwnd, WND *wndPtr,
52 LPHEADLIST lphl, LPLISTSTRUCT lpls);
53 int ListBoxFindNextMatch(HWND hwnd, WORD wChar);
54 int ListMaxFirstVisible(LPHEADLIST lphl);
56 #define HasStrings(wndPtr) ( \
57 ( ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) != LBS_OWNERDRAWFIXED) && \
58 ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) != LBS_OWNERDRAWVARIABLE) ) || \
59 ((wndPtr->dwStyle & LBS_HASSTRINGS) == LBS_HASSTRINGS) )
61 #define LIST_HEAP_ALLOC(lphl,f,size) ((int)HEAP_Alloc(&lphl->Heap,f,size) & 0xffff)
62 #define LIST_HEAP_FREE(lphl,handle) (HEAP_Free(&lphl->Heap,LIST_HEAP_ADDR(lphl,handle)))
63 #define LIST_HEAP_ADDR(lphl,handle) \
64 ((void *)((handle) ? ((handle) | ((int)lphl->Heap & 0xffff0000)) : 0))
65 #define LIST_HEAP_SIZE 0x10000
67 /***********************************************************************
68 * ListBoxWndProc
70 LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
72 WND *wndPtr;
73 LPHEADLIST lphl;
74 HWND hWndCtl;
75 WORD wRet;
76 LONG lRet;
77 RECT rect;
78 int y;
79 CREATESTRUCT *createStruct;
80 static RECT rectsel;
81 switch(message) {
82 case WM_CREATE:
83 CreateListBoxStruct(hwnd);
84 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
85 dprintf_listbox(stddeb,"ListBox WM_CREATE %p !\n", lphl);
86 if (lphl == NULL) return 0;
87 createStruct = (CREATESTRUCT *)lParam;
88 if (HIWORD(createStruct->lpCreateParams) != 0)
89 lphl->hWndLogicParent = (HWND)HIWORD(createStruct->lpCreateParams);
90 else
91 lphl->hWndLogicParent = GetParent(hwnd);
92 lphl->hFont = GetStockObject(SYSTEM_FONT);
93 lphl->ColumnsWidth = wndPtr->rectClient.right - wndPtr->rectClient.left;
94 if (wndPtr->dwStyle & WS_VSCROLL) {
95 SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
96 ShowScrollBar(hwnd, SB_VERT, FALSE);
98 if (wndPtr->dwStyle & WS_HSCROLL) {
99 SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
100 ShowScrollBar(hwnd, SB_HORZ, FALSE);
102 if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) {
104 return 0;
105 case WM_DESTROY:
106 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
107 if (lphl == NULL) return 0;
108 ListBoxResetContent(hwnd);
109 /* XXX need to free lphl->Heap */
110 free(lphl);
111 *((LPHEADLIST *)&wndPtr->wExtra[1]) = 0;
112 dprintf_listbox(stddeb,"ListBox WM_DESTROY %p !\n", lphl);
113 return 0;
115 case WM_VSCROLL:
116 dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
117 wParam, lParam);
118 lphl = ListBoxGetStorageHeader(hwnd);
119 if (lphl == NULL) return 0;
120 y = lphl->FirstVisible;
121 switch(wParam) {
122 case SB_LINEUP:
123 if (lphl->FirstVisible > 1)
124 lphl->FirstVisible--;
125 break;
126 case SB_LINEDOWN:
127 if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
128 lphl->FirstVisible++;
129 break;
130 case SB_PAGEUP:
131 if (lphl->FirstVisible > 1)
132 lphl->FirstVisible -= lphl->ItemsVisible;
133 break;
134 case SB_PAGEDOWN:
135 if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
136 lphl->FirstVisible += lphl->ItemsVisible;
137 break;
138 case SB_THUMBTRACK:
139 lphl->FirstVisible = LOWORD(lParam);
140 break;
142 if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
143 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
144 lphl->FirstVisible = ListMaxFirstVisible(lphl);
145 if (y != lphl->FirstVisible) {
146 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
147 InvalidateRect(hwnd, NULL, TRUE);
148 UpdateWindow(hwnd);
150 return 0;
152 case WM_HSCROLL:
153 dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
154 wParam, lParam);
155 lphl = ListBoxGetStorageHeader(hwnd);
156 if (lphl == NULL) return 0;
157 y = lphl->FirstVisible;
158 switch(wParam) {
159 case SB_LINEUP:
160 if (lphl->FirstVisible > 1)
161 lphl->FirstVisible -= lphl->ItemsPerColumn;
162 break;
163 case SB_LINEDOWN:
164 if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
165 lphl->FirstVisible += lphl->ItemsPerColumn;
166 break;
167 case SB_PAGEUP:
168 if (lphl->FirstVisible > 1 && lphl->ItemsPerColumn != 0)
169 lphl->FirstVisible -= lphl->ItemsVisible /
170 lphl->ItemsPerColumn * lphl->ItemsPerColumn;
171 break;
172 case SB_PAGEDOWN:
173 if (lphl->FirstVisible < ListMaxFirstVisible(lphl) &&
174 lphl->ItemsPerColumn != 0)
175 lphl->FirstVisible += lphl->ItemsVisible /
176 lphl->ItemsPerColumn * lphl->ItemsPerColumn;
177 break;
178 case SB_THUMBTRACK:
179 lphl->FirstVisible = lphl->ItemsPerColumn *
180 (LOWORD(lParam) - 1) + 1;
181 break;
183 if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
184 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
185 lphl->FirstVisible = ListMaxFirstVisible(lphl);
186 if (lphl->ItemsPerColumn != 0) {
187 lphl->FirstVisible = lphl->FirstVisible /
188 lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
189 if (y != lphl->FirstVisible) {
190 SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible /
191 lphl->ItemsPerColumn + 1, TRUE);
192 InvalidateRect(hwnd, NULL, TRUE);
193 UpdateWindow(hwnd);
196 return 0;
198 case WM_LBUTTONDOWN:
199 SetFocus(hwnd);
200 SetCapture(hwnd);
201 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
202 if (lphl == NULL) return 0;
203 lphl->PrevFocused = lphl->ItemFocused;
204 y = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
205 if (y==-1)
206 return 0;
207 if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
208 lphl->ItemFocused = y;
209 wRet = ListBoxGetSel(hwnd, y);
210 ListBoxSetSel(hwnd, y, !wRet);
212 else {
213 ListBoxSetCurSel(hwnd, y);
214 if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
215 SendMessage(lphl->hWndLogicParent, WM_COMMAND,
216 wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
218 ListBoxGetItemRect(hwnd, y, &rectsel);
219 InvalidateRect(hwnd, NULL, TRUE);
220 UpdateWindow(hwnd);
221 return 0;
222 case WM_LBUTTONUP:
223 ReleaseCapture();
224 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
225 if (lphl == NULL) return 0;
226 if (lphl->PrevFocused != lphl->ItemFocused)
227 SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
228 MAKELONG(hwnd, LBN_SELCHANGE));
229 return 0;
230 case WM_RBUTTONUP:
231 case WM_LBUTTONDBLCLK:
232 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
233 if (lphl == NULL) return 0;
234 SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
235 MAKELONG(hwnd, LBN_DBLCLK));
236 return 0;
237 case WM_MOUSEMOVE:
238 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
239 if (lphl == NULL) return 0;
240 if ((wParam & MK_LBUTTON) != 0) {
241 y = HIWORD(lParam);
242 if (y < 4) {
243 if (lphl->FirstVisible > 1) {
244 lphl->FirstVisible--;
245 if (wndPtr->dwStyle & WS_VSCROLL)
246 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
247 InvalidateRect(hwnd, NULL, TRUE);
248 UpdateWindow(hwnd);
249 break;
252 GetClientRect(hwnd, &rect);
253 if (y > (rect.bottom - 4)) {
254 if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
255 lphl->FirstVisible++;
256 if (wndPtr->dwStyle & WS_VSCROLL)
257 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
258 InvalidateRect(hwnd, NULL, TRUE);
259 UpdateWindow(hwnd);
260 break;
263 if ((y > 0) && (y < (rect.bottom - 4))) {
264 if ((y < rectsel.top) || (y > rectsel.bottom)) {
265 wRet = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
266 if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
267 lphl->ItemFocused = wRet;
269 else {
270 ListBoxSetCurSel(hwnd, wRet);
271 if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
272 SendMessage(lphl->hWndLogicParent, WM_COMMAND,
273 wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
275 ListBoxGetItemRect(hwnd, wRet, &rectsel);
276 InvalidateRect(hwnd, NULL, TRUE);
277 UpdateWindow(hwnd);
281 break;
282 case WM_KEYDOWN:
283 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
284 if (lphl == NULL) return 0;
285 switch(wParam) {
286 case VK_TAB:
287 hWndCtl = GetNextDlgTabItem(lphl->hWndLogicParent,
288 hwnd, !(GetKeyState(VK_SHIFT) < 0));
289 SetFocus(hWndCtl);
290 #ifdef DEBUG_LISTBOX
291 if ((GetKeyState(VK_SHIFT) < 0))
292 dprintf_listbox(stddeb,"ListBox PreviousDlgTabItem %04X !\n", hWndCtl);
293 else
294 dprintf_listbox(stddeb,"ListBox NextDlgTabItem %04X !\n", hWndCtl);
295 #endif
296 break;
297 case VK_HOME:
298 lphl->ItemFocused = 0;
299 break;
300 case VK_END:
301 lphl->ItemFocused = lphl->ItemsCount - 1;
302 break;
303 case VK_LEFT:
304 if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
305 lphl->ItemFocused -= lphl->ItemsPerColumn;
307 break;
308 case VK_UP:
309 lphl->ItemFocused--;
310 break;
311 case VK_RIGHT:
312 if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
313 lphl->ItemFocused += lphl->ItemsPerColumn;
315 break;
316 case VK_DOWN:
317 lphl->ItemFocused++;
318 break;
319 case VK_PRIOR:
320 lphl->ItemFocused -= lphl->ItemsVisible;
321 break;
322 case VK_NEXT:
323 lphl->ItemFocused += lphl->ItemsVisible;
324 break;
325 case VK_SPACE:
326 wRet = ListBoxGetSel(hwnd, lphl->ItemFocused);
327 ListBoxSetSel(hwnd, lphl->ItemFocused, !wRet);
328 break;
329 default:
330 ListBoxFindNextMatch(hwnd, wParam);
331 return 0;
333 if (lphl->ItemFocused < 0) lphl->ItemFocused = 0;
334 if (lphl->ItemFocused >= lphl->ItemsCount)
335 lphl->ItemFocused = lphl->ItemsCount - 1;
336 lphl->FirstVisible = lphl->ItemFocused / lphl->ItemsVisible *
337 lphl->ItemsVisible + 1;
338 if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
339 if ((wndPtr->dwStyle & LBS_MULTIPLESEL) != LBS_MULTIPLESEL) {
340 ListBoxSetCurSel(hwnd, lphl->ItemFocused);
341 if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
342 SendMessage(lphl->hWndLogicParent, WM_COMMAND,
343 wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
345 if (wndPtr->dwStyle & WS_VSCROLL)
346 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
347 InvalidateRect(hwnd, NULL, TRUE);
348 UpdateWindow(hwnd);
349 break;
350 case WM_SETFONT:
351 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
352 if (lphl == NULL) return 0;
353 if (wParam == 0)
354 lphl->hFont = GetStockObject(SYSTEM_FONT);
355 else
356 lphl->hFont = wParam;
357 if (wParam == 0) break;
358 break;
359 case WM_SETREDRAW:
360 #ifdef DEBUG_LISTBOX
361 printf("ListBox WM_SETREDRAW hWnd=%04X w=%04X !\n", hwnd, wParam);
362 #endif
363 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
364 if (lphl == NULL) return 0;
365 lphl->bRedrawFlag = wParam;
366 break;
367 case WM_PAINT:
368 wndPtr = WIN_FindWndPtr(hwnd);
369 if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) {
370 OwnerDrawListBox(hwnd);
371 break;
373 if ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) {
374 OwnerDrawListBox(hwnd);
375 break;
377 StdDrawListBox(hwnd);
378 break;
379 case WM_SETFOCUS:
380 dprintf_listbox(stddeb,"ListBox WM_SETFOCUS !\n");
381 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
382 break;
383 case WM_KILLFOCUS:
384 dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS !\n");
385 InvalidateRect(hwnd, NULL, TRUE);
386 UpdateWindow(hwnd);
387 break;
389 case LB_RESETCONTENT:
390 dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
391 ListBoxResetContent(hwnd);
392 return 0;
393 case LB_DIR:
394 dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
395 wRet = ListBoxDirectory(hwnd, wParam, (LPSTR)lParam);
396 InvalidateRect(hwnd, NULL, TRUE);
397 UpdateWindow(hwnd);
398 return wRet;
399 case LB_ADDSTRING:
400 wRet = ListBoxAddString(hwnd, (LPSTR)lParam);
401 return wRet;
402 case LB_GETTEXT:
403 dprintf_listbox(stddeb, "LB_GETTEXT wParam=%d\n",wParam);
404 wRet = ListBoxGetText(hwnd, wParam, (LPSTR)lParam, FALSE);
405 return wRet;
406 case LB_INSERTSTRING:
407 wRet = ListBoxInsertString(hwnd, wParam, (LPSTR)lParam);
408 return wRet;
409 case LB_DELETESTRING:
410 wRet = ListBoxDeleteString(hwnd, wParam);
411 return wRet;
412 case LB_FINDSTRING:
413 wRet = ListBoxFindString(hwnd, wParam, (LPSTR)lParam);
414 return wRet;
415 case LB_GETCARETINDEX:
416 return wRet;
417 case LB_GETCOUNT:
418 lphl = ListBoxGetStorageHeader(hwnd);
419 return lphl->ItemsCount;
420 case LB_GETCURSEL:
421 lphl = ListBoxGetStorageHeader(hwnd);
422 dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %u !\n",
423 lphl->ItemFocused);
424 return lphl->ItemFocused;
425 case LB_GETHORIZONTALEXTENT:
426 return wRet;
427 case LB_GETITEMDATA:
428 dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
429 lRet = ListBoxGetText(hwnd, wParam, (LPSTR)lParam, TRUE);
430 return lRet;
431 case LB_GETITEMHEIGHT:
432 ListBoxGetItemRect(hwnd, wParam, &rect);
433 return (rect.bottom - rect.top);
434 case LB_GETITEMRECT:
435 ListBoxGetItemRect(hwnd, wParam, (LPRECT)lParam);
436 return 0;
437 case LB_GETSEL:
438 wRet = ListBoxGetSel(hwnd, wParam);
439 return wRet;
440 case LB_GETSELCOUNT:
441 lphl = ListBoxGetStorageHeader(hwnd);
442 if (lphl == NULL) return LB_ERR;
443 return lphl->SelCount;
444 case LB_GETSELITEMS:
445 return wRet;
446 case LB_GETTEXTLEN:
447 return wRet;
448 case LB_GETTOPINDEX:
449 lphl = ListBoxGetStorageHeader(hwnd);
450 if (lphl == NULL) return LB_ERR;
451 return lphl->FirstVisible;
452 case LB_SELECTSTRING:
453 return wRet;
454 case LB_SELITEMRANGE:
455 return wRet;
456 case LB_SETCARETINDEX:
457 return wRet;
458 case LB_SETCOLUMNWIDTH:
459 lphl = ListBoxGetStorageHeader(hwnd);
460 if (lphl == NULL) return LB_ERR;
461 lphl->ColumnsWidth = wParam;
462 break;
463 case LB_SETHORIZONTALEXTENT:
464 return wRet;
465 case LB_SETITEMDATA:
466 dprintf_listbox(stddeb, "LB_SETITEMDATA wParam=%x lParam=%lx\n", wParam, lParam);
467 wRet = ListBoxSetItemData(hwnd, wParam, lParam);
468 return wRet;
469 case LB_SETTABSTOPS:
470 lphl = ListBoxGetStorageHeader(hwnd);
471 if (lphl == NULL) return LB_ERR;
472 lphl->FirstVisible = wParam;
473 return 0;
474 case LB_SETCURSEL:
475 dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n",
476 wParam);
477 wRet = ListBoxSetCurSel(hwnd, wParam);
478 InvalidateRect(hwnd, NULL, TRUE);
479 UpdateWindow(hwnd);
480 return wRet;
481 case LB_SETSEL:
482 dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
483 wRet = ListBoxSetSel(hwnd, LOWORD(lParam), wParam);
484 InvalidateRect(hwnd, NULL, TRUE);
485 UpdateWindow(hwnd);
486 return wRet;
487 case LB_SETTOPINDEX:
488 dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
489 wParam);
490 lphl = ListBoxGetStorageHeader(hwnd);
491 lphl->FirstVisible = wParam;
492 wndPtr = WIN_FindWndPtr(hwnd);
493 if (wndPtr->dwStyle & WS_VSCROLL)
494 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
495 InvalidateRect(hwnd, NULL, TRUE);
496 UpdateWindow(hwnd);
497 break;
498 case LB_SETITEMHEIGHT:
499 dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
500 wRet = ListBoxSetItemHeight(hwnd, wParam, lParam);
501 return wRet;
503 default:
504 return DefWindowProc( hwnd, message, wParam, lParam );
506 return 0;
510 LPHEADLIST ListBoxGetWindowAndStorage(HWND hwnd, WND **wndPtr)
512 WND *Ptr;
513 LPHEADLIST lphl;
514 *(wndPtr) = Ptr = WIN_FindWndPtr(hwnd);
515 lphl = *((LPHEADLIST *)&Ptr->wExtra[1]);
516 return lphl;
520 LPHEADLIST ListBoxGetStorageHeader(HWND hwnd)
522 WND *wndPtr;
523 LPHEADLIST lphl;
524 wndPtr = WIN_FindWndPtr(hwnd);
525 lphl = *((LPHEADLIST *)&wndPtr->wExtra[1]);
526 return lphl;
530 void StdDrawListBox(HWND hwnd)
532 WND *wndPtr;
533 LPHEADLIST lphl;
534 LPLISTSTRUCT lpls;
535 PAINTSTRUCT ps;
536 HBRUSH hBrush;
537 int OldBkMode;
538 DWORD dwOldTextColor;
539 HDC hdc;
540 RECT rect;
541 int i, h, h2, maxwidth, ipc;
542 h = 0;
543 hdc = BeginPaint( hwnd, &ps );
544 if (!IsWindowVisible(hwnd)) {
545 EndPaint( hwnd, &ps );
546 return;
548 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
549 if (lphl == NULL) goto EndOfPaint;
550 if (!lphl->bRedrawFlag) goto EndOfPaint;
551 SelectObject(hdc, lphl->hFont);
552 hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
553 MAKELONG(hwnd, CTLCOLOR_LISTBOX));
554 if (hBrush == (HBRUSH)NULL) hBrush = GetStockObject(WHITE_BRUSH);
555 GetClientRect(hwnd, &rect);
557 if (wndPtr->dwStyle & WS_VSCROLL) rect.right -= 16;
558 if (wndPtr->dwStyle & WS_HSCROLL) rect.bottom -= 16;
560 FillRect(hdc, &rect, hBrush);
561 maxwidth = rect.right;
562 rect.right = lphl->ColumnsWidth;
563 if (lphl->ItemsCount == 0) goto EndOfPaint;
564 lpls = lphl->lpFirst;
565 if (lpls == NULL) goto EndOfPaint;
566 lphl->ItemsVisible = 0;
567 lphl->ItemsPerColumn = ipc = 0;
568 for(i = 1; i <= lphl->ItemsCount; i++) {
569 if (i >= lphl->FirstVisible) {
570 if (lpls == NULL) break;
571 if ((h + lpls->dis.rcItem.bottom - lpls->dis.rcItem.top) > rect.bottom) {
572 if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
573 lphl->ItemsPerColumn = max(lphl->ItemsPerColumn, ipc);
574 ipc = 0;
575 h = 0;
576 rect.left += lphl->ColumnsWidth;
577 rect.right += lphl->ColumnsWidth;
578 if (rect.left > maxwidth) break;
580 else
581 break;
583 h2 = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
584 lpls->dis.rcItem.top = h;
585 lpls->dis.rcItem.bottom = h + h2;
586 lpls->dis.rcItem.left = rect.left;
587 lpls->dis.rcItem.right = rect.right;
588 OldBkMode = SetBkMode(hdc, TRANSPARENT);
589 if (lpls->dis.itemState != 0) {
590 dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
591 FillRect(hdc, &lpls->dis.rcItem, GetStockObject(BLACK_BRUSH));
593 TextOut(hdc, rect.left + 5, h + 2, (char *)lpls->itemText,
594 strlen((char *)lpls->itemText));
595 if (lpls->dis.itemState != 0) {
596 SetTextColor(hdc, dwOldTextColor);
598 SetBkMode(hdc, OldBkMode);
599 if ((lphl->ItemFocused == i - 1) && GetFocus() == hwnd) {
600 DrawFocusRect(hdc, &lpls->dis.rcItem);
602 h += h2;
603 lphl->ItemsVisible++;
604 ipc++;
606 if (lpls->lpNext == NULL) goto EndOfPaint;
607 lpls = (LPLISTSTRUCT)lpls->lpNext;
609 EndOfPaint:
610 EndPaint( hwnd, &ps );
611 if ((lphl->ItemsCount > lphl->ItemsVisible) &
612 (wndPtr->dwStyle & WS_VSCROLL)) {
614 InvalidateRect(wndPtr->hWndVScroll, NULL, TRUE);
615 UpdateWindow(wndPtr->hWndVScroll);
622 void OwnerDrawListBox(HWND hwnd)
624 WND *wndPtr,*ParentWndPtr;
625 LPHEADLIST lphl;
626 LPLISTSTRUCT lpls;
627 PAINTSTRUCT ps;
628 HBRUSH hBrush;
629 HWND hWndParent;
630 DWORD itemData;
631 HDC hdc;
632 RECT rect;
633 int i, h, h2, maxwidth;
634 h = 0;
635 hdc = BeginPaint(hwnd, &ps);
636 if (!IsWindowVisible(hwnd)) {
637 EndPaint( hwnd, &ps );
638 return;
640 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
641 if (lphl == NULL) goto EndOfPaint;
642 if (!lphl->bRedrawFlag) goto EndOfPaint;
643 hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
644 MAKELONG(hwnd, CTLCOLOR_LISTBOX));
645 if (hBrush == (HBRUSH)NULL) hBrush = GetStockObject(WHITE_BRUSH);
646 GetClientRect(hwnd, &rect);
647 if (wndPtr->dwStyle & WS_VSCROLL) rect.right -= 16;
648 if (wndPtr->dwStyle & WS_HSCROLL) rect.bottom -= 16;
649 FillRect(hdc, &rect, hBrush);
650 maxwidth = rect.right;
651 rect.right = lphl->ColumnsWidth;
652 if (lphl->ItemsCount == 0) goto EndOfPaint;
653 lpls = lphl->lpFirst;
654 if (lpls == NULL) goto EndOfPaint;
655 lphl->ItemsVisible = 0;
656 for (i = 1; i <= lphl->ItemsCount; i++) {
657 if (i >= lphl->FirstVisible) {
658 lpls->dis.hDC = hdc;
659 lpls->dis.hwndItem = hwnd;
660 lpls->dis.CtlType = ODT_LISTBOX;
661 lpls->dis.itemID = i - 1;
662 if ((!lpls->dis.CtlID) && (lphl->hWndLogicParent)) {
663 ParentWndPtr = WIN_FindWndPtr(lphl->hWndLogicParent);
664 lpls->dis.CtlID = ParentWndPtr->wIDmenu;
666 h2 = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
667 lpls->dis.rcItem.top = h;
668 lpls->dis.rcItem.bottom = h + h2;
669 lpls->dis.rcItem.left = rect.left;
670 lpls->dis.rcItem.right = rect.right;
671 lpls->dis.itemAction = ODA_DRAWENTIRE;
672 /* if (lpls->dis.itemState != 0) {
673 lpls->dis.itemAction |= ODA_SELECT;
675 if (lphl->ItemFocused == i - 1) {
676 lpls->dis.itemAction |= ODA_FOCUS;
678 dprintf_listbox(stddeb,"LBOX WM_DRAWITEM #%d left=%d top=%d right=%d bottom=%d !\n",
679 i-1, lpls->dis.rcItem.left, lpls->dis.rcItem.top,
680 lpls->dis.rcItem.right, lpls->dis.rcItem.bottom);
681 dprintf_listbox(stddeb,"LBOX WM_DRAWITEM Parent=%X &dis=%lX CtlID=%u !\n",
682 hWndParent, (LONG)&lpls->dis, lpls->dis.CtlID);
683 dprintf_listbox(stddeb,"LBOX WM_DRAWITEM %08lX!\n",lpls->dis.itemData);
684 if (HasStrings(wndPtr))
685 dprintf_listbox(stddeb," '%s'\n",lpls->itemText);
686 if (HasStrings(wndPtr)) {
687 itemData = lpls->dis.itemData;
688 lpls->dis.itemData = (DWORD)lpls->itemText;
690 SendMessage(lphl->hWndLogicParent, WM_DRAWITEM,
691 i-1, (LPARAM)&lpls->dis);
692 if (HasStrings(wndPtr))
693 lpls->dis.itemData = itemData;
695 /* if (lpls->dis.itemState != 0) {
696 InvertRect(hdc, &lpls->dis.rcItem);
697 } */
698 h += h2;
699 lphl->ItemsVisible++;
700 /* if (h > rect.bottom) goto EndOfPaint;*/
702 if (lpls->lpNext == NULL) goto EndOfPaint;
703 lpls = (LPLISTSTRUCT)lpls->lpNext;
705 EndOfPaint:
706 EndPaint( hwnd, &ps );
707 if ((lphl->ItemsCount > lphl->ItemsVisible) &
708 (wndPtr->dwStyle & WS_VSCROLL)) {
710 InvalidateRect(wndPtr->hWndVScroll, NULL, TRUE);
711 UpdateWindow(wndPtr->hWndVScroll);
719 int ListBoxFindMouse(HWND hwnd, int X, int Y)
721 WND *wndPtr;
722 LPHEADLIST lphl;
723 LPLISTSTRUCT lpls;
724 RECT rect;
725 int i, h, h2, w, w2;
726 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
727 if (lphl == NULL) return LB_ERR;
728 if (lphl->ItemsCount == 0) return LB_ERR;
729 lpls = lphl->lpFirst;
730 if (lpls == NULL) return LB_ERR;
731 GetClientRect(hwnd, &rect);
732 if (wndPtr->dwStyle & WS_VSCROLL) rect.right -= 16;
733 if (wndPtr->dwStyle & WS_HSCROLL) rect.bottom -= 16;
734 h = w2 = 0;
735 w = lphl->ColumnsWidth;
736 for(i = 1; i <= lphl->ItemsCount; i++) {
737 if (i >= lphl->FirstVisible) {
738 h2 = h;
739 h += lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
740 if ((Y > h2) && (Y < h) &&
741 (X > w2) && (X < w)) return(i - 1);
742 if (h > rect.bottom) {
743 if ((wndPtr->dwStyle & LBS_MULTICOLUMN) != LBS_MULTICOLUMN) return LB_ERR;
744 h = 0;
745 w2 = w;
746 w += lphl->ColumnsWidth;
747 if (w2 > rect.right) return LB_ERR;
750 if (lpls->lpNext == NULL) return LB_ERR;
751 lpls = (LPLISTSTRUCT)lpls->lpNext;
753 return(LB_ERR);
758 int CreateListBoxStruct(HWND hwnd)
760 WND *wndPtr;
761 LPHEADLIST lphl;
762 int HeapHandle;
763 void *HeapBase;
764 wndPtr = WIN_FindWndPtr(hwnd);
765 lphl = (LPHEADLIST)malloc(sizeof(HEADLIST));
766 lphl->lpFirst = NULL;
767 *((LPHEADLIST *)&wndPtr->wExtra[1]) = lphl; /* HEAD of List */
768 lphl->ItemsCount = 0;
769 lphl->ItemsVisible = 0;
770 lphl->FirstVisible = 1;
771 lphl->ColumnsVisible = 1;
772 lphl->ItemsPerColumn = 0;
773 lphl->StdItemHeight = 15;
774 lphl->ItemFocused = 0;
775 lphl->PrevFocused = 0;
776 lphl->SelCount = 0;
777 lphl->DrawCtlType = ODT_LISTBOX;
778 lphl->bRedrawFlag = TRUE;
779 HeapHandle = GlobalAlloc(GMEM_FIXED, LIST_HEAP_SIZE);
780 HeapBase = GlobalLock(HeapHandle);
781 HEAP_Init(&lphl->Heap, HeapBase, LIST_HEAP_SIZE);
782 return TRUE;
786 void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls)
788 MEASUREITEMSTRUCT *lpmeasure;
789 HANDLE hTemp = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(MEASUREITEMSTRUCT));
790 lpmeasure = (MEASUREITEMSTRUCT *) USER_HEAP_ADDR(hTemp);
791 if (lpmeasure == NULL) {
792 fprintf(stderr,"ListBoxAskMeasure() // Bad allocation of Measure struct !\n");
793 return;
795 lpmeasure->CtlType = ODT_LISTBOX;
796 lpmeasure->CtlID = wndPtr->wIDmenu;
797 lpmeasure->itemID = lpls->dis.itemID;
798 lpmeasure->itemWidth = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
799 lpmeasure->itemHeight = 0;
800 if (HasStrings(wndPtr))
801 lpmeasure->itemData = (DWORD)lpls->itemText;
802 else
803 lpmeasure->itemData = lpls->dis.itemData;
804 SendMessage(lphl->hWndLogicParent, WM_MEASUREITEM, 0, (DWORD)lpmeasure);
805 lpls->dis.rcItem.right = lpls->dis.rcItem.left + lpmeasure->itemWidth;
806 lpls->dis.rcItem.bottom = lpls->dis.rcItem.top + lpmeasure->itemHeight;
807 USER_HEAP_FREE(hTemp);
811 int ListBoxAddString(HWND hwnd, LPSTR newstr)
813 LPHEADLIST lphl;
814 UINT pos = (UINT) -1;
815 WND *wndPtr;
817 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
818 if (lphl == NULL) return LB_ERR;
819 if (HasStrings(wndPtr) && (wndPtr->dwStyle & LBS_SORT)) {
820 LPLISTSTRUCT lpls = lphl->lpFirst;
821 for (pos = 0; lpls; lpls = lpls->lpNext, pos++)
822 if (strcmp(lpls->itemText, newstr) >= 0)
823 break;
825 return ListBoxInsertString(hwnd, pos, newstr);
828 int ListBoxInsertString(HWND hwnd, UINT uIndex, LPSTR newstr)
830 WND *wndPtr;
831 LPHEADLIST lphl;
832 LPLISTSTRUCT *lppls, lplsnew;
833 HANDLE hItem;
834 HANDLE hStr;
835 LPSTR str;
836 UINT Count;
838 dprintf_listbox(stddeb,"ListBoxInsertString(%04X, %d, %p);\n",
839 hwnd, uIndex, newstr);
841 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
842 if (lphl == NULL) return LB_ERR;
844 if (uIndex == (UINT)-1)
845 uIndex = lphl->ItemsCount;
846 if (uIndex > lphl->ItemsCount) return LB_ERR;
847 lppls = (LPLISTSTRUCT *) &lphl->lpFirst;
849 for(Count = 0; Count < uIndex; Count++) {
850 if (*lppls == NULL) return LB_ERR;
851 lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
854 hItem = LIST_HEAP_ALLOC(lphl, GMEM_MOVEABLE, sizeof(LISTSTRUCT));
855 lplsnew = (LPLISTSTRUCT) LIST_HEAP_ADDR(lphl, hItem);
856 if (lplsnew == NULL) {
857 printf("ListBoxInsertString() // Bad allocation of new item !\n");
858 return LB_ERRSPACE;
860 ListBoxDefaultItem(hwnd, wndPtr, lphl, lplsnew);
861 lplsnew->hMem = hItem;
862 lplsnew->lpNext = *lppls;
863 *lppls = lplsnew;
864 lphl->ItemsCount++;
865 hStr = 0;
867 if (HasStrings(wndPtr)) {
868 hStr = LIST_HEAP_ALLOC(lphl, GMEM_MOVEABLE, strlen(newstr) + 1);
869 str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
870 if (str == NULL) return LB_ERRSPACE;
871 strcpy(str, newstr);
872 newstr = str;
873 lplsnew->itemText = str;
874 dprintf_listbox(stddeb,"ListBoxInsertString // LBS_HASSTRINGS after strcpy '%s'\n", str);
876 else {
877 lplsnew->itemText = NULL;
878 lplsnew->dis.itemData = (DWORD)newstr;
880 lplsnew->dis.itemID = lphl->ItemsCount;
881 lplsnew->hData = hStr;
882 if (((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) ||
883 ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED))
884 ListBoxAskMeasure(wndPtr, lphl, lplsnew);
885 if (wndPtr->dwStyle & WS_VSCROLL)
886 SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl),
887 (lphl->FirstVisible != 1 && lphl->bRedrawFlag));
888 if ((wndPtr->dwStyle & WS_HSCROLL) && lphl->ItemsPerColumn != 0)
889 SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
890 lphl->ItemsPerColumn + 1,
891 (lphl->FirstVisible != 1 && lphl->bRedrawFlag));
892 if (((lphl->ItemsCount - lphl->FirstVisible) == lphl->ItemsVisible) &&
893 (lphl->ItemsVisible != 0)) {
894 if (wndPtr->dwStyle & WS_VSCROLL) ShowScrollBar(hwnd, SB_VERT, TRUE);
895 if (wndPtr->dwStyle & WS_HSCROLL) ShowScrollBar(hwnd, SB_HORZ, TRUE);
897 if ((lphl->FirstVisible <= uIndex) &&
898 ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
899 InvalidateRect(hwnd, NULL, TRUE);
900 UpdateWindow(hwnd);
902 dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
903 return uIndex;
907 int ListBoxGetText(HWND hwnd, UINT uIndex, LPSTR OutStr, BOOL bItemData)
909 WND *wndPtr;
910 LPHEADLIST lphl;
911 LPLISTSTRUCT lpls;
912 UINT Count;
913 if ((!OutStr)&&(!bItemData))
914 fprintf(stderr, "ListBoxGetText // OutStr==NULL\n");
915 if (!bItemData) *OutStr=0;
916 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
917 if (lphl == NULL) return LB_ERR;
918 if (uIndex >= lphl->ItemsCount) return LB_ERR;
919 lpls = lphl->lpFirst;
920 if (lpls == NULL) return LB_ERR;
921 if (uIndex > lphl->ItemsCount) return LB_ERR;
922 for(Count = 0; Count < uIndex; Count++) {
923 if (lpls->lpNext == NULL) return LB_ERR;
924 lpls = (LPLISTSTRUCT)lpls->lpNext;
926 if (bItemData)
927 return lpls->dis.itemData;
928 if (!(HasStrings(wndPtr)) )
930 *((long *)OutStr) = lpls->dis.itemData;
931 return 4;
934 strcpy(OutStr, lpls->itemText);
935 return strlen(OutStr);
938 int ListBoxSetItemData(HWND hwnd, UINT uIndex, DWORD ItemData)
940 WND *wndPtr;
941 LPHEADLIST lphl;
942 LPLISTSTRUCT lpls;
943 UINT Count;
944 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
945 if (lphl == NULL) return LB_ERR;
946 if (uIndex >= lphl->ItemsCount) return LB_ERR;
947 lpls = lphl->lpFirst;
948 if (lpls == NULL) return LB_ERR;
949 if (uIndex > lphl->ItemsCount) return LB_ERR;
950 for(Count = 0; Count < uIndex; Count++) {
951 if (lpls->lpNext == NULL) return LB_ERR;
952 lpls = (LPLISTSTRUCT)lpls->lpNext;
954 lpls->dis.itemData = ItemData;
955 return 1;
959 int ListBoxDeleteString(HWND hwnd, UINT uIndex)
961 WND *wndPtr;
962 LPHEADLIST lphl;
963 LPLISTSTRUCT lpls, lpls2;
964 UINT Count;
965 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
966 if (lphl == NULL) return LB_ERR;
967 if (uIndex >= lphl->ItemsCount) return LB_ERR;
968 lpls = lphl->lpFirst;
969 if (lpls == NULL) return LB_ERR;
970 if (uIndex > lphl->ItemsCount) return LB_ERR;
971 for(Count = 1; Count < uIndex; Count++) {
972 if (lpls->lpNext == NULL) return LB_ERR;
973 lpls2 = lpls;
974 lpls = (LPLISTSTRUCT)lpls->lpNext;
976 lpls2->lpNext = (LPLISTSTRUCT)lpls->lpNext;
977 lphl->ItemsCount--;
978 if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
979 if (lpls->hMem != 0) LIST_HEAP_FREE(lphl, lpls->hMem);
980 if (wndPtr->dwStyle & WS_VSCROLL)
981 SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
982 if ((wndPtr->dwStyle & WS_HSCROLL) && lphl->ItemsPerColumn != 0)
983 SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
984 lphl->ItemsPerColumn + 1, TRUE);
985 if (lphl->ItemsCount < lphl->ItemsVisible) {
986 if (wndPtr->dwStyle & WS_VSCROLL)
987 ShowScrollBar(hwnd, SB_VERT, FALSE);
988 if (wndPtr->dwStyle & WS_HSCROLL)
989 ShowScrollBar(hwnd, SB_HORZ, FALSE);
991 if ((lphl->FirstVisible <= uIndex) &&
992 ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
993 InvalidateRect(hwnd, NULL, TRUE);
994 UpdateWindow(hwnd);
996 return lphl->ItemsCount;
1000 int ListBoxFindString(HWND hwnd, UINT nFirst, LPSTR MatchStr)
1002 WND *wndPtr;
1003 LPHEADLIST lphl;
1004 LPLISTSTRUCT lpls;
1005 UINT Count;
1006 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1007 if (lphl == NULL) return LB_ERR;
1008 if (nFirst > lphl->ItemsCount) return LB_ERR;
1009 lpls = lphl->lpFirst;
1010 if (lpls == NULL) return LB_ERR;
1011 Count = 0;
1012 while(lpls != NULL) {
1013 if (HasStrings(wndPtr))
1015 if (strcmp(lpls->itemText, MatchStr) == 0) return Count;
1017 else
1019 if (lpls->dis.itemData == (DWORD)MatchStr) return Count;
1021 lpls = (LPLISTSTRUCT)lpls->lpNext;
1022 Count++;
1024 return LB_ERR;
1028 int ListBoxResetContent(HWND hwnd)
1030 WND *wndPtr;
1031 LPHEADLIST lphl;
1032 LPLISTSTRUCT lpls, lpls2;
1033 UINT i;
1034 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1035 if (lphl == NULL) return LB_ERR;
1036 lpls = lphl->lpFirst;
1037 if (lpls == NULL) return LB_ERR;
1038 dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n",
1039 lphl->ItemsCount);
1040 for(i = 0; i <= lphl->ItemsCount; i++) {
1041 lpls2 = lpls;
1042 lpls = (LPLISTSTRUCT)lpls->lpNext;
1043 if (i != 0) {
1044 dprintf_listbox(stddeb,"ResetContent #%u\n", i);
1045 if (lpls2->hData != 0 && lpls2->hData != lpls2->hMem)
1046 LIST_HEAP_FREE(lphl, lpls2->hData);
1047 if (lpls2->hMem != 0) LIST_HEAP_FREE(lphl, lpls2->hMem);
1049 if (lpls == NULL) break;
1051 lphl->lpFirst = NULL;
1052 lphl->FirstVisible = 1;
1053 lphl->ItemsCount = 0;
1054 lphl->ItemFocused = -1;
1055 lphl->PrevFocused = -1;
1056 if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
1057 SendMessage(lphl->hWndLogicParent, WM_COMMAND,
1058 wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
1059 if (wndPtr->dwStyle & WS_VSCROLL)
1060 SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
1061 if ((wndPtr->dwStyle & WS_HSCROLL) && lphl->ItemsPerColumn != 0)
1062 SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
1063 lphl->ItemsPerColumn + 1, TRUE);
1064 if (wndPtr->dwStyle & WS_VSCROLL)
1065 ShowScrollBar(hwnd, SB_VERT, FALSE);
1066 if (wndPtr->dwStyle & WS_HSCROLL)
1067 ShowScrollBar(hwnd, SB_HORZ, FALSE);
1068 InvalidateRect(hwnd, NULL, TRUE);
1069 UpdateWindow(hwnd);
1070 return TRUE;
1074 int ListBoxSetCurSel(HWND hwnd, WORD wIndex)
1076 WND *wndPtr;
1077 LPHEADLIST lphl;
1078 LPLISTSTRUCT lpls, lpls2;
1079 UINT i;
1080 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1081 if (lphl == NULL) return LB_ERR;
1082 lphl->ItemFocused = LB_ERR;
1083 if (wIndex >= lphl->ItemsCount) return LB_ERR;
1084 lpls = lphl->lpFirst;
1085 if (lpls == NULL) return LB_ERR;
1086 for(i = 0; i < lphl->ItemsCount; i++) {
1087 lpls2 = lpls;
1088 lpls = (LPLISTSTRUCT)lpls->lpNext;
1089 if (i == wIndex)
1090 lpls2->dis.itemState = 1;
1091 else
1092 if (lpls2->dis.itemState != 0)
1093 lpls2->dis.itemState = 0;
1094 if (lpls == NULL) break;
1096 lphl->ItemFocused = wIndex;
1097 if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
1098 SendMessage(lphl->hWndLogicParent, WM_COMMAND,
1099 wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
1100 return LB_ERR;
1105 int ListBoxSetSel(HWND hwnd, WORD wIndex, WORD state)
1107 LPHEADLIST lphl;
1108 LPLISTSTRUCT lpls, lpls2;
1109 UINT i;
1110 lphl = ListBoxGetStorageHeader(hwnd);
1111 if (lphl == NULL) return LB_ERR;
1112 if (wIndex >= lphl->ItemsCount) return LB_ERR;
1113 lpls = lphl->lpFirst;
1114 if (lpls == NULL) return LB_ERR;
1115 for(i = 0; i < lphl->ItemsCount; i++) {
1116 lpls2 = lpls;
1117 lpls = (LPLISTSTRUCT)lpls->lpNext;
1118 if ((i == wIndex) || (wIndex == (WORD)-1)) {
1119 lpls2->dis.itemState = state;
1120 break;
1122 if (lpls == NULL) break;
1124 return LB_ERR;
1128 int ListBoxGetSel(HWND hwnd, WORD wIndex)
1130 LPHEADLIST lphl;
1131 LPLISTSTRUCT lpls, lpls2;
1132 UINT i;
1133 lphl = ListBoxGetStorageHeader(hwnd);
1134 if (lphl == NULL) return LB_ERR;
1135 if (wIndex >= lphl->ItemsCount) return LB_ERR;
1136 lpls = lphl->lpFirst;
1137 if (lpls == NULL) return LB_ERR;
1138 for(i = 0; i < lphl->ItemsCount; i++) {
1139 lpls2 = lpls;
1140 lpls = (LPLISTSTRUCT)lpls->lpNext;
1141 if (i == wIndex) {
1142 return lpls2->dis.itemState;
1144 if (lpls == NULL) break;
1146 return LB_ERR;
1150 int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec)
1152 struct dosdirent *dp;
1153 int x, wRet;
1154 BOOL OldFlag;
1155 char temp[256];
1156 LPHEADLIST lphl;
1157 dprintf_listbox(stddeb,"ListBoxDirectory: %s, %4x\n",filespec,attrib);
1158 lphl = ListBoxGetStorageHeader(hwnd);
1159 if (lphl == NULL) return LB_ERR;
1160 if ((dp = (struct dosdirent *)DOS_opendir(filespec)) ==NULL) return 0;
1161 OldFlag = lphl->bRedrawFlag;
1162 lphl->bRedrawFlag = FALSE;
1163 while ((dp = (struct dosdirent *)DOS_readdir(dp))) {
1164 if (!dp->inuse) break;
1165 dprintf_listbox(stddeb,"ListBoxDirectory %p '%s' !\n", dp->filename, dp->filename);
1166 if (dp->attribute & FA_DIREC) {
1167 if (attrib & DDL_DIRECTORY &&
1168 strcmp(dp->filename, ".")) {
1169 sprintf(temp, "[%s]", dp->filename);
1170 if ( (wRet = ListBoxAddString(hwnd, temp)) == LB_ERR) break;
1173 else {
1174 if (attrib & DDL_EXCLUSIVE) {
1175 if (attrib & (DDL_READWRITE | DDL_READONLY | DDL_HIDDEN |
1176 DDL_SYSTEM) )
1177 if ( (wRet = ListBoxAddString(hwnd, dp->filename))
1178 == LB_ERR) break;
1180 else {
1181 if ( (wRet = ListBoxAddString(hwnd, dp->filename))
1182 == LB_ERR) break;
1186 DOS_closedir(dp);
1188 if (attrib & DDL_DRIVES) {
1189 for (x=0;x!=MAX_DOS_DRIVES;x++) {
1190 if (DOS_ValidDrive(x)) {
1191 sprintf(temp, "[-%c-]", 'a'+x);
1192 if ( (wRet = ListBoxAddString(hwnd, temp)) == LB_ERR) break;
1196 lphl->bRedrawFlag = OldFlag;
1197 if (OldFlag) {
1198 InvalidateRect(hwnd, NULL, TRUE);
1199 UpdateWindow(hwnd);
1201 dprintf_listbox(stddeb,"End of ListBoxDirectory !\n");
1202 return wRet;
1206 int ListBoxGetItemRect(HWND hwnd, WORD wIndex, LPRECT lprect)
1208 LPHEADLIST lphl;
1209 LPLISTSTRUCT lpls, lpls2;
1210 UINT i;
1211 lphl = ListBoxGetStorageHeader(hwnd);
1212 if (lphl == NULL) return LB_ERR;
1213 if (wIndex > lphl->ItemsCount) return LB_ERR;
1214 lpls = lphl->lpFirst;
1215 if (lpls == NULL) return LB_ERR;
1216 for(i = 0; i < lphl->ItemsCount; i++) {
1217 lpls2 = lpls;
1218 lpls = (LPLISTSTRUCT)lpls->lpNext;
1219 if (i == wIndex) {
1220 *(lprect) = lpls2->dis.rcItem;
1221 break;
1223 if (lpls == NULL) break;
1225 return LB_ERR;
1230 int ListBoxSetItemHeight(HWND hwnd, WORD wIndex, long height)
1232 LPHEADLIST lphl;
1233 LPLISTSTRUCT lpls, lpls2;
1234 UINT i;
1235 lphl = ListBoxGetStorageHeader(hwnd);
1236 if (lphl == NULL) return LB_ERR;
1237 if (wIndex > lphl->ItemsCount) return LB_ERR;
1238 lpls = lphl->lpFirst;
1239 if (lpls == NULL) return LB_ERR;
1240 for(i = 0; i < lphl->ItemsCount; i++) {
1241 lpls2 = lpls;
1242 lpls = (LPLISTSTRUCT)lpls->lpNext;
1243 if (i == wIndex) {
1244 lpls2->dis.rcItem.bottom = lpls2->dis.rcItem.top + (short)height;
1245 InvalidateRect(hwnd, NULL, TRUE);
1246 UpdateWindow(hwnd);
1247 break;
1249 if (lpls == NULL) break;
1251 return LB_ERR;
1258 int ListBoxDefaultItem(HWND hwnd, WND *wndPtr,
1259 LPHEADLIST lphl, LPLISTSTRUCT lpls)
1261 RECT rect;
1262 if (wndPtr == NULL || lphl == NULL || lpls == NULL) {
1263 fprintf(stderr,"ListBoxDefaultItem() // Bad Pointers !\n");
1264 return FALSE;
1266 GetClientRect(hwnd, &rect);
1267 SetRect(&lpls->dis.rcItem, 0, 0, rect.right, lphl->StdItemHeight);
1268 lpls->dis.CtlType = lphl->DrawCtlType;
1269 lpls->dis.CtlID = wndPtr->wIDmenu;
1270 lpls->dis.itemID = 0;
1271 lpls->dis.itemAction = 0;
1272 lpls->dis.itemState = 0;
1273 lpls->dis.hwndItem = hwnd;
1274 lpls->dis.hDC = 0;
1275 lpls->dis.itemData = 0;
1276 return TRUE;
1281 int ListBoxFindNextMatch(HWND hwnd, WORD wChar)
1283 WND *wndPtr;
1284 LPHEADLIST lphl;
1285 LPLISTSTRUCT lpls;
1286 UINT Count;
1287 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1288 if (lphl == NULL) return LB_ERR;
1289 lpls = lphl->lpFirst;
1290 if (lpls == NULL) return LB_ERR;
1291 if (wChar < ' ') return LB_ERR;
1292 if (((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) ||
1293 ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE)) {
1294 if ((wndPtr->dwStyle & LBS_HASSTRINGS) != LBS_HASSTRINGS) {
1295 return LB_ERR;
1298 Count = 0;
1299 while(lpls != NULL) {
1300 if (Count > lphl->ItemFocused) {
1301 if (*(lpls->itemText) == (char)wChar) {
1302 lphl->FirstVisible = Count - lphl->ItemsVisible / 2;
1303 if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
1304 if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
1305 lphl->ItemFocused = Count;
1307 else {
1308 ListBoxSetCurSel(hwnd, Count);
1310 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1311 InvalidateRect(hwnd, NULL, TRUE);
1312 UpdateWindow(hwnd);
1313 return Count;
1316 lpls = (LPLISTSTRUCT)lpls->lpNext;
1317 Count++;
1319 Count = 0;
1320 lpls = lphl->lpFirst;
1321 while(lpls != NULL) {
1322 if (*(lpls->itemText) == (char)wChar) {
1323 if (Count == lphl->ItemFocused) return LB_ERR;
1324 lphl->FirstVisible = Count - lphl->ItemsVisible / 2;
1325 if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
1326 if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
1327 lphl->ItemFocused = Count;
1329 else {
1330 ListBoxSetCurSel(hwnd, Count);
1332 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1333 InvalidateRect(hwnd, NULL, TRUE);
1334 UpdateWindow(hwnd);
1335 return Count;
1337 lpls = (LPLISTSTRUCT)lpls->lpNext;
1338 Count++;
1340 return LB_ERR;
1344 /************************************************************************
1345 * DlgDirSelect [USER.99]
1347 BOOL DlgDirSelect(HWND hDlg, LPSTR lpStr, int nIDLBox)
1349 fprintf(stdnimp,"DlgDirSelect(%04X, '%s', %d) \n", hDlg, lpStr, nIDLBox);
1350 return FALSE;
1354 /************************************************************************
1355 * DlgDirList [USER.100]
1357 int DlgDirList(HWND hDlg, LPSTR lpPathSpec,
1358 int nIDLBox, int nIDStat, WORD wType)
1360 HWND hWnd;
1361 int ret;
1362 dprintf_listbox(stddeb,"DlgDirList(%04X, '%s', %d, %d, %04X) \n",
1363 hDlg, lpPathSpec, nIDLBox, nIDStat, wType);
1364 if (nIDLBox)
1365 hWnd = GetDlgItem(hDlg, nIDLBox);
1366 else
1367 hWnd = 0;
1368 if (hWnd)
1369 ListBoxResetContent(hWnd);
1370 if (hWnd)
1371 ret=ListBoxDirectory(hWnd, wType, lpPathSpec);
1372 else
1373 ret=0;
1374 if (nIDStat)
1376 int drive;
1377 drive = DOS_GetDefaultDrive();
1378 SendDlgItemMessage(hDlg, nIDStat, WM_SETTEXT, 0,
1379 (LONG) DOS_GetCurrentDir(drive) );
1381 return ret;
1384 /* get the maximum value of lphl->FirstVisible */
1385 int ListMaxFirstVisible(LPHEADLIST lphl)
1387 int m = lphl->ItemsCount-lphl->ItemsVisible+1;
1388 return (m < 1) ? 1 : m;