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);