Release 940614
[wine] / controls / listbox.c
1 /*
2  * Interface code to listbox widgets
3  *
4  * Copyright  Martin Ayotte, 1993
5  *
6  */
7
8 /*
9 #define DEBUG_LISTBOX
10 */
11
12 static char Copyright[] = "Copyright Martin Ayotte, 1993";
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include "windows.h"
19 #include "user.h"
20 #include "heap.h"
21 #include "win.h"
22 #include "msdos.h"
23 #include "wine.h"
24 #include "listbox.h"
25 #include "scroll.h"
26 #include "prototypes.h"
27
28 #define GMEM_ZEROINIT 0x0040
29
30
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);
41 int ListBoxDeleteString(HWND hwnd, UINT uIndex);
42 int ListBoxFindString(HWND hwnd, UINT nFirst, LPSTR MatchStr);
43 int ListBoxResetContent(HWND hwnd);
44 int ListBoxSetCurSel(HWND hwnd, WORD wIndex);
45 int ListBoxSetSel(HWND hwnd, WORD wIndex, WORD state);
46 int ListBoxGetSel(HWND hwnd, WORD wIndex);
47 int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec);
48 int ListBoxGetItemRect(HWND hwnd, WORD wIndex, LPRECT rect);
49 int ListBoxSetItemHeight(HWND hwnd, WORD wIndex, long height);
50 int ListBoxDefaultItem(HWND hwnd, WND *wndPtr, 
51         LPHEADLIST lphl, LPLISTSTRUCT lpls);
52 int ListBoxFindNextMatch(HWND hwnd, WORD wChar);
53
54
55 /***********************************************************************
56  *           ListBoxWndProc 
57  */
58 LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
59 {    
60         WND  *wndPtr;
61         LPHEADLIST  lphl;
62         HWND    hWndCtl;
63         WORD    wRet;
64         RECT    rect;
65         int             y;
66         CREATESTRUCT *createStruct;
67         static RECT rectsel;
68     switch(message) {
69         case WM_CREATE:
70                 CreateListBoxStruct(hwnd);
71                 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
72 #ifdef DEBUG_LISTBOX
73                 printf("ListBox WM_CREATE %lX !\n", lphl);
74 #endif
75                 if (lphl == NULL) return 0;
76                 createStruct = (CREATESTRUCT *)lParam;
77                 if (HIWORD(createStruct->lpCreateParams) != 0)
78                         lphl->hWndLogicParent = (HWND)HIWORD(createStruct->lpCreateParams);
79                 else
80                         lphl->hWndLogicParent = GetParent(hwnd);
81                 lphl->hFont = GetStockObject(SYSTEM_FONT);
82                 lphl->ColumnsWidth = wndPtr->rectClient.right - wndPtr->rectClient.left;
83                 if (wndPtr->dwStyle & WS_VSCROLL) {
84                         SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, TRUE);
85                         ShowScrollBar(hwnd, SB_VERT, FALSE);
86                         }
87                 if (wndPtr->dwStyle & WS_HSCROLL) {
88                         SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
89                         ShowScrollBar(hwnd, SB_HORZ, FALSE);
90                         }
91                 if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) {
92                         }
93                 return 0;
94         case WM_DESTROY:
95                 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
96                 if (lphl == NULL) return 0;
97                 ListBoxResetContent(hwnd);
98                 free(lphl);
99                 *((LPHEADLIST *)&wndPtr->wExtra[1]) = 0;
100 #ifdef DEBUG_LISTBOX
101                 printf("ListBox WM_DESTROY %lX !\n", lphl);
102 #endif
103                 return 0;
104
105         case WM_VSCROLL:
106 #ifdef DEBUG_LISTBOX
107                 printf("ListBox WM_VSCROLL w=%04X l=%08X !\n", wParam, lParam);
108 #endif
109                 lphl = ListBoxGetStorageHeader(hwnd);
110                 if (lphl == NULL) return 0;
111                 y = lphl->FirstVisible;
112                 switch(wParam) {
113                         case SB_LINEUP:
114                                 if (lphl->FirstVisible > 1)     
115                                         lphl->FirstVisible--;
116                                 break;
117                         case SB_LINEDOWN:
118                                 if (lphl->FirstVisible < lphl->ItemsCount)
119                                         lphl->FirstVisible++;
120                                 break;
121                         case SB_PAGEUP:
122                                 if (lphl->FirstVisible > 1)  
123                                         lphl->FirstVisible -= lphl->ItemsVisible;
124                                 break;
125                         case SB_PAGEDOWN:
126                                 if (lphl->FirstVisible < lphl->ItemsCount)  
127                                         lphl->FirstVisible += lphl->ItemsVisible;
128                                 break;
129                         case SB_THUMBTRACK:
130                                 lphl->FirstVisible = LOWORD(lParam);
131                                 break;
132                         }
133                 if (lphl->FirstVisible < 1)    lphl->FirstVisible = 1;
134                 if (lphl->FirstVisible > lphl->ItemsCount)
135                         lphl->FirstVisible = lphl->ItemsCount;
136                 if (y != lphl->FirstVisible) {
137                         SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
138                         InvalidateRect(hwnd, NULL, TRUE);
139                         UpdateWindow(hwnd);
140                         }
141                 return 0;
142         
143         case WM_HSCROLL:
144 #ifdef DEBUG_LISTBOX
145                 printf("ListBox WM_HSCROLL w=%04X l=%08X !\n", wParam, lParam);
146 #endif
147                 lphl = ListBoxGetStorageHeader(hwnd);
148                 if (lphl == NULL) return 0;
149                 y = lphl->FirstVisible;
150                 switch(wParam) {
151                         case SB_LINEUP:
152                                 if (lphl->FirstVisible > 1)
153                                         lphl->FirstVisible -= lphl->ItemsPerColumn;
154                                 break;
155                         case SB_LINEDOWN:
156                                 if (lphl->FirstVisible < lphl->ItemsCount)
157                                         lphl->FirstVisible += lphl->ItemsPerColumn;
158                                 break;
159                         case SB_PAGEUP:
160                                 if (lphl->FirstVisible > 1 && lphl->ItemsPerColumn != 0)  
161                                         lphl->FirstVisible -= lphl->ItemsVisible /
162                                         lphl->ItemsPerColumn * lphl->ItemsPerColumn;
163                                 break;
164                         case SB_PAGEDOWN:
165                                 if (lphl->FirstVisible < lphl->ItemsCount &&
166                                                         lphl->ItemsPerColumn != 0)  
167                                         lphl->FirstVisible += lphl->ItemsVisible /
168                                         lphl->ItemsPerColumn * lphl->ItemsPerColumn;
169                                 break;
170                         case SB_THUMBTRACK:
171                                 lphl->FirstVisible = lphl->ItemsPerColumn * 
172                                                                 (LOWORD(lParam) - 1) + 1;
173                                 break;
174                         }
175                 if (lphl->FirstVisible < 1)    lphl->FirstVisible = 1;
176                 if (lphl->FirstVisible > lphl->ItemsCount)
177                         lphl->FirstVisible = lphl->ItemsCount;
178                 if (lphl->ItemsPerColumn != 0) {
179                         lphl->FirstVisible = lphl->FirstVisible /
180                                 lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
181                         if (y != lphl->FirstVisible) {
182                                 SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible / 
183                                 lphl->ItemsPerColumn + 1, TRUE);
184                                 InvalidateRect(hwnd, NULL, TRUE);
185                                 UpdateWindow(hwnd);
186                                 }
187                         }
188                 return 0;
189         
190         case WM_LBUTTONDOWN:
191                 SetFocus(hwnd);
192                 SetCapture(hwnd);
193                 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
194                 if (lphl == NULL) return 0;
195                 lphl->PrevFocused = lphl->ItemFocused;
196                 y = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
197                 if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
198                     lphl->ItemFocused = y;
199                     wRet = ListBoxGetSel(hwnd, y);
200                     ListBoxSetSel(hwnd, y, !wRet);
201                     }
202                 else {
203                     ListBoxSetCurSel(hwnd, y);
204                     }
205                 ListBoxGetItemRect(hwnd, y, &rectsel);
206                 InvalidateRect(hwnd, NULL, TRUE);
207                 UpdateWindow(hwnd);
208                 return 0;
209         case WM_LBUTTONUP:
210                 ReleaseCapture();
211                 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
212                 if (lphl == NULL) return 0;
213                 if (lphl->PrevFocused != lphl->ItemFocused)
214                         SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
215                                                                                         MAKELONG(hwnd, LBN_SELCHANGE));
216                 return 0;
217         case WM_RBUTTONUP:
218         case WM_LBUTTONDBLCLK:
219                 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
220                 if (lphl == NULL) return 0;
221                 SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
222                                                                                 MAKELONG(hwnd, LBN_DBLCLK));
223                 printf("ListBox Send LBN_DBLCLK !\n");
224                 return 0;
225         case WM_MOUSEMOVE:
226                 if ((wParam & MK_LBUTTON) != 0) {
227                         y = HIWORD(lParam);
228                         if (y < 4) {
229                                 lphl = ListBoxGetStorageHeader(hwnd);
230                                 if (lphl == NULL) return 0;
231                                 if (lphl->FirstVisible > 1) {
232                                         lphl->FirstVisible--;
233                                         if (wndPtr->dwStyle & WS_VSCROLL)
234                                         SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
235                                         InvalidateRect(hwnd, NULL, TRUE);
236                                         UpdateWindow(hwnd);
237                                         break;
238                                         }
239                                 }
240                         GetClientRect(hwnd, &rect);
241                         if (y > (rect.bottom - 4)) {
242                                 lphl = ListBoxGetStorageHeader(hwnd);
243                                 if (lphl == NULL) return 0;
244                                 if (lphl->FirstVisible < lphl->ItemsCount) {
245                                         lphl->FirstVisible++;
246                                         if (wndPtr->dwStyle & WS_VSCROLL)
247                                         SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
248                                         InvalidateRect(hwnd, NULL, TRUE);
249                                         UpdateWindow(hwnd);
250                                         break;
251                                         }
252                                 }
253                         if ((y > 0) && (y < (rect.bottom - 4))) {
254                                 if ((y < rectsel.top) || (y > rectsel.bottom)) {
255                                         lphl = ListBoxGetStorageHeader(hwnd);
256                                         if (lphl == NULL) return 0;
257                                         wRet = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
258                                         if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
259                                                 lphl->ItemFocused = wRet;
260                                                 }
261                                         else {
262                                                 ListBoxSetCurSel(hwnd, wRet);
263                                                 }
264                                         ListBoxGetItemRect(hwnd, wRet, &rectsel);
265                                         InvalidateRect(hwnd, NULL, TRUE);
266                                         UpdateWindow(hwnd);
267                                         }
268                                 }
269                         }
270                 break;
271         case WM_KEYDOWN:
272                 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
273                 if (lphl == NULL) return 0;
274                 switch(wParam) {
275                         case VK_TAB:
276                                 hWndCtl = GetNextDlgTabItem(lphl->hWndLogicParent,
277                                         hwnd, !(GetKeyState(VK_SHIFT) < 0));
278                                 SetFocus(hWndCtl);
279                                 if ((GetKeyState(VK_SHIFT) < 0))
280                                         printf("ListBox PreviousDlgTabItem %04X !\n", hWndCtl);
281                                 else
282                                         printf("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;
293                                         }
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;
301                                         }
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;
319                         }
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                         }
329                 if (wndPtr->dwStyle & WS_VSCROLL)
330                         SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
331                 InvalidateRect(hwnd, NULL, TRUE);
332                 UpdateWindow(hwnd);
333                 break;
334         case WM_SETFONT:
335                 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
336                 if (lphl == NULL) return 0;
337                 if (wParam == 0)
338                         lphl->hFont = GetStockObject(SYSTEM_FONT);
339                 else
340                         lphl->hFont = wParam;
341                 if (wParam == 0) break;
342         case WM_PAINT:
343                 wndPtr = WIN_FindWndPtr(hwnd);
344                 if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) {
345                         OwnerDrawListBox(hwnd);
346                         break;
347                         }
348                 if ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) {
349                         OwnerDrawListBox(hwnd);
350                         break;
351                         }
352                 StdDrawListBox(hwnd);
353                 break;
354         case WM_SETFOCUS:
355 #ifdef DEBUG_LISTBOX
356                 printf("ListBox WM_SETFOCUS !\n");
357 #endif
358                 lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
359                 break;
360         case WM_KILLFOCUS:
361 #ifdef DEBUG_LISTBOX
362                 printf("ListBox WM_KILLFOCUS !\n");
363 #endif
364                 InvalidateRect(hwnd, NULL, TRUE);
365                 UpdateWindow(hwnd);
366                 break;
367
368     case LB_RESETCONTENT:
369 #ifdef DEBUG_LISTBOX
370                 printf("ListBox LB_RESETCONTENT !\n");
371 #endif
372                 ListBoxResetContent(hwnd);
373                 return 0;
374     case LB_DIR:
375 #ifdef DEBUG_LISTBOX
376                 printf("ListBox LB_DIR !\n");
377 #endif
378                 wRet = ListBoxDirectory(hwnd, wParam, (LPSTR)lParam);
379                 InvalidateRect(hwnd, NULL, TRUE);
380                 UpdateWindow(hwnd);
381                 return wRet;
382         case LB_ADDSTRING:
383                 wRet = ListBoxAddString(hwnd, (LPSTR)lParam);
384                 return wRet;
385         case LB_GETTEXT:
386                 wRet = ListBoxGetText(hwnd, wParam, (LPSTR)lParam);
387 #ifdef DEBUG_LISTBOX
388                 printf("ListBox LB_GETTEXT #%u '%s' !\n", wParam, (LPSTR)lParam);
389 #endif
390                 return wRet;
391         case LB_INSERTSTRING:
392                 wRet = ListBoxInsertString(hwnd, wParam, (LPSTR)lParam);
393                 return wRet;
394         case LB_DELETESTRING:
395                 printf("ListBox LB_DELETESTRING #%u !\n", wParam);
396                 wRet = ListBoxDeleteString(hwnd, wParam);
397                 return wRet;
398         case LB_FINDSTRING:
399                 wRet = ListBoxFindString(hwnd, wParam, (LPSTR)lParam);
400                 return wRet;
401         case LB_GETCARETINDEX:
402                 return wRet;
403         case LB_GETCOUNT:
404                 lphl = ListBoxGetStorageHeader(hwnd);
405                 return lphl->ItemsCount;
406         case LB_GETCURSEL:
407                 lphl = ListBoxGetStorageHeader(hwnd);
408 #ifdef DEBUG_LISTBOX
409                 printf("ListBox LB_GETCURSEL %u !\n", lphl->ItemFocused);
410 #endif
411                 return lphl->ItemFocused;
412         case LB_GETHORIZONTALEXTENT:
413                 return wRet;
414         case LB_GETITEMDATA:
415                 return wRet;
416         case LB_GETITEMHEIGHT:
417                 return wRet;
418         case LB_GETITEMRECT:
419                 return wRet;
420         case LB_GETSEL:
421                 wRet = ListBoxGetSel(hwnd, wParam);
422                 return wRet;
423         case LB_GETSELCOUNT:
424                 return wRet;
425         case LB_GETSELITEMS:
426                 return wRet;
427         case LB_GETTEXTLEN:
428                 return wRet;
429         case LB_GETTOPINDEX:
430                 return wRet;
431         case LB_SELECTSTRING:
432                 return wRet;
433         case LB_SELITEMRANGE:
434                 return wRet;
435         case LB_SETCARETINDEX:
436                 return wRet;
437         case LB_SETCOLUMNWIDTH:
438                 lphl = ListBoxGetStorageHeader(hwnd);
439                 lphl->ColumnsWidth = wParam;
440                 break;
441         case LB_SETHORIZONTALEXTENT:
442                 return wRet;
443         case LB_SETITEMDATA:
444                 return wRet;
445         case LB_SETTABSTOPS:
446                 return wRet;
447         case LB_SETCURSEL:
448 #ifdef DEBUG_LISTBOX
449                 printf("ListBox LB_SETCURSEL wParam=%x !\n", wParam);
450 #endif
451                 wRet = ListBoxSetCurSel(hwnd, wParam);
452                 InvalidateRect(hwnd, NULL, TRUE);
453                 UpdateWindow(hwnd);
454                 return wRet;
455         case LB_SETSEL:
456                 printf("ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
457                 wRet = ListBoxSetSel(hwnd, LOWORD(lParam), wParam);
458                 InvalidateRect(hwnd, NULL, TRUE);
459                 UpdateWindow(hwnd);
460                 return wRet;
461         case LB_SETTOPINDEX:
462                 printf("ListBox LB_SETTOPINDEX wParam=%x !\n", wParam);
463                 lphl = ListBoxGetStorageHeader(hwnd);
464                 lphl->FirstVisible = wParam;
465                 wndPtr = WIN_FindWndPtr(hwnd);
466                 if (wndPtr->dwStyle & WS_VSCROLL)
467                     SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
468                 InvalidateRect(hwnd, NULL, TRUE);
469                 UpdateWindow(hwnd);
470                 break;
471         case LB_SETITEMHEIGHT:
472 #ifdef DEBUG_LISTBOX
473                 printf("ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
474 #endif
475                 wRet = ListBoxSetItemHeight(hwnd, wParam, lParam);
476                 return wRet;
477
478         default:
479                 return DefWindowProc( hwnd, message, wParam, lParam );
480     }
481 return 0;
482 }
483
484
485 LPHEADLIST ListBoxGetWindowAndStorage(HWND hwnd, WND **wndPtr)
486 {
487     WND  *Ptr;
488     LPHEADLIST lphl;
489     *(wndPtr) = Ptr = WIN_FindWndPtr(hwnd);
490     lphl = *((LPHEADLIST *)&Ptr->wExtra[1]);
491     return lphl;
492 }
493
494
495 LPHEADLIST ListBoxGetStorageHeader(HWND hwnd)
496 {
497     WND  *wndPtr;
498     LPHEADLIST lphl;
499     wndPtr = WIN_FindWndPtr(hwnd);
500     lphl = *((LPHEADLIST *)&wndPtr->wExtra[1]);
501     return lphl;
502 }
503
504
505 void StdDrawListBox(HWND hwnd)
506 {
507         WND     *wndPtr;
508         LPHEADLIST  lphl;
509         LPLISTSTRUCT lpls;
510         PAINTSTRUCT ps;
511         HBRUSH  hBrush;
512         int     OldBkMode;
513         DWORD   dwOldTextColor;
514         HWND    hWndParent;
515         HDC     hdc;
516         RECT    rect;
517         UINT    i, h, h2, maxwidth, ipc;
518         char    C[128];
519         h = 0;
520         hdc = BeginPaint( hwnd, &ps );
521         if (!IsWindowVisible(hwnd)) {
522             EndPaint( hwnd, &ps );
523             return;
524             }
525         lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
526         if (lphl == NULL) goto EndOfPaint;
527         SelectObject(hdc, lphl->hFont);
528         hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
529                     MAKELONG(hwnd, CTLCOLOR_LISTBOX));
530         if (hBrush == (HBRUSH)NULL)  hBrush = GetStockObject(WHITE_BRUSH);
531         GetClientRect(hwnd, &rect);
532 /*
533         if (wndPtr->dwStyle & WS_VSCROLL) rect.right -= 16;
534         if (wndPtr->dwStyle & WS_HSCROLL) rect.bottom -= 16;
535 */
536         FillRect(hdc, &rect, hBrush);
537         maxwidth = rect.right;
538         rect.right = lphl->ColumnsWidth;
539         if (lphl->ItemsCount == 0) goto EndOfPaint;
540         lpls = lphl->lpFirst;
541         if (lpls == NULL) goto EndOfPaint;
542         lphl->ItemsVisible = 0;
543         lphl->ItemsPerColumn = ipc = 0;
544         for(i = 1; i <= lphl->ItemsCount; i++) {
545             if (i >= lphl->FirstVisible) {
546                 if (lpls == NULL) break;
547                 if ((h + lpls->dis.rcItem.bottom - lpls->dis.rcItem.top) > rect.bottom) {
548                     if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
549                         lphl->ItemsPerColumn = max(lphl->ItemsPerColumn, ipc);
550                         ipc = 0;
551                         h = 0;
552                         rect.left += lphl->ColumnsWidth;
553                         rect.right += lphl->ColumnsWidth;
554                         if (rect.left > maxwidth) break;
555                         }
556                     else 
557                         break;
558                     }
559                 h2 = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
560                 lpls->dis.rcItem.top = h;
561                 lpls->dis.rcItem.bottom = h + h2;
562                 lpls->dis.rcItem.left = rect.left;
563                 lpls->dis.rcItem.right = rect.right;
564                 OldBkMode = SetBkMode(hdc, TRANSPARENT);
565                 if (lpls->dis.itemState != 0) {
566                         dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
567                     FillRect(hdc, &lpls->dis.rcItem, GetStockObject(BLACK_BRUSH));
568                     }
569                 TextOut(hdc, rect.left + 5, h + 2, (char *)lpls->dis.itemData, 
570                         strlen((char *)lpls->dis.itemData));
571                 if (lpls->dis.itemState != 0) {
572                         SetTextColor(hdc, dwOldTextColor);
573                     }
574                 SetBkMode(hdc, OldBkMode);
575                 if ((lphl->ItemFocused == i - 1) && GetFocus() == hwnd) {
576                     DrawFocusRect(hdc, &lpls->dis.rcItem);
577                     }
578                 h += h2;
579                 lphl->ItemsVisible++;
580                 ipc++;
581                 }
582             if (lpls->lpNext == NULL) goto EndOfPaint;
583             lpls = (LPLISTSTRUCT)lpls->lpNext;
584         }
585 EndOfPaint:
586     EndPaint( hwnd, &ps );
587     if ((lphl->ItemsCount > lphl->ItemsVisible) &
588         (wndPtr->dwStyle & WS_VSCROLL)) {
589 /*
590         InvalidateRect(wndPtr->hWndVScroll, NULL, TRUE);
591         UpdateWindow(wndPtr->hWndVScroll);
592 */
593         }
594 }
595
596
597
598 void OwnerDrawListBox(HWND hwnd)
599 {
600         WND     *wndPtr;
601         LPHEADLIST  lphl;
602         LPLISTSTRUCT lpls;
603         PAINTSTRUCT ps;
604         HBRUSH  hBrush;
605         HWND    hWndParent;
606         HDC hdc;
607         RECT rect;
608         UINT  i, h, h2, maxwidth;
609         char    C[128];
610         h = 0;
611         hdc = BeginPaint(hwnd, &ps);
612         if (!IsWindowVisible(hwnd)) {
613             EndPaint( hwnd, &ps );
614             return;
615             }
616         lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
617         if (lphl == NULL) goto EndOfPaint;
618         hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
619                     MAKELONG(hwnd, CTLCOLOR_LISTBOX));
620         if (hBrush == (HBRUSH)NULL)  hBrush = GetStockObject(WHITE_BRUSH);
621         GetClientRect(hwnd, &rect);
622         if (wndPtr->dwStyle & WS_VSCROLL) rect.right -= 16;
623         if (wndPtr->dwStyle & WS_HSCROLL) rect.bottom -= 16;
624         FillRect(hdc, &rect, hBrush);
625         maxwidth = rect.right;
626         rect.right = lphl->ColumnsWidth;
627         if (lphl->ItemsCount == 0) goto EndOfPaint;
628         lpls = lphl->lpFirst;
629         if (lpls == NULL) goto EndOfPaint;
630         lphl->ItemsVisible = 0;
631         for (i = 1; i <= lphl->ItemsCount; i++) {
632             if (i >= lphl->FirstVisible) {
633                 lpls->dis.hDC = hdc;
634                 lpls->dis.itemID = i - 1;
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;
643                     }
644                 if (lphl->ItemFocused == i - 1) {
645                     lpls->dis.itemAction |= ODA_FOCUS;
646                     }
647 #ifdef DEBUT_LISTBOX
648                 printf("LBOX WM_DRAWITEM #%d left=%d top=%d right=%d bottom=%d !\n", 
649                         i, lpls->dis.rcItem.left, lpls->dis.rcItem.top, 
650                         lpls->dis.rcItem.right, lpls->dis.rcItem.bottom);
651                 printf("LBOX WM_DRAWITEM Parent=%X &dis=%lX CtlID=%u !\n", 
652                         hWndParent, (LONG)&lpls->dis, lpls->dis.CtlID);
653                 printf("LBOX WM_DRAWITEM '%s' !\n", lpls->dis.itemData);
654 #endif
655                 SendMessage(lphl->hWndLogicParent, WM_DRAWITEM, i, (LPARAM)&lpls->dis);
656                 if (lpls->dis.itemState != 0) {
657                     InvertRect(hdc, &lpls->dis.rcItem);
658                     }
659                 h += h2;
660                 lphl->ItemsVisible++;
661                 if (h > rect.bottom) goto EndOfPaint;
662                 }
663             if (lpls->lpNext == NULL) goto EndOfPaint;
664             lpls = (LPLISTSTRUCT)lpls->lpNext;
665         }
666 EndOfPaint:
667     EndPaint( hwnd, &ps );
668     if ((lphl->ItemsCount > lphl->ItemsVisible) &
669         (wndPtr->dwStyle & WS_VSCROLL)) {
670 /*
671         InvalidateRect(wndPtr->hWndVScroll, NULL, TRUE);
672         UpdateWindow(wndPtr->hWndVScroll);
673 */
674         }
675 }
676
677
678
679 int ListBoxFindMouse(HWND hwnd, int X, int Y)
680 {
681     WND                 *wndPtr;
682     LPHEADLIST          lphl;
683     LPLISTSTRUCT        lpls;
684     RECT                rect;
685     UINT                i, h, h2, w, w2;
686     char                C[128];
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     if (wndPtr->dwStyle & WS_VSCROLL) rect.right -= 16;
694     if (wndPtr->dwStyle & WS_HSCROLL) rect.bottom -= 16;
695     h = w2 = 0;
696     w = lphl->ColumnsWidth;
697     for(i = 1; i <= lphl->ItemsCount; i++) {
698         if (i >= lphl->FirstVisible) {
699             h2 = h;
700             h += lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
701             if ((Y > h2) && (Y < h) &&
702                 (X > w2) && (X < w)) return(i - 1);
703             if (h > rect.bottom) {
704                 if ((wndPtr->dwStyle & LBS_MULTICOLUMN) != LBS_MULTICOLUMN) return LB_ERR;
705                 h = 0;
706                 w2 = w;
707                 w += lphl->ColumnsWidth;
708                 if (w2 > rect.right) return LB_ERR;
709                 }
710             }
711         if (lpls->lpNext == NULL) return LB_ERR;
712         lpls = (LPLISTSTRUCT)lpls->lpNext;
713         }
714     return(LB_ERR);
715 }
716
717
718
719 int CreateListBoxStruct(HWND hwnd)
720 {
721     WND  *wndPtr;
722     LPHEADLIST lphl;
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->StdItemHeight = 15;
731     lphl->DrawCtlType = ODT_LISTBOX;
732     return TRUE;
733 }
734
735
736 void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls)  
737 {
738         MEASUREITEMSTRUCT *measure;
739         HANDLE hTemp = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(MEASUREITEMSTRUCT));
740         measure = (MEASUREITEMSTRUCT *) USER_HEAP_ADDR(hTemp);
741         if (measure == NULL) {
742                 printf("ListBoxAskMeasure() // Bad allocation of Measure struct !\n");
743                 return;
744                 }
745         measure->CtlType = ODT_LISTBOX;
746         measure->CtlID = wndPtr->wIDmenu;
747         measure->itemID = lpls->dis.itemID;
748         measure->itemWidth = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
749         measure->itemHeight = 0;
750         measure->itemData = lpls->dis.itemData;
751         SendMessage(lphl->hWndLogicParent, WM_MEASUREITEM, 0, (DWORD)measure);
752         lpls->dis.rcItem.right = lpls->dis.rcItem.left + measure->itemWidth;
753         lpls->dis.rcItem.bottom = lpls->dis.rcItem.top + measure->itemHeight;
754         USER_HEAP_FREE(hTemp);                  
755 }
756
757
758 int ListBoxAddString(HWND hwnd, LPSTR newstr)
759 {
760     WND         *wndPtr;
761     LPHEADLIST  lphl;
762     LPLISTSTRUCT lpls, lplsnew;
763     HANDLE      hTemp;
764     LPSTR       str;
765     lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
766     if (lphl == NULL) return LB_ERR;
767     hTemp = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LISTSTRUCT));
768     lplsnew = (LPLISTSTRUCT) USER_HEAP_ADDR(hTemp);
769     if (lplsnew == NULL) {
770                 printf("ListBoxAddString() // Bad allocation of new item !\n");
771                 return LB_ERRSPACE;
772                 }
773     lpls = lphl->lpFirst;
774     if (lpls != NULL) {
775         while(lpls->lpNext != NULL) {
776             lpls = (LPLISTSTRUCT)lpls->lpNext;
777             }
778         lpls->lpNext = lplsnew;
779         }
780     else
781         lphl->lpFirst = lplsnew;
782     lphl->ItemsCount++;
783 #ifdef DEBUG_LISTBOX
784     printf("Items Count = %u\n", lphl->ItemsCount);
785 #endif
786     hTemp = 0;
787     if ((wndPtr->dwStyle & LBS_HASSTRINGS) != LBS_HASSTRINGS) {
788         if (((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) != LBS_OWNERDRAWFIXED) &&
789             ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) != LBS_OWNERDRAWVARIABLE)) {
790             hTemp = USER_HEAP_ALLOC(GMEM_MOVEABLE, strlen(newstr) + 1);
791             str = (LPSTR)USER_HEAP_ADDR(hTemp);
792             if (str == NULL) return LB_ERRSPACE;
793             strcpy(str, newstr);
794             newstr = str;
795 #ifdef DEBUG_LISTBOX
796             printf("ListBoxAddString// after strcpy '%s'\n", str);
797 #endif
798             }
799         }
800     ListBoxDefaultItem(hwnd, wndPtr, lphl, lplsnew);
801     lplsnew->hMem = hTemp;
802     lplsnew->lpNext = NULL;
803     lplsnew->dis.itemID = lphl->ItemsCount;
804     lplsnew->dis.itemData = (DWORD)newstr;
805     lplsnew->hData = hTemp;
806         if ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) 
807                 ListBoxAskMeasure(wndPtr, lphl, lplsnew);
808     if (wndPtr->dwStyle & WS_VSCROLL)
809         SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, 
810             (lphl->FirstVisible != 1));
811     if ((wndPtr->dwStyle & WS_HSCROLL) && lphl->ItemsPerColumn != 0)
812         SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
813             lphl->ItemsPerColumn + 1, (lphl->FirstVisible != 1));
814     if (lphl->FirstVisible >= (lphl->ItemsCount - lphl->ItemsVisible)) {
815         InvalidateRect(hwnd, NULL, TRUE);
816         UpdateWindow(hwnd);
817         }
818     if ((lphl->ItemsCount - lphl->FirstVisible) == lphl->ItemsVisible) {
819         if (wndPtr->dwStyle & WS_VSCROLL)
820             ShowScrollBar(hwnd, SB_VERT, TRUE);
821         if (wndPtr->dwStyle & WS_HSCROLL)
822             ShowScrollBar(hwnd, SB_HORZ, TRUE);
823         }
824     return lphl->ItemsCount;
825 }
826
827
828 int ListBoxInsertString(HWND hwnd, UINT uIndex, LPSTR newstr)
829 {
830         WND     *wndPtr;
831         LPHEADLIST      lphl;
832         LPLISTSTRUCT lpls, lplsnew;
833         HANDLE  hTemp;
834         LPSTR   str;
835         UINT    Count;
836 #ifdef DEBUG_LISTBOX
837     printf("ListBoxInsertString(%04X, %d, %08X);\n", hwnd, uIndex, newstr);
838 #endif
839         if (uIndex == (UINT)-1) return ListBoxAddString(hwnd, newstr);
840         lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
841         if (lphl == NULL) return LB_ERR;
842         if (uIndex >= lphl->ItemsCount) return LB_ERR;
843         lpls = lphl->lpFirst;
844         if (lpls == NULL) return LB_ERR;
845         if (uIndex > lphl->ItemsCount) return LB_ERR;
846         for(Count = 1; Count < uIndex; Count++) {
847                 if (lpls->lpNext == NULL) return LB_ERR;
848                 lpls = (LPLISTSTRUCT)lpls->lpNext;
849                 }
850         hTemp = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LISTSTRUCT));
851         lplsnew = (LPLISTSTRUCT) USER_HEAP_ADDR(hTemp);
852     if (lplsnew == NULL) {
853                 printf("ListBoxInsertString() // Bad allocation of new item !\n");
854                 return LB_ERRSPACE;
855                 }
856         ListBoxDefaultItem(hwnd, wndPtr, lphl, lplsnew);
857         lplsnew->hMem = hTemp;
858         lpls->lpNext = lplsnew;
859         lphl->ItemsCount++;
860         hTemp = 0;
861         if ((wndPtr->dwStyle & LBS_HASSTRINGS) != LBS_HASSTRINGS) {
862                 if (((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) != LBS_OWNERDRAWFIXED) &&
863                         ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) != LBS_OWNERDRAWVARIABLE)) {
864                         hTemp = USER_HEAP_ALLOC(GMEM_MOVEABLE, strlen(newstr) + 1);
865                         str = (LPSTR)USER_HEAP_ADDR(hTemp);
866                         if (str == NULL) return LB_ERRSPACE;
867                         strcpy(str, newstr);
868                         newstr = str;
869 #ifdef DEBUG_LISTBOX
870                     printf("ListBoxInsertString // after strcpy '%s'\n", str);
871 #endif
872                         }
873                 }
874         lplsnew->lpNext = NULL;
875         lplsnew->dis.itemID = lphl->ItemsCount;
876         lplsnew->dis.itemData = (DWORD)newstr;
877         lplsnew->hData = hTemp;
878         if ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) 
879                 ListBoxAskMeasure(wndPtr, lphl, lplsnew);
880         if (wndPtr->dwStyle & WS_VSCROLL)
881                 SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, 
882                                                     (lphl->FirstVisible != 1));
883         if ((wndPtr->dwStyle & WS_HSCROLL) && lphl->ItemsPerColumn != 0)
884                 SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
885                         lphl->ItemsPerColumn + 1, (lphl->FirstVisible != 1));
886         if (((lphl->ItemsCount - lphl->FirstVisible) == lphl->ItemsVisible) && 
887                 (lphl->ItemsVisible != 0)) {
888                 if (wndPtr->dwStyle & WS_VSCROLL) ShowScrollBar(hwnd, SB_VERT, TRUE);
889                 if (wndPtr->dwStyle & WS_HSCROLL) ShowScrollBar(hwnd, SB_HORZ, TRUE);
890                 }
891         if ((lphl->FirstVisible <= uIndex) &&
892                 ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
893                 InvalidateRect(hwnd, NULL, TRUE);
894                 UpdateWindow(hwnd);
895                 }
896 #ifdef DEBUG_LISTBOX
897     printf("ListBoxInsertString // count=%d\n", lphl->ItemsCount);
898 #endif
899         return lphl->ItemsCount;
900 }
901
902
903 int ListBoxGetText(HWND hwnd, UINT uIndex, LPSTR OutStr)
904 {
905     WND         *wndPtr;
906     LPHEADLIST  lphl;
907     LPLISTSTRUCT lpls;
908     UINT        Count;
909     lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
910     if (lphl == NULL) return LB_ERR;
911     if (uIndex >= lphl->ItemsCount) return LB_ERR;
912     lpls = lphl->lpFirst;
913     if (lpls == NULL) return LB_ERR;
914     if (uIndex > lphl->ItemsCount) return LB_ERR;
915     for(Count = 0; Count < uIndex; Count++) {
916         if (lpls->lpNext == NULL) return LB_ERR;
917         lpls = (LPLISTSTRUCT)lpls->lpNext;
918     }
919     if (((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) ||
920             ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE)) {
921         if ((wndPtr->dwStyle & LBS_HASSTRINGS) != LBS_HASSTRINGS) { 
922             *((long *)OutStr) = lpls->dis.itemData;
923             return 4;
924             }
925         }
926         
927     strcpy(OutStr, (char *)lpls->dis.itemData);
928     return strlen(OutStr);
929 }
930
931
932 int ListBoxDeleteString(HWND hwnd, UINT uIndex)
933 {
934     WND         *wndPtr;
935     LPHEADLIST  lphl;
936     LPLISTSTRUCT lpls, lpls2;
937     UINT        Count;
938     lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
939     if (lphl == NULL) return LB_ERR;
940     if (uIndex >= lphl->ItemsCount) return LB_ERR;
941     lpls = lphl->lpFirst;
942     if (lpls == NULL) return LB_ERR;
943     if (uIndex > lphl->ItemsCount) return LB_ERR;
944     for(Count = 1; Count < uIndex; Count++) {
945         if (lpls->lpNext == NULL) return LB_ERR;
946         lpls2 = lpls;
947         lpls = (LPLISTSTRUCT)lpls->lpNext;
948     }
949     lpls2->lpNext = (LPLISTSTRUCT)lpls->lpNext;
950     lphl->ItemsCount--;
951     if (lpls->hData != 0) USER_HEAP_FREE(lpls->hData);
952     if (lpls->hMem != 0) USER_HEAP_FREE(lpls->hMem);
953     if (wndPtr->dwStyle & WS_VSCROLL)
954         SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, TRUE);
955     if ((wndPtr->dwStyle & WS_HSCROLL) && lphl->ItemsPerColumn != 0)
956         SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
957             lphl->ItemsPerColumn + 1, TRUE);
958     if (lphl->ItemsCount < lphl->ItemsVisible) {
959         if (wndPtr->dwStyle & WS_VSCROLL)
960             ShowScrollBar(hwnd, SB_VERT, FALSE);
961         if (wndPtr->dwStyle & WS_HSCROLL)
962             ShowScrollBar(hwnd, SB_HORZ, FALSE);
963         }
964     if ((lphl->FirstVisible <= uIndex) &&
965         ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
966         InvalidateRect(hwnd, NULL, TRUE);
967         UpdateWindow(hwnd);
968         }
969     return lphl->ItemsCount;
970 }
971
972
973 int ListBoxFindString(HWND hwnd, UINT nFirst, LPSTR MatchStr)
974 {
975     LPHEADLIST  lphl;
976     LPLISTSTRUCT lpls;
977     UINT        Count;
978     lphl = ListBoxGetStorageHeader(hwnd);
979     if (lphl == NULL) return LB_ERR;
980     if (nFirst > lphl->ItemsCount) return LB_ERR;
981     lpls = lphl->lpFirst;
982     if (lpls == NULL) return LB_ERR;
983     Count = 0;
984     while(lpls != NULL) {
985         if (strcmp((char *)lpls->dis.itemData, MatchStr) == 0) return Count;
986         lpls = (LPLISTSTRUCT)lpls->lpNext;
987         Count++;
988         }
989     return LB_ERR;
990 }
991
992
993 int ListBoxResetContent(HWND hwnd)
994 {
995     WND  *wndPtr;
996     LPHEADLIST  lphl;
997     LPLISTSTRUCT lpls, lpls2;
998     UINT        i;
999     lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1000     if (lphl == NULL) return LB_ERR;
1001     lpls = lphl->lpFirst;
1002     if (lpls == NULL) return LB_ERR;
1003     for(i = 0; i <= lphl->ItemsCount; i++) {
1004         lpls2 = lpls;
1005         lpls = (LPLISTSTRUCT)lpls->lpNext;
1006         if (i != 0) {
1007 #ifdef DEBUG_LISTBOX
1008             printf("ResetContent #%u\n", i);
1009 #endif
1010             if (lpls2->hData != 0 && lpls2->hData != lpls2->hMem)
1011                 USER_HEAP_FREE(lpls2->hData);
1012             if (lpls2->hMem != 0) USER_HEAP_FREE(lpls2->hMem);
1013             }  
1014         if (lpls == NULL)  break;
1015     }
1016     lphl->lpFirst = NULL;
1017     lphl->FirstVisible = 1;
1018     lphl->ItemsCount = 0;
1019     lphl->ItemFocused = 0;
1020     lphl->PrevFocused = 0;
1021     if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
1022         SendMessage(lphl->hWndLogicParent, WM_COMMAND, 
1023             wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
1024     if (wndPtr->dwStyle & WS_VSCROLL)
1025         SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, TRUE);
1026     if ((wndPtr->dwStyle & WS_HSCROLL) && lphl->ItemsPerColumn != 0)
1027         SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
1028             lphl->ItemsPerColumn + 1, TRUE);
1029     if (wndPtr->dwStyle & WS_VSCROLL)
1030         ShowScrollBar(hwnd, SB_VERT, FALSE);
1031     if (wndPtr->dwStyle & WS_HSCROLL)
1032         ShowScrollBar(hwnd, SB_HORZ, FALSE);
1033     InvalidateRect(hwnd, NULL, TRUE);
1034     UpdateWindow(hwnd);
1035     return TRUE;
1036 }
1037
1038
1039 int ListBoxSetCurSel(HWND hwnd, WORD wIndex)
1040 {
1041     WND  *wndPtr;
1042     LPHEADLIST  lphl;
1043     LPLISTSTRUCT lpls, lpls2;
1044     UINT        i;
1045     lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1046     if (lphl == NULL) return LB_ERR;
1047     lphl->ItemFocused = LB_ERR; 
1048     if (wIndex >= lphl->ItemsCount) return LB_ERR;
1049     lpls = lphl->lpFirst;
1050     if (lpls == NULL) return LB_ERR;
1051     for(i = 0; i < lphl->ItemsCount; i++) {
1052         lpls2 = lpls;
1053         lpls = (LPLISTSTRUCT)lpls->lpNext;
1054         if (i == wIndex)
1055             lpls2->dis.itemState = 1;
1056         else 
1057             if (lpls2->dis.itemState != 0)
1058                 lpls2->dis.itemState = 0;
1059         if (lpls == NULL)  break;
1060     }
1061     lphl->ItemFocused = wIndex;
1062     if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
1063         SendMessage(lphl->hWndLogicParent, WM_COMMAND, 
1064             wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
1065     return LB_ERR;
1066 }
1067
1068
1069
1070 int ListBoxSetSel(HWND hwnd, WORD wIndex, WORD state)
1071 {
1072     LPHEADLIST  lphl;
1073     LPLISTSTRUCT lpls, lpls2;
1074     UINT        i;
1075     lphl = ListBoxGetStorageHeader(hwnd);
1076     if (lphl == NULL) return LB_ERR;
1077     if (wIndex >= lphl->ItemsCount) return LB_ERR;
1078     lpls = lphl->lpFirst;
1079     if (lpls == NULL) return LB_ERR;
1080     for(i = 0; i < lphl->ItemsCount; i++) {
1081         lpls2 = lpls;
1082         lpls = (LPLISTSTRUCT)lpls->lpNext;
1083         if ((i == wIndex) || (wIndex == (WORD)-1)) {
1084             lpls2->dis.itemState = state;
1085             break;
1086             }  
1087         if (lpls == NULL)  break;
1088     }
1089     return LB_ERR;
1090 }
1091
1092
1093 int ListBoxGetSel(HWND hwnd, WORD wIndex)
1094 {
1095     LPHEADLIST  lphl;
1096     LPLISTSTRUCT lpls, lpls2;
1097     UINT        i;
1098     lphl = ListBoxGetStorageHeader(hwnd);
1099     if (lphl == NULL) return LB_ERR;
1100     if (wIndex >= lphl->ItemsCount) return LB_ERR;
1101     lpls = lphl->lpFirst;
1102     if (lpls == NULL) return LB_ERR;
1103     for(i = 0; i < lphl->ItemsCount; i++) {
1104         lpls2 = lpls;
1105         lpls = (LPLISTSTRUCT)lpls->lpNext;
1106         if (i == wIndex) {
1107             return lpls2->dis.itemState;
1108             }  
1109         if (lpls == NULL)  break;
1110     }
1111     return LB_ERR;
1112 }
1113
1114
1115 int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec)
1116 {
1117         struct dosdirent *dp;
1118         struct dosdirent *newdp;
1119         struct stat     st;
1120         int     x, wRet;
1121         char    temp[256];
1122 #ifdef DEBUG_LISTBOX
1123         fprintf(stderr,"ListBoxDirectory: %s, %4x\n",filespec,attrib);
1124 #endif
1125         if ((dp = (struct dosdirent *)DOS_opendir(filespec)) ==NULL) return 0;
1126         while (dp = (struct dosdirent *)DOS_readdir(dp)) {
1127                 if (!dp->inuse) break;
1128 #ifdef DEBUG_LISTBOX
1129                 printf("ListBoxDirectory %08X '%s' !\n", dp->filename, dp->filename);
1130 #endif
1131                 if (dp->attribute & FA_DIREC) {
1132                         if (attrib & DDL_DIRECTORY) {
1133                                 sprintf(temp, "[%s]", dp->filename);
1134                                 if ( (wRet = ListBoxAddString(hwnd, temp)) == LB_ERR) break;
1135                         }
1136                 } else 
1137                 if (attrib & DDL_EXCLUSIVE) {
1138                         if (attrib & (DDL_READWRITE | DDL_READONLY | DDL_HIDDEN | DDL_SYSTEM) )
1139                                 if ( (wRet = ListBoxAddString(hwnd, dp->filename)) == LB_ERR)
1140                                         break;
1141                 } else {
1142                         if ( (wRet = ListBoxAddString(hwnd, dp->filename)) == LB_ERR)
1143                                 break;
1144                 }
1145         }
1146         DOS_closedir(dp);
1147         
1148         if (attrib & DDL_DRIVES)
1149         {
1150                 for (x=0;x!=MAX_DOS_DRIVES;x++)
1151                 {
1152                         if (DOS_ValidDrive(x))
1153                         {
1154                                 sprintf(temp, "[-%c-]", 'A'+x);
1155                                 if ( (wRet = ListBoxAddString(hwnd, temp)) == LB_ERR)
1156                                         break;
1157                         }               
1158                 }
1159         }
1160 #ifdef DEBUG_LISTBOX
1161         printf("End of ListBoxDirectory !\n");
1162 #endif
1163         return wRet;
1164 }
1165
1166
1167 int ListBoxGetItemRect(HWND hwnd, WORD wIndex, LPRECT lprect)
1168 {
1169     LPHEADLIST  lphl;
1170     LPLISTSTRUCT lpls, lpls2;
1171     UINT        i;
1172     lphl = ListBoxGetStorageHeader(hwnd);
1173     if (lphl == NULL) return LB_ERR;
1174     if (wIndex > lphl->ItemsCount) return LB_ERR;
1175     lpls = lphl->lpFirst;
1176     if (lpls == NULL) return LB_ERR;
1177     for(i = 0; i < lphl->ItemsCount; i++) {
1178         lpls2 = lpls;
1179         lpls = (LPLISTSTRUCT)lpls->lpNext;
1180         if (i == wIndex) {
1181             *(lprect) = lpls2->dis.rcItem;
1182             break;
1183             }  
1184         if (lpls == NULL)  break;
1185     }
1186     return LB_ERR;
1187 }
1188
1189
1190
1191 int ListBoxSetItemHeight(HWND hwnd, WORD wIndex, long height)
1192 {
1193     LPHEADLIST  lphl;
1194     LPLISTSTRUCT lpls, lpls2;
1195     UINT        i;
1196     lphl = ListBoxGetStorageHeader(hwnd);
1197     if (lphl == NULL) return LB_ERR;
1198     if (wIndex > lphl->ItemsCount) return LB_ERR;
1199     lpls = lphl->lpFirst;
1200     if (lpls == NULL) return LB_ERR;
1201     for(i = 0; i < lphl->ItemsCount; i++) {
1202         lpls2 = lpls;
1203         lpls = (LPLISTSTRUCT)lpls->lpNext;
1204         if (i == wIndex) {
1205             lpls2->dis.rcItem.bottom = lpls2->dis.rcItem.top + (short)height;
1206             InvalidateRect(hwnd, NULL, TRUE);
1207             UpdateWindow(hwnd);
1208             break;
1209             }  
1210         if (lpls == NULL)  break;
1211     }
1212     return LB_ERR;
1213 }
1214
1215
1216
1217
1218
1219 int ListBoxDefaultItem(HWND hwnd, WND *wndPtr, 
1220         LPHEADLIST lphl, LPLISTSTRUCT lpls)
1221 {
1222     RECT        rect;
1223         if (wndPtr == NULL || lphl == NULL || lpls == NULL) {
1224                 printf("ListBoxDefaultItem() // Bad Pointers !\n");
1225                 return FALSE;
1226                 }
1227     GetClientRect(hwnd, &rect);
1228     SetRect(&lpls->dis.rcItem, 0, 0, rect.right, lphl->StdItemHeight);
1229     lpls->dis.CtlType = lphl->DrawCtlType;
1230     lpls->dis.CtlID = wndPtr->wIDmenu;
1231     lpls->dis.itemID = 0;
1232     lpls->dis.itemAction = 0;
1233     lpls->dis.itemState = 0;
1234     lpls->dis.hwndItem = hwnd;
1235     lpls->dis.hDC = 0;
1236     lpls->dis.itemData = 0;
1237         return TRUE;
1238 }
1239
1240
1241
1242 int ListBoxFindNextMatch(HWND hwnd, WORD wChar)
1243 {
1244     WND         *wndPtr;
1245     LPHEADLIST  lphl;
1246     LPLISTSTRUCT lpls;
1247     UINT        Count;
1248     lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
1249     if (lphl == NULL) return LB_ERR;
1250     lpls = lphl->lpFirst;
1251     if (lpls == NULL) return LB_ERR;
1252     if (wChar < ' ') return LB_ERR;
1253     if (((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) ||
1254             ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE)) {
1255         if ((wndPtr->dwStyle & LBS_HASSTRINGS) != LBS_HASSTRINGS) { 
1256             return LB_ERR;
1257             }
1258         }
1259     Count = 0;
1260     while(lpls != NULL) {
1261         if (Count > lphl->ItemFocused) {
1262             if (*((char *)lpls->dis.itemData) == (char)wChar) {
1263                 lphl->FirstVisible = Count - lphl->ItemsVisible / 2;
1264                 if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
1265                 if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
1266                     lphl->ItemFocused = Count;
1267                     }
1268                 else {
1269                     ListBoxSetCurSel(hwnd, Count);
1270                     }
1271                 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1272                 InvalidateRect(hwnd, NULL, TRUE);
1273                 UpdateWindow(hwnd);
1274                 return Count;
1275                 }
1276             }
1277         lpls = (LPLISTSTRUCT)lpls->lpNext;
1278         Count++;
1279         }
1280     Count = 0;
1281     lpls = lphl->lpFirst;
1282     while(lpls != NULL) {
1283         if (*((char *)lpls->dis.itemData) == (char)wChar) {
1284             if (Count == lphl->ItemFocused)    return LB_ERR;
1285             lphl->FirstVisible = Count - lphl->ItemsVisible / 2;
1286             if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
1287             if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
1288                 lphl->ItemFocused = Count;
1289                 }
1290             else {
1291                 ListBoxSetCurSel(hwnd, Count);
1292                 }
1293             SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1294             InvalidateRect(hwnd, NULL, TRUE);
1295             UpdateWindow(hwnd);
1296             return Count;
1297             }
1298         lpls = (LPLISTSTRUCT)lpls->lpNext;
1299         Count++;
1300         }
1301     return LB_ERR;
1302 }
1303
1304
1305 /************************************************************************
1306  *                                      DlgDirSelect                    [USER.99]
1307  */
1308 BOOL DlgDirSelect(HWND hDlg, LPSTR lpStr, int nIDLBox)
1309 {
1310         printf("DlgDirSelect(%04X, '%s', %d) \n",       hDlg, lpStr, nIDLBox);
1311 }
1312
1313
1314 /************************************************************************
1315  *                                      DlgDirList                              [USER.100]
1316  */
1317 int DlgDirList(HWND hDlg, LPSTR lpPathSpec, 
1318         int nIDLBox, int nIDStat, WORD wType)
1319 {
1320         HWND    hWnd;
1321         printf("DlgDirList(%04X, '%s', %d, %d, %04X) \n",
1322                         hDlg, lpPathSpec, nIDLBox, nIDStat, wType);
1323         hWnd = GetDlgItem(hDlg, nIDLBox);
1324         ListBoxResetContent(hWnd);
1325         return ListBoxDirectory(hWnd, wType, lpPathSpec);
1326 }
1327
1328
1329