1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00
wine/controls/listbox.c
Alexandre Julliard ecc3712ddf Release 941122
Sun Nov 20 18:30:06 1994  Alexandre Julliard  (julliard@lamisun.epfl.ch)

	* [controls/scroll.c] [include/scroll.h]
	Rewritten most of scroll-bar code for better Windows look & feel.
	Implemented EnableScrollBar().
	Preliminary keyboard support.

	* [objects/bitblt.c]
	Fixed BadMatch error for BitBlt() and StretchBlt() when reading
	bits from outside the visible region.

	* [objects/oembitmap.c] [include/bitmaps/obm_*]
	Use XPM symbolic colors to load bitmaps. This allows the colors
	of the bitmaps to depend on the system colors.

	* [tools/make_debug]
	Made the make_debug script more robust.

	* [windows/dialog.c]
	Fixed CheckRadioButton().

	* [windows/nonclient.c]
	A few changes to scroll-bar drawing and tracking.

	* [windows/winpos.c]
	Renamed NextWindowFromPoint() to WINPOS_NextWindowFromPoint() to
	avoid confusion, and optimized it somewhat.

Nov 19, 94 Martin Ayotte (wine@trgcorp.mksinfo.qc.ca)

	* [misc/audio.c]
	* [misc/mcianim.c]
	more coding but nothing spectacular.

	* [misc/mmaux.c]
	some coding to access '/dev/mixer'.

	* [misc/midi.c]
	some coding to read .MID files, but it's not playing yet.

Sun Nov 13 19:31:03 1994    James Youngman (mbcstjy@afs.man.ac.uk)

	* [objects/dib.c]
	Reimplemented DIB_SetImageBits_RLE8() so that it would cope with
	bitmaps which don't end 0x00, 0x02 (previously it blew up).  This
	includes some bitmaps output by Paint Shop Pro.  Implementation is
	possibly now too lax.  Please see the notes on the function about
	why.

	* [controls/desktop.c]
	The desktop pattern should be painted if the wallpaper doesn't
	cover the whole screen width OR the whole screen height.

Sun Nov 13 00:07:11 MET 1994	Erik Bos	<erik@xs4all.nl>

	* [objects/dib.c]
	Small bug in DIB_SetImageBits() fixed, bitmaps in 16,24 bpp
	now work.

	* [loader/ne_resource.c] [include/resource.h]
	Some cleanup.

Thu Nov 10 20:44:58 1994  Martin von Loewis  (martin@cs.csufresno.edu)

	* [Configure]
	  [rc/sysres.rc]
	Primitive compile-time support for multiple languages

	* [rc/sysres_De.rc]
	New file

	* [loader/resource.c]
	LoadBitmap: Recognize end of sysresbm properly

	* [rc/Imakefile]
	Rules to compile resources simplified, dependencies changed

	* [rc/sysresbm.rc]
	Don't use sysresbm if using XPM

	* [windows/dialog.c]
	CreateDialogIndirectParam: Reverse Z-order of controls

	* [windows/message.c]
	MSG_TranslateMouseMsg: Fix HTTRANSPARENT handling

	* [windows/winpos.c]
	NextWindowFromPoint: New function

	* [controls/button.c]
	WM_NCHITTEST: Group Box is HTTRANSPARENT
	BUTTON_CheckAutoRadioButton: New function
	BM_SETCHECK: Added call to BUTTON_CheckAutoRadioButton

Mon Nov  7 11:20:26 1994  Paul Falstad  (pf@zoof.cts.com)

	* [objects/text.c]
	Fix hang when using DrawText(..., DT_WORDBREAK) with a word that
	is too long to break.

	* [objects/font.c]
	Don't assume helvetica if there is no font family; let the other
	font attributes decide what font to use.

	* [controls/widgets.c]
	Listboxes and combo boxes need to be notified of double-clicks.

	* [controls/listbox.c]
	  [include/listbox.h]

	scrolling to bottom of list box should display last item at the
	bottom, not at the top.
	
	list boxes need to allocate a separate heap for their item data,
	rather than using the user heap.  Otherwise, it's very easy to run
	out of memory for list box items.

	removed redundant code in ListBoxAddString().  Implemented simple
	version of LBS_SORT.

	Don't put [.] in the list box when using DDL_DIRECTORY.

	* [controls/combo.c]
	Combos should pass CBS_SORT onto their list box.

	* [windows/win.c]
	If window creation is aborted, remove the window from the
	linked lists.

	* [controls/static.c]
	static controls with SS_ICON were always returning 0 from
	WM_NCCREATE.

	Make sure static controls have text to draw before drawing it.
1994-11-22 16:31:29 +00:00

1389 lines
40 KiB
C

/*
* Interface code to listbox widgets
*
* Copyright Martin Ayotte, 1993
*
*/
static char Copyright[] = "Copyright Martin Ayotte, 1993";
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "windows.h"
#include "user.h"
#include "heap.h"
#include "win.h"
#include "msdos.h"
#include "wine.h"
#include "listbox.h"
#include "prototypes.h"
#include "stddebug.h"
/* #define DEBUG_LISTBOX */
/* #undef DEBUG_LISTBOX */
#include "debug.h"
#define GMEM_ZEROINIT 0x0040
LPHEADLIST ListBoxGetWindowAndStorage(HWND hwnd, WND **wndPtr);
LPHEADLIST ListBoxGetStorageHeader(HWND hwnd);
void StdDrawListBox(HWND hwnd);
void OwnerDrawListBox(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);
#define HasStrings(wndPtr) ( \
( ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) != LBS_OWNERDRAWFIXED) && \
((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) != LBS_OWNERDRAWVARIABLE) ) || \
((wndPtr->dwStyle & LBS_HASSTRINGS) == LBS_HASSTRINGS) )
#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))
#define LIST_HEAP_SIZE 0x10000
/***********************************************************************
* ListBoxWndProc
*/
LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
WND *wndPtr;
LPHEADLIST lphl;
HWND hWndCtl;
WORD wRet;
LONG lRet;
RECT rect;
int y;
CREATESTRUCT *createStruct;
static RECT rectsel;
switch(message) {
case WM_CREATE:
CreateListBoxStruct(hwnd);
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
dprintf_listbox(stddeb,"ListBox WM_CREATE %p !\n", lphl);
if (lphl == NULL) return 0;
createStruct = (CREATESTRUCT *)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;
if (wndPtr->dwStyle & WS_VSCROLL) {
SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
ShowScrollBar(hwnd, SB_VERT, FALSE);
}
if (wndPtr->dwStyle & WS_HSCROLL) {
SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
ShowScrollBar(hwnd, SB_HORZ, FALSE);
}
if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) {
}
return 0;
case WM_DESTROY:
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return 0;
ListBoxResetContent(hwnd);
/* XXX need to free lphl->Heap */
free(lphl);
*((LPHEADLIST *)&wndPtr->wExtra[1]) = 0;
dprintf_listbox(stddeb,"ListBox WM_DESTROY %p !\n", lphl);
return 0;
case WM_VSCROLL:
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;
case WM_HSCROLL:
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;
case WM_LBUTTONDOWN:
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) == LBS_MULTIPLESEL) {
lphl->ItemFocused = y;
wRet = ListBoxGetSel(hwnd, y);
ListBoxSetSel(hwnd, y, !wRet);
}
else {
ListBoxSetCurSel(hwnd, y);
if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
SendMessage(lphl->hWndLogicParent, WM_COMMAND,
wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
}
ListBoxGetItemRect(hwnd, y, &rectsel);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return 0;
case WM_LBUTTONUP:
ReleaseCapture();
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return 0;
if (lphl->PrevFocused != lphl->ItemFocused)
SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
MAKELONG(hwnd, LBN_SELCHANGE));
return 0;
case WM_RBUTTONUP:
case WM_LBUTTONDBLCLK:
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return 0;
SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
MAKELONG(hwnd, LBN_DBLCLK));
return 0;
case WM_MOUSEMOVE:
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--;
if (wndPtr->dwStyle & WS_VSCROLL)
SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
break;
}
}
GetClientRect(hwnd, &rect);
if (y > (rect.bottom - 4)) {
if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
lphl->FirstVisible++;
if (wndPtr->dwStyle & WS_VSCROLL)
SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
break;
}
}
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;
}
else {
ListBoxSetCurSel(hwnd, wRet);
if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
SendMessage(lphl->hWndLogicParent, WM_COMMAND,
wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
}
ListBoxGetItemRect(hwnd, wRet, &rectsel);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
}
}
break;
case WM_KEYDOWN:
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);
#ifdef DEBUG_LISTBOX
if ((GetKeyState(VK_SHIFT) < 0))
dprintf_listbox(stddeb,"ListBox PreviousDlgTabItem %04X !\n", hWndCtl);
else
dprintf_listbox(stddeb,"ListBox NextDlgTabItem %04X !\n", hWndCtl);
#endif
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;
lphl->FirstVisible = lphl->ItemFocused / lphl->ItemsVisible *
lphl->ItemsVisible + 1;
if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
if ((wndPtr->dwStyle & LBS_MULTIPLESEL) != LBS_MULTIPLESEL) {
ListBoxSetCurSel(hwnd, lphl->ItemFocused);
if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
SendMessage(lphl->hWndLogicParent, WM_COMMAND,
wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
}
if (wndPtr->dwStyle & WS_VSCROLL)
SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
break;
case WM_SETFONT:
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return 0;
if (wParam == 0)
lphl->hFont = GetStockObject(SYSTEM_FONT);
else
lphl->hFont = wParam;
if (wParam == 0) break;
break;
case WM_SETREDRAW:
#ifdef DEBUG_LISTBOX
printf("ListBox WM_SETREDRAW hWnd=%04X w=%04X !\n", hwnd, wParam);
#endif
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return 0;
lphl->bRedrawFlag = wParam;
break;
case WM_PAINT:
wndPtr = WIN_FindWndPtr(hwnd);
if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) {
OwnerDrawListBox(hwnd);
break;
}
if ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) {
OwnerDrawListBox(hwnd);
break;
}
StdDrawListBox(hwnd);
break;
case WM_SETFOCUS:
dprintf_listbox(stddeb,"ListBox WM_SETFOCUS !\n");
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
break;
case WM_KILLFOCUS:
dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS !\n");
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
break;
case LB_RESETCONTENT:
dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
ListBoxResetContent(hwnd);
return 0;
case LB_DIR:
dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
wRet = ListBoxDirectory(hwnd, wParam, (LPSTR)lParam);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return wRet;
case LB_ADDSTRING:
wRet = ListBoxAddString(hwnd, (LPSTR)lParam);
return wRet;
case LB_GETTEXT:
dprintf_listbox(stddeb, "LB_GETTEXT wParam=%d\n",wParam);
wRet = ListBoxGetText(hwnd, wParam, (LPSTR)lParam, FALSE);
return wRet;
case LB_INSERTSTRING:
wRet = ListBoxInsertString(hwnd, wParam, (LPSTR)lParam);
return wRet;
case LB_DELETESTRING:
wRet = ListBoxDeleteString(hwnd, wParam);
return wRet;
case LB_FINDSTRING:
wRet = ListBoxFindString(hwnd, wParam, (LPSTR)lParam);
return wRet;
case LB_GETCARETINDEX:
return wRet;
case LB_GETCOUNT:
lphl = ListBoxGetStorageHeader(hwnd);
return lphl->ItemsCount;
case LB_GETCURSEL:
lphl = ListBoxGetStorageHeader(hwnd);
dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %u !\n",
lphl->ItemFocused);
return lphl->ItemFocused;
case LB_GETHORIZONTALEXTENT:
return wRet;
case LB_GETITEMDATA:
dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
lRet = ListBoxGetText(hwnd, wParam, (LPSTR)lParam, TRUE);
return lRet;
case LB_GETITEMHEIGHT:
ListBoxGetItemRect(hwnd, wParam, &rect);
return (rect.bottom - rect.top);
case LB_GETITEMRECT:
ListBoxGetItemRect(hwnd, wParam, (LPRECT)lParam);
return 0;
case LB_GETSEL:
wRet = ListBoxGetSel(hwnd, wParam);
return wRet;
case LB_GETSELCOUNT:
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return LB_ERR;
return lphl->SelCount;
case LB_GETSELITEMS:
return wRet;
case LB_GETTEXTLEN:
return wRet;
case LB_GETTOPINDEX:
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return LB_ERR;
return lphl->FirstVisible;
case LB_SELECTSTRING:
return wRet;
case LB_SELITEMRANGE:
return wRet;
case LB_SETCARETINDEX:
return wRet;
case LB_SETCOLUMNWIDTH:
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return LB_ERR;
lphl->ColumnsWidth = wParam;
break;
case LB_SETHORIZONTALEXTENT:
return wRet;
case LB_SETITEMDATA:
dprintf_listbox(stddeb, "LB_SETITEMDATA wParam=%x lParam=%lx\n", wParam, lParam);
wRet = ListBoxSetItemData(hwnd, wParam, lParam);
return wRet;
case LB_SETTABSTOPS:
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return LB_ERR;
lphl->FirstVisible = wParam;
return 0;
case LB_SETCURSEL:
dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n",
wParam);
wRet = ListBoxSetCurSel(hwnd, wParam);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return wRet;
case LB_SETSEL:
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;
case LB_SETTOPINDEX:
dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
wParam);
lphl = ListBoxGetStorageHeader(hwnd);
lphl->FirstVisible = wParam;
wndPtr = WIN_FindWndPtr(hwnd);
if (wndPtr->dwStyle & WS_VSCROLL)
SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
break;
case LB_SETITEMHEIGHT:
dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
wRet = ListBoxSetItemHeight(hwnd, wParam, lParam);
return wRet;
default:
return DefWindowProc( hwnd, message, wParam, lParam );
}
return 0;
}
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 StdDrawListBox(HWND hwnd)
{
WND *wndPtr;
LPHEADLIST lphl;
LPLISTSTRUCT lpls;
PAINTSTRUCT ps;
HBRUSH hBrush;
int OldBkMode;
DWORD dwOldTextColor;
HDC hdc;
RECT rect;
int i, h, h2, maxwidth, ipc;
h = 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);
/*
if (wndPtr->dwStyle & WS_VSCROLL) rect.right -= 16;
if (wndPtr->dwStyle & WS_HSCROLL) rect.bottom -= 16;
*/
FillRect(hdc, &rect, hBrush);
maxwidth = rect.right;
rect.right = lphl->ColumnsWidth;
if (lphl->ItemsCount == 0) goto EndOfPaint;
lpls = lphl->lpFirst;
if (lpls == NULL) goto EndOfPaint;
lphl->ItemsVisible = 0;
lphl->ItemsPerColumn = ipc = 0;
for(i = 1; i <= lphl->ItemsCount; i++) {
if (i >= lphl->FirstVisible) {
if (lpls == NULL) break;
if ((h + lpls->dis.rcItem.bottom - lpls->dis.rcItem.top) > rect.bottom) {
if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
lphl->ItemsPerColumn = max(lphl->ItemsPerColumn, ipc);
ipc = 0;
h = 0;
rect.left += lphl->ColumnsWidth;
rect.right += lphl->ColumnsWidth;
if (rect.left > maxwidth) break;
}
else
break;
}
h2 = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
lpls->dis.rcItem.top = h;
lpls->dis.rcItem.bottom = h + h2;
lpls->dis.rcItem.left = rect.left;
lpls->dis.rcItem.right = rect.right;
OldBkMode = SetBkMode(hdc, TRANSPARENT);
if (lpls->dis.itemState != 0) {
dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
FillRect(hdc, &lpls->dis.rcItem, GetStockObject(BLACK_BRUSH));
}
TextOut(hdc, rect.left + 5, h + 2, (char *)lpls->itemText,
strlen((char *)lpls->itemText));
if (lpls->dis.itemState != 0) {
SetTextColor(hdc, dwOldTextColor);
}
SetBkMode(hdc, OldBkMode);
if ((lphl->ItemFocused == i - 1) && GetFocus() == hwnd) {
DrawFocusRect(hdc, &lpls->dis.rcItem);
}
h += h2;
lphl->ItemsVisible++;
ipc++;
}
if (lpls->lpNext == NULL) goto EndOfPaint;
lpls = (LPLISTSTRUCT)lpls->lpNext;
}
EndOfPaint:
EndPaint( hwnd, &ps );
if ((lphl->ItemsCount > lphl->ItemsVisible) &
(wndPtr->dwStyle & WS_VSCROLL)) {
/*
InvalidateRect(wndPtr->hWndVScroll, NULL, TRUE);
UpdateWindow(wndPtr->hWndVScroll);
*/
}
}
void OwnerDrawListBox(HWND hwnd)
{
WND *wndPtr,*ParentWndPtr;
LPHEADLIST lphl;
LPLISTSTRUCT lpls;
PAINTSTRUCT ps;
HBRUSH hBrush;
HWND hWndParent;
DWORD itemData;
HDC hdc;
RECT rect;
int i, h, h2, maxwidth;
h = 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;
hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
MAKELONG(hwnd, CTLCOLOR_LISTBOX));
if (hBrush == (HBRUSH)NULL) hBrush = GetStockObject(WHITE_BRUSH);
GetClientRect(hwnd, &rect);
if (wndPtr->dwStyle & WS_VSCROLL) rect.right -= 16;
if (wndPtr->dwStyle & WS_HSCROLL) rect.bottom -= 16;
FillRect(hdc, &rect, hBrush);
maxwidth = rect.right;
rect.right = lphl->ColumnsWidth;
if (lphl->ItemsCount == 0) goto EndOfPaint;
lpls = lphl->lpFirst;
if (lpls == NULL) goto EndOfPaint;
lphl->ItemsVisible = 0;
for (i = 1; i <= lphl->ItemsCount; i++) {
if (i >= lphl->FirstVisible) {
lpls->dis.hDC = hdc;
lpls->dis.hwndItem = hwnd;
lpls->dis.CtlType = ODT_LISTBOX;
lpls->dis.itemID = i - 1;
if ((!lpls->dis.CtlID) && (lphl->hWndLogicParent)) {
ParentWndPtr = WIN_FindWndPtr(lphl->hWndLogicParent);
lpls->dis.CtlID = ParentWndPtr->wIDmenu;
}
h2 = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
lpls->dis.rcItem.top = h;
lpls->dis.rcItem.bottom = h + h2;
lpls->dis.rcItem.left = rect.left;
lpls->dis.rcItem.right = rect.right;
lpls->dis.itemAction = ODA_DRAWENTIRE;
/* if (lpls->dis.itemState != 0) {
lpls->dis.itemAction |= ODA_SELECT;
}
if (lphl->ItemFocused == i - 1) {
lpls->dis.itemAction |= ODA_FOCUS;
}*/
dprintf_listbox(stddeb,"LBOX WM_DRAWITEM #%d left=%d top=%d right=%d bottom=%d !\n",
i-1, lpls->dis.rcItem.left, lpls->dis.rcItem.top,
lpls->dis.rcItem.right, lpls->dis.rcItem.bottom);
dprintf_listbox(stddeb,"LBOX WM_DRAWITEM Parent=%X &dis=%lX CtlID=%u !\n",
hWndParent, (LONG)&lpls->dis, lpls->dis.CtlID);
dprintf_listbox(stddeb,"LBOX WM_DRAWITEM %08lX!\n",lpls->dis.itemData);
if (HasStrings(wndPtr))
dprintf_listbox(stddeb," '%s'\n",lpls->itemText);
if (HasStrings(wndPtr)) {
itemData = lpls->dis.itemData;
lpls->dis.itemData = (DWORD)lpls->itemText;
}
SendMessage(lphl->hWndLogicParent, WM_DRAWITEM,
i-1, (LPARAM)&lpls->dis);
if (HasStrings(wndPtr))
lpls->dis.itemData = itemData;
/* if (lpls->dis.itemState != 0) {
InvertRect(hdc, &lpls->dis.rcItem);
} */
h += h2;
lphl->ItemsVisible++;
/* if (h > rect.bottom) goto EndOfPaint;*/
}
if (lpls->lpNext == NULL) goto EndOfPaint;
lpls = (LPLISTSTRUCT)lpls->lpNext;
}
EndOfPaint:
EndPaint( hwnd, &ps );
if ((lphl->ItemsCount > lphl->ItemsVisible) &
(wndPtr->dwStyle & WS_VSCROLL)) {
/*
InvalidateRect(wndPtr->hWndVScroll, NULL, TRUE);
UpdateWindow(wndPtr->hWndVScroll);
*/
}
}
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);
if (wndPtr->dwStyle & WS_VSCROLL) rect.right -= 16;
if (wndPtr->dwStyle & WS_HSCROLL) rect.bottom -= 16;
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);
}
int CreateListBoxStruct(HWND hwnd)
{
WND *wndPtr;
LPHEADLIST lphl;
int HeapHandle;
void *HeapBase;
wndPtr = WIN_FindWndPtr(hwnd);
lphl = (LPHEADLIST)malloc(sizeof(HEADLIST));
lphl->lpFirst = NULL;
*((LPHEADLIST *)&wndPtr->wExtra[1]) = lphl; /* HEAD of List */
lphl->ItemsCount = 0;
lphl->ItemsVisible = 0;
lphl->FirstVisible = 1;
lphl->ColumnsVisible = 1;
lphl->ItemsPerColumn = 0;
lphl->StdItemHeight = 15;
lphl->ItemFocused = 0;
lphl->PrevFocused = 0;
lphl->SelCount = 0;
lphl->DrawCtlType = ODT_LISTBOX;
lphl->bRedrawFlag = TRUE;
HeapHandle = GlobalAlloc(GMEM_FIXED, LIST_HEAP_SIZE);
HeapBase = GlobalLock(HeapHandle);
HEAP_Init(&lphl->Heap, HeapBase, LIST_HEAP_SIZE);
return TRUE;
}
void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls)
{
MEASUREITEMSTRUCT *lpmeasure;
HANDLE hTemp = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(MEASUREITEMSTRUCT));
lpmeasure = (MEASUREITEMSTRUCT *) USER_HEAP_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, (DWORD)lpmeasure);
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_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) ||
((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED))
ListBoxAskMeasure(wndPtr, lphl, lplsnew);
if (wndPtr->dwStyle & WS_VSCROLL)
SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl),
(lphl->FirstVisible != 1 && lphl->bRedrawFlag));
if ((wndPtr->dwStyle & WS_HSCROLL) && lphl->ItemsPerColumn != 0)
SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
lphl->ItemsPerColumn + 1,
(lphl->FirstVisible != 1 && lphl->bRedrawFlag));
if (((lphl->ItemsCount - lphl->FirstVisible) == lphl->ItemsVisible) &&
(lphl->ItemsVisible != 0)) {
if (wndPtr->dwStyle & WS_VSCROLL) ShowScrollBar(hwnd, SB_VERT, TRUE);
if (wndPtr->dwStyle & WS_HSCROLL) ShowScrollBar(hwnd, SB_HORZ, TRUE);
}
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;
LPHEADLIST lphl;
LPLISTSTRUCT lpls;
UINT Count;
if ((!OutStr)&&(!bItemData))
fprintf(stderr, "ListBoxGetText // OutStr==NULL\n");
if (!bItemData) *OutStr=0;
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 > lphl->ItemsCount) return LB_ERR;
for(Count = 0; Count < uIndex; Count++) {
if (lpls->lpNext == NULL) return LB_ERR;
lpls = (LPLISTSTRUCT)lpls->lpNext;
}
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)
{
WND *wndPtr;
LPHEADLIST lphl;
LPLISTSTRUCT lpls;
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 > lphl->ItemsCount) return LB_ERR;
for(Count = 0; Count < uIndex; Count++) {
if (lpls->lpNext == NULL) return LB_ERR;
lpls = (LPLISTSTRUCT)lpls->lpNext;
}
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 > lphl->ItemsCount) return LB_ERR;
for(Count = 1; 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);
if (wndPtr->dwStyle & WS_VSCROLL)
SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
if ((wndPtr->dwStyle & WS_HSCROLL) && lphl->ItemsPerColumn != 0)
SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
lphl->ItemsPerColumn + 1, TRUE);
if (lphl->ItemsCount < lphl->ItemsVisible) {
if (wndPtr->dwStyle & WS_VSCROLL)
ShowScrollBar(hwnd, SB_VERT, FALSE);
if (wndPtr->dwStyle & WS_HSCROLL)
ShowScrollBar(hwnd, SB_HORZ, FALSE);
}
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;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
if (nFirst > lphl->ItemsCount) return LB_ERR;
lpls = lphl->lpFirst;
if (lpls == NULL) return LB_ERR;
Count = 0;
while(lpls != NULL) {
if (HasStrings(wndPtr))
{
if (strcmp(lpls->itemText, MatchStr) == 0) return Count;
}
else
{
if (lpls->dis.itemData == (DWORD)MatchStr) return Count;
}
lpls = (LPLISTSTRUCT)lpls->lpNext;
Count++;
}
return LB_ERR;
}
int ListBoxResetContent(HWND hwnd)
{
WND *wndPtr;
LPHEADLIST lphl;
LPLISTSTRUCT lpls, lpls2;
UINT i;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
lpls = lphl->lpFirst;
if (lpls == NULL) return LB_ERR;
dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n",
lphl->ItemsCount);
for(i = 0; i <= lphl->ItemsCount; i++) {
lpls2 = lpls;
lpls = (LPLISTSTRUCT)lpls->lpNext;
if (i != 0) {
dprintf_listbox(stddeb,"ResetContent #%u\n", i);
if (lpls2->hData != 0 && lpls2->hData != lpls2->hMem)
LIST_HEAP_FREE(lphl, lpls2->hData);
if (lpls2->hMem != 0) LIST_HEAP_FREE(lphl, lpls2->hMem);
}
if (lpls == NULL) break;
}
lphl->lpFirst = NULL;
lphl->FirstVisible = 1;
lphl->ItemsCount = 0;
lphl->ItemFocused = -1;
lphl->PrevFocused = -1;
if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
SendMessage(lphl->hWndLogicParent, WM_COMMAND,
wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
if (wndPtr->dwStyle & WS_VSCROLL)
SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
if ((wndPtr->dwStyle & WS_HSCROLL) && lphl->ItemsPerColumn != 0)
SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
lphl->ItemsPerColumn + 1, TRUE);
if (wndPtr->dwStyle & WS_VSCROLL)
ShowScrollBar(hwnd, SB_VERT, FALSE);
if (wndPtr->dwStyle & WS_HSCROLL)
ShowScrollBar(hwnd, SB_HORZ, FALSE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return TRUE;
}
int ListBoxSetCurSel(HWND hwnd, WORD wIndex)
{
WND *wndPtr;
LPHEADLIST lphl;
LPLISTSTRUCT lpls, lpls2;
UINT i;
lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
if (lphl == NULL) return LB_ERR;
lphl->ItemFocused = LB_ERR;
if (wIndex >= lphl->ItemsCount) return LB_ERR;
lpls = lphl->lpFirst;
if (lpls == NULL) return LB_ERR;
for(i = 0; i < lphl->ItemsCount; i++) {
lpls2 = lpls;
lpls = (LPLISTSTRUCT)lpls->lpNext;
if (i == wIndex)
lpls2->dis.itemState = 1;
else
if (lpls2->dis.itemState != 0)
lpls2->dis.itemState = 0;
if (lpls == NULL) break;
}
lphl->ItemFocused = wIndex;
if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
SendMessage(lphl->hWndLogicParent, WM_COMMAND,
wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
return LB_ERR;
}
int ListBoxSetSel(HWND hwnd, WORD wIndex, WORD state)
{
LPHEADLIST lphl;
LPLISTSTRUCT lpls, lpls2;
UINT i;
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return LB_ERR;
if (wIndex >= lphl->ItemsCount) return LB_ERR;
lpls = lphl->lpFirst;
if (lpls == NULL) return LB_ERR;
for(i = 0; i < lphl->ItemsCount; i++) {
lpls2 = lpls;
lpls = (LPLISTSTRUCT)lpls->lpNext;
if ((i == wIndex) || (wIndex == (WORD)-1)) {
lpls2->dis.itemState = state;
break;
}
if (lpls == NULL) break;
}
return LB_ERR;
}
int ListBoxGetSel(HWND hwnd, WORD wIndex)
{
LPHEADLIST lphl;
LPLISTSTRUCT lpls, lpls2;
UINT i;
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return LB_ERR;
if (wIndex >= lphl->ItemsCount) return LB_ERR;
lpls = lphl->lpFirst;
if (lpls == NULL) return LB_ERR;
for(i = 0; i < lphl->ItemsCount; i++) {
lpls2 = lpls;
lpls = (LPLISTSTRUCT)lpls->lpNext;
if (i == wIndex) {
return lpls2->dis.itemState;
}
if (lpls == NULL) break;
}
return LB_ERR;
}
int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec)
{
struct dosdirent *dp;
int x, wRet;
BOOL OldFlag;
char temp[256];
LPHEADLIST lphl;
dprintf_listbox(stddeb,"ListBoxDirectory: %s, %4x\n",filespec,attrib);
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return LB_ERR;
if ((dp = (struct dosdirent *)DOS_opendir(filespec)) ==NULL) return 0;
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);
if (attrib & DDL_DRIVES) {
for (x=0;x!=MAX_DOS_DRIVES;x++) {
if (DOS_ValidDrive(x)) {
sprintf(temp, "[-%c-]", 'a'+x);
if ( (wRet = ListBoxAddString(hwnd, temp)) == LB_ERR) break;
}
}
}
lphl->bRedrawFlag = OldFlag;
if (OldFlag) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
dprintf_listbox(stddeb,"End of ListBoxDirectory !\n");
return wRet;
}
int ListBoxGetItemRect(HWND hwnd, WORD wIndex, LPRECT lprect)
{
LPHEADLIST lphl;
LPLISTSTRUCT lpls, lpls2;
UINT i;
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return LB_ERR;
if (wIndex > lphl->ItemsCount) return LB_ERR;
lpls = lphl->lpFirst;
if (lpls == NULL) return LB_ERR;
for(i = 0; i < lphl->ItemsCount; i++) {
lpls2 = lpls;
lpls = (LPLISTSTRUCT)lpls->lpNext;
if (i == wIndex) {
*(lprect) = lpls2->dis.rcItem;
break;
}
if (lpls == NULL) break;
}
return LB_ERR;
}
int ListBoxSetItemHeight(HWND hwnd, WORD wIndex, long height)
{
LPHEADLIST lphl;
LPLISTSTRUCT lpls, lpls2;
UINT i;
lphl = ListBoxGetStorageHeader(hwnd);
if (lphl == NULL) return LB_ERR;
if (wIndex > lphl->ItemsCount) return LB_ERR;
lpls = lphl->lpFirst;
if (lpls == NULL) return LB_ERR;
for(i = 0; i < lphl->ItemsCount; i++) {
lpls2 = lpls;
lpls = (LPLISTSTRUCT)lpls->lpNext;
if (i == wIndex) {
lpls2->dis.rcItem.bottom = lpls2->dis.rcItem.top + (short)height;
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
break;
}
if (lpls == NULL) break;
}
return LB_ERR;
}
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 (((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) ||
((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE)) {
if ((wndPtr->dwStyle & LBS_HASSTRINGS) != LBS_HASSTRINGS) {
return LB_ERR;
}
}
Count = 0;
while(lpls != NULL) {
if (Count > lphl->ItemFocused) {
if (*(lpls->itemText) == (char)wChar) {
lphl->FirstVisible = Count - lphl->ItemsVisible / 2;
if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
lphl->ItemFocused = Count;
}
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;
lphl->FirstVisible = Count - lphl->ItemsVisible / 2;
if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
lphl->ItemFocused = Count;
}
else {
ListBoxSetCurSel(hwnd, Count);
}
SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return Count;
}
lpls = (LPLISTSTRUCT)lpls->lpNext;
Count++;
}
return LB_ERR;
}
/************************************************************************
* DlgDirSelect [USER.99]
*/
BOOL DlgDirSelect(HWND hDlg, LPSTR lpStr, int nIDLBox)
{
fprintf(stdnimp,"DlgDirSelect(%04X, '%s', %d) \n", hDlg, lpStr, nIDLBox);
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;
drive = DOS_GetDefaultDrive();
SendDlgItemMessage(hDlg, nIDStat, WM_SETTEXT, 0,
(LONG) DOS_GetCurrentDir(drive) );
}
return ret;
}
/* get the maximum value of lphl->FirstVisible */
int ListMaxFirstVisible(LPHEADLIST lphl)
{
int m = lphl->ItemsCount-lphl->ItemsVisible+1;
return (m < 1) ? 1 : m;
}