mirror of
https://github.com/reactos/wine.git
synced 2024-11-25 20:59:54 +00:00
75d86e1f06
Sun Nov 17 15:01:45 1996 Alexandre Julliard <julliard@lrc.epfl.ch> * [graphics/bitblt.c] [graphics/x11drv/bitblt.c] Moved BitBlt operations to the new graphics driver interface. Implemented PatBlt32, BitBlt32 and StretchBlt32. * [memory/global.c] Unified MemManInfo() and GlobalMemoryStatus(). * [objects/text.c] Fixed ExtTextOut() to always use physical coords for clip rect. * [windows/dialog.c] Implemented DlgDirSelectEx() and Win32 version of DlgDirSelect*. * [windows/event.c] Avoid busy-looping in EVENT_WaitXEvent when no timer is pending (thanks to Thomas Koenig). * [windows/painting.c] Moved update region clipping for CS_PARENTDC windows to BeginPaint(). * [windows/scroll.c] Implemented Win32 version of ScrollWindow() and ScrollDC(). Tue Nov 12 09:52:17 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de> * [files/*.c] [win32/file.c] Some win32 filetime conversion functions added. Fixed behaviour with DOS drives pointing to UNIX / SetCurrentDirectory() may also get X:\xxx paths. Fixed FILE_Open when called from CreateFile(). Added GetFileSize(), MapViewOfFile(), SetFileTime(), GetFileTime(). * [misc/crtdll.c] [if1632/crtdll.spec] Added some new functions. * [if1632/user32.spec] Some thunks into win16 code added. * [win32/init.c] Added GetSystemInfo(), removed GetModuleFileName() stub. * [win32/code_page.c] [if1632/thunk.c] Added EnumSystemCodePages* (untested). * [objects/font.c] [if1632/thunk.c] Added EnumFontFamilies32*. Mon Nov 11 14:50:24 1996 Huw D. M. Davies <h.davies1@physics.oxford.ac.uk> * [controls/menu.c] [windows/mdi.c] Don't delete the MDI `windows' menu if it's already been deleted. * [misc/exec.c] Notepad always calls WinHelp(.., HELP_QUIT, ...) at termination and complains if it returns FALSE. * [windows/winpos.c] Get maximized MDI child's nonclient area redrawn after resize. Thu Nov 7 13:32:34 1996 Lee Jaekil <juria@seodu.co.kr> * [memory/global.c] Use /proc filesystem for GlobalMemoryStatus() on Linux. Mon Nov 4 18:30:00 1996 Alex Korobka <alex@trantor.pharm.sunysb.edu> * [windows/event.c] Added OffiX-style file drop handling. File paths must be DOS-mappable by Wine (via wine.conf). * [controls/combo.c] Added WM_GETTEXT handler. * [objects/palette.c] Added ResizePalette() (untested). * [objects/cursoricon.c] Implemented icon to cursor conversion. * [objects/color.c] Fixed crash on startup when no colorcells are writeable. Mon Nov 4 00:49:41 1996 Ulrich Schmid <uschmid@mail.hh.provi.de> * [rc/winerc.c] Added support for win32 output. * [library/libres.c] [include/libres.h] [loader/resource.c] Renamed LIBRES_FindResource to LIBRES_FindResource16. Added LIBRES_FindResource32. Sun Nov 3 21:21:45 1996 Robert Pouliot <krynos@clic.net> * [loader/builtin.c] [if1632/Makefile.in] [if1632/wing.spec] Added the spec file for WinG, it's only stub for now, but it should be easy to do by someone with Windows programming knowledge. See: ftp.microsoft.com/SoftLib/MSLFILES/wing10.exe. * [if1632/crtdll.spec] Added some string and memory functions to make sfxed95.exe (of Warcraft 2) almost work.
2270 lines
64 KiB
C
2270 lines
64 KiB
C
/*
|
|
* Listbox controls
|
|
*
|
|
* Copyright Martin Ayotte, 1993
|
|
* Constantine Sapuntzakis, 1995
|
|
* Alex Korobka, 1995, 1996
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* FIXME:
|
|
* - proper scrolling for multicolumn style
|
|
* - anchor and caret for LBS_EXTENDEDSEL
|
|
* - proper selection with keyboard
|
|
* - how to handle (LBS_EXTENDEDSEL | LBS_MULTIPLESEL) style
|
|
* - support for LBS_NOINTEGRALHEIGHT and LBS_OWNERDRAWVARIABLE styles
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include "windows.h"
|
|
#include "win.h"
|
|
#include "gdi.h"
|
|
#include "msdos.h"
|
|
#include "listbox.h"
|
|
#include "dos_fs.h"
|
|
#include "drive.h"
|
|
#include "file.h"
|
|
#include "heap.h"
|
|
#include "stddebug.h"
|
|
#include "debug.h"
|
|
#include "xmalloc.h"
|
|
|
|
#define LIST_HEAP_ALLOC(lphl,f,size) \
|
|
LOCAL_Alloc( lphl->HeapSel, LMEM_FIXED, (size) )
|
|
#define LIST_HEAP_FREE(lphl,handle) \
|
|
LOCAL_Free( lphl->HeapSel, (handle) )
|
|
#define LIST_HEAP_ADDR(lphl,handle) \
|
|
((handle) ? PTR_SEG_OFF_TO_LIN(lphl->HeapSel, (handle)) : NULL)
|
|
|
|
#define LIST_HEAP_SIZE 0x10000
|
|
|
|
#define LBMM_EDGE 4 /* distance inside box which is same as moving mouse
|
|
outside box, to trigger scrolling of LB */
|
|
|
|
#define MATCH_SUBSTR 2
|
|
#define MATCH_EXACT 1
|
|
#define MATCH_NEAREST 0
|
|
|
|
static void ListBoxInitialize(LPHEADLIST lphl)
|
|
{
|
|
lphl->lpFirst = NULL;
|
|
lphl->ItemsCount = 0;
|
|
lphl->ItemsVisible = 0;
|
|
lphl->FirstVisible = 0;
|
|
lphl->ColumnsVisible = 1;
|
|
lphl->ItemsPerColumn = 0;
|
|
lphl->ItemFocused = -1;
|
|
lphl->PrevFocused = -1;
|
|
}
|
|
|
|
void CreateListBoxStruct(HWND hwnd, WORD CtlType, LONG styles, HWND parent)
|
|
{
|
|
LPHEADLIST lphl;
|
|
HDC32 hdc;
|
|
|
|
lphl = (LPHEADLIST)xmalloc(sizeof(HEADLIST));
|
|
SetWindowLong32A(hwnd, 0, (LONG)lphl);
|
|
ListBoxInitialize(lphl);
|
|
lphl->DrawCtlType = CtlType;
|
|
lphl->CtlID = GetWindowWord(hwnd,GWW_ID);
|
|
lphl->bRedrawFlag = TRUE;
|
|
lphl->iNumStops = 0;
|
|
lphl->TabStops = NULL;
|
|
lphl->hFont = GetStockObject32(SYSTEM_FONT);
|
|
lphl->hSelf = hwnd;
|
|
if (CtlType==ODT_COMBOBOX) /* use the "faked" style for COMBOLBOX */
|
|
/* LBS_SORT instead CBS_SORT e.g. */
|
|
lphl->dwStyle = MAKELONG(LOWORD(styles),HIWORD(GetWindowLong32A(hwnd,GWL_STYLE)));
|
|
else
|
|
lphl->dwStyle = GetWindowLong32A(hwnd,GWL_STYLE); /* use original style dword */
|
|
lphl->hParent = parent;
|
|
lphl->StdItemHeight = 15; /* FIXME: should get the font height */
|
|
lphl->OwnerDrawn = styles & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE);
|
|
lphl->HasStrings = (styles & LBS_HASSTRINGS) || !lphl->OwnerDrawn;
|
|
|
|
/* create dummy hdc to set text height */
|
|
if ((hdc = GetDC32(0)))
|
|
{
|
|
TEXTMETRIC16 tm;
|
|
GetTextMetrics16( hdc, &tm );
|
|
lphl->StdItemHeight = tm.tmHeight;
|
|
dprintf_listbox(stddeb,"CreateListBoxStruct: font height %d\n",
|
|
lphl->StdItemHeight);
|
|
ReleaseDC32( 0, hdc );
|
|
}
|
|
|
|
if (lphl->OwnerDrawn)
|
|
{
|
|
LISTSTRUCT dummyls;
|
|
|
|
lphl->needMeasure = TRUE;
|
|
dummyls.mis.CtlType = lphl->DrawCtlType;
|
|
dummyls.mis.CtlID = lphl->CtlID;
|
|
dummyls.mis.itemID = -1;
|
|
dummyls.mis.itemWidth = 0; /* ignored */
|
|
dummyls.mis.itemData = 0;
|
|
|
|
ListBoxAskMeasure(lphl,&dummyls);
|
|
}
|
|
|
|
lphl->HeapSel = GlobalAlloc16(GMEM_FIXED,LIST_HEAP_SIZE);
|
|
LocalInit( lphl->HeapSel, 0, LIST_HEAP_SIZE-1);
|
|
}
|
|
|
|
void DestroyListBoxStruct(LPHEADLIST lphl)
|
|
{
|
|
/* XXX need to free lphl->Heap */
|
|
GlobalFree16(lphl->HeapSel);
|
|
free(lphl);
|
|
}
|
|
|
|
static LPHEADLIST ListBoxGetStorageHeader(HWND hwnd)
|
|
{
|
|
return (LPHEADLIST)GetWindowLong32A(hwnd,0);
|
|
}
|
|
|
|
/* Send notification "code" as part of a WM_COMMAND-message if hwnd
|
|
has the LBS_NOTIFY style */
|
|
void ListBoxSendNotification(LPHEADLIST lphl, WORD code)
|
|
{
|
|
if (lphl->dwStyle & LBS_NOTIFY)
|
|
SendMessage32A( lphl->hParent, WM_COMMAND,
|
|
MAKEWPARAM( lphl->CtlID, code), (LPARAM)lphl->hSelf );
|
|
}
|
|
|
|
|
|
/* get the maximum value of lphl->FirstVisible */
|
|
int ListMaxFirstVisible(LPHEADLIST lphl)
|
|
{
|
|
int m = lphl->ItemsCount-lphl->ItemsVisible;
|
|
return (m < 0) ? 0 : m;
|
|
}
|
|
|
|
|
|
void ListBoxUpdateWindow(HWND hwnd, LPHEADLIST lphl, BOOL repaint)
|
|
{
|
|
if (lphl->dwStyle & WS_VSCROLL)
|
|
SetScrollRange32(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
|
|
if ((lphl->dwStyle & WS_HSCROLL) && (lphl->ItemsPerColumn != 0))
|
|
SetScrollRange32(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
|
|
lphl->ItemsPerColumn + 1, TRUE);
|
|
|
|
if (repaint && lphl->bRedrawFlag) InvalidateRect32( hwnd, NULL, TRUE );
|
|
}
|
|
|
|
/* Returns: 0 if nothing needs to be changed */
|
|
/* 1 if FirstVisible changed */
|
|
|
|
int ListBoxScrollToFocus(LPHEADLIST lphl)
|
|
{
|
|
short end;
|
|
|
|
if (lphl->ItemsCount == 0) return 0;
|
|
if (lphl->ItemFocused == -1) return 0;
|
|
|
|
end = lphl->FirstVisible + lphl->ItemsVisible - 1;
|
|
|
|
if (lphl->ItemFocused < lphl->FirstVisible ) {
|
|
lphl->FirstVisible = lphl->ItemFocused;
|
|
return 1;
|
|
} else {
|
|
if (lphl->ItemFocused > end) {
|
|
WORD maxFirstVisible = ListMaxFirstVisible(lphl);
|
|
|
|
lphl->FirstVisible = lphl->ItemFocused;
|
|
|
|
if (lphl->FirstVisible > maxFirstVisible) {
|
|
lphl->FirstVisible = maxFirstVisible;
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
LPLISTSTRUCT ListBoxGetItem(LPHEADLIST lphl, UINT uIndex)
|
|
{
|
|
LPLISTSTRUCT lpls;
|
|
UINT Count = 0;
|
|
|
|
if (uIndex >= lphl->ItemsCount) return NULL;
|
|
|
|
lpls = lphl->lpFirst;
|
|
while (Count++ < uIndex) lpls = lpls->lpNext;
|
|
return lpls;
|
|
}
|
|
|
|
|
|
void ListBoxDrawItem(HWND hwnd, LPHEADLIST lphl, HDC16 hdc, LPLISTSTRUCT lpls,
|
|
RECT16 *rect, WORD itemAction, WORD itemState)
|
|
{
|
|
if (lphl->OwnerDrawn)
|
|
{
|
|
DRAWITEMSTRUCT32 dis;
|
|
|
|
dis.CtlID = lpls->mis.CtlID;
|
|
dis.CtlType = lpls->mis.CtlType;
|
|
dis.itemID = lpls->mis.itemID;
|
|
dis.hDC = hdc;
|
|
dis.hwndItem = hwnd;
|
|
dis.itemData = lpls->mis.itemData;
|
|
dis.itemAction = itemAction;
|
|
dis.itemState = itemState;
|
|
CONV_RECT16TO32( rect, &dis.rcItem );
|
|
SendMessage32A( lphl->hParent, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis );
|
|
return;
|
|
}
|
|
if (itemAction == ODA_DRAWENTIRE || itemAction == ODA_SELECT) {
|
|
int OldBkMode;
|
|
DWORD dwOldTextColor = 0;
|
|
|
|
OldBkMode = SetBkMode(hdc, TRANSPARENT);
|
|
|
|
if (itemState != 0) {
|
|
dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
|
|
FillRect16(hdc, rect, GetStockObject32(BLACK_BRUSH));
|
|
}
|
|
|
|
if (lphl->dwStyle & LBS_USETABSTOPS) {
|
|
TabbedTextOut(hdc, rect->left + 5, rect->top + 2,
|
|
(char *)lpls->itemText, strlen((char *)lpls->itemText),
|
|
lphl->iNumStops, lphl->TabStops, 0);
|
|
} else {
|
|
TextOut16(hdc, rect->left + 5, rect->top + 2,
|
|
(char *)lpls->itemText, strlen((char *)lpls->itemText));
|
|
}
|
|
|
|
if (itemState != 0) {
|
|
SetTextColor(hdc, dwOldTextColor);
|
|
}
|
|
|
|
SetBkMode(hdc, OldBkMode);
|
|
}
|
|
else DrawFocusRect16(hdc, rect);
|
|
}
|
|
|
|
|
|
int ListBoxFindMouse(LPHEADLIST lphl, int X, int Y)
|
|
{
|
|
LPLISTSTRUCT lpls = lphl->lpFirst;
|
|
int i, j;
|
|
POINT16 point;
|
|
|
|
point.x = X; point.y = Y;
|
|
if (lphl->ItemsCount == 0) return LB_ERR;
|
|
|
|
for(i = 0; i < lphl->FirstVisible; i++) {
|
|
if (lpls == NULL) return LB_ERR;
|
|
lpls = lpls->lpNext;
|
|
}
|
|
for(j = 0; j < lphl->ItemsVisible; i++, j++) {
|
|
if (lpls == NULL) return LB_ERR;
|
|
if (PtInRect16(&lpls->itemRect,point)) {
|
|
return i;
|
|
}
|
|
lpls = lpls->lpNext;
|
|
}
|
|
dprintf_listbox(stddeb,"ListBoxFindMouse: not found\n");
|
|
return LB_ERR;
|
|
}
|
|
|
|
BOOL32 lbDeleteItemNotify(LPHEADLIST lphl, LPLISTSTRUCT lpls)
|
|
{
|
|
/* called only for owner drawn listboxes */
|
|
BOOL32 ret;
|
|
DELETEITEMSTRUCT16 *delItem = SEGPTR_NEW(DELETEITEMSTRUCT16);
|
|
if (!delItem) return FALSE;
|
|
|
|
delItem->CtlType = lphl->DrawCtlType;
|
|
delItem->CtlID = lphl->CtlID;
|
|
delItem->itemID = lpls->mis.itemID;
|
|
delItem->hwndItem = lphl->hSelf;
|
|
delItem->itemData = lpls->mis.itemData;
|
|
|
|
ret = SendMessage16( lphl->hParent, WM_DELETEITEM, (WPARAM16)lphl->CtlID,
|
|
(LPARAM)SEGPTR_GET(delItem) );
|
|
SEGPTR_FREE(delItem);
|
|
return ret;
|
|
}
|
|
|
|
void ListBoxAskMeasure(LPHEADLIST lphl, LPLISTSTRUCT lpls)
|
|
{
|
|
MEASUREITEMSTRUCT16 *lpmeasure = SEGPTR_NEW(MEASUREITEMSTRUCT16);
|
|
if (!lpmeasure) return;
|
|
*lpmeasure = lpls->mis;
|
|
lpmeasure->itemHeight = lphl->StdItemHeight;
|
|
SendMessage16( lphl->hParent, WM_MEASUREITEM, lphl->CtlID,
|
|
(LPARAM)SEGPTR_GET(lpmeasure) );
|
|
|
|
if (lphl->dwStyle & LBS_OWNERDRAWFIXED)
|
|
{
|
|
if (lpmeasure->itemHeight > lphl->StdItemHeight)
|
|
lphl->StdItemHeight = lpmeasure->itemHeight;
|
|
lpls->mis.itemHeight = lpmeasure->itemHeight;
|
|
}
|
|
SEGPTR_FREE(lpmeasure);
|
|
}
|
|
|
|
/* -------------------- strings and item data ---------------------- */
|
|
|
|
LPLISTSTRUCT ListBoxCreateItem(LPHEADLIST lphl, int id)
|
|
{
|
|
LPLISTSTRUCT lplsnew = (LPLISTSTRUCT)malloc(sizeof(LISTSTRUCT));
|
|
|
|
if (lplsnew == NULL) return NULL;
|
|
|
|
lplsnew->itemState = 0;
|
|
lplsnew->mis.CtlType = lphl->DrawCtlType;
|
|
lplsnew->mis.CtlID = lphl->CtlID;
|
|
lplsnew->mis.itemID = id;
|
|
lplsnew->mis.itemHeight = lphl->StdItemHeight;
|
|
lplsnew->mis.itemWidth = 0; /* ignored */
|
|
lplsnew->mis.itemData = 0;
|
|
SetRectEmpty16( &lplsnew->itemRect );
|
|
|
|
return lplsnew;
|
|
}
|
|
|
|
int ListBoxAskCompare(LPHEADLIST lphl, int startItem, SEGPTR matchData, BOOL exactMatch )
|
|
{
|
|
/* Do binary search for sorted listboxes. Linked list item storage sort of
|
|
* defeats the purpose ( forces to traverse item list all the time ) but M$ does it this way...
|
|
*
|
|
* MATCH_NEAREST (0) - return position for insertion - for all styles
|
|
* MATCH_EXACT (1) - search for an item, return index or LB_ERR
|
|
* MATCH_SUBSTR (2) - same as exact match but with strncmp for string comparision
|
|
*/
|
|
|
|
COMPAREITEMSTRUCT16 *itemCmp;
|
|
LPLISTSTRUCT currentItem = NULL;
|
|
LPCSTR matchStr = (lphl->HasStrings)?(LPCSTR)PTR_SEG_TO_LIN(matchData):NULL;
|
|
int head, pos = -1, tail, loop = 1;
|
|
short b = 0, s_length = 0;
|
|
|
|
/* check if empty */
|
|
|
|
if( !lphl->ItemsCount )
|
|
return (exactMatch)? LB_ERR: 0;
|
|
|
|
/* set up variables */
|
|
|
|
if( exactMatch == MATCH_NEAREST )
|
|
startItem = 0;
|
|
else if( ++startItem )
|
|
{
|
|
loop = 2;
|
|
if( startItem >= lphl->ItemsCount ) startItem = lphl->ItemsCount - 1;
|
|
}
|
|
|
|
if( exactMatch == MATCH_SUBSTR && lphl->HasStrings )
|
|
{
|
|
s_length = strlen( matchStr );
|
|
if( !s_length ) return 0; /* head of the list - empty string */
|
|
}
|
|
|
|
head = startItem; tail = lphl->ItemsCount - 1;
|
|
|
|
dprintf_listbox(stddeb,"AskCompare: head = %i, tail = %i, data = %08x\n", head, tail, (unsigned)matchData );
|
|
|
|
if (!(itemCmp = SEGPTR_NEW(COMPAREITEMSTRUCT16))) return 0;
|
|
itemCmp->CtlType = lphl->DrawCtlType;
|
|
itemCmp->CtlID = lphl->CtlID;
|
|
itemCmp->hwndItem = lphl->hSelf;
|
|
|
|
/* search from startItem */
|
|
|
|
while ( loop-- )
|
|
{
|
|
while( head <= tail )
|
|
{
|
|
pos = (tail + head)/2;
|
|
currentItem = ListBoxGetItem( lphl, pos );
|
|
|
|
if( lphl->HasStrings )
|
|
{
|
|
b = ( s_length )? lstrncmpi32A( currentItem->itemText, matchStr, s_length)
|
|
: lstrcmpi32A( currentItem->itemText, matchStr);
|
|
}
|
|
else
|
|
{
|
|
itemCmp->itemID1 = pos;
|
|
itemCmp->itemData1 = currentItem->mis.itemData;
|
|
itemCmp->itemID2 = -1;
|
|
itemCmp->itemData2 = matchData;
|
|
|
|
b = SendMessage16( lphl->hParent, WM_COMPAREITEM,
|
|
(WPARAM16)lphl->CtlID,
|
|
(LPARAM)SEGPTR_GET(itemCmp) );
|
|
}
|
|
|
|
if( b == 0 )
|
|
{
|
|
SEGPTR_FREE(itemCmp);
|
|
return pos; /* found exact match */
|
|
}
|
|
else
|
|
if( b < 0 ) head = ++pos;
|
|
else
|
|
if( b > 0 ) tail = pos - 1;
|
|
}
|
|
|
|
/* reset to search from the first item */
|
|
head = 0; tail = startItem - 1;
|
|
}
|
|
|
|
dprintf_listbox(stddeb,"\t-> pos = %i\n", pos );
|
|
SEGPTR_FREE(itemCmp);
|
|
|
|
/* if we got here match is not exact */
|
|
|
|
if( pos < 0 ) pos = 0;
|
|
else if( pos > lphl->ItemsCount ) pos = lphl->ItemsCount;
|
|
|
|
return (exactMatch)? LB_ERR: pos;
|
|
}
|
|
|
|
int ListBoxInsertString(LPHEADLIST lphl, UINT uIndex, LPCSTR newstr)
|
|
{
|
|
LPLISTSTRUCT *lppls, lplsnew, lpls;
|
|
HANDLE16 hStr;
|
|
LPSTR str;
|
|
UINT Count;
|
|
|
|
dprintf_listbox(stddeb,"ListBoxInsertString(%d, %p);\n", uIndex, newstr);
|
|
|
|
if (!newstr) return -1;
|
|
|
|
if (uIndex == (UINT)-1)
|
|
uIndex = lphl->ItemsCount;
|
|
|
|
lppls = &lphl->lpFirst;
|
|
for(Count = 0; Count < uIndex; Count++) {
|
|
if (*lppls == NULL) return LB_ERR;
|
|
lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
|
|
}
|
|
|
|
lplsnew = ListBoxCreateItem(lphl, Count);
|
|
|
|
if (lplsnew == NULL) {
|
|
fprintf(stdnimp,"ListBoxInsertString() out of memory !\n");
|
|
return LB_ERRSPACE;
|
|
}
|
|
|
|
lplsnew->lpNext = *lppls;
|
|
*lppls = lplsnew;
|
|
lphl->ItemsCount++;
|
|
|
|
hStr = 0;
|
|
if (lphl->HasStrings) {
|
|
dprintf_listbox(stddeb," string: %s\n", newstr);
|
|
hStr = LIST_HEAP_ALLOC(lphl, LMEM_MOVEABLE, strlen(newstr) + 1);
|
|
str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
|
|
if (str == NULL) return LB_ERRSPACE;
|
|
strcpy(str, newstr);
|
|
lplsnew->itemText = str;
|
|
/* I'm not so sure about the next one */
|
|
lplsnew->mis.itemData = 0;
|
|
} else {
|
|
lplsnew->itemText = NULL;
|
|
lplsnew->mis.itemData = (DWORD)newstr;
|
|
}
|
|
|
|
lplsnew->mis.itemID = uIndex;
|
|
lplsnew->hData = hStr;
|
|
|
|
/* adjust the itemID field of the following entries */
|
|
for(lpls = lplsnew->lpNext; lpls != NULL; lpls = lpls->lpNext) {
|
|
lpls->mis.itemID++;
|
|
}
|
|
|
|
if (lphl->needMeasure) {
|
|
ListBoxAskMeasure(lphl, lplsnew);
|
|
}
|
|
|
|
dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
|
|
return uIndex;
|
|
}
|
|
|
|
|
|
int ListBoxAddString(LPHEADLIST lphl, SEGPTR itemData)
|
|
{
|
|
UINT pos = (UINT) -1;
|
|
LPCSTR newstr = (lphl->HasStrings)?(LPCSTR)PTR_SEG_TO_LIN(itemData):(LPCSTR)itemData;
|
|
|
|
if ( lphl->dwStyle & LBS_SORT )
|
|
pos = ListBoxAskCompare( lphl, -1, itemData, MATCH_NEAREST );
|
|
|
|
return ListBoxInsertString(lphl, pos, newstr);
|
|
}
|
|
|
|
|
|
int ListBoxGetText(LPHEADLIST lphl, UINT uIndex, LPSTR OutStr)
|
|
{
|
|
LPLISTSTRUCT lpls;
|
|
|
|
if (!OutStr) {
|
|
dprintf_listbox(stddeb, "ListBoxGetText // OutStr==NULL\n");
|
|
return 0;
|
|
}
|
|
*OutStr = '\0';
|
|
lpls = ListBoxGetItem (lphl, uIndex);
|
|
if (lpls == NULL) return LB_ERR;
|
|
|
|
if (!lphl->HasStrings) {
|
|
*((long *)OutStr) = lpls->mis.itemData;
|
|
return 4;
|
|
}
|
|
|
|
strcpy(OutStr, lpls->itemText);
|
|
return strlen(OutStr);
|
|
}
|
|
|
|
|
|
DWORD ListBoxGetItemData(LPHEADLIST lphl, UINT uIndex)
|
|
{
|
|
LPLISTSTRUCT lpls;
|
|
|
|
lpls = ListBoxGetItem (lphl, uIndex);
|
|
if (lpls == NULL) return LB_ERR;
|
|
return lpls->mis.itemData;
|
|
}
|
|
|
|
|
|
int ListBoxSetItemData(LPHEADLIST lphl, UINT uIndex, DWORD ItemData)
|
|
{
|
|
LPLISTSTRUCT lpls = ListBoxGetItem(lphl, uIndex);
|
|
|
|
if (lpls == NULL) return LB_ERR;
|
|
lpls->mis.itemData = ItemData;
|
|
return 1;
|
|
}
|
|
|
|
|
|
int ListBoxDeleteString(LPHEADLIST lphl, UINT uIndex)
|
|
{
|
|
LPLISTSTRUCT lpls, lpls2;
|
|
UINT Count;
|
|
|
|
if (uIndex >= lphl->ItemsCount) return LB_ERR;
|
|
|
|
lpls = lphl->lpFirst;
|
|
if (lpls == NULL) return LB_ERR;
|
|
|
|
if (uIndex == 0)
|
|
{
|
|
if( lphl->OwnerDrawn )
|
|
lbDeleteItemNotify( lphl, lpls);
|
|
lphl->lpFirst = lpls->lpNext;
|
|
}
|
|
else
|
|
{
|
|
LPLISTSTRUCT lpls2 = NULL;
|
|
for(Count = 0; Count < uIndex; Count++) {
|
|
if (lpls->lpNext == NULL) return LB_ERR;
|
|
|
|
lpls2 = lpls;
|
|
lpls = (LPLISTSTRUCT)lpls->lpNext;
|
|
}
|
|
if( lphl->OwnerDrawn )
|
|
lbDeleteItemNotify( lphl, lpls);
|
|
lpls2->lpNext = lpls->lpNext;
|
|
}
|
|
|
|
/* adjust the itemID field of the following entries */
|
|
for(lpls2 = lpls->lpNext; lpls2 != NULL; lpls2 = lpls2->lpNext) {
|
|
lpls2->mis.itemID--;
|
|
}
|
|
|
|
lphl->ItemsCount--;
|
|
|
|
if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
|
|
free(lpls);
|
|
|
|
return lphl->ItemsCount;
|
|
}
|
|
|
|
int lbFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr, BOOL match)
|
|
{
|
|
/* match is either MATCH_SUBSTR or MATCH_EXACT */
|
|
|
|
LPLISTSTRUCT lpls;
|
|
UINT Count;
|
|
UINT First = nFirst + 1;
|
|
int s_length = 0;
|
|
LPSTR lpMatchStr = (LPSTR)MatchStr;
|
|
|
|
if (First > lphl->ItemsCount) return LB_ERR;
|
|
|
|
if (lphl->dwStyle & LBS_SORT )
|
|
return ListBoxAskCompare( lphl, nFirst, MatchStr, match );
|
|
|
|
if (lphl->HasStrings )
|
|
{
|
|
lpMatchStr = PTR_SEG_TO_LIN(MatchStr);
|
|
|
|
if( match == MATCH_SUBSTR )
|
|
{
|
|
s_length = strlen(lpMatchStr);
|
|
if( !s_length ) return (lphl->ItemsCount)?0:LB_ERR;
|
|
}
|
|
}
|
|
|
|
lpls = ListBoxGetItem(lphl, First);
|
|
Count = 0;
|
|
while(lpls != NULL)
|
|
{
|
|
if (lphl->HasStrings)
|
|
{
|
|
if ( ( s_length )? !lstrncmpi32A(lpls->itemText, lpMatchStr, s_length)
|
|
: !lstrcmpi32A(lpls->itemText, lpMatchStr) ) return Count;
|
|
}
|
|
else
|
|
if ( lpls->mis.itemData == (DWORD)lpMatchStr ) return Count;
|
|
|
|
lpls = lpls->lpNext;
|
|
Count++;
|
|
}
|
|
|
|
/* Start over at top */
|
|
Count = 0;
|
|
lpls = lphl->lpFirst;
|
|
|
|
while (Count < First)
|
|
{
|
|
if (lphl->HasStrings)
|
|
{
|
|
if ( ( s_length )? !lstrncmpi32A(lpls->itemText, lpMatchStr, s_length)
|
|
: !lstrcmpi32A(lpls->itemText, lpMatchStr) ) return Count;
|
|
}
|
|
else
|
|
if ( lpls->mis.itemData == (DWORD)lpMatchStr ) return Count;
|
|
|
|
lpls = lpls->lpNext;
|
|
Count++;
|
|
}
|
|
|
|
return LB_ERR;
|
|
}
|
|
|
|
int ListBoxFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr)
|
|
{
|
|
return lbFindString(lphl, nFirst, MatchStr, MATCH_SUBSTR );
|
|
}
|
|
|
|
int ListBoxFindStringExact(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr)
|
|
{
|
|
return lbFindString(lphl, nFirst, MatchStr, MATCH_EXACT );
|
|
}
|
|
|
|
int ListBoxResetContent(LPHEADLIST lphl)
|
|
{
|
|
LPLISTSTRUCT lpls;
|
|
int i;
|
|
|
|
if (lphl->ItemsCount == 0) return 0;
|
|
|
|
dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n",
|
|
lphl->ItemsCount);
|
|
|
|
for(i = 0; i < lphl->ItemsCount; i++) {
|
|
lpls = lphl->lpFirst;
|
|
if (lpls == NULL) return LB_ERR;
|
|
|
|
if (lphl->OwnerDrawn) lbDeleteItemNotify(lphl, lpls);
|
|
|
|
lphl->lpFirst = lpls->lpNext;
|
|
if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
|
|
free(lpls);
|
|
}
|
|
ListBoxInitialize(lphl);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* --------------------- selection ------------------------- */
|
|
|
|
int ListBoxSetCurSel(LPHEADLIST lphl, WORD wIndex)
|
|
{
|
|
LPLISTSTRUCT lpls;
|
|
|
|
/* use ListBoxSetSel instead */
|
|
if (lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ) return 0;
|
|
|
|
/* unselect previous item */
|
|
if (lphl->ItemFocused != -1) {
|
|
lphl->PrevFocused = lphl->ItemFocused;
|
|
lpls = ListBoxGetItem(lphl, lphl->ItemFocused);
|
|
if (lpls == 0) return LB_ERR;
|
|
lpls->itemState = 0;
|
|
}
|
|
|
|
if ((wIndex != (UINT)-1) && (wIndex < lphl->ItemsCount))
|
|
{
|
|
lphl->ItemFocused = wIndex;
|
|
lpls = ListBoxGetItem(lphl, wIndex);
|
|
if (lpls == 0) return LB_ERR;
|
|
lpls->itemState = ODS_SELECTED | ODS_FOCUS;
|
|
|
|
return 0;
|
|
}
|
|
|
|
return LB_ERR;
|
|
}
|
|
|
|
|
|
int ListBoxSetSel(LPHEADLIST lphl, WORD wIndex, WORD state)
|
|
{
|
|
LPLISTSTRUCT lpls;
|
|
int n = 0;
|
|
|
|
if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
|
|
return LB_ERR;
|
|
|
|
if (wIndex == (UINT)-1) {
|
|
for (lpls = lphl->lpFirst; lpls != NULL; lpls = lpls->lpNext) {
|
|
if( lpls->itemState & ODS_SELECTED) n++;
|
|
lpls->itemState = state? lpls->itemState | ODS_SELECTED
|
|
: lpls->itemState & ~ODS_SELECTED;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
if (wIndex >= lphl->ItemsCount) return LB_ERR;
|
|
|
|
lpls = ListBoxGetItem(lphl, wIndex);
|
|
lpls->itemState = state? lpls->itemState | ODS_SELECTED
|
|
: lpls->itemState & ~ODS_SELECTED;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int ListBoxGetSel(LPHEADLIST lphl, WORD wIndex)
|
|
{
|
|
LPLISTSTRUCT lpls = ListBoxGetItem(lphl, wIndex);
|
|
|
|
if (lpls == NULL) return LB_ERR;
|
|
return lpls->itemState & ODS_SELECTED;
|
|
}
|
|
|
|
/* ------------------------- dir listing ------------------------ */
|
|
|
|
LONG ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPCSTR filespec)
|
|
{
|
|
char mask[13];
|
|
char* temp = NULL;
|
|
const char* ptr;
|
|
int skip, count;
|
|
LONG ret;
|
|
DOS_DIRENT entry;
|
|
char *path, *p;
|
|
|
|
dprintf_listbox(stddeb, "ListBoxDirectory: '%s' %04x\n", filespec, attrib);
|
|
if (!filespec) return LB_ERR;
|
|
if (!(ptr = DOSFS_GetUnixFileName( filespec, FALSE ))) return LB_ERR;
|
|
path = xstrdup(ptr);
|
|
p = strrchr( path, '/' );
|
|
*p++ = '\0';
|
|
if (!(ptr = DOSFS_ToDosFCBFormat( p )) ||
|
|
!(temp = SEGPTR_ALLOC( sizeof(char) * 16 )) )
|
|
{
|
|
free( path );
|
|
return LB_ERR;
|
|
}
|
|
|
|
strcpy( mask, ptr );
|
|
|
|
dprintf_listbox(stddeb, "ListBoxDirectory: path=%s mask=%s\n", path, mask);
|
|
|
|
skip = ret = 0;
|
|
attrib &= ~FA_LABEL;
|
|
while ((count = DOSFS_FindNext( path, mask, NULL, 0,
|
|
attrib, skip, &entry )) > 0)
|
|
{
|
|
skip += count;
|
|
if (entry.attr & FA_DIRECTORY)
|
|
{
|
|
if ((attrib & DDL_DIRECTORY) && strcmp(entry.name, ". "))
|
|
{
|
|
sprintf(temp, "[%s]", DOSFS_ToDosDTAFormat( entry.name ) );
|
|
AnsiLower( temp );
|
|
if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break;
|
|
}
|
|
}
|
|
else /* not a directory */
|
|
{
|
|
if (!(attrib & DDL_EXCLUSIVE) ||
|
|
((attrib & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)) ==
|
|
(entry.attr & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE))))
|
|
{
|
|
strcpy( temp, DOSFS_ToDosDTAFormat( entry.name ) );
|
|
AnsiLower( temp );
|
|
if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break;
|
|
}
|
|
}
|
|
|
|
dprintf_listbox(stddeb,"\tn - %i, file '%s'\n", count, temp);
|
|
}
|
|
if (attrib & DDL_DRIVES)
|
|
{
|
|
int x;
|
|
DWORD oldstyle = lphl->dwStyle;
|
|
|
|
lphl->dwStyle &= ~LBS_SORT;
|
|
strcpy( temp, "[-a-]" );
|
|
for (x = 0; x < MAX_DOS_DRIVES; x++, temp[2]++)
|
|
{
|
|
if (DRIVE_IsValid(x))
|
|
if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break;
|
|
}
|
|
lphl->dwStyle = oldstyle;
|
|
}
|
|
|
|
free( path );
|
|
SEGPTR_FREE( temp );
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* ------------------------- dimensions ------------------------- */
|
|
|
|
int ListBoxGetItemRect(LPHEADLIST lphl, WORD wIndex, LPRECT16 lprect)
|
|
{
|
|
LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wIndex);
|
|
|
|
dprintf_listbox(stddeb,"ListBox LB_GETITEMRECT %i %p", wIndex,lpls);
|
|
if (lpls == NULL)
|
|
{
|
|
if (lphl->dwStyle & LBS_OWNERDRAWVARIABLE)
|
|
return LB_ERR;
|
|
else
|
|
{
|
|
GetClientRect16(lphl->hSelf,lprect);
|
|
lprect->bottom=lphl->StdItemHeight;
|
|
if (lprect->right<0) lprect->right=0;
|
|
}
|
|
}
|
|
else
|
|
*lprect = lpls->itemRect;
|
|
dprintf_listbox(stddeb," = %d,%d %d,%d\n", lprect->left,lprect->top,
|
|
lprect->right,lprect->bottom);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int ListBoxSetItemHeight(LPHEADLIST lphl, WORD wIndex, long height)
|
|
{
|
|
LPLISTSTRUCT lpls;
|
|
|
|
if (!(lphl->dwStyle & LBS_OWNERDRAWVARIABLE)) {
|
|
lphl->StdItemHeight = (short)height;
|
|
return 0;
|
|
}
|
|
|
|
lpls = ListBoxGetItem(lphl, wIndex);
|
|
if (lpls == NULL) return LB_ERR;
|
|
|
|
lpls->mis.itemHeight = height;
|
|
return 0;
|
|
}
|
|
|
|
/* -------------------------- string search ------------------------ */
|
|
|
|
int ListBoxFindNextMatch(LPHEADLIST lphl, WORD wChar)
|
|
{
|
|
LPLISTSTRUCT lpls;
|
|
UINT count,first;
|
|
|
|
if ((char)wChar < ' ') return LB_ERR;
|
|
if (!lphl->HasStrings) return LB_ERR;
|
|
|
|
lpls = lphl->lpFirst;
|
|
|
|
for (count = 0; lpls != NULL; lpls = lpls->lpNext, count++) {
|
|
if (tolower(*lpls->itemText) == tolower((char)wChar)) break;
|
|
}
|
|
if (lpls == NULL) return LB_ERR;
|
|
first = count;
|
|
for(; lpls != NULL; lpls = lpls->lpNext, count++) {
|
|
if (*lpls->itemText != (char)wChar)
|
|
break;
|
|
if ((short) count > lphl->ItemFocused)
|
|
return count;
|
|
}
|
|
return first;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBCreate
|
|
*/
|
|
static LONG LBCreate(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl;
|
|
LONG dwStyle = GetWindowLong32A(hwnd,GWL_STYLE);
|
|
RECT16 rect;
|
|
|
|
CreateListBoxStruct(hwnd, ODT_LISTBOX, dwStyle, GetParent16(hwnd));
|
|
lphl = ListBoxGetStorageHeader(hwnd);
|
|
dprintf_listbox(stddeb,"ListBox created: lphl = %p dwStyle = %04x:%04x\n",
|
|
lphl, HIWORD(dwStyle), LOWORD(dwStyle));
|
|
|
|
GetClientRect16(hwnd,&rect);
|
|
lphl->ColumnsWidth = rect.right - rect.left;
|
|
|
|
if (dwStyle & WS_VSCROLL)
|
|
SetScrollRange32(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
|
|
if (dwStyle & WS_HSCROLL)
|
|
SetScrollRange32(hwnd, SB_HORZ, 1, 1, TRUE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* LBDestroy
|
|
*/
|
|
static LONG LBDestroy(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
|
|
ListBoxResetContent(lphl);
|
|
|
|
DestroyListBoxStruct(lphl);
|
|
dprintf_listbox(stddeb,"ListBox destroyed: lphl = %p\n",lphl);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* LBNCCalcSize
|
|
*/
|
|
static LONG LBNCCalcSize(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LONG ret = DefWindowProc16(hwnd, WM_NCCALCSIZE, wParam, lParam);
|
|
|
|
return (GetWindowLong32A(hwnd,GWL_STYLE) & LBS_MULTICOLUMN)? WVR_VREDRAW : ret;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* LBVScroll
|
|
*/
|
|
static LONG LBVScroll(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
int y;
|
|
|
|
dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
|
|
wParam, lParam);
|
|
y = lphl->FirstVisible;
|
|
|
|
switch(wParam) {
|
|
case SB_LINEUP:
|
|
if (lphl->FirstVisible > 0)
|
|
lphl->FirstVisible--;
|
|
break;
|
|
|
|
case SB_LINEDOWN:
|
|
lphl->FirstVisible++;
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
if (lphl->FirstVisible > lphl->ItemsVisible) {
|
|
lphl->FirstVisible -= lphl->ItemsVisible;
|
|
} else {
|
|
lphl->FirstVisible = 0;
|
|
}
|
|
break;
|
|
|
|
case SB_PAGEDOWN:
|
|
lphl->FirstVisible += lphl->ItemsVisible;
|
|
break;
|
|
|
|
case SB_THUMBTRACK:
|
|
lphl->FirstVisible = LOWORD(lParam);
|
|
break;
|
|
}
|
|
|
|
if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
|
|
lphl->FirstVisible = ListMaxFirstVisible(lphl);
|
|
|
|
if (y != lphl->FirstVisible) {
|
|
SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBHScroll
|
|
*/
|
|
static LONG LBHScroll(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl;
|
|
int y;
|
|
|
|
dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
|
|
wParam, lParam);
|
|
lphl = ListBoxGetStorageHeader(hwnd);
|
|
y = lphl->FirstVisible;
|
|
switch(wParam) {
|
|
case SB_LINEUP:
|
|
if (lphl->FirstVisible > lphl->ItemsPerColumn) {
|
|
lphl->FirstVisible -= lphl->ItemsPerColumn;
|
|
} else {
|
|
lphl->FirstVisible = 0;
|
|
}
|
|
break;
|
|
case SB_LINEDOWN:
|
|
lphl->FirstVisible += lphl->ItemsPerColumn;
|
|
break;
|
|
case SB_PAGEUP:
|
|
if (lphl->ItemsPerColumn != 0) {
|
|
int lbsub = lphl->ItemsVisible / lphl->ItemsPerColumn * lphl->ItemsPerColumn;
|
|
if (lphl->FirstVisible > lbsub) {
|
|
lphl->FirstVisible -= lbsub;
|
|
} else {
|
|
lphl->FirstVisible = 0;
|
|
}
|
|
}
|
|
break;
|
|
case SB_PAGEDOWN:
|
|
if (lphl->ItemsPerColumn != 0)
|
|
lphl->FirstVisible += lphl->ItemsVisible /
|
|
lphl->ItemsPerColumn * lphl->ItemsPerColumn;
|
|
break;
|
|
case SB_THUMBTRACK:
|
|
lphl->FirstVisible = lphl->ItemsPerColumn * LOWORD(lParam);
|
|
break;
|
|
}
|
|
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) {
|
|
SetScrollPos32(hwnd, SB_HORZ, lphl->FirstVisible /
|
|
lphl->ItemsPerColumn + 1, TRUE);
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBLButtonDown
|
|
*/
|
|
static LONG LBLButtonDown(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
WORD wRet;
|
|
int y,n;
|
|
RECT16 rectsel;
|
|
|
|
SetFocus32(hwnd);
|
|
SetCapture32(hwnd);
|
|
|
|
lphl->PrevFocused = lphl->ItemFocused;
|
|
|
|
y = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
|
|
|
|
if (y == -1) return 0;
|
|
|
|
if (lphl->dwStyle & LBS_NOTIFY && y!= LB_ERR )
|
|
if( SendMessage16(lphl->hParent, WM_LBTRACKPOINT, y, lParam) )
|
|
return 0;
|
|
|
|
|
|
switch( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )
|
|
{
|
|
case LBS_MULTIPLESEL:
|
|
lphl->ItemFocused = y;
|
|
wRet = ListBoxGetSel(lphl, y);
|
|
ListBoxSetSel(lphl, y, !wRet);
|
|
break;
|
|
case LBS_EXTENDEDSEL:
|
|
/* should handle extended mode here and in kbd handler
|
|
*/
|
|
|
|
if ( lphl->PrevFocused != y && y!= LB_ERR)
|
|
{
|
|
LPLISTSTRUCT lpls = ListBoxGetItem( lphl, lphl->ItemFocused = y );
|
|
n = ListBoxSetSel(lphl,-1,FALSE);
|
|
|
|
lpls->itemState = ODS_FOCUS | ODS_SELECTED;
|
|
|
|
if( n > 1 && n != LB_ERR )
|
|
InvalidateRect32( hwnd,NULL,TRUE );
|
|
}
|
|
else
|
|
return 0;
|
|
|
|
break;
|
|
case 0:
|
|
if( y!=lphl->ItemFocused )
|
|
ListBoxSetCurSel(lphl, y);
|
|
else
|
|
return 0;
|
|
break;
|
|
default:
|
|
fprintf(stdnimp,"Listbox: LBS_MULTIPLESEL and LBS_EXTENDEDSEL are on!\n");
|
|
return 0;
|
|
}
|
|
|
|
/* invalidate changed items */
|
|
if( lphl->dwStyle & LBS_MULTIPLESEL || y!=lphl->PrevFocused )
|
|
{
|
|
ListBoxGetItemRect(lphl, y, &rectsel);
|
|
InvalidateRect16( hwnd, &rectsel, TRUE );
|
|
}
|
|
if( lphl->PrevFocused!=-1 && y!=lphl->PrevFocused )
|
|
{
|
|
ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
|
|
InvalidateRect16( hwnd, &rectsel, TRUE );
|
|
}
|
|
|
|
if (GetWindowLong32A(lphl->hSelf,GWL_EXSTYLE) & WS_EX_DRAGDETECT)
|
|
if( DragDetect(lphl->hSelf,MAKEPOINT16(lParam)) )
|
|
SendMessage16(lphl->hParent, WM_BEGINDRAG,0,0L);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBLButtonUp
|
|
*/
|
|
static LONG LBLButtonUp(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
|
|
if (GetCapture32() == hwnd) ReleaseCapture();
|
|
|
|
if (lphl->PrevFocused != lphl->ItemFocused)
|
|
ListBoxSendNotification(lphl, LBN_SELCHANGE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBRButtonUp
|
|
*/
|
|
static LONG LBRButtonUp(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
|
|
SendMessage16(lphl->hParent, WM_COMMAND, GetWindowWord(hwnd,GWW_ID),
|
|
MAKELONG(hwnd, LBN_DBLCLK));
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBMouseMove
|
|
*/
|
|
static LONG LBMouseMove(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
int y,redraw_prev = 0;
|
|
int iRet;
|
|
RECT16 rect, rectsel; /* XXX Broken */
|
|
|
|
dprintf_listbox(stddeb,"LBMouseMove %d %d\n",SLOWORD(lParam),SHIWORD(lParam));
|
|
if ((wParam & MK_LBUTTON) != 0) {
|
|
y = SHIWORD(lParam);
|
|
if (y < LBMM_EDGE) {
|
|
if (lphl->FirstVisible > 0) {
|
|
lphl->FirstVisible--;
|
|
SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
return 0;
|
|
}
|
|
}
|
|
GetClientRect16(hwnd, &rect);
|
|
if (y >= (rect.bottom-LBMM_EDGE)) {
|
|
if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
|
|
lphl->FirstVisible++;
|
|
SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
return 0;
|
|
}
|
|
}
|
|
if ((y > 0) && (y < (rect.bottom - LBMM_EDGE))) {
|
|
if ((y < rectsel.top) || (y > rectsel.bottom)) {
|
|
iRet = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
|
|
if (iRet == lphl->ItemFocused || iRet == -1) {
|
|
return 0;
|
|
}
|
|
if (lphl->dwStyle & LBS_MULTIPLESEL) {
|
|
lphl->ItemFocused = iRet;
|
|
ListBoxSendNotification(lphl, LBN_SELCHANGE);
|
|
} else if ( lphl->dwStyle & LBS_EXTENDEDSEL )
|
|
{
|
|
/* Fixme: extended selection mode */
|
|
ListBoxSetSel( lphl, lphl->ItemFocused, 0);
|
|
lphl->PrevFocused = lphl->ItemFocused;
|
|
lphl->ItemFocused = iRet;
|
|
ListBoxSetSel( lphl, iRet, TRUE);
|
|
redraw_prev = 1;
|
|
}
|
|
else
|
|
{
|
|
ListBoxSetCurSel(lphl, (WORD)iRet);
|
|
redraw_prev = 1;
|
|
}
|
|
if( lphl->PrevFocused!=-1 && redraw_prev )
|
|
{
|
|
ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
|
|
InvalidateRect16( hwnd, &rectsel, TRUE );
|
|
}
|
|
ListBoxGetItemRect(lphl, iRet, &rectsel);
|
|
InvalidateRect16( hwnd, &rectsel, TRUE );
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBKeyDown
|
|
*
|
|
* Doesn't yet handle properly VK_SHIFT with LB_EXTENDEDSEL
|
|
*/
|
|
static LONG LBKeyDown(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
WORD newFocused = 0xFFFF;
|
|
RECT16 rect;
|
|
|
|
ListBoxGetItemRect(lphl,lphl->ItemFocused,&rect);
|
|
switch(wParam)
|
|
{
|
|
case VK_HOME:
|
|
case VK_END:
|
|
case VK_LEFT:
|
|
case VK_RIGHT:
|
|
case VK_UP:
|
|
case VK_DOWN:
|
|
case VK_PRIOR:
|
|
case VK_NEXT:
|
|
if ( lphl->dwStyle & LBS_WANTKEYBOARDINPUT )
|
|
{
|
|
newFocused = (WORD)(INT)SendMessage16(lphl->hParent,WM_VKEYTOITEM,
|
|
wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
|
|
if ( newFocused == 0xFFFE ) return 0L;
|
|
}
|
|
if ( newFocused == 0xFFFF )
|
|
{
|
|
newFocused = lphl->ItemFocused;
|
|
|
|
/* nested switch */
|
|
switch(wParam)
|
|
{
|
|
case VK_HOME:
|
|
newFocused = 0;
|
|
break;
|
|
case VK_END:
|
|
newFocused = lphl->ItemsCount - 1;
|
|
break;
|
|
case VK_LEFT:
|
|
if (lphl->dwStyle & LBS_MULTICOLUMN) {
|
|
if (newFocused >= lphl->ItemsPerColumn) {
|
|
newFocused -= lphl->ItemsPerColumn;
|
|
} else {
|
|
newFocused = 0;
|
|
}
|
|
}
|
|
break;
|
|
case VK_UP:
|
|
if (newFocused > 0) newFocused--;
|
|
break;
|
|
case VK_RIGHT:
|
|
if (lphl->dwStyle & LBS_MULTICOLUMN)
|
|
newFocused += lphl->ItemsPerColumn;
|
|
break;
|
|
case VK_DOWN:
|
|
newFocused++;
|
|
break;
|
|
case VK_PRIOR:
|
|
if (newFocused > lphl->ItemsVisible)
|
|
newFocused -= lphl->ItemsVisible;
|
|
else newFocused = 0;
|
|
break;
|
|
case VK_NEXT:
|
|
newFocused += lphl->ItemsVisible;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
/* end of nested switch */
|
|
}
|
|
break;
|
|
case VK_SPACE:
|
|
if (lphl->dwStyle & LBS_MULTIPLESEL)
|
|
{
|
|
WORD wRet = ListBoxGetSel(lphl, lphl->ItemFocused);
|
|
ListBoxSetSel(lphl, lphl->ItemFocused, !wRet);
|
|
}
|
|
return 0;
|
|
|
|
/* chars are handled in LBChar */
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
/* at this point newFocused is set up */
|
|
|
|
if (newFocused >= lphl->ItemsCount)
|
|
newFocused = lphl->ItemsCount - 1;
|
|
|
|
if (!(lphl->dwStyle & LBS_MULTIPLESEL))
|
|
{
|
|
ListBoxSetCurSel(lphl, newFocused);
|
|
ListBoxSendNotification(lphl, LBN_SELCHANGE);
|
|
}
|
|
|
|
lphl->ItemFocused = newFocused;
|
|
|
|
if( ListBoxScrollToFocus(lphl) || (lphl->dwStyle &
|
|
(LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) )
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
else
|
|
{
|
|
InvalidateRect16( hwnd, &rect, TRUE );
|
|
if( newFocused < 0x8000 )
|
|
{
|
|
ListBoxGetItemRect(lphl, newFocused, &rect);
|
|
InvalidateRect16( hwnd, &rect, TRUE );
|
|
}
|
|
}
|
|
|
|
SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBChar
|
|
*/
|
|
static LONG LBChar(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
WORD newFocused = 0xFFFF;
|
|
|
|
if ( (lphl->dwStyle & LBS_WANTKEYBOARDINPUT) && !(lphl->HasStrings))
|
|
{
|
|
newFocused = (WORD)(INT)SendMessage16(lphl->hParent,WM_CHARTOITEM,
|
|
wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
|
|
if ( newFocused == 0xFFFE ) return 0L;
|
|
}
|
|
|
|
if (newFocused == 0xFFFF )
|
|
newFocused = ListBoxFindNextMatch(lphl, wParam);
|
|
|
|
if (newFocused == (WORD)LB_ERR) return 0;
|
|
|
|
if (newFocused >= lphl->ItemsCount)
|
|
newFocused = lphl->ItemsCount - 1;
|
|
|
|
if (!(lphl->dwStyle & LBS_MULTIPLESEL))
|
|
{
|
|
ListBoxSetCurSel(lphl, newFocused);
|
|
ListBoxSendNotification(lphl, LBN_SELCHANGE);
|
|
}
|
|
|
|
lphl->ItemFocused = newFocused;
|
|
ListBoxScrollToFocus(lphl);
|
|
SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
|
|
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBSetRedraw
|
|
*/
|
|
static LONG LBSetRedraw(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
|
|
dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd=%04x w=%04x !\n",
|
|
hwnd, wParam);
|
|
lphl->bRedrawFlag = wParam;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBSetFont
|
|
*/
|
|
static LONG LBSetFont(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
HDC32 hdc;
|
|
|
|
if (wParam == 0)
|
|
lphl->hFont = GetStockObject32(SYSTEM_FONT);
|
|
else
|
|
lphl->hFont = (HFONT16)wParam;
|
|
|
|
/* a new font means possible new text height */
|
|
/* does this mean the height of each entry must be separately changed? */
|
|
/* or are we guaranteed to get a LBSetFont before the first insert/add? */
|
|
if ((hdc = GetDC32(0)))
|
|
{
|
|
TEXTMETRIC16 tm;
|
|
GetTextMetrics16( hdc, &tm );
|
|
lphl->StdItemHeight = tm.tmHeight;
|
|
dprintf_listbox(stddeb,"LBSetFont: new font %d with height %d\n",
|
|
lphl->hFont, lphl->StdItemHeight);
|
|
ReleaseDC32( 0, hdc );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBPaint
|
|
*/
|
|
static LONG LBPaint(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
LPLISTSTRUCT lpls;
|
|
PAINTSTRUCT16 ps;
|
|
HBRUSH16 hBrush;
|
|
HFONT32 hOldFont;
|
|
HDC16 hdc = BeginPaint16( hwnd, &ps );
|
|
DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
|
|
RECT16 rect, paintRect, scratchRect;
|
|
int i, top, height, maxwidth, ipc;
|
|
|
|
top = 0;
|
|
|
|
if (!IsWindowVisible(hwnd) || !lphl->bRedrawFlag) {
|
|
EndPaint16(hwnd, &ps);
|
|
return 0;
|
|
}
|
|
|
|
GetRgnBox16(dc->w.hGCClipRgn,&paintRect);
|
|
GetClientRect16(hwnd, &rect);
|
|
IntersectRect16(&paintRect,&rect,&paintRect);
|
|
|
|
hOldFont = SelectObject32(hdc, lphl->hFont);
|
|
|
|
hBrush = (HBRUSH16)SendMessage32A( lphl->hParent, WM_CTLCOLORLISTBOX,
|
|
(WPARAM32)hdc, (LPARAM)hwnd);
|
|
if (hBrush == 0) hBrush = GetStockObject32(WHITE_BRUSH);
|
|
|
|
FillRect16(hdc, &rect, hBrush);
|
|
|
|
maxwidth = rect.right;
|
|
if (lphl->dwStyle & LBS_MULTICOLUMN) {
|
|
rect.right = lphl->ColumnsWidth;
|
|
}
|
|
lpls = lphl->lpFirst;
|
|
|
|
lphl->ItemsVisible = 0;
|
|
lphl->ItemsPerColumn = ipc = 0;
|
|
|
|
for(i = 0; i < lphl->ItemsCount; i++) {
|
|
if (lpls == NULL) break;
|
|
|
|
if (i >= lphl->FirstVisible) {
|
|
height = lpls->mis.itemHeight;
|
|
|
|
if (top > (rect.bottom-height+1)) {
|
|
if (lphl->dwStyle & 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->itemRect.top = top;
|
|
lpls->itemRect.bottom = top + height;
|
|
lpls->itemRect.left = rect.left;
|
|
lpls->itemRect.right = rect.right;
|
|
|
|
if( IntersectRect16(&scratchRect,&paintRect,&lpls->itemRect) )
|
|
{
|
|
dprintf_listbox(stddeb,"LBPaint: drawing item: %d %d %d %d %d\n",
|
|
rect.left,top,rect.right,top+height,lpls->itemState);
|
|
|
|
if (lphl->OwnerDrawn && (lphl->ItemFocused == i) && GetFocus32() == hwnd)
|
|
{
|
|
ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS,
|
|
lpls->itemState & ~ODS_FOCUS);
|
|
ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
|
|
lpls->itemState & ~ODS_FOCUS);
|
|
ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS, lpls->itemState);
|
|
}
|
|
else
|
|
ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
|
|
lpls->itemState);
|
|
}
|
|
|
|
top += height;
|
|
lphl->ItemsVisible++;
|
|
ipc++;
|
|
}
|
|
|
|
lpls = lpls->lpNext;
|
|
}
|
|
ListBoxUpdateWindow(hwnd,lphl,FALSE);
|
|
SelectObject32(hdc,hOldFont);
|
|
EndPaint16( hwnd, &ps );
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBSetFocus
|
|
*/
|
|
static LONG LBSetFocus(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
|
|
dprintf_listbox(stddeb,"ListBox WM_SETFOCUS for %04x\n",hwnd);
|
|
if(!(lphl->dwStyle & LBS_MULTIPLESEL) )
|
|
if( lphl->ItemsCount && lphl->ItemFocused != -1)
|
|
{
|
|
HDC32 hDC = GetDC32(hwnd);
|
|
HFONT32 hOldFont = SelectObject32(hDC, lphl->hFont);
|
|
LPLISTSTRUCT lpls;
|
|
|
|
lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
|
|
lpls->itemState |= ODS_FOCUS;
|
|
|
|
ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
|
|
SelectObject32(hDC, hOldFont);
|
|
ReleaseDC32(hwnd,hDC);
|
|
}
|
|
|
|
ListBoxSendNotification(lphl, LBN_SETFOCUS);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBKillFocus
|
|
*/
|
|
static LONG LBKillFocus(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
|
|
dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS for %04x\n",hwnd);
|
|
if (!(lphl->dwStyle & LBS_MULTIPLESEL))
|
|
{
|
|
if( lphl->ItemsCount )
|
|
if( lphl->ItemFocused != -1 )
|
|
{
|
|
HDC32 hDC = GetDC32(hwnd);
|
|
HFONT32 hOldFont = SelectObject32(hDC, lphl->hFont);
|
|
LPLISTSTRUCT lpls;
|
|
|
|
lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
|
|
lpls->itemState &= ~ODS_FOCUS;
|
|
|
|
ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
|
|
SelectObject32(hDC, hOldFont);
|
|
ReleaseDC32(hwnd,hDC);
|
|
}
|
|
else
|
|
dprintf_listbox(stddeb,"LBKillFocus: no focused item!\n");
|
|
}
|
|
else
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
|
|
ListBoxSendNotification(lphl, LBN_KILLFOCUS);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBResetContent
|
|
*/
|
|
static LONG LBResetContent(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
|
|
dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
|
|
ListBoxResetContent(lphl);
|
|
ListBoxUpdateWindow(hwnd, lphl, TRUE);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBDir
|
|
*/
|
|
static LONG LBDir(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LONG ret;
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
|
|
|
|
ret = ListBoxDirectory(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
|
|
ListBoxUpdateWindow(hwnd, lphl, TRUE);
|
|
return ret;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBAddString
|
|
*/
|
|
static LONG LBAddString(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
WORD wRet;
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
|
|
wRet = ListBoxAddString(lphl, (SEGPTR)lParam);
|
|
|
|
ListBoxUpdateWindow(hwnd,lphl,TRUE);
|
|
return wRet;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBGetText
|
|
*/
|
|
static LONG LBGetText(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LONG wRet;
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
|
|
dprintf_listbox(stddeb, "LB_GETTEXT wParam=%d\n",wParam);
|
|
wRet = ListBoxGetText(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
|
|
|
|
return wRet;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBInsertString
|
|
*/
|
|
static LONG LBInsertString(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
WORD wRet;
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
|
|
if (lphl->HasStrings)
|
|
wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)PTR_SEG_TO_LIN(lParam));
|
|
else
|
|
wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)lParam);
|
|
|
|
ListBoxUpdateWindow(hwnd,lphl,TRUE);
|
|
return wRet;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBDeleteString
|
|
*/
|
|
static LONG LBDeleteString(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
LONG lRet = ListBoxDeleteString(lphl,wParam);
|
|
|
|
ListBoxUpdateWindow(hwnd,lphl,TRUE);
|
|
return lRet;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBFindString
|
|
*/
|
|
static LONG LBFindString(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
return lbFindString(lphl, wParam, (SEGPTR)lParam, MATCH_SUBSTR);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBFindStringExact
|
|
*/
|
|
static LONG LBFindStringExact(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
return lbFindString(lphl, wParam, (SEGPTR)lParam, MATCH_EXACT);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBGetCaretIndex
|
|
*/
|
|
static LONG LBGetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
return lphl->ItemFocused;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBGetCount
|
|
*/
|
|
static LONG LBGetCount(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl;
|
|
|
|
lphl = ListBoxGetStorageHeader(hwnd);
|
|
return lphl->ItemsCount;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBGetCurSel
|
|
*/
|
|
static LONG LBGetCurSel(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl;
|
|
|
|
lphl = ListBoxGetStorageHeader(hwnd);
|
|
dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %i !\n",
|
|
lphl->ItemFocused);
|
|
return lphl->ItemFocused;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBGetHorizontalExtent
|
|
*/
|
|
static LONG LBGetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBGetItemHeight
|
|
*/
|
|
static LONG LBGetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
LPLISTSTRUCT lpls = ListBoxGetItem (lphl, wParam);
|
|
|
|
if (lpls == NULL) return LB_ERR;
|
|
return lpls->mis.itemHeight;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBGetItemRect
|
|
*/
|
|
static LONG LBGetItemRect(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
return ListBoxGetItemRect(lphl, wParam, PTR_SEG_TO_LIN(lParam));
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBGetSel
|
|
*/
|
|
static LONG LBGetSel(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
int iSel = ListBoxGetSel(lphl, wParam);
|
|
|
|
dprintf_listbox(stdnimp,"LBGetSel: item %u - %i\n",wParam,iSel);
|
|
|
|
return (iSel)? 1 : 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBGetSelCount
|
|
*/
|
|
static LONG LBGetSelCount(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
LPLISTSTRUCT lpls;
|
|
int cnt = 0;
|
|
int items = 0;
|
|
|
|
if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
|
|
return LB_ERR;
|
|
|
|
for( lpls = lphl->lpFirst;
|
|
lpls;
|
|
lpls = lpls->lpNext )
|
|
{
|
|
items++;
|
|
if (lpls->itemState )
|
|
cnt++;
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBGetSelItems
|
|
*/
|
|
static LONG LBGetSelItems(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
LPLISTSTRUCT lpls;
|
|
int cnt, idx;
|
|
int *lpItems = PTR_SEG_TO_LIN(lParam);
|
|
|
|
if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
|
|
return LB_ERR;
|
|
|
|
if (wParam == 0) return 0;
|
|
|
|
lpls = lphl->lpFirst;
|
|
cnt = 0; idx = 0;
|
|
|
|
while (lpls != NULL) {
|
|
if (lpls->itemState > 0) lpItems[cnt++] = idx;
|
|
|
|
if (cnt == wParam) break;
|
|
idx++;
|
|
lpls = lpls->lpNext;
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBGetTextLen
|
|
*/
|
|
static LONG LBGetTextLen(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wParam);
|
|
|
|
if (lpls == NULL || !lphl->HasStrings) return LB_ERR;
|
|
return strlen(lpls->itemText);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBGetDlgCode
|
|
*/
|
|
static LONG LBGetDlgCode(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
return DLGC_WANTARROWS | DLGC_WANTCHARS;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBGetTopIndex
|
|
*/
|
|
static LONG LBGetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
|
|
return lphl->FirstVisible;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* LBSelectString
|
|
*/
|
|
static LONG LBSelectString(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
INT iRet;
|
|
|
|
iRet = lbFindString(lphl, wParam, (SEGPTR)lParam, MATCH_SUBSTR);
|
|
|
|
if( iRet != LB_ERR)
|
|
{
|
|
if( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )
|
|
ListBoxSetSel(lphl,iRet,TRUE);
|
|
else
|
|
ListBoxSetCurSel(lphl,iRet);
|
|
|
|
lphl->ItemFocused = iRet;
|
|
InvalidateRect32( hwnd, 0, TRUE );
|
|
}
|
|
return iRet;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBSelItemRange
|
|
*/
|
|
static LONG LBSelItemRange(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
LPLISTSTRUCT lpls;
|
|
WORD cnt;
|
|
WORD first = LOWORD(lParam);
|
|
WORD last = HIWORD(lParam);
|
|
BOOL select = wParam;
|
|
|
|
if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
|
|
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->itemState = select ? lpls->itemState | ODS_SELECTED : 0;
|
|
|
|
if (cnt > last)
|
|
break;
|
|
|
|
lpls = lpls->lpNext;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBSetCaretIndex
|
|
*/
|
|
static LONG LBSetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
int i;
|
|
|
|
if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )) return 0;
|
|
|
|
dprintf_listbox(stddeb,"LBSetCaretIndex: hwnd %04x n=%i\n",hwnd,wParam);
|
|
|
|
if (wParam >= lphl->ItemsCount) return LB_ERR;
|
|
|
|
lphl->ItemFocused = wParam;
|
|
i = ListBoxScrollToFocus (lphl);
|
|
|
|
SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
|
|
if(i)
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
|
|
return 1;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBSetColumnWidth
|
|
*/
|
|
static LONG LBSetColumnWidth(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
lphl->ColumnsWidth = wParam;
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBSetHorizontalExtent
|
|
*/
|
|
static LONG LBSetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBGetItemData
|
|
*/
|
|
static LONG LBGetItemData(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
|
|
return ListBoxGetItemData(lphl, wParam);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBSetItemData
|
|
*/
|
|
static LONG LBSetItemData(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
dprintf_listbox(stddeb, "LB_SETITEMDATA wParam=%x lParam=%lx\n", wParam, lParam);
|
|
return ListBoxSetItemData(lphl, wParam, lParam);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBSetTabStops
|
|
*/
|
|
static LONG LBSetTabStops(HWND hwnd, 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
|
|
*/
|
|
static LONG LBSetCurSel(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
WORD wRet;
|
|
|
|
dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n",
|
|
wParam);
|
|
|
|
wRet = ListBoxSetCurSel(lphl, wParam);
|
|
|
|
SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
|
|
return wRet;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBSetSel
|
|
*/
|
|
static LONG LBSetSel(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
RECT16 rect;
|
|
int iRet;
|
|
|
|
dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
|
|
|
|
iRet = ListBoxSetSel(lphl, LOWORD(lParam), wParam);
|
|
|
|
if( iRet > 1 ) InvalidateRect32( hwnd, NULL, TRUE );
|
|
else if( iRet != LB_ERR )
|
|
{
|
|
if( lphl->dwStyle & LBS_EXTENDEDSEL &&
|
|
lphl->ItemFocused != LOWORD(lParam) )
|
|
{
|
|
ListBoxGetItemRect(lphl, lphl->ItemFocused , &rect);
|
|
InvalidateRect16( hwnd, &rect, TRUE );
|
|
lphl->ItemFocused = LOWORD(lParam);
|
|
}
|
|
ListBoxGetItemRect(lphl,LOWORD(lParam),&rect);
|
|
InvalidateRect16( hwnd, &rect, TRUE );
|
|
}
|
|
|
|
return (iRet == (WORD)LB_ERR)? LB_ERR: 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBSetTopIndex
|
|
*/
|
|
static LONG LBSetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
|
|
dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
|
|
wParam);
|
|
lphl->FirstVisible = wParam;
|
|
SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
|
|
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBSetItemHeight
|
|
*/
|
|
static LONG LBSetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
WORD wRet;
|
|
|
|
dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
|
|
wRet = ListBoxSetItemHeight(lphl, wParam, lParam);
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
return wRet;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LBPassToParent
|
|
*/
|
|
static LRESULT LBPassToParent(HWND hwnd, UINT message, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
WND* ptrWnd = WIN_FindWndPtr(hwnd);
|
|
|
|
if( ptrWnd )
|
|
if( /* !(ptrWnd->dwExStyle & WS_EX_NOPARENTNOTIFY) && */
|
|
ptrWnd->parent )
|
|
return SendMessage16(ptrWnd->parent->hwndSelf,message,wParam,lParam);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ListBoxWndProc
|
|
*/
|
|
LRESULT ListBoxWndProc(HWND hwnd, UINT message, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
switch (message) {
|
|
case WM_CREATE: return LBCreate(hwnd, wParam, lParam);
|
|
case WM_DESTROY: return LBDestroy(hwnd, wParam, lParam);
|
|
case WM_GETDLGCODE: return LBGetDlgCode(hwnd, wParam, lParam);
|
|
case WM_VSCROLL: return LBVScroll(hwnd, wParam, lParam);
|
|
case WM_HSCROLL: return LBHScroll(hwnd, wParam, lParam);
|
|
case WM_LBUTTONDOWN: return LBLButtonDown(hwnd, wParam, lParam);
|
|
case WM_LBUTTONUP: return LBLButtonUp(hwnd, wParam, lParam);
|
|
case WM_RBUTTONUP: return LBRButtonUp(hwnd, wParam, lParam);
|
|
case WM_LBUTTONDBLCLK: return LBRButtonUp(hwnd, wParam, lParam);
|
|
case WM_MOUSEMOVE: return LBMouseMove(hwnd, wParam, lParam);
|
|
case WM_KEYDOWN: return LBKeyDown(hwnd, wParam, lParam);
|
|
case WM_CHAR: return LBChar(hwnd, wParam, lParam);
|
|
case WM_SETFONT: return LBSetFont(hwnd, wParam, lParam);
|
|
case WM_SETREDRAW: return LBSetRedraw(hwnd, wParam, lParam);
|
|
case WM_PAINT: return LBPaint(hwnd, wParam, lParam);
|
|
case WM_SETFOCUS: return LBSetFocus(hwnd, wParam, lParam);
|
|
case WM_KILLFOCUS: return LBKillFocus(hwnd, wParam, lParam);
|
|
case WM_NCCALCSIZE: return LBNCCalcSize(hwnd, wParam, lParam);
|
|
case LB_RESETCONTENT16: return LBResetContent(hwnd, wParam, lParam);
|
|
case LB_DIR16: return LBDir(hwnd, wParam, lParam);
|
|
case LB_ADDSTRING16: return LBAddString(hwnd, wParam, lParam);
|
|
case LB_INSERTSTRING16: return LBInsertString(hwnd, wParam, lParam);
|
|
case LB_DELETESTRING16: return LBDeleteString(hwnd, wParam, lParam);
|
|
case LB_FINDSTRING16: return LBFindString(hwnd, wParam, lParam);
|
|
case LB_FINDSTRINGEXACT16: return LBFindStringExact(hwnd, wParam, lParam);
|
|
case LB_GETCARETINDEX16: return LBGetCaretIndex(hwnd, wParam, lParam);
|
|
case LB_GETCOUNT16: return LBGetCount(hwnd, wParam, lParam);
|
|
case LB_GETCURSEL16: return LBGetCurSel(hwnd, wParam, lParam);
|
|
case LB_GETHORIZONTALEXTENT16: return LBGetHorizontalExtent(hwnd, wParam, lParam);
|
|
case LB_GETITEMDATA16: return LBGetItemData(hwnd, wParam, lParam);
|
|
case LB_GETITEMHEIGHT16: return LBGetItemHeight(hwnd, wParam, lParam);
|
|
case LB_GETITEMRECT16: return LBGetItemRect(hwnd, wParam, lParam);
|
|
case LB_GETSEL16: return LBGetSel(hwnd, wParam, lParam);
|
|
case LB_GETSELCOUNT16: return LBGetSelCount(hwnd, wParam, lParam);
|
|
case LB_GETSELITEMS16: return LBGetSelItems(hwnd, wParam, lParam);
|
|
case LB_GETTEXT16: return LBGetText(hwnd, wParam, lParam);
|
|
case LB_GETTEXTLEN16: return LBGetTextLen(hwnd, wParam, lParam);
|
|
case LB_GETTOPINDEX16: return LBGetTopIndex(hwnd, wParam, lParam);
|
|
case LB_SELECTSTRING16: return LBSelectString(hwnd, wParam, lParam);
|
|
case LB_SELITEMRANGE16: return LBSelItemRange(hwnd, wParam, lParam);
|
|
case LB_SETCARETINDEX16: return LBSetCaretIndex(hwnd, wParam, lParam);
|
|
case LB_SETCOLUMNWIDTH16: return LBSetColumnWidth(hwnd, wParam, lParam);
|
|
case LB_SETHORIZONTALEXTENT16: return LBSetHorizontalExtent(hwnd, wParam, lParam);
|
|
case LB_SETITEMDATA16: return LBSetItemData(hwnd, wParam, lParam);
|
|
case LB_SETTABSTOPS16: return LBSetTabStops(hwnd, wParam, lParam);
|
|
case LB_SETCURSEL16: return LBSetCurSel(hwnd, wParam, lParam);
|
|
case LB_SETSEL16: return LBSetSel(hwnd, wParam, lParam);
|
|
case LB_SETTOPINDEX16: return LBSetTopIndex(hwnd, wParam, lParam);
|
|
case LB_SETITEMHEIGHT16: return LBSetItemHeight(hwnd, wParam, lParam);
|
|
|
|
case WM_DROPFILES: return LBPassToParent(hwnd, message, wParam, lParam);
|
|
|
|
/* these will have to be implemented for proper LBS_EXTENDEDSEL -
|
|
*
|
|
* anchor item is an item that with caret (focused) item defines a
|
|
* range of currently selected items when listbox is in the extended
|
|
* selection mode.
|
|
*/
|
|
case LB_SETANCHORINDEX16: return LB_SETANCHORINDEX16; /* that's what Windows returns */
|
|
case LB_GETANCHORINDEX16: return 0;
|
|
|
|
case WM_DROPOBJECT:
|
|
case WM_QUERYDROPOBJECT:
|
|
case WM_DRAGSELECT:
|
|
case WM_DRAGMOVE:
|
|
{
|
|
LPDRAGINFO lpDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN((SEGPTR)lParam);
|
|
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
|
|
|
|
lpDragInfo->l = ListBoxFindMouse(lphl,lpDragInfo->pt.x,
|
|
lpDragInfo->pt.y);
|
|
|
|
return LBPassToParent(hwnd, message, wParam, lParam);
|
|
}
|
|
}
|
|
|
|
return DefWindowProc16(hwnd, message, wParam, lParam);
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* DlgDirList (USER.100)
|
|
*/
|
|
INT DlgDirList( HWND hDlg, SEGPTR spec, INT idLBox, INT idStatic, UINT attrib )
|
|
{
|
|
char *filespec = (char *)PTR_SEG_TO_LIN( spec );
|
|
int drive;
|
|
HWND hwnd;
|
|
|
|
#define SENDMSG(msg,wparam,lparam) \
|
|
((attrib & DDL_POSTMSGS) ? PostMessage( hwnd, msg, wparam, lparam ) \
|
|
: SendMessage16( hwnd, msg, wparam, lparam ))
|
|
|
|
dprintf_listbox( stddeb, "DlgDirList: %04x '%s' %d %d %04x\n",
|
|
hDlg, filespec ? filespec : "NULL",
|
|
idLBox, idStatic, attrib );
|
|
|
|
if (filespec && filespec[0] && (filespec[1] == ':'))
|
|
{
|
|
drive = toupper( filespec[0] ) - 'A';
|
|
filespec += 2;
|
|
if (!DRIVE_SetCurrentDrive( drive )) return FALSE;
|
|
}
|
|
else drive = DRIVE_GetCurrentDrive();
|
|
|
|
if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
|
|
{
|
|
char mask[20];
|
|
|
|
if (!filespec || !filespec[0]) strcpy( mask, "*.*" );
|
|
else
|
|
{
|
|
/* If the path exists and is a directory, chdir to it */
|
|
if (DRIVE_Chdir( drive, filespec )) strcpy( mask, "*.*" );
|
|
else
|
|
{
|
|
char *p, *p2;
|
|
p = filespec;
|
|
if ((p2 = strrchr( p, '\\' ))) p = p2 + 1;
|
|
if ((p2 = strrchr( p, '/' ))) p = p2 + 1;
|
|
lstrcpyn32A( mask, p, sizeof(mask) );
|
|
if (p != filespec)
|
|
{
|
|
p[-1] = '\0';
|
|
if (!DRIVE_Chdir( drive, filespec )) return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
strcpy( (char *)PTR_SEG_TO_LIN(spec), mask );
|
|
|
|
dprintf_listbox(stddeb, "ListBoxDirectory: path=%c:\\%s mask=%s\n",
|
|
'A' + drive, DRIVE_GetDosCwd(drive), mask);
|
|
|
|
SENDMSG( LB_RESETCONTENT16, 0, 0 );
|
|
if ((attrib & DDL_DIRECTORY) && !(attrib & DDL_EXCLUSIVE))
|
|
{
|
|
char *temp;
|
|
if (SENDMSG( LB_DIR16, attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
|
|
(LPARAM)spec ) == LB_ERR) return FALSE;
|
|
if (!(temp = SEGPTR_ALLOC( 4*sizeof(char) ))) return FALSE;
|
|
strcpy( temp, "*.*" );
|
|
/* FIXME: this won't work with PostMessage(), as temp will */
|
|
/* have been freed by the time we do a DispatchMessage(). */
|
|
if (SENDMSG( LB_DIR16, (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
|
|
(LPARAM)SEGPTR_GET(temp) ) == LB_ERR)
|
|
{
|
|
SEGPTR_FREE(temp);
|
|
return FALSE;
|
|
}
|
|
SEGPTR_FREE(temp);
|
|
}
|
|
else
|
|
{
|
|
if (SENDMSG( LB_DIR16, attrib, (LPARAM)spec) == LB_ERR) return FALSE;
|
|
}
|
|
}
|
|
|
|
if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
|
|
{
|
|
char temp[512];
|
|
int drive = DRIVE_GetCurrentDrive();
|
|
strcpy( temp, "A:\\" );
|
|
temp[0] += drive;
|
|
lstrcpyn32A( temp + 3, DRIVE_GetDosCwd(drive), sizeof(temp)-3 );
|
|
AnsiLower( temp );
|
|
/* Can't use PostMessage() here, because the string is on the stack */
|
|
SetDlgItemText32A( hDlg, idStatic, temp );
|
|
}
|
|
return TRUE;
|
|
#undef SENDMSG
|
|
}
|