Release 960218
[wine/testsucceed.git] / controls / listbox.c
blobb9cd547072c8387db36ffaf1a712bf554302170e
1 /*
2 * Listbox controls
3 *
4 * Copyright Martin Ayotte, 1993
5 * Constantine Sapuntzakis, 1995
6 * Alex Korobka, 1995
7 *
8 */
11 * FIXME:
12 * - check if multi-column listboxes work
13 * - implement more messages and styles (LB_EXTENDEDSEL for instance)
14 * - exterminate evil InvalidateRect(whole listbox) where possible!!!!
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <ctype.h>
21 #include "windows.h"
22 #include "user.h"
23 #include "win.h"
24 #include "msdos.h"
25 #include "listbox.h"
26 #include "dos_fs.h"
27 #include "drive.h"
28 #include "file.h"
29 #include "stackframe.h"
30 #include "stddebug.h"
31 #include "debug.h"
32 #include "xmalloc.h"
34 #if 0
35 #define LIST_HEAP_ALLOC(lphl,f,size) ((int)HEAP_Alloc(&lphl->Heap,f,size) & 0xffff)
36 #define LIST_HEAP_FREE(lphl,handle) (HEAP_Free(&lphl->Heap,LIST_HEAP_ADDR(lphl,handle)))
37 #define LIST_HEAP_ADDR(lphl,handle) \
38 ((void *)((handle) ? ((handle) | ((int)lphl->Heap & 0xffff0000)) : 0))
39 #else
40 /* FIXME: shouldn't each listbox have its own heap? */
41 #if 0
42 #define LIST_HEAP_ALLOC(lphl,f,size) USER_HEAP_ALLOC(size)
43 #define LIST_HEAP_FREE(lphl,handle) USER_HEAP_FREE(handle)
44 #define LIST_HEAP_ADDR(lphl,handle) USER_HEAP_LIN_ADDR(handle)
45 #define LIST_HEAP_SEG_ADDR(lphl,handle) USER_HEAP_SEG_ADDR(handle)
46 #else
47 /* Something like this maybe ? */
48 #define LIST_HEAP_ALLOC(lphl,f,size) \
49 LOCAL_Alloc( lphl->HeapSel, LMEM_FIXED, (size) )
50 #if 0
51 #define LIST_HEAP_REALLOC(handle,size) \
52 LOCAL_ReAlloc( USER_HeapSel, (handle), (size), LMEM_FIXED )
53 #endif
54 #define LIST_HEAP_FREE(lphl,handle) \
55 LOCAL_Free( lphl->HeapSel, (handle) )
56 #define LIST_HEAP_ADDR(lphl,handle) \
57 ((handle) ? PTR_SEG_OFF_TO_LIN(lphl->HeapSel, (handle)) : NULL)
58 #define LIST_HEAP_SEG_ADDR(lphl,handle) \
59 ((handle) ? MAKELONG((handle), lphl->HeapSel) : 0)
60 #endif
61 #endif
63 #define LIST_HEAP_SIZE 0x10000
65 static void ListBoxInitialize(LPHEADLIST lphl)
67 lphl->lpFirst = NULL;
68 lphl->ItemsCount = 0;
69 lphl->ItemsVisible = 0;
70 lphl->FirstVisible = 0;
71 lphl->ColumnsVisible = 1;
72 lphl->ItemsPerColumn = 0;
73 lphl->ItemFocused = -1;
74 lphl->PrevFocused = -1;
77 void CreateListBoxStruct(HWND hwnd, WORD CtlType, LONG styles, HWND parent)
79 LPHEADLIST lphl;
81 lphl = (LPHEADLIST)xmalloc(sizeof(HEADLIST));
82 SetWindowLong(hwnd, 0, (LONG)lphl);
83 ListBoxInitialize(lphl);
84 lphl->DrawCtlType = CtlType;
85 lphl->CtlID = GetWindowWord(hwnd,GWW_ID);
86 lphl->bRedrawFlag = TRUE;
87 lphl->iNumStops = 0;
88 lphl->TabStops = NULL;
89 lphl->hFont = GetStockObject(SYSTEM_FONT);
90 lphl->hSelf = hwnd;
91 lphl->hParent = parent;
92 lphl->StdItemHeight = 15; /* FIXME: should get the font height */
93 lphl->OwnerDrawn = styles & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE);
94 lphl->HasStrings = (styles & LBS_HASSTRINGS) || !lphl->OwnerDrawn;
96 if (lphl->OwnerDrawn) {
97 LISTSTRUCT dummyls;
99 lphl->hDrawItemStruct = USER_HEAP_ALLOC(sizeof(DRAWITEMSTRUCT));
100 lphl->needMeasure = TRUE;
101 dummyls.mis.CtlType = lphl->DrawCtlType;
102 dummyls.mis.CtlID = lphl->CtlID;
103 dummyls.mis.itemID = -1;
104 dummyls.mis.itemWidth = 0; /* ignored */
105 dummyls.mis.itemData = 0;
107 ListBoxAskMeasure(lphl,&dummyls);
108 } else {
109 lphl->hDrawItemStruct = 0;
112 #if 0
113 HeapHandle = GlobalAlloc(GMEM_FIXED, LIST_HEAP_SIZE);
114 HeapBase = GlobalLock(HeapHandle);
115 HEAP_Init(&lphl->Heap, HeapBase, LIST_HEAP_SIZE);
116 #endif
117 /* WINELIBS list boxes do not operate on local heaps */
118 #ifndef WINELIB
119 lphl->HeapSel = GlobalAlloc(GMEM_FIXED,LIST_HEAP_SIZE);
120 LocalInit( lphl->HeapSel, 0, LIST_HEAP_SIZE-1);
121 #else
122 lphl->HeapSel = 0;
123 #endif
126 void DestroyListBoxStruct(LPHEADLIST lphl)
128 if (lphl->hDrawItemStruct)
129 USER_HEAP_FREE(lphl->hDrawItemStruct);
131 /* XXX need to free lphl->Heap */
132 GlobalFree(lphl->HeapSel);
133 free(lphl);
136 static LPHEADLIST ListBoxGetStorageHeader(HWND hwnd)
138 return (LPHEADLIST)GetWindowLong(hwnd,0);
141 /* Send notification "code" as part of a WM_COMMAND-message if hwnd
142 has the LBS_NOTIFY style */
143 void ListBoxSendNotification(LPHEADLIST lphl, WORD code)
145 DWORD dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
147 if (dwStyle & LBS_NOTIFY)
148 #ifdef WINELIB32
149 SendMessage(lphl->hParent, WM_COMMAND,
150 MAKEWPARAM(lphl->CtlID,code), (LPARAM)lphl->hSelf);
151 #else
152 SendMessage(lphl->hParent, WM_COMMAND,
153 lphl->CtlID, MAKELONG(lphl->hSelf, code));
154 #endif
158 /* get the maximum value of lphl->FirstVisible */
159 int ListMaxFirstVisible(LPHEADLIST lphl)
161 int m = lphl->ItemsCount-lphl->ItemsVisible;
162 return (m < 0) ? 0 : m;
166 void ListBoxUpdateWindow(HWND hwnd, LPHEADLIST lphl, BOOL repaint)
168 SetScrollRange(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
169 if (lphl->ItemsPerColumn != 0) {
170 SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
171 lphl->ItemsPerColumn + 1, TRUE);
173 if (repaint && lphl->bRedrawFlag) {
174 InvalidateRect(hwnd, NULL, TRUE);
178 /* Returns: 0 if nothing needs to be changed */
179 /* 1 if FirstVisible changed */
181 int ListBoxScrollToFocus(LPHEADLIST lphl)
183 short end;
185 if (lphl->ItemsCount == 0) return 0;
186 if (lphl->ItemFocused == -1) return 0;
188 end = lphl->FirstVisible + lphl->ItemsVisible - 1;
190 if (lphl->ItemFocused < lphl->FirstVisible ) {
191 lphl->FirstVisible = lphl->ItemFocused;
192 return 1;
193 } else {
194 if (lphl->ItemFocused > end) {
195 WORD maxFirstVisible = ListMaxFirstVisible(lphl);
197 lphl->FirstVisible = lphl->ItemFocused;
199 if (lphl->FirstVisible > maxFirstVisible) {
200 lphl->FirstVisible = maxFirstVisible;
202 return 1;
205 return 0;
209 LPLISTSTRUCT ListBoxGetItem(LPHEADLIST lphl, UINT uIndex)
211 LPLISTSTRUCT lpls;
212 UINT Count = 0;
214 if (uIndex >= lphl->ItemsCount) return NULL;
216 lpls = lphl->lpFirst;
217 while (Count++ < uIndex) lpls = lpls->lpNext;
218 return lpls;
222 void ListBoxDrawItem (HWND hwnd, LPHEADLIST lphl, HDC hdc, LPLISTSTRUCT lpls,
223 RECT *rect, WORD itemAction, WORD itemState)
225 LONG dwStyle = GetWindowLong(hwnd,GWL_STYLE);
227 if (lphl->OwnerDrawn) {
228 DRAWITEMSTRUCT *dis = USER_HEAP_LIN_ADDR(lphl->hDrawItemStruct);
230 dis->CtlID = lpls->mis.CtlID;
231 dis->CtlType = lpls->mis.CtlType;
232 dis->itemID = lpls->mis.itemID;
233 dis->hDC = hdc;
234 dis->hwndItem = hwnd;
235 dis->itemData = lpls->mis.itemData;
236 dis->itemAction = itemAction;
237 dis->itemState = itemState;
238 dis->rcItem = *rect;
239 SendMessage(lphl->hParent, WM_DRAWITEM,
240 0, (LPARAM)USER_HEAP_SEG_ADDR(lphl->hDrawItemStruct));
241 } else {
242 if (itemAction == ODA_DRAWENTIRE || itemAction == ODA_SELECT) {
243 int OldBkMode;
244 DWORD dwOldTextColor = 0;
246 OldBkMode = SetBkMode(hdc, TRANSPARENT);
248 if (itemState != 0) {
249 dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
250 FillRect(hdc, rect, GetStockObject(BLACK_BRUSH));
253 if (dwStyle & LBS_USETABSTOPS) {
254 TabbedTextOut(hdc, rect->left + 5, rect->top + 2,
255 (char *)lpls->itemText, strlen((char *)lpls->itemText),
256 lphl->iNumStops, lphl->TabStops, 0);
257 } else {
258 TextOut(hdc, rect->left + 5, rect->top + 2,
259 (char *)lpls->itemText, strlen((char *)lpls->itemText));
262 if (itemState != 0) {
263 SetTextColor(hdc, dwOldTextColor);
266 SetBkMode(hdc, OldBkMode);
267 } else DrawFocusRect(hdc, rect);
270 return;
274 int ListBoxFindMouse(LPHEADLIST lphl, int X, int Y)
276 LPLISTSTRUCT lpls = lphl->lpFirst;
277 int i, j;
278 POINT point;
280 point.x = X; point.y = Y;
281 if (lphl->ItemsCount == 0) return LB_ERR;
283 for(i = 0; i < lphl->FirstVisible; i++) {
284 if (lpls == NULL) return LB_ERR;
285 lpls = lpls->lpNext;
287 for(j = 0; j < lphl->ItemsVisible; i++, j++) {
288 if (lpls == NULL) return LB_ERR;
289 if (PtInRect(&lpls->itemRect,point)) {
290 return i;
292 lpls = lpls->lpNext;
294 dprintf_listbox(stddeb,"ListBoxFindMouse: not found\n");
295 return LB_ERR;
299 void ListBoxAskMeasure(LPHEADLIST lphl, LPLISTSTRUCT lpls)
301 HANDLE hTemp = USER_HEAP_ALLOC( sizeof(MEASUREITEMSTRUCT) );
302 MEASUREITEMSTRUCT *lpmeasure = (MEASUREITEMSTRUCT *) USER_HEAP_LIN_ADDR(hTemp);
304 if (lpmeasure == NULL) {
305 fprintf(stdnimp,"ListBoxAskMeasure() out of memory !\n");
306 return;
309 *lpmeasure = lpls->mis;
310 lpmeasure->itemHeight = lphl->StdItemHeight;
311 SendMessage(lphl->hParent, WM_MEASUREITEM, 0, (LPARAM)USER_HEAP_SEG_ADDR(hTemp));
313 if (GetWindowLong(lphl->hSelf,GWL_STYLE) & LBS_OWNERDRAWFIXED) {
314 lphl->StdItemHeight = lpmeasure->itemHeight;
315 lphl->needMeasure = FALSE;
318 USER_HEAP_FREE(hTemp);
321 /* -------------------- strings and item data ---------------------- */
323 LPLISTSTRUCT ListBoxCreateItem(LPHEADLIST lphl, int id)
325 LPLISTSTRUCT lplsnew = (LPLISTSTRUCT)malloc(sizeof(LISTSTRUCT));
327 if (lplsnew == NULL) return NULL;
329 lplsnew->itemState = 0;
330 lplsnew->mis.CtlType = lphl->DrawCtlType;
331 lplsnew->mis.CtlID = lphl->CtlID;
332 lplsnew->mis.itemID = id;
333 lplsnew->mis.itemHeight = lphl->StdItemHeight;
334 lplsnew->mis.itemWidth = 0; /* ignored */
335 lplsnew->mis.itemData = 0;
336 SetRect(&lplsnew->itemRect, 0, 0, 0, 0);
338 return lplsnew;
342 int ListBoxInsertString(LPHEADLIST lphl, UINT uIndex, LPCSTR newstr)
344 LPLISTSTRUCT *lppls, lplsnew, lpls;
345 HANDLE hStr;
346 LPSTR str;
347 UINT Count;
349 dprintf_listbox(stddeb,"ListBoxInsertString(%d, %p);\n", uIndex, newstr);
351 if (!newstr) return -1;
353 if (uIndex == (UINT)-1)
354 uIndex = lphl->ItemsCount;
356 lppls = &lphl->lpFirst;
357 for(Count = 0; Count < uIndex; Count++) {
358 if (*lppls == NULL) return LB_ERR;
359 lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
362 lplsnew = ListBoxCreateItem(lphl, Count);
364 if (lplsnew == NULL) {
365 fprintf(stdnimp,"ListBoxInsertString() out of memory !\n");
366 return LB_ERRSPACE;
369 lplsnew->lpNext = *lppls;
370 *lppls = lplsnew;
371 lphl->ItemsCount++;
373 hStr = 0;
374 if (lphl->HasStrings) {
375 dprintf_listbox(stddeb," string: %s\n", newstr);
376 hStr = LIST_HEAP_ALLOC(lphl, LMEM_MOVEABLE, strlen(newstr) + 1);
377 str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
378 if (str == NULL) return LB_ERRSPACE;
379 strcpy(str, newstr);
380 lplsnew->itemText = str;
381 /* I'm not so sure about the next one */
382 lplsnew->mis.itemData = 0;
383 } else {
384 lplsnew->itemText = NULL;
385 lplsnew->mis.itemData = (DWORD)newstr;
388 lplsnew->mis.itemID = uIndex;
389 lplsnew->hData = hStr;
391 /* adjust the itemID field of the following entries */
392 for(lpls = lplsnew->lpNext; lpls != NULL; lpls = lpls->lpNext) {
393 lpls->mis.itemID++;
396 if (lphl->needMeasure) {
397 ListBoxAskMeasure(lphl, lplsnew);
400 dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
401 return uIndex;
405 int ListBoxAddString(LPHEADLIST lphl, LPCSTR newstr)
407 LONG dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
408 UINT pos = (UINT) -1;
410 if (lphl->HasStrings && (dwStyle & LBS_SORT)) {
411 LPLISTSTRUCT lpls = lphl->lpFirst;
412 for (pos = 0; lpls != NULL; lpls = lpls->lpNext, pos++)
413 if (strcmp(lpls->itemText, newstr) >= 0)
414 break;
416 return ListBoxInsertString(lphl, pos, newstr);
420 int ListBoxGetText(LPHEADLIST lphl, UINT uIndex, LPSTR OutStr)
422 LPLISTSTRUCT lpls;
424 if (!OutStr) {
425 dprintf_listbox(stddeb, "ListBoxGetText // OutStr==NULL\n");
426 return 0;
428 *OutStr = '\0';
429 lpls = ListBoxGetItem (lphl, uIndex);
430 if (lpls == NULL) return LB_ERR;
432 if (!lphl->HasStrings) {
433 *((long *)OutStr) = lpls->mis.itemData;
434 return 4;
437 strcpy(OutStr, lpls->itemText);
438 return strlen(OutStr);
442 DWORD ListBoxGetItemData(LPHEADLIST lphl, UINT uIndex)
444 LPLISTSTRUCT lpls;
446 lpls = ListBoxGetItem (lphl, uIndex);
447 if (lpls == NULL) return LB_ERR;
448 return lpls->mis.itemData;
452 int ListBoxSetItemData(LPHEADLIST lphl, UINT uIndex, DWORD ItemData)
454 LPLISTSTRUCT lpls = ListBoxGetItem(lphl, uIndex);
456 if (lpls == NULL) return LB_ERR;
457 lpls->mis.itemData = ItemData;
458 return 1;
462 int ListBoxDeleteString(LPHEADLIST lphl, UINT uIndex)
464 LPLISTSTRUCT lpls, lpls2;
465 UINT Count;
467 if (uIndex >= lphl->ItemsCount) return LB_ERR;
469 lpls = lphl->lpFirst;
470 if (lpls == NULL) return LB_ERR;
472 if (uIndex == 0)
473 lphl->lpFirst = lpls->lpNext;
474 else {
475 LPLISTSTRUCT lpls2 = NULL;
476 for(Count = 0; Count < uIndex; Count++) {
477 if (lpls->lpNext == NULL) return LB_ERR;
479 lpls2 = lpls;
480 lpls = (LPLISTSTRUCT)lpls->lpNext;
482 lpls2->lpNext = lpls->lpNext;
485 /* adjust the itemID field of the following entries */
486 for(lpls2 = lpls->lpNext; lpls2 != NULL; lpls2 = lpls2->lpNext) {
487 lpls2->mis.itemID--;
490 lphl->ItemsCount--;
492 if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
493 free(lpls);
495 return lphl->ItemsCount;
499 int ListBoxFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr)
501 LPLISTSTRUCT lpls;
502 UINT Count;
503 UINT First = nFirst + 1;
504 LPSTR lpMatchStr = (LPSTR)MatchStr;
505 LONG dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
507 if (First > lphl->ItemsCount) return LB_ERR;
509 if (lphl->HasStrings) lpMatchStr = PTR_SEG_TO_LIN(MatchStr);
511 lpls = ListBoxGetItem(lphl, First);
512 Count = 0;
513 while(lpls != NULL) {
514 if (lphl->HasStrings) {
515 if (strstr(lpls->itemText, lpMatchStr) == lpls->itemText) return Count;
516 } else if (dwStyle & LBS_SORT) {
517 /* XXX Do a compare item */
519 else
520 if (lpls->mis.itemData == (DWORD)lpMatchStr) return Count;
522 lpls = lpls->lpNext;
523 Count++;
526 /* Start over at top */
527 Count = 0;
528 lpls = lphl->lpFirst;
530 while (Count < First) {
531 if (lphl->HasStrings) {
532 if (strstr(lpls->itemText, lpMatchStr) == lpls->itemText) return Count;
533 } else if (dwStyle & LBS_SORT) {
534 /* XXX Do a compare item */
535 } else {
536 if (lpls->mis.itemData == (DWORD)lpMatchStr) return Count;
538 lpls = lpls->lpNext;
539 Count++;
542 return LB_ERR;
546 int ListBoxResetContent(LPHEADLIST lphl)
548 LPLISTSTRUCT lpls;
549 int i;
551 if (lphl->ItemsCount == 0) return 0;
553 dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n",
554 lphl->ItemsCount);
556 for(i = 0; i < lphl->ItemsCount; i++) {
557 lpls = lphl->lpFirst;
558 if (lpls == NULL) return LB_ERR;
560 lphl->lpFirst = lpls->lpNext;
561 if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
562 free(lpls);
564 ListBoxInitialize(lphl);
566 return TRUE;
569 /* --------------------- selection ------------------------- */
571 int ListBoxSetCurSel(LPHEADLIST lphl, WORD wIndex)
573 LPLISTSTRUCT lpls;
574 DWORD dwStyle = GetWindowWord(lphl->hSelf,GWL_STYLE);
576 /* use ListBoxSetSel instead */
577 if (dwStyle & LBS_MULTIPLESEL ) return 0;
579 /* unselect all previously selected */
580 if (dwStyle & LBS_EXTENDEDSEL )
581 ListBoxSetSel(lphl,-1,0);
582 else
583 /* unselect previous item */
584 if (lphl->ItemFocused != -1) {
585 lpls = ListBoxGetItem(lphl, lphl->ItemFocused);
586 if (lpls == 0) return LB_ERR;
587 lpls->itemState = 0;
590 if (wIndex != (UINT)-1) {
591 lphl->ItemFocused = wIndex;
592 lpls = ListBoxGetItem(lphl, wIndex);
593 if (lpls == 0) return LB_ERR;
594 lpls->itemState = ODS_SELECTED | ODS_FOCUS;
596 return 0;
599 return LB_ERR;
603 int ListBoxSetSel(LPHEADLIST lphl, WORD wIndex, WORD state)
605 LPLISTSTRUCT lpls;
607 if (!(GetWindowLong(lphl->hSelf,GWL_STYLE) &
608 (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
609 return 0;
611 if (wIndex == (UINT)-1) {
612 for (lpls = lphl->lpFirst; lpls != NULL; lpls = lpls->lpNext) {
613 lpls->itemState = state;
615 return 0;
618 if (wIndex >= lphl->ItemsCount) return LB_ERR;
620 lpls = ListBoxGetItem(lphl, wIndex);
621 lpls->itemState = state;
623 return 0;
627 int ListBoxGetSel(LPHEADLIST lphl, WORD wIndex)
629 LPLISTSTRUCT lpls = ListBoxGetItem(lphl, wIndex);
631 if (lpls == NULL) return LB_ERR;
632 return lpls->itemState;
635 /* ------------------------- dir listing ------------------------ */
637 LONG ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPCSTR filespec)
639 char temp[16], mask[13];
640 char *path, *p;
641 const char *ptr;
642 int skip, count;
643 LONG ret;
644 DOS_DIRENT entry;
646 dprintf_listbox(stddeb, "ListBoxDirectory: '%s' %04x\n", filespec, attrib);
647 if (!filespec) return LB_ERR;
648 if (!(ptr = DOSFS_GetUnixFileName( filespec, FALSE ))) return LB_ERR;
649 path = xstrdup(ptr);
650 p = strrchr( path, '/' );
651 *p++ = '\0';
652 if (!(ptr = DOSFS_ToDosFCBFormat( p )))
654 free( path );
655 return LB_ERR;
657 strcpy( mask, ptr );
659 dprintf_listbox(stddeb, "ListBoxDirectory: path=%s mask=%s\n", path, mask);
661 skip = ret = 0;
662 attrib &= ~FA_LABEL;
663 while ((count = DOSFS_FindNext( path, mask, 0, attrib, skip, &entry )) > 0)
665 skip += count;
666 if (entry.attr & FA_DIRECTORY)
668 if ((attrib & DDL_DIRECTORY) && strcmp(entry.name, ". "))
670 sprintf(temp, "[%s]", DOSFS_ToDosDTAFormat( entry.name ) );
671 AnsiLower( temp );
672 if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
675 else /* not a directory */
677 if (!(attrib & DDL_EXCLUSIVE) ||
678 ((attrib & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)) ==
679 (entry.attr & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE))))
681 strcpy( temp, DOSFS_ToDosDTAFormat( entry.name ) );
682 AnsiLower( temp );
683 if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
687 if (attrib & DDL_DRIVES)
689 int x;
690 strcpy( temp, "[-a-]" );
691 for (x = 0; x < MAX_DOS_DRIVES; x++, temp[2]++)
693 if (DRIVE_IsValid(x))
694 if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
697 free( path );
698 return ret;
701 /* ------------------------- dimensions ------------------------- */
703 int ListBoxGetItemRect(LPHEADLIST lphl, WORD wIndex, LPRECT lprect)
705 LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wIndex);
707 if (lpls == NULL) return LB_ERR;
708 *lprect = lpls->itemRect;
709 return 0;
713 int ListBoxSetItemHeight(LPHEADLIST lphl, WORD wIndex, long height)
715 LPLISTSTRUCT lpls;
717 if (!(GetWindowLong(lphl->hSelf,GWL_STYLE) & LBS_OWNERDRAWVARIABLE)) {
718 lphl->StdItemHeight = (short)height;
719 return 0;
722 lpls = ListBoxGetItem(lphl, wIndex);
723 if (lpls == NULL) return LB_ERR;
725 lpls->mis.itemHeight = height;
726 return 0;
729 /* -------------------------- string search ------------------------ */
731 int ListBoxFindNextMatch(LPHEADLIST lphl, WORD wChar)
733 LPLISTSTRUCT lpls;
734 UINT count,first;
736 if ((char)wChar < ' ') return LB_ERR;
737 if (!lphl->HasStrings) return LB_ERR;
739 lpls = lphl->lpFirst;
741 for (count = 0; lpls != NULL; lpls = lpls->lpNext, count++) {
742 if (tolower(*lpls->itemText) == tolower((char)wChar)) break;
744 if (lpls == NULL) return LB_ERR;
745 first = count;
746 for(; lpls != NULL; lpls = lpls->lpNext, count++) {
747 if (*lpls->itemText != (char)wChar)
748 break;
749 if (count > lphl->ItemFocused)
750 return count;
752 return first;
755 /***********************************************************************
756 * LBCreate
758 static LONG LBCreate(HWND hwnd, WORD wParam, LONG lParam)
760 LPHEADLIST lphl;
761 LONG dwStyle = GetWindowLong(hwnd,GWL_STYLE);
762 RECT rect;
764 CreateListBoxStruct(hwnd, ODT_LISTBOX, dwStyle, GetParent(hwnd));
765 lphl = ListBoxGetStorageHeader(hwnd);
766 dprintf_listbox(stddeb,"ListBox created: lphl = %p dwStyle = %04x:%04x\n",
767 lphl, HIWORD(dwStyle), LOWORD(dwStyle));
769 GetClientRect(hwnd,&rect);
770 lphl->ColumnsWidth = rect.right - rect.left;
772 SetScrollRange(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
773 SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
775 return 0;
778 /***********************************************************************
779 * LBDestroy
781 static LONG LBDestroy(HWND hwnd, WORD wParam, LONG lParam)
783 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
785 ListBoxResetContent(lphl);
787 DestroyListBoxStruct(lphl);
788 dprintf_listbox(stddeb,"ListBox destroyed: lphl = %p\n",lphl);
789 return 0;
792 /***********************************************************************
793 * LBVScroll
795 static LONG LBVScroll(HWND hwnd, WORD wParam, LONG lParam)
797 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
798 int y;
800 dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
801 wParam, lParam);
802 y = lphl->FirstVisible;
804 switch(wParam) {
805 case SB_LINEUP:
806 if (lphl->FirstVisible > 0)
807 lphl->FirstVisible--;
808 break;
810 case SB_LINEDOWN:
811 lphl->FirstVisible++;
812 break;
814 case SB_PAGEUP:
815 if (lphl->FirstVisible > lphl->ItemsVisible) {
816 lphl->FirstVisible -= lphl->ItemsVisible;
817 } else {
818 lphl->FirstVisible = 0;
820 break;
822 case SB_PAGEDOWN:
823 lphl->FirstVisible += lphl->ItemsVisible;
824 break;
826 case SB_THUMBTRACK:
827 lphl->FirstVisible = LOWORD(lParam);
828 break;
831 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
832 lphl->FirstVisible = ListMaxFirstVisible(lphl);
834 if (y != lphl->FirstVisible) {
835 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
836 InvalidateRect(hwnd, NULL, TRUE);
838 return 0;
841 /***********************************************************************
842 * LBHScroll
844 static LONG LBHScroll(HWND hwnd, WORD wParam, LONG lParam)
846 LPHEADLIST lphl;
847 int y;
849 dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
850 wParam, lParam);
851 lphl = ListBoxGetStorageHeader(hwnd);
852 y = lphl->FirstVisible;
853 switch(wParam) {
854 case SB_LINEUP:
855 if (lphl->FirstVisible > lphl->ItemsPerColumn) {
856 lphl->FirstVisible -= lphl->ItemsPerColumn;
857 } else {
858 lphl->FirstVisible = 0;
860 break;
861 case SB_LINEDOWN:
862 lphl->FirstVisible += lphl->ItemsPerColumn;
863 break;
864 case SB_PAGEUP:
865 if (lphl->ItemsPerColumn != 0) {
866 int lbsub = lphl->ItemsVisible / lphl->ItemsPerColumn * lphl->ItemsPerColumn;
867 if (lphl->FirstVisible > lbsub) {
868 lphl->FirstVisible -= lbsub;
869 } else {
870 lphl->FirstVisible = 0;
873 break;
874 case SB_PAGEDOWN:
875 if (lphl->ItemsPerColumn != 0)
876 lphl->FirstVisible += lphl->ItemsVisible /
877 lphl->ItemsPerColumn * lphl->ItemsPerColumn;
878 break;
879 case SB_THUMBTRACK:
880 lphl->FirstVisible = lphl->ItemsPerColumn * LOWORD(lParam);
881 break;
883 if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
884 lphl->FirstVisible = ListMaxFirstVisible(lphl);
886 if (lphl->ItemsPerColumn != 0) {
887 lphl->FirstVisible = lphl->FirstVisible /
888 lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
889 if (y != lphl->FirstVisible) {
890 SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible /
891 lphl->ItemsPerColumn + 1, TRUE);
892 InvalidateRect(hwnd, NULL, TRUE);
895 return 0;
898 /***********************************************************************
899 * LBLButtonDown
901 static LONG LBLButtonDown(HWND hwnd, WORD wParam, LONG lParam)
903 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
904 WORD wRet;
905 int y;
906 RECT rectsel;
907 LONG dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
908 POINT tmpPOINT;
909 tmpPOINT.x = LOWORD(lParam); tmpPOINT.y = HIWORD(lParam);
911 SetFocus(hwnd);
912 SetCapture(hwnd);
914 lphl->PrevFocused = lphl->ItemFocused;
916 y = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
917 if (y == -1)
918 return 0;
920 if (dwStyle & LBS_MULTIPLESEL) {
921 lphl->ItemFocused = y;
922 wRet = ListBoxGetSel(lphl, y);
923 ListBoxSetSel(lphl, y, !wRet);
925 InvalidateRect(hwnd, NULL, TRUE);
926 } else {
927 ListBoxSetCurSel(lphl, y);
929 ListBoxGetItemRect(lphl, y, &rectsel);
930 InvalidateRect(hwnd, &rectsel, TRUE);
931 if(lphl->PrevFocused) {
932 ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
933 InvalidateRect(hwnd, &rectsel, TRUE);
937 if (dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))
938 ListBoxSendNotification(lphl, LBN_SELCHANGE);
940 if (dwStyle & LBS_NOTIFY)
941 SendMessage(lphl->hParent, WM_LBTRACKPOINT, y, lParam);
942 #ifndef WINELIB
943 if (GetWindowLong(lphl->hSelf,GWL_EXSTYLE) & WS_EX_DRAGDETECT)
944 if( DragDetect(lphl->hSelf,tmpPOINT) )
945 SendMessage(lphl->hParent, WM_BEGINDRAG,0,0L);
946 #endif
947 return 0;
950 /***********************************************************************
951 * LBLButtonUp
953 static LONG LBLButtonUp(HWND hwnd, WORD wParam, LONG lParam)
955 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
957 if (GetCapture() == hwnd) ReleaseCapture();
959 if (lphl->PrevFocused != lphl->ItemFocused)
960 ListBoxSendNotification(lphl, LBN_SELCHANGE);
962 return 0;
965 /***********************************************************************
966 * LBRButtonUp
968 static LONG LBRButtonUp(HWND hwnd, WORD wParam, LONG lParam)
970 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
972 #ifdef WINELIB32
973 SendMessage(lphl->hParent, WM_COMMAND,
974 MAKEWPARAM(GetWindowWord(hwnd,GWW_ID),LBN_DBLCLK),
975 (LPARAM)hwnd);
976 #else
977 SendMessage(lphl->hParent, WM_COMMAND, GetWindowWord(hwnd,GWW_ID),
978 MAKELONG(hwnd, LBN_DBLCLK));
979 #endif
981 return 0;
984 /***********************************************************************
985 * LBMouseMove
987 static LONG LBMouseMove(HWND hwnd, WORD wParam, LONG lParam)
989 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
990 int y;
991 WORD wRet;
992 LONG dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
993 RECT rect, rectsel; /* XXX Broken */
995 dprintf_listbox(stddeb,"LBMouseMove %d %d\n",SLOWORD(lParam),SHIWORD(lParam));
996 if ((wParam & MK_LBUTTON) != 0) {
997 y = SHIWORD(lParam);
998 if (y < 0) {
999 if (lphl->FirstVisible > 0) {
1000 lphl->FirstVisible--;
1001 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1002 InvalidateRect(hwnd, NULL, TRUE);
1003 return 0;
1006 GetClientRect(hwnd, &rect);
1007 if (y >= rect.bottom) {
1008 if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
1009 lphl->FirstVisible++;
1010 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1011 InvalidateRect(hwnd, NULL, TRUE);
1012 return 0;
1015 if ((y > 0) && (y < (rect.bottom - 4))) {
1016 if ((y < rectsel.top) || (y > rectsel.bottom)) {
1017 wRet = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
1018 if (wRet == lphl->ItemFocused) {
1019 return 0;
1021 if (dwStyle & LBS_MULTIPLESEL) {
1022 lphl->ItemFocused = wRet;
1023 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1024 } else {
1025 ListBoxSetCurSel(lphl, wRet);
1026 if(dwStyle & LBS_EXTENDEDSEL)
1027 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1029 ListBoxGetItemRect(lphl, wRet, &rectsel);
1030 InvalidateRect(hwnd, &rectsel, TRUE);
1035 return 0;
1038 /***********************************************************************
1039 * LBKeyDown
1041 * Doesn't yet handle properly VK_SHIFT with LB_EXTENDEDSEL
1043 static LONG LBKeyDown(HWND hwnd, WORD wParam, LONG lParam)
1045 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1046 LONG dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
1047 WORD newFocused = 0xFFFF;
1048 RECT rect;
1050 ListBoxGetItemRect(lphl,lphl->ItemFocused,&rect);
1051 switch(wParam)
1053 /* ugly kludge that belongs in TranslateMessage */
1055 case VK_HOME:
1056 case VK_END:
1057 case VK_LEFT:
1058 case VK_RIGHT:
1059 case VK_UP:
1060 case VK_DOWN:
1061 case VK_PRIOR:
1062 case VK_NEXT:
1063 if ( dwStyle & LBS_WANTKEYBOARDINPUT )
1065 newFocused = (WORD)(INT)SendMessage(lphl->hParent,WM_VKEYTOITEM,
1066 wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
1067 if ( newFocused == 0xFFFE ) return 0L;
1069 if ( newFocused == 0xFFFF )
1071 newFocused = lphl->ItemFocused;
1073 /* nested switch */
1074 switch(wParam)
1076 case VK_HOME:
1077 newFocused = 0;
1078 break;
1079 case VK_END:
1080 newFocused = lphl->ItemsCount - 1;
1081 break;
1082 case VK_LEFT:
1083 if (dwStyle & LBS_MULTICOLUMN) {
1084 if (newFocused >= lphl->ItemsPerColumn) {
1085 newFocused -= lphl->ItemsPerColumn;
1086 } else {
1087 newFocused = 0;
1090 break;
1091 case VK_UP:
1092 if (newFocused > 0) newFocused--;
1093 break;
1094 case VK_RIGHT:
1095 if (dwStyle & LBS_MULTICOLUMN)
1096 newFocused += lphl->ItemsPerColumn;
1097 break;
1098 case VK_DOWN:
1099 newFocused++;
1100 break;
1101 case VK_PRIOR:
1102 if (newFocused > lphl->ItemsVisible)
1103 newFocused -= lphl->ItemsVisible;
1104 else newFocused = 0;
1105 break;
1106 case VK_NEXT:
1107 newFocused += lphl->ItemsVisible;
1108 break;
1109 default:
1110 return 0;
1112 /* end of nested switch */
1114 break;
1115 case VK_SPACE:
1116 if (dwStyle & LBS_MULTIPLESEL)
1118 WORD wRet = ListBoxGetSel(lphl, lphl->ItemFocused);
1119 ListBoxSetSel(lphl, lphl->ItemFocused, !wRet);
1121 return 0;
1123 /* chars are handled in LBChar */
1124 default:
1125 return 0;
1128 /* at this point newFocused is set up */
1130 if (newFocused >= lphl->ItemsCount)
1131 newFocused = lphl->ItemsCount - 1;
1133 if (!(dwStyle & LBS_MULTIPLESEL))
1135 ListBoxSetCurSel(lphl, newFocused);
1136 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1139 lphl->ItemFocused = newFocused;
1141 if( ListBoxScrollToFocus(lphl) || (dwStyle &
1142 (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) )
1143 InvalidateRect(hwnd, NULL, TRUE);
1144 else
1146 InvalidateRect(hwnd, &rect, TRUE);
1147 if( newFocused < 0x8000 )
1149 ListBoxGetItemRect(lphl, newFocused, &rect);
1150 InvalidateRect(hwnd, &rect, TRUE);
1154 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1156 return 0;
1159 /***********************************************************************
1160 * LBChar
1162 static LONG LBChar(HWND hwnd, WORD wParam, LONG lParam)
1164 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1165 LONG dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
1166 WORD newFocused = 0xFFFF;
1168 if ( (dwStyle & LBS_WANTKEYBOARDINPUT) && !(lphl->HasStrings))
1170 newFocused = (WORD)(INT)SendMessage(lphl->hParent,WM_CHARTOITEM,
1171 wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
1172 if ( newFocused == 0xFFFE ) return 0L;
1175 if (newFocused == 0xFFFF )
1176 newFocused = ListBoxFindNextMatch(lphl, wParam);
1178 if (newFocused == (WORD)LB_ERR) return 0;
1180 if (newFocused >= lphl->ItemsCount)
1181 newFocused = lphl->ItemsCount - 1;
1183 if (!(dwStyle & LBS_MULTIPLESEL))
1185 ListBoxSetCurSel(lphl, newFocused);
1186 ListBoxSendNotification(lphl, LBN_SELCHANGE);
1189 lphl->ItemFocused = newFocused;
1190 ListBoxScrollToFocus(lphl);
1191 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1193 InvalidateRect(hwnd, NULL, TRUE);
1195 return 0;
1198 /***********************************************************************
1199 * LBSetRedraw
1201 static LONG LBSetRedraw(HWND hwnd, WORD wParam, LONG lParam)
1203 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1205 dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd="NPFMT" w=%04X !\n",
1206 hwnd, wParam);
1207 lphl->bRedrawFlag = wParam;
1209 return 0;
1212 /***********************************************************************
1213 * LBSetFont
1215 static LONG LBSetFont(HWND hwnd, WPARAM wParam, LPARAM lParam)
1217 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1219 if (wParam == 0)
1220 lphl->hFont = GetStockObject(SYSTEM_FONT);
1221 else
1222 lphl->hFont = (HFONT) wParam;
1224 return 0;
1227 /***********************************************************************
1228 * LBPaint
1230 static LONG LBPaint(HWND hwnd, WORD wParam, LONG lParam)
1232 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1233 LONG dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
1234 LPLISTSTRUCT lpls;
1235 PAINTSTRUCT ps;
1236 HBRUSH hBrush;
1237 HFONT hOldFont;
1238 HDC hdc;
1239 RECT rect;
1240 int i, top, height, maxwidth, ipc;
1242 top = 0;
1243 hdc = BeginPaint( hwnd, &ps );
1245 if (!IsWindowVisible(hwnd) || !lphl->bRedrawFlag) {
1246 EndPaint(hwnd, &ps);
1247 return 0;
1250 hOldFont = SelectObject(hdc, lphl->hFont);
1252 #ifdef WINELIB32
1253 hBrush = (HBRUSH) SendMessage(lphl->hParent, WM_CTLCOLORLISTBOX, (WPARAM)hdc,
1254 (LPARAM)hwnd);
1255 #else
1256 hBrush = SendMessage(lphl->hParent, WM_CTLCOLOR, hdc,
1257 MAKELONG(hwnd, CTLCOLOR_LISTBOX));
1258 #endif
1260 if (hBrush == 0) hBrush = GetStockObject(WHITE_BRUSH);
1262 GetClientRect(hwnd, &rect);
1263 FillRect(hdc, &rect, hBrush);
1265 maxwidth = rect.right;
1266 if (dwStyle & LBS_MULTICOLUMN) {
1267 rect.right = lphl->ColumnsWidth;
1269 lpls = lphl->lpFirst;
1271 lphl->ItemsVisible = 0;
1272 lphl->ItemsPerColumn = ipc = 0;
1274 for(i = 0; i < lphl->ItemsCount; i++) {
1275 if (lpls == NULL) break;
1277 if (i >= lphl->FirstVisible) {
1278 height = lpls->mis.itemHeight;
1280 if (top > rect.bottom) {
1281 if (dwStyle & LBS_MULTICOLUMN) {
1282 lphl->ItemsPerColumn = MAX(lphl->ItemsPerColumn, ipc);
1283 ipc = 0;
1284 top = 0;
1285 rect.left += lphl->ColumnsWidth;
1286 rect.right += lphl->ColumnsWidth;
1287 if (rect.left > maxwidth) break;
1288 } else {
1289 break;
1293 lpls->itemRect.top = top;
1294 lpls->itemRect.bottom = top + height;
1295 lpls->itemRect.left = rect.left;
1296 lpls->itemRect.right = rect.right;
1298 dprintf_listbox(stddeb,"drawing item: %ld %d %ld %d %d\n",(LONG)rect.left,top,(LONG)rect.right,top+height,lpls->itemState);
1299 if (lphl->OwnerDrawn) {
1300 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE, 0);
1301 if (lpls->itemState)
1302 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_SELECT, ODS_SELECTED);
1303 } else {
1304 ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
1305 lpls->itemState);
1307 if ((lphl->ItemFocused == i) && GetFocus() == hwnd)
1308 ListBoxDrawItem (hwnd,lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS, ODS_FOCUS);
1310 top += height;
1311 lphl->ItemsVisible++;
1312 ipc++;
1315 lpls = lpls->lpNext;
1317 ListBoxUpdateWindow(hwnd,lphl,FALSE);
1318 SelectObject(hdc,hOldFont);
1319 EndPaint( hwnd, &ps );
1320 return 0;
1323 /***********************************************************************
1324 * LBSetFocus
1326 static LONG LBSetFocus(HWND hwnd, WORD wParam, LONG lParam)
1328 dprintf_listbox(stddeb,"ListBox WM_SETFOCUS !\n");
1330 return 0;
1333 /***********************************************************************
1334 * LBKillFocus
1336 static LONG LBKillFocus(HWND hwnd, WORD wParam, LONG lParam)
1338 dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS !\n");
1340 InvalidateRect(hwnd, NULL, TRUE);
1342 return 0;
1345 /***********************************************************************
1346 * LBResetContent
1348 static LONG LBResetContent(HWND hwnd, WORD wParam, LONG lParam)
1350 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1352 dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
1353 ListBoxResetContent(lphl);
1354 ListBoxUpdateWindow(hwnd, lphl, TRUE);
1355 return 0;
1358 /***********************************************************************
1359 * LBDir
1361 static LONG LBDir(HWND hwnd, WORD wParam, LONG lParam)
1363 LONG ret;
1364 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1365 dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
1367 ret = ListBoxDirectory(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
1368 ListBoxUpdateWindow(hwnd, lphl, TRUE);
1369 return ret;
1372 /***********************************************************************
1373 * LBAddString
1375 static LONG LBAddString(HWND hwnd, WORD wParam, LONG lParam)
1377 WORD wRet;
1378 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1380 if (lphl->HasStrings)
1381 wRet = ListBoxAddString(lphl, (LPCSTR)PTR_SEG_TO_LIN(lParam));
1382 else
1383 wRet = ListBoxAddString(lphl, (LPCSTR)lParam);
1385 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1386 return wRet;
1389 /***********************************************************************
1390 * LBGetText
1392 static LONG LBGetText(HWND hwnd, WORD wParam, LONG lParam)
1394 LONG wRet;
1395 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1397 dprintf_listbox(stddeb, "LB_GETTEXT wParam=%d\n",wParam);
1398 wRet = ListBoxGetText(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
1400 return wRet;
1403 /***********************************************************************
1404 * LBInsertString
1406 static LONG LBInsertString(HWND hwnd, WORD wParam, LONG lParam)
1408 WORD wRet;
1409 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1411 if (lphl->HasStrings)
1412 wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)PTR_SEG_TO_LIN(lParam));
1413 else
1414 wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)lParam);
1416 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1417 return wRet;
1420 /***********************************************************************
1421 * LBDeleteString
1423 static LONG LBDeleteString(HWND hwnd, WORD wParam, LONG lParam)
1425 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1426 LONG lRet = ListBoxDeleteString(lphl,wParam);
1428 ListBoxUpdateWindow(hwnd,lphl,TRUE);
1429 return lRet;
1432 /***********************************************************************
1433 * LBFindString
1435 static LONG LBFindString(HWND hwnd, WORD wParam, LONG lParam)
1437 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1438 return ListBoxFindString(lphl, wParam, (SEGPTR)lParam);
1441 /***********************************************************************
1442 * LBGetCaretIndex
1444 static LONG LBGetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
1446 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1447 return lphl->ItemFocused;
1450 /***********************************************************************
1451 * LBGetCount
1453 static LONG LBGetCount(HWND hwnd, WORD wParam, LONG lParam)
1455 LPHEADLIST lphl;
1457 lphl = ListBoxGetStorageHeader(hwnd);
1458 return lphl->ItemsCount;
1461 /***********************************************************************
1462 * LBGetCurSel
1464 static LONG LBGetCurSel(HWND hwnd, WORD wParam, LONG lParam)
1466 LPHEADLIST lphl;
1468 lphl = ListBoxGetStorageHeader(hwnd);
1469 dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %u !\n",
1470 lphl->ItemFocused);
1471 return lphl->ItemFocused;
1474 /***********************************************************************
1475 * LBGetHorizontalExtent
1477 static LONG LBGetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
1479 return 0;
1482 /***********************************************************************
1483 * LBGetItemHeight
1485 static LONG LBGetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
1487 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1488 LPLISTSTRUCT lpls = ListBoxGetItem (lphl, wParam);
1490 if (lpls == NULL) return LB_ERR;
1491 return lpls->mis.itemHeight;
1494 /***********************************************************************
1495 * LBGetItemRect
1497 static LONG LBGetItemRect(HWND hwnd, WORD wParam, LONG lParam)
1499 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1500 return ListBoxGetItemRect(lphl, wParam, PTR_SEG_TO_LIN(lParam));
1503 /***********************************************************************
1504 * LBGetSel
1506 static LONG LBGetSel(HWND hwnd, WORD wParam, LONG lParam)
1508 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1509 return (ListBoxGetSel(lphl, wParam) )? 1 : 0;
1512 /***********************************************************************
1513 * LBGetSelCount
1515 static LONG LBGetSelCount(HWND hwnd, WORD wParam, LONG lParam)
1517 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1518 LPLISTSTRUCT lpls;
1519 int cnt = 0;
1520 int items = 0;
1522 if (!(GetWindowLong(lphl->hSelf,GWL_STYLE) &
1523 (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1524 return LB_ERR;
1526 for( lpls = lphl->lpFirst;
1527 lpls;
1528 lpls = lpls->lpNext )
1530 items++;
1531 if (lpls->itemState )
1532 cnt++;
1535 return cnt;
1538 /***********************************************************************
1539 * LBGetSelItems
1541 static LONG LBGetSelItems(HWND hwnd, WORD wParam, LONG lParam)
1543 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1544 LPLISTSTRUCT lpls;
1545 int cnt, idx;
1546 int *lpItems = PTR_SEG_TO_LIN(lParam);
1548 if (!(GetWindowLong(lphl->hSelf,GWL_STYLE) &
1549 (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1550 return LB_ERR;
1552 if (wParam == 0) return 0;
1554 lpls = lphl->lpFirst;
1555 cnt = 0; idx = 0;
1557 while (lpls != NULL) {
1558 if (lpls->itemState > 0) lpItems[cnt++] = idx;
1560 if (cnt == wParam) break;
1561 idx++;
1562 lpls = lpls->lpNext;
1565 return cnt;
1568 /***********************************************************************
1569 * LBGetTextLen
1571 static LONG LBGetTextLen(HWND hwnd, WORD wParam, LONG lParam)
1573 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1574 LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wParam);
1576 if (lpls == NULL || !lphl->HasStrings) return LB_ERR;
1577 return strlen(lpls->itemText);
1580 /***********************************************************************
1581 * LBGetDlgCode
1583 static LONG LBGetDlgCode(HWND hwnd, WORD wParam, LONG lParam)
1585 return DLGC_WANTARROWS | DLGC_WANTCHARS;
1588 /***********************************************************************
1589 * LBGetTopIndex
1591 static LONG LBGetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
1593 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1595 return lphl->FirstVisible;
1599 /***********************************************************************
1600 * LBSelectString
1602 static LONG LBSelectString(HWND hwnd, WORD wParam, LONG lParam)
1604 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1605 WORD wRet;
1607 wRet = ListBoxFindString(lphl, wParam, (SEGPTR)lParam);
1609 /* XXX add functionality here */
1611 return 0;
1614 /***********************************************************************
1615 * LBSelItemRange
1617 static LONG LBSelItemRange(HWND hwnd, WORD wParam, LONG lParam)
1619 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1620 LPLISTSTRUCT lpls;
1621 WORD cnt;
1622 WORD first = LOWORD(lParam);
1623 WORD last = HIWORD(lParam);
1624 BOOL select = wParam;
1626 if (!(GetWindowLong(lphl->hSelf,GWL_STYLE) &
1627 (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
1628 return LB_ERR;
1630 if (first >= lphl->ItemsCount ||
1631 last >= lphl->ItemsCount) return LB_ERR;
1633 lpls = lphl->lpFirst;
1634 cnt = 0;
1636 while (lpls != NULL) {
1637 if (cnt++ >= first)
1638 lpls->itemState = select ? ODS_SELECTED : 0;
1640 if (cnt > last)
1641 break;
1643 lpls = lpls->lpNext;
1646 return 0;
1649 /***********************************************************************
1650 * LBSetCaretIndex
1652 static LONG LBSetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
1654 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1656 if (!(GetWindowLong(lphl->hSelf,GWL_STYLE) & LBS_MULTIPLESEL)) return 0;
1657 if (wParam >= lphl->ItemsCount) return LB_ERR;
1659 lphl->ItemFocused = wParam;
1660 ListBoxScrollToFocus (lphl);
1662 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1663 InvalidateRect(hwnd, NULL, TRUE);
1664 return 0;
1667 /***********************************************************************
1668 * LBSetColumnWidth
1670 static LONG LBSetColumnWidth(HWND hwnd, WORD wParam, LONG lParam)
1672 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1673 lphl->ColumnsWidth = wParam;
1674 InvalidateRect(hwnd,NULL,TRUE);
1675 return 0;
1678 /***********************************************************************
1679 * LBSetHorizontalExtent
1681 static LONG LBSetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
1683 return 0;
1686 /***********************************************************************
1687 * LBGetItemData
1689 static LONG LBGetItemData(HWND hwnd, WORD wParam, LONG lParam)
1691 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1692 dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
1693 return ListBoxGetItemData(lphl, wParam);
1696 /***********************************************************************
1697 * LBSetItemData
1699 static LONG LBSetItemData(HWND hwnd, WORD wParam, LONG lParam)
1701 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1702 dprintf_listbox(stddeb, "LB_SETITEMDATA wParam=%x lParam=%lx\n", wParam, lParam);
1703 return ListBoxSetItemData(lphl, wParam, lParam);
1706 /***********************************************************************
1707 * LBSetTabStops
1709 static LONG LBSetTabStops(HWND hwnd, WORD wParam, LONG lParam)
1711 LPHEADLIST lphl;
1713 lphl = ListBoxGetStorageHeader(hwnd);
1715 if (lphl->TabStops != NULL) {
1716 lphl->iNumStops = 0;
1717 free (lphl->TabStops);
1720 lphl->TabStops = malloc (wParam * sizeof (short));
1721 if (lphl->TabStops) {
1722 lphl->iNumStops = wParam;
1723 memcpy (lphl->TabStops, PTR_SEG_TO_LIN(lParam), wParam * sizeof (short));
1724 return TRUE;
1727 return FALSE;
1730 /***********************************************************************
1731 * LBSetCurSel
1733 static LONG LBSetCurSel(HWND hwnd, WORD wParam, LONG lParam)
1735 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1736 WORD wRet;
1738 dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n",
1739 wParam);
1741 wRet = ListBoxSetCurSel(lphl, wParam);
1743 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1744 InvalidateRect(hwnd, NULL, TRUE);
1746 return wRet;
1749 /***********************************************************************
1750 * LBSetSel
1752 static LONG LBSetSel(HWND hwnd, WORD wParam, LONG lParam)
1754 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1755 WORD wRet;
1757 dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
1759 wRet = ListBoxSetSel(lphl, LOWORD(lParam), wParam);
1760 InvalidateRect(hwnd, NULL, TRUE);
1762 return wRet;
1765 /***********************************************************************
1766 * LBSetTopIndex
1768 static LONG LBSetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
1770 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1772 dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
1773 wParam);
1774 lphl->FirstVisible = wParam;
1775 SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
1777 InvalidateRect(hwnd, NULL, TRUE);
1779 return 0;
1782 /***********************************************************************
1783 * LBSetItemHeight
1785 static LONG LBSetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
1787 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1788 WORD wRet;
1790 dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
1791 wRet = ListBoxSetItemHeight(lphl, wParam, lParam);
1792 InvalidateRect(hwnd,NULL,TRUE);
1793 return wRet;
1796 /***********************************************************************
1797 * LBPassToParent
1799 static LRESULT LBPassToParent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1801 WND* ptrWnd = WIN_FindWndPtr(hwnd);
1803 if( ptrWnd )
1804 if( /* !(ptrWnd->dwExStyle & WS_EX_NOPARENTNOTIFY) && */
1805 ptrWnd->hwndParent )
1806 return SendMessage(ptrWnd->hwndParent,message,wParam,lParam);
1807 return 0;
1810 /***********************************************************************
1811 * ListBoxWndProc
1813 LRESULT ListBoxWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1815 switch (message) {
1816 case WM_CREATE: return LBCreate(hwnd, wParam, lParam);
1817 case WM_DESTROY: return LBDestroy(hwnd, wParam, lParam);
1818 case WM_GETDLGCODE: return LBGetDlgCode(hwnd, wParam, lParam);
1819 case WM_VSCROLL: return LBVScroll(hwnd, wParam, lParam);
1820 case WM_HSCROLL: return LBHScroll(hwnd, wParam, lParam);
1821 case WM_LBUTTONDOWN: return LBLButtonDown(hwnd, wParam, lParam);
1822 case WM_LBUTTONUP: return LBLButtonUp(hwnd, wParam, lParam);
1823 case WM_RBUTTONUP: return LBRButtonUp(hwnd, wParam, lParam);
1824 case WM_LBUTTONDBLCLK: return LBRButtonUp(hwnd, wParam, lParam);
1825 case WM_MOUSEMOVE: return LBMouseMove(hwnd, wParam, lParam);
1826 case WM_KEYDOWN: return LBKeyDown(hwnd, wParam, lParam);
1827 case WM_CHAR: return LBChar(hwnd, wParam, lParam);
1828 case WM_SETFONT: return LBSetFont(hwnd, wParam, lParam);
1829 case WM_SETREDRAW: return LBSetRedraw(hwnd, wParam, lParam);
1830 case WM_PAINT: return LBPaint(hwnd, wParam, lParam);
1831 case WM_SETFOCUS: return LBSetFocus(hwnd, wParam, lParam);
1832 case WM_KILLFOCUS: return LBKillFocus(hwnd, wParam, lParam);
1833 case LB_RESETCONTENT: return LBResetContent(hwnd, wParam, lParam);
1834 case LB_DIR: return LBDir(hwnd, wParam, lParam);
1835 case LB_ADDSTRING: return LBAddString(hwnd, wParam, lParam);
1836 case LB_INSERTSTRING: return LBInsertString(hwnd, wParam, lParam);
1837 case LB_DELETESTRING: return LBDeleteString(hwnd, wParam, lParam);
1838 case LB_FINDSTRING: return LBFindString(hwnd, wParam, lParam);
1839 case LB_GETCARETINDEX: return LBGetCaretIndex(hwnd, wParam, lParam);
1840 case LB_GETCOUNT: return LBGetCount(hwnd, wParam, lParam);
1841 case LB_GETCURSEL: return LBGetCurSel(hwnd, wParam, lParam);
1842 case LB_GETHORIZONTALEXTENT: return LBGetHorizontalExtent(hwnd, wParam, lParam);
1843 case LB_GETITEMDATA: return LBGetItemData(hwnd, wParam, lParam);
1844 case LB_GETITEMHEIGHT: return LBGetItemHeight(hwnd, wParam, lParam);
1845 case LB_GETITEMRECT: return LBGetItemRect(hwnd, wParam, lParam);
1846 case LB_GETSEL: return LBGetSel(hwnd, wParam, lParam);
1847 case LB_GETSELCOUNT: return LBGetSelCount(hwnd, wParam, lParam);
1848 case LB_GETSELITEMS: return LBGetSelItems(hwnd, wParam, lParam);
1849 case LB_GETTEXT: return LBGetText(hwnd, wParam, lParam);
1850 case LB_GETTEXTLEN: return LBGetTextLen(hwnd, wParam, lParam);
1851 case LB_GETTOPINDEX: return LBGetTopIndex(hwnd, wParam, lParam);
1852 case LB_SELECTSTRING: return LBSelectString(hwnd, wParam, lParam);
1853 case LB_SELITEMRANGE: return LBSelItemRange(hwnd, wParam, lParam);
1854 case LB_SETCARETINDEX: return LBSetCaretIndex(hwnd, wParam, lParam);
1855 case LB_SETCOLUMNWIDTH: return LBSetColumnWidth(hwnd, wParam, lParam);
1856 case LB_SETHORIZONTALEXTENT: return LBSetHorizontalExtent(hwnd, wParam, lParam);
1857 case LB_SETITEMDATA: return LBSetItemData(hwnd, wParam, lParam);
1858 case LB_SETTABSTOPS: return LBSetTabStops(hwnd, wParam, lParam);
1859 case LB_SETCURSEL: return LBSetCurSel(hwnd, wParam, lParam);
1860 case LB_SETSEL: return LBSetSel(hwnd, wParam, lParam);
1861 case LB_SETTOPINDEX: return LBSetTopIndex(hwnd, wParam, lParam);
1862 case LB_SETITEMHEIGHT: return LBSetItemHeight(hwnd, wParam, lParam);
1864 case WM_DROPFILES: return LBPassToParent(hwnd, message, wParam, lParam);
1866 case WM_DROPOBJECT:
1867 case WM_QUERYDROPOBJECT:
1868 case WM_DRAGSELECT:
1869 case WM_DRAGMOVE:
1871 LPDRAGINFO lpDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN((SEGPTR)lParam);
1872 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
1874 /* more undocumented Microsoft crap - drag&drop depends on it - AK */
1876 lpDragInfo->l = ListBoxFindMouse(lphl,lpDragInfo->pt.x,
1877 lpDragInfo->pt.y);
1879 return LBPassToParent(hwnd, message, wParam, lParam);
1883 return DefWindowProc(hwnd, message, wParam, lParam);
1887 /**********************************************************************
1888 * DlgDirSelect (USER.99)
1890 BOOL DlgDirSelect( HWND hDlg, LPSTR lpStr, INT id )
1892 char buffer[20];
1893 INT i;
1895 dprintf_listbox( stddeb, "DlgDirSelect: "NPFMT" '%s' %d\n",
1896 hDlg, lpStr, id );
1897 if ((i = SendDlgItemMessage( hDlg, id, LB_GETCURSEL, 0, 0 )) == LB_ERR)
1898 return FALSE;
1899 SendDlgItemMessage( hDlg, id, LB_GETTEXT, i, MAKE_SEGPTR(buffer) );
1900 if (buffer[0] == '[') /* drive or directory */
1902 if (buffer[1] == '-') /* drive */
1904 lpStr[0] = buffer[2];
1905 lpStr[1] = ':';
1906 lpStr[2] = '\0';
1907 dprintf_listbox( stddeb, "Returning drive '%s'\n", lpStr );
1908 return TRUE;
1910 strcpy( lpStr, buffer + 1 );
1911 lpStr[strlen(lpStr)-1] = '\\';
1912 dprintf_listbox( stddeb, "Returning directory '%s'\n", lpStr );
1913 return TRUE;
1915 strcpy( lpStr, buffer );
1916 dprintf_listbox( stddeb, "Returning file '%s'\n", lpStr );
1917 return FALSE;
1921 /**********************************************************************
1922 * DlgDirList (USER.100)
1924 INT DlgDirList( HWND hDlg, SEGPTR spec, INT idLBox, INT idStatic, UINT attrib )
1926 char *filespec = (char *)PTR_SEG_TO_LIN( spec );
1927 int drive;
1928 HWND hwnd;
1930 #define SENDMSG(msg,wparam,lparam) \
1931 ((attrib & DDL_POSTMSGS) ? PostMessage( hwnd, msg, wparam, lparam ) \
1932 : SendMessage( hwnd, msg, wparam, lparam ))
1934 dprintf_listbox( stddeb, "DlgDirList: "NPFMT" '%s' %d %d %04x\n",
1935 hDlg, filespec ? filespec : "NULL",
1936 idLBox, idStatic, attrib );
1938 if (filespec && filespec[0] && (filespec[1] == ':'))
1940 drive = toupper( filespec[0] ) - 'A';
1941 filespec += 2;
1942 if (!DRIVE_SetCurrentDrive( drive )) return FALSE;
1944 else drive = DRIVE_GetCurrentDrive();
1946 if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
1948 char mask[20];
1949 char temp[] = "*.*";
1951 if (!filespec[0]) strcpy( mask, "*.*" );
1952 else
1954 const char *ptr;
1955 BYTE attr;
1956 if (((ptr = DOSFS_GetUnixFileName( filespec, TRUE )) != NULL) &&
1957 FILE_Stat( ptr, &attr, NULL, NULL, NULL ) &&
1958 (attr & FA_DIRECTORY))
1960 /* If the path exists and is a directory, chdir to it */
1961 if (!DRIVE_Chdir( drive, filespec )) return FALSE;
1962 strcpy( mask, "*.*" );
1964 else
1966 char *p, *p2;
1967 p = filespec;
1968 if ((p2 = strrchr( p, '\\' ))) p = p2 + 1;
1969 if ((p2 = strrchr( p, '/' ))) p = p2 + 1;
1970 lstrcpyn( mask, p, sizeof(mask) );
1971 if (p != filespec)
1973 p[-1] = '\0';
1974 if (!DRIVE_Chdir( drive, filespec )) return FALSE;
1979 strcpy( (char *)PTR_SEG_TO_LIN(spec), mask );
1981 dprintf_listbox(stddeb, "ListBoxDirectory: path=%c:\\%s mask=%s\n",
1982 'A' + drive, DRIVE_GetDosCwd(drive), mask);
1984 SENDMSG( LB_RESETCONTENT, 0, 0 );
1985 if ((attrib & DDL_DIRECTORY) && !(attrib & DDL_EXCLUSIVE))
1987 if (SENDMSG( LB_DIR, attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
1988 (LPARAM)spec ) == LB_ERR) return FALSE;
1989 if (SENDMSG( LB_DIR, (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
1990 (LPARAM)MAKE_SEGPTR(temp) ) == LB_ERR) return FALSE;
1992 else
1994 if (SENDMSG( LB_DIR, attrib, (LPARAM)spec) == LB_ERR) return FALSE;
1998 if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
2000 char temp[256];
2001 strcpy( temp, "A:\\" );
2002 temp[0] += drive;
2003 lstrcpyn( temp+3, DRIVE_GetDosCwd(drive), 253 );
2004 AnsiLower( temp );
2005 SENDMSG( WM_SETTEXT, 0, (LPARAM)MAKE_SEGPTR(temp) );
2007 return TRUE;
2008 #undef SENDMSG