Release 950109
[wine/multimedia.git] / controls / listbox.c
blob96a194fb796637e17fac8bc426d58bddcfaa9603
1 /*
2 * Interface code to listbox widgets
4 * Copyright Martin Ayotte, 1993
6 static char Copyright[] = "Copyright Martin Ayotte, 1993";
7 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include "windows.h"
14 #include "user.h"
15 #include "heap.h"
16 #include "win.h"
17 #include "msdos.h"
18 #include "listbox.h"
19 #include "dos_fs.h"
20 #include "stddebug.h"
21 #include "debug.h"
23 #define GMEM_ZEROINIT 0x0040
26 LPHEADLIST ListBoxGetWindowAndStorage(HWND hwnd, WND **wndPtr);
27 LPHEADLIST ListBoxGetStorageHeader(HWND hwnd);
28 void StdDrawListBox(HWND hwnd);
29 void OwnerDrawListBox(HWND hwnd);
30 int ListBoxFindMouse(HWND hwnd, int X, int Y);
31 int CreateListBoxStruct(HWND hwnd);
32 void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls);
33 int ListBoxAddString(HWND hwnd, LPSTR newstr);
34 int ListBoxInsertString(HWND hwnd, UINT uIndex, LPSTR newstr);
35 int ListBoxGetText(HWND hwnd, UINT uIndex, LPSTR OutStr, BOOL bItemData);
36 int ListBoxSetItemData(HWND hwnd, UINT uIndex, DWORD ItemData);
37 int ListBoxDeleteString(HWND hwnd, UINT uIndex);
38 int ListBoxFindString(HWND hwnd, UINT nFirst, LPSTR MatchStr);
39 int ListBoxResetContent(HWND hwnd);
40 int ListBoxSetCurSel(HWND hwnd, WORD wIndex);
41 int ListBoxSetSel(HWND hwnd, WORD wIndex, WORD state);
42 int ListBoxGetSel(HWND hwnd, WORD wIndex);
43 int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec);
44 int ListBoxGetItemRect(HWND hwnd, WORD wIndex, LPRECT rect);
45 int ListBoxSetItemHeight(HWND hwnd, WORD wIndex, long height);
46 int ListBoxDefaultItem(HWND hwnd, WND *wndPtr,
47 LPHEADLIST lphl, LPLISTSTRUCT lpls);
48 int ListBoxFindNextMatch(HWND hwnd, WORD wChar);
49 int ListMaxFirstVisible(LPHEADLIST lphl);
51 #define HasStrings(wndPtr) ( \
52 ( ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) != LBS_OWNERDRAWFIXED) && \
53 ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) != LBS_OWNERDRAWVARIABLE) ) || \
54 ((wndPtr->dwStyle & LBS_HASSTRINGS) == LBS_HASSTRINGS) )
56 #define LIST_HEAP_ALLOC(lphl,f,size) ((int)HEAP_Alloc(&lphl->Heap,f,size) & 0xffff)
57 #define LIST_HEAP_FREE(lphl,handle) (HEAP_Free(&lphl->Heap,LIST_HEAP_ADDR(lphl,handle)))
58 #define LIST_HEAP_ADDR(lphl,handle) \
59 ((void *)((handle) ? ((handle) | ((int)lphl->Heap & 0xffff0000)) : 0))
60 #define LIST_HEAP_SIZE 0x10000
62 /***********************************************************************
63 * ListBoxWndProc
65 LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
67 WND *wndPtr;
68 LPHEADLIST lphl;
69 HWND hWndCtl;
70 WORD wRet;
71 LONG lRet;
72 RECT rect;
73 int y;
74 CREATESTRUCT *createStruct;
75 static RECT rectsel;
76 switch(message) {
77 case WM_CREATE:
78 CreateListBoxStruct(hwnd);
79 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
80 dprintf_listbox(stddeb,"ListBox WM_CREATE %p !\n", lphl);
81 if (lphl == NULL) return 0;
82 createStruct = (CREATESTRUCT *)lParam;
83 if (HIWORD(createStruct->lpCreateParams) != 0)
84 lphl->hWndLogicParent = (HWND)HIWORD(createStruct->lpCreateParams);
85 else
86 lphl->hWndLogicParent = GetParent(hwnd);
87 lphl->hFont = GetStockObject(SYSTEM_FONT);
88 lphl->ColumnsWidth = wndPtr->rectClient.right - wndPtr->rectClient.left;
89 SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
90 SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
91 if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) {
93 return 0;
94 case WM_DESTROY:
95 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
96 if (lphl == NULL) return 0;
97 ListBoxResetContent(hwnd);
98 /* XXX need to free lphl->Heap */
99 free(lphl);
100 *((LPHEADLIST *)&wndPtr->wExtra[1]) = 0;
101 dprintf_listbox(stddeb,"ListBox WM_DESTROY %p !\n", lphl);
102 return 0;
104 case WM_VSCROLL:
105 dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
106 wParam, lParam);
107 lphl = ListBoxGetStorageHeader(hwnd);
108 if (lphl == NULL) return 0;
109 y = lphl->FirstVisible;
110 switch(wParam) {
111 case SB_LINEUP:
112 if (lphl->FirstVisible > 1)
113 lphl->FirstVisible--;
114 break;
115 case SB_LINEDOWN:
116 if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
117 lphl->FirstVisible++;
118 break;
119 case SB_PAGEUP:
120 if (lphl->FirstVisible > 1)
121 lphl->FirstVisible -= lphl->ItemsVisible;
122 break;
123 case SB_PAGEDOWN:
124 if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
125 lphl->FirstVisible += lphl->ItemsVisible;
126 break;
127 case SB_THUMBTRACK:
128 lphl->FirstVisible = LOWORD(lParam);
129 break;
131 if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
132 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
133 lphl->FirstVisible = ListMaxFirstVisible(lphl);
134 if (y != lphl->FirstVisible) {
135 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
136 InvalidateRect(hwnd, NULL, TRUE);
137 UpdateWindow(hwnd);
139 return 0;
141 case WM_HSCROLL:
142 dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
143 wParam, lParam);
144 lphl = ListBoxGetStorageHeader(hwnd);
145 if (lphl == NULL) return 0;
146 y = lphl->FirstVisible;
147 switch(wParam) {
148 case SB_LINEUP:
149 if (lphl->FirstVisible > 1)
150 lphl->FirstVisible -= lphl->ItemsPerColumn;
151 break;
152 case SB_LINEDOWN:
153 if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
154 lphl->FirstVisible += lphl->ItemsPerColumn;
155 break;
156 case SB_PAGEUP:
157 if (lphl->FirstVisible > 1 && lphl->ItemsPerColumn != 0)
158 lphl->FirstVisible -= lphl->ItemsVisible /
159 lphl->ItemsPerColumn * lphl->ItemsPerColumn;
160 break;
161 case SB_PAGEDOWN:
162 if (lphl->FirstVisible < ListMaxFirstVisible(lphl) &&
163 lphl->ItemsPerColumn != 0)
164 lphl->FirstVisible += lphl->ItemsVisible /
165 lphl->ItemsPerColumn * lphl->ItemsPerColumn;
166 break;
167 case SB_THUMBTRACK:
168 lphl->FirstVisible = lphl->ItemsPerColumn *
169 (LOWORD(lParam) - 1) + 1;
170 break;
172 if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
173 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
174 lphl->FirstVisible = ListMaxFirstVisible(lphl);
175 if (lphl->ItemsPerColumn != 0) {
176 lphl->FirstVisible = lphl->FirstVisible /
177 lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
178 if (y != lphl->FirstVisible) {
179 SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible /
180 lphl->ItemsPerColumn + 1, TRUE);
181 InvalidateRect(hwnd, NULL, TRUE);
182 UpdateWindow(hwnd);
185 return 0;
187 case WM_LBUTTONDOWN:
188 SetFocus(hwnd);
189 SetCapture(hwnd);
190 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
191 if (lphl == NULL) return 0;
192 lphl->PrevFocused = lphl->ItemFocused;
193 y = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
194 if (y==-1)
195 return 0;
196 if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
197 lphl->ItemFocused = y;
198 wRet = ListBoxGetSel(hwnd, y);
199 ListBoxSetSel(hwnd, y, !wRet);
201 else {
202 ListBoxSetCurSel(hwnd, y);
203 if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
204 SendMessage(lphl->hWndLogicParent, WM_COMMAND,
205 wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
207 ListBoxGetItemRect(hwnd, y, &rectsel);
208 InvalidateRect(hwnd, NULL, TRUE);
209 UpdateWindow(hwnd);
210 return 0;
211 case WM_LBUTTONUP:
212 ReleaseCapture();
213 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
214 if (lphl == NULL) return 0;
215 if (lphl->PrevFocused != lphl->ItemFocused)
216 SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
217 MAKELONG(hwnd, LBN_SELCHANGE));
218 return 0;
219 case WM_RBUTTONUP:
220 case WM_LBUTTONDBLCLK:
221 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
222 if (lphl == NULL) return 0;
223 SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
224 MAKELONG(hwnd, LBN_DBLCLK));
225 return 0;
226 case WM_MOUSEMOVE:
227 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
228 if (lphl == NULL) return 0;
229 if ((wParam & MK_LBUTTON) != 0) {
230 y = HIWORD(lParam);
231 if (y < 4) {
232 if (lphl->FirstVisible > 1) {
233 lphl->FirstVisible--;
234 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
235 InvalidateRect(hwnd, NULL, TRUE);
236 UpdateWindow(hwnd);
237 break;
240 GetClientRect(hwnd, &rect);
241 if (y > (rect.bottom - 4)) {
242 if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
243 lphl->FirstVisible++;
244 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
245 InvalidateRect(hwnd, NULL, TRUE);
246 UpdateWindow(hwnd);
247 break;
250 if ((y > 0) && (y < (rect.bottom - 4))) {
251 if ((y < rectsel.top) || (y > rectsel.bottom)) {
252 wRet = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
253 if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
254 lphl->ItemFocused = wRet;
256 else {
257 ListBoxSetCurSel(hwnd, wRet);
258 if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
259 SendMessage(lphl->hWndLogicParent, WM_COMMAND,
260 wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
262 ListBoxGetItemRect(hwnd, wRet, &rectsel);
263 InvalidateRect(hwnd, NULL, TRUE);
264 UpdateWindow(hwnd);
268 break;
269 case WM_KEYDOWN:
270 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
271 if (lphl == NULL) return 0;
272 switch(wParam) {
273 case VK_TAB:
274 hWndCtl = GetNextDlgTabItem(lphl->hWndLogicParent,
275 hwnd, !(GetKeyState(VK_SHIFT) < 0));
276 SetFocus(hWndCtl);
277 if(debugging_listbox){
278 if ((GetKeyState(VK_SHIFT) < 0))
279 dprintf_listbox(stddeb,"ListBox PreviousDlgTabItem %04X !\n", hWndCtl);
280 else
281 dprintf_listbox(stddeb,"ListBox NextDlgTabItem %04X !\n", hWndCtl);
283 break;
284 case VK_HOME:
285 lphl->ItemFocused = 0;
286 break;
287 case VK_END:
288 lphl->ItemFocused = lphl->ItemsCount - 1;
289 break;
290 case VK_LEFT:
291 if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
292 lphl->ItemFocused -= lphl->ItemsPerColumn;
294 break;
295 case VK_UP:
296 lphl->ItemFocused--;
297 break;
298 case VK_RIGHT:
299 if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
300 lphl->ItemFocused += lphl->ItemsPerColumn;
302 break;
303 case VK_DOWN:
304 lphl->ItemFocused++;
305 break;
306 case VK_PRIOR:
307 lphl->ItemFocused -= lphl->ItemsVisible;
308 break;
309 case VK_NEXT:
310 lphl->ItemFocused += lphl->ItemsVisible;
311 break;
312 case VK_SPACE:
313 wRet = ListBoxGetSel(hwnd, lphl->ItemFocused);
314 ListBoxSetSel(hwnd, lphl->ItemFocused, !wRet);
315 break;
316 default:
317 ListBoxFindNextMatch(hwnd, wParam);
318 return 0;
320 if (lphl->ItemFocused < 0) lphl->ItemFocused = 0;
321 if (lphl->ItemFocused >= lphl->ItemsCount)
322 lphl->ItemFocused = lphl->ItemsCount - 1;
323 lphl->FirstVisible = lphl->ItemFocused / lphl->ItemsVisible *
324 lphl->ItemsVisible + 1;
325 if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
326 if ((wndPtr->dwStyle & LBS_MULTIPLESEL) != LBS_MULTIPLESEL) {
327 ListBoxSetCurSel(hwnd, lphl->ItemFocused);
328 if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
329 SendMessage(lphl->hWndLogicParent, WM_COMMAND,
330 wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
332 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
333 InvalidateRect(hwnd, NULL, TRUE);
334 UpdateWindow(hwnd);
335 break;
336 case WM_SETFONT:
337 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
338 if (lphl == NULL) return 0;
339 if (wParam == 0)
340 lphl->hFont = GetStockObject(SYSTEM_FONT);
341 else
342 lphl->hFont = wParam;
343 if (wParam == 0) break;
344 break;
345 case WM_SETREDRAW:
346 dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd=%04X w=%04X !\n", hwnd, wParam);
347 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
348 if (lphl == NULL) return 0;
349 lphl->bRedrawFlag = wParam;
350 break;
351 case WM_PAINT:
352 wndPtr = WIN_FindWndPtr(hwnd);
353 if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) {
354 OwnerDrawListBox(hwnd);
355 break;
357 if ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) {
358 OwnerDrawListBox(hwnd);
359 break;
361 StdDrawListBox(hwnd);
362 break;
363 case WM_SETFOCUS:
364 dprintf_listbox(stddeb,"ListBox WM_SETFOCUS !\n");
365 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
366 break;
367 case WM_KILLFOCUS:
368 dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS !\n");
369 InvalidateRect(hwnd, NULL, TRUE);
370 UpdateWindow(hwnd);
371 break;
373 case LB_RESETCONTENT:
374 dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
375 ListBoxResetContent(hwnd);
376 return 0;
377 case LB_DIR:
378 dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
379 wRet = ListBoxDirectory(hwnd, wParam, (LPSTR)lParam);
380 InvalidateRect(hwnd, NULL, TRUE);
381 UpdateWindow(hwnd);
382 return wRet;
383 case LB_ADDSTRING:
384 wRet = ListBoxAddString(hwnd, (LPSTR)lParam);
385 return wRet;
386 case LB_GETTEXT:
387 dprintf_listbox(stddeb, "LB_GETTEXT wParam=%d\n",wParam);
388 wRet = ListBoxGetText(hwnd, wParam, (LPSTR)lParam, FALSE);
389 return wRet;
390 case LB_INSERTSTRING:
391 wRet = ListBoxInsertString(hwnd, wParam, (LPSTR)lParam);
392 return wRet;
393 case LB_DELETESTRING:
394 wRet = ListBoxDeleteString(hwnd, wParam);
395 return wRet;
396 case LB_FINDSTRING:
397 wRet = ListBoxFindString(hwnd, wParam, (LPSTR)lParam);
398 return wRet;
399 case LB_GETCARETINDEX:
400 return wRet;
401 case LB_GETCOUNT:
402 lphl = ListBoxGetStorageHeader(hwnd);
403 return lphl->ItemsCount;
404 case LB_GETCURSEL:
405 lphl = ListBoxGetStorageHeader(hwnd);
406 dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %u !\n",
407 lphl->ItemFocused);
408 return lphl->ItemFocused;
409 case LB_GETHORIZONTALEXTENT:
410 return wRet;
411 case LB_GETITEMDATA:
412 dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
413 lRet = ListBoxGetText(hwnd, wParam, (LPSTR)lParam, TRUE);
414 return lRet;
415 case LB_GETITEMHEIGHT:
416 ListBoxGetItemRect(hwnd, wParam, &rect);
417 return (rect.bottom - rect.top);
418 case LB_GETITEMRECT:
419 ListBoxGetItemRect(hwnd, wParam, (LPRECT)lParam);
420 return 0;
421 case LB_GETSEL:
422 wRet = ListBoxGetSel(hwnd, wParam);
423 return wRet;
424 case LB_GETSELCOUNT:
425 lphl = ListBoxGetStorageHeader(hwnd);
426 if (lphl == NULL) return LB_ERR;
427 return lphl->SelCount;
428 case LB_GETSELITEMS:
429 return wRet;
430 case LB_GETTEXTLEN:
431 return wRet;
432 case LB_GETTOPINDEX:
433 lphl = ListBoxGetStorageHeader(hwnd);
434 if (lphl == NULL) return LB_ERR;
435 return lphl->FirstVisible;
436 case LB_SELECTSTRING:
437 return wRet;
438 case LB_SELITEMRANGE:
439 return wRet;
440 case LB_SETCARETINDEX:
441 return wRet;
442 case LB_SETCOLUMNWIDTH:
443 lphl = ListBoxGetStorageHeader(hwnd);
444 if (lphl == NULL) return LB_ERR;
445 lphl->ColumnsWidth = wParam;
446 break;
447 case LB_SETHORIZONTALEXTENT:
448 return wRet;
449 case LB_SETITEMDATA:
450 dprintf_listbox(stddeb, "LB_SETITEMDATA wParam=%x lParam=%lx\n", wParam, lParam);
451 wRet = ListBoxSetItemData(hwnd, wParam, lParam);
452 return wRet;
453 case LB_SETTABSTOPS:
454 lphl = ListBoxGetStorageHeader(hwnd);
455 if (lphl == NULL) return LB_ERR;
456 lphl->FirstVisible = wParam;
457 return 0;
458 case LB_SETCURSEL:
459 dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n",
460 wParam);
461 wRet = ListBoxSetCurSel(hwnd, wParam);
462 InvalidateRect(hwnd, NULL, TRUE);
463 UpdateWindow(hwnd);
464 return wRet;
465 case LB_SETSEL:
466 dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
467 wRet = ListBoxSetSel(hwnd, LOWORD(lParam), wParam);
468 InvalidateRect(hwnd, NULL, TRUE);
469 UpdateWindow(hwnd);
470 return wRet;
471 case LB_SETTOPINDEX:
472 dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
473 wParam);
474 lphl = ListBoxGetStorageHeader(hwnd);
475 lphl->FirstVisible = wParam;
476 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
477 InvalidateRect(hwnd, NULL, TRUE);
478 UpdateWindow(hwnd);
479 break;
480 case LB_SETITEMHEIGHT:
481 dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
482 wRet = ListBoxSetItemHeight(hwnd, wParam, lParam);
483 return wRet;
485 default:
486 return DefWindowProc( hwnd, message, wParam, lParam );
488 return 0;
492 LPHEADLIST ListBoxGetWindowAndStorage(HWND hwnd, WND **wndPtr)
494 WND *Ptr;
495 LPHEADLIST lphl;
496 *(wndPtr) = Ptr = WIN_FindWndPtr(hwnd);
497 lphl = *((LPHEADLIST *)&Ptr->wExtra[1]);
498 return lphl;
502 LPHEADLIST ListBoxGetStorageHeader(HWND hwnd)
504 WND *wndPtr;
505 LPHEADLIST lphl;
506 wndPtr = WIN_FindWndPtr(hwnd);
507 lphl = *((LPHEADLIST *)&wndPtr->wExtra[1]);
508 return lphl;
512 void StdDrawListBox(HWND hwnd)
514 WND *wndPtr;
515 LPHEADLIST lphl;
516 LPLISTSTRUCT lpls;
517 PAINTSTRUCT ps;
518 HBRUSH hBrush;
519 int OldBkMode;
520 DWORD dwOldTextColor;
521 HDC hdc;
522 RECT rect;
523 int i, h, h2, maxwidth, ipc;
524 h = 0;
525 hdc = BeginPaint( hwnd, &ps );
526 if (!IsWindowVisible(hwnd)) {
527 EndPaint( hwnd, &ps );
528 return;
530 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
531 if (lphl == NULL) goto EndOfPaint;
532 if (!lphl->bRedrawFlag) goto EndOfPaint;
533 SelectObject(hdc, lphl->hFont);
534 hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
535 MAKELONG(hwnd, CTLCOLOR_LISTBOX));
536 if (hBrush == (HBRUSH)NULL) hBrush = GetStockObject(WHITE_BRUSH);
537 GetClientRect(hwnd, &rect);
538 FillRect(hdc, &rect, hBrush);
539 maxwidth = rect.right;
540 rect.right = lphl->ColumnsWidth;
541 if (lphl->ItemsCount == 0) goto EndOfPaint;
542 lpls = lphl->lpFirst;
543 if (lpls == NULL) goto EndOfPaint;
544 lphl->ItemsVisible = 0;
545 lphl->ItemsPerColumn = ipc = 0;
546 for(i = 1; i <= lphl->ItemsCount; i++) {
547 if (i >= lphl->FirstVisible) {
548 if (lpls == NULL) break;
549 if ((h + lpls->dis.rcItem.bottom - lpls->dis.rcItem.top) > rect.bottom) {
550 if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
551 lphl->ItemsPerColumn = max(lphl->ItemsPerColumn, ipc);
552 ipc = 0;
553 h = 0;
554 rect.left += lphl->ColumnsWidth;
555 rect.right += lphl->ColumnsWidth;
556 if (rect.left > maxwidth) break;
558 else
559 break;
561 h2 = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
562 lpls->dis.rcItem.top = h;
563 lpls->dis.rcItem.bottom = h + h2;
564 lpls->dis.rcItem.left = rect.left;
565 lpls->dis.rcItem.right = rect.right;
566 OldBkMode = SetBkMode(hdc, TRANSPARENT);
567 if (lpls->dis.itemState != 0) {
568 dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
569 FillRect(hdc, &lpls->dis.rcItem, GetStockObject(BLACK_BRUSH));
571 TextOut(hdc, rect.left + 5, h + 2, (char *)lpls->itemText,
572 strlen((char *)lpls->itemText));
573 if (lpls->dis.itemState != 0) {
574 SetTextColor(hdc, dwOldTextColor);
576 SetBkMode(hdc, OldBkMode);
577 if ((lphl->ItemFocused == i - 1) && GetFocus() == hwnd) {
578 DrawFocusRect(hdc, &lpls->dis.rcItem);
580 h += h2;
581 lphl->ItemsVisible++;
582 ipc++;
584 if (lpls->lpNext == NULL) goto EndOfPaint;
585 lpls = (LPLISTSTRUCT)lpls->lpNext;
587 EndOfPaint:
588 EndPaint( hwnd, &ps );
593 void OwnerDrawListBox(HWND hwnd)
595 WND *wndPtr,*ParentWndPtr;
596 LPHEADLIST lphl;
597 LPLISTSTRUCT lpls;
598 PAINTSTRUCT ps;
599 HBRUSH hBrush;
600 HWND hWndParent;
601 DWORD itemData;
602 HDC hdc;
603 RECT rect;
604 int i, h, h2, maxwidth;
605 h = 0;
606 hdc = BeginPaint(hwnd, &ps);
607 if (!IsWindowVisible(hwnd)) {
608 EndPaint( hwnd, &ps );
609 return;
611 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
612 if (lphl == NULL) goto EndOfPaint;
613 if (!lphl->bRedrawFlag) goto EndOfPaint;
614 hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
615 MAKELONG(hwnd, CTLCOLOR_LISTBOX));
616 if (hBrush == (HBRUSH)NULL) hBrush = GetStockObject(WHITE_BRUSH);
617 GetClientRect(hwnd, &rect);
618 FillRect(hdc, &rect, hBrush);
619 maxwidth = rect.right;
620 rect.right = lphl->ColumnsWidth;
621 if (lphl->ItemsCount == 0) goto EndOfPaint;
622 lpls = lphl->lpFirst;
623 if (lpls == NULL) goto EndOfPaint;
624 lphl->ItemsVisible = 0;
625 for (i = 1; i <= lphl->ItemsCount; i++) {
626 if (i >= lphl->FirstVisible) {
627 lpls->dis.hDC = hdc;
628 lpls->dis.hwndItem = hwnd;
629 lpls->dis.CtlType = ODT_LISTBOX;
630 lpls->dis.itemID = i - 1;
631 if ((!lpls->dis.CtlID) && (lphl->hWndLogicParent)) {
632 ParentWndPtr = WIN_FindWndPtr(lphl->hWndLogicParent);
633 lpls->dis.CtlID = ParentWndPtr->wIDmenu;
635 h2 = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
636 lpls->dis.rcItem.top = h;
637 lpls->dis.rcItem.bottom = h + h2;
638 lpls->dis.rcItem.left = rect.left;
639 lpls->dis.rcItem.right = rect.right;
640 lpls->dis.itemAction = ODA_DRAWENTIRE;
641 /* if (lpls->dis.itemState != 0) {
642 lpls->dis.itemAction |= ODA_SELECT;
644 if (lphl->ItemFocused == i - 1) {
645 lpls->dis.itemAction |= ODA_FOCUS;
647 dprintf_listbox(stddeb,"LBOX WM_DRAWITEM #%d left=%d top=%d right=%d bottom=%d !\n",
648 i-1, lpls->dis.rcItem.left, lpls->dis.rcItem.top,
649 lpls->dis.rcItem.right, lpls->dis.rcItem.bottom);
650 dprintf_listbox(stddeb,"LBOX WM_DRAWITEM Parent=%X &dis=%lX CtlID=%u !\n",
651 hWndParent, (LONG)&lpls->dis, lpls->dis.CtlID);
652 dprintf_listbox(stddeb,"LBOX WM_DRAWITEM %08lX!\n",lpls->dis.itemData);
653 if (HasStrings(wndPtr))
654 dprintf_listbox(stddeb," '%s'\n",lpls->itemText);
655 if (HasStrings(wndPtr)) {
656 itemData = lpls->dis.itemData;
657 lpls->dis.itemData = (DWORD)lpls->itemText;
659 SendMessage(lphl->hWndLogicParent, WM_DRAWITEM,
660 i-1, (LPARAM)&lpls->dis);
661 if (HasStrings(wndPtr))
662 lpls->dis.itemData = itemData;
664 /* if (lpls->dis.itemState != 0) {
665 InvertRect(hdc, &lpls->dis.rcItem);
666 } */
667 h += h2;
668 lphl->ItemsVisible++;
669 /* if (h > rect.bottom) goto EndOfPaint;*/
671 if (lpls->lpNext == NULL) goto EndOfPaint;
672 lpls = (LPLISTSTRUCT)lpls->lpNext;
674 EndOfPaint:
675 EndPaint( hwnd, &ps );
680 int ListBoxFindMouse(HWND hwnd, int X, int Y)
682 WND *wndPtr;
683 LPHEADLIST lphl;
684 LPLISTSTRUCT lpls;
685 RECT rect;
686 int i, h, h2, w, w2;
687 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
688 if (lphl == NULL) return LB_ERR;
689 if (lphl->ItemsCount == 0) return LB_ERR;
690 lpls = lphl->lpFirst;
691 if (lpls == NULL) return LB_ERR;
692 GetClientRect(hwnd, &rect);
693 h = w2 = 0;
694 w = lphl->ColumnsWidth;
695 for(i = 1; i <= lphl->ItemsCount; i++) {
696 if (i >= lphl->FirstVisible) {
697 h2 = h;
698 h += lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
699 if ((Y > h2) && (Y < h) &&
700 (X > w2) && (X < w)) return(i - 1);
701 if (h > rect.bottom) {
702 if ((wndPtr->dwStyle & LBS_MULTICOLUMN) != LBS_MULTICOLUMN) return LB_ERR;
703 h = 0;
704 w2 = w;
705 w += lphl->ColumnsWidth;
706 if (w2 > rect.right) return LB_ERR;
709 if (lpls->lpNext == NULL) return LB_ERR;
710 lpls = (LPLISTSTRUCT)lpls->lpNext;
712 return(LB_ERR);
717 int CreateListBoxStruct(HWND hwnd)
719 WND *wndPtr;
720 LPHEADLIST lphl;
721 int HeapHandle;
722 void *HeapBase;
723 wndPtr = WIN_FindWndPtr(hwnd);
724 lphl = (LPHEADLIST)malloc(sizeof(HEADLIST));
725 lphl->lpFirst = NULL;
726 *((LPHEADLIST *)&wndPtr->wExtra[1]) = lphl; /* HEAD of List */
727 lphl->ItemsCount = 0;
728 lphl->ItemsVisible = 0;
729 lphl->FirstVisible = 1;
730 lphl->ColumnsVisible = 1;
731 lphl->ItemsPerColumn = 0;
732 lphl->StdItemHeight = 15;
733 lphl->ItemFocused = 0;
734 lphl->PrevFocused = 0;
735 lphl->SelCount = 0;
736 lphl->DrawCtlType = ODT_LISTBOX;
737 lphl->bRedrawFlag = TRUE;
738 HeapHandle = GlobalAlloc(GMEM_FIXED, LIST_HEAP_SIZE);
739 HeapBase = GlobalLock(HeapHandle);
740 HEAP_Init(&lphl->Heap, HeapBase, LIST_HEAP_SIZE);
741 return TRUE;
745 void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls)
747 MEASUREITEMSTRUCT *lpmeasure;
748 HANDLE hTemp = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(MEASUREITEMSTRUCT));
749 lpmeasure = (MEASUREITEMSTRUCT *) USER_HEAP_ADDR(hTemp);
750 if (lpmeasure == NULL) {
751 fprintf(stderr,"ListBoxAskMeasure() // Bad allocation of Measure struct !\n");
752 return;
754 lpmeasure->CtlType = ODT_LISTBOX;
755 lpmeasure->CtlID = wndPtr->wIDmenu;
756 lpmeasure->itemID = lpls->dis.itemID;
757 lpmeasure->itemWidth = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
758 lpmeasure->itemHeight = 0;
759 if (HasStrings(wndPtr))
760 lpmeasure->itemData = (DWORD)lpls->itemText;
761 else
762 lpmeasure->itemData = lpls->dis.itemData;
763 SendMessage(lphl->hWndLogicParent, WM_MEASUREITEM, 0, (DWORD)lpmeasure);
764 lpls->dis.rcItem.right = lpls->dis.rcItem.left + lpmeasure->itemWidth;
765 lpls->dis.rcItem.bottom = lpls->dis.rcItem.top + lpmeasure->itemHeight;
766 USER_HEAP_FREE(hTemp);
770 int ListBoxAddString(HWND hwnd, LPSTR newstr)
772 LPHEADLIST lphl;
773 UINT pos = (UINT) -1;
774 WND *wndPtr;
776 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
777 if (lphl == NULL) return LB_ERR;
778 if (HasStrings(wndPtr) && (wndPtr->dwStyle & LBS_SORT)) {
779 LPLISTSTRUCT lpls = lphl->lpFirst;
780 for (pos = 0; lpls; lpls = lpls->lpNext, pos++)
781 if (strcmp(lpls->itemText, newstr) >= 0)
782 break;
784 return ListBoxInsertString(hwnd, pos, newstr);
787 int ListBoxInsertString(HWND hwnd, UINT uIndex, LPSTR newstr)
789 WND *wndPtr;
790 LPHEADLIST lphl;
791 LPLISTSTRUCT *lppls, lplsnew;
792 HANDLE hItem;
793 HANDLE hStr;
794 LPSTR str;
795 UINT Count;
797 dprintf_listbox(stddeb,"ListBoxInsertString(%04X, %d, %p);\n",
798 hwnd, uIndex, newstr);
800 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
801 if (lphl == NULL) return LB_ERR;
803 if (uIndex == (UINT)-1)
804 uIndex = lphl->ItemsCount;
805 if (uIndex > lphl->ItemsCount) return LB_ERR;
806 lppls = (LPLISTSTRUCT *) &lphl->lpFirst;
808 for(Count = 0; Count < uIndex; Count++) {
809 if (*lppls == NULL) return LB_ERR;
810 lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
813 hItem = LIST_HEAP_ALLOC(lphl, GMEM_MOVEABLE, sizeof(LISTSTRUCT));
814 lplsnew = (LPLISTSTRUCT) LIST_HEAP_ADDR(lphl, hItem);
815 if (lplsnew == NULL) {
816 printf("ListBoxInsertString() // Bad allocation of new item !\n");
817 return LB_ERRSPACE;
819 ListBoxDefaultItem(hwnd, wndPtr, lphl, lplsnew);
820 lplsnew->hMem = hItem;
821 lplsnew->lpNext = *lppls;
822 *lppls = lplsnew;
823 lphl->ItemsCount++;
824 hStr = 0;
826 if (HasStrings(wndPtr)) {
827 hStr = LIST_HEAP_ALLOC(lphl, GMEM_MOVEABLE, strlen(newstr) + 1);
828 str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
829 if (str == NULL) return LB_ERRSPACE;
830 strcpy(str, newstr);
831 newstr = str;
832 lplsnew->itemText = str;
833 dprintf_listbox(stddeb,"ListBoxInsertString // LBS_HASSTRINGS after strcpy '%s'\n", str);
835 else {
836 lplsnew->itemText = NULL;
837 lplsnew->dis.itemData = (DWORD)newstr;
839 lplsnew->dis.itemID = lphl->ItemsCount;
840 lplsnew->hData = hStr;
841 if (((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) ||
842 ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED))
843 ListBoxAskMeasure(wndPtr, lphl, lplsnew);
844 SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl),
845 (lphl->FirstVisible != 1 && lphl->bRedrawFlag));
846 if (lphl->ItemsPerColumn != 0)
847 SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
848 lphl->ItemsPerColumn + 1,
849 (lphl->FirstVisible != 1 && lphl->bRedrawFlag));
850 if ((lphl->FirstVisible <= uIndex) &&
851 ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
852 InvalidateRect(hwnd, NULL, TRUE);
853 UpdateWindow(hwnd);
855 dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
856 return uIndex;
860 int ListBoxGetText(HWND hwnd, UINT uIndex, LPSTR OutStr, BOOL bItemData)
862 WND *wndPtr;
863 LPHEADLIST lphl;
864 LPLISTSTRUCT lpls;
865 UINT Count;
866 if ((!OutStr)&&(!bItemData))
867 fprintf(stderr, "ListBoxGetText // OutStr==NULL\n");
868 if (!bItemData) *OutStr=0;
869 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
870 if (lphl == NULL) return LB_ERR;
871 if (uIndex >= lphl->ItemsCount) return LB_ERR;
872 lpls = lphl->lpFirst;
873 if (lpls == NULL) return LB_ERR;
874 if (uIndex > lphl->ItemsCount) return LB_ERR;
875 for(Count = 0; Count < uIndex; Count++) {
876 if (lpls->lpNext == NULL) return LB_ERR;
877 lpls = (LPLISTSTRUCT)lpls->lpNext;
879 if (bItemData)
880 return lpls->dis.itemData;
881 if (!(HasStrings(wndPtr)) )
883 *((long *)OutStr) = lpls->dis.itemData;
884 return 4;
887 strcpy(OutStr, lpls->itemText);
888 return strlen(OutStr);
891 int ListBoxSetItemData(HWND hwnd, UINT uIndex, DWORD ItemData)
893 WND *wndPtr;
894 LPHEADLIST lphl;
895 LPLISTSTRUCT lpls;
896 UINT Count;
897 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
898 if (lphl == NULL) return LB_ERR;
899 if (uIndex >= lphl->ItemsCount) return LB_ERR;
900 lpls = lphl->lpFirst;
901 if (lpls == NULL) return LB_ERR;
902 if (uIndex > lphl->ItemsCount) return LB_ERR;
903 for(Count = 0; Count < uIndex; Count++) {
904 if (lpls->lpNext == NULL) return LB_ERR;
905 lpls = (LPLISTSTRUCT)lpls->lpNext;
907 lpls->dis.itemData = ItemData;
908 return 1;
912 int ListBoxDeleteString(HWND hwnd, UINT uIndex)
914 WND *wndPtr;
915 LPHEADLIST lphl;
916 LPLISTSTRUCT lpls, lpls2;
917 UINT Count;
918 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
919 if (lphl == NULL) return LB_ERR;
920 if (uIndex >= lphl->ItemsCount) return LB_ERR;
921 lpls = lphl->lpFirst;
922 if (lpls == NULL) return LB_ERR;
923 if (uIndex > lphl->ItemsCount) return LB_ERR;
924 for(Count = 1; Count < uIndex; Count++) {
925 if (lpls->lpNext == NULL) return LB_ERR;
926 lpls2 = lpls;
927 lpls = (LPLISTSTRUCT)lpls->lpNext;
929 lpls2->lpNext = (LPLISTSTRUCT)lpls->lpNext;
930 lphl->ItemsCount--;
931 if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
932 if (lpls->hMem != 0) LIST_HEAP_FREE(lphl, lpls->hMem);
933 SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
934 if (lphl->ItemsPerColumn != 0)
935 SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
936 lphl->ItemsPerColumn + 1, TRUE);
937 if ((lphl->FirstVisible <= uIndex) &&
938 ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
939 InvalidateRect(hwnd, NULL, TRUE);
940 UpdateWindow(hwnd);
942 return lphl->ItemsCount;
946 int ListBoxFindString(HWND hwnd, UINT nFirst, LPSTR MatchStr)
948 WND *wndPtr;
949 LPHEADLIST lphl;
950 LPLISTSTRUCT lpls;
951 UINT Count;
952 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
953 if (lphl == NULL) return LB_ERR;
954 if (nFirst > lphl->ItemsCount) return LB_ERR;
955 lpls = lphl->lpFirst;
956 if (lpls == NULL) return LB_ERR;
957 Count = 0;
958 while(lpls != NULL) {
959 if (HasStrings(wndPtr))
961 if (strcmp(lpls->itemText, MatchStr) == 0) return Count;
963 else
965 if (lpls->dis.itemData == (DWORD)MatchStr) return Count;
967 lpls = (LPLISTSTRUCT)lpls->lpNext;
968 Count++;
970 return LB_ERR;
974 int ListBoxResetContent(HWND hwnd)
976 WND *wndPtr;
977 LPHEADLIST lphl;
978 LPLISTSTRUCT lpls, lpls2;
979 UINT i;
980 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
981 if (lphl == NULL) return LB_ERR;
982 lpls = lphl->lpFirst;
983 if (lpls == NULL) return LB_ERR;
984 dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n",
985 lphl->ItemsCount);
986 for(i = 0; i <= lphl->ItemsCount; i++) {
987 lpls2 = lpls;
988 lpls = (LPLISTSTRUCT)lpls->lpNext;
989 if (i != 0) {
990 dprintf_listbox(stddeb,"ResetContent #%u\n", i);
991 if (lpls2->hData != 0 && lpls2->hData != lpls2->hMem)
992 LIST_HEAP_FREE(lphl, lpls2->hData);
993 if (lpls2->hMem != 0) LIST_HEAP_FREE(lphl, lpls2->hMem);
995 if (lpls == NULL) break;
997 lphl->lpFirst = NULL;
998 lphl->FirstVisible = 1;
999 lphl->ItemsCount = 0;
1000 lphl->ItemFocused = -1;
1001 lphl->PrevFocused = -1;
1002 if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
1003 SendMessage(lphl->hWndLogicParent, WM_COMMAND,
1004 wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
1005 SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
1006 if (lphl->ItemsPerColumn != 0)
1007 SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
1008 lphl->ItemsPerColumn + 1, TRUE);
1009 InvalidateRect(hwnd, NULL, TRUE);
1010 UpdateWindow(hwnd);
1011 return TRUE;
1015 int ListBoxSetCurSel(HWND hwnd, WORD wIndex)
1017 WND *wndPtr;
1018 LPHEADLIST lphl;
1019 LPLISTSTRUCT lpls, lpls2;
1020 UINT i;
1021 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1022 if (lphl == NULL) return LB_ERR;
1023 lphl->ItemFocused = LB_ERR;
1024 if (wIndex >= lphl->ItemsCount) return LB_ERR;
1025 lpls = lphl->lpFirst;
1026 if (lpls == NULL) return LB_ERR;
1027 for(i = 0; i < lphl->ItemsCount; i++) {
1028 lpls2 = lpls;
1029 lpls = (LPLISTSTRUCT)lpls->lpNext;
1030 if (i == wIndex)
1031 lpls2->dis.itemState = 1;
1032 else
1033 if (lpls2->dis.itemState != 0)
1034 lpls2->dis.itemState = 0;
1035 if (lpls == NULL) break;
1037 lphl->ItemFocused = wIndex;
1038 if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
1039 SendMessage(lphl->hWndLogicParent, WM_COMMAND,
1040 wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
1041 return LB_ERR;
1046 int ListBoxSetSel(HWND hwnd, WORD wIndex, WORD state)
1048 LPHEADLIST lphl;
1049 LPLISTSTRUCT lpls, lpls2;
1050 UINT i;
1051 lphl = ListBoxGetStorageHeader(hwnd);
1052 if (lphl == NULL) return LB_ERR;
1053 if (wIndex >= lphl->ItemsCount) return LB_ERR;
1054 lpls = lphl->lpFirst;
1055 if (lpls == NULL) return LB_ERR;
1056 for(i = 0; i < lphl->ItemsCount; i++) {
1057 lpls2 = lpls;
1058 lpls = (LPLISTSTRUCT)lpls->lpNext;
1059 if ((i == wIndex) || (wIndex == (WORD)-1)) {
1060 lpls2->dis.itemState = state;
1061 break;
1063 if (lpls == NULL) break;
1065 return LB_ERR;
1069 int ListBoxGetSel(HWND hwnd, WORD wIndex)
1071 LPHEADLIST lphl;
1072 LPLISTSTRUCT lpls, lpls2;
1073 UINT i;
1074 lphl = ListBoxGetStorageHeader(hwnd);
1075 if (lphl == NULL) return LB_ERR;
1076 if (wIndex >= lphl->ItemsCount) return LB_ERR;
1077 lpls = lphl->lpFirst;
1078 if (lpls == NULL) return LB_ERR;
1079 for(i = 0; i < lphl->ItemsCount; i++) {
1080 lpls2 = lpls;
1081 lpls = (LPLISTSTRUCT)lpls->lpNext;
1082 if (i == wIndex) {
1083 return lpls2->dis.itemState;
1085 if (lpls == NULL) break;
1087 return LB_ERR;
1091 int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec)
1093 struct dosdirent *dp;
1094 int x, wRet = LB_OKAY;
1095 BOOL OldFlag;
1096 char temp[256];
1097 LPHEADLIST lphl;
1098 dprintf_listbox(stddeb,"ListBoxDirectory: %s, %4x\n",filespec,attrib);
1099 lphl = ListBoxGetStorageHeader(hwnd);
1100 if (lphl == NULL) return LB_ERR;
1101 if ((dp = (struct dosdirent *)DOS_opendir(filespec)) ==NULL) return 0;
1102 OldFlag = lphl->bRedrawFlag;
1103 lphl->bRedrawFlag = FALSE;
1104 while ((dp = (struct dosdirent *)DOS_readdir(dp))) {
1105 if (!dp->inuse) break;
1106 dprintf_listbox(stddeb,"ListBoxDirectory %p '%s' !\n", dp->filename, dp->filename);
1107 if (dp->attribute & FA_DIREC) {
1108 if (attrib & DDL_DIRECTORY &&
1109 strcmp(dp->filename, ".")) {
1110 sprintf(temp, "[%s]", dp->filename);
1111 if ( (wRet = ListBoxAddString(hwnd, temp)) == LB_ERR) break;
1114 else {
1115 if (attrib & DDL_EXCLUSIVE) {
1116 if (attrib & (DDL_READWRITE | DDL_READONLY | DDL_HIDDEN |
1117 DDL_SYSTEM) )
1118 if ( (wRet = ListBoxAddString(hwnd, dp->filename))
1119 == LB_ERR) break;
1121 else {
1122 if ( (wRet = ListBoxAddString(hwnd, dp->filename))
1123 == LB_ERR) break;
1127 DOS_closedir(dp);
1129 if (attrib & DDL_DRIVES) {
1130 for (x=0;x!=MAX_DOS_DRIVES;x++) {
1131 if (DOS_ValidDrive(x)) {
1132 sprintf(temp, "[-%c-]", 'a'+x);
1133 if ( (wRet = ListBoxAddString(hwnd, temp)) == LB_ERR) break;
1137 lphl->bRedrawFlag = OldFlag;
1138 if (OldFlag) {
1139 InvalidateRect(hwnd, NULL, TRUE);
1140 UpdateWindow(hwnd);
1142 dprintf_listbox(stddeb,"End of ListBoxDirectory !\n");
1143 return wRet;
1147 int ListBoxGetItemRect(HWND hwnd, WORD wIndex, LPRECT lprect)
1149 LPHEADLIST lphl;
1150 LPLISTSTRUCT lpls, lpls2;
1151 UINT i;
1152 lphl = ListBoxGetStorageHeader(hwnd);
1153 if (lphl == NULL) return LB_ERR;
1154 if (wIndex > lphl->ItemsCount) return LB_ERR;
1155 lpls = lphl->lpFirst;
1156 if (lpls == NULL) return LB_ERR;
1157 for(i = 0; i < lphl->ItemsCount; i++) {
1158 lpls2 = lpls;
1159 lpls = (LPLISTSTRUCT)lpls->lpNext;
1160 if (i == wIndex) {
1161 *(lprect) = lpls2->dis.rcItem;
1162 break;
1164 if (lpls == NULL) break;
1166 return LB_ERR;
1171 int ListBoxSetItemHeight(HWND hwnd, WORD wIndex, long height)
1173 LPHEADLIST lphl;
1174 LPLISTSTRUCT lpls, lpls2;
1175 UINT i;
1176 lphl = ListBoxGetStorageHeader(hwnd);
1177 if (lphl == NULL) return LB_ERR;
1178 if (wIndex > lphl->ItemsCount) return LB_ERR;
1179 lpls = lphl->lpFirst;
1180 if (lpls == NULL) return LB_ERR;
1181 for(i = 0; i < lphl->ItemsCount; i++) {
1182 lpls2 = lpls;
1183 lpls = (LPLISTSTRUCT)lpls->lpNext;
1184 if (i == wIndex) {
1185 lpls2->dis.rcItem.bottom = lpls2->dis.rcItem.top + (short)height;
1186 InvalidateRect(hwnd, NULL, TRUE);
1187 UpdateWindow(hwnd);
1188 break;
1190 if (lpls == NULL) break;
1192 return LB_ERR;
1199 int ListBoxDefaultItem(HWND hwnd, WND *wndPtr,
1200 LPHEADLIST lphl, LPLISTSTRUCT lpls)
1202 RECT rect;
1203 if (wndPtr == NULL || lphl == NULL || lpls == NULL) {
1204 fprintf(stderr,"ListBoxDefaultItem() // Bad Pointers !\n");
1205 return FALSE;
1207 GetClientRect(hwnd, &rect);
1208 SetRect(&lpls->dis.rcItem, 0, 0, rect.right, lphl->StdItemHeight);
1209 lpls->dis.CtlType = lphl->DrawCtlType;
1210 lpls->dis.CtlID = wndPtr->wIDmenu;
1211 lpls->dis.itemID = 0;
1212 lpls->dis.itemAction = 0;
1213 lpls->dis.itemState = 0;
1214 lpls->dis.hwndItem = hwnd;
1215 lpls->dis.hDC = 0;
1216 lpls->dis.itemData = 0;
1217 return TRUE;
1222 int ListBoxFindNextMatch(HWND hwnd, WORD wChar)
1224 WND *wndPtr;
1225 LPHEADLIST lphl;
1226 LPLISTSTRUCT lpls;
1227 UINT Count;
1228 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1229 if (lphl == NULL) return LB_ERR;
1230 lpls = lphl->lpFirst;
1231 if (lpls == NULL) return LB_ERR;
1232 if (wChar < ' ') return LB_ERR;
1233 if (((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) ||
1234 ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE)) {
1235 if ((wndPtr->dwStyle & LBS_HASSTRINGS) != LBS_HASSTRINGS) {
1236 return LB_ERR;
1239 Count = 0;
1240 while(lpls != NULL) {
1241 if (Count > lphl->ItemFocused) {
1242 if (*(lpls->itemText) == (char)wChar) {
1243 lphl->FirstVisible = Count - lphl->ItemsVisible / 2;
1244 if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
1245 if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
1246 lphl->ItemFocused = Count;
1248 else {
1249 ListBoxSetCurSel(hwnd, Count);
1251 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1252 InvalidateRect(hwnd, NULL, TRUE);
1253 UpdateWindow(hwnd);
1254 return Count;
1257 lpls = (LPLISTSTRUCT)lpls->lpNext;
1258 Count++;
1260 Count = 0;
1261 lpls = lphl->lpFirst;
1262 while(lpls != NULL) {
1263 if (*(lpls->itemText) == (char)wChar) {
1264 if (Count == lphl->ItemFocused) return LB_ERR;
1265 lphl->FirstVisible = Count - lphl->ItemsVisible / 2;
1266 if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
1267 if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
1268 lphl->ItemFocused = Count;
1270 else {
1271 ListBoxSetCurSel(hwnd, Count);
1273 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1274 InvalidateRect(hwnd, NULL, TRUE);
1275 UpdateWindow(hwnd);
1276 return Count;
1278 lpls = (LPLISTSTRUCT)lpls->lpNext;
1279 Count++;
1281 return LB_ERR;
1285 /************************************************************************
1286 * DlgDirSelect [USER.99]
1288 BOOL DlgDirSelect(HWND hDlg, LPSTR lpStr, int nIDLBox)
1290 fprintf(stdnimp,"DlgDirSelect(%04X, '%s', %d) \n", hDlg, lpStr, nIDLBox);
1291 return FALSE;
1295 /************************************************************************
1296 * DlgDirList [USER.100]
1298 int DlgDirList(HWND hDlg, LPSTR lpPathSpec,
1299 int nIDLBox, int nIDStat, WORD wType)
1301 HWND hWnd;
1302 int ret;
1303 dprintf_listbox(stddeb,"DlgDirList(%04X, '%s', %d, %d, %04X) \n",
1304 hDlg, lpPathSpec, nIDLBox, nIDStat, wType);
1305 if (nIDLBox)
1306 hWnd = GetDlgItem(hDlg, nIDLBox);
1307 else
1308 hWnd = 0;
1309 if (hWnd)
1310 ListBoxResetContent(hWnd);
1311 if (hWnd)
1312 ret=ListBoxDirectory(hWnd, wType, lpPathSpec);
1313 else
1314 ret=0;
1315 if (nIDStat)
1317 int drive;
1318 drive = DOS_GetDefaultDrive();
1319 SendDlgItemMessage(hDlg, nIDStat, WM_SETTEXT, 0,
1320 (LONG) DOS_GetCurrentDir(drive) );
1322 return ret;
1325 /* get the maximum value of lphl->FirstVisible */
1326 int ListMaxFirstVisible(LPHEADLIST lphl)
1328 int m = lphl->ItemsCount-lphl->ItemsVisible+1;
1329 return (m < 1) ? 1 : m;