wine/controls/listbox.c
Alexandre Julliard fa68b75bad Release 950403
Sun Apr  2 18:31:12 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)

	* [Configure] [if1632/Imakefile]
	Removed new build and short names options.

	* [if1632/*.c] [tools/build.c]
	Implemented compiled call-back functions for better performance;
	all the relay code is now done in assembly code generated by the
	build program.
	Relay code is no longer dependent on being loaded below 64K.

	* [loader/resource.c]
	Fixed memory leak in LoadString(). A fix will also be needed for
	other resources.

	* [memory/global.c]
	Implemented global heap arenas, so we can store informations about
	global blocks, like lock counts or owner handle.
	Implemented FarGetOwner() and FarSetOwner().
	Implemented global heap TOOLHELP functions.

	* [memory/selector.c]
	Bug fix: it was not possible to re-use a free selector.

Sun Apr 2 01:34:52 1995 Constantine Sapuntzakis  (csapuntz@mit.edu)

	*  [controls/listbox.c]
	Major work on listbox code
         - Many bugs fixed (still many bugs)
         - More messages supported
         - Code simplified

Fri Mar 31 03:27:16 EST 1995 William Magro (wmagro@tc.cornell.edu)

	* [controls/edit.c]
	Lots of bug fixes related to diappearing text, lost carets,
	highlighting, segmentation faults, occurance of random
	characters, insertion of characters over selection, misplaced
	caret location, display corruption, end of line behavior, etc.

	* [controls/widgets.c]
	EDIT class doesn't want to use CS_PARENTDC flag.

Thu Mar 30 20:58:25 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
        
	* [loader/selector.c]
	  FixupFunctionPrologs() should also handle multiple data modules.
	  (this bug only became visible because MakeProcInstance() was fixed
	  in 950319)
	
	* [misc/dosfs.c]
	  Simplified DOS_SimplifyPath.
	  Small fix to DOS_opendir to reuse an entry if an open directory
	  is opened again, to prevent "too many open directories" messages.

Thu Mar 30 12:05:05 1995 Martin von Loewis  <loewis@informatik.hu-berlin.de>

	* [if1632/compobj.spec][include/compobj.h][misc/compobj.c]
	CoDisconnectObject: new stub function

	* [include/msdos.h]
	fix DOSVERSION

	* [loader/ne_image.c]
	NE_FixupSegment: Be more generous on additive fixups

	* [if1632/user.spec][misc/network.c]
	Add more WNet* stubs

Wed Mar 29 11:47:22 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>

        * [controls/listbox.c]
	  DlgDirList(): send segptr instead of linear pointer 
	  in message to static control
	* [controls/menu.c]
	  Tried to implement ownerdrawn menuitems. Doesn't work.
	* [if1632/gdi.spec] [include/windows.h] [objects/font.c]
	  Provide a stub for GetRasterizerCaps()
	* [loader/selector.c]
	  Pass end address instead of length to LocalInit() in 
	  CreateSelectors()
	* [memory/local.c]
	  LocalInit(): If there's already a local heap in the segment, do
	  nothing and return TRUE
	* [objects/linedda.c]
	  Replaced buggy LineDDA() with a Bresenham algorithm. Should work
	  now.
	* [windows/cursor.c]
	  LoadCursor()/CreateCursor(): Cleaned up the mess. Needs some
	  more work still.

Tue Mar 21 17:54:43 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>

        * [if1632/relay.c] [if1632/callback.c] [include/dlls.h]
	  [if1632/winprocs.spec] [if1632/winprocs.c] [include/winprocs.h]
	  [controls/widgets.c] [misc/shell.c] [misc/commdlg.c]
	  [windows/nonclient.c] [misc/message.c]
	  Added a new builtin DLL that provides 16 bit entry points for all
	  the Def*Procs (DefDlgProc, ButtonProc etc.). OWL programs work
	  again.
	* [misc/shell.c]
	  RegOpenKey()/RegCreateKey() bugs fixed.
        * [loader/ne_image.c]
	  Skipping the initialization of a DLL when CS == 0 was broken.
1995-04-03 16:55:37 +00:00

2214 lines
55 KiB
C

/*
* Interface code to listbox widgets
*
* Copyright Martin Ayotte, 1993
* Copyright Constantine Sapuntzakis, 1995
*
static char Copyright[] = "Copyright Martin Ayotte, 1993";
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "windows.h"
#include "user.h"
#include "win.h"
#include "msdos.h"
#include "listbox.h"
#include "dos_fs.h"
#include "stddebug.h"
#include "debug.h"
#define GMEM_ZEROINIT 0x0040
LPLISTSTRUCT ListBoxGetItem (HWND hwnd, UINT uIndex);
int ListBoxScrolltoFocus(HWND hwnd);
LPHEADLIST ListBoxGetWindowAndStorage(HWND hwnd, WND **wndPtr);
LPHEADLIST ListBoxGetStorageHeader(HWND hwnd);
void RepaintListBox(HWND hwnd);
int ListBoxFindMouse(HWND hwnd, int X, int Y);
int CreateListBoxStruct(HWND hwnd);
void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls);
int ListBoxAddString(HWND hwnd, LPSTR newstr);
int ListBoxInsertString(HWND hwnd, UINT uIndex, LPSTR newstr);
int ListBoxGetText(HWND hwnd, UINT uIndex, LPSTR OutStr, BOOL bItemData);
int ListBoxSetItemData(HWND hwnd, UINT uIndex, DWORD ItemData);
int ListBoxDeleteString(HWND hwnd, UINT uIndex);
int ListBoxFindString(HWND hwnd, UINT nFirst, LPSTR MatchStr);
int ListBoxResetContent(HWND hwnd);
int ListBoxSetCurSel(HWND hwnd, WORD wIndex);
int ListBoxSetSel(HWND hwnd, WORD wIndex, WORD state);
int ListBoxGetSel(HWND hwnd, WORD wIndex);
int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec);
int ListBoxGetItemRect(HWND hwnd, WORD wIndex, LPRECT rect);
int ListBoxSetItemHeight(HWND hwnd, WORD wIndex, long height);
int ListBoxDefaultItem(HWND hwnd, WND *wndPtr,
LPHEADLIST lphl, LPLISTSTRUCT lpls);
int ListBoxFindNextMatch(HWND hwnd, WORD wChar);
int ListMaxFirstVisible(LPHEADLIST lphl);
void ListBoxSendNotification(HWND hwnd, WORD code);
#define OWNER_DRAWN(wndPtr) \
((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) || \
(wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE))
#define HasStrings(wndPtr) ( \
(! OWNER_DRAWN (wndPtr)) || \
(wndPtr->dwStyle & LBS_HASSTRINGS))
#if 0
#define LIST_HEAP_ALLOC(lphl,f,size) ((int)HEAP_Alloc(&lphl->Heap,f,size) & 0xffff)
#define LIST_HEAP_FREE(lphl,handle) (HEAP_Free(&lphl->Heap,LIST_HEAP_ADDR(lphl,handle)))
#define LIST_HEAP_ADDR(lphl,handle) \
((void *)((handle) ? ((handle) | ((int)lphl->Heap & 0xffff0000)) : 0))
#else
#define LIST_HEAP_ALLOC(lphl,f,size) USER_HEAP_ALLOC(size)
#define LIST_HEAP_FREE(lphl,handle) USER_HEAP_FREE(handle)
#define LIST_HEAP_ADDR(lphl,handle) USER_HEAP_LIN_ADDR(handle)
#endif
#define LIST_HEAP_SIZE 0x10000
/* Design notes go here */
LONG LBCreate( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBGetDlgCode( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBDestroy( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBVScroll( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBHScroll( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBLButtonDown( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBLButtonUp( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBRButtonUp( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBMouseMove( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBKeyDown( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBSetFont( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBSetRedraw( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBPaint( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBSetFocus( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBKillFocus( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBResetContent( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBDir( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBAddString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBGetText( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBInsertString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBDeleteString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBFindString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBGetCaretIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBGetCount( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBGetCurSel( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBGetHorizontalExtent(HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBGetItemData( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBGetItemHeight( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBGetItemRect( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBGetSel( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBGetSelCount( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBGetSelItems( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBGetTextLen( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBGetTopIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBSelectString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBSelItemRange( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBSetCaretIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBSetColumnWidth( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBSetHorizontalExtent(HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBSetItemData( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBSetTabStops( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBSetCurSel( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBSetSel( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBSetTopIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam );
LONG LBSetItemHeight( HWND hwnd, WORD message, WORD wParam, LONG lParam );
typedef struct {
WORD message;
LONG (*handler)(HWND, WORD, WPARAM, LPARAM);
} msg_tbl;
static msg_tbl methods[] = {
{WM_CREATE, LBCreate},
{WM_DESTROY, LBDestroy},
{WM_GETDLGCODE, LBGetDlgCode},
{WM_VSCROLL, LBVScroll},
{WM_HSCROLL, LBHScroll},
{WM_LBUTTONDOWN, LBLButtonDown},
{WM_LBUTTONUP, LBLButtonUp},
{WM_RBUTTONUP, LBRButtonUp},
{WM_LBUTTONDBLCLK, LBRButtonUp},
{WM_MOUSEMOVE, LBMouseMove},
{WM_KEYDOWN, LBKeyDown},
{WM_SETFONT, LBSetFont},
{WM_SETREDRAW, LBSetRedraw},
{WM_PAINT, LBPaint},
{WM_SETFOCUS, LBSetFocus},
{WM_KILLFOCUS, LBKillFocus},
{LB_RESETCONTENT, LBResetContent},
{LB_DIR, LBDir},
{LB_ADDSTRING, LBAddString},
{LB_INSERTSTRING, LBInsertString},
{LB_DELETESTRING, LBDeleteString},
{LB_FINDSTRING, LBFindString},
{LB_GETCARETINDEX, LBGetCaretIndex},
{LB_GETCOUNT, LBGetCount},
{LB_GETCURSEL, LBGetCurSel},
{LB_GETHORIZONTALEXTENT, LBGetHorizontalExtent},
{LB_GETITEMDATA, LBGetItemData},
{LB_GETITEMHEIGHT, LBGetItemHeight},
{LB_GETITEMRECT, LBGetItemRect},
{LB_GETSEL, LBGetSel},
{LB_GETSELCOUNT, LBGetSelCount},
{LB_GETSELITEMS, LBGetSelItems},
{LB_GETTEXT, LBGetText},
{LB_GETTEXTLEN, LBGetTextLen},
{LB_GETTOPINDEX, LBGetTopIndex},
{LB_SELECTSTRING, LBSelectString},
{LB_SELITEMRANGE, LBSelItemRange},
{LB_SETCARETINDEX, LBSetCaretIndex},
{LB_SETCOLUMNWIDTH, LBSetColumnWidth},
{LB_SETHORIZONTALEXTENT, LBSetHorizontalExtent},
{LB_SETITEMDATA, LBSetItemData},
{LB_SETTABSTOPS, LBSetTabStops},
{LB_SETCURSEL, LBSetCurSel},
{LB_SETSEL, LBSetSel},
{LB_SETTOPINDEX, LBSetTopIndex},
{LB_SETITEMHEIGHT, LBSetItemHeight}
};
/***********************************************************************
* LBCreate
*/
LONG LBCreate( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
CREATESTRUCT *createStruct;
WND *wndPtr;
CreateListBoxStruct(hwnd);
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
dprintf_listbox(stddeb,"ListBox WM_CREATE %p !\n", lphl);
if (lphl == NULL) return 0;
createStruct = (CREATESTRUCT *)PTR_SEG_TO_LIN(lParam);
if (HIWORD(createStruct->lpCreateParams) != 0)
lphl->hWndLogicParent = (HWND)HIWORD(createStruct->lpCreateParams);
else
lphl->hWndLogicParent = GetParent(hwnd);
lphl->hFont = GetStockObject(SYSTEM_FONT);
lphl->ColumnsWidth = wndPtr->rectClient.right - wndPtr->rectClient.left;
SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
return 0;
}
int CreateListBoxStruct(HWND hwnd)
{
WND *wndPtr;
LPHEADLIST lphl;
wndPtr = WIN_FindWndPtr(hwnd);
lphl = (LPHEADLIST)malloc(sizeof(HEADLIST));
*((LPHEADLIST *)&wndPtr->wExtra[1]) = lphl;
lphl->lpFirst = NULL;
lphl->ItemsCount = 0;
lphl->ItemsVisible = 0;
lphl->FirstVisible = 1;
lphl->ColumnsVisible = 1;
lphl->ItemsPerColumn = 0;
lphl->StdItemHeight = 15;
lphl->ItemFocused = -1;
lphl->PrevFocused = -1;
lphl->DrawCtlType = ODT_LISTBOX;
lphl->bRedrawFlag = TRUE;
lphl->iNumStops = 0;
lphl->TabStops = NULL;
if (OWNER_DRAWN(wndPtr))
lphl->hDrawItemStruct = USER_HEAP_ALLOC(sizeof(DRAWITEMSTRUCT));
else
lphl->hDrawItemStruct = 0;
#if 0
HeapHandle = GlobalAlloc(GMEM_FIXED, LIST_HEAP_SIZE);
HeapBase = GlobalLock(HeapHandle);
HEAP_Init(&lphl->Heap, HeapBase, LIST_HEAP_SIZE);
#endif
return TRUE;
}
/***********************************************************************
* LBDestroy
*/
LONG LBDestroy( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
WND *wndPtr;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return 0;
ListBoxResetContent(hwnd);
if (lphl->hDrawItemStruct)
USER_HEAP_FREE(lphl->hDrawItemStruct);
/* XXX need to free lphl->Heap */
free(lphl);
*((LPHEADLIST *)&wndPtr->wExtra[1]) = 0;
dprintf_listbox(stddeb,"ListBox WM_DESTROY %p !\n", lphl);
return 0;
}
/* get the maximum value of lphl->FirstVisible */
int ListMaxFirstVisible(LPHEADLIST lphl)
{
int m = lphl->ItemsCount-lphl->ItemsVisible+1;
return (m < 1) ? 1 : m;
}
/***********************************************************************
* LBVScroll
*/
LONG LBVScroll( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
int y;
dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
wParam, lParam);
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return 0;
y = lphl->FirstVisible;
switch(wParam) {
case SB_LINEUP:
if (lphl->FirstVisible > 1)
lphl->FirstVisible--;
break;
case SB_LINEDOWN:
if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
lphl->FirstVisible++;
break;
case SB_PAGEUP:
if (lphl->FirstVisible > 1)
lphl->FirstVisible -= lphl->ItemsVisible;
break;
case SB_PAGEDOWN:
if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
lphl->FirstVisible += lphl->ItemsVisible;
break;
case SB_THUMBTRACK:
lphl->FirstVisible = LOWORD(lParam);
break;
}
if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
lphl->FirstVisible = ListMaxFirstVisible(lphl);
if (y != lphl->FirstVisible) {
SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
return 0;
}
/***********************************************************************
* LBHScroll
*/
LONG LBHScroll( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
int y;
dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
wParam, lParam);
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return 0;
y = lphl->FirstVisible;
switch(wParam) {
case SB_LINEUP:
if (lphl->FirstVisible > 1)
lphl->FirstVisible -= lphl->ItemsPerColumn;
break;
case SB_LINEDOWN:
if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
lphl->FirstVisible += lphl->ItemsPerColumn;
break;
case SB_PAGEUP:
if (lphl->FirstVisible > 1 && lphl->ItemsPerColumn != 0)
lphl->FirstVisible -= lphl->ItemsVisible /
lphl->ItemsPerColumn * lphl->ItemsPerColumn;
break;
case SB_PAGEDOWN:
if (lphl->FirstVisible < ListMaxFirstVisible(lphl) &&
lphl->ItemsPerColumn != 0)
lphl->FirstVisible += lphl->ItemsVisible /
lphl->ItemsPerColumn * lphl->ItemsPerColumn;
break;
case SB_THUMBTRACK:
lphl->FirstVisible = lphl->ItemsPerColumn *
(LOWORD(lParam) - 1) + 1;
break;
}
if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
lphl->FirstVisible = ListMaxFirstVisible(lphl);
if (lphl->ItemsPerColumn != 0) {
lphl->FirstVisible = lphl->FirstVisible /
lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
if (y != lphl->FirstVisible) {
SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible /
lphl->ItemsPerColumn + 1, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
}
return 0;
}
/***********************************************************************
* LBLButtonDown
*/
LONG LBLButtonDown( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
WND *wndPtr;
WORD wRet;
int y;
RECT rectsel;
SetFocus(hwnd);
SetCapture(hwnd);
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return 0;
lphl->PrevFocused = lphl->ItemFocused;
y = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
if (y==-1)
return 0;
if (wndPtr->dwStyle & LBS_MULTIPLESEL) {
lphl->ItemFocused = y;
wRet = ListBoxGetSel(hwnd, y);
ListBoxSetSel(hwnd, y, !wRet);
}
else
ListBoxSetCurSel(hwnd, y);
if (wndPtr->dwStyle & LBS_MULTIPLESEL)
ListBoxSendNotification( hwnd, LBN_SELCHANGE );
ListBoxGetItemRect(hwnd, y, &rectsel);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return 0;
}
/***********************************************************************
* LBLButtonUp
*/
LONG LBLButtonUp( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
WND *wndPtr;
ReleaseCapture();
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return 0;
if (lphl->PrevFocused != lphl->ItemFocused)
ListBoxSendNotification( hwnd, LBN_SELCHANGE );
return 0;
}
/***********************************************************************
* LBRButtonUp
*/
LONG LBRButtonUp( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
WND *wndPtr;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return 0;
SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
MAKELONG(hwnd, LBN_DBLCLK));
return 0;
}
/***********************************************************************
* LBMouseMove
*/
LONG LBMouseMove( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
WND *wndPtr;
int y;
WORD wRet;
RECT rect, rectsel; /* XXX Broken */
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return 0;
if ((wParam & MK_LBUTTON) != 0) {
y = HIWORD(lParam);
if (y < 4) {
if (lphl->FirstVisible > 1) {
lphl->FirstVisible--;
SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return 0;
}
}
GetClientRect(hwnd, &rect);
if (y > (rect.bottom - 4)) {
if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
lphl->FirstVisible++;
SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return 0;
}
}
if ((y > 0) && (y < (rect.bottom - 4))) {
if ((y < rectsel.top) || (y > rectsel.bottom)) {
wRet = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
lphl->ItemFocused = wRet;
ListBoxSendNotification(hwnd, LBN_SELCHANGE);
}
else
ListBoxSetCurSel(hwnd, wRet);
ListBoxGetItemRect(hwnd, wRet, &rectsel);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
}
}
return 0;
}
/***********************************************************************
* LBKeyDown
*/
LONG LBKeyDown( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
WND *wndPtr;
HWND hWndCtl;
WORD wRet;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return 0;
switch(wParam) {
case VK_TAB:
hWndCtl = GetNextDlgTabItem(lphl->hWndLogicParent,
hwnd, !(GetKeyState(VK_SHIFT) < 0));
SetFocus(hWndCtl);
if(debugging_listbox){
if ((GetKeyState(VK_SHIFT) < 0))
dprintf_listbox(stddeb,"ListBox PreviousDlgTabItem %04X !\n", hWndCtl);
else
dprintf_listbox(stddeb,"ListBox NextDlgTabItem %04X !\n", hWndCtl);
}
break;
case VK_HOME:
lphl->ItemFocused = 0;
break;
case VK_END:
lphl->ItemFocused = lphl->ItemsCount - 1;
break;
case VK_LEFT:
if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
lphl->ItemFocused -= lphl->ItemsPerColumn;
}
break;
case VK_UP:
lphl->ItemFocused--;
break;
case VK_RIGHT:
if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
lphl->ItemFocused += lphl->ItemsPerColumn;
}
break;
case VK_DOWN:
lphl->ItemFocused++;
break;
case VK_PRIOR:
lphl->ItemFocused -= lphl->ItemsVisible;
break;
case VK_NEXT:
lphl->ItemFocused += lphl->ItemsVisible;
break;
case VK_SPACE:
wRet = ListBoxGetSel(hwnd, lphl->ItemFocused);
ListBoxSetSel(hwnd, lphl->ItemFocused, !wRet);
break;
default:
ListBoxFindNextMatch(hwnd, wParam);
return 0;
}
if (lphl->ItemFocused < 0) lphl->ItemFocused = 0;
if (lphl->ItemFocused >= lphl->ItemsCount)
lphl->ItemFocused = lphl->ItemsCount - 1;
if (lphl->ItemsVisible != 0)
lphl->FirstVisible = lphl->ItemFocused / lphl->ItemsVisible *
lphl->ItemsVisible + 1;
if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
lphl->FirstVisible = ListMaxFirstVisible(lphl);
if ((wndPtr->dwStyle & LBS_MULTIPLESEL) != LBS_MULTIPLESEL) {
ListBoxSetCurSel(hwnd, lphl->ItemFocused);
ListBoxSendNotification(hwnd, LBN_SELCHANGE);
}
SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return 0;
}
/***********************************************************************
* LBSetRedraw
*/
LONG LBSetRedraw( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
WND *wndPtr;
dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd=%04X w=%04X !\n", hwnd, wParam);
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return 0;
lphl->bRedrawFlag = wParam;
return 0;
}
/***********************************************************************
* LBSetFont
*/
LONG LBSetFont( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
WND *wndPtr;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return 0;
if (wParam == 0)
lphl->hFont = GetStockObject(SYSTEM_FONT);
else
lphl->hFont = wParam;
return 0;
}
/***********************************************************************
* LBPaint
*/
LONG LBPaint( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
RepaintListBox(hwnd);
return 0;
}
/***********************************************************************
* LBSetFocus
*/
LONG LBSetFocus( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
WND *wndPtr;
dprintf_listbox(stddeb,"ListBox WM_SETFOCUS !\n");
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
return 0;
}
/***********************************************************************
* LBKillFocus
*/
LONG LBKillFocus( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS !\n");
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return 0;
}
/***********************************************************************
* LBResetContent
*/
LONG LBResetContent( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
ListBoxResetContent(hwnd);
return 0;
}
/***********************************************************************
* LBDir
*/
LONG LBDir( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
WORD wRet;
dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
wRet = ListBoxDirectory(hwnd, wParam,
(LPSTR)PTR_SEG_TO_LIN(lParam));
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return wRet;
}
/***********************************************************************
* LBAddString
*/
LONG LBAddString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
WORD wRet;
WND *wndPtr;
wndPtr = WIN_FindWndPtr(hwnd);
if (HasStrings(wndPtr))
wRet = ListBoxAddString(hwnd, (LPSTR)PTR_SEG_TO_LIN(lParam));
else
wRet = ListBoxAddString(hwnd, (LPSTR)lParam);
return wRet;
}
/***********************************************************************
* LBGetText
*/
LONG LBGetText( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LONG wRet;
dprintf_listbox(stddeb, "LB_GETTEXT wParam=%d\n",wParam);
wRet = ListBoxGetText(hwnd, wParam,
(LPSTR)PTR_SEG_TO_LIN(lParam), FALSE);
return wRet;
}
/***********************************************************************
* LBInsertString
*/
LONG LBInsertString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
WORD wRet;
WND *wndPtr;
wndPtr = WIN_FindWndPtr(hwnd);
if (HasStrings(wndPtr))
wRet = ListBoxInsertString(hwnd, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
else
wRet = ListBoxInsertString(hwnd, wParam, (LPSTR)lParam);
return wRet;
}
/***********************************************************************
* LBDeleteString
*/
LONG LBDeleteString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
return ListBoxDeleteString(hwnd, wParam);
}
/***********************************************************************
* LBFindString
*/
LONG LBFindString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
return ListBoxFindString(hwnd, wParam,
(LPSTR)PTR_SEG_TO_LIN(lParam));
}
/***********************************************************************
* LBGetCaretIndex
*/
LONG LBGetCaretIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return LB_ERR;
return lphl->ItemFocused;
}
/***********************************************************************
* LBGetCount
*/
LONG LBGetCount( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
lphl = ListBoxGetStorageHeader(hwnd);
return lphl->ItemsCount;
}
/***********************************************************************
* LBGetCurSel
*/
LONG LBGetCurSel( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
lphl = ListBoxGetStorageHeader(hwnd);
dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %u !\n",
lphl->ItemFocused);
return lphl->ItemFocused;
}
/***********************************************************************
* LBGetHorizontalExtent
*/
LONG LBGetHorizontalExtent( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
return 0;
}
/***********************************************************************
* LBGetItemData
*/
LONG LBGetItemData( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
return ListBoxGetText(hwnd, wParam,
(LPSTR)PTR_SEG_TO_LIN(lParam), TRUE);
}
/***********************************************************************
* LBGetItemHeight
*/
LONG LBGetItemHeight( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
RECT rect;
ListBoxGetItemRect(hwnd, wParam, &rect);
return (rect.bottom - rect.top);
}
/***********************************************************************
* LBGetItemRect
*/
LONG LBGetItemRect( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
return ListBoxGetItemRect (hwnd, wParam, PTR_SEG_TO_LIN(lParam));
}
/***********************************************************************
* LBGetSel
*/
LONG LBGetSel( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
return ListBoxGetSel (hwnd, wParam);
}
/***********************************************************************
* LBGetSelCount
*/
LONG LBGetSelCount( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
LPLISTSTRUCT lpls;
int cnt = 0;
WND *wndPtr;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return LB_ERR;
lpls = lphl->lpFirst;
while (lpls != NULL) {
if (lpls->dis.itemState > 0) cnt++;
lpls = lpls->lpNext;
}
return cnt;
}
/***********************************************************************
* LBGetSelItems
*/
LONG LBGetSelItems( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
LPLISTSTRUCT lpls;
int cnt, idx;
WND *wndPtr;
int *lpItems = PTR_SEG_TO_LIN(lParam);
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return LB_ERR;
if (wParam == 0) return 0;
lpls = lphl->lpFirst;
cnt = 0; idx = 0;
while (lpls != NULL) {
if (lpls->dis.itemState > 0) lpItems[cnt++] = idx;
if (cnt == wParam) break;
idx++;
lpls = lpls->lpNext;
}
return cnt;
}
/***********************************************************************
* LBGetTextLen
*/
LONG LBGetTextLen( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
LPLISTSTRUCT lpls;
WND *wndPtr;
int cnt = 0;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
if (!HasStrings(wndPtr)) return LB_ERR;
if (wParam >= lphl->ItemsCount) return LB_ERR;
lpls = lphl->lpFirst;
while (cnt++ < wParam) lpls = lpls->lpNext;
return strlen(lpls->itemText);
}
/***********************************************************************
* LBGetDlgCode
*/
LONG LBGetDlgCode( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
return DLGC_WANTALLKEYS;
}
/***********************************************************************
* LBGetTopIndex
*/
LONG LBGetTopIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return LB_ERR;
return (lphl->FirstVisible - 1);
}
/***********************************************************************
* LBSelectString
*/
LONG LBSelectString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
WND *wndPtr;
WORD wRet;
wndPtr = WIN_FindWndPtr(hwnd);
wRet = ListBoxFindString(hwnd, wParam,
(LPSTR)PTR_SEG_TO_LIN(lParam));
/* XXX add functionality here */
return 0;
}
/***********************************************************************
* LBSelItemRange
*/
LONG LBSelItemRange( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
LPLISTSTRUCT lpls;
WND *wndPtr;
WORD cnt;
WORD first = LOWORD(lParam);
WORD last = HIWORD(lParam);
BOOL select = wParam;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return LB_ERR;
if (first >= lphl->ItemsCount ||
last >= lphl->ItemsCount) return LB_ERR;
lpls = lphl->lpFirst;
cnt = 0;
while (lpls != NULL) {
if (cnt++ >= first)
lpls->dis.itemState = select ? ODS_SELECTED : 0;
if (cnt > last)
break;
lpls = lpls->lpNext;
}
return 0;
}
/***********************************************************************
* LBSetCaretIndex
*/
LONG LBSetCaretIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
WND *wndPtr;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return 0;
if (wParam >= lphl->ItemsCount) return LB_ERR;
lphl->ItemFocused = wParam;
ListBoxScrolltoFocus (hwnd);
SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return 0;
}
/***********************************************************************
* LBSetColumnWidth
*/
LONG LBSetColumnWidth( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return LB_ERR;
lphl->ColumnsWidth = wParam;
return 0;
}
/***********************************************************************
* LBSetHorizontalExtent
*/
LONG LBSetHorizontalExtent( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
return 0;
}
/***********************************************************************
* LBSetItemData
*/
LONG LBSetItemData( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
dprintf_listbox(stddeb, "LB_SETITEMDATA wParam=%x lParam=%lx\n", wParam, lParam);
return ListBoxSetItemData(hwnd, wParam, lParam);
}
/***********************************************************************
* LBSetTabStops
*/
LONG LBSetTabStops( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl->TabStops != NULL) {
lphl->iNumStops = 0;
free (lphl->TabStops);
}
lphl->TabStops = malloc (wParam * sizeof (short));
if (lphl->TabStops) {
lphl->iNumStops = wParam;
memcpy (lphl->TabStops, PTR_SEG_TO_LIN(lParam), wParam * sizeof (short));
return TRUE;
}
return FALSE;
}
/***********************************************************************
* LBSetCurSel
*/
LONG LBSetCurSel( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
WORD wRet;
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return LB_ERR;
dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n",
wParam);
wRet = ListBoxSetCurSel(hwnd, wParam);
SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return wRet;
}
/***********************************************************************
* LBSetSel
*/
LONG LBSetSel( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
WORD wRet;
dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
wRet = ListBoxSetSel(hwnd, LOWORD(lParam), wParam);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return wRet;
}
/***********************************************************************
* LBSetTopIndex
*/
LONG LBSetTopIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
LPHEADLIST lphl;
dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
wParam);
lphl = ListBoxGetStorageHeader(hwnd);
lphl->FirstVisible = wParam;
SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return 0;
}
/***********************************************************************
* LBSetItemHeight
*/
LONG LBSetItemHeight( HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
WORD wRet;
dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
wRet = ListBoxSetItemHeight(hwnd, wParam, lParam);
return wRet;
}
/***********************************************************************
* ListBoxWndProc
*/
LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
int idx = 0;
int table_size = sizeof (methods) / sizeof (msg_tbl);
while (idx < table_size) {
if (message == methods[idx].message) {
return (*(methods[idx].handler))(hwnd, message, wParam, lParam);
}
idx++;
}
return DefWindowProc (hwnd, message, wParam, lParam);
}
LPLISTSTRUCT ListBoxGetItem(HWND hwnd, UINT uIndex)
{
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
LPLISTSTRUCT lpls;
UINT Count = 0;
if (uIndex >= lphl->ItemsCount) return NULL;
lpls = lphl->lpFirst;
while (Count++ < uIndex) lpls = lpls->lpNext;
return lpls;
}
LPHEADLIST ListBoxGetWindowAndStorage(HWND hwnd, WND **wndPtr)
{
WND *Ptr;
LPHEADLIST lphl;
*(wndPtr) = Ptr = WIN_FindWndPtr(hwnd);
lphl = *((LPHEADLIST *)&Ptr->wExtra[1]);
return lphl;
}
LPHEADLIST ListBoxGetStorageHeader(HWND hwnd)
{
WND *wndPtr;
LPHEADLIST lphl;
wndPtr = WIN_FindWndPtr(hwnd);
lphl = *((LPHEADLIST *)&wndPtr->wExtra[1]);
return lphl;
}
void ListBoxDrawItem (HWND hwnd, HDC hdc, LPLISTSTRUCT lpls,
WORD itemAction, WORD itemState)
{
LPHEADLIST lphl;
WND *wndPtr;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (OWNER_DRAWN(wndPtr)) {
DRAWITEMSTRUCT *dis = USER_HEAP_LIN_ADDR(lphl->hDrawItemStruct);
memcpy (dis, &lpls->dis, sizeof(DRAWITEMSTRUCT));
dis->CtlType = ODT_LISTBOX;
dis->hDC = hdc;
if ((!dis->CtlID) && lphl->hWndLogicParent) {
WND *ParentWndPtr;
ParentWndPtr = WIN_FindWndPtr(lphl->hWndLogicParent);
dis->CtlID = ParentWndPtr->wIDmenu;
}
if (HasStrings(wndPtr)) dis->itemData = (DWORD)lpls->itemText;
dis->itemAction = itemAction;
dis->itemState = itemState;
SendMessage(lphl->hWndLogicParent, WM_DRAWITEM,
0, (LPARAM)USER_HEAP_SEG_ADDR(lphl->hDrawItemStruct));
}
else {
if (itemAction == ODA_DRAWENTIRE ||
itemAction == ODA_SELECT) {
int OldBkMode;
DWORD dwOldTextColor;
OldBkMode = SetBkMode(hdc, TRANSPARENT);
if (itemState != 0) {
dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
FillRect(hdc, &lpls->dis.rcItem, GetStockObject(BLACK_BRUSH));
}
if (wndPtr->dwStyle & LBS_USETABSTOPS)
TabbedTextOut(hdc, lpls->dis.rcItem.left + 5,
lpls->dis.rcItem.top + 2,
(char *)lpls->itemText,
strlen((char *)lpls->itemText), lphl->iNumStops,
lphl->TabStops, 0);
else
TextOut(hdc, lpls->dis.rcItem.left + 5, lpls->dis.rcItem.top + 2,
(char *)lpls->itemText, strlen((char *)lpls->itemText));
if (itemState != 0) {
SetTextColor(hdc, dwOldTextColor);
}
SetBkMode(hdc, OldBkMode);
} else DrawFocusRect(hdc, &lpls->dis.rcItem);
}
return;
}
void RepaintListBox(HWND hwnd)
{
WND *wndPtr;
LPHEADLIST lphl;
LPLISTSTRUCT lpls;
PAINTSTRUCT ps;
HBRUSH hBrush;
HDC hdc;
RECT rect;
int i, top, height, maxwidth, ipc;
top = 0;
hdc = BeginPaint( hwnd, &ps );
if (!IsWindowVisible(hwnd)) {
EndPaint( hwnd, &ps );
return;
}
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) goto EndOfPaint;
if (!lphl->bRedrawFlag) goto EndOfPaint;
SelectObject(hdc, lphl->hFont);
hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
MAKELONG(hwnd, CTLCOLOR_LISTBOX));
if (hBrush == (HBRUSH)NULL) hBrush = GetStockObject(WHITE_BRUSH);
GetClientRect(hwnd, &rect);
FillRect(hdc, &rect, hBrush);
maxwidth = rect.right;
rect.right = lphl->ColumnsWidth;
if (lphl->ItemsCount == 0) goto EndOfPaint;
lpls = lphl->lpFirst;
lphl->ItemsVisible = 0;
lphl->ItemsPerColumn = ipc = 0;
for(i = 0; i < lphl->ItemsCount; i++) {
if (lpls == NULL) goto EndOfPaint;
if (i >= lphl->FirstVisible - 1) {
height = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
if (top > rect.bottom) {
if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
lphl->ItemsPerColumn = max(lphl->ItemsPerColumn, ipc);
ipc = 0;
top = 0;
rect.left += lphl->ColumnsWidth;
rect.right += lphl->ColumnsWidth;
if (rect.left > maxwidth) break;
}
else
break;
}
lpls->dis.rcItem.top = top;
lpls->dis.rcItem.bottom = top + height;
lpls->dis.rcItem.left = rect.left;
lpls->dis.rcItem.right = rect.right;
if (OWNER_DRAWN(wndPtr)) {
ListBoxDrawItem (hwnd, hdc, lpls, ODA_DRAWENTIRE, 0);
if (lpls->dis.itemState)
ListBoxDrawItem (hwnd, hdc, lpls, ODA_SELECT, ODS_SELECTED);
}
else
ListBoxDrawItem (hwnd, hdc, lpls, ODA_DRAWENTIRE, lpls->dis.itemState);
if ((lphl->ItemFocused == i) && GetFocus() == hwnd)
ListBoxDrawItem (hwnd, hdc, lpls, ODA_FOCUS, ODS_FOCUS);
top += height;
lphl->ItemsVisible++;
ipc++;
}
lpls = lpls->lpNext;
}
EndOfPaint:
EndPaint( hwnd, &ps );
}
int ListBoxFindMouse(HWND hwnd, int X, int Y)
{
WND *wndPtr;
LPHEADLIST lphl;
LPLISTSTRUCT lpls;
RECT rect;
int i, h, h2, w, w2;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
if (lphl->ItemsCount == 0) return LB_ERR;
lpls = lphl->lpFirst;
if (lpls == NULL) return LB_ERR;
GetClientRect(hwnd, &rect);
h = w2 = 0;
w = lphl->ColumnsWidth;
for(i = 1; i <= lphl->ItemsCount; i++) {
if (i >= lphl->FirstVisible) {
h2 = h;
h += lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
if ((Y > h2) && (Y < h) &&
(X > w2) && (X < w)) return(i - 1);
if (h > rect.bottom) {
if ((wndPtr->dwStyle & LBS_MULTICOLUMN) != LBS_MULTICOLUMN) return LB_ERR;
h = 0;
w2 = w;
w += lphl->ColumnsWidth;
if (w2 > rect.right) return LB_ERR;
}
}
if (lpls->lpNext == NULL) return LB_ERR;
lpls = (LPLISTSTRUCT)lpls->lpNext;
}
return(LB_ERR);
}
void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls)
{
MEASUREITEMSTRUCT *lpmeasure;
HANDLE hTemp = USER_HEAP_ALLOC( sizeof(MEASUREITEMSTRUCT) );
lpmeasure = (MEASUREITEMSTRUCT *) USER_HEAP_LIN_ADDR(hTemp);
if (lpmeasure == NULL) {
fprintf(stderr,"ListBoxAskMeasure() // Bad allocation of Measure struct !\n");
return;
}
lpmeasure->CtlType = ODT_LISTBOX;
lpmeasure->CtlID = wndPtr->wIDmenu;
lpmeasure->itemID = lpls->dis.itemID;
lpmeasure->itemWidth = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
lpmeasure->itemHeight = 0;
if (HasStrings(wndPtr))
lpmeasure->itemData = (DWORD)lpls->itemText;
else
lpmeasure->itemData = lpls->dis.itemData;
SendMessage(lphl->hWndLogicParent, WM_MEASUREITEM,
0, USER_HEAP_SEG_ADDR(hTemp));
if (wndPtr->dwStyle & LBS_OWNERDRAWFIXED) {
lphl->StdItemHeight = lpmeasure->itemHeight;
}
lpls->dis.rcItem.right = lpls->dis.rcItem.left + lpmeasure->itemWidth;
lpls->dis.rcItem.bottom = lpls->dis.rcItem.top + lpmeasure->itemHeight;
USER_HEAP_FREE(hTemp);
}
int ListBoxAddString(HWND hwnd, LPSTR newstr)
{
LPHEADLIST lphl;
UINT pos = (UINT) -1;
WND *wndPtr;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
if (HasStrings(wndPtr) && (wndPtr->dwStyle & LBS_SORT)) {
LPLISTSTRUCT lpls = lphl->lpFirst;
for (pos = 0; lpls; lpls = lpls->lpNext, pos++)
if (strcmp(lpls->itemText, newstr) >= 0)
break;
}
return ListBoxInsertString(hwnd, pos, newstr);
}
int ListBoxInsertString(HWND hwnd, UINT uIndex, LPSTR newstr)
{
WND *wndPtr;
LPHEADLIST lphl;
LPLISTSTRUCT *lppls, lplsnew;
HANDLE hItem;
HANDLE hStr;
LPSTR str;
UINT Count;
dprintf_listbox(stddeb,"ListBoxInsertString(%04X, %d, %p);\n",
hwnd, uIndex, newstr);
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
if (uIndex == (UINT)-1)
uIndex = lphl->ItemsCount;
if (uIndex > lphl->ItemsCount) return LB_ERR;
lppls = (LPLISTSTRUCT *) &lphl->lpFirst;
for(Count = 0; Count < uIndex; Count++) {
if (*lppls == NULL) return LB_ERR;
lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
}
hItem = LIST_HEAP_ALLOC(lphl, GMEM_MOVEABLE, sizeof(LISTSTRUCT));
lplsnew = (LPLISTSTRUCT) LIST_HEAP_ADDR(lphl, hItem);
if (lplsnew == NULL) {
printf("ListBoxInsertString() // Bad allocation of new item !\n");
return LB_ERRSPACE;
}
ListBoxDefaultItem(hwnd, wndPtr, lphl, lplsnew);
lplsnew->hMem = hItem;
lplsnew->lpNext = *lppls;
*lppls = lplsnew;
lphl->ItemsCount++;
hStr = 0;
if (HasStrings(wndPtr)) {
hStr = LIST_HEAP_ALLOC(lphl, GMEM_MOVEABLE, strlen(newstr) + 1);
str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
if (str == NULL) return LB_ERRSPACE;
strcpy(str, newstr);
newstr = str;
lplsnew->itemText = str;
dprintf_listbox(stddeb,"ListBoxInsertString // LBS_HASSTRINGS after strcpy '%s'\n", str);
}
else {
lplsnew->itemText = NULL;
lplsnew->dis.itemData = (DWORD)newstr;
}
lplsnew->dis.itemID = lphl->ItemsCount;
lplsnew->hData = hStr;
if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) && (lphl->ItemsCount == 1)) {
ListBoxAskMeasure(wndPtr, lphl, lplsnew);
}
if (wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE)
ListBoxAskMeasure(wndPtr, lphl, lplsnew);
SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl),
(lphl->FirstVisible != 1 && lphl->bRedrawFlag));
if (lphl->ItemsPerColumn != 0)
SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
lphl->ItemsPerColumn + 1,
(lphl->FirstVisible != 1 && lphl->bRedrawFlag));
if ((lphl->FirstVisible <= uIndex) &&
((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
return uIndex;
}
int ListBoxGetText(HWND hwnd, UINT uIndex, LPSTR OutStr, BOOL bItemData)
{
WND *wndPtr;
LPLISTSTRUCT lpls;
wndPtr = WIN_FindWndPtr(hwnd);
if (!OutStr && !bItemData) {
dprintf_listbox(stddeb, "ListBoxGetText // OutStr==NULL\n");
return 0;
}
if (!bItemData) *OutStr=0;
if ((lpls = ListBoxGetItem (hwnd, uIndex)) == NULL)
return 0;
if (bItemData)
return lpls->dis.itemData;
if (!HasStrings(wndPtr)) {
*((long *)OutStr) = lpls->dis.itemData;
return 4;
}
strcpy(OutStr, lpls->itemText);
return strlen(OutStr);
}
int ListBoxSetItemData(HWND hwnd, UINT uIndex, DWORD ItemData)
{
LPLISTSTRUCT lpls;
if ((lpls = ListBoxGetItem(hwnd, uIndex)) == NULL)
return 0;
lpls->dis.itemData = ItemData;
return 1;
}
int ListBoxDeleteString(HWND hwnd, UINT uIndex)
{
WND *wndPtr;
LPHEADLIST lphl;
LPLISTSTRUCT lpls, lpls2;
UINT Count;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
if (uIndex >= lphl->ItemsCount) return LB_ERR;
lpls = lphl->lpFirst;
if (lpls == NULL) return LB_ERR;
if( uIndex == 0 )
lphl->lpFirst = lpls->lpNext;
else {
for(Count = 0; Count < uIndex; Count++) {
if (lpls->lpNext == NULL) return LB_ERR;
lpls2 = lpls;
lpls = (LPLISTSTRUCT)lpls->lpNext;
}
lpls2->lpNext = (LPLISTSTRUCT)lpls->lpNext;
}
lphl->ItemsCount--;
if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
if (lpls->hMem != 0) LIST_HEAP_FREE(lphl, lpls->hMem);
SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
if (lphl->ItemsPerColumn != 0)
SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
lphl->ItemsPerColumn + 1, TRUE);
if ((lphl->FirstVisible <= uIndex) &&
((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
return lphl->ItemsCount;
}
int ListBoxFindString(HWND hwnd, UINT nFirst, LPSTR MatchStr)
{
WND *wndPtr;
LPHEADLIST lphl;
LPLISTSTRUCT lpls;
UINT Count;
UINT First = nFirst + 1;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
if (First > lphl->ItemsCount) return LB_ERR;
lpls = ListBoxGetItem(hwnd, First);
Count = 0;
while(lpls != NULL) {
if (HasStrings(wndPtr)) {
if (strstr(lpls->itemText, MatchStr) == lpls->itemText) return Count;
} else if (wndPtr->dwStyle & LBS_SORT) {
/* XXX Do a compare item */
}
else
if (lpls->dis.itemData == (DWORD)MatchStr) return Count;
lpls = lpls->lpNext;
Count++;
}
/* Start over at top */
Count = 0;
lpls = lphl->lpFirst;
while (Count < First) {
if (HasStrings(wndPtr)) {
if (strstr(lpls->itemText, MatchStr) == lpls->itemText) return Count;
} else if (wndPtr->dwStyle & LBS_SORT) {
/* XXX Do a compare item */
}
else
if (lpls->dis.itemData == (DWORD)MatchStr) return Count;
lpls = lpls->lpNext;
Count++;
}
return LB_ERR;
}
int ListBoxResetContent(HWND hwnd)
{
WND *wndPtr;
LPHEADLIST lphl;
LPLISTSTRUCT lpls;
UINT i;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
if (lphl->ItemsCount == 0) return 0;
lpls = lphl->lpFirst;
dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n",
lphl->ItemsCount);
for(i = 0; i < lphl->ItemsCount; i++) {
LPLISTSTRUCT lpls2;
if (lpls == NULL) return LB_ERR;
lpls2 = lpls->lpNext;
if (i != 0) {
dprintf_listbox(stddeb,"ResetContent #%u\n", i);
if (lpls->hData != 0 && lpls->hData != lpls->hMem)
LIST_HEAP_FREE(lphl, lpls->hData);
if (lpls->hMem != 0) LIST_HEAP_FREE(lphl, lpls->hMem);
}
lpls = lpls2;
}
lphl->lpFirst = NULL;
lphl->FirstVisible = 1;
lphl->ItemsCount = 0;
lphl->ItemFocused = -1;
lphl->PrevFocused = -1;
SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
if (lphl->ItemsPerColumn != 0)
SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
lphl->ItemsPerColumn + 1, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return TRUE;
}
int ListBoxSetCurSel(HWND hwnd, WORD wIndex)
{
WND *wndPtr;
LPHEADLIST lphl;
LPLISTSTRUCT lpls;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
if (wndPtr->dwStyle & LBS_MULTIPLESEL) return 0;
if (lphl->ItemFocused != -1) {
lpls = ListBoxGetItem(hwnd, lphl->ItemFocused);
lpls->dis.itemState = 0;
}
if (wIndex != (UINT)-1) {
lphl->ItemFocused = wIndex;
lpls = ListBoxGetItem(hwnd, wIndex);
lpls->dis.itemState = ODS_SELECTED | ODS_FOCUS;
return 0;
}
return LB_ERR;
}
int ListBoxSetSel(HWND hwnd, WORD wIndex, WORD state)
{
LPHEADLIST lphl;
LPLISTSTRUCT lpls;
WND *wndPtr;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return 0;
if (wIndex == (UINT)-1) {
lpls = lphl->lpFirst;
while (lpls != NULL) {
lpls->dis.itemState = state;
lpls = lpls->lpNext;
}
return 0;
}
if (wIndex >= lphl->ItemsCount) return LB_ERR;
lpls = ListBoxGetItem(hwnd, wIndex);
lpls->dis.itemState = state;
return 0;
}
int ListBoxGetSel(HWND hwnd, WORD wIndex)
{
LPLISTSTRUCT lpls;
if ((lpls = ListBoxGetItem(hwnd, wIndex)) == NULL) return LB_ERR;
return lpls->dis.itemState;
}
int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec)
{
struct dosdirent *dp, *dp_old;
int x, wRet = LB_OKAY;
BOOL OldFlag;
char temp[256];
LPHEADLIST lphl;
int drive;
dprintf_listbox(stddeb,"ListBoxDirectory: %s, %4x\n",filespec,attrib);
if( strchr( filespec, '\\' ) || strchr( filespec, ':' ) ) {
drive = DOS_GetDefaultDrive();
if( filespec[1] == ':' ) {
drive = toupper(filespec[0]) - 'A';
filespec += 2;
}
if( !strchr( filespec, '\\' ) )
DOS_SetDefaultDrive( drive );
else {
int i;
strcpy( temp, filespec );
for( i=0; i<strlen(temp); i++ )
if( temp[i] == '\\' ) {
temp[i] = 0;
filespec += ( i+1 );
break;
}
DOS_ChangeDir( drive, temp );
DOS_SetDefaultDrive( drive );
}
dprintf_listbox(stddeb,"Changing directory to %c:%s, filemask is %s\n",
drive+'A', temp, filespec );
}
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return LB_ERR;
if ((dp = (struct dosdirent *)DOS_opendir(filespec)) ==NULL) return 0;
dp_old = dp;
OldFlag = lphl->bRedrawFlag;
lphl->bRedrawFlag = FALSE;
while ((dp = (struct dosdirent *)DOS_readdir(dp))) {
if (!dp->inuse) break;
dprintf_listbox( stddeb, "ListBoxDirectory %p '%s' !\n", dp->filename,
dp->filename);
if (dp->attribute & FA_DIREC) {
if (attrib & DDL_DIRECTORY &&
strcmp(dp->filename, ".")) {
sprintf(temp, "[%s]", dp->filename);
if ( (wRet = ListBoxAddString(hwnd, temp)) == LB_ERR) break;
}
}
else {
if (attrib & DDL_EXCLUSIVE) {
if (attrib & (DDL_READWRITE | DDL_READONLY | DDL_HIDDEN |
DDL_SYSTEM) )
if ( (wRet = ListBoxAddString(hwnd, dp->filename))
== LB_ERR) break;
}
else {
if ( (wRet = ListBoxAddString(hwnd, dp->filename))
== LB_ERR) break;
}
}
}
DOS_closedir(dp_old);
if (attrib & DDL_DRIVES) {
for (x=0;x!=MAX_DOS_DRIVES;x++) {
if (DOS_ValidDrive(x)) {
sprintf(temp, "[-%c-]", 'a'+x);
if((wRet = ListBoxInsertString(hwnd, (UINT)-1, temp)) == LB_ERR) break;
}
}
}
lphl->bRedrawFlag = OldFlag;
if (OldFlag) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
dprintf_listbox(stddeb,"End of ListBoxDirectory !\n");
return 1; /* FIXME: Should be 0 if "filespec" is invalid */
}
int ListBoxGetItemRect(HWND hwnd, WORD wIndex, LPRECT lprect)
{
LPLISTSTRUCT lpls;
if ((lpls = ListBoxGetItem(hwnd, wIndex)) == NULL) return LB_ERR;
*(lprect) = lpls->dis.rcItem;
return 0;
}
int ListBoxSetItemHeight(HWND hwnd, WORD wIndex, long height)
{
LPHEADLIST lphl;
WND *wndPtr;
LPLISTSTRUCT lpls;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
if (!(wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE)) {
lphl->StdItemHeight = (short)height;
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return 0;
}
if ((lpls = ListBoxGetItem(hwnd, wIndex)) == NULL) return LB_ERR;
lpls->dis.rcItem.bottom = lpls->dis.rcItem.top + (short)height;
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return 0;
}
int ListBoxDefaultItem(HWND hwnd, WND *wndPtr,
LPHEADLIST lphl, LPLISTSTRUCT lpls)
{
RECT rect;
if (wndPtr == NULL || lphl == NULL || lpls == NULL) {
fprintf(stderr,"ListBoxDefaultItem() // Bad Pointers !\n");
return FALSE;
}
GetClientRect(hwnd, &rect);
SetRect(&lpls->dis.rcItem, 0, 0, rect.right, lphl->StdItemHeight);
lpls->dis.CtlType = lphl->DrawCtlType;
lpls->dis.CtlID = wndPtr->wIDmenu;
lpls->dis.itemID = 0;
lpls->dis.itemAction = 0;
lpls->dis.itemState = 0;
lpls->dis.hwndItem = hwnd;
lpls->dis.hDC = 0;
lpls->dis.itemData = 0;
return TRUE;
}
int ListBoxFindNextMatch(HWND hwnd, WORD wChar)
{
WND *wndPtr;
LPHEADLIST lphl;
LPLISTSTRUCT lpls;
UINT Count;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
lpls = lphl->lpFirst;
if (lpls == NULL) return LB_ERR;
if (wChar < ' ') return LB_ERR;
if (!HasStrings(wndPtr)) return LB_ERR;
Count = 0;
while(lpls != NULL) {
if (Count > lphl->ItemFocused) {
if (*(lpls->itemText) == (char)wChar) {
if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
lphl->ItemFocused = Count;
ListBoxScrolltoFocus(hwnd);
}
else {
ListBoxSetCurSel(hwnd, Count);
}
SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return Count;
}
}
lpls = (LPLISTSTRUCT)lpls->lpNext;
Count++;
}
Count = 0;
lpls = lphl->lpFirst;
while(lpls != NULL) {
if (*(lpls->itemText) == (char)wChar) {
if (Count == lphl->ItemFocused) return LB_ERR;
if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
lphl->ItemFocused = Count;
ListBoxScrolltoFocus(hwnd);
}
else {
ListBoxSetCurSel(hwnd, Count);
}
SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return Count;
}
lpls = lpls->lpNext;
Count++;
}
return LB_ERR;
}
/************************************************************************
* DlgDirSelect [USER.99]
*/
BOOL DlgDirSelect(HWND hDlg, LPSTR lpStr, int nIDLBox)
{
HWND hwnd;
LPHEADLIST lphl;
char s[130];
dprintf_listbox( stddeb, "DlgDirSelect(%04X, '%s', %d) \n", hDlg, lpStr,
nIDLBox );
hwnd = GetDlgItem(hDlg, nIDLBox);
lphl = ListBoxGetStorageHeader(hwnd);
if( lphl->ItemFocused == -1 ) {
dprintf_listbox( stddeb, "Nothing selected!\n" );
return FALSE;
}
ListBoxGetText(hwnd, lphl->ItemFocused, (LPSTR)s, FALSE);
dprintf_listbox( stddeb, "Selection is %s\n", s );
if( s[0] == '[' ) {
if( s[1] == '-' ) {
strncpy( lpStr, s+2, strlen(s)-4 ); /* device name */
lpStr[ strlen(s)-4 ] = 0;
strcat( lpStr, ":" );
}
else {
strncpy( lpStr, s+1, strlen(s)-2 ); /* directory name */
lpStr[ strlen(s)-2 ] = 0;
strcat( lpStr, "\\" );
}
dprintf_listbox( stddeb, "Returning %s\n", lpStr );
return TRUE;
}
else {
strcpy( lpStr, s ); /* file name */
dprintf_listbox( stddeb, "Returning %s\n", lpStr );
return FALSE;
}
}
/************************************************************************
* DlgDirList [USER.100]
*/
int DlgDirList(HWND hDlg, LPSTR lpPathSpec,
int nIDLBox, int nIDStat, WORD wType)
{
HWND hWnd;
int ret;
dprintf_listbox(stddeb,"DlgDirList(%04X, '%s', %d, %d, %04X) \n",
hDlg, lpPathSpec, nIDLBox, nIDStat, wType);
if (nIDLBox)
hWnd = GetDlgItem(hDlg, nIDLBox);
else
hWnd = 0;
if (hWnd)
ListBoxResetContent(hWnd);
if (hWnd)
ret=ListBoxDirectory(hWnd, wType, lpPathSpec);
else
ret=0;
if (nIDStat)
{
int drive;
HANDLE hTemp;
char *temp;
drive = DOS_GetDefaultDrive();
hTemp = USER_HEAP_ALLOC( 256 );
temp = (char *) USER_HEAP_LIN_ADDR( hTemp );
strcpy( temp+3, DOS_GetCurrentDir(drive) );
if( temp[3] == '\\' ) {
temp[1] = 'A'+drive;
temp[2] = ':';
SendDlgItemMessage( hDlg, nIDStat, WM_SETTEXT, 0,
USER_HEAP_SEG_ADDR(hTemp) + 1 );
}
else {
temp[0] = 'A'+drive;
temp[1] = ':';
temp[2] = '\\';
SendDlgItemMessage( hDlg, nIDStat, WM_SETTEXT, 0,
USER_HEAP_SEG_ADDR(hTemp) );
}
USER_HEAP_FREE( hTemp );
}
return ret;
}
/* Returns: 0 if nothing needs to be changed */
/* 1 if FirstVisible changed */
int ListBoxScrolltoFocus(HWND hwnd)
{
WND *wndPtr;
LPHEADLIST lphl;
short end;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl->ItemsCount == 0) return 0;
if (lphl->ItemFocused == -1) return 0;
end = lphl->FirstVisible + lphl->ItemsVisible - 2;
if (lphl->ItemFocused < lphl->FirstVisible - 1) {
lphl->FirstVisible = lphl->ItemFocused + 1;
}
else if (lphl->ItemFocused > end) {
UINT maxFirstVisible = ListMaxFirstVisible(lphl);
lphl->FirstVisible = lphl->ItemFocused;
if (lphl->FirstVisible > maxFirstVisible) {
lphl->FirstVisible = maxFirstVisible;
}
} else return 0;
return 1;
}
/* Send notification "code" as part of a WM_COMMAND-message if hwnd
has the LBS_NOTIFY style */
void ListBoxSendNotification(HWND hwnd, WORD code)
{
WND *wndPtr;
LPHEADLIST lphl;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (wndPtr && (wndPtr->dwStyle & LBS_NOTIFY))
SendMessage(lphl->hWndLogicParent, WM_COMMAND,
wndPtr->wIDmenu, MAKELONG(hwnd, code));
}