Release 951124
Tue Nov 21 18:49:10 1995 Alexandre Julliard <julliard@sunsite.unc.edu>
* [configure.in] [Makefile] [misc/dos_fs.c]
Got rid of autoconf.h file.
* [debugger/dbg.y]
More logical behavior upon syntax errors.
* [include/hook.h] [windows/hook.c]
Changed hook structure and rewrote most of the hook functions for
better compatibility, based on investigations by Alex Korobka.
* [include/message.h] [windows/message.c]
Added hooks to message queue structure and made the structure
layout Windows-compatible.
Added support for WH_MOUSE, WH_KEYBOARD, WH_HARDWARE and
WH_JOURNALRECORD hooks.
* [misc/main.c]
Added command-line option for changing the language at run-time
(not implemented yet), based on a suggestion from Michael Patra.
* [objects/cursoricon.c]
Fixed silly SEGPTR bug in DumpIcon().
Mon Nov 20 22:22:22 1995 Alex Korobka <alex@phm30.pharm.sunysb.edu>
* [controls/listbox.c] [controls/combo.c] [include/listbox.h]
Partial implementaion of LBS_EXTENDEDSEL style,
yet more updates for drag & drop support. Now works.
* [windows/defwnd.c]
More message handlers.
* [windows/win.c]
DragObject, DragDetect, AnyPopup functions.
* [controls/listbox.c]
More kludgy fixes (WM_...TOITEM, etc.).
* [objects/cursoricon.c] [objects/oembitmap.c]
IconToCursor skeleton, patch for OBM_LoadCursorIcon to handle new
cursor.
* [include/bitmaps/ocr*]
New OEM cursors.
Mon Nov 20 11:05:20 EST 1995 Jim Peterson <jspeter@birch.ee.vt.edu>
* [toolkit/heap.c]
Swapped flags and size arguments to LocalRealloc as per changes in
memory/local.c by William Magro in previous release.
* [include/wintypes.h]
Reinstated the #define's for 'min' and 'max', since they're part of
the Windows API. I really don't think it's a wise idea, so I put
a '#ifndef DONT_DEFINE_min_AND_max' around them. I think the actual
WINE code should never use these (it should use 'MIN' and 'MAX'
instead).
* [loader/*]
Put '#ifndef WINELIB' around many things that WINElib should not need.
* [controls/edit.c]
Took out many '#if defined(WINELIB)' sections with the associated
comment 'temporary fix, until Local memory is correctly implemented in
WINELIB', since the effective translations are now in
toolkit/miscstubs.c.
Took out the #ifndef's I put in EDIT_ClearText. Whoever modified this
file fixed (or at least postponed) the bug I had encountered.
* [loader/task.c]
Put an #ifdef in TASK_CreateTask() that hardwires the current drive to
C: This will probably cause a lot of trouble if this change is
forgotten in the future, but it will let things like the OpenFileName
dialog work for now.
* [toolkit/libres.c] [toolkit/Makefile.in] [toolkit/Makefile]
[include/libres.h]
Made new libres.c file, which will contain functions for supporting
accessing resources by name in WINElib. 'winerc' will need to be
changed.
* [toolkit/heap.c]
Refined memory routines to allow for differences between LocalAlloc
and GlobalAlloc and between LocalSize and GlobalSize.
* [windows/message.c] [include/windows.h]
Defined the GetCurrentTime routine in windows/message.c, and removed
the #define in windows.h.
Mon Nov 20 00:36:42 MET 1995 Sven Verdoolaege <skimo@dns.ufsia.ac.be>
* [*/*]
Added new debugging type DEBUG_WIN32 and DEBUG_ENV.
* [loader/module.c]
Added undocumented GetExpWinVer.
* [tools/build.c]
Previous code didn't pop possibly changed %esi, %edi and %edx
from the stack.
* [win32/advapi.c]
Added GetUserNameA.
* [win32/code_page.c]
Added stub for MultiByteToWideChar.
* [win32/console.c]
Added SetConsoleCtrlHandler stub.
* [win32/file.c]
Added ReadFile CreateFileA GetFileInformationByHandle stubs.
Added CloseHandle.
* [win32/memory.c]
Changed VirtualAlloc and VirtualFree.
* [win32/process.c]
Added ExitProcess.
Sun Nov 19 17:54:42 1995 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
* [include/windows.h]
Fixed a few broken structure definitions.
* [loader/resource.c]
FindResource(): Need to check for '#xxx' strings here.
* [miscemu/int21.c]
FindNext(): Return MS-DOS filenames uppercase.
* [objects/cursoricon.c]
CreateIcon(), CreateCursor(): Added missing element to CURSORICONINFO
initializers.
* [misc/file.c]
_lopen(): Files opened in OF_WRITE mode are truncated.
OpenFile(): Ignore OF_READ/OF_WRITE/OF_READWRITE when files are
created; use read/write mode.
* [misc/profile.c]
load(): Rewritten.
* [misc/commdlg.c]
Fixed bad call to strncpy() that smashed the stack.
* [controls/combo.c] [windows/winpos.c] [memory/selector.c]
Operator precedence fixes. People who use gcc 2.7.1 don't need a
debugger :-)
* [if1632/gdi.spec] [objects/palette.c]
Add ResizePalette() and AnimatePalette() stubs. They don't do anything,
but sometimes that's good enough.
Fri Nov 17 09:10:35 GMT 1995 John Harvey <john@division.co.uk>
* [include/wine.h] [include/registers.h] [include/winsock.h]
Added definitions for Unixware.
* [loader/signal.c] [misc/comm.c] [misc/winsocket.c]
Misc. fixes for Unixware.
* [loader/task.c]
Made assignemts to context in InitTask for registers use the macros
from registers.h to make them more portable. (Needed for Unixware)
* [tools/build.c]
Fixed register acces routines to work on Unixware. Bit grubby but
it seems to work.
* [controls/edit.c]
EDIT_WM_NCCreate allocates local heap if hasn't been previously
allocated.
* [miscemu/int21.c]
mkdir now creates directory with permission to access it.
* [misc/dos_fs.c]
mkdir now creates directory with permission to access it.
DOS_opendir now uses linked list of dirents to avoid problems with
realloc changing address of malloced memory.
Thu Nov 16 12:47:13 1995 Michael Patra <patra@itp1.Physik.TU-Berlin.DE>
* [controls/menu.c]
MENU_CalcItemSize(): Fixed handling of empty menu items.
Sat Nov 11 21:46:54 1995 Hans de Graaff <graaff@twi72.twi.tudelft.nl>
* [misc/file.c]
In OpenFile, unlink should be done on the unix filename.
Sat Nov 11 16:43:29 1995 Cameron Heide (heide@ee.ualberta.ca)
* [include/handle32.h]
New header file containing internal Win32 kernel handle
information.
* [win32/file.c]
Added ReadFile, CreateFile, and CloseFileHandle, and did
some reorganizing to match the new handle allocation scheme.
* [win32/init.c]
Added CloseHandle and the creation of standard I/O handles.
* [win32/object_mgt.c]
New module for allocating and freeing Win32 kernel handles.
diff --git a/controls/listbox.c b/controls/listbox.c
index d06760d..a215ec3 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -2,14 +2,16 @@
* Listbox controls
*
* Copyright Martin Ayotte, 1993
- * Copyright Constantine Sapuntzakis, 1995
+ * Constantine Sapuntzakis, 1995
+ * Alex Korobka, 1995
*
*/
/*
- * TODO:
+ * FIXME:
* - check if multi-column listboxes work
- * - implement more messages and styles
+ * - implement more messages and styles (LB_EXTENDEDSEL for instance)
+ * - exterminate evil InvalidateRect(whole listbox) where possible!!!!
*/
#include <stdio.h>
@@ -33,10 +35,26 @@
((void *)((handle) ? ((handle) | ((int)lphl->Heap & 0xffff0000)) : 0))
#else
/* FIXME: shouldn't each listbox have its own heap? */
+#if 0
#define LIST_HEAP_ALLOC(lphl,f,size) USER_HEAP_ALLOC(size)
#define LIST_HEAP_FREE(lphl,handle) USER_HEAP_FREE(handle)
#define LIST_HEAP_ADDR(lphl,handle) USER_HEAP_LIN_ADDR(handle)
#define LIST_HEAP_SEG_ADDR(lphl,handle) USER_HEAP_SEG_ADDR(handle)
+#else
+/* Something like this maybe ? */
+#define LIST_HEAP_ALLOC(lphl,f,size) \
+ LOCAL_Alloc( lphl->HeapSel, LMEM_FIXED, (size) )
+#if 0
+#define LIST_HEAP_REALLOC(handle,size) \
+ LOCAL_ReAlloc( USER_HeapSel, (handle), (size), LMEM_FIXED )
+#endif
+#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_SEG_ADDR(lphl,handle) \
+ ((handle) ? MAKELONG((handle), lphl->HeapSel) : 0)
+#endif
#endif
#define LIST_HEAP_SIZE 0x10000
@@ -66,9 +84,9 @@
lphl->iNumStops = 0;
lphl->TabStops = NULL;
lphl->hFont = GetStockObject(SYSTEM_FONT);
+ lphl->hSelf = hwnd;
lphl->hParent = parent;
lphl->StdItemHeight = 15; /* FIXME: should get the font height */
- lphl->dwStyle = styles;
lphl->OwnerDrawn = styles & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE);
lphl->HasStrings = (styles & LBS_HASSTRINGS) || !lphl->OwnerDrawn;
@@ -93,6 +111,8 @@
HeapBase = GlobalLock(HeapHandle);
HEAP_Init(&lphl->Heap, HeapBase, LIST_HEAP_SIZE);
#endif
+ lphl->HeapSel = GlobalAlloc(GMEM_FIXED,LIST_HEAP_SIZE);
+ LocalInit( lphl->HeapSel, 0, LIST_HEAP_SIZE-1);
}
void DestroyListBoxStruct(LPHEADLIST lphl)
@@ -101,6 +121,7 @@
USER_HEAP_FREE(lphl->hDrawItemStruct);
/* XXX need to free lphl->Heap */
+ GlobalFree(lphl->HeapSel);
free(lphl);
}
@@ -111,15 +132,17 @@
/* Send notification "code" as part of a WM_COMMAND-message if hwnd
has the LBS_NOTIFY style */
-void ListBoxSendNotification(LPHEADLIST lphl, HWND hwnd, WORD code)
+void ListBoxSendNotification(LPHEADLIST lphl, WORD code)
{
- if (lphl->dwStyle & LBS_NOTIFY)
+ DWORD dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
+
+ if (dwStyle & LBS_NOTIFY)
#ifdef WINELIB32
SendMessage(lphl->hParent, WM_COMMAND,
- MAKEWPARAM(lphl->CtlID,code), (LPARAM)hwnd);
+ MAKEWPARAM(lphl->CtlID,code), (LPARAM)lphl->hSelf);
#else
SendMessage(lphl->hParent, WM_COMMAND,
- lphl->CtlID, MAKELONG(hwnd, code));
+ lphl->CtlID, MAKELONG(lphl->hSelf, code));
#endif
}
@@ -191,6 +214,8 @@
void ListBoxDrawItem (HWND hwnd, LPHEADLIST lphl, HDC hdc, LPLISTSTRUCT lpls,
RECT *rect, WORD itemAction, WORD itemState)
{
+ LONG dwStyle = GetWindowLong(hwnd,GWL_STYLE);
+
if (lphl->OwnerDrawn) {
DRAWITEMSTRUCT *dis = USER_HEAP_LIN_ADDR(lphl->hDrawItemStruct);
@@ -217,7 +242,7 @@
FillRect(hdc, rect, GetStockObject(BLACK_BRUSH));
}
- if (lphl->dwStyle & LBS_USETABSTOPS) {
+ if (dwStyle & LBS_USETABSTOPS) {
TabbedTextOut(hdc, rect->left + 5, rect->top + 2,
(char *)lpls->itemText, strlen((char *)lpls->itemText),
lphl->iNumStops, lphl->TabStops, 0);
@@ -269,7 +294,7 @@
MEASUREITEMSTRUCT *lpmeasure = (MEASUREITEMSTRUCT *) USER_HEAP_LIN_ADDR(hTemp);
if (lpmeasure == NULL) {
- fprintf(stderr,"ListBoxAskMeasure() out of memory !\n");
+ fprintf(stdnimp,"ListBoxAskMeasure() out of memory !\n");
return;
}
@@ -277,7 +302,7 @@
lpmeasure->itemHeight = lphl->StdItemHeight;
SendMessage(lphl->hParent, WM_MEASUREITEM, 0, (LPARAM)USER_HEAP_SEG_ADDR(hTemp));
- if (lphl->dwStyle & LBS_OWNERDRAWFIXED) {
+ if (GetWindowLong(lphl->hSelf,GWL_STYLE) & LBS_OWNERDRAWFIXED) {
lphl->StdItemHeight = lpmeasure->itemHeight;
lphl->needMeasure = FALSE;
}
@@ -285,6 +310,7 @@
USER_HEAP_FREE(hTemp);
}
+/* -------------------- strings and item data ---------------------- */
LPLISTSTRUCT ListBoxCreateItem(LPHEADLIST lphl, int id)
{
@@ -314,6 +340,8 @@
dprintf_listbox(stddeb,"ListBoxInsertString(%d, %p);\n", uIndex, newstr);
+ if (!newstr) return -1;
+
if (uIndex == (UINT)-1)
uIndex = lphl->ItemsCount;
@@ -326,7 +354,7 @@
lplsnew = ListBoxCreateItem(lphl, Count);
if (lplsnew == NULL) {
- printf("ListBoxInsertString() out of memory !\n");
+ fprintf(stdnimp,"ListBoxInsertString() out of memory !\n");
return LB_ERRSPACE;
}
@@ -368,9 +396,10 @@
int ListBoxAddString(LPHEADLIST lphl, LPSTR newstr)
{
+ LONG dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
UINT pos = (UINT) -1;
- if (lphl->HasStrings && (lphl->dwStyle & LBS_SORT)) {
+ if (lphl->HasStrings && (dwStyle & LBS_SORT)) {
LPLISTSTRUCT lpls = lphl->lpFirst;
for (pos = 0; lpls != NULL; lpls = lpls->lpNext, pos++)
if (strcmp(lpls->itemText, newstr) >= 0)
@@ -465,6 +494,7 @@
UINT Count;
UINT First = nFirst + 1;
LPSTR lpMatchStr = (LPSTR)MatchStr;
+ LONG dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
if (First > lphl->ItemsCount) return LB_ERR;
@@ -475,7 +505,7 @@
while(lpls != NULL) {
if (lphl->HasStrings) {
if (strstr(lpls->itemText, lpMatchStr) == lpls->itemText) return Count;
- } else if (lphl->dwStyle & LBS_SORT) {
+ } else if (dwStyle & LBS_SORT) {
/* XXX Do a compare item */
}
else
@@ -492,7 +522,7 @@
while (Count < First) {
if (lphl->HasStrings) {
if (strstr(lpls->itemText, lpMatchStr) == lpls->itemText) return Count;
- } else if (lphl->dwStyle & LBS_SORT) {
+ } else if (dwStyle & LBS_SORT) {
/* XXX Do a compare item */
} else {
if (lpls->mis.itemData == (DWORD)lpMatchStr) return Count;
@@ -528,13 +558,21 @@
return TRUE;
}
+/* --------------------- selection ------------------------- */
int ListBoxSetCurSel(LPHEADLIST lphl, WORD wIndex)
{
LPLISTSTRUCT lpls;
+ DWORD dwStyle = GetWindowWord(lphl->hSelf,GWL_STYLE);
- if (lphl->dwStyle & LBS_MULTIPLESEL) return 0;
+ /* use ListBoxSetSel instead */
+ if (dwStyle & LBS_MULTIPLESEL ) return 0;
+ /* unselect all previously selected */
+ if (dwStyle & LBS_EXTENDEDSEL )
+ ListBoxSetSel(lphl,-1,0);
+ else
+ /* unselect previous item */
if (lphl->ItemFocused != -1) {
lpls = ListBoxGetItem(lphl, lphl->ItemFocused);
if (lpls == 0) return LB_ERR;
@@ -558,7 +596,9 @@
{
LPLISTSTRUCT lpls;
- if (!(lphl->dwStyle & LBS_MULTIPLESEL)) return 0;
+ if (!(GetWindowLong(lphl->hSelf,GWL_STYLE) &
+ (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
+ return 0;
if (wIndex == (UINT)-1) {
for (lpls = lphl->lpFirst; lpls != NULL; lpls = lpls->lpNext) {
@@ -584,6 +624,7 @@
return lpls->itemState;
}
+/* ------------------------- dir listing ------------------------ */
int ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPSTR filespec)
{
@@ -648,6 +689,7 @@
return 1;
}
+/* ------------------------- dimensions ------------------------- */
int ListBoxGetItemRect(LPHEADLIST lphl, WORD wIndex, LPRECT lprect)
{
@@ -663,7 +705,7 @@
{
LPLISTSTRUCT lpls;
- if (!(lphl->dwStyle & LBS_OWNERDRAWVARIABLE)) {
+ if (!(GetWindowLong(lphl->hSelf,GWL_STYLE) & LBS_OWNERDRAWVARIABLE)) {
lphl->StdItemHeight = (short)height;
return 0;
}
@@ -675,6 +717,7 @@
return 0;
}
+/* -------------------------- string search ------------------------ */
int ListBoxFindNextMatch(LPHEADLIST lphl, WORD wChar)
{
@@ -706,11 +749,13 @@
static LONG LBCreate(HWND hwnd, WORD wParam, LONG lParam)
{
LPHEADLIST lphl;
+ LONG dwStyle = GetWindowLong(hwnd,GWL_STYLE);
RECT rect;
- CreateListBoxStruct(hwnd, ODT_LISTBOX, GetWindowLong(hwnd,GWL_STYLE), GetParent(hwnd));
+ CreateListBoxStruct(hwnd, ODT_LISTBOX, dwStyle, GetParent(hwnd));
lphl = ListBoxGetStorageHeader(hwnd);
- dprintf_listbox(stddeb,"ListBox WM_CREATE %p !\n", lphl);
+ dprintf_listbox(stddeb,"ListBox created: lphl = %p dwStyle = "NPFMT":"NPFMT"\n",
+ lphl, HIWORD(dwStyle), LOWORD(dwStyle));
GetClientRect(hwnd,&rect);
lphl->ColumnsWidth = rect.right - rect.left;
@@ -731,7 +776,7 @@
ListBoxResetContent(lphl);
DestroyListBoxStruct(lphl);
- dprintf_listbox(stddeb,"ListBox WM_DESTROY %p !\n", lphl);
+ dprintf_listbox(stddeb,"ListBox destroyed: lphl = %p\n",lphl);
return 0;
}
@@ -850,6 +895,7 @@
WORD wRet;
int y;
RECT rectsel;
+ LONG dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
SetFocus(hwnd);
SetCapture(hwnd);
@@ -860,19 +906,32 @@
if (y == -1)
return 0;
- if (lphl->dwStyle & LBS_MULTIPLESEL) {
+ if (dwStyle & LBS_MULTIPLESEL) {
lphl->ItemFocused = y;
wRet = ListBoxGetSel(lphl, y);
ListBoxSetSel(lphl, y, !wRet);
+
+ InvalidateRect(hwnd, NULL, TRUE);
} else {
ListBoxSetCurSel(lphl, y);
- }
- if (lphl->dwStyle & LBS_MULTIPLESEL)
- ListBoxSendNotification(lphl, hwnd, LBN_SELCHANGE);
ListBoxGetItemRect(lphl, y, &rectsel);
+ InvalidateRect(hwnd, &rectsel, TRUE);
+ if(lphl->PrevFocused) {
+ ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
+ InvalidateRect(hwnd, &rectsel, TRUE);
+ }
+ }
- InvalidateRect(hwnd, NULL, TRUE);
+ if (dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))
+ ListBoxSendNotification(lphl, LBN_SELCHANGE);
+
+ if (dwStyle & LBS_NOTIFY)
+ SendMessage(lphl->hParent, WM_LBTRACKPOINT, y, lParam);
+
+ if (GetWindowLong(lphl->hSelf,GWL_EXSTYLE) & WS_EX_DRAGDETECT)
+ if( DragDetect(lphl->hSelf,MAKEPOINT(lParam)) )
+ SendMessage(lphl->hParent, WM_BEGINDRAG,0,0L);
return 0;
}
@@ -887,7 +946,7 @@
if (GetCapture() == hwnd) ReleaseCapture();
if (lphl->PrevFocused != lphl->ItemFocused)
- ListBoxSendNotification(lphl, hwnd, LBN_SELCHANGE);
+ ListBoxSendNotification(lphl, LBN_SELCHANGE);
return 0;
}
@@ -919,6 +978,7 @@
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
int y;
WORD wRet;
+ LONG dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
RECT rect, rectsel; /* XXX Broken */
dprintf_listbox(stddeb,"LBMouseMove %d %d\n",SLOWORD(lParam),SHIWORD(lParam));
@@ -947,14 +1007,16 @@
if (wRet == lphl->ItemFocused) {
return 0;
}
- if (lphl->dwStyle & LBS_MULTIPLESEL) {
+ if (dwStyle & LBS_MULTIPLESEL) {
lphl->ItemFocused = wRet;
- ListBoxSendNotification(lphl, hwnd, LBN_SELCHANGE);
+ ListBoxSendNotification(lphl, LBN_SELCHANGE);
} else {
ListBoxSetCurSel(lphl, wRet);
+ if(dwStyle & LBS_EXTENDEDSEL)
+ ListBoxSendNotification(lphl, LBN_SELCHANGE);
}
ListBoxGetItemRect(lphl, wRet, &rectsel);
- InvalidateRect(hwnd, NULL, TRUE);
+ InvalidateRect(hwnd, &rectsel, TRUE);
}
}
}
@@ -964,20 +1026,42 @@
/***********************************************************************
* 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 = lphl->ItemFocused;
+ LONG dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
+ WORD newFocused = 0xFFFF;
+ RECT rect;
- if (wParam == VK_SPACE) {
- if (lphl->dwStyle & LBS_MULTIPLESEL) {
- WORD wRet = ListBoxGetSel(lphl, lphl->ItemFocused);
- ListBoxSetSel(lphl, lphl->ItemFocused, !wRet);
- }
- return 0;
+ ListBoxGetItemRect(lphl,lphl->ItemFocused,&rect);
+ switch(wParam)
+ {
+ /* ugly kludge that belongs in TranslateMessage */
+
+ 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 ( dwStyle & LBS_WANTKEYBOARDINPUT )
+ {
+ newFocused = (WORD)(INT)SendMessage(lphl->hParent,WM_VKEYTOITEM,
+ wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
+ if ( newFocused == 0xFFFE ) return 0L;
}
- switch(wParam) {
+ if ( newFocused == 0xFFFF )
+ {
+ newFocused = lphl->ItemFocused;
+
+ /* nested switch */
+ switch(wParam)
+ {
case VK_HOME:
newFocused = 0;
break;
@@ -985,7 +1069,7 @@
newFocused = lphl->ItemsCount - 1;
break;
case VK_LEFT:
- if (lphl->dwStyle & LBS_MULTICOLUMN) {
+ if (dwStyle & LBS_MULTICOLUMN) {
if (newFocused >= lphl->ItemsPerColumn) {
newFocused -= lphl->ItemsPerColumn;
} else {
@@ -997,19 +1081,16 @@
if (newFocused > 0) newFocused--;
break;
case VK_RIGHT:
- if (lphl->dwStyle & LBS_MULTICOLUMN) {
+ if (dwStyle & LBS_MULTICOLUMN)
newFocused += lphl->ItemsPerColumn;
- }
break;
case VK_DOWN:
newFocused++;
break;
case VK_PRIOR:
- if (newFocused > lphl->ItemsVisible) {
+ if (newFocused > lphl->ItemsVisible)
newFocused -= lphl->ItemsVisible;
- } else {
- newFocused = 0;
- }
+ else newFocused = 0;
break;
case VK_NEXT:
newFocused += lphl->ItemsVisible;
@@ -1017,19 +1098,49 @@
default:
return 0;
}
+ /* end of nested switch */
+ }
+ break;
+ case VK_SPACE:
+ if (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)) {
+ if (!(dwStyle & LBS_MULTIPLESEL))
+ {
ListBoxSetCurSel(lphl, newFocused);
- ListBoxSendNotification(lphl, hwnd, LBN_SELCHANGE);
+ ListBoxSendNotification(lphl, LBN_SELCHANGE);
}
lphl->ItemFocused = newFocused;
- ListBoxScrollToFocus(lphl);
- SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+
+ if( ListBoxScrollToFocus(lphl) || (dwStyle &
+ (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) )
InvalidateRect(hwnd, NULL, TRUE);
+ else
+ {
+ InvalidateRect(hwnd, &rect, TRUE);
+ if( newFocused < 0x8000 )
+ {
+ ListBoxGetItemRect(lphl, newFocused, &rect);
+ InvalidateRect(hwnd, &rect, TRUE);
+ }
+ }
+
+ SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
return 0;
}
@@ -1040,21 +1151,34 @@
static LONG LBChar(HWND hwnd, WORD wParam, LONG lParam)
{
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- WORD newFocused;
+ LONG dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
+ WORD newFocused = 0xFFFF;
+ if ( (dwStyle & LBS_WANTKEYBOARDINPUT) && !(lphl->HasStrings))
+ {
+ newFocused = (WORD)(INT)SendMessage(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)) {
+
+ if (!(dwStyle & LBS_MULTIPLESEL))
+ {
ListBoxSetCurSel(lphl, newFocused);
- ListBoxSendNotification(lphl, hwnd, LBN_SELCHANGE);
+ ListBoxSendNotification(lphl, LBN_SELCHANGE);
}
lphl->ItemFocused = newFocused;
ListBoxScrollToFocus(lphl);
SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+
InvalidateRect(hwnd, NULL, TRUE);
return 0;
@@ -1095,6 +1219,7 @@
static LONG LBPaint(HWND hwnd, WORD wParam, LONG lParam)
{
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
+ LONG dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
LPLISTSTRUCT lpls;
PAINTSTRUCT ps;
HBRUSH hBrush;
@@ -1127,7 +1252,7 @@
FillRect(hdc, &rect, hBrush);
maxwidth = rect.right;
- if (lphl->dwStyle & LBS_MULTICOLUMN) {
+ if (dwStyle & LBS_MULTICOLUMN) {
rect.right = lphl->ColumnsWidth;
}
lpls = lphl->lpFirst;
@@ -1142,7 +1267,7 @@
height = lpls->mis.itemHeight;
if (top > rect.bottom) {
- if (lphl->dwStyle & LBS_MULTICOLUMN) {
+ if (dwStyle & LBS_MULTICOLUMN) {
lphl->ItemsPerColumn = MAX(lphl->ItemsPerColumn, ipc);
ipc = 0;
top = 0;
@@ -1159,7 +1284,7 @@
lpls->itemRect.left = rect.left;
lpls->itemRect.right = rect.right;
- dprintf_listbox(stddeb,"drawing item: %d %d %d %d %d\n",rect.left,top,rect.right,top+height,lpls->itemState);
+ dprintf_listbox(stddeb,"drawing item: %ld %d %ld %d %d\n",(LONG)rect.left,top,(LONG)rect.right,top+height,lpls->itemState);
if (lphl->OwnerDrawn) {
ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE, 0);
if (lpls->itemState)
@@ -1370,7 +1495,7 @@
static LONG LBGetSel(HWND hwnd, WORD wParam, LONG lParam)
{
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- return ListBoxGetSel(lphl, wParam);
+ return (ListBoxGetSel(lphl, wParam) )? 1 : 0;
}
/***********************************************************************
@@ -1381,15 +1506,19 @@
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
LPLISTSTRUCT lpls;
int cnt = 0;
+ int items = 0;
- if (!(lphl->dwStyle & LBS_MULTIPLESEL)) return LB_ERR;
+ if (!(GetWindowLong(lphl->hSelf,GWL_STYLE) &
+ (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
+ return LB_ERR;
- lpls = lphl->lpFirst;
-
- while (lpls != NULL) {
- if (lpls->itemState > 0) cnt++;
-
- lpls = lpls->lpNext;
+ for( lpls = lphl->lpFirst;
+ lpls;
+ lpls = lpls->lpNext )
+ {
+ items++;
+ if (lpls->itemState )
+ cnt++;
}
return cnt;
@@ -1405,7 +1534,9 @@
int cnt, idx;
int *lpItems = PTR_SEG_TO_LIN(lParam);
- if (!(lphl->dwStyle & LBS_MULTIPLESEL)) return LB_ERR;
+ if (!(GetWindowLong(lphl->hSelf,GWL_STYLE) &
+ (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
+ return LB_ERR;
if (wParam == 0) return 0;
@@ -1481,7 +1612,9 @@
WORD last = HIWORD(lParam);
BOOL select = wParam;
- if (!(lphl->dwStyle & LBS_MULTIPLESEL)) return LB_ERR;
+ if (!(GetWindowLong(lphl->hSelf,GWL_STYLE) &
+ (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
+ return LB_ERR;
if (first >= lphl->ItemsCount ||
last >= lphl->ItemsCount) return LB_ERR;
@@ -1509,7 +1642,7 @@
{
LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- if (!(lphl->dwStyle & LBS_MULTIPLESEL)) return 0;
+ if (!(GetWindowLong(lphl->hSelf,GWL_STYLE) & LBS_MULTIPLESEL)) return 0;
if (wParam >= lphl->ItemsCount) return LB_ERR;
lphl->ItemFocused = wParam;
@@ -1650,6 +1783,20 @@
}
/***********************************************************************
+ * LBPassToParent
+ */
+static LRESULT LBPassToParent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ WND* ptrWnd = WIN_FindWndPtr(hwnd);
+
+ if( ptrWnd )
+ if( /* !(ptrWnd->dwExStyle & WS_EX_NOPARENTNOTIFY) && */
+ ptrWnd->hwndParent )
+ return SendMessage(ptrWnd->hwndParent,message,wParam,lParam);
+ return 0;
+}
+
+/***********************************************************************
* ListBoxWndProc
*/
LRESULT ListBoxWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
@@ -1702,6 +1849,24 @@
case LB_SETSEL: return LBSetSel(hwnd, wParam, lParam);
case LB_SETTOPINDEX: return LBSetTopIndex(hwnd, wParam, lParam);
case LB_SETITEMHEIGHT: return LBSetItemHeight(hwnd, wParam, lParam);
+
+ case WM_DROPFILES: return LBPassToParent(hwnd, message, wParam, lParam);
+
+ 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);
+
+ /* more undocumented Microsoft crap - drag&drop depends on it - AK */
+
+ lpDragInfo->l = ListBoxFindMouse(lphl,lpDragInfo->pt.x,
+ lpDragInfo->pt.y);
+
+ return LBPassToParent(hwnd, message, wParam, lParam);
+ }
}
return DefWindowProc(hwnd, message, wParam, lParam);