Release 970329

Fri Mar 28 14:18:32 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [misc/main.c] [ANNOUNCE]
	Update the list of contributors. Please let me know if I forgot
	someone.

	* [controls/combo.c]
	Fixed bug in CB_DIR16 handling.
	Use correct text color in CBPaintText.

	* [controls/listbox.c]
	Fixed WM_CTLCOLOR handling.

	* [windows/winproc.c]
	Added translation for EM_*32 messages.

Mon Mar 24 01:31:52 1997  Steffen Moeller <moeller@mpimg-berlin-dahlem.mpg.de>

	* [files/drive.c]
	Added information on device and inode numbers to the DOSDRIVE
	struct, using it to find DOS drives in a path even if it contains
	symbolic links, eliminating annoying messages at startup.  
	Edited functions DRIVE_Init and rewrote DRIVE_FindDriveRoot.

Wed Mar 19 16:31:18 1997  John Harvey <john@division.co.uk>

	* [graphics/win16drv/font.c] [graphics/win16drv/init.c]
	  [graphics/x11drv/font.c] [objects/font.c] [include/gdi.h]
	  [include/win16drv.h] [include/x11drv.h]
	Implemented GetCharWidth via graphics drivers.

	* [graphics/win16drv/Makefile.in] [graphics/win16drv/prtdrv.c]
	Moved printer driver interfaces into a separate file.

	* [graphics/win16drv/text.c]
	Fixed bugs that seg-faulted write.

Wed Mar 19 13:52:41 1997  Alex Korobka <alex@trantor.pharm.sunysb.edu>

	* [BUGS]
	Update.

	* [controls/edit.c]
	Removed useless parameters from a lot of functions.

	* [controls/menu.c]
	Improved keyboard shortcuts. Added check for entries with popup 
	menu in EnableMenuItem().

	* [windows/winproc.c] [windows/win.c] [memory/selector.c]
	Do not allocate separate thunks for new windows.

	* [misc/clipboard.c] [windows/painting.c]
	Fixed problems with ClipBook.

        * [controls/combo.c] [controls/edit.c] [controls/listbox.c]
	  [controls/widgets.c] [windows/graphics.c] [windows/defdlg.c]
        Combo rewrite.

	* [objects/dib.c]
	Slight improvements.

Wed Mar 19 11:21:17 1997  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [misc/crtdll.c]
	Added chdir/mkdir.

	* [misc/ntdll.c]
	Fixed some bugs, added RtlUnicodeStringToAnsiString.

	* [win32/process.c]
	Added initialisation of events/semaphores/mutices.

Wed Mar 19 01:55:40 1997  Ricardo R. Massaro <massaro@ime.usp.br>

	* [resources/sysres_Po.rc]
	Added support for Portuguese language.

Sat Mar 18 18:00:14 1997  Uwe Bonnes  <bon@elektron.ikp.physik.th-darmstadt.de>

	* [windows/winpos.c] [if1632/user.spec] [if1632/user32.spec]
	Implemented SwitchToThisWindow().
	
	* [misc/ver.c]
	Corrected a flaw in VerInstallFile32A.
	
	* [msdos/int21.c]
	Corrected wrong number in Int21 3305
	Corrected Int21 714e, implemented Int21 7160,CL=2, 7143 and 7147
	
Sun Mar 16 09:53:04 1997  Andreas Mohr <100.30936@germany.net>

	* [loader/ne_module.c]
	Fixed NE_LoadSegments() to set size to pSeg->minsize rather than
	setting it to 0x10000 if pSeg->size is 0.

Thu Mar 13 12:15:00 1997  Anand Kumria <akumria@ozemail.com.au>

	* [ANNOUNCE]
	Added ftp.progsoc.uts.edu.au as a mirror of Wine.

	* [memory/global.c]
	Removed MemManInfo sizeof check.

Mon Mar 10 10:35:44 MET 1997 Sven Verdoolaege <skimo@breughel.ufsia.ac.be>

	* [files/dos_fs.c]
	Pick up kernel dirent on glibc systems.

	* [loader/signal.c]
	Pick up kernel sigaction on glibc systems.

Sat Mar  8 21:05:37 1997  Jimen Ching  <jching@aloha.com>

	* [debugger/stabs.c] [debugger/msc.c]
	Check return value of mmap.

Fri Mar  7 05:42:03 1997  Lee Jaekil <juria@seodu.co.kr>

	* [win32/code_page.c]
	Added IsValidCodePage.
diff --git a/ANNOUNCE b/ANNOUNCE
index 1c03369..2589715 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,13 +1,14 @@
-This is release 970305 of Wine, the MS Windows emulator.  This is still a
+This is release 970329 of Wine, the MS Windows emulator.  This is still a
 developer's only release.  There are many bugs and many unimplemented API
 features.  Most applications still do not work correctly.
 
 Patches should be submitted to "julliard@lrc.epfl.ch".  Please don't
 forget to include a ChangeLog entry.
 
-WHAT'S NEW with Wine-970305: (see ChangeLog for details)
-	- Completed transition to new Win32 types.
-	- Polish language support.
+WHAT'S NEW with Wine-970329: (see ChangeLog for details)
+	- Win32 event/mutex/semaphore functions.
+	- Rewritten combobox.
+	- Portuguese language support.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -16,10 +17,11 @@
 the release is available at the ftp sites.  The sources will be available
 from the following locations:
 
-  ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-970305.tar.gz
-  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-970305.tar.gz
-  ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-970305.tar.gz
-  ftp://aris.com/pub/linux/ALPHA/Wine/development/Wine-970305.tar.gz
+  ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-970329.tar.gz
+  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-970329.tar.gz
+  ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-970329.tar.gz
+  ftp://aris.com/pub/linux/ALPHA/Wine/development/Wine-970329.tar.gz
+  ftp://ftp.progsoc.uts.edu.au/pub/Wine/development/Wine-970329.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
@@ -31,25 +33,29 @@
 wine-patches your_address' to majordomo@tiger.informatik.hu-berlin.de.
 
 Wine is available thanks to the work of Bob Amstadt, Dag Asheim,
-Martin Ayotte, Ross Biro, Uwe Bonnes, Erik Bos, Fons Botman, John Brezak,
-Andrew Bulhak, John Burton, Niels de Carpentier, Roman Dolejsi,
-Frans van Dorsselaer, Paul Falstad, Olaf Flebbe, Peter Galbavy,
-Ramon Garcia, Hans de Graaff, Charles M. Hannum, John Harvey,
-Cameron Heide, Jochen Hoenicke, Onno Hovers, Jeffrey Hsu,
-Miguel de Icaza, Jukka Iivonen, Alexandre Julliard, Jochen Karrer,
-Andreas Kirschbaum, Albrecht Kleine, Jon Konrath, Alex Korobka,
-Greg Kreider, Anand Kumria, Scott A. Laird, Martin von Loewis,
-Kenneth MacDonald, Peter MacDonald, William Magro, Juergen Marquardt,
-Marcus Meissner, Graham Menhennitt, David Metcalfe, Steffen Moeller,
+Martin Ayotte, Peter Bajusz, Ross Biro, Uwe Bonnes, Erik Bos, Fons Botman,
+John Brezak, Andrew Bulhak, John Burton, Niels de Carpentier, Jimen Ching,
+Huw D. M. Davies, Roman Dolejsi, Frans van Dorsselaer, Paul Falstad,
+David Faure, Olaf Flebbe, Peter Galbavy, Ramon Garcia, Matthew Ghio,
+Hans de Graaff, Charles M. Hannum, John Harvey, Cameron Heide,
+Jochen Hoenicke, Onno Hovers, Jeffrey Hsu, Miguel de Icaza, Jukka Iivonen,
+Lee Jaekil, Alexandre Julliard, Bang Jun-Young, Pavel Kankovsky,
+Jochen Karrer, Andreas Kirschbaum, Albrecht Kleine, Jon Konrath,
+Alex Korobka, Greg Kreider, Anand Kumria, Scott A. Laird, Andrew Lewycky,
+Martin von Loewis, Kenneth MacDonald, Peter MacDonald, William Magro,
+Juergen Marquardt, Ricardo Massaro, Marcus Meissner, Graham Menhennitt,
+David Metcalfe, Bruce Milner, Steffen Moeller, Andreas Mohr,
 Philippe De Muyter, Itai Nahshon, Michael Patra, Jim Peterson,
-Robert Pouliot, Keith Reynolds, John Richardson, Johannes Ruscheinski,
-Thomas Sandford, Constantine Sapuntzakis, Daniel Schepler, Ulrich Schmid,
-Bernd Schmidt, Yngvi Sigurjonsson, Rick Sladkey, William Smith,
-Erik Svendsen, Tristan Tarrant, Andrew Taylor, Duncan C Thomson,
-Goran Thyni, Jimmy Tirtawangsa, Jon Tombs, Linus Torvalds,
-Gregory Trubetskoy, Michael Veksler, Sven Verdoolaege, Eric Warnke,
-Manfred Weichel, Morten Welinder, Jan Willamowius, Carl Williams,
-Karl Guenter Wuensch, Eric Youngdale, and James Youngman.
+Robert Pouliot, Keith Reynolds, Slaven Rezic, John Richardson,
+Johannes Ruscheinski, Thomas Sandford, Constantine Sapuntzakis,
+Pablo Saratxaga, Daniel Schepler, Ulrich Schmid, Bernd Schmidt,
+Yngvi Sigurjonsson, Stephen Simmons, Rick Sladkey, William Smith,
+Dominik Strasser, Vadim Strizhevsky, Erik Svendsen, Tristan Tarrant,
+Andrew Taylor, Duncan C Thomson, Goran Thyni, Jimmy Tirtawangsa, Jon Tombs,
+Linus Torvalds, Gregory Trubetskoy, Petri Tuomola, Michael Veksler,
+Sven Verdoolaege, Ronan Waide, Eric Warnke, Manfred Weichel,
+Morten Welinder, Jan Willamowius, Carl Williams, Karl Guenter Wuensch,
+Eric Youngdale, James Youngman, Mikolaj Zalewski, and John Zero.
 
 --
 Alexandre Julliard
diff --git a/BUGS b/BUGS
index b4e8b84..79ef935 100644
--- a/BUGS
+++ b/BUGS
@@ -5,23 +5,21 @@
 add new entries and, more importantly, remove those for the 
 bugs you fixed ;-)
 ------------------------------------------------------------
-As of Dec 22 1996 -
+As of March 10 1997 -
 
 General:
 
- * Combobox code is very inadequate (no notification messages,
-   dropdown listboxes often stay visible, etc... ).
-
  * Font mapping is too generic. No soft font loading, no rotated 
-   text support. [alex@amadeus.pharm.sunysb.edu]
+   text support, incorrect metrics. [alex@amadeus.pharm.sunysb.edu]
 
  * No thread/process/kernel-object support in Win32 code. 
 
  * Very alpha printing code. [john@division.co.uk]
 
- * No OLE and OLE32 support (including OLE interfaces etc.).
+ * No OLE2 and OLE32 support (including OLE2 interfaces etc.).
 
- * No MS Video support (perhaps interface with xanim).
+ * No MS Video support (perhaps interface with xanim, don't hold
+   your breath for this one).
 
  * No COMDLG32 support. (Needed badly, the Windows95 comdlg32.dll
    doesn't work with WINE.)
@@ -33,14 +31,26 @@
 	  Handles to these title windows are stored in the icon window
 	  properties.
 
+ * No manual pages describing the various Windows calls.
+
 Miscellaneous:
 
- * Simple OLE actions were working in October release, got
-   broken in November (in Winword "Insert Object" now results in 
-   segfault right after the call to LoadModule()).
+ * "Cursor XXXX has more than 1 bpp!"
+
+ * 32-bit Freecell segfaults when started from the Progman (looks like
+   a problem with cards.dll).
+
+ * Word 6.0 often segfaults when system menu is double-clicked. 
+
+ * Edit controls are prone to show blank space when, in fact, there is a
+   text there.
+
+ * SGI window manager treats Wine windows as topmost.
+
+ * Write shows blank space instead of Paintbrush OLE1 object.
+
  * AllocCSToDSAlias() shouldn't alloc alias for the same segment multiple
    times.
- * ScrollWindowEx() is outdated.
 
 Where to look in source files:
 
diff --git a/ChangeLog b/ChangeLog
index 3a722b6..23b82db 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,127 @@
 ----------------------------------------------------------------------
+Fri Mar 28 14:18:32 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>
+
+	* [misc/main.c] [ANNOUNCE]
+	Update the list of contributors. Please let me know if I forgot
+	someone.
+
+	* [controls/combo.c]
+	Fixed bug in CB_DIR16 handling.
+	Use correct text color in CBPaintText.
+
+	* [controls/listbox.c]
+	Fixed WM_CTLCOLOR handling.
+
+	* [windows/winproc.c]
+	Added translation for EM_*32 messages.
+
+Mon Mar 24 01:31:52 1997  Steffen Moeller <moeller@mpimg-berlin-dahlem.mpg.de>
+
+	* [files/drive.c]
+	Added information on device and inode numbers to the DOSDRIVE
+	struct, using it to find DOS drives in a path even if it contains
+	symbolic links, eliminating annoying messages at startup.  
+	Edited functions DRIVE_Init and rewrote DRIVE_FindDriveRoot.
+
+Wed Mar 19 16:31:18 1997  John Harvey <john@division.co.uk>
+
+	* [graphics/win16drv/font.c] [graphics/win16drv/init.c]
+	  [graphics/x11drv/font.c] [objects/font.c] [include/gdi.h]
+	  [include/win16drv.h] [include/x11drv.h]
+	Implemented GetCharWidth via graphics drivers.
+
+	* [graphics/win16drv/Makefile.in] [graphics/win16drv/prtdrv.c]
+	Moved printer driver interfaces into a separate file.
+
+	* [graphics/win16drv/text.c]
+	Fixed bugs that seg-faulted write.
+
+Wed Mar 19 13:52:41 1997  Alex Korobka <alex@trantor.pharm.sunysb.edu>
+
+	* [BUGS]
+	Update.
+
+	* [controls/edit.c]
+	Removed useless parameters from a lot of functions.
+
+	* [controls/menu.c]
+	Improved keyboard shortcuts. Added check for entries with popup 
+	menu in EnableMenuItem().
+
+	* [windows/winproc.c] [windows/win.c] [memory/selector.c]
+	Do not allocate separate thunks for new windows.
+
+	* [misc/clipboard.c] [windows/painting.c]
+	Fixed problems with ClipBook.
+
+        * [controls/combo.c] [controls/edit.c] [controls/listbox.c]
+	  [controls/widgets.c] [windows/graphics.c] [windows/defdlg.c]
+        Combo rewrite.
+
+	* [objects/dib.c]
+	Slight improvements.
+
+Wed Mar 19 11:21:17 1997  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
+
+	* [misc/crtdll.c]
+	Added chdir/mkdir.
+
+	* [misc/ntdll.c]
+	Fixed some bugs, added RtlUnicodeStringToAnsiString.
+
+	* [win32/process.c]
+	Added initialisation of events/semaphores/mutices.
+
+Wed Mar 19 01:55:40 1997  Ricardo R. Massaro <massaro@ime.usp.br>
+
+	* [resources/sysres_Po.rc]
+	Added support for Portuguese language.
+
+Sat Mar 18 18:00:14 1997  Uwe Bonnes  <bon@elektron.ikp.physik.th-darmstadt.de>
+
+	* [windows/winpos.c] [if1632/user.spec] [if1632/user32.spec]
+	Implemented SwitchToThisWindow().
+	
+	* [misc/ver.c]
+	Corrected a flaw in VerInstallFile32A.
+	
+	* [msdos/int21.c]
+	Corrected wrong number in Int21 3305
+	Corrected Int21 714e, implemented Int21 7160,CL=2, 7143 and 7147
+	
+Sun Mar 16 09:53:04 1997  Andreas Mohr <100.30936@germany.net>
+
+	* [loader/ne_module.c]
+	Fixed NE_LoadSegments() to set size to pSeg->minsize rather than
+	setting it to 0x10000 if pSeg->size is 0.
+
+Thu Mar 13 12:15:00 1997  Anand Kumria <akumria@ozemail.com.au>
+
+	* [ANNOUNCE]
+	Added ftp.progsoc.uts.edu.au as a mirror of Wine.
+
+	* [memory/global.c]
+	Removed MemManInfo sizeof check.
+
+Mon Mar 10 10:35:44 MET 1997 Sven Verdoolaege <skimo@breughel.ufsia.ac.be>
+
+	* [files/dos_fs.c]
+	Pick up kernel dirent on glibc systems.
+
+	* [loader/signal.c]
+	Pick up kernel sigaction on glibc systems.
+
+Sat Mar  8 21:05:37 1997  Jimen Ching  <jching@aloha.com>
+
+	* [debugger/stabs.c] [debugger/msc.c]
+	Check return value of mmap.
+
+Fri Mar  7 05:42:03 1997  Lee Jaekil <juria@seodu.co.kr>
+
+	* [win32/code_page.c]
+	Added IsValidCodePage.
+
+----------------------------------------------------------------------
 Sun Mar  2 14:57:37 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>
 
 	* [*/*]
diff --git a/controls/Makefile.in b/controls/Makefile.in
index 7f7dff9..09188b5 100644
--- a/controls/Makefile.in
+++ b/controls/Makefile.in
@@ -12,7 +12,6 @@
 	edit.c \
 	listbox.c \
 	menu.c \
-	oldlbox.c \
 	scroll.c \
 	static.c \
 	status.c \
diff --git a/controls/button.c b/controls/button.c
index 2058887..72e2893 100644
--- a/controls/button.c
+++ b/controls/button.c
@@ -472,23 +472,19 @@
 
     if (action != ODA_DRAWENTIRE) return;
 
-    if (infoPtr->hFont) SelectObject32( hDC, infoPtr->hFont );
     BUTTON_SEND_CTLCOLOR( wndPtr, hDC );
-    SelectObject32( hDC, sysColorObjects.hpenWindowFrame );
 
     GetClientRect16( wndPtr->hwndSelf, &rc);
-
-    MoveTo( hDC, rc.left, rc.top+2 );
-    LineTo32( hDC, rc.right-1, rc.top+2 );
-    LineTo32( hDC, rc.right-1, rc.bottom-1 );
-    LineTo32( hDC, rc.left, rc.bottom-1 );
-    LineTo32( hDC, rc.left, rc.top+2 );
-
-    if (!wndPtr->text) return;
-    if (wndPtr->dwStyle & WS_DISABLED)
-        SetTextColor32( hDC, GetSysColor32(COLOR_GRAYTEXT) );
-    rc.left += 10;
-    DrawText16( hDC, wndPtr->text, -1, &rc, DT_SINGLELINE | DT_NOCLIP );
+    GRAPH_DrawRectangle( hDC, rc.left, rc.top + 2, rc.right - 1, rc.bottom - 1,
+					     sysColorObjects.hpenWindowFrame );
+    if (wndPtr->text)
+    {
+	if (infoPtr->hFont) SelectObject32( hDC, infoPtr->hFont );
+        if (wndPtr->dwStyle & WS_DISABLED)
+            SetTextColor32( hDC, GetSysColor32(COLOR_GRAYTEXT) );
+        rc.left += 10;
+        DrawText16( hDC, wndPtr->text, -1, &rc, DT_SINGLELINE | DT_NOCLIP );
+    }
 }
 
 
diff --git a/controls/combo.c b/controls/combo.c
index f8fccf8..7bfb68d 100644
--- a/controls/combo.c
+++ b/controls/combo.c
@@ -1,1240 +1,1551 @@
 /*
  * Combo controls
  * 
- * Copyright 1993 Martin Ayotte
- * Copyright 1995 Bernd Schmidt
- * Copyright 1996 Albrecht Kleine  [some fixes]
+ * Copyright 1997 Alex Korobka
  * 
+ * FIXME: roll up in Netscape 3.01.
  */
 
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
 
 #include "windows.h"
 #include "sysmetrics.h"
+#include "syscolor.h"
 #include "win.h"
-#include "combo.h"
+#include "spy.h"
 #include "user.h"
 #include "graphics.h"
 #include "heap.h"
-#include "listbox.h"
+#include "combo.h"
 #include "drive.h"
 #include "stddebug.h"
 #include "debug.h"
-#include "xmalloc.h"
 
- /*
-  * Note: Combos are probably implemented in a different way by Windows.
-  * Using a message spy for Windows, you can see some undocumented
-  * messages being passed between ComboBox and ComboLBox.
-  * I hope no programs rely on the implementation of combos.
-  */
+  /* bits in the dwKeyData */
+#define KEYDATA_ALT             0x2000
+#define KEYDATA_PREVSTATE       0x4000
 
-#define ID_EDIT  1
-#define ID_CLB   2
-#define CBLMM_EDGE   4    /* distance inside box which is same as moving mouse
-			     outside box, to trigger scrolling of CBL */
+/*
+ * Additional combo box definitions
+ */
 
-static BOOL32 CBCheckSize(HWND16 hwnd);
-static BOOL32 CBLCheckSize(HWND16 hwnd);
+#define CB_GETPTR( wnd )      (*(LPHEADCOMBO*)((wnd)->wExtra))
+#define CB_NOTIFY( lphc, code ) \
+	(SendMessage32A( (lphc)->owner, WM_COMMAND, \
+			 MAKEWPARAM((lphc)->self->wIDmenu, (code)), (lphc)->self->hwndSelf))
+#define CB_GETEDITTEXTLENGTH( lphc ) \
+	(SendMessage32A( (lphc)->hWndEdit, WM_GETTEXTLENGTH, 0, 0 ))
 
-static HBITMAP16 hComboBit = 0;
-static WORD CBitHeight, CBitWidth;
+static HBITMAP16 	hComboBmp = 0;
+static UINT16		CBitHeight, CBitWidth;
+static UINT16		CBitOffset = 8;
 
-static int COMBO_Init()
+/***********************************************************************
+ *           COMBO_Init
+ *
+ * Load combo button bitmap.
+ */
+static BOOL32 COMBO_Init()
 {
-  BITMAP16 bm;
+  HDC16		hDC;
   
-  dprintf_combo(stddeb, "COMBO_Init\n");
-  hComboBit = LoadBitmap16(0, MAKEINTRESOURCE(OBM_COMBO));
-  GetObject16( hComboBit, sizeof(bm), &bm );
-  CBitHeight = bm.bmHeight;
-  CBitWidth = bm.bmWidth;
-  return 0;
-}
-
-LPHEADCOMBO ComboGetStorageHeader(HWND16 hwnd)
-{
-  return (LPHEADCOMBO)GetWindowLong32A(hwnd,4);
-}
-
-LPHEADLIST ComboGetListHeader(HWND16 hwnd)
-{
-  return (LPHEADLIST)GetWindowLong32A(hwnd,0);
-}
-
-int CreateComboStruct(HWND16 hwnd, LONG style)
-{
-  LPHEADCOMBO lphc;
-
-  lphc = (LPHEADCOMBO)xmalloc(sizeof(HEADCOMBO));
-  SetWindowLong32A(hwnd,4,(LONG)lphc);
-  lphc->hWndEdit = 0;
-  lphc->hWndLBox = 0;
-  lphc->dwState = 0;
-  lphc->LastSel = -1;
-  lphc->dwStyle = style; 
-  lphc->DropDownVisible = FALSE;
-  return TRUE;
-}
-
-void ComboUpdateWindow(HWND16 hwnd, LPHEADLIST lphl, LPHEADCOMBO lphc, BOOL32 repaint)
-{
-  WND *wndPtr = WIN_FindWndPtr(hwnd);
-
-  if (wndPtr->dwStyle & WS_VSCROLL) 
-    SetScrollRange32(lphc->hWndLBox,SB_VERT,0,ListMaxFirstVisible(lphl),TRUE);
-  if (repaint && lphl->bRedrawFlag) InvalidateRect32( hwnd, NULL, TRUE );
-}
-
-/***********************************************************************
- *           CBNCCreate
- */
-static LRESULT CBNCCreate(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  CREATESTRUCT16 *createStruct;
-
-  if (!hComboBit) COMBO_Init();
-
-  createStruct = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
-  createStruct->style |= WS_BORDER;
-  SetWindowLong32A(hwnd, GWL_STYLE, createStruct->style);
-
-  dprintf_combo(stddeb,"ComboBox WM_NCCREATE!\n");
-  return DefWindowProc16(hwnd, WM_NCCREATE, wParam, lParam);
-
-}
-
-/***********************************************************************
- *           CBCreate
- */
-static LRESULT CBCreate(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST   lphl;
-  LPHEADCOMBO  lphc;
-  LONG         style = 0;
-  LONG         cstyle = GetWindowLong32A(hwnd,GWL_STYLE);
-  RECT16       rect,lboxrect;
-  WND*         wndPtr = WIN_FindWndPtr(hwnd);
-  char className[] = "COMBOLBOX";  /* Hack so that class names are > 0x10000 */
-  char editName[] = "EDIT";
-  HWND16 hwndp=0;
-
-  /* translate combo into listbox styles */
-  cstyle |= WS_BORDER;
-  if (cstyle & CBS_OWNERDRAWFIXED) style |= LBS_OWNERDRAWFIXED;
-  if (cstyle & CBS_OWNERDRAWVARIABLE) style |= LBS_OWNERDRAWVARIABLE;
-  if (cstyle & CBS_SORT) style |= LBS_SORT;
-  if (cstyle & CBS_HASSTRINGS) style |= LBS_HASSTRINGS;
-  style |= LBS_NOTIFY;
-  CreateListBoxStruct(hwnd, ODT_COMBOBOX, style, GetParent16(hwnd));
-  CreateComboStruct(hwnd,cstyle);
-
-  lphl = ComboGetListHeader(hwnd);
-  lphc = ComboGetStorageHeader(hwnd);
-
-  GetClientRect16(hwnd,&rect);
-  lphc->LBoxTop = lphl->StdItemHeight;
-
-  switch(cstyle & 3) 
+  if( hComboBmp ) return TRUE;
+  if( (hDC = CreateCompatibleDC16(0)) )
   {
-   case CBS_SIMPLE:            /* edit control, list always visible  */
-     lboxrect=rect;    
-     dprintf_combo(stddeb,"CBS_SIMPLE\n");
-     style= WS_BORDER |  WS_CHILD | WS_VISIBLE | WS_VSCROLL;
-     SetRectEmpty16(&lphc->RectButton);
-     hwndp=hwnd;
-     break;
+    BOOL32	bRet = FALSE;
+    if( (hComboBmp = LoadBitmap16(0, MAKEINTRESOURCE(OBM_COMBO))) )
+    {
+      BITMAP16      bm;
+      HBITMAP16     hPrevB;
+      RECT16        r;
 
-   case CBS_DROPDOWNLIST:      /* static control, dropdown listbox   */
-   case CBS_DROPDOWN:          /* edit control, dropdown listbox     */
-     GetWindowRect16(hwnd,&lboxrect);
-     style = WS_POPUP | WS_BORDER | WS_VSCROLL;
-     /* FIXME: WinSight says these should be CHILD windows with the TOPMOST flag
-      * set. Wine doesn't support TOPMOST, and simply setting the WS_CHILD
-      * flag doesn't work. */
-     lphc->RectButton = rect;
-     lphc->RectButton.left = lphc->RectButton.right - 6 - CBitWidth;
-     lphc->RectButton.bottom = lphc->RectButton.top + lphl->StdItemHeight;
-     SetWindowPos32(hwnd, 0, 0, 0, rect.right -rect.left + 2*SYSMETRICS_CXBORDER,
-		 lphl->StdItemHeight + 2*SYSMETRICS_CYBORDER,
-		 SWP_NOMOVE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOACTIVATE);
-     dprintf_combo(stddeb,(cstyle & 3)==CBS_DROPDOWN ? "CBS_DROPDOWN\n": "CBS_DROPDOWNLIST\n");
-     break;
-     
-   default: fprintf(stderr,"COMBOBOX error: bad class style!\n");
-     return 0;
+      GetObject16( hComboBmp, sizeof(bm), &bm );
+      CBitHeight = bm.bmHeight;
+      CBitWidth  = bm.bmWidth;
+
+      dprintf_combo(stddeb, "combo bitmap [%i,%i]\n", CBitWidth, CBitHeight );
+
+      hPrevB = SelectObject16( hDC, hComboBmp);
+      SetRect16( &r, 0, 0, CBitWidth, CBitHeight );
+      InvertRect16( hDC, &r );
+      SelectObject16( hDC, hPrevB );
+      bRet = TRUE;
+    }
+    DeleteDC16( hDC );
+    return bRet;
   }
+  return FALSE;
+}
 
-  if ((cstyle & 3) != CBS_DROPDOWNLIST)
-      lphc->hWndEdit = CreateWindow16( editName, NULL,
-				  WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | ES_LEFT,
-				  0, 0, rect.right-6-CBitWidth,
-				  lphl->StdItemHeight+2*SYSMETRICS_CYBORDER,
-				  hwnd, (HMENU16)ID_EDIT, WIN_GetWindowInstance(hwnd), NULL );
-				  
-  lboxrect.top+=lphc->LBoxTop;
-  lphc->hWndLBox = CreateWindow16( className, NULL, style |
- 				((cstyle & WS_HSCROLL)? WS_HSCROLL : 0) |
- 				((cstyle & WS_VSCROLL)? WS_VSCROLL : 0),
-				lboxrect.left, lboxrect.top,
-				lboxrect.right - lboxrect.left, 
-				lboxrect.bottom - lboxrect.top,
-				hwndp,(HMENU16)ID_CLB, WIN_GetWindowInstance(hwnd),
-				(LPVOID)(HWND32)hwnd );
+/***********************************************************************
+ *           COMBO_NCCreate
+ */
+static LRESULT COMBO_NCCreate(WND* wnd, LPARAM lParam)
+{
+  LPHEADCOMBO 		lphc;
 
-   wndPtr->dwStyle &= ~(WS_VSCROLL | WS_HSCROLL);
+  if ( wnd && COMBO_Init() &&
+      (lphc = HeapAlloc(GetProcessHeap(), 0, sizeof(HEADCOMBO))) )
+  {
+       LPCREATESTRUCT32A     lpcs = (CREATESTRUCT32A*)lParam;
+       
+       memset( lphc, 0, sizeof(HEADCOMBO) );
+       *(LPHEADCOMBO*)wnd->wExtra = lphc;
 
-   dprintf_combo( stddeb, "Combo Creation hwnd=%04x  LBox=%04x  Edit=%04x\n",
-                  hwnd, lphc->hWndLBox, lphc->hWndEdit);
-   dprintf_combo( stddeb, "  lbox %d,%d-%d,%d     button %d,%d-%d,%d\n",
-                  lboxrect.left, lboxrect.top, lboxrect.right, lboxrect.bottom,
-                  lphc->RectButton.left, lphc->RectButton.top,
-                  lphc->RectButton.right, lphc->RectButton.bottom );
-   dprintf_combo( stddeb, "   client %d,%d-%d,%d     window %d,%d-%d,%d\n",
-                  wndPtr->rectClient.left, wndPtr->rectClient.top,
-                  wndPtr->rectClient.right, wndPtr->rectClient.bottom,
-                  wndPtr->rectWindow.left, wndPtr->rectWindow.top,
-                  wndPtr->rectWindow.right, wndPtr->rectWindow.bottom );
+       /* some braindead apps do try to use scrollbar/border flags */
+
+       lphc->dwStyle = (lpcs->style & ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL));
+       wnd->dwStyle &= ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL);
+
+       if( !(lpcs->style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) )
+             lphc->dwStyle |= CBS_HASSTRINGS;
+
+       dprintf_combo(stddeb, "COMBO_NCCreate: [0x%08x], style = %08x\n", 
+				              (UINT32)lphc, lphc->dwStyle );
+
+       return (LRESULT)(UINT32)wnd->hwndSelf; 
+  }
+  return (LRESULT)FALSE;
+}
+
+/***********************************************************************
+ *           COMBO_NCDestroy
+ */
+static LRESULT COMBO_NCDestroy( LPHEADCOMBO lphc )
+{
+
+   if( lphc )
+   {
+       WND*		wnd = lphc->self;
+
+       dprintf_combo(stddeb,"Combo [%04x]: freeing storage\n", CB_HWND(lphc));
+
+       if( (CB_GETTYPE(lphc) != CBS_SIMPLE) && lphc->hWndLBox ) 
+   	   DestroyWindow32( lphc->hWndLBox );
+
+       HeapFree( GetProcessHeap(), 0, lphc );
+       wnd->wExtra[0] = 0;
+   }
    return 0;
 }
 
 /***********************************************************************
- *           CBDestroy
+ *           CBCalcPlacement
+ *
+ * Set up component coordinates given valid lphc->RectCombo.
  */
-static LRESULT CBDestroy(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
+static void CBCalcPlacement( LPHEADCOMBO lphc, 
+			     LPRECT16 lprEdit, LPRECT16 lprButton, LPRECT16 lprLB )
 {
-  LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
+   RECT16	rect = lphc->RectCombo;
+   SIZE16	size;
 
-  if (lphc->hWndEdit) DestroyWindow32( lphc->hWndEdit );
-  if (lphc->hWndLBox) DestroyWindow32( lphc->hWndLBox );
-  return 0;
-}
+   /* get combo height and width */
 
-/***********************************************************************
- *           CBPaint
- */
-static LRESULT CBPaint(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
-  LPLISTSTRUCT lpls;
-  PAINTSTRUCT16  ps;
-  HBRUSH32 hBrush;
-  HFONT32 hOldFont;
-  HDC16 hdc;
-  RECT16 rect;
-  
-  hdc = BeginPaint16(hwnd, &ps);
-
-  GetClientRect16(hwnd, &rect);
-  CBCheckSize(hwnd);
-  /* 1 for button border */
-  rect.right = lphc->RectButton.left - 1;
-
-  if (hComboBit != 0 && !IsRectEmpty16(&lphc->RectButton))
-  {
-    Rectangle32(hdc,lphc->RectButton.left-1,lphc->RectButton.top-1,
-                lphc->RectButton.right+1,lphc->RectButton.bottom+1);
-    {
-        RECT32 r;
-        CONV_RECT16TO32( &lphc->RectButton, &r );
-        GRAPH_DrawReliefRect(hdc, &r, 2, 2, FALSE);
-    }
-    GRAPH_DrawBitmap(hdc, hComboBit,
-		     lphc->RectButton.left + 2,lphc->RectButton.top + 2,
-		     0, 0, CBitWidth, CBitHeight );
-  }
-  if (!IsWindowVisible16(hwnd) || !lphl->bRedrawFlag 
-      || (lphc->dwStyle & 3) != CBS_DROPDOWNLIST) 
-  {
-    /* we don't want to draw an entry when there is an edit control */
-    EndPaint16(hwnd, &ps);
-    return 0;
-  }
-
-  hOldFont = SelectObject32(hdc, lphl->hFont);
-
-  hBrush = SendMessage32A( lphl->hParent, WM_CTLCOLORLISTBOX, hdc, hwnd );
-  if (hBrush == 0) hBrush = GetStockObject32(WHITE_BRUSH);
-
-  lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
-  if (lpls != NULL) {  
-    FillRect16(hdc, &rect, hBrush);
-    ListBoxDrawItem (hwnd, lphl, hdc, lpls, &rect, ODA_DRAWENTIRE, 0);
-    if (GetFocus32() == hwnd)
-    ListBoxDrawItem (hwnd,lphl, hdc, lpls, &rect, ODA_FOCUS, ODS_FOCUS);
-  }
-  else FillRect16(hdc, &rect, hBrush);
-  SelectObject32(hdc,hOldFont);
-  EndPaint16(hwnd, &ps);
-  return 0;
-}
-
-/***********************************************************************
- *           CBGetDlgCode
- */
-static LRESULT CBGetDlgCode(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  return DLGC_WANTARROWS | DLGC_WANTCHARS;
-}
-
-/***********************************************************************
- *           CBLButtonDown
- */
-static LRESULT CBLButtonDown(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
-  SendMessage16(hwnd,CB_SHOWDROPDOWN16,!lphc->DropDownVisible,0);
-  return 0;
-}
-
-/***********************************************************************
- *           CBKeyDown
- */
-static LRESULT CBKeyDown(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  WORD       newFocused = lphl->ItemFocused;
-
-  switch(wParam) {
-  case VK_HOME:
-    newFocused = 0;
-    break;
-  case VK_END:
-    newFocused = lphl->ItemsCount - 1;
-    break;
-  case VK_UP:
-    if (newFocused > 0) newFocused--;
-    break;
-  case VK_DOWN:
-    newFocused++;
-    break;
-  default:
-    return 0;
-  }
-
-  if (newFocused >= lphl->ItemsCount)
-    newFocused = lphl->ItemsCount - 1;
-  
-  ListBoxSetCurSel(lphl, newFocused);
-  SendMessage16(hwnd, WM_COMMAND,ID_CLB,MAKELONG(0,CBN_SELCHANGE));
-  ListBoxSendNotification(lphl, CBN_SELCHANGE);
-
-  lphl->ItemFocused = newFocused;
-  ListBoxScrollToFocus(lphl);
-/*  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
-  InvalidateRect32( hwnd, NULL, TRUE );
-
-  return 0;
-}
-
-/***********************************************************************
- *           CBChar
- */
-static LRESULT CBChar(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  WORD       newFocused;
-
-  newFocused = ListBoxFindNextMatch(lphl, wParam);
-  if (newFocused == (WORD)LB_ERR) return 0;
-
-  if (newFocused >= lphl->ItemsCount)
-    newFocused = lphl->ItemsCount - 1;
-  
-  ListBoxSetCurSel(lphl, newFocused);
-  SendMessage16(hwnd, WM_COMMAND,ID_CLB,MAKELONG(0,CBN_SELCHANGE));
-  ListBoxSendNotification(lphl, CBN_SELCHANGE);
-  lphl->ItemFocused = newFocused;
-  ListBoxScrollToFocus(lphl);
-  
-/*  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
-  InvalidateRect32( hwnd, NULL, TRUE );
-
-  return 0;
-}
-
-/***********************************************************************
- *           CBKillFocus
- */
-static LRESULT CBKillFocus(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  return 0;
-}
-
-/***********************************************************************
- *           CBSetFocus
- */
-static LRESULT CBSetFocus(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  return 0;
-}
-
-/***********************************************************************
- *           CBResetContent
- */
-static LRESULT CBResetContent(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
-
-  ListBoxResetContent(lphl);
-  ComboUpdateWindow(hwnd, lphl, lphc, TRUE);
-  return 0;
-}
-
-/***********************************************************************
- *           CBDir
- */
-static LRESULT CBDir(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  WORD wRet;
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
-
-  wRet = ListBoxDirectory(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
-  ComboUpdateWindow(hwnd, lphl, lphc, TRUE);
-  return wRet;
-}
-
-/***********************************************************************
- *           CBInsertString
- */
-static LRESULT CBInsertString(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  WORD  wRet;
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
-
-  if (lphl->HasStrings)
-    wRet = ListBoxInsertString(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
-  else
-    wRet = ListBoxInsertString(lphl, wParam, (LPSTR)lParam);
-  ComboUpdateWindow(hwnd, lphl, lphc, TRUE);
-  return wRet;
-}
-
-/***********************************************************************
- *           CBAddString
- */
-static LRESULT CBAddString(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  WORD  wRet;
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
-
-  wRet = ListBoxAddString(lphl, (SEGPTR)lParam);
-
-  ComboUpdateWindow(hwnd, lphl, lphc, TRUE);
-  return wRet;
-}
-
-/***********************************************************************
- *           CBDeleteString
- */
-static LRESULT CBDeleteString(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
-  LONG lRet = ListBoxDeleteString(lphl,wParam);
-  
-  ComboUpdateWindow(hwnd, lphl, lphc, TRUE);
-  return lRet;
-}
-
-/***********************************************************************
- *           CBSelectString
- */
-static LRESULT CBSelectString(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  WORD  wRet;
-
-  wRet = ListBoxFindString(lphl, wParam, (SEGPTR)lParam);
-
-  /* XXX add functionality here */
-
-  return 0;
-}
-
-/***********************************************************************
- *           CBFindString
- */
-static LRESULT CBFindString(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  return ListBoxFindString(lphl, wParam, (SEGPTR)lParam);
-}
-
-/***********************************************************************
- *           CBFindStringExact
- */
-static LRESULT CBFindStringExact(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  return ListBoxFindStringExact(lphl, wParam, (SEGPTR)lParam);
-}
-
-/***********************************************************************
- *           CBGetCount
- */
-static LRESULT CBGetCount(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  return lphl->ItemsCount;
-}
-
-/***********************************************************************
- *           CBSetCurSel
- */
-static LRESULT CBSetCurSel(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  WORD  wRet;
-
-  wRet = ListBoxSetCurSel(lphl, wParam);
-
-  dprintf_combo(stddeb,"CBSetCurSel: hwnd %04x wp %x lp %lx wRet %d\n",
-		hwnd,wParam,lParam,wRet);
-/*  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
-  InvalidateRect32( hwnd, NULL, TRUE );
-
-  return wRet;
-}
-
-/***********************************************************************
- *           CBGetCurSel
- */
-static LRESULT CBGetCurSel(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  return lphl->ItemFocused;
-}
-
-/***********************************************************************
- *           CBGetItemHeight
- */
-static LRESULT CBGetItemHeight(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  LPLISTSTRUCT lpls = ListBoxGetItem (lphl, wParam);
-
-  if (lpls == NULL) return LB_ERR;
-  return lpls->mis.itemHeight;
-}
-
-/***********************************************************************
- *           CBSetItemHeight
- */
-static LRESULT CBSetItemHeight(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  return ListBoxSetItemHeight(lphl, wParam, lParam);
-}
-
-/***********************************************************************
- *           CBSetRedraw
- */
-static LRESULT CBSetRedraw(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  lphl->bRedrawFlag = wParam;
-  return 0;
-}
-
-/***********************************************************************
- *           CBSetFont
- */
-static LRESULT CBSetFont(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST  lphl = ComboGetListHeader(hwnd);
-  LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
-  
-  if (wParam == 0)
-    lphl->hFont = GetStockObject32(SYSTEM_FONT);
-  else
-    lphl->hFont = (HFONT16)wParam;
-  if (lphc->hWndEdit)
-     SendMessage16(lphc->hWndEdit,WM_SETFONT,lphl->hFont,0); 
-  return 0;
-}
-
-/***********************************************************************
- *           CBGetLBTextLen
- */
-static LRESULT CBGetLBTextLen(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST   lphl = ComboGetListHeader(hwnd);
-  LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wParam);
-
-  if (lpls == NULL || !lphl->HasStrings) return LB_ERR;
-  return strlen(lpls->itemText);
-}
-
-/***********************************************************************
- *           CBGetLBText
- */
-static LRESULT CBGetLBText(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  return ListBoxGetText(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
-}
-
-/***********************************************************************
- *           CBGetItemData
- */
-static LRESULT CBGetItemData(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  return ListBoxGetItemData(lphl, wParam);
-}
-
-/***********************************************************************
- *           CBSetItemData
- */
-static LRESULT CBSetItemData(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  return ListBoxSetItemData(lphl, wParam, lParam);
-}
-
-/***********************************************************************
- *           CBShowDropDown
- */
-static LRESULT CBShowDropDown(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
-  RECT32 rect;
-  
-  if ((lphc->dwStyle & 3) == CBS_SIMPLE) return LB_ERR;
-  
-  wParam = !!wParam;
-  if (wParam != lphc->DropDownVisible) {
-    lphc->DropDownVisible = wParam;
-    GetWindowRect32(hwnd,&rect);
-    SetWindowPos32(lphc->hWndLBox, 0, rect.left, rect.top+lphc->LBoxTop, 0, 0,
-		 SWP_NOSIZE | SWP_NOACTIVATE |
-                 (wParam ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
-    if (!wParam) SetFocus32(hwnd);
-  }
-  return 0;
-}
-
-
-/***********************************************************************
- *             CBCheckSize
- */
-static BOOL32 CBCheckSize(HWND16 hwnd)
-{
-  LPHEADCOMBO  lphc = ComboGetStorageHeader(hwnd);
-  LPHEADLIST   lphl = ComboGetListHeader(hwnd);
-  LONG         cstyle = GetWindowLong32A(hwnd,GWL_STYLE);
-  RECT16       cRect, wRect;
-
-  if (lphc->hWndLBox == 0) return FALSE;
-
-  GetClientRect16(hwnd,&cRect);
-  GetWindowRect16(hwnd,&wRect);
-
-  dprintf_combo(stddeb,
-	 "CBCheckSize: hwnd %04x Rect %d,%d-%d,%d  wRect %d,%d-%d,%d\n", 
-		hwnd,cRect.left,cRect.top,cRect.right,cRect.bottom,
-		wRect.left,wRect.top,wRect.right,wRect.bottom);
-  if ((cstyle & 3) == CBS_SIMPLE) return TRUE;
-
-  if ((cRect.bottom - cRect.top) >
-      (lphl->StdItemHeight + 2*SYSMETRICS_CYBORDER)) {
-    SetWindowPos32(hwnd, 0, 0, 0, 
-		 cRect.right-cRect.left,
-		 lphl->StdItemHeight+2*SYSMETRICS_CYBORDER, 
-		 SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE );
-    GetClientRect16(hwnd,&cRect);
-    GetWindowRect16(hwnd,&wRect);
-
-    lphc->RectButton.right = cRect.right;
-    lphc->RectButton.left = cRect.right - 2*SYSMETRICS_CXBORDER - 4 
-                            - CBitWidth;
-    lphc->RectButton.top = cRect.top;
-    lphc->RectButton.bottom = cRect.bottom;
-  }
-
-  if (cRect.right < lphc->RectButton.left) {
-    /* if the button is outside the window move it in */
-    if ((wRect.right - wRect.left - 2*SYSMETRICS_CXBORDER) == (cRect.right - cRect.left)) {
-      lphc->RectButton.right = cRect.right;
-      lphc->RectButton.left = cRect.right - 2*SYSMETRICS_CXBORDER - 4 
-	                       - CBitWidth;
-      lphc->RectButton.top = cRect.top;
-      lphc->RectButton.bottom = cRect.bottom;
-    }
-    /* otherwise we need to make the client include the button */
-    else
-      SetWindowPos32(hwnd, 0, 0, 0, lphc->RectButton.right,
-		   lphl->StdItemHeight+2*SYSMETRICS_CYBORDER,
-		   SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
-
-      if ((lphc->dwStyle & 3) != CBS_DROPDOWNLIST)
-        SetWindowPos32(lphc->hWndEdit, 0, 0, 0, lphc->RectButton.left,
-		     lphl->StdItemHeight,
-		     SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
-  }
-
-  CBLCheckSize(hwnd);
-  return TRUE;
-}
-
-/***********************************************************************
- *           CBCommand        
- */
-static LRESULT CBCommand(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
-  char       buffer[256];
-  WORD       newFocused;
-  WORD       id;
-  if (lphc->hWndEdit)  /* interdependence only used for CBS_SIMPLE and CBS_DROPDOWN styles */
-  {
-   switch (wParam)
+   if( lphc->editHeight )
+       size.cy = (INT16)lphc->editHeight;
+   else
    {
-    case ID_CLB:                                        /* update EDIT window */
-                if (HIWORD(lParam)==CBN_SELCHANGE)
-                 if (lphl->HasStrings)
-                 { 
-                  ListBoxGetText(lphl,lphl->ItemFocused, buffer);
-                  dprintf_combo(stddeb,"CBCommand: update Edit: %s\n",buffer);
-                  SetWindowText32A( lphc->hWndEdit, buffer );
-                 }
-                break;
-    case ID_EDIT:                                      /* update LISTBOX window */
-                 id = GetWindowWord32(hwnd,GWW_ID);
-                 switch (HIWORD(lParam))
-                 {
-                  case EN_UPDATE:GetWindowText32A(lphc->hWndEdit,buffer,255);
-                                 if (*buffer)
-                                 {
-                                  char *str = SEGPTR_STRDUP(buffer);
-                                  newFocused=ListBoxFindString(lphl, -1, SEGPTR_GET(str));
-                                  SEGPTR_FREE(str);
-                                  dprintf_combo(stddeb,"CBCommand: new selection #%d is= %s\n",
-                                                newFocused,buffer);
-                                  if (newFocused != (WORD)LB_ERR)
-                                  {                             /* if found something */
-                                   ListBoxSetCurSel(lphl, newFocused);
-                                   ListBoxSendNotification(lphl, CBN_SELCHANGE);
-                                   InvalidateRect32(hwnd, NULL, TRUE); 
-                                  }
-                                 }
-                                 SendMessage16(GetParent16(hwnd),WM_COMMAND,id,
-                                         MAKELONG(hwnd, CBN_EDITUPDATE));
-                                 break;
-                  case EN_CHANGE:SendMessage16(GetParent16(hwnd),WM_COMMAND,id,
-                                         MAKELONG(hwnd, CBN_EDITCHANGE));
-                                 break;
-                  case EN_ERRSPACE:SendMessage16(GetParent16(hwnd),WM_COMMAND,id,
-                                         MAKELONG(hwnd, CBN_ERRSPACE));
-                                 break;
-                }
-                break;        
+       HDC16	hDC = GetDC16( lphc->self->hwndSelf );
+       HFONT16	hPrevFont = (HFONT16)0;
+
+       if( lphc->hFont ) hPrevFont = SelectObject16( hDC, lphc->hFont );
+   
+       GetTextExtentPoint16( hDC, "X", 1, &size);
+       size.cy += size.cy / 4 + 4 * SYSMETRICS_CYBORDER;
+
+       if( hPrevFont ) SelectObject16( hDC, hPrevFont );
+       ReleaseDC16( lphc->self->hwndSelf, hDC );
    }
-  } 
+   size.cx = rect.right - rect.left;
+
+   if( CB_OWNERDRAWN(lphc) )
+   {
+       UINT16	u = lphc->RectEdit.bottom - lphc->RectEdit.top;
+
+       if( lphc->wState & CBF_MEASUREITEM ) /* first initialization */
+       {
+	 MEASUREITEMSTRUCT32        mi32;
+
+	 lphc->wState &= ~CBF_MEASUREITEM;
+	 mi32.CtlType = ODT_COMBOBOX;
+	 mi32.CtlID   = lphc->self->wIDmenu;
+	 mi32.itemID  = -1;
+	 mi32.itemWidth  = size.cx;
+	 mi32.itemHeight = size.cy - 6;	/* ownerdrawn cb is taller */
+	 mi32.itemData   = 0;
+	 SendMessage32A(lphc->owner, WM_MEASUREITEM, 
+				(WPARAM32)mi32.CtlID, (LPARAM)&mi32);
+	 u = 6 + (UINT16)mi32.itemHeight;
+       }
+       size.cy = u;
+   }
+
+   /* calculate text and button placement */
+
+   lprEdit->left = lprEdit->top = lprButton->top = 0;
+   if( CB_GETTYPE(lphc) == CBS_SIMPLE ) 	/* no button */
+       lprButton->left = lprButton->right = lprButton->bottom = 0;
+   else
+   {
+       INT32	i = size.cx - CBitWidth - 10;	/* seems ok */
+
+       lprButton->right = size.cx;
+       lprButton->left = (INT16)i;
+       lprButton->bottom = lprButton->top + size.cy;
+
+       if( i < 0 ) size.cx = 0;
+       else size.cx = (INT16)i;
+   }
+
+   if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
+   {
+       size.cx -= CBitOffset;
+       if( size.cx < 0 ) size.cx = 0;
+   }
+
+   lprEdit->right = size.cx; lprEdit->bottom = size.cy;
+
+   /* listbox placement */
+
+   lprLB->left = ( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST ) ? 0 : CBitOffset;
+   lprLB->top = lprEdit->bottom - SYSMETRICS_CYBORDER;
+   lprLB->right = rect.right - rect.left;
+   lprLB->bottom = rect.bottom - rect.top;
+
+   if( lphc->droppedWidth > (lprLB->right - lprLB->left) )
+       lprLB->right = lprLB->left + (INT16)lphc->droppedWidth;
+
+dprintf_combo(stddeb,"Combo [%04x]: (%i,%i-%i,%i) placement\n\ttext\t= (%i,%i-%i,%i)\
+\n\tbutton\t= (%i,%i-%i,%i)\n\tlbox\t= (%i,%i-%i,%i)\n", CB_HWND(lphc),
+lphc->RectCombo.left, lphc->RectCombo.top, lphc->RectCombo.right, lphc->RectCombo.bottom,
+lprEdit->left, lprEdit->top, lprEdit->right, lprEdit->bottom,
+lprButton->left, lprButton->top, lprButton->right, lprButton->bottom, 
+lprLB->left, lprLB->top, lprLB->right, lprLB->bottom );
+
+}
+
+/***********************************************************************
+ *           CBGetDroppedControlRect32
+ */
+static void CBGetDroppedControlRect32( LPHEADCOMBO lphc, LPRECT32 lpRect)
+{
+   lpRect->left = lphc->RectCombo.left +
+                      (lphc->wState & CBF_EDIT) ? CBitOffset : 0;
+   lpRect->top = lphc->RectCombo.top + lphc->RectEdit.bottom -
+                                             SYSMETRICS_CYBORDER;
+   lpRect->right = lphc->RectCombo.right;
+   lpRect->bottom = lphc->RectCombo.bottom - SYSMETRICS_CYBORDER;
+}
+
+/***********************************************************************
+ *           COMBO_Create
+ */
+static LRESULT COMBO_Create( LPHEADCOMBO lphc, WND* wnd, LPARAM lParam)
+{
+  static char clbName[] = "ComboLBox";
+  static char editName[] = "Edit";
+
+  LPCREATESTRUCT32A  lpcs = (CREATESTRUCT32A*)lParam;
+  
+  if( !CB_GETTYPE(lphc) ) lphc->dwStyle |= CBS_SIMPLE;
+  else if( CB_GETTYPE(lphc) != CBS_DROPDOWNLIST ) lphc->wState |= CBF_EDIT;
+
+  lphc->self  = wnd;
+  lphc->owner = lpcs->hwndParent;
+
+  /* M$ IE 3.01 actually creates (and rapidly destroys) an ownerless combobox */
+
+  if( lphc->owner || !(lpcs->style & WS_VISIBLE) )
+  {
+      UINT32	lbeStyle;
+      RECT16	editRect, btnRect, lbRect;
+
+      GetWindowRect16( wnd->hwndSelf, &lphc->RectCombo );
+
+      lphc->wState |= CBF_MEASUREITEM;
+      CBCalcPlacement( lphc, &editRect, &btnRect, &lbRect );
+      lphc->RectButton = btnRect;
+      lphc->droppedWidth = lphc->editHeight = 0;
+
+      /* create listbox popup */
+
+      lbeStyle = (LBS_NOTIFY | WS_BORDER | WS_CLIPSIBLINGS) | 
+                 (lpcs->style & (WS_VSCROLL | CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE));
+
+      if( lphc->dwStyle & CBS_SORT )
+	lbeStyle |= LBS_SORT;
+      if( lphc->dwStyle & CBS_HASSTRINGS )
+	lbeStyle |= LBS_HASSTRINGS;
+      if( lphc->dwStyle & CBS_NOINTEGRALHEIGHT )
+	lbeStyle |= LBS_NOINTEGRALHEIGHT;
+      if( lphc->dwStyle & CBS_DISABLENOSCROLL )
+	lbeStyle |= LBS_DISABLENOSCROLL;
+  
+      if( CB_GETTYPE(lphc) == CBS_SIMPLE ) 	/* child listbox */
+	lbeStyle |= WS_CHILD | WS_VISIBLE;
+      else					/* popup listbox */
+      {
+	lbeStyle |= WS_POPUP;
+	OffsetRect16( &lbRect, lphc->RectCombo.left, lphc->RectCombo.top );
+      }
+
+     /* Dropdown ComboLBox is not a child window and we cannot pass 
+      * ID_CB_LISTBOX directly because it will be treated as a menu handle.
+      */
+
+      lphc->hWndLBox = CreateWindowEx32A( 0, clbName, NULL, lbeStyle, 
+		        lbRect.left + SYSMETRICS_CXBORDER, 
+		        lbRect.top + SYSMETRICS_CYBORDER, 
+			lbRect.right - lbRect.left - 2 * SYSMETRICS_CXBORDER, 
+			lbRect.bottom - lbRect.top - 2 * SYSMETRICS_CYBORDER, 
+			lphc->self->hwndSelf, 
+		       (lphc->dwStyle & CBS_DROPDOWN)? (HMENU32)0 : (HMENU32)ID_CB_LISTBOX,
+			lphc->self->hInstance, (LPVOID)lphc );
+      if( lphc->hWndLBox )
+      {
+	  BOOL32	bEdit = TRUE;
+	  lbeStyle = WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NOHIDESEL | ES_LEFT;
+	  if( lphc->wState & CBF_EDIT ) 
+	  {
+	      if( lphc->dwStyle & CBS_OEMCONVERT )
+		  lbeStyle |= ES_OEMCONVERT;
+	      if( lphc->dwStyle & CBS_AUTOHSCROLL )
+		  lbeStyle |= ES_AUTOHSCROLL;
+	      if( lphc->dwStyle & CBS_LOWERCASE )
+		  lbeStyle |= ES_LOWERCASE;
+	      else if( lphc->dwStyle & CBS_UPPERCASE )
+		  lbeStyle |= ES_UPPERCASE;
+	      lphc->hWndEdit = CreateWindowEx32A( 0, editName, NULL, lbeStyle,
+		  	editRect.left, editRect.top, editRect.right - editRect.left,
+			editRect.bottom - editRect.top, lphc->self->hwndSelf, 
+			(HMENU32)ID_CB_EDIT, lphc->self->hInstance, NULL );
+	      if( !lphc->hWndEdit ) bEdit = FALSE;
+	  } 
+
+          if( bEdit )
+	  {
+	      lphc->RectEdit = editRect;
+	      if( CB_GETTYPE(lphc) != CBS_SIMPLE )
+	      {
+		lphc->wState |= CBF_NORESIZE;
+		SetWindowPos32( wnd->hwndSelf, 0, 0, 0, 
+				lphc->RectCombo.right - lphc->RectCombo.left,
+				lphc->RectEdit.bottom - lphc->RectEdit.top,
+				SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
+		lphc->wState &= ~CBF_NORESIZE;
+	      }
+	      dprintf_combo(stddeb,"COMBO_Create: init done\n");
+	      return wnd->hwndSelf;
+	  }
+	  dprintf_combo(stderr, "COMBO_Create: edit control failure.\n");
+      } else dprintf_combo(stderr, "COMBO_Create: listbox failure.\n");
+  } else dprintf_combo(stderr, "COMBO_Create: no owner for visible combo.\n");
+
+  /* CreateWindow() will send WM_NCDESTROY to cleanup */
+
+  return -1;
+}
+
+/***********************************************************************
+ *           CBPaintButton
+ *
+ * Paint combo button (normal, pressed, and disabled states).
+ */
+static void CBPaintButton(LPHEADCOMBO lphc, HDC16 hdc)
+{
+    RECT32 	r;
+    HBRUSH32 	hPrevBrush;
+    UINT32 	x, y;
+    BOOL32 	bBool;
+
+    hPrevBrush = (HBRUSH32)SelectObject32(hdc, sysColorObjects.hbrushBtnFace);
+    CONV_RECT16TO32( &lphc->RectButton, &r );
+
+    Rectangle32(hdc, r.left, r.top, r.right, r.bottom );
+    InflateRect32( &r, -1, -1 );
+    if( (bBool = lphc->wState & CBF_BUTTONDOWN) )
+    {
+	GRAPH_DrawReliefRect(hdc, &r, 1, 0, TRUE);
+	OffsetRect32( &r, 1, 1 );
+    } else GRAPH_DrawReliefRect(hdc, &r, 1, 2, FALSE);
+
+    x = (r.left + r.right - CBitWidth) >> 1;
+    y = (r.top + r.bottom - CBitHeight) >> 1;
+
+    InflateRect32( &r, -3, -3 );
+    if( (bBool = CB_DISABLED(lphc)) )
+    {
+        GRAPH_SelectClipMask(hdc, hComboBmp, x + 1, y + 1 );
+        FillRect32(hdc, &r, (HBRUSH32)GetStockObject32(WHITE_BRUSH));
+    }
+
+    GRAPH_SelectClipMask(hdc, hComboBmp, x, y );
+    FillRect32(hdc, &r, (HBRUSH32)GetStockObject32((bBool) ? GRAY_BRUSH : BLACK_BRUSH));
+
+    GRAPH_SelectClipMask(hdc, (HBITMAP32)0, 0, 0);
+    SelectObject32( hdc, hPrevBrush );
+}
+
+/***********************************************************************
+ *           CBPaintText
+ *
+ * Paint CBS_DROPDOWNLIST text field / update edit control contents.
+ */
+static void CBPaintText(LPHEADCOMBO lphc, HDC16 hdc)
+{
+   INT32	id, size;
+   LPSTR	pText = NULL;
+
+   /* follow Windows combobox that sends a bunch of text 
+    * inquiries to its listbox while processing WM_PAINT.
+    */
+
+   size = SendMessage32A( lphc->hWndLBox, LB_GETTEXTLEN32,
+	 	(id = SendMessage32A(lphc->hWndLBox, LB_GETCURSEL32, 0, 0)), 0);
+
+   if( !(pText = HeapAlloc( GetProcessHeap(), 0, size + 1)) ) return;
+
+   SendMessage32A( lphc->hWndLBox, LB_GETTEXT32, (WPARAM32)id, (LPARAM)pText );
+   pText[size] = '\0';	/* just in case */
+
+   if( lphc->wState & CBF_EDIT )
+   {
+	if( CB_HASSTRINGS(lphc) )
+	    SetWindowText32A( lphc->hWndEdit, (pText) ? pText : "" );
+	if( lphc->wState & CBF_FOCUSED )
+	    SendMessage32A( lphc->hWndEdit, EM_SETSEL32, 0, (LPARAM)(-1));
+   }
+   else /* paint text field ourselves */
+   {
+        HBRUSH32 hPrevBrush = 0;
+	HDC32	 hDC = hdc;
+
+	if( !hDC ) 
+	{
+	    if ((hDC = GetDC32(lphc->self->hwndSelf)))
+            {
+                HBRUSH32 hBrush = SendMessage32A( lphc->owner,
+                                                  WM_CTLCOLORLISTBOX, 
+                                                  hDC, lphc->self->hwndSelf );
+                hPrevBrush = SelectObject32( hDC, 
+                           (hBrush) ? hBrush : GetStockObject32(WHITE_BRUSH) );
+            }
+	}
+	if( hDC )
+	{
+	    RECT32	rect;
+	    UINT16	itemState;
+	    HFONT32	hPrevFont = (lphc->hFont) ? SelectObject32(hDC, lphc->hFont) : 0;
+
+	    PatBlt32( hDC, (rect.left = lphc->RectEdit.left + SYSMETRICS_CXBORDER),
+			   (rect.top = lphc->RectEdit.top + SYSMETRICS_CYBORDER),
+			   (rect.right = lphc->RectEdit.right - SYSMETRICS_CXBORDER),
+			   (rect.bottom = lphc->RectEdit.bottom - SYSMETRICS_CYBORDER) - 1, PATCOPY );
+	    InflateRect32( &rect, -1, -1 );
+
+	    if( lphc->wState & CBF_FOCUSED && 
+	        !(lphc->wState & CBF_DROPPED) )
+	    {
+		/* highlight */
+
+		FillRect32( hDC, &rect, sysColorObjects.hbrushHighlight );
+                SetBkColor32( hDC, GetSysColor32( COLOR_HIGHLIGHT ) );
+                SetTextColor32( hDC, GetSysColor32( COLOR_HIGHLIGHTTEXT ) );
+		itemState = ODS_SELECTED | ODS_FOCUS;
+	    } else itemState = 0;
+
+	    if( CB_OWNERDRAWN(lphc) )
+	    {
+		DRAWITEMSTRUCT32 dis;
+
+		if( lphc->self->dwStyle & WS_DISABLED ) itemState |= ODS_DISABLED;
+
+		dis.CtlType	= ODT_COMBOBOX;
+		dis.CtlID	= lphc->self->wIDmenu;
+		dis.hwndItem	= lphc->self->hwndSelf;
+		dis.itemAction	= ODA_DRAWENTIRE;
+		dis.itemID	= id;
+		dis.itemState	= itemState;
+		dis.hDC		= hDC;
+		dis.rcItem	= rect;
+		dis.itemData	= SendMessage32A( lphc->hWndLBox, LB_GETITEMDATA32, 
+						  		  (WPARAM32)id, 0 );
+		SendMessage32A( lphc->owner, WM_DRAWITEM, 
+				lphc->self->wIDmenu, (LPARAM)&dis );
+	    }
+	    else
+	    {
+		ExtTextOut32A( hDC, rect.left + 1, rect.top + 1,
+			       ETO_OPAQUE | ETO_CLIPPED, &rect, pText, size, NULL );
+		if( lphc->wState & CBF_FOCUSED && !(lphc->wState & CBF_DROPPED) )
+		    DrawFocusRect32( hDC, &rect );
+	    }
+
+	    if( hPrevFont ) SelectObject32(hDC, hPrevFont );
+	    if( !hdc ) 
+	    {
+		if( hPrevBrush ) SelectObject32( hDC, hPrevBrush );
+		ReleaseDC32( lphc->self->hwndSelf, hDC );
+	    }
+	}
+   }
+   HeapFree( GetProcessHeap(), 0, pText );
+}
+
+/***********************************************************************
+ *           COMBO_Paint
+ */
+static LRESULT COMBO_Paint(LPHEADCOMBO lphc, HDC16 hParamDC)
+{
+  PAINTSTRUCT16 ps;
+  HDC16 	hDC;
+  
+  hDC = (hParamDC) ? hParamDC
+		   : BeginPaint16( lphc->self->hwndSelf, &ps);
+  if( hDC && !(lphc->self->flags & WIN_NO_REDRAW) )
+  {
+      HBRUSH32	hPrevBrush, hBkgBrush;
+
+      hBkgBrush = SendMessage32A( lphc->owner, WM_CTLCOLORLISTBOX,
+				  hDC, lphc->self->hwndSelf );
+      if( !hBkgBrush ) hBkgBrush = GetStockObject32(WHITE_BRUSH);
+
+      hPrevBrush = SelectObject32( hDC, hBkgBrush );
+      if( !IsRectEmpty16(&lphc->RectButton) )
+      {
+	  /* paint everything to the right of the text field */
+
+	  PatBlt32( hDC, lphc->RectEdit.right, lphc->RectEdit.top,
+			 lphc->RectButton.right - lphc->RectEdit.right,
+			 lphc->RectEdit.bottom - lphc->RectEdit.top, PATCOPY );
+          CBPaintButton( lphc, hDC );
+      }
+
+      if( !(lphc->wState & CBF_EDIT) )
+      {
+	  /* paint text field */
+
+	  GRAPH_DrawRectangle( hDC, lphc->RectEdit.left, lphc->RectEdit.top,
+				    lphc->RectEdit.right - lphc->RectEdit.left, 
+				    lphc->RectButton.bottom - lphc->RectButton.top,
+				    sysColorObjects.hpenWindowFrame ); 
+	  CBPaintText( lphc, hDC );
+      }
+      if( hPrevBrush ) SelectObject32( hDC, hPrevBrush );
+  }
+  if( !hParamDC ) EndPaint16(lphc->self->hwndSelf, &ps);
+  return 0;
+}
+
+/***********************************************************************
+ *           CBUpdateLBox
+ *
+ * Select listbox entry according to the contents of the edit control.
+ */
+static INT32 CBUpdateLBox( LPHEADCOMBO lphc )
+{
+   INT32	length, idx, ret;
+   LPSTR	pText = NULL;
+   
+   idx = ret = LB_ERR;
+   length = CB_GETEDITTEXTLENGTH( lphc );
+ 
+   if( length > 0 ) 
+       pText = (LPSTR) HeapAlloc( GetProcessHeap(), 0, length + 1);
+
+   dprintf_combo(stddeb,"\tCBUpdateLBox: edit text length %i\n", length );
+
+   if( pText )
+   {
+       if( length ) GetWindowText32A( lphc->hWndEdit, pText, length + 1);
+       else pText[0] = '\0';
+       idx = SendMessage32A( lphc->hWndLBox, LB_FINDSTRING32, 
+			     (WPARAM32)(-1), (LPARAM)pText );
+       if( idx == LB_ERR ) idx = 0;	/* select first item */
+       else ret = idx;
+       HeapFree( GetProcessHeap(), 0, pText );
+   }
+
+   /* select entry */
+
+   SendMessage32A( lphc->hWndLBox, LB_SETCURSEL32, (WPARAM32)idx, 0 );
+   
+   if( idx >= 0 )
+   {
+       SendMessage32A( lphc->hWndLBox, LB_SETTOPINDEX32, (WPARAM32)idx, 0 );
+       /* probably superfluous but Windows sends this too */
+       SendMessage32A( lphc->hWndLBox, LB_SETCARETINDEX32, (WPARAM32)idx, 0 );
+   }
+   return ret;
+}
+
+/***********************************************************************
+ *           CBUpdateEdit
+ *
+ * Copy a listbox entry to the edit control.
+ */
+static void CBUpdateEdit( LPHEADCOMBO lphc , INT32 index )
+{
+   INT32	length;
+   LPSTR	pText = NULL;
+
+   dprintf_combo(stddeb,"\tCBUpdateEdit: %i\n", index );
+
+   if( index == -1 )
+   {
+       length = CB_GETEDITTEXTLENGTH( lphc );
+       if( length )
+       {
+           if( (pText = (LPSTR) HeapAlloc( GetProcessHeap(), 0, length + 1)) )
+           {
+ 	   	GetWindowText32A( lphc->hWndEdit, pText, length + 1 );
+	   	index = SendMessage32A( lphc->hWndLBox, LB_FINDSTRING32,
+				        (WPARAM32)(-1), (LPARAM)pText );
+	   	HeapFree( GetProcessHeap(), 0, pText );
+           }
+       }
+   }
+
+   if( index >= 0 ) /* got an entry */
+   {
+       length = SendMessage32A( lphc->hWndLBox, LB_GETTEXTLEN32, (WPARAM32)index, 0);
+       if( length )
+       {
+	   if( (pText = (LPSTR) HeapAlloc( GetProcessHeap(), 0, length + 1)) )
+	   {
+		SendMessage32A( lphc->hWndLBox, LB_GETTEXT32, 
+				(WPARAM32)index, (LPARAM)pText );
+		SendMessage32A( lphc->hWndEdit, WM_SETTEXT, 0, (LPARAM)pText );
+		SendMessage32A( lphc->hWndEdit, EM_SETSEL32, 0, (LPARAM)(-1) );
+		HeapFree( GetProcessHeap(), 0, pText );
+	   }
+       }
+   }
+}
+
+/***********************************************************************
+ *           CBDropDown
+ * 
+ * Show listbox popup.
+ */
+static void CBDropDown( LPHEADCOMBO lphc )
+{
+   INT32	index;
+   RECT16	rect;
+   LPRECT16	pRect = NULL;
+
+   dprintf_combo(stddeb,"Combo [%04x]: drop down\n", CB_HWND(lphc));
+
+   CB_NOTIFY( lphc, CBN_DROPDOWN );
+
+   /* set selection */
+
+   lphc->wState |= CBF_DROPPED;
+   if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
+   {
+       index = CBUpdateLBox( lphc );
+       if( !(lphc->wState & CBF_CAPTURE) ) CBUpdateEdit( lphc, index );
+   }
+   else
+   {
+       index = SendMessage32A( lphc->hWndLBox, LB_GETCURSEL32, 0, 0 );
+       if( index == LB_ERR ) index = 0;
+       SendMessage32A( lphc->hWndLBox, LB_SETTOPINDEX32, (WPARAM32)index, 0 );
+       SendMessage32A( lphc->hWndLBox, LB_CARETON32, 0, 0 );
+       pRect = &lphc->RectEdit;
+   }
+
+   /* now set popup position */
+
+   GetWindowRect16( lphc->self->hwndSelf, &rect );
+   
+   rect.top += lphc->RectEdit.bottom - lphc->RectEdit.top - SYSMETRICS_CYBORDER;
+   rect.bottom = rect.top + lphc->RectCombo.bottom - 
+			    lphc->RectCombo.top - SYSMETRICS_CYBORDER;
+   rect.right = rect.left + lphc->RectCombo.right - lphc->RectCombo.left;
+   rect.left += ( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST ) ? 0 : CBitOffset;
+
+   SetWindowPos32( lphc->hWndLBox, HWND_TOP, rect.left, rect.top, 
+		 rect.right - rect.left, rect.bottom - rect.top, 
+		 SWP_NOACTIVATE | SWP_NOSIZE );
+   if( pRect )
+       RedrawWindow16( lphc->self->hwndSelf, pRect, 0, RDW_INVALIDATE | 
+			   RDW_ERASE | RDW_UPDATENOW | RDW_NOCHILDREN );
+   ShowWindow32( lphc->hWndLBox, SW_SHOWNA );
+}
+
+/***********************************************************************
+ *           CBRollUp
+ *
+ * Hide listbox popup.
+ */
+static void CBRollUp( LPHEADCOMBO lphc, BOOL32 ok, BOOL32 bButton )
+{
+   HWND32	hWnd = lphc->self->hwndSelf;
+
+   CB_NOTIFY( lphc, (ok) ? CBN_SELENDOK : CBN_SELENDCANCEL );
+
+   if( IsWindow32( hWnd ) && CB_GETTYPE(lphc) != CBS_SIMPLE )
+   {
+
+       dprintf_combo(stddeb,"Combo [%04x]: roll up [%i]\n", CB_HWND(lphc), (INT32)ok );
+
+       /* always send WM_LBUTTONUP? */
+       SendMessage32A( lphc->hWndLBox, WM_LBUTTONUP, 0, (LPARAM)(-1) );
+
+       if( lphc->wState & CBF_DROPPED ) 
+       {
+	   RECT16	rect;
+
+	   lphc->wState &= ~CBF_DROPPED;
+	   ShowWindow32( lphc->hWndLBox, SW_HIDE );
+
+	   if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
+	   {
+	       INT32 index = SendMessage32A( lphc->hWndLBox, LB_GETCURSEL32, 0, 0 );
+	       CBUpdateEdit( lphc, index );
+	       rect = lphc->RectButton;
+	   }
+	   else 
+           {
+	       if( bButton )
+	           UnionRect16( &rect, &lphc->RectButton,
+				       &lphc->RectEdit );
+	       else
+		   rect = lphc->RectEdit;
+	       bButton = TRUE;
+	   }
+
+	   if( bButton )
+	       RedrawWindow16( hWnd, &rect, 0, RDW_INVALIDATE | 
+			       RDW_ERASE | RDW_UPDATENOW | RDW_NOCHILDREN );
+	   CB_NOTIFY( lphc, CBN_CLOSEUP );
+       }
+   }
+}
+
+/***********************************************************************
+ *           COMBO_FlipListbox
+ *
+ * Used by the ComboLBox to show/hide itself in response to VK_F4, etc...
+ */
+BOOL32 COMBO_FlipListbox( LPHEADCOMBO lphc, BOOL32 bRedrawButton )
+{
+   if( lphc->wState & CBF_DROPPED )
+   {
+       CBRollUp( lphc, TRUE, bRedrawButton );
+       return FALSE;
+   }
+
+   CBDropDown( lphc );
+   return TRUE;
+}
+
+/***********************************************************************
+ *           COMBO_GetLBWindow
+ *
+ * Edit control helper.
+ */
+HWND32 COMBO_GetLBWindow( WND* pWnd )
+{
+  LPHEADCOMBO       lphc = CB_GETPTR(pWnd);
+  if( lphc ) return lphc->hWndLBox;
   return 0;
 }
 
 
 /***********************************************************************
- *           CBGetEditSel
- * Look out! Under Win32, the parameter packing is very different.
+ *           CBRepaintButton
  */
-static LRESULT CBGetEditSel(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
+static void CBRepaintButton( LPHEADCOMBO lphc )
 {
-    LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
+   HDC32        hDC = GetDC32( lphc->self->hwndSelf );
 
-    if ((lphc->dwStyle & 3) == CBS_DROPDOWNLIST)
-      return CB_ERR;	/* err, documented for CBSetEditSel */
-    return SendMessage16(lphc->hWndEdit, EM_GETSEL16, 0, 0);
+   if( hDC )
+   {
+       CBPaintButton( lphc, (HDC16)hDC );
+       ReleaseDC32( lphc->self->hwndSelf, hDC );
+   }
+}
+
+/***********************************************************************
+ *           COMBO_SetFocus
+ */
+static void COMBO_SetFocus( LPHEADCOMBO lphc )
+{
+   if( !(lphc->wState & CBF_FOCUSED) )
+   {
+       if( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST )
+           SendMessage32A( lphc->hWndLBox, LB_CARETON32, 0, 0 );
+
+       if( lphc->wState & CBF_EDIT )
+           SendMessage32A( lphc->hWndEdit, EM_SETSEL32, 0, (LPARAM)(-1) );
+       lphc->wState |= CBF_FOCUSED;
+       if( !(lphc->wState & CBF_EDIT) ) CBPaintText( lphc, 0 );
+
+       CB_NOTIFY( lphc, CBN_SETFOCUS );
+   }
+}
+
+/***********************************************************************
+ *           COMBO_KillFocus
+ */
+static void COMBO_KillFocus( LPHEADCOMBO lphc )
+{
+   HWND32	hWnd = lphc->self->hwndSelf;
+
+   if( lphc->wState & CBF_FOCUSED )
+   {
+       SendMessage32A( hWnd, WM_LBUTTONUP, 0, (LPARAM)(-1) );
+
+       CBRollUp( lphc, FALSE, TRUE );
+       if( IsWindow32( hWnd ) )
+       {
+           if( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST )
+               SendMessage32A( lphc->hWndLBox, LB_CARETOFF32, 0, 0 );
+
+ 	   lphc->wState &= ~CBF_FOCUSED;
+
+           /* redraw text */
+           if( lphc->wState & CBF_EDIT )
+               SendMessage32A( lphc->hWndEdit, EM_SETSEL32, (WPARAM32)(-1), 0 );
+           else CBPaintText( lphc, 0 );
+
+           CB_NOTIFY( lphc, CBN_KILLFOCUS );
+       }
+   }
+}
+
+/***********************************************************************
+ *           COMBO_Command
+ */
+static LRESULT COMBO_Command( LPHEADCOMBO lphc, WPARAM32 wParam, HWND32 hWnd )
+{
+   if( lphc->wState & CBF_EDIT && lphc->hWndEdit == hWnd )
+   {
+       /* ">> 8" makes gcc generate jump-table instead of cmp ladder */
+
+       switch( HIWORD(wParam) >> 8 )
+       {   
+	   case (EN_SETFOCUS >> 8):
+
+		dprintf_combo(stddeb,"Combo [%04x]: edit [%04x] got focus\n", 
+				     CB_HWND(lphc), (HWND16)lphc->hWndEdit );
+
+		if( !(lphc->wState & CBF_FOCUSED) ) COMBO_SetFocus( lphc );
+	        break;
+
+	   case (EN_KILLFOCUS >> 8):
+
+		dprintf_combo(stddeb,"Combo [%04x]: edit [%04x] lost focus\n",
+				      CB_HWND(lphc), (HWND16)lphc->hWndEdit );
+
+		/* NOTE: it seems that Windows' edit control sends an
+		 * undocumented message WM_USER + 0x1B instead of this
+		 * notification (only when it happens to be a part of 
+		 * the combo). ?? - AK.
+		 */
+
+		COMBO_KillFocus( lphc );
+		break;
+
+
+	   case (EN_CHANGE >> 8):
+		CB_NOTIFY( lphc, CBN_EDITCHANGE );
+		CBUpdateLBox( lphc );
+		break;
+
+	   case (EN_UPDATE >> 8):
+		CB_NOTIFY( lphc, CBN_EDITUPDATE );
+		break;
+
+	   case (EN_ERRSPACE >> 8):
+		CB_NOTIFY( lphc, CBN_ERRSPACE );
+       }
+   }
+   else if( lphc->hWndLBox == hWnd )
+   {
+       switch( HIWORD(wParam) )
+       {
+	   case LBN_ERRSPACE:
+		CB_NOTIFY( lphc, CBN_ERRSPACE );
+		break;
+
+	   case LBN_DBLCLK:
+		CB_NOTIFY( lphc, CBN_DBLCLK );
+		break;
+
+	   case LBN_SELCHANGE:
+	   case LBN_SELCANCEL:
+
+		dprintf_combo(stddeb,"Combo [%04x]: lbox selection change [%04x]\n", 
+						      CB_HWND(lphc), lphc->wState );
+
+		/* do not roll up if selection is being tracked 
+		 * by arrowkeys in the dropdown listbox */
+
+		if( (lphc->wState & CBF_DROPPED) && !(lphc->wState & CBF_NOROLLUP) )
+		     CBRollUp( lphc, (HIWORD(wParam) == LBN_SELCHANGE), TRUE );
+		else lphc->wState &= ~CBF_NOROLLUP;
+
+		CB_NOTIFY( lphc, CBN_SELCHANGE );
+		CBPaintText( lphc, 0 );
+		/* fall through */
+
+	   case LBN_SETFOCUS:
+	   case LBN_KILLFOCUS:
+		/* nothing to do here since ComboLBox always resets the focus to its
+		 * combo/edit counterpart */
+       }
+   }
+   return 0;
+}
+
+/***********************************************************************
+ *           COMBO_ItemOp
+ *
+ * Fixup an ownerdrawn item operation and pass it up to the combobox owner.
+ */
+static LRESULT COMBO_ItemOp32( LPHEADCOMBO lphc, UINT32 msg, 
+			       WPARAM32 wParam, LPARAM lParam ) 
+{
+   HWND32	hWnd = lphc->self->hwndSelf;
+
+   dprintf_combo(stddeb,"Combo [%04x]: ownerdraw op %04x\n", 
+				       CB_HWND(lphc), (UINT16)msg );
+
+#define lpIS    ((LPDELETEITEMSTRUCT32)lParam)
+
+   /* two first items are the same in all 4 structs */
+   lpIS->CtlType = ODT_COMBOBOX;
+   lpIS->CtlID   = lphc->self->wIDmenu;
+
+   switch( msg )	/* patch window handle */
+   {
+	case WM_DELETEITEM: 
+	     lpIS->hwndItem = hWnd; 
+#undef  lpIS
+	     break;
+	case WM_DRAWITEM: 
+#define lpIS    ((LPDRAWITEMSTRUCT32)lParam)
+	     lpIS->hwndItem = hWnd; 
+#undef  lpIS
+	     break;
+	case WM_COMPAREITEM: 
+#define lpIS    ((LPCOMPAREITEMSTRUCT32)lParam)
+	     lpIS->hwndItem = hWnd; 
+#undef  lpIS
+	     break;
+   }
+
+  return SendMessage32A( lphc->owner, msg, lphc->self->wIDmenu, lParam );
+}
+
+/***********************************************************************
+ *           COMBO_GetText
+ */
+static LRESULT COMBO_GetText( LPHEADCOMBO lphc, UINT32 N, LPSTR lpText)
+{
+   INT32	idx;
+
+   if( lphc->wState & CBF_EDIT )
+       return SendMessage32A( lphc->hWndEdit, WM_GETTEXT, 
+			     (WPARAM32)N, (LPARAM)lpText );     
+
+   /* get it from the listbox */
+
+   idx = SendMessage32A( lphc->hWndLBox, LB_GETCURSEL32, 0, 0 );
+   if( idx >= 0 )
+   {
+       LPSTR        lpBuffer;
+       INT32	    length = SendMessage32A( lphc->hWndLBox, LB_GETTEXTLEN32,
+					    (WPARAM32)idx, 0 );
+
+       /* 'length' is without the terminating character */
+       if( length >= N )
+	   lpBuffer = (LPSTR) HeapAlloc( GetProcessHeap(), 0, length + 1 );
+       else 
+	   lpBuffer = lpText;
+
+       if( lpBuffer )
+       {
+	   INT32    n = SendMessage32A( lphc->hWndLBox, LB_GETTEXT32, 
+				       (WPARAM32)idx, (LPARAM)lpText );
+
+	   /* truncate if buffer is too short */
+
+	   if( length >= N )
+	   {
+	       if( n != LB_ERR ) memcpy( lpText, lpBuffer, (N>n) ? n+1 : N-1 );
+	       lpText[N - 1] = '\0';
+	       HeapFree( GetProcessHeap(), 0, lpBuffer );
+	   }
+	   return (LRESULT)n;
+       }
+   }
+   return 0;
 }
 
 
 /***********************************************************************
- *           CBSetEditSel
- * Look out! Under Win32, the parameter packing is very different.
+ *           CBResetPos
+ *
+ * This function sets window positions according to the updated 
+ * component placement struct.
  */
-static LRESULT CBSetEditSel(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
+static void CBResetPos( LPHEADCOMBO lphc, LPRECT16 lbRect, BOOL32 bRedraw )
 {
-    LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
+   BOOL32	bDrop = (CB_GETTYPE(lphc) != CBS_SIMPLE);
 
-    if ((lphc->dwStyle & 3) == CBS_DROPDOWNLIST)
-      return CB_ERR;
-    return SendMessage16(lphc->hWndEdit, EM_SETSEL16, 0, lParam);
+   /* NOTE: logs sometimes have WM_LBUTTONUP before a cascade of
+    * sizing messages */
+
+   if( lphc->wState & CBF_EDIT )
+       SetWindowPos32( lphc->hWndEdit, 0, lphc->RectEdit.left, lphc->RectEdit.top,
+                       lphc->RectEdit.right - lphc->RectEdit.left,
+                       lphc->RectEdit.bottom - lphc->RectEdit.top,
+                       SWP_NOZORDER | SWP_NOACTIVATE | ((bDrop) ? SWP_NOREDRAW : 0) );
+
+   if( bDrop )
+       OffsetRect16( lbRect, lphc->RectCombo.left, lphc->RectCombo.top );
+
+   lbRect->right -= lbRect->left;	/* convert to width */
+   lbRect->bottom -= lbRect->top;
+   SetWindowPos32( lphc->hWndLBox, 0, lbRect->left, lbRect->top,
+                   lbRect->right, lbRect->bottom, 
+		   SWP_NOACTIVATE | SWP_NOZORDER | ((bDrop) ? SWP_NOREDRAW : 0) );
+
+   if( bDrop )
+   {
+       if( lphc->wState & CBF_DROPPED )
+       {
+           lphc->wState &= ~CBF_DROPPED;
+           ShowWindow32( lphc->hWndLBox, SW_HIDE );
+       }
+
+       lphc->wState |= CBF_NORESIZE;
+       SetWindowPos32( lphc->self->hwndSelf, 0, 0, 0,
+                       lphc->RectCombo.right - lphc->RectCombo.left,
+                       lphc->RectEdit.bottom - lphc->RectEdit.top,
+                       SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW );
+       lphc->wState &= ~CBF_NORESIZE;
+       if( bRedraw )
+           RedrawWindow32( lphc->self->hwndSelf, NULL, 0,
+                           RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW );
+   }
+}
+
+
+/***********************************************************************
+ *           COMBO_Size
+ */
+static void COMBO_Size( LPHEADCOMBO lphc )
+{
+  RECT16	rect;
+  INT16		w, h;
+
+  GetWindowRect16( lphc->self->hwndSelf, &rect );
+  w = rect.right - rect.left; h = rect.bottom - rect.top;
+
+  dprintf_combo(stddeb,"COMBO_Size: w = %i, h = %i\n", w, h );
+
+  /* CreateWindow() may send a bogus WM_SIZE, ignore it */
+
+  if( w == (lphc->RectCombo.right - lphc->RectCombo.left) )
+      if( (CB_GETTYPE(lphc) == CBS_SIMPLE) &&
+	  (h == (lphc->RectCombo.bottom - lphc->RectCombo.top)) )
+          return;
+      else if( (lphc->dwStyle & CBS_DROPDOWN) &&
+	       (h == (lphc->RectEdit.bottom - lphc->RectEdit.top))  )
+	       return;
+  
+  lphc->RectCombo = rect;
+  CBCalcPlacement( lphc, &lphc->RectEdit, &lphc->RectButton, &rect );
+  CBResetPos( lphc, &rect, TRUE );
+}
+
+
+/***********************************************************************
+ *           COMBO_Font
+ */
+static void COMBO_Font( LPHEADCOMBO lphc, HFONT16 hFont, BOOL32 bRedraw )
+{
+  RECT16        rect;
+
+  lphc->hFont = hFont;
+
+  if( lphc->wState & CBF_EDIT )
+      SendMessage32A( lphc->hWndEdit, WM_SETFONT, (WPARAM32)hFont, bRedraw );
+  SendMessage32A( lphc->hWndLBox, WM_SETFONT, (WPARAM32)hFont, bRedraw );
+
+  GetWindowRect16( lphc->self->hwndSelf, &rect );
+  OffsetRect16( &lphc->RectCombo, rect.left - lphc->RectCombo.left,
+                                  rect.top - lphc->RectCombo.top );
+  CBCalcPlacement( lphc, &lphc->RectEdit,
+                         &lphc->RectButton, &rect );
+  CBResetPos( lphc, &rect, bRedraw );
+}
+
+
+/***********************************************************************
+ *           COMBO_SetItemHeight
+ */
+static LRESULT COMBO_SetItemHeight( LPHEADCOMBO lphc, INT32 index, INT32 height )
+{
+   LRESULT	lRet = CB_ERR;
+
+   if( index == -1 ) /* set text field height */
+   {
+       if( height < 32768 )
+       {
+           RECT16	rect;
+
+           lphc->editHeight = height;
+           GetWindowRect16( lphc->self->hwndSelf, &rect );
+           OffsetRect16( &lphc->RectCombo, rect.left - lphc->RectCombo.left,
+				           rect.top - lphc->RectCombo.top );
+           CBCalcPlacement( lphc, &lphc->RectEdit,
+			          &lphc->RectButton, &rect );
+           CBResetPos( lphc, &rect, TRUE );
+	   lRet = height;
+       }
+   } 
+   else if ( CB_OWNERDRAWN(lphc) )	/* set listbox item height */
+	lRet = SendMessage32A( lphc->hWndLBox, LB_SETITEMHEIGHT32, 
+			      (WPARAM32)index, (LPARAM)height );
+   return lRet;
 }
 
 /***********************************************************************
- *           CBGetText
+ *           COMBO_SelectString
  */
-static LRESULT CBGetText(HWND16 hwnd, WPARAM16 wParam, LPARAM lParam)
+static LRESULT COMBO_SelectString( LPHEADCOMBO lphc, INT32 start, LPCSTR pText )
 {
-    LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
-
-    return SendMessage16(lphc->hWndEdit, WM_GETTEXT, wParam, lParam);   
+   INT32 index = SendMessage32A( lphc->hWndLBox, CB_SELECTSTRING32, 
+				 (WPARAM32)start, (LPARAM)pText );
+   if( index >= 0 )
+        if( lphc->wState & CBF_EDIT )
+	    CBUpdateEdit( lphc, index );
+	else
+	    CBPaintText( lphc, 0 );
+   return (LRESULT)index;
 }
 
 /***********************************************************************
+ *           COMBO_LButtonDown
+ */
+static void COMBO_LButtonDown( LPHEADCOMBO lphc, LPARAM lParam )
+{
+   BOOL32      bButton = PtInRect16(&lphc->RectButton, MAKEPOINT16(lParam));
+   HWND32      hWnd = lphc->self->hwndSelf;
+
+   if( (CB_GETTYPE(lphc) == CBS_DROPDOWNLIST) ||
+       (bButton && (CB_GETTYPE(lphc) == CBS_DROPDOWN)) )
+   {
+       lphc->wState |= CBF_BUTTONDOWN;
+       if( lphc->wState & CBF_DROPPED )
+       {
+	   /* got a click to cancel selection */
+
+           CBRollUp( lphc, TRUE, FALSE );
+	   if( !IsWindow32( hWnd ) ) return;
+
+           if( lphc->wState & CBF_CAPTURE )
+           {
+               lphc->wState &= ~CBF_CAPTURE;
+               ReleaseCapture();
+           }
+           lphc->wState &= ~CBF_BUTTONDOWN;
+       }
+       else
+       {
+	   /* drop down the listbox and start tracking */
+
+           lphc->wState |= CBF_CAPTURE;
+           CBDropDown( lphc );
+           SetCapture32( hWnd );
+       }
+       if( bButton ) CBRepaintButton( lphc );
+   }
+}
+
+/***********************************************************************
+ *           COMBO_LButtonUp
+ *
+ * Release capture and stop tracking if needed.
+ */
+static void COMBO_LButtonUp( LPHEADCOMBO lphc, LPARAM lParam )
+{
+   if( lphc->wState & CBF_CAPTURE )
+   {
+       lphc->wState &= ~CBF_CAPTURE;
+       if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
+       {
+	   INT32 index = CBUpdateLBox( lphc );
+	   CBUpdateEdit( lphc, index );
+       }
+       ReleaseCapture();
+   }
+
+   if( lphc->wState & CBF_BUTTONDOWN )
+   {
+       lphc->wState &= ~CBF_BUTTONDOWN;
+       CBRepaintButton( lphc );
+   }
+}
+
+/***********************************************************************
+ *           COMBO_MouseMove
+ *
+ * Two things to do - track combo button and release capture when
+ * pointer goes into the listbox.
+ */
+static void COMBO_MouseMove( LPHEADCOMBO lphc, WPARAM32 wParam, LPARAM lParam )
+{
+   RECT16	lbRect;
+
+   if( lphc->wState & CBF_BUTTONDOWN )
+   {
+       BOOL32	bButton = PtInRect16(&lphc->RectButton, MAKEPOINT16(lParam));
+
+       if( !bButton )
+       {
+	   lphc->wState &= ~CBF_BUTTONDOWN;
+	   CBRepaintButton( lphc );
+       }
+   }
+
+   GetClientRect16( lphc->hWndLBox, &lbRect );
+   MapWindowPoints16( lphc->self->hwndSelf, 
+		      lphc->hWndLBox, (LPPOINT16)&lParam, 1 );
+   if( PtInRect16(&lbRect, MAKEPOINT16(lParam)) )
+   {
+       lphc->wState &= ~CBF_CAPTURE;
+       ReleaseCapture();
+       if( CB_GETTYPE(lphc) == CBS_DROPDOWN ) CBUpdateLBox( lphc );
+
+       /* hand over pointer tracking */
+       SendMessage32A( lphc->hWndLBox, WM_LBUTTONDOWN, wParam, lParam );
+   }
+}
+
+
+/***********************************************************************
  *           ComboWndProc
+ *
+ * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/ctrl/src/combobox_15.htm
  */
-LRESULT ComboBoxWndProc(HWND16 hwnd, UINT16 message, WPARAM16 wParam, LPARAM lParam)
+LRESULT ComboWndProc(HWND32 hwnd, UINT32 message, WPARAM32 wParam, LPARAM lParam)
 {
-    switch(message) {	
-     case WM_NCCREATE: return CBNCCreate(hwnd, wParam, lParam);
-     case WM_CREATE: return CBCreate(hwnd, wParam, lParam);
-     case WM_DESTROY: return CBDestroy(hwnd, wParam, lParam);
-     case WM_GETDLGCODE: return CBGetDlgCode(hwnd, wParam, lParam);
-     case WM_KEYDOWN: return CBKeyDown(hwnd, wParam, lParam);
-     case WM_CHAR: return CBChar(hwnd, wParam, lParam);
-     case WM_SETFONT: return CBSetFont(hwnd, wParam, lParam);
-     case WM_SETREDRAW: return CBSetRedraw(hwnd, wParam, lParam);
-     case WM_PAINT: return CBPaint(hwnd, wParam, lParam);
-     case WM_GETTEXT: return CBGetText( hwnd, wParam, lParam);
-     case WM_LBUTTONDOWN: return CBLButtonDown(hwnd, wParam, lParam);
-     case WM_SETFOCUS: return CBSetFocus(hwnd, wParam, lParam);
-     case WM_KILLFOCUS: return CBKillFocus(hwnd, wParam, lParam);
-     case WM_SIZE: return CBCheckSize(hwnd);
-     case WM_COMMAND: return CBCommand(hwnd, wParam, lParam);
-     case CB_RESETCONTENT16: return CBResetContent(hwnd, wParam, lParam);
-     case CB_DIR16: return CBDir(hwnd, wParam, lParam);
-     case CB_ADDSTRING16: return CBAddString(hwnd, wParam, lParam);
-     case CB_INSERTSTRING16: return CBInsertString(hwnd, wParam, lParam);
-     case CB_DELETESTRING16: return CBDeleteString(hwnd, wParam, lParam);
-     case CB_FINDSTRING16: return CBFindString(hwnd, wParam, lParam);
-     case CB_GETCOUNT16: return CBGetCount(hwnd, wParam, lParam);
-     case CB_GETCURSEL16: return CBGetCurSel(hwnd, wParam, lParam);
-     case CB_GETITEMDATA16: return CBGetItemData(hwnd, wParam, lParam);
-     case CB_GETITEMHEIGHT16: return CBGetItemHeight(hwnd, wParam, lParam);
-     case CB_GETLBTEXT16: return CBGetLBText(hwnd, wParam, lParam);
-     case CB_GETLBTEXTLEN16: return CBGetLBTextLen(hwnd, wParam, lParam);
-     case CB_SELECTSTRING16: return CBSelectString(hwnd, wParam, lParam);
-     case CB_SETITEMDATA16: return CBSetItemData(hwnd, wParam, lParam);
-     case CB_SETCURSEL16: return CBSetCurSel(hwnd, wParam, lParam);
-     case CB_SETITEMHEIGHT16: return CBSetItemHeight(hwnd, wParam, lParam);
-     case CB_SHOWDROPDOWN16: return CBShowDropDown(hwnd, wParam, lParam);
-     case CB_GETEDITSEL16: return CBGetEditSel(hwnd, wParam, lParam);
-     case CB_SETEDITSEL16: return CBSetEditSel(hwnd, wParam, lParam);
-     case CB_FINDSTRINGEXACT16: return CBFindStringExact(hwnd, wParam, lParam);
+    WND*	pWnd = WIN_FindWndPtr(hwnd);
+   
+    if( pWnd )
+    {
+      LPHEADCOMBO	lphc = CB_GETPTR(pWnd);
+
+      dprintf_combo( stddeb, "Combo [%04x]: msg %s wp %08x lp %08lx\n",
+                     pWnd->hwndSelf, SPY_GetMsgName(message), wParam, lParam );
+
+      if( lphc || message == WM_NCCREATE )
+      switch(message) 
+      {	
+
+	/* System messages */
+
+     	case WM_NCCREATE: 
+		return COMBO_NCCreate(pWnd, lParam);
+
+     	case WM_NCDESTROY: 
+		COMBO_NCDestroy(lphc);
+		break;
+
+     	case WM_CREATE: 
+		return COMBO_Create(lphc, pWnd, lParam);
+
+     	case WM_PAINT:
+		/* wParam may contain a valid HDC! */
+		return COMBO_Paint(lphc, (HDC16)wParam);
+
+	case WM_ERASEBKGND:
+		return TRUE;
+
+     	case WM_GETDLGCODE: 
+		return (LRESULT)(DLGC_WANTARROWS | DLGC_WANTCHARS);
+
+	case WM_SIZE:
+	        if( lphc->hWndLBox && 
+		  !(lphc->wState & CBF_NORESIZE) ) COMBO_Size( lphc );
+		return TRUE;
+
+	case WM_SETFONT:
+		COMBO_Font( lphc, (HFONT16)wParam, (BOOL32)lParam );
+		return TRUE;
+
+	case WM_GETFONT:
+		return (LRESULT)lphc->hFont;
+
+	case WM_SETFOCUS:
+		if( lphc->wState & CBF_EDIT )
+		    SetFocus32( lphc->hWndEdit );
+		else
+		    COMBO_SetFocus( lphc );
+		return TRUE;
+
+	case WM_KILLFOCUS:
+#define hwndFocus ((HWND16)wParam)
+		if( !hwndFocus ||
+		    (hwndFocus != lphc->hWndEdit && hwndFocus != lphc->hWndLBox ))
+		    COMBO_KillFocus( lphc );
+#undef hwndFocus
+		return TRUE;
+
+	case WM_COMMAND:
+		return COMBO_Command( lphc, wParam, (HWND32)lParam );
+
+	case WM_GETTEXT:
+		return COMBO_GetText( lphc, (UINT32)wParam, (LPSTR)lParam );
+
+	case WM_SETTEXT:
+	case WM_GETTEXTLENGTH:
+	case WM_CLEAR:
+	case WM_CUT:
+        case WM_PASTE:
+	case WM_COPY:
+		if( lphc->wState & CBF_EDIT )
+		    return SendMessage32A( lphc->hWndEdit, message, wParam, lParam );
+		return CB_ERR;
+
+	case WM_DRAWITEM:
+	case WM_DELETEITEM:
+	case WM_COMPAREITEM:
+	case WM_MEASUREITEM:
+		return COMBO_ItemOp32( lphc, message, wParam, lParam );
+
+	case WM_ENABLE:
+		if( lphc->wState & CBF_EDIT )
+		    EnableWindow32( lphc->hWndEdit, (BOOL32)wParam ); 
+		EnableWindow32( lphc->hWndLBox, (BOOL32)wParam );
+		return TRUE;
+
+	case WM_SETREDRAW:
+		if( lphc->wState & CBF_EDIT )
+		    SendMessage32A( lphc->hWndEdit, message, wParam, lParam );
+		SendMessage32A( lphc->hWndLBox, message, wParam, lParam );
+		break;
+		
+	case WM_SYSKEYDOWN:
+		if( KEYDATA_ALT & HIWORD(lParam) )
+		    if( wParam == VK_UP || wParam == VK_DOWN )
+			COMBO_FlipListbox( lphc, TRUE );
+		break;
+
+	case WM_CHAR:
+	case WM_KEYDOWN:
+		if( lphc->wState & CBF_EDIT )
+		    return SendMessage32A( lphc->hWndEdit, message, wParam, lParam );
+		else
+		    return SendMessage32A( lphc->hWndLBox, message, wParam, lParam );
+
+	case WM_LBUTTONDOWN: 
+		if( !(lphc->wState & CBF_FOCUSED) ) SetFocus32( lphc->self->hwndSelf );
+		if( lphc->wState & CBF_FOCUSED ) COMBO_LButtonDown( lphc, lParam );
+		return TRUE;
+
+	case WM_LBUTTONUP:
+		COMBO_LButtonUp( lphc, lParam );
+		return TRUE;
+
+	case WM_MOUSEMOVE: 
+		if( lphc->wState & CBF_CAPTURE ) 
+		    COMBO_MouseMove( lphc, wParam, lParam );
+		return TRUE;
+
+	/* Combo messages */
+
+	case CB_ADDSTRING16:
+		if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+	case CB_ADDSTRING32:
+		return SendMessage32A( lphc->hWndLBox, LB_ADDSTRING32, 0, lParam);
+
+	case CB_INSERTSTRING16:
+		wParam = (INT32)(INT16)wParam;
+		if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+	case CB_INSERTSTRING32:
+		return SendMessage32A( lphc->hWndLBox, LB_INSERTSTRING32, wParam, lParam);
+
+	case CB_DELETESTRING16:
+	case CB_DELETESTRING32:
+		return SendMessage32A( lphc->hWndLBox, LB_DELETESTRING32, wParam, 0);
+
+	case CB_SELECTSTRING16:
+		wParam = (INT32)(INT16)wParam;
+		if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+	case CB_SELECTSTRING32:
+		return COMBO_SelectString( lphc, (INT32)wParam, (LPSTR)lParam );
+
+	case CB_FINDSTRING16:
+		wParam = (INT32)(INT16)wParam;
+		if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+	case CB_FINDSTRING32:
+		return SendMessage32A( lphc->hWndLBox, LB_FINDSTRING32, wParam, lParam);
+
+	case CB_FINDSTRINGEXACT16:
+		wParam = (INT32)(INT16)wParam;
+		if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+	case CB_FINDSTRINGEXACT32:
+		return SendMessage32A( lphc->hWndLBox, LB_FINDSTRINGEXACT32, 
+						       wParam, lParam );
+	case CB_SETITEMHEIGHT16:
+		wParam = (INT32)(INT16)wParam;
+	case CB_SETITEMHEIGHT32:
+		return COMBO_SetItemHeight( lphc, (INT32)wParam, (INT32)lParam);
+
+	case CB_RESETCONTENT16: 
+	case CB_RESETCONTENT32:
+		SendMessage32A( lphc->hWndLBox, LB_RESETCONTENT32, 0, 0 );
+		CBPaintText( lphc, 0 );
+		return TRUE;
+
+	case CB_INITSTORAGE32:
+		return SendMessage32A( lphc->hWndLBox, LB_INITSTORAGE32, wParam, lParam);
+
+	case CB_GETHORIZONTALEXTENT32:
+		return SendMessage32A( lphc->hWndLBox, LB_GETHORIZONTALEXTENT32, 0, 0);
+
+	case CB_SETHORIZONTALEXTENT32:
+		return SendMessage32A( lphc->hWndLBox, LB_SETHORIZONTALEXTENT32, wParam, 0);
+
+	case CB_GETTOPINDEX32:
+		return SendMessage32A( lphc->hWndLBox, LB_GETTOPINDEX32, 0, 0);
+
+	case CB_GETLOCALE32:
+		return SendMessage32A( lphc->hWndLBox, LB_GETLOCALE32, 0, 0);
+
+	case CB_SETLOCALE32:
+		return SendMessage32A( lphc->hWndLBox, LB_SETLOCALE32, wParam, 0);
+
+	case CB_GETDROPPEDWIDTH32:
+		if( lphc->droppedWidth )
+		    return lphc->droppedWidth;
+		return lphc->RectCombo.right - lphc->RectCombo.left - 
+		           (lphc->wState & CBF_EDIT) ? CBitOffset : 0;
+
+	case CB_SETDROPPEDWIDTH32:
+		if( (CB_GETTYPE(lphc) != CBS_SIMPLE) &&
+		    (INT32)wParam < 32768 ) lphc->droppedWidth = (INT32)wParam;
+		return CB_ERR;
+
+	case CB_GETDROPPEDCONTROLRECT16:
+		lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+		if( lParam ) 
+		{
+		    RECT32	r;
+		    CBGetDroppedControlRect32( lphc, &r );
+		    CONV_RECT32TO16( &r, (LPRECT16)lParam );
+		}
+		return CB_OKAY;
+
+	case CB_GETDROPPEDCONTROLRECT32:
+		if( lParam ) CBGetDroppedControlRect32(lphc, (LPRECT32)lParam );
+		return CB_OKAY;
+
+	case CB_GETDROPPEDSTATE16:
+	case CB_GETDROPPEDSTATE32:
+		return (lphc->wState & CBF_DROPPED) ? TRUE : FALSE;
+
+	case CB_DIR16: 
+                lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+                /* fall through */
+	case CB_DIR32:
+		return COMBO_Directory( lphc, (UINT32)wParam, 
+				       (LPSTR)lParam, (message == CB_DIR32));
+	case CB_SHOWDROPDOWN16:
+	case CB_SHOWDROPDOWN32:
+		if( CB_GETTYPE(lphc) != CBS_SIMPLE )
+		    if( wParam )
+		    {
+			if( !(lphc->wState & CBF_DROPPED) )
+			    CBDropDown( lphc );
+		    }
+		    else 
+			if( lphc->wState & CBF_DROPPED ) 
+		            CBRollUp( lphc, FALSE, TRUE );
+		return TRUE;
+
+	case CB_GETCOUNT16: 
+	case CB_GETCOUNT32:
+		return SendMessage32A( lphc->hWndLBox, LB_GETCOUNT32, 0, 0);
+
+	case CB_GETCURSEL16: 
+	case CB_GETCURSEL32:
+		return SendMessage32A( lphc->hWndLBox, LB_GETCURSEL32, 0, 0);
+
+	case CB_SETCURSEL16:
+		wParam = (INT32)(INT16)wParam;
+	case CB_SETCURSEL32:
+		return SendMessage32A( lphc->hWndLBox, LB_SETCURSEL32, wParam, 0);
+
+	case CB_GETLBTEXT16: 
+		wParam = (INT32)(INT16)wParam;
+		lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+	case CB_GETLBTEXT32:
+		return SendMessage32A( lphc->hWndLBox, LB_GETTEXT32, wParam, lParam);
+
+	case CB_GETLBTEXTLEN16: 
+		wParam = (INT32)(INT16)wParam;
+	case CB_GETLBTEXTLEN32:
+		return SendMessage32A( lphc->hWndLBox, LB_GETTEXTLEN32, wParam, 0);
+
+	case CB_GETITEMDATA16:
+		wParam = (INT32)(INT16)wParam;
+	case CB_GETITEMDATA32:
+		return SendMessage32A( lphc->hWndLBox, LB_GETITEMDATA32, wParam, 0);
+
+	case CB_SETITEMDATA16:
+		wParam = (INT32)(INT16)wParam;
+	case CB_SETITEMDATA32:
+		return SendMessage32A( lphc->hWndLBox, LB_SETITEMDATA32, wParam, lParam);
+
+	case CB_GETEDITSEL16: 
+		wParam = lParam = 0;   /* just in case */
+	case CB_GETEDITSEL32:
+		if( lphc->wState & CBF_EDIT )
+		{
+		    INT32	a, b;
+
+		    return SendMessage32A( lphc->hWndEdit, EM_GETSEL32,
+					   (wParam) ? wParam : (WPARAM32)&a,
+					   (lParam) ? lParam : (LPARAM)&b );
+		}
+		return CB_ERR;
+
+	case CB_SETEDITSEL16: 
+	case CB_SETEDITSEL32:
+		if( lphc->wState & CBF_EDIT ) 
+		    return SendMessage32A( lphc->hWndEdit, EM_SETSEL32, 
+			  (INT32)(INT16)LOWORD(lParam), (INT32)(INT16)HIWORD(lParam) );
+		return CB_ERR;
+
+	case CB_SETEXTENDEDUI16:
+	case CB_SETEXTENDEDUI32:
+		if( CB_GETTYPE(lphc) == CBS_SIMPLE ) return CB_ERR;
+
+		if( wParam )
+		    lphc->wState |= CBF_EUI;
+		else lphc->wState &= ~CBF_EUI;
+		return CB_OKAY;
+
+	case CB_GETEXTENDEDUI16:
+	case CB_GETEXTENDEDUI32:
+		return (lphc->wState & CBF_EUI) ? TRUE : FALSE;
+
+	case (WM_USER + 0x1B):
+	        dprintf_combo(stddeb,"Combo [%04x]: undocumented msg!\n", (HWND16)hwnd );
     }
-    return DefWindowProc16(hwnd, message, wParam, lParam);
-}
-
-/*--------------------------------------------------------------------*/
-/* ComboLBox code starts here */
-
-HWND16 CLBoxGetCombo(HWND16 hwnd)
-{
-  return (HWND16)GetWindowLong32A(hwnd,0);
-}
-
-LPHEADLIST CLBoxGetListHeader(HWND16 hwnd)
-{
-  return ComboGetListHeader(CLBoxGetCombo(hwnd));
-}
-
-/***********************************************************************
- *           CBLCreate
- */
-static LRESULT CBLCreate( HWND16 hwnd, WPARAM16 wParam, LPARAM lParam )
-{
-  CREATESTRUCT16 *createStruct = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
-  SetWindowLong32A(hwnd,0,(LONG)createStruct->lpCreateParams);
-  return 0;
-}
-
-/***********************************************************************
- *           CBLGetDlgCode
- */
-static LRESULT CBLGetDlgCode( HWND16 hwnd, WPARAM16 wParam, LPARAM lParam )
-{
-  return DLGC_WANTARROWS | DLGC_WANTCHARS;
-}
-
-/***********************************************************************
- *           CBLKeyDown
- */
-static LRESULT CBLKeyDown( HWND16 hwnd, WPARAM16 wParam, LPARAM lParam ) 
-{
-  LPHEADLIST lphl = CLBoxGetListHeader(hwnd);
-  WORD newFocused = lphl->ItemFocused;
-
-  switch(wParam) {
-  case VK_HOME:
-    newFocused = 0;
-    break;
-  case VK_END:
-    newFocused = lphl->ItemsCount - 1;
-    break;
-  case VK_UP:
-    if (newFocused > 0) newFocused--;
-    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;
+    return DefWindowProc32A(hwnd, message, wParam, lParam);
   }
-
-  if (newFocused >= lphl->ItemsCount)
-    newFocused = lphl->ItemsCount - 1;
-  
-  ListBoxSetCurSel(lphl, newFocused);
-  ListBoxSendNotification(lphl, CBN_SELCHANGE);
-  SendMessage16(GetParent16(hwnd), WM_COMMAND,ID_CLB,MAKELONG(0,CBN_SELCHANGE));
-  lphl->ItemFocused = newFocused;
-  ListBoxScrollToFocus(lphl);
-  SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-  InvalidateRect32( hwnd, NULL, TRUE );
-  return 0;
+  return CB_ERR;
 }
 
-/***********************************************************************
- *           CBLChar
- */
-static LRESULT CBLChar( HWND16 hwnd, WPARAM16 wParam, LPARAM lParam )
-{
-  return 0;
-}
-
-/***********************************************************************
- *           CBLPaint
- */
-static LRESULT CBLPaint( HWND16 hwnd, WPARAM16 wParam, LPARAM lParam )
-{
-  LPHEADLIST   lphl = CLBoxGetListHeader(hwnd);
-  LPLISTSTRUCT lpls;
-  PAINTSTRUCT16  ps;
-  HBRUSH32 hBrush;
-  HFONT32 hOldFont;
-  WND * wndPtr = WIN_FindWndPtr(hwnd);
-  HWND16  combohwnd = CLBoxGetCombo(hwnd);
-  HDC16 hdc;
-  RECT16 rect;
-  int   i, top, height;
-
-  top = 0;
-  if (!lphl)
-    return 0;
-  hdc = BeginPaint16( hwnd, &ps );
-
-  if (!lphl) {
-    fprintf(stdnimp,"CBLPaint: CLBoxGetListHeader returned NULL!\n");
-  }
-  if (!IsWindowVisible16(hwnd) || !lphl || !lphl->bRedrawFlag) {
-    EndPaint16(hwnd, &ps);
-    return 0;
-  }
-
-  hOldFont = SelectObject32(hdc, lphl->hFont);
-  /* listboxes should be white */
-  hBrush = GetStockObject32(WHITE_BRUSH);
-
-  GetClientRect16(hwnd, &rect);
-  FillRect16(hdc, &rect, hBrush);
-  CBLCheckSize(hwnd);
-
-  lpls = lphl->lpFirst;
-
-  lphl->ItemsVisible = 0;
-  for(i = 0; i < lphl->ItemsCount; i++) {
-    if (lpls == NULL) break;
-
-    if (i >= lphl->FirstVisible) {
-      height = lpls->mis.itemHeight;
-      /* must have enough room to draw entire item */
-      if (top > (rect.bottom-height+1)) break;
-
-      lpls->itemRect.top    = top;
-      lpls->itemRect.bottom = top + height;
-      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);
-      if (lphl->OwnerDrawn) {
-	ListBoxDrawItem (combohwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE, 0);
-	if (lpls->itemState)
-	  ListBoxDrawItem (combohwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_SELECT, ODS_SELECTED);
-      } else {
-	ListBoxDrawItem (combohwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE, 
-			 lpls->itemState);
-      }
-      if ((lphl->ItemFocused == i) && GetFocus32() == hwnd)
-	ListBoxDrawItem (combohwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS, ODS_FOCUS);
-
-      top += height;
-      lphl->ItemsVisible++;
-    }
-
-    lpls = lpls->lpNext;
-  }
-
-  if (wndPtr->dwStyle & WS_VSCROLL) 
-      SetScrollRange32(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
-
-  SelectObject32(hdc,hOldFont);
-  EndPaint16( hwnd, &ps );
-  return 0;
-
-}
-
-/***********************************************************************
- *           CBLKillFocus
- */
-static LRESULT CBLKillFocus( HWND16 hwnd, WPARAM16 wParam, LPARAM lParam )
-{
-/*  SendMessage16(CLBoxGetCombo(hwnd),CB_SHOWDROPDOWN16,0,0);*/
-  return 0;
-}
-
-/***********************************************************************
- *           CBLActivate
- */
-static LRESULT CBLActivate( HWND16 hwnd, WPARAM16 wParam, LPARAM lParam )
-{
-  if (wParam == WA_INACTIVE)
-    SendMessage16(CLBoxGetCombo(hwnd),CB_SHOWDROPDOWN16,0,0);
-  return 0;
-}
-
-/***********************************************************************
- *           CBLLButtonDown
- */
-static LRESULT CBLLButtonDown( HWND16 hwnd, WPARAM16 wParam, LPARAM lParam )
-{
-  LPHEADLIST lphl = CLBoxGetListHeader(hwnd);
-  int        y;
-  RECT16     rectsel;
-
-/*  SetFocus32(hwnd); */
-  SetCapture32(hwnd);
-
-  lphl->PrevFocused = lphl->ItemFocused;
-
-  y = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
-  if (y == -1)
-    return 0;
-
-  ListBoxSetCurSel(lphl, y);
-  ListBoxGetItemRect(lphl, y, &rectsel);
-
-  InvalidateRect32( hwnd, NULL, TRUE );
-  return 0;
-}
-
-/***********************************************************************
- *           CBLLButtonUp
- */
-static LRESULT CBLLButtonUp( HWND16 hwnd, WPARAM16 wParam, LPARAM lParam )
-{
-  LPHEADLIST lphl = CLBoxGetListHeader(hwnd);
-
-  if (GetCapture32() == hwnd) ReleaseCapture();
-
-  if(!lphl)
-     {
-      fprintf(stdnimp,"CBLLButtonUp: CLBoxGetListHeader returned NULL!\n");
-     }
-  else if (lphl->PrevFocused != lphl->ItemFocused) 
-          {
-      		SendMessage16(CLBoxGetCombo(hwnd),CB_SETCURSEL16,lphl->ItemFocused,0);
-      		SendMessage16(GetParent16(hwnd), WM_COMMAND,ID_CLB,MAKELONG(0,CBN_SELCHANGE));
-      		ListBoxSendNotification(lphl, CBN_SELCHANGE);
-     	  }
-
-  SendMessage16(CLBoxGetCombo(hwnd),CB_SHOWDROPDOWN16,0,0);
-
-  return 0;
-}
-
-/***********************************************************************
- *           CBLMouseMove
- */
-static LRESULT CBLMouseMove( HWND16 hwnd, WPARAM16 wParam, LPARAM lParam )
-{
-  LPHEADLIST lphl = CLBoxGetListHeader(hwnd);
-  short y;
-  WORD wRet;
-  RECT16 rect, rectsel;
-
-  y = SHIWORD(lParam);
-  wRet = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
-  ListBoxGetItemRect(lphl, wRet, &rectsel);
-  GetClientRect16(hwnd, &rect);
-
-  dprintf_combo(stddeb,"CBLMouseMove: hwnd %04x wp %x lp %lx  y %d  if %d wret %d %d,%d-%d,%d\n",
-hwnd,wParam,lParam,y,lphl->ItemFocused,wRet,rectsel.left,rectsel.top,rectsel.right,rectsel.bottom);
-  
-  if ((wParam & MK_LBUTTON) != 0) {
-    if (y < CBLMM_EDGE) {
-      if (lphl->FirstVisible > 0) {
-	lphl->FirstVisible--;
-	SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-	ListBoxSetCurSel(lphl, wRet);
-	InvalidateRect32( hwnd, NULL, TRUE );
-	return 0;
-      }
-    }
-    else if (y >= (rect.bottom-CBLMM_EDGE)) {
-      if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
-	lphl->FirstVisible++;
-	SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-	ListBoxSetCurSel(lphl, wRet);
-	InvalidateRect32( hwnd, NULL, TRUE );
-	return 0;
-      }
-    }
-    else {
-      if ((short) wRet == lphl->ItemFocused) return 0;
-      ListBoxSetCurSel(lphl, wRet);
-      InvalidateRect32( hwnd, NULL, TRUE );
-    }
-  }
-
-  return 0;
-}
-
-/***********************************************************************
- *           CBLVScroll
- */
-static LRESULT CBLVScroll( HWND16 hwnd, WPARAM16 wParam, LPARAM lParam )
-{
-  LPHEADLIST lphl = CLBoxGetListHeader(hwnd);
-  int  y;
-
-  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;
-}
-
-
-/***********************************************************************
- *             CBLCheckSize
- */
-static BOOL32 CBLCheckSize(HWND16 hwnd)
-{
-  LPHEADCOMBO  lphc = ComboGetStorageHeader(hwnd);
-  LPHEADLIST   lphl = ComboGetListHeader(hwnd);
-  LPLISTSTRUCT lpls;
-  HWND16         hWndLBox;
-  RECT16 cRect,wRect,lRect,lwRect;
-  int totheight,dw;
-  char className[80];
-
-  GetClassName32A(hwnd,className,80);
-  fflush(stddeb);
-  if (strncmp(className,"COMBOBOX",8)) return FALSE;
-  if ((hWndLBox = lphc->hWndLBox) == 0) return FALSE;
-  dprintf_combo(stddeb,"CBLCheckSize headers hw %04x  lb %04x  name %s\n",
-		hwnd,hWndLBox,className);
-
-  GetClientRect16(hwnd,&cRect);
-  GetWindowRect16(hwnd,&wRect);
-  GetClientRect16(hWndLBox,&lRect);
-  GetWindowRect16(hWndLBox,&lwRect);
-
-  dprintf_combo(stddeb,"CBLCheckSize: init cRect %d,%d-%d,%d  wRect %d,%d-%d,%d\n",
-		cRect.left,cRect.top,cRect.right,cRect.bottom,
-		wRect.left,wRect.top,wRect.right,wRect.bottom);
-  dprintf_combo(stddeb,"                   lRect %d,%d-%d,%d  lwRect %d,%d-%d,%d\n",
-	      lRect.left,lRect.top,lRect.right,lRect.bottom,
-	      lwRect.left,lwRect.top,lwRect.right,lwRect.bottom);
-  fflush(stddeb);
-  
-  totheight = 0;
-  for (lpls=lphl->lpFirst; lpls != NULL; lpls=lpls->lpNext)
-    totheight += lpls->mis.itemHeight;
-
-  dw = cRect.right-cRect.left+2*SYSMETRICS_CXBORDER+SYSMETRICS_CXVSCROLL;
-  dw -= lwRect.right-lwRect.left;
-  dw -= SYSMETRICS_CXVSCROLL;
-
-  /* TODO: This isn't really what windows does */
-  if ((lRect.bottom-lRect.top < 3*lphl->StdItemHeight) || dw) {
-    dprintf_combo(stddeb,"    Changing; totHeight %d  StdItemHght %d  dw %d\n",
-		  totheight,lphl->StdItemHeight,dw);
-    SetWindowPos32(hWndLBox, 0, lRect.left, lRect.top, 
-		 lwRect.right-lwRect.left+dw, totheight+2*SYSMETRICS_CYBORDER, 
-		 SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE );
-  }
-  return TRUE;
-}
-
-
-/***********************************************************************
- *           ComboLBoxWndProc
- */
-LRESULT ComboLBoxWndProc(HWND16 hwnd, UINT16 message, WPARAM16 wParam, LPARAM lParam)
-{
-    switch(message) {	
-     case WM_CREATE: return CBLCreate(hwnd, wParam, lParam);
-     case WM_GETDLGCODE: return CBLGetDlgCode(hwnd, wParam, lParam);
-     case WM_KEYDOWN: return CBLKeyDown(hwnd, wParam, lParam);
-     case WM_CHAR: return CBLChar(hwnd, wParam, lParam);
-     case WM_PAINT: return CBLPaint(hwnd, wParam, lParam);
-     case WM_KILLFOCUS: return CBLKillFocus(hwnd, wParam, lParam);
-     case WM_ACTIVATE: return CBLActivate(hwnd, wParam, lParam);
-     case WM_LBUTTONDOWN: return CBLLButtonDown(hwnd, wParam, lParam);
-     case WM_LBUTTONUP: return CBLLButtonUp(hwnd, wParam, lParam);
-     case WM_MOUSEMOVE: return CBLMouseMove(hwnd, wParam, lParam);
-     case WM_VSCROLL: return CBLVScroll(hwnd, wParam, lParam);
-     case WM_SIZE: return CBLCheckSize(hwnd);
-     case WM_MOUSEACTIVATE:  /* We don't want to be activated */
-	return MA_NOACTIVATE;
-    }
-    return DefWindowProc16(hwnd, message, wParam, lParam);
-}
diff --git a/controls/edit.c b/controls/edit.c
index 3187698..6f6f5ce 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -13,11 +13,13 @@
  *
  */
 
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "windows.h"
 #include "win.h"
+#include "combo.h"
 #include "local.h"
 #include "resource.h"
 #include "stddebug.h"
@@ -35,6 +37,9 @@
 #define GROWLENGTH		64	/* buffers grow by this much */
 #define HSCROLL_FRACTION	3	/* scroll window by 1/3 width */
 
+#define EF_TEXTCHANGED		0x0001
+#define EF_FOCUSED		0x0002
+
 typedef enum
 {
 	END_0 = 0,
@@ -86,13 +91,12 @@
 	INT32 AveCharWidth;	/* average character width in pixels */
 	INT32 BufLimit;
 	INT32 BufSize;
-	BOOL32 TextChanged;
+	UINT32 eState;		/* EF flags */
 	INT32 UndoInsertLen;
 	INT32 UndoPos;
 	INT32 UndoBufSize;
 	HLOCAL32 hUndoBuf;
 	LPSTR UndoText;
-	BOOL32 Redraw;
 	INT32 SelStart;		/* offset of selection start, == SelEnd if no selection */
 	INT32 SelEnd;		/* offset of selection end == current caret position */
 	INT32 NumTabStops;
@@ -126,6 +130,7 @@
 #define IsPassword(wndPtr) ((wndPtr)->dwStyle & ES_PASSWORD)
 #define IsLower(wndPtr) ((wndPtr)->dwStyle & ES_LOWERCASE)
 #define IsUpper(wndPtr) ((wndPtr)->dwStyle & ES_UPPERCASE)
+#define IsNoRedraw(wndPtr) ((wndPtr)->flags & WIN_NO_REDRAW)
 
 #define EDITSTATEPTR(wndPtr) (*(EDITSTATE **)((wndPtr)->wExtra))
 
@@ -145,7 +150,6 @@
 		 "edit: 32 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
 		 (UINT32)hwnd, (UINT32)wParam, (UINT32)lParam)
 
-
 /*********************************************************************
  *
  *	Declarations
@@ -166,7 +170,6 @@
 static void    EDIT_GetLineRect(WND *wndPtr, INT32 line, INT32 scol, INT32 ecol, LPRECT32 rc);
 static LPSTR   EDIT_GetPointer(WND *wndPtr);
 static LPSTR   EDIT_GetPasswordPointer(WND *wndPtr);
-static BOOL32  EDIT_GetRedraw(WND *wndPtr);
 static void    EDIT_GetSel(WND *wndPtr, LPINT32 s, LPINT32 e);
 static INT32   EDIT_GetTextWidth(WND *wndPtr);
 static LPSTR   EDIT_GetUndoPointer(WND *wndPtr);
@@ -196,39 +199,39 @@
 static INT32   EDIT_WndYFromLine(WND *wndPtr, INT32 line);
 static INT32   EDIT_WordBreakProc(LPSTR s, INT32 index, INT32 count, INT32 action);
 
-static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_CanUndo(WND *wndPtr);
 static LRESULT EDIT_EM_CharFromPos(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_GetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr);
+static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam);
+static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr);
+static LRESULT EDIT_EM_GetHandle(WND *wndPtr);
+static LRESULT EDIT_EM_GetHandle16(WND *wndPtr);
 static LRESULT EDIT_EM_GetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetLineCount(WND *wndPtr);
 static LRESULT EDIT_EM_GetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetModify(WND *wndPtr);
+static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr);
 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_GetRect16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetThumb(WND *wndPtr);
 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam);
+static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam);
+static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam);
 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_PosFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_PosFromChar(WND *wndPtr, WPARAM32 wParam);
 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_ScrollCaret(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_SetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam);
+static LRESULT EDIT_EM_ScrollCaret(WND *wndPtr);
+static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam);
+static LRESULT EDIT_EM_SetHandle16(WND *wndPtr, WPARAM32 wParam);
 static LRESULT EDIT_EM_SetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_SetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam);
+static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam);
+static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam);
 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
@@ -236,36 +239,36 @@
 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_SetTabStops16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_Undo(WND *wndPtr);
 
 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_WM_Clear(WND *wndPtr);
 static LRESULT EDIT_WM_Command(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_WM_ContextMenu(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_WM_Copy(WND *wndPtr);
+static LRESULT EDIT_WM_Cut(WND *wndPtr);
 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_WM_Destroy(WND *wndPtr);
+static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam);
+static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam);
+static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr);
+static LRESULT EDIT_WM_GetFont(WND *wndPtr);
 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_WM_GetTextLength(WND *wndPtr);
 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_WM_InitMenuPopup(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam);
 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam);
+static LRESULT EDIT_WM_Paste(WND *wndPtr);
 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam);
 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam);
 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_WM_SysKeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
@@ -368,7 +371,7 @@
 		/* fall through */
 	case EM_SCROLL32:
 		DPRINTF_EDIT_MSG32("EM_SCROLL");
-		lResult = EDIT_EM_Scroll(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_Scroll(wndPtr, wParam);
  		break;
 
 	case EM_LINESCROLL16:
@@ -386,7 +389,7 @@
 		/* fall through */
 	case EM_SCROLLCARET32:
 		DPRINTF_EDIT_MSG32("EM_SCROLLCARET");
-		lResult = EDIT_EM_ScrollCaret(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_ScrollCaret(wndPtr);
 		break;
 
 	case EM_GETMODIFY16:
@@ -394,7 +397,7 @@
 		/* fall through */
 	case EM_GETMODIFY32:
 		DPRINTF_EDIT_MSG32("EM_GETMODIFY");
-		lResult = EDIT_EM_GetModify(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_GetModify(wndPtr);
 		break;
 
 	case EM_SETMODIFY16:
@@ -402,7 +405,7 @@
 		/* fall through */
 	case EM_SETMODIFY32:
 		DPRINTF_EDIT_MSG32("EM_SETMODIFY");
-		lResult = EDIT_EM_SetModify(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_SetModify(wndPtr, wParam);
 		break;
 
 	case EM_GETLINECOUNT16:
@@ -410,7 +413,7 @@
 		/* fall through */
 	case EM_GETLINECOUNT32:
 		DPRINTF_EDIT_MSG32("EM_GETLINECOUNT");
-		lResult = EDIT_EM_GetLineCount(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_GetLineCount(wndPtr);
 		break;
 
 	case EM_LINEINDEX16:
@@ -418,25 +421,25 @@
 		/* fall through */
 	case EM_LINEINDEX32:
 		DPRINTF_EDIT_MSG32("EM_LINEINDEX");
-		lResult = EDIT_EM_LineIndex(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_LineIndex(wndPtr, wParam);
 		break;
 
 	case EM_SETHANDLE16:
 		DPRINTF_EDIT_MSG16("EM_SETHANDLE");
-		lResult = EDIT_EM_SetHandle16(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_SetHandle16(wndPtr, wParam);
 		break;
 	case EM_SETHANDLE32:
 		DPRINTF_EDIT_MSG32("EM_SETHANDLE");
-		lResult = EDIT_EM_SetHandle(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_SetHandle(wndPtr, wParam);
 		break;
 
 	case EM_GETHANDLE16:
 		DPRINTF_EDIT_MSG16("EM_GETHANDLE");
-		lResult = EDIT_EM_GetHandle16(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_GetHandle16(wndPtr);
 		break;
 	case EM_GETHANDLE32:
 		DPRINTF_EDIT_MSG32("EM_GETHANDLE");
-		lResult = EDIT_EM_GetHandle(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_GetHandle(wndPtr);
 		break;
 
 	case EM_GETTHUMB16:
@@ -444,7 +447,7 @@
 		/* fall through */
 	case EM_GETTHUMB32:
 		DPRINTF_EDIT_MSG32("EM_GETTHUMB");
-		lResult = EDIT_EM_GetThumb(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_GetThumb(wndPtr);
 		break;
 
 	/* messages 0x00bf and 0x00c0 missing from specs */
@@ -470,7 +473,7 @@
 		/* fall through */
 	case EM_LINELENGTH32:
 		DPRINTF_EDIT_MSG32("EM_LINELENGTH");
-		lResult = EDIT_EM_LineLength(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_LineLength(wndPtr, wParam);
 		break;
 
 	case EM_REPLACESEL16:
@@ -514,7 +517,7 @@
 		/* fall through */
 	case EM_CANUNDO32:
 		DPRINTF_EDIT_MSG32("EM_CANUNDO");
-		lResult = EDIT_EM_CanUndo(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_CanUndo(wndPtr);
 		break;
 
 	case EM_UNDO16:
@@ -524,7 +527,7 @@
 		/* fall through */
 	case WM_UNDO:
 		DPRINTF_EDIT_MSG32("EM_UNDO / WM_UNDO");
-		lResult = EDIT_EM_Undo(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_Undo(wndPtr);
 		break;
 
 	case EM_FMTLINES16:
@@ -532,7 +535,7 @@
 		/* fall through */
 	case EM_FMTLINES32:
 		DPRINTF_EDIT_MSG32("EM_FMTLINES");
-		lResult = EDIT_EM_FmtLines(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_FmtLines(wndPtr, wParam);
 		break;
 
 	case EM_LINEFROMCHAR16:
@@ -540,7 +543,7 @@
 		/* fall through */
 	case EM_LINEFROMCHAR32:
 		DPRINTF_EDIT_MSG32("EM_LINEFROMCHAR");
-		lResult = EDIT_EM_LineFromChar(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_LineFromChar(wndPtr, wParam);
 		break;
 
 	/* message 0x00ca missing from specs */
@@ -567,7 +570,7 @@
 		/* fall through */
 	case EM_SETPASSWORDCHAR32:
 		DPRINTF_EDIT_MSG32("EM_SETPASSWORDCHAR");
-		lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam);
 		break;
 
 	case EM_EMPTYUNDOBUFFER16:
@@ -575,7 +578,7 @@
 		/* fall through */
 	case EM_EMPTYUNDOBUFFER32:
 		DPRINTF_EDIT_MSG32("EM_EMPTYUNDOBUFFER");
-		lResult = EDIT_EM_EmptyUndoBuffer(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_EmptyUndoBuffer(wndPtr);
 		break;
 
 	case EM_GETFIRSTVISIBLELINE16:
@@ -583,7 +586,7 @@
 		/* fall through */
 	case EM_GETFIRSTVISIBLELINE32:
 		DPRINTF_EDIT_MSG32("EM_GETFIRSTVISIBLELINE");
-		lResult = EDIT_EM_GetFirstVisibleLine(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_GetFirstVisibleLine(wndPtr);
 		break;
 
 	case EM_SETREADONLY16:
@@ -591,7 +594,7 @@
 		/* fall through */
 	case EM_SETREADONLY32:
 		DPRINTF_EDIT_MSG32("EM_SETREADONLY");
-		lResult = EDIT_EM_SetReadOnly(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_SetReadOnly(wndPtr, wParam);
  		break;
 
 	case EM_SETWORDBREAKPROC16:
@@ -615,7 +618,7 @@
 		/* fall through */
 	case EM_GETPASSWORDCHAR32:
 		DPRINTF_EDIT_MSG32("EM_GETPASSWORDCHAR");
-		lResult = EDIT_EM_GetPasswordChar(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_GetPasswordChar(wndPtr);
 		break;
 
 	/* The following EM_xxx are new to win95 and don't exist for 16 bit */
@@ -637,7 +640,7 @@
 
 	case EM_POSFROMCHAR32:
 		DPRINTF_EDIT_MSG16("EM_POSFROMCHAR");
-		lResult = EDIT_EM_PosFromChar(wndPtr, wParam, lParam);
+		lResult = EDIT_EM_PosFromChar(wndPtr, wParam);
 		break;
 
 	case EM_CHARFROMPOS32:
@@ -647,7 +650,7 @@
 
 	case WM_GETDLGCODE:
 		DPRINTF_EDIT_MSG32("WM_GETDLGCODE");
-		lResult = EDIT_WM_GetDlgCode(wndPtr, wParam, lParam);
+		lResult = EDIT_WM_GetDlgCode(wndPtr);
 		break;
 
 	case WM_CHAR:
@@ -657,7 +660,7 @@
 
 	case WM_CLEAR:
 		DPRINTF_EDIT_MSG32("WM_CLEAR");
-		lResult = EDIT_WM_Clear(wndPtr, wParam, lParam);
+		lResult = EDIT_WM_Clear(wndPtr);
 		break;
 
 	case WM_COMMAND:
@@ -672,7 +675,7 @@
 
 	case WM_COPY:
 		DPRINTF_EDIT_MSG32("WM_COPY");
-		lResult = EDIT_WM_Copy(wndPtr, wParam, lParam);
+		lResult = EDIT_WM_Copy(wndPtr);
 		break;
 
 	case WM_CREATE:
@@ -682,27 +685,27 @@
 
 	case WM_CUT:
 		DPRINTF_EDIT_MSG32("WM_CUT");
-		lResult = EDIT_WM_Cut(wndPtr, wParam, lParam);
+		lResult = EDIT_WM_Cut(wndPtr);
 		break;
 
 	case WM_DESTROY:
 		DPRINTF_EDIT_MSG32("WM_DESTROY");
-		lResult = EDIT_WM_Destroy(wndPtr, wParam, lParam);
+		lResult = EDIT_WM_Destroy(wndPtr);
 		break;
 
 	case WM_ENABLE:
 		DPRINTF_EDIT_MSG32("WM_ENABLE");
-		lResult = EDIT_WM_Enable(wndPtr, wParam, lParam);
+		lResult = EDIT_WM_Enable(wndPtr, wParam);
 		break;
 
 	case WM_ERASEBKGND:
 		DPRINTF_EDIT_MSG32("WM_ERASEBKGND");
-		lResult = EDIT_WM_EraseBkGnd(wndPtr, wParam, lParam);
+		lResult = EDIT_WM_EraseBkGnd(wndPtr, wParam);
 		break;
 
 	case WM_GETFONT:
 		DPRINTF_EDIT_MSG32("WM_GETFONT");
-		lResult = EDIT_WM_GetFont(wndPtr, wParam, lParam);
+		lResult = EDIT_WM_GetFont(wndPtr);
 		break;
 
 	case WM_GETTEXT:
@@ -712,7 +715,7 @@
 
 	case WM_GETTEXTLENGTH:
 		DPRINTF_EDIT_MSG32("WM_GETTEXTLENGTH");
-		lResult = EDIT_WM_GetTextLength(wndPtr, wParam, lParam);
+		lResult = EDIT_WM_GetTextLength(wndPtr);
 		break;
 
 	case WM_HSCROLL:
@@ -732,7 +735,7 @@
 
 	case WM_KILLFOCUS:
 		DPRINTF_EDIT_MSG32("WM_KILLFOCUS");
-		lResult = EDIT_WM_KillFocus(wndPtr, wParam, lParam);
+		lResult = EDIT_WM_KillFocus(wndPtr, wParam);
 		break;
 
 	case WM_LBUTTONDBLCLK:
@@ -759,12 +762,12 @@
 
 	case WM_PAINT:
 		DPRINTF_EDIT_MSG32("WM_PAINT");
-		lResult = EDIT_WM_Paint(wndPtr, wParam, lParam);
+		lResult = EDIT_WM_Paint(wndPtr, wParam);
 		break;
 
 	case WM_PASTE:
 		DPRINTF_EDIT_MSG32("WM_PASTE");
-		lResult = EDIT_WM_Paste(wndPtr, wParam, lParam);
+		lResult = EDIT_WM_Paste(wndPtr);
 		break;
 
 	case WM_SETCURSOR:
@@ -776,7 +779,7 @@
 
 	case WM_SETFOCUS:
 		DPRINTF_EDIT_MSG32("WM_SETFOCUS");
-		lResult = EDIT_WM_SetFocus(wndPtr, wParam, lParam);
+		lResult = EDIT_WM_SetFocus(wndPtr, wParam);
 		break;
 
 	case WM_SETFONT:
@@ -786,7 +789,7 @@
 
 	case WM_SETREDRAW:
 		DPRINTF_EDIT_MSG32("WM_SETREDRAW");
-		lResult = EDIT_WM_SetRedraw(wndPtr, wParam, lParam);
+		lResult = EDIT_WM_SetRedraw(wndPtr, wParam);
 		break;
 
 	case WM_SETTEXT:
@@ -847,14 +850,14 @@
 	LINE_END ending;
 
 	hdc = GetDC32(wndPtr->hwndSelf);
-	hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0);
+	hFont = (HFONT32)EDIT_WM_GetFont(wndPtr);
 	if (hFont) oldFont = SelectObject32(hdc, hFont);
 
 	if (!IsMultiLine(wndPtr)) {
 		es->LineCount = 1;
 		es->LineDefs = xrealloc(es->LineDefs, sizeof(LINEDEF));
 		es->LineDefs[0].offset = 0;
-		es->LineDefs[0].length = EDIT_WM_GetTextLength(wndPtr, 0, 0);
+		es->LineDefs[0].length = EDIT_WM_GetTextLength(wndPtr);
 		es->LineDefs[0].ending = END_0;
 		es->TextWidth = (INT32)LOWORD(GetTabbedTextExtent32A(hdc, text,
 					es->LineDefs[0].length,
@@ -976,9 +979,9 @@
  */
 static INT32 EDIT_ColFromWndX(WND *wndPtr, INT32 line, INT32 x)
 {
-	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
-	INT32 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
-	INT32 ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
+	INT32 li = (INT32)EDIT_EM_LineIndex(wndPtr, line);
+	INT32 ll = (INT32)EDIT_EM_LineLength(wndPtr, li);
 	INT32 i;
 
 	line = MAX(0, MIN(line, lc - 1));
@@ -1000,7 +1003,7 @@
 {
 	EDIT_EM_SetSel(wndPtr, -1, 0);
 	EDIT_MoveEnd(wndPtr, TRUE);
-	EDIT_WM_Clear(wndPtr, 0, 0);
+	EDIT_WM_Clear(wndPtr);
 }
 
 
@@ -1015,7 +1018,7 @@
 {
 	EDIT_EM_SetSel(wndPtr, -1, 0);
 	EDIT_MoveBackward(wndPtr, TRUE);
-	EDIT_WM_Clear(wndPtr, 0, 0);
+	EDIT_WM_Clear(wndPtr);
 }
 
 
@@ -1030,7 +1033,7 @@
 {
 	EDIT_EM_SetSel(wndPtr, -1, 0);
 	EDIT_MoveForward(wndPtr, TRUE);
-	EDIT_WM_Clear(wndPtr, 0, 0);
+	EDIT_WM_Clear(wndPtr);
 }
 
 
@@ -1126,19 +1129,6 @@
 
 /*********************************************************************
  *
- *	EDIT_GetRedraw
- *
- */
-static BOOL32 EDIT_GetRedraw(WND *wndPtr)
-{
-	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-
-	return es->Redraw;
-}
-
-
-/*********************************************************************
- *
  *	EDIT_GetSel
  *
  *	Beware: This is not the function called on EM_GETSEL.
@@ -1242,7 +1232,7 @@
  */
 static void EDIT_InvalidateText(WND *wndPtr, INT32 start, INT32 end)
 {
-	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
 	INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
 	INT32 sl;
 	INT32 el;
@@ -1257,15 +1247,15 @@
 		return;
 
 	if (end == -1)
-		end = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
+		end = (INT32)EDIT_WM_GetTextLength(wndPtr);
 	ORDER_INT32(start, end);
-	sl = (INT32)EDIT_EM_LineFromChar(wndPtr, start, 0);
-	el = (INT32)EDIT_EM_LineFromChar(wndPtr, end, 0);
+	sl = (INT32)EDIT_EM_LineFromChar(wndPtr, start);
+	el = (INT32)EDIT_EM_LineFromChar(wndPtr, end);
 	if ((el < fv) || (sl > fv + vlc))
 		return;
 
-	sc = start - (INT32)EDIT_EM_LineIndex(wndPtr, sl, 0);
-	ec = end - (INT32)EDIT_EM_LineIndex(wndPtr, el, 0);
+	sc = start - (INT32)EDIT_EM_LineIndex(wndPtr, sl);
+	ec = end - (INT32)EDIT_EM_LineIndex(wndPtr, el);
 	if (sl < fv) {
 		sl = fv;
 		sc = 0;
@@ -1273,7 +1263,7 @@
 	if (el > fv + vlc) {
 		el = fv + vlc;
 		ec = (INT32)EDIT_EM_LineLength(wndPtr,
-				(INT32)EDIT_EM_LineIndex(wndPtr, el, 0), 0);
+				(INT32)EDIT_EM_LineIndex(wndPtr, el));
 	}
 	EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rcWnd);
 	if (sl == el) {
@@ -1283,14 +1273,14 @@
 	} else {
 		EDIT_GetLineRect(wndPtr, sl, sc,
 				(INT32)EDIT_EM_LineLength(wndPtr,
-					(INT32)EDIT_EM_LineIndex(wndPtr, sl, 0), 0),
+					(INT32)EDIT_EM_LineIndex(wndPtr, sl)),
 				&rcLine);
 		if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
 			InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE );
 		for (l = sl + 1 ; l < el ; l++) {
 			EDIT_GetLineRect(wndPtr, l, 0,
 				(INT32)EDIT_EM_LineLength(wndPtr,
-					(INT32)EDIT_EM_LineIndex(wndPtr, l, 0), 0),
+					(INT32)EDIT_EM_LineIndex(wndPtr, l)),
 				&rcLine);
 			if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
 				InvalidateRect32(wndPtr->hwndSelf, &rcUpdate, FALSE);
@@ -1311,9 +1301,9 @@
  */
 static INT32 EDIT_LineFromWndY(WND *wndPtr, INT32 y)
 {
-	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
 	INT32 lh = EDIT_GetLineHeight(wndPtr);
-	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
 
 	return MAX(0, MIN(lc - 1, y / lh + fv));
 }
@@ -1429,19 +1419,19 @@
 	INT32 li;
 
 	EDIT_GetSel(wndPtr, &s, &e);
-	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
-	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
 	if (e - li == 0) {
 		if (l) {
-			li = (INT32)EDIT_EM_LineIndex(wndPtr, l - 1, 0);
-			e = li + (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
+			li = (INT32)EDIT_EM_LineIndex(wndPtr, l - 1);
+			e = li + (INT32)EDIT_EM_LineLength(wndPtr, li);
 		}
 	} else
 		e--;
 	if (!extend)
 		s = e;
 	EDIT_SetSel(wndPtr, s, e);
-	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	EDIT_EM_ScrollCaret(wndPtr);
 }
 
 
@@ -1460,19 +1450,19 @@
 	INT32 x;
 
 	EDIT_GetSel(wndPtr, &s, &e);
-	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
-	lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
-	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
+	lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
 	if (l < lc - 1) {
 		x = EDIT_WndXFromCol(wndPtr, l, e - li);
 		l++;
-		e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
+		e = (INT32)EDIT_EM_LineIndex(wndPtr, l) +
 				EDIT_ColFromWndX(wndPtr, l, x);
 	}
 	if (!extend)
 		s = e;
 	EDIT_SetSel(wndPtr, s, e);
-	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	EDIT_EM_ScrollCaret(wndPtr);
 }
 
 
@@ -1490,14 +1480,14 @@
 	INT32 li;
 
 	EDIT_GetSel(wndPtr, &s, &e);
-	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
-	ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
-	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
+	ll = (INT32)EDIT_EM_LineLength(wndPtr, e);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
 	e = li + ll;
 	if (!extend)
 		s = e;
 	EDIT_SetSel(wndPtr, s, e);
-	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	EDIT_EM_ScrollCaret(wndPtr);
 }
 
 
@@ -1516,19 +1506,19 @@
 	INT32 li;
 
 	EDIT_GetSel(wndPtr, &s, &e);
-	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
-	lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
-	ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
-	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
+	lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
+	ll = (INT32)EDIT_EM_LineLength(wndPtr, e);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
 	if (e - li == ll) {
 		if (l != lc - 1)
-			e = (INT32)EDIT_EM_LineIndex(wndPtr, l + 1, 0);
+			e = (INT32)EDIT_EM_LineIndex(wndPtr, l + 1);
 	} else
 		e++;
 	if (!extend)
 		s = e;
 	EDIT_SetSel(wndPtr, s, e);
-	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	EDIT_EM_ScrollCaret(wndPtr);
 }
 
 
@@ -1547,13 +1537,13 @@
 	INT32 li;
 
 	EDIT_GetSel(wndPtr, &s, &e);
-	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
-	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
 	e = li;
 	if (!extend)
 		s = e;
 	EDIT_SetSel(wndPtr, s, e);
-	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	EDIT_EM_ScrollCaret(wndPtr);
 }
 
 
@@ -1572,19 +1562,19 @@
 	INT32 x;
 
 	EDIT_GetSel(wndPtr, &s, &e);
-	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
-	lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
-	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
+	lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
 	if (l < lc - 1) {
 		x = EDIT_WndXFromCol(wndPtr, l, e - li);
 		l = MIN(lc - 1, l + EDIT_GetVisibleLineCount(wndPtr));
-		e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
+		e = (INT32)EDIT_EM_LineIndex(wndPtr, l) +
 				EDIT_ColFromWndX(wndPtr, l, x);
 	}
 	if (!extend)
 		s = e;
 	EDIT_SetSel(wndPtr, s, e);
-	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	EDIT_EM_ScrollCaret(wndPtr);
 }
 
 
@@ -1602,18 +1592,18 @@
 	INT32 x;
 
 	EDIT_GetSel(wndPtr, &s, &e);
-	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
-	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
 	if (l) {
 		x = EDIT_WndXFromCol(wndPtr, l, e - li);
 		l = MAX(0, l - EDIT_GetVisibleLineCount(wndPtr));
-		e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
+		e = (INT32)EDIT_EM_LineIndex(wndPtr, l) +
 				EDIT_ColFromWndX(wndPtr, l, x);
 	}
 	if (!extend)
 		s = e;
 	EDIT_SetSel(wndPtr, s, e);
-	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	EDIT_EM_ScrollCaret(wndPtr);
 }
 
 
@@ -1631,18 +1621,18 @@
 	INT32 x;
 
 	EDIT_GetSel(wndPtr, &s, &e);
-	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
-	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
 	if (l) {
 		x = EDIT_WndXFromCol(wndPtr, l, e - li);
 		l--;
-		e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
+		e = (INT32)EDIT_EM_LineIndex(wndPtr, l) +
 				EDIT_ColFromWndX(wndPtr, l, x);
 	}
 	if (!extend)
 		s = e;
 	EDIT_SetSel(wndPtr, s, e);
-	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	EDIT_EM_ScrollCaret(wndPtr);
 }
 
 
@@ -1661,13 +1651,13 @@
 	LPSTR text;
 
 	EDIT_GetSel(wndPtr, &s, &e);
-	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
-	ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
-	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
+	ll = (INT32)EDIT_EM_LineLength(wndPtr, e);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
 	if (e - li == 0) {
 		if (l) {
-			li = (INT32)EDIT_EM_LineIndex(wndPtr, l - 1, 0);
-			e = li + (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
+			li = (INT32)EDIT_EM_LineIndex(wndPtr, l - 1);
+			e = li + (INT32)EDIT_EM_LineLength(wndPtr, li);
 		}
 	} else {
 		text = EDIT_GetPointer(wndPtr);
@@ -1677,7 +1667,7 @@
 	if (!extend)
 		s = e;
 	EDIT_SetSel(wndPtr, s, e);
-	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	EDIT_EM_ScrollCaret(wndPtr);
 }
 
 
@@ -1697,13 +1687,13 @@
 	LPSTR text;
 
 	EDIT_GetSel(wndPtr, &s, &e);
-	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
-	lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
-	ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
-	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
+	lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
+	ll = (INT32)EDIT_EM_LineLength(wndPtr, e);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
 	if (e - li == ll) {
 		if (l != lc - 1)
-			e = (INT32)EDIT_EM_LineIndex(wndPtr, l + 1, 0);
+			e = (INT32)EDIT_EM_LineIndex(wndPtr, l + 1);
 	} else {
 		text = EDIT_GetPointer(wndPtr);
 		e = li + EDIT_CallWordBreakProc(wndPtr,
@@ -1712,7 +1702,7 @@
 	if (!extend)
 		s = e;
 	EDIT_SetSel(wndPtr, s, e);
-	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	EDIT_EM_ScrollCaret(wndPtr);
 }
 
 
@@ -1723,15 +1713,16 @@
  */
 static void EDIT_PaintLine(WND *wndPtr, HDC32 hdc, INT32 line, BOOL32 rev)
 {
-	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
 	INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
-	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
 	INT32 li;
 	INT32 ll;
 	INT32 s;
 	INT32 e;
 	INT32 x;
 	INT32 y;
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
 	if ((line < fv) || (line > fv + vlc) || (line >= lc))
 		return;
@@ -1740,15 +1731,14 @@
 
 	x = EDIT_WndXFromCol(wndPtr, line, 0);
 	y = EDIT_WndYFromLine(wndPtr, line);
-	li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
-	ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, line);
+	ll = (INT32)EDIT_EM_LineLength(wndPtr, li);
 	EDIT_GetSel(wndPtr, &s, &e);
 	ORDER_INT32(s, e);
 	s = MIN(li + ll, MAX(li, s));
 	e = MIN(li + ll, MAX(li, e));
 	if (rev && (s != e) &&
-			((GetFocus32() == wndPtr->hwndSelf) ||
-				(wndPtr->dwStyle & ES_NOHIDESEL))) {
+		((es->eState & EF_FOCUSED) || (wndPtr->dwStyle & ES_NOHIDESEL)) ) {
 		x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, s - li, FALSE);
 		x += EDIT_PaintText(wndPtr, hdc, x, y, line, s - li, e - s, TRUE);
 		x += EDIT_PaintText(wndPtr, hdc, x, y, line, e - li, li + ll - e, FALSE);
@@ -1776,21 +1766,19 @@
 		return 0;
 	BkColor = GetBkColor32(hdc);
 	TextColor = GetTextColor32(hdc);
-	if (rev)
-        {
-            SetBkColor32(hdc, GetSysColor32(COLOR_HIGHLIGHT));
-            SetTextColor32(hdc, GetSysColor32(COLOR_HIGHLIGHTTEXT));
+	if (rev) {
+		SetBkColor32(hdc, GetSysColor32(COLOR_HIGHLIGHT));
+		SetTextColor32(hdc, GetSysColor32(COLOR_HIGHLIGHTTEXT));
 	}
 	text = EDIT_GetPasswordPointer(wndPtr);
-	li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, line);
 	xoff = EDIT_GetXOffset(wndPtr);
 	ret = (INT32)LOWORD(TabbedTextOut32A(hdc, x, y, text + li + col, count,
 					es->NumTabStops, es->TabStops, -xoff));
 	free(text);
-	if (rev)
-        {
-            SetBkColor32(hdc, BkColor);
-            SetTextColor32(hdc, TextColor);
+	if (rev) {
+		SetBkColor32(hdc, BkColor);
+		SetTextColor32(hdc, TextColor);
 	}
 	return ret;
 }
@@ -1860,9 +1848,9 @@
 	EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e);
 	es->SelStart = ns;
 	es->SelEnd = ne;
-	if (EDIT_GetRedraw(wndPtr)) {
-		if (wndPtr->hwndSelf == GetFocus32()) {
-			pos = EDIT_EM_PosFromChar(wndPtr, ne, 0);
+	if (!IsNoRedraw(wndPtr)) {
+		if (es->eState & EF_FOCUSED) {
+			pos = EDIT_EM_PosFromChar(wndPtr, ne);
 			SetCaretPos16((INT16)LOWORD(pos), (INT16)HIWORD(pos));
 		}
 		ORDER_INT32(s, ns);
@@ -1894,13 +1882,13 @@
 	HDC32 hdc;
 	HFONT32 hFont;
 	HFONT32 oldFont = 0;
-	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
-	INT32 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
-	INT32 ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
+	INT32 li = (INT32)EDIT_EM_LineIndex(wndPtr, line);
+	INT32 ll = (INT32)EDIT_EM_LineLength(wndPtr, li);
 	INT32 xoff = EDIT_GetXOffset(wndPtr);
 
 	hdc = GetDC32(wndPtr->hwndSelf);
-	hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0);
+	hFont = (HFONT32)EDIT_WM_GetFont(wndPtr);
 	if (hFont) oldFont = SelectObject32(hdc, hFont);
 	line = MAX(0, MIN(line, lc - 1));
 	col = MIN(col, ll);
@@ -1923,7 +1911,7 @@
  */
 static INT32 EDIT_WndYFromLine(WND *wndPtr, INT32 line)
 {
-	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
 	INT32 lh = EDIT_GetLineHeight(wndPtr);
 
 	return (line - fv) * lh;
@@ -2001,7 +1989,7 @@
  *	EM_CANUNDO
  *
  */
-static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_CanUndo(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
@@ -2031,7 +2019,7 @@
 		return -1;
 
 	l = EDIT_LineFromWndY(wndPtr, pt.y);
-	li = EDIT_EM_LineIndex(wndPtr, l, 0);
+	li = EDIT_EM_LineIndex(wndPtr, l);
 	c = EDIT_ColFromWndX(wndPtr, l, pt.x);
 
 	return (LRESULT)MAKELONG(li + c, li);
@@ -2043,7 +2031,7 @@
  *	EM_EMPTYUNDOBUFFER
  *
  */
-static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
@@ -2058,7 +2046,7 @@
  *	EM_FMTLINES
  *
  */
-static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam)
 {
 	fprintf(stdnimp, "edit: EM_FMTLINES: message not implemented\n");
 	return wParam ? TRUE : FALSE;
@@ -2070,7 +2058,7 @@
  *	EM_GETFIRSTVISIBLELINE
  *
  */
-static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
@@ -2086,7 +2074,7 @@
  *	EM_GETHANDLE
  *
  */
-static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_GetHandle(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
@@ -2115,7 +2103,7 @@
  *
  *	In this function we'll try to switch to local heap.
  */
-static LRESULT EDIT_EM_GetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_GetHandle16(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	LPSTR text;
@@ -2138,8 +2126,7 @@
 		dprintf_edit(stddeb, "edit: EM_GETHANDLE: local heap initialized\n");
 	}
 	if (!(newBuf = LOCAL_Alloc(wndPtr->hInstance, LMEM_MOVEABLE,
-                                   EDIT_WM_GetTextLength(wndPtr, 0, 0) + 1)))
-        {
+				   EDIT_WM_GetTextLength(wndPtr) + 1))) {
 		fprintf(stderr, "edit: EM_GETHANDLE: could not allocate new 16 bit buffer\n");
 		return 0;
 	}
@@ -2188,16 +2175,16 @@
 	LPSTR dst;
 	INT32 len;
 	INT32 i;
-	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
 
 	if (!IsMultiLine(wndPtr))
 		wParam = 0;
 	if ((INT32)wParam >= lc)
 		return 0;
 	text = EDIT_GetPointer(wndPtr);
-	src = text + (INT32)EDIT_EM_LineIndex(wndPtr, wParam, 0);
+	src = text + (INT32)EDIT_EM_LineIndex(wndPtr, wParam);
 	dst = (LPSTR)lParam;
-	len = MIN(*(WORD *)dst, (INT32)EDIT_EM_LineLength(wndPtr, wParam, 0));
+	len = MIN(*(WORD *)dst, (INT32)EDIT_EM_LineLength(wndPtr, wParam));
 	for (i = 0 ; i < len ; i++) {
 		*dst = *src;
 		src++;
@@ -2212,7 +2199,7 @@
  *	EM_GETLINECOUNT
  *
  */
-static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_GetLineCount(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
@@ -2238,11 +2225,11 @@
  *	EM_GETMODIFY
  *
  */
-static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_GetModify(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
-	return (LRESULT)es->TextChanged;
+	return (LRESULT)((es->eState & EF_TEXTCHANGED) != 0);
 }
 
 
@@ -2251,7 +2238,7 @@
  *	EM_GETPASSWORDCHAR
  *
  */
-static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
@@ -2320,7 +2307,7 @@
  *	All in all: very poorly documented
  *
  */
-static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_GetThumb(WND *wndPtr)
 {
 	return MAKELONG(EDIT_WM_VScroll(wndPtr, EM_GETTHUMB16, 0),
 		EDIT_WM_HScroll(wndPtr, EM_GETTHUMB16, 0));
@@ -2350,7 +2337,7 @@
  *	EM_LINEFROMCHAR
  *
  */
-static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam)
 {
 	INT32 l;
 
@@ -2358,8 +2345,8 @@
 		return 0;
 	if ((INT32)wParam == -1)
 		EDIT_EM_GetSel(wndPtr, (WPARAM32)&wParam, 0);	/* intentional (looks weird, doesn't it ?) */
-	l = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0) - 1;
-	while ((INT32)EDIT_EM_LineIndex(wndPtr, l, 0) > (INT32)wParam)
+	l = (INT32)EDIT_EM_GetLineCount(wndPtr) - 1;
+	while ((INT32)EDIT_EM_LineIndex(wndPtr, l) > (INT32)wParam)
 		l--;
 	return (LRESULT)l;
 }
@@ -2370,12 +2357,12 @@
  *	EM_LINEINDEX
  *
  */
-static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	INT32 e;
 	INT32 l;
-	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
 
 	if ((INT32)wParam == -1) {
 		EDIT_GetSel(wndPtr, NULL, &e);
@@ -2395,7 +2382,7 @@
  *	EM_LINELENGTH
  *
  */
-static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	INT32 s;
@@ -2407,13 +2394,13 @@
 		return (LRESULT)es->LineDefs[0].length;
 	if ((INT32)wParam == -1) {
 		EDIT_GetSel(wndPtr, &s, &e);
-		sl = (INT32)EDIT_EM_LineFromChar(wndPtr, s, 0);
-		el = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
+		sl = (INT32)EDIT_EM_LineFromChar(wndPtr, s);
+		el = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
 		return (LRESULT)(s - es->LineDefs[sl].offset +
 				es->LineDefs[el].offset +
 				es->LineDefs[el].length - e);
 	}
-	return (LRESULT)es->LineDefs[(INT32)EDIT_EM_LineFromChar(wndPtr, wParam, 0)].length;
+	return (LRESULT)es->LineDefs[(INT32)EDIT_EM_LineFromChar(wndPtr, wParam)].length;
 }
 
 
@@ -2430,8 +2417,8 @@
 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
-	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
 	INT32 nfv = MAX(0, fv + (INT32)lParam);
 	INT32 xoff = EDIT_GetXOffset(wndPtr);
 	INT32 nxoff = MAX(0, xoff + (INT32)wParam);
@@ -2447,8 +2434,9 @@
 	dx = xoff - nxoff;
 	dy = EDIT_WndYFromLine(wndPtr, fv) - EDIT_WndYFromLine(wndPtr, nfv);
 	if (dx || dy) {
-		if (EDIT_GetRedraw(wndPtr))
-			ScrollWindow32(wndPtr->hwndSelf, dx, dy, NULL, NULL);
+		if (!IsNoRedraw(wndPtr))
+			ScrollWindowEx32(wndPtr->hwndSelf, dx, dy, 
+					 NULL, NULL, 0, NULL, (SW_INVALIDATE | SW_ERASE));
 		es->FirstVisibleLine = nfv;
 		es->XOffset = nxoff;
 		if (IsVScrollBar(wndPtr))
@@ -2470,15 +2458,15 @@
  *	EM_POSFROMCHAR
  *
  */
-static LRESULT EDIT_EM_PosFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_PosFromChar(WND *wndPtr, WPARAM32 wParam)
 {
-	INT32 len = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
+	INT32 len = (INT32)EDIT_WM_GetTextLength(wndPtr);
 	INT32 l;
 	INT32 li;
 
 	wParam = MIN(wParam, len);
-	l = EDIT_EM_LineFromChar(wndPtr, wParam, 0);
-	li = EDIT_EM_LineIndex(wndPtr, l, 0);
+	l = EDIT_EM_LineFromChar(wndPtr, wParam);
+	li = EDIT_EM_LineIndex(wndPtr, l);
 	return (LRESULT)MAKELONG(EDIT_WndXFromCol(wndPtr, l, wParam - li),
 				EDIT_WndYFromLine(wndPtr, l));
 }
@@ -2494,7 +2482,7 @@
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	LPCSTR str = (LPCSTR)lParam;
 	INT32 strl = lstrlen32A(str);
-	INT32 tl = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
+	INT32 tl = (INT32)EDIT_WM_GetTextLength(wndPtr);
 	INT32 utl;
 	INT32 s;
 	INT32 e;
@@ -2540,7 +2528,7 @@
 			/* any deletion makes the old insertion-undo invalid */
 			es->UndoInsertLen = 0;
 		} else
-			EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
+			EDIT_EM_EmptyUndoBuffer(wndPtr);
 
 		/* now delete */
 		lstrcpy32A(text + s, text + e);
@@ -2565,7 +2553,7 @@
 				*utext = '\0';
 			}
 		} else
-			EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
+			EDIT_EM_EmptyUndoBuffer(wndPtr);
 
 		/* now insert */
 		tl = lstrlen32A(text);
@@ -2579,15 +2567,15 @@
 			CharLowerBuff32A(p, strl);
 		s += strl;
 	}
-	redraw = EDIT_GetRedraw(wndPtr);
-	EDIT_WM_SetRedraw(wndPtr, FALSE, 0);
+	redraw = !IsNoRedraw(wndPtr);
+	EDIT_WM_SetRedraw(wndPtr, FALSE);
 	EDIT_BuildLineDefs(wndPtr);
 	EDIT_EM_SetSel(wndPtr, s, s);
-	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
-	EDIT_EM_SetModify(wndPtr, TRUE, 0);
+	EDIT_EM_ScrollCaret(wndPtr);
+	EDIT_EM_SetModify(wndPtr, TRUE);
 	dprintf_edit(stddeb, "edit: notification EN_UPDATE sent\n");
 	EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
-	EDIT_WM_SetRedraw(wndPtr, redraw, 0);
+	EDIT_WM_SetRedraw(wndPtr, redraw);
 	if (redraw) {
 		InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
 		dprintf_edit(stddeb, "edit: notification EN_CHANGE sent\n");
@@ -2600,14 +2588,32 @@
 /*********************************************************************
  *
  *	EM_SCROLL
- *
- *	FIXME: Scroll what ???  And where ???
- *
  */
-static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam)
 {
-	fprintf(stdnimp, "edit: EM_SCROLL: message not implemented\n");
-	return 0;
+	INT32	dy;
+
+        switch (wParam) {
+        case SB_LINEUP:
+                dy = -1;
+                break;
+        case SB_LINEDOWN:
+                dy = 1;
+                break;
+        case SB_PAGEUP:
+	case SB_PAGEDOWN:
+		dy = EDIT_GetVisibleLineCount(wndPtr);
+                if( wParam == SB_PAGEUP) dy = -dy;
+                break;
+	default:
+		return FALSE;
+	}
+	if (dy) {
+		EDIT_EM_LineScroll(wndPtr, 0, dy);
+		dprintf_edit(stddeb, "edit: notification EN_VSCROLL sent\n");
+		EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
+	}
+	return MAKELONG( ((UINT16)(INT16)dy), TRUE );
 }
 
 
@@ -2620,12 +2626,12 @@
  *		controls ???
  *
  */
-static LRESULT EDIT_EM_ScrollCaret(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_ScrollCaret(WND *wndPtr)
 {
 	INT32 e;
 	INT32 l;
 	INT32 li;
-	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
 	INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
 	INT32 ww = EDIT_GetWndWidth(wndPtr);
 	INT32 cw = EDIT_GetAveCharWidth(wndPtr);
@@ -2634,8 +2640,8 @@
 	INT32 dx = 0;
 
 	EDIT_GetSel(wndPtr, NULL, &e);
-	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
-	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
 	x = EDIT_WndXFromCol(wndPtr, l, e - li);
 	if (l >= fv + vlc)
 		dy = l - vlc + 1 - fv;
@@ -2665,7 +2671,7 @@
  *	EM_SETHANDLE
  *
  */
-static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
@@ -2680,12 +2686,12 @@
 		es->LineCount = 0;
 		es->FirstVisibleLine = 0;
 		es->SelStart = es->SelEnd = 0;
-		EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
-		EDIT_EM_SetModify(wndPtr, FALSE, 0);
+		EDIT_EM_EmptyUndoBuffer(wndPtr);
+		EDIT_EM_SetModify(wndPtr, FALSE);
 		EDIT_BuildLineDefs(wndPtr);
-		if (EDIT_GetRedraw(wndPtr))
+		if (!IsNoRedraw(wndPtr))
 			InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
-		EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+		EDIT_EM_ScrollCaret(wndPtr);
 	}
 	return 0;
 }
@@ -2696,7 +2702,7 @@
  *	EM_SETHANDLE16
  *
  */
-static LRESULT EDIT_EM_SetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_SetHandle16(WND *wndPtr, WPARAM32 wParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
@@ -2711,12 +2717,12 @@
 		es->LineCount = 0;
 		es->FirstVisibleLine = 0;
 		es->SelStart = es->SelEnd = 0;
-		EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
-		EDIT_EM_SetModify(wndPtr, FALSE, 0);
+		EDIT_EM_EmptyUndoBuffer(wndPtr);
+		EDIT_EM_SetModify(wndPtr, FALSE);
 		EDIT_BuildLineDefs(wndPtr);
-		if (EDIT_GetRedraw(wndPtr))
+		if (!IsNoRedraw(wndPtr))
 			InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
-		EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+		EDIT_EM_ScrollCaret(wndPtr);
 	}
 	return 0;
 }
@@ -2784,11 +2790,14 @@
  *	EM_SETMODIFY
  *
  */
-static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
-	es->TextChanged = (BOOL32)wParam;
+	if( wParam )
+	    es->eState |= EF_TEXTCHANGED;
+	else
+	    es->eState &= ~EF_TEXTCHANGED;
 	return 0;
 }
 
@@ -2800,7 +2809,7 @@
  *	FIXME: This imlementation is way too simple
  *
  */
-static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
@@ -2814,7 +2823,7 @@
  *	EM_SETREADONLY
  *
  */
-static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam)
 {
 	if ((BOOL32)wParam)
 		wndPtr->dwStyle |= ES_READONLY;
@@ -2857,7 +2866,7 @@
 {
 	INT32 ns = (INT32)wParam;
 	INT32 ne = (INT32)lParam;
-	INT32 tl = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
+	INT32 tl = (INT32)EDIT_WM_GetTextLength(wndPtr);
 
 	if (ns == -1) {
 		EDIT_GetSel(wndPtr, NULL, &ne);
@@ -2890,7 +2899,7 @@
 		ne = -1;
 	EDIT_EM_SetSel(wndPtr, ns, ne);
 	if (!wParam)
-		EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+		EDIT_EM_ScrollCaret(wndPtr);
 	return -1;
 }
 
@@ -2968,7 +2977,7 @@
  *	EM_UNDO / WM_UNDO
  *
  */
-static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_EM_Undo(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	LPSTR utext = xstrdup(EDIT_GetUndoPointer(wndPtr));
@@ -2977,7 +2986,7 @@
 			es->UndoInsertLen, utext);
 
 	EDIT_EM_SetSel(wndPtr, es->UndoPos, es->UndoPos + es->UndoInsertLen);
-	EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
+	EDIT_EM_EmptyUndoBuffer(wndPtr);
 	EDIT_EM_ReplaceSel(wndPtr, TRUE, (LPARAM)utext);
 	EDIT_EM_SetSel(wndPtr, es->UndoPos, es->UndoPos + es->UndoInsertLen);
 	free(utext);
@@ -3031,7 +3040,7 @@
  *	WM_CLEAR
  *
  */
-static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_WM_Clear(WND *wndPtr)
 {
 	EDIT_EM_ReplaceSel(wndPtr, TRUE, (LPARAM)"");
 
@@ -3051,23 +3060,23 @@
 
 	switch (LOWORD(wParam)) {
 		case EM_UNDO32:	
-			EDIT_EM_Undo(wndPtr, 0, 0);
+			EDIT_EM_Undo(wndPtr);
 			break;
 		case WM_CUT:
-			EDIT_WM_Cut(wndPtr, 0, 0);
+			EDIT_WM_Cut(wndPtr);
 			break;
 		case WM_COPY:
-			EDIT_WM_Copy(wndPtr, 0, 0);
+			EDIT_WM_Copy(wndPtr);
 			break;
 		case WM_PASTE:
-			EDIT_WM_Paste(wndPtr, 0, 0);
+			EDIT_WM_Paste(wndPtr);
 			break;
 		case WM_CLEAR:
-			EDIT_WM_Clear(wndPtr, 0, 0);
+			EDIT_WM_Clear(wndPtr);
 			break;
 		case EM_SETSEL32:
 			EDIT_EM_SetSel(wndPtr, 0, -1);
-			EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+			EDIT_EM_ScrollCaret(wndPtr);
 			break;
 		default:
 			dprintf_edit(stddeb, "edit: unknown menu item, please report\n");
@@ -3103,7 +3112,7 @@
  *	WM_COPY
  *
  */
-static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_WM_Copy(WND *wndPtr)
 {
 	INT32 s;
 	INT32 e;
@@ -3174,14 +3183,14 @@
 	}
 	es->BufSize = LocalSize32(es->hBuf32) - 1;
 	es->UndoBufSize = LocalSize32(es->hUndoBuf) - 1;
-	EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
+	EDIT_EM_EmptyUndoBuffer(wndPtr);
 	text = EDIT_GetPointer(wndPtr);
 	*text = '\0';
 	EDIT_BuildLineDefs(wndPtr);
 	EDIT_WM_SetFont(wndPtr, 0, 0);
 	if (cs->lpszName && *(cs->lpszName) != '\0')
 		EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)FALSE, (LPARAM)cs->lpszName);
-	EDIT_WM_SetRedraw(wndPtr, TRUE, 0);
+	EDIT_WM_SetRedraw(wndPtr, TRUE);
 	return 0;
 }
 
@@ -3191,10 +3200,10 @@
  *	WM_CUT
  *
  */
-static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_WM_Cut(WND *wndPtr)
 {
-	EDIT_WM_Copy(wndPtr, 0, 0);
-	EDIT_WM_Clear(wndPtr, 0, 0);
+	EDIT_WM_Copy(wndPtr);
+	EDIT_WM_Clear(wndPtr);
 	return -1;
 }
 
@@ -3204,7 +3213,7 @@
  *	WM_DESTROY
  *
  */
-static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_WM_Destroy(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
@@ -3219,7 +3228,8 @@
 	else
 		LOCAL_Free(wndPtr->hInstance, es->hBuf16);
 	free(es);
-	*(EDITSTATE **)&wndPtr->wExtra = NULL;
+	wndPtr->wExtra[0] = 0;
+
 	return 0;
 }
 
@@ -3229,7 +3239,7 @@
  *	WM_ENABLE
  *
  */
-static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam)
 {
 	EDIT_InvalidateText(wndPtr, 0, -1);
 	return 0;
@@ -3241,7 +3251,7 @@
  *	WM_ERASEBKGND
  *
  */
-static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam)
 {
 	HBRUSH32 hBrush;
 	RECT32 rc;
@@ -3269,7 +3279,7 @@
  *	WM_GETDLGCODE
  *
  */
-static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr)
 {
 	return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
 }
@@ -3280,7 +3290,7 @@
  *	WM_GETFONT
  *
  */
-static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_WM_GetFont(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
@@ -3313,7 +3323,7 @@
  *	WM_GETTEXTLENGTH
  *
  */
-static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_WM_GetTextLength(WND *wndPtr)
 {
 	LPSTR text = EDIT_GetPointer(wndPtr);
 
@@ -3408,7 +3418,7 @@
 
 	/* undo */
 	EnableMenuItem32(hPopup, 0, MF_BYPOSITION |
-		(EDIT_EM_CanUndo(wndPtr, 0, 0) ? MF_ENABLED : MF_GRAYED));
+		(EDIT_EM_CanUndo(wndPtr) ? MF_ENABLED : MF_GRAYED));
 	/* cut */
 	EnableMenuItem32(hPopup, 2, MF_BYPOSITION |
 		((e - s) && !IsPassword(wndPtr) ? MF_ENABLED : MF_GRAYED));
@@ -3423,11 +3433,63 @@
 		((e - s) ? MF_ENABLED : MF_GRAYED));
 	/* select all */
 	EnableMenuItem32(hPopup, 7, MF_BYPOSITION |
-		(s || (e != EDIT_WM_GetTextLength(wndPtr, 0, 0)) ? MF_ENABLED : MF_GRAYED));
+		(s || (e != EDIT_WM_GetTextLength(wndPtr)) ? MF_ENABLED : MF_GRAYED));
 
 	return 0;
 }
 
+/*********************************************************************
+ *
+ *      EDIT_CheckCombo
+ *
+ */
+static BOOL32 EDIT_CheckCombo(WND *wndPtr, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
+{
+   HWND32 hLBox;
+
+   if( WIDGETS_IsControl32( wndPtr->parent, BIC32_COMBO ) &&
+            (hLBox = COMBO_GetLBWindow( wndPtr->parent )) )
+   {
+       HWND32 hCombo = wndPtr->parent->hwndSelf;
+       BOOL32 bUIFlip = TRUE;
+
+       dprintf_combo(stddeb, "EDIT_CheckCombo [%04x]: handling msg %04x (%04x)\n",
+				  wndPtr->hwndSelf, (UINT16)msg, (UINT16)wParam );
+       switch( msg )
+       {
+	 case WM_KEYDOWN: /* Handle F4 and arrow keys */
+	   if( wParam != VK_F4 )
+	   {
+	       bUIFlip = (BOOL32)SendMessage32A( hCombo, CB_GETEXTENDEDUI32, 0, 0 );
+	       if( SendMessage32A( hCombo, CB_GETDROPPEDSTATE32, 0, 0 ) ) bUIFlip = FALSE;
+	   }
+
+	   if( !bUIFlip )
+	       SendMessage32A( hLBox, WM_KEYDOWN, wParam, 0 );
+	   else
+	   {
+	       /* make sure ComboLBox pops up */
+
+	       SendMessage32A( hCombo, CB_SETEXTENDEDUI32, 0, 0 );
+	       SendMessage32A( hLBox, WM_KEYDOWN, VK_F4, 0 ); 
+	       SendMessage32A( hCombo, CB_SETEXTENDEDUI32, 1, 0 );
+	   }
+	   break;
+
+	 case WM_SYSKEYDOWN: /* Handle Alt+up/down arrows */
+	   bUIFlip = (BOOL32)SendMessage32A( hCombo, CB_GETEXTENDEDUI32, 0, 0 );
+
+	   if( bUIFlip )
+	   {
+	     bUIFlip = (BOOL32)SendMessage32A( hCombo, CB_GETDROPPEDSTATE32, 0, 0 );
+	     SendMessage32A( hCombo, CB_SHOWDROPDOWN32, (bUIFlip) ? FALSE : TRUE, 0 );
+	   } else SendMessage32A( hLBox, WM_KEYDOWN, VK_F4, 0 );
+	   break;
+       }
+       return TRUE;
+   }
+   return FALSE;
+}
 
 /*********************************************************************
  *
@@ -3452,8 +3514,12 @@
 
 	EDIT_GetSel(wndPtr, &s, &e);
 	switch (wParam) {
-	case VK_LEFT:
+	case VK_F4:
 	case VK_UP:
+		if( EDIT_CheckCombo(wndPtr, WM_KEYDOWN, wParam, lParam) ) break;
+		if( wParam == VK_F4 ) break;
+                /* fall through */
+	case VK_LEFT:
 		if (IsMultiLine(wndPtr) && (wParam == VK_UP))
 			EDIT_MoveUpward(wndPtr, shift);
 		else
@@ -3462,8 +3528,10 @@
 			else
 				EDIT_MoveBackward(wndPtr, shift);
 		break;
-	case VK_RIGHT:
 	case VK_DOWN:
+		if( EDIT_CheckCombo(wndPtr, WM_KEYDOWN, wParam, lParam) ) break;
+		/* fall through */
+	case VK_RIGHT:
 		if (IsMultiLine(wndPtr) && (wParam == VK_DOWN))
 			EDIT_MoveDownward(wndPtr, shift);
 		else if (control)
@@ -3488,7 +3556,7 @@
 	case VK_BACK:
 		if (!IsReadOnly(wndPtr) && !control)
 			if (e != s)
-				EDIT_WM_Clear(wndPtr, 0, 0);
+				EDIT_WM_Clear(wndPtr);
 			else
 				EDIT_DelLeft(wndPtr);
 		break;
@@ -3496,9 +3564,9 @@
 		if (!IsReadOnly(wndPtr) && !(shift && control))
 			if (e != s) {
 				if (shift)
-					EDIT_WM_Cut(wndPtr, 0, 0);
+					EDIT_WM_Cut(wndPtr);
 				else
-					EDIT_WM_Clear(wndPtr, 0, 0);
+					EDIT_WM_Clear(wndPtr);
 			} else {
 				if (shift)
 					EDIT_DelLeft(wndPtr);
@@ -3511,9 +3579,9 @@
 	case VK_INSERT:
 		if (shift) {
 			if (!IsReadOnly(wndPtr))
-				EDIT_WM_Paste(wndPtr, 0, 0);
+				EDIT_WM_Paste(wndPtr);
 		} else if (control)
-			EDIT_WM_Copy(wndPtr, 0, 0);
+			EDIT_WM_Copy(wndPtr);
 		break;
 	}
 	return 0;
@@ -3525,11 +3593,13 @@
  *	WM_KILLFOCUS
  *
  */
-static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam)
 {
 	INT32 s;
 	INT32 e;
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
+	es->eState &= ~EF_FOCUSED;
 	DestroyCaret32();
 	if(!(wndPtr->dwStyle & ES_NOHIDESEL)) {
 		EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e);
@@ -3558,13 +3628,13 @@
 	LPSTR text = EDIT_GetPointer(wndPtr);
 
 	EDIT_GetSel(wndPtr, NULL, &e);
-	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
-	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
-	ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
+	ll = (INT32)EDIT_EM_LineLength(wndPtr, e);
 	s = li + EDIT_CallWordBreakProc (wndPtr, text + li, e - li, ll, WB_LEFT);
 	e = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_RIGHT);
 	EDIT_EM_SetSel(wndPtr, s, e);
-	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	EDIT_EM_ScrollCaret(wndPtr);
 	return 0;
 }
 
@@ -3582,7 +3652,7 @@
 	INT32 c;
 	INT32 s;
 	INT32 e;
-	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
 	INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
 	INT32 li;
 
@@ -3591,14 +3661,14 @@
 	l = MIN(fv + vlc - 1, MAX(fv, l));
 	x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
 	c = EDIT_ColFromWndX(wndPtr, l, x);
-	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
 	e = li + c;
 	if (GetKeyState32(VK_SHIFT) & 0x8000)
 		EDIT_GetSel(wndPtr, &s, NULL);
 	else
 		s = e;
 	EDIT_SetSel(wndPtr, s, e);
-	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	EDIT_EM_ScrollCaret(wndPtr);
 	SetTimer32(wndPtr->hwndSelf, 0, 100, NULL);
 	return 0;
 }
@@ -3638,14 +3708,14 @@
 	if (GetCapture32() == wndPtr->hwndSelf) {
 		x = (INT32)(INT16)LOWORD(lParam);
 		y = (INT32)(INT16)HIWORD(lParam);
-		fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+		fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
 		vlc = EDIT_GetVisibleLineCount(wndPtr);
 		l = EDIT_LineFromWndY(wndPtr, y);
 		l = MIN(fv + vlc - 1, MAX(fv, l));
 		x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
 		c = EDIT_ColFromWndX(wndPtr, l, x);
 		EDIT_GetSel(wndPtr, &s, NULL);
-		li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
+		li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
 		EDIT_SetSel(wndPtr, s, li + c);
 	}
 	/*
@@ -3661,13 +3731,13 @@
  *	WM_PAINT
  *
  */
-static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam)
 {
 	PAINTSTRUCT32 ps;
 	INT32 i;
-	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
 	INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
-	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
 	HDC32 hdc;
 	HFONT32 hFont;
 	HFONT32 oldFont = 0;
@@ -3676,14 +3746,15 @@
 	RECT32 rcRgn;
  	LRESULT pos;
  	INT32 e;
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	BOOL32 rev = IsWindowEnabled32(wndPtr->hwndSelf) &&
-				((GetFocus32() == wndPtr->hwndSelf) ||
+				((es->eState & EF_FOCUSED) ||
 					(wndPtr->dwStyle & ES_NOHIDESEL));
 
 	hdc = BeginPaint32(wndPtr->hwndSelf, &ps);
 	GetClientRect32(wndPtr->hwndSelf, &rc);
 	IntersectClipRect32( hdc, rc.left, rc.top, rc.right, rc.bottom );
-	hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0);
+	hFont = (HFONT32)EDIT_WM_GetFont(wndPtr);
 	if (hFont)
 		oldFont = (HFONT32)SelectObject32(hdc, hFont);
 	EDIT_SEND_CTLCOLOR(wndPtr, hdc);
@@ -3696,10 +3767,10 @@
 			EDIT_PaintLine(wndPtr, hdc, i, rev);
 	}
 	if (hFont) SelectObject32(hdc, oldFont);
-	if (wndPtr->hwndSelf == GetFocus32()) {
+	if (es->eState & EF_FOCUSED) {
 		EDIT_GetSel(wndPtr, NULL, &e);
-		pos = EDIT_EM_PosFromChar(wndPtr, e, 0);
-		SetCaretPos16( (INT16)LOWORD(pos), (INT16)HIWORD(pos) );
+		pos = EDIT_EM_PosFromChar(wndPtr, e);
+		SetCaretPos16((INT16)LOWORD(pos), (INT16)HIWORD(pos));
 	}
 	EndPaint32(wndPtr->hwndSelf, &ps);
 	return 0;
@@ -3711,14 +3782,13 @@
  *	WM_PASTE
  *
  */
-static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_WM_Paste(WND *wndPtr)
 {
 	HGLOBAL16 hsrc;
 	LPSTR src;
 
 	OpenClipboard32(wndPtr->hwndSelf);
-	if ((hsrc = GetClipboardData16(CF_TEXT)))
-        {
+	if ((hsrc = GetClipboardData16(CF_TEXT))) {
 		src = (LPSTR)GlobalLock16(hsrc);
 		EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)src);
 		GlobalUnlock16(hsrc);
@@ -3748,13 +3818,15 @@
  *	WM_SETFOCUS
  *
  */
-static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam)
 {
 	INT32 s;
 	INT32 e;
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
+	es->eState |= EF_FOCUSED;
 	EDIT_GetSel(wndPtr, &s, &e);
-	CreateCaret32( wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr) );
+	CreateCaret32(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
 	EDIT_SetSel(wndPtr, s, e);
 	if(!(wndPtr->dwStyle & ES_NOHIDESEL))
 		EDIT_InvalidateText(wndPtr, s, e);
@@ -3789,12 +3861,11 @@
 	if (es->hFont) SelectObject32(hdc, oldFont);
 	ReleaseDC32(wndPtr->hwndSelf, hdc);
 	EDIT_BuildLineDefs(wndPtr);
-	if ((BOOL32)lParam && EDIT_GetRedraw(wndPtr))
+	if ((BOOL32)lParam && !IsNoRedraw(wndPtr))
 		InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
-	if (wndPtr->hwndSelf == GetFocus32()) {
+	if (es->eState & EF_FOCUSED) {
 		DestroyCaret32();
-		CreateCaret32( wndPtr->hwndSelf, 0,
-                               2, EDIT_GetLineHeight(wndPtr) );
+		CreateCaret32(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
 		EDIT_SetSel(wndPtr, s, e);
 		ShowCaret32(wndPtr->hwndSelf);
 	}
@@ -3807,11 +3878,12 @@
  *	WM_SETREDRAW
  *
  */
-static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam)
 {
-	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-
-	es->Redraw = (BOOL32)wParam;
+	if( wParam )
+	    wndPtr->flags &= ~WIN_NO_REDRAW;
+	else
+	    wndPtr->flags |= WIN_NO_REDRAW;
 	return 0;
 }
 
@@ -3825,9 +3897,12 @@
 {
 	EDIT_EM_SetSel(wndPtr, 0, -1);
 	if (lParam)
+	{
+		dprintf_edit(stddeb,"\t'%s'\n", (char*)lParam );
 		EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)FALSE, lParam);
-	EDIT_EM_SetModify(wndPtr, TRUE, 0);
-	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	}
+	EDIT_EM_SetModify(wndPtr, TRUE);
+	EDIT_EM_ScrollCaret(wndPtr);
 	return 1;
 }
 
@@ -3846,7 +3921,7 @@
 	
 	EDIT_GetSel(wndPtr, 0, &e);
 	GetClientRect32(wndPtr->hwndSelf, &es->FormatRect);
-	if (EDIT_GetRedraw(wndPtr) &&
+	if (!IsNoRedraw(wndPtr) &&
 			((wParam == SIZE_MAXIMIZED) ||
 				(wParam == SIZE_RESTORED))) {
 		if (IsMultiLine(wndPtr) && IsWordWrap(wndPtr))
@@ -3865,8 +3940,10 @@
 static LRESULT EDIT_WM_SysKeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
 	if ((wParam == VK_BACK) && (lParam & 0x2000) &&
-			(BOOL32)EDIT_EM_CanUndo(wndPtr, 0, 0))
-		EDIT_EM_Undo(wndPtr, 0, 0);
+			(BOOL32)EDIT_EM_CanUndo(wndPtr))
+		EDIT_EM_Undo(wndPtr);
+	else if( wParam == VK_UP || wParam == VK_DOWN )
+		EDIT_CheckCombo( wndPtr, WM_SYSKEYDOWN, wParam, lParam );
 	return 0;
 }
 
@@ -3895,48 +3972,44 @@
  */
 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
-	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
-	INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
+	INT32 lc, fv;
 	INT32 dy = 0;
 	BOOL32 not = TRUE;
 	LRESULT ret = 0;
 
 	switch (wParam) {
 	case SB_LINEUP:
-		dy = -1;
-		break;
 	case SB_LINEDOWN:
-		dy = 1;
-		break;
 	case SB_PAGEUP:
-		dy = -vlc;
-		break;
 	case SB_PAGEDOWN:
-		dy = vlc;
-		break;
-	case SB_TOP:
-		dy = -fv;
-		break;
-	case SB_BOTTOM:
-		dy = lc - 1 - fv;
-		break;
-	case SB_THUMBTRACK:
-		not = FALSE;
-		/* fall through */
-	case SB_THUMBPOSITION:
-		dy = HIWORD(wParam) * (lc - 1) / 100 - fv;
-		break;
-	/* The next two are undocumented ! */
-	case EM_GETTHUMB16:
-		ret = (lc > 1) ? MAKELONG(fv * 100 / (lc - 1), 0) : 0;
-		break;
-	case EM_LINESCROLL16:
-		dy = (INT16)LOWORD(lParam);
-		break;
-	case SB_ENDSCROLL:
+		EDIT_EM_Scroll( wndPtr, wParam );
+		return ret;
 	default:
-		break;
+		lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
+		fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
+		switch( wParam ) {
+		case SB_TOP:
+			dy = -fv;
+			break;
+		case SB_BOTTOM:
+			dy = lc - 1 - fv;
+			break;
+		case SB_THUMBTRACK:
+			not = FALSE;
+			/* fall through */
+		case SB_THUMBPOSITION:
+			dy = HIWORD(wParam) * (lc - 1) / 100 - fv;
+			break;
+		/* The next two are undocumented ! */
+		case EM_GETTHUMB16:
+			ret = (lc > 1) ? MAKELONG(fv * 100 / (lc - 1), 0) : 0;
+			break;
+		case EM_LINESCROLL16:
+			dy = (INT16)LOWORD(lParam);
+			break;
+		case SB_ENDSCROLL:
+			/* nothing to do */
+		}
 	}
 	if (dy) {
 		EDIT_EM_LineScroll(wndPtr, 0, dy);
diff --git a/controls/listbox.c b/controls/listbox.c
index 57afcf4..20f6028 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -12,6 +12,7 @@
 #include "heap.h"
 #include "spy.h"
 #include "win.h"
+#include "combo.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -20,7 +21,6 @@
  * - LBS_USETABSTOPS
  * - Unicode
  * - Locale handling
- * - COMBOLBOX
  */
 
 /* Items array granularity */
@@ -45,7 +45,7 @@
 typedef struct
 {
     HANDLE32      heap;           /* Heap for this listbox */
-    HWND32        owner;          /* Owner window */
+    HWND32        owner;          /* Owner window to send notifications to */
     UINT32        style;          /* Window style */
     INT32         width;          /* Window width */
     INT32         height;         /* Window height */
@@ -65,6 +65,7 @@
     BOOL32        caret_on;       /* Is caret on? */
     HFONT32       font;           /* Current font */
     LCID          locale;         /* Current locale for string comparisons */
+    LPHEADCOMBO   lphc;		  /* ComboLBox */
 } LB_DESCR;
 
 
@@ -76,7 +77,7 @@
 
 #define SEND_NOTIFICATION(wnd,descr,code) \
     (SendMessage32A( (descr)->owner, WM_COMMAND, \
-                     MAKEWPARAM( (wnd)->wIDmenu, (code) ), (wnd)->hwndSelf ))
+     MAKEWPARAM((((descr)->lphc)?ID_CB_LISTBOX:(wnd)->wIDmenu), (code) ), (wnd)->hwndSelf ))
 
 /* Current timer status */
 typedef enum
@@ -439,8 +440,10 @@
     if (IS_OWNERDRAW(descr))
     {
         DRAWITEMSTRUCT32 dis;
+	UINT32		 id = (descr->lphc) ? ID_CB_LISTBOX : wnd->wIDmenu;
+
         dis.CtlType      = ODT_LISTBOX;
-        dis.CtlID        = wnd->wIDmenu;
+        dis.CtlID        = id;
         dis.hwndItem     = wnd->hwndSelf;
         dis.itemAction   = action;
         dis.hDC          = hdc;
@@ -458,10 +461,12 @@
                          wnd->hwndSelf, index, item ? item->str : "", action,
                          dis.itemState, rect->left, rect->top,
                          rect->right, rect->bottom );
-        SendMessage32A(descr->owner, WM_DRAWITEM, wnd->wIDmenu, (LPARAM)&dis);
+        SendMessage32A(descr->owner, WM_DRAWITEM, id, (LPARAM)&dis);
     }
     else
     {
+        COLORREF oldText = 0, oldBk = 0;
+
         if (action == ODA_FOCUS)
         {
             DrawFocusRect32( hdc, rect );
@@ -469,17 +474,10 @@
         }
         if (item && item->selected)
         {
-            SetBkColor32( hdc, GetSysColor32( COLOR_HIGHLIGHT ) );
-            SetTextColor32( hdc, GetSysColor32( COLOR_HIGHLIGHTTEXT ) );
+            oldBk = SetBkColor32( hdc, GetSysColor32( COLOR_HIGHLIGHT ) );
+            oldText = SetTextColor32( hdc, GetSysColor32(COLOR_HIGHLIGHTTEXT));
         }
-        else
-        {
-            SetBkColor32( hdc, GetSysColor32( COLOR_WINDOW ) );
-            if (wnd->dwStyle & WS_DISABLED)
-                SetTextColor32( hdc, GetSysColor32( COLOR_GRAYTEXT ) );
-            else
-                SetTextColor32( hdc, GetSysColor32( COLOR_WINDOWTEXT ) );
-        }
+
         dprintf_listbox( stddeb, "Listbox %04x: painting %d (%s) action=%02x "
                          "rect=%d,%d-%d,%d\n",
                          wnd->hwndSelf, index, item ? item->str : "", action,
@@ -492,6 +490,11 @@
         else
             ExtTextOut32A( hdc, rect->left + 1, rect->top + 1,
                            ETO_OPAQUE | ETO_CLIPPED, rect, NULL, 0, NULL );
+        if (item && item->selected)
+        {
+            SetBkColor32( hdc, oldBk );
+            SetTextColor32( hdc, oldText );
+        }
         if ((descr->focus_item == index) &&
             (descr->caret_on) &&
             (GetFocus32() == wnd->hwndSelf)) DrawFocusRect32( hdc, rect );
@@ -526,18 +529,23 @@
 {
     HDC32 hdc;
     RECT32 rect;
+    HFONT32 oldFont = 0;
+    HBRUSH32 hbrush, oldBrush = 0;
 
     if (descr->style & LBS_NOREDRAW) return;
     if (LISTBOX_GetItemRect( wnd, descr, index, &rect ) != 1) return;
-    if ((hdc = GetDCEx32( wnd->hwndSelf, 0, DCX_CACHE )))
-    {
-        HFONT32 oldFont = 0;
-        if (descr->font) oldFont = SelectObject32( hdc, descr->font );
-        SetWindowOrgEx32( hdc, descr->horz_pos, 0, NULL );
-        LISTBOX_PaintItem( wnd, descr, hdc, &rect, index, action );
-        if (oldFont) SelectObject32( hdc, oldFont );
-        ReleaseDC32( wnd->hwndSelf, hdc );
-    }
+    if (!(hdc = GetDCEx32( wnd->hwndSelf, 0, DCX_CACHE ))) return;
+    if (descr->font) oldFont = SelectObject32( hdc, descr->font );
+    hbrush = SendMessage32A( descr->owner, WM_CTLCOLORLISTBOX,
+                             hdc, (LPARAM)wnd->hwndSelf );
+    if (hbrush) oldBrush = SelectObject32( hdc, hbrush );
+    if (wnd->dwStyle & WS_DISABLED)
+        SetTextColor32( hdc, GetSysColor32( COLOR_GRAYTEXT ) );
+    SetWindowOrgEx32( hdc, descr->horz_pos, 0, NULL );
+    LISTBOX_PaintItem( wnd, descr, hdc, &rect, index, action );
+    if (oldFont) SelectObject32( hdc, oldFont );
+    if (oldBrush) SelectObject32( hdc, oldBrush );
+    ReleaseDC32( wnd->hwndSelf, hdc );
 }
 
 
@@ -635,8 +643,10 @@
         else
         {
             COMPAREITEMSTRUCT32 cis;
+	    UINT32		id = (descr->lphc) ? ID_CB_LISTBOX : wnd->wIDmenu;
+
             cis.CtlType    = ODT_LISTBOX;
-            cis.CtlID      = wnd->wIDmenu;
+            cis.CtlID      = id;
             cis.hwndItem   = wnd->hwndSelf;
             cis.itemID1    = index;
             cis.itemData1  = descr->items[index].data;
@@ -644,7 +654,7 @@
             cis.itemData2  = (DWORD)str;
             cis.dwLocaleId = descr->locale;
             res = SendMessage32A( descr->owner, WM_COMPAREITEM,
-                                  wnd->wIDmenu, (LPARAM)&cis );
+                                  id, (LPARAM)&cis );
         }
         if (!res) return index;
         if (res > 0) max = index;
@@ -817,6 +827,7 @@
     INT32 i, col_pos = descr->page_size - 1;
     RECT32 rect;
     HFONT32 oldFont = 0;
+    HBRUSH32 hbrush, oldBrush = 0;
 
     SetRect32( &rect, 0, 0, descr->width, descr->height );
     if (descr->style & LBS_NOREDRAW) return 0;
@@ -829,6 +840,11 @@
     }
 
     if (descr->font) oldFont = SelectObject32( hdc, descr->font );
+    hbrush = SendMessage32A( descr->owner, WM_CTLCOLORLISTBOX,
+                             hdc, (LPARAM)wnd->hwndSelf );
+    if (hbrush) oldBrush = SelectObject32( hdc, hbrush );
+    if (wnd->dwStyle & WS_DISABLED)
+        SetTextColor32( hdc, GetSysColor32( COLOR_GRAYTEXT ) );
 
     if (!descr->nb_items && (descr->focus_item != -1) && descr->caret_on &&
         (GetFocus32() == wnd->hwndSelf))
@@ -898,6 +914,7 @@
         }
     }
     if (oldFont) SelectObject32( hdc, oldFont );
+    if (oldBrush) SelectObject32( hdc, oldBrush );
     return 0;
 }
 
@@ -1261,13 +1278,14 @@
     if (descr->style & LBS_OWNERDRAWVARIABLE)
     {
         MEASUREITEMSTRUCT32 mis;
+	UINT32		    id = (descr->lphc) ? ID_CB_LISTBOX : wnd->wIDmenu;
+
         mis.CtlType    = ODT_LISTBOX;
-        mis.CtlID      = wnd->wIDmenu;
+        mis.CtlID      = id;
         mis.itemID     = index;
         mis.itemData   = descr->items[index].data;
         mis.itemHeight = descr->item_height;
-        SendMessage32A( descr->owner, WM_MEASUREITEM, wnd->wIDmenu,
-                        (LPARAM)&mis );
+        SendMessage32A( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
         item->height = mis.itemHeight ? mis.itemHeight : 1;
         dprintf_listbox( stddeb, "Listbox %04x: measure item %d (%s) = %d\n",
                          wnd->hwndSelf, index, str ? str : "", item->height );
@@ -1342,13 +1360,14 @@
     if (IS_OWNERDRAW(descr) || descr->items[index].data)
     {
         DELETEITEMSTRUCT32 dis;
+	UINT32		   id = (descr->lphc) ? ID_CB_LISTBOX : wnd->wIDmenu;
+
         dis.CtlType  = ODT_LISTBOX;
-        dis.CtlID    = wnd->wIDmenu;
+        dis.CtlID    = id;
         dis.itemID   = index;
         dis.hwndItem = wnd->hwndSelf;
         dis.itemData = descr->items[index].data;
-        SendMessage32A( wnd->hwndSelf, WM_DELETEITEM, wnd->wIDmenu,
-                        (LPARAM)&dis );
+        SendMessage32A( descr->owner, WM_DELETEITEM, id, (LPARAM)&dis );
     }
     if (HAS_STRINGS(descr) && descr->items[index].str)
         HeapFree( descr->heap, 0, descr->items[index].str );
@@ -1454,8 +1473,8 @@
 /***********************************************************************
  *           LISTBOX_Directory
  */
-LRESULT LISTBOX_Directory( WND *wnd, LB_DESCR *descr, UINT32 attrib,
-                           LPCSTR filespec, BOOL32 long_names )
+static LRESULT LISTBOX_Directory( WND *wnd, LB_DESCR *descr, UINT32 attrib,
+                                  LPCSTR filespec, BOOL32 long_names )
 {
     HANDLE32 handle;
     LRESULT ret = LB_OKAY;
@@ -1681,11 +1700,15 @@
                                    !descr->items[index].selected), FALSE );
         }
     }
-    SetFocus32( wnd->hwndSelf );
+
+    if( !descr->lphc ) SetFocus32( wnd->hwndSelf );
+    else SetFocus32( (descr->lphc->hWndEdit) ? descr->lphc->hWndEdit
+                                             : descr->lphc->self->hwndSelf ) ;
+
     SetCapture32( wnd->hwndSelf );
-    if (index != -1)
+    if (index != -1 && !descr->lphc)
     {
-        if (descr->style & LBS_NOTIFY)
+        if (descr->style & LBS_NOTIFY )
             SendMessage32A( descr->owner, WM_LBTRACKPOINT, index,
                             MAKELPARAM( x, y ) );
         if (wnd->dwExStyle & WS_EX_DRAGDETECT)
@@ -1707,9 +1730,12 @@
     if (LISTBOX_Timer != LB_TIMER_NONE)
         KillSystemTimer32( wnd->hwndSelf, LB_TIMER_ID );
     LISTBOX_Timer = LB_TIMER_NONE;
-    if (GetCapture32() == wnd->hwndSelf) ReleaseCapture();
-    if (descr->style & LBS_NOTIFY)
-        SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
+    if (GetCapture32() == wnd->hwndSelf) 
+    {
+	ReleaseCapture();
+        if (descr->style & LBS_NOTIFY)
+            SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
+    }
     return 0;
 }
 
@@ -1819,8 +1845,7 @@
 /***********************************************************************
  *           LISTBOX_HandleKeyDown
  */
-static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr,
-                                      WPARAM32 wParam )
+static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr, WPARAM32 wParam )
 {
     INT32 caret = -1;
     if (descr->style & LBS_WANTKEYBOARDINPUT)
@@ -1899,7 +1924,14 @@
             descr->anchor_item = caret;
         LISTBOX_MoveCaret( wnd, descr, caret, TRUE );
         if (descr->style & LBS_NOTIFY)
+        {
+	    if( descr->lphc && CB_GETTYPE(descr->lphc) != CBS_SIMPLE )
+            {
+		/* make sure that combo parent doesn't hide us */
+		descr->lphc->wState |= CBF_NOROLLUP;
+	    }
             SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
+        }
     }
     return 0;
 }
@@ -1936,7 +1968,7 @@
 /***********************************************************************
  *           LISTBOX_Create
  */
-static BOOL32 LISTBOX_Create( WND *wnd )
+static BOOL32 LISTBOX_Create( WND *wnd, LPHEADCOMBO lphc )
 {
     LB_DESCR *descr;
     MEASUREITEMSTRUCT32 mis;
@@ -1970,6 +2002,14 @@
     descr->caret_on      = TRUE;
     descr->font          = 0;
     descr->locale        = 0;  /* FIXME */
+    descr->lphc		 = lphc;
+
+    if( lphc )
+    {
+	dprintf_combo(stddeb,"ComboLBox [%04x]: resetting owner %04x -> %04x\n",
+			      wnd->hwndSelf, descr->owner, lphc->self->hwndSelf );
+	descr->owner = lphc->self->hwndSelf;
+    }
 
     *(LB_DESCR **)wnd->wExtra = descr;
 
@@ -1980,15 +2020,24 @@
 
     if (descr->style & LBS_OWNERDRAWFIXED)
     {
-        mis.CtlType    = ODT_LISTBOX;
-        mis.CtlID      = wnd->wIDmenu;
-        mis.itemID     = 0;
-        mis.itemWidth  = 0;
-        mis.itemData   = 0;
-        mis.itemHeight = descr->item_height;
-        SendMessage32A( descr->owner, WM_MEASUREITEM, wnd->wIDmenu,
-                        (LPARAM)&mis );
-        descr->item_height = mis.itemHeight ? mis.itemHeight : 1;
+	if( descr->lphc && (descr->lphc->dwStyle & CBS_DROPDOWN))
+	{
+	    /* WinWord gets VERY unhappy if we send WM_MEASUREITEM from here */
+	    descr->item_height = lphc->RectButton.bottom - lphc->RectButton.top - 6;
+	}
+	else
+	{
+	    UINT32	id = (descr->lphc ) ? ID_CB_LISTBOX : wnd->wIDmenu;
+
+            mis.CtlType    = ODT_LISTBOX;
+            mis.CtlID      = id;
+            mis.itemID     = -1;
+            mis.itemWidth  =  0;
+            mis.itemData   =  0;
+            mis.itemHeight = descr->item_height;
+            SendMessage32A( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
+            descr->item_height = mis.itemHeight ? mis.itemHeight : 1;
+	}
     }
 
     return TRUE;
@@ -2003,7 +2052,7 @@
     LISTBOX_ResetContent( wnd, descr );
     HeapDestroy( descr->heap );
     HeapFree( GetProcessHeap(), 0, descr );
-    *(LB_DESCR **)wnd->wExtra = NULL;
+    wnd->wExtra[0] = 0;
     return TRUE;
 }
 
@@ -2022,7 +2071,7 @@
     {
         if (msg == WM_CREATE)
         {
-            if (!LISTBOX_Create( wnd )) return -1;
+            if (!LISTBOX_Create( wnd, NULL )) return -1;
             dprintf_listbox( stddeb, "Listbox: creating wnd=%04x descr=%p\n",
                              hwnd, *(LB_DESCR **)wnd->wExtra );
             return 0;
@@ -2305,9 +2354,10 @@
     case WM_PAINT:
         {
             PAINTSTRUCT32 ps;
-            HDC32 hdc = BeginPaint32( hwnd, &ps );
+            HDC32 hdc = ( wParam ) ? ((HDC32)wParam)
+				   :  BeginPaint32( hwnd, &ps );
             ret = LISTBOX_Paint( wnd, descr, hdc );
-            EndPaint32( hwnd, &ps );
+            if( !wParam ) EndPaint32( hwnd, &ps );
         }
         return ret;
 
@@ -2381,18 +2431,22 @@
         return 1;
 
     case WM_DROPFILES:
-        return SendMessage32A( descr->owner, msg, wParam, lParam );
+        if( !descr->lphc ) 
+	    return SendMessage32A( descr->owner, msg, wParam, lParam );
+	break;
 
     case WM_DROPOBJECT:
     case WM_QUERYDROPOBJECT:
     case WM_DRAGSELECT:
     case WM_DRAGMOVE:
-    {
-        LPDRAGINFO dragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN( (SEGPTR)lParam );
-        dragInfo->l = LISTBOX_GetItemFromPoint( wnd, descr, dragInfo->pt.x,
+	if( !descr->lphc )
+        {
+            LPDRAGINFO dragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN( (SEGPTR)lParam );
+            dragInfo->l = LISTBOX_GetItemFromPoint( wnd, descr, dragInfo->pt.x,
                                                 dragInfo->pt.y );
-        return SendMessage32A( descr->owner, msg, wParam, lParam );
-    }
+            return SendMessage32A( descr->owner, msg, wParam, lParam );
+        }
+	break;
 
     default:
         if ((msg >= WM_USER) && (msg < 0xc000))
@@ -2402,3 +2456,99 @@
     }
     return 0;
 }
+
+/***********************************************************************
+ *           COMBO_Directory
+ */
+LRESULT COMBO_Directory( LPHEADCOMBO lphc, UINT32 attrib, LPSTR dir, BOOL32 bLong)
+{
+    WND *wnd = WIN_FindWndPtr( lphc->hWndLBox );
+
+    if( wnd )
+    {
+        LB_DESCR *descr = *(LB_DESCR **)wnd->wExtra;
+	if( descr )
+	{
+	    LRESULT	lRet = LISTBOX_Directory( wnd, descr, attrib, dir, bLong );
+
+	    RedrawWindow32( lphc->self->hwndSelf, NULL, 0, 
+			    RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW );
+	    return lRet;
+	}
+    }
+    return CB_ERR;
+}
+
+/***********************************************************************
+ *           ComboLBWndProc
+ *
+ *  NOTE: in Windows, winproc address of the ComboLBox is the same 
+ *	  as that of the Listbox.
+ */
+LRESULT ComboLBWndProc(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
+{
+    LRESULT lRet = 0;
+    WND *wnd = WIN_FindWndPtr( hwnd );
+
+    if (wnd)
+    {
+	LB_DESCR *descr = *(LB_DESCR **)wnd->wExtra;
+
+        dprintf_combo( stddeb, "ComboLBox [%04x]: msg %s wp %08x lp %08lx\n",
+                       wnd->hwndSelf, SPY_GetMsgName(msg), wParam, lParam );
+
+	if( descr || msg == WM_CREATE )
+        {
+	    LPHEADCOMBO lphc = (descr) ? descr->lphc : NULL;
+
+	    switch( msg )
+	    {
+		case WM_CREATE:
+#define lpcs	((LPCREATESTRUCT32A)lParam)
+		     dprintf_combo(stddeb, "\tpassed parent handle = 0x%08x\n", 
+					         (UINT32)lpcs->lpCreateParams);
+
+		     lphc = (LPHEADCOMBO)(lpcs->lpCreateParams);
+#undef  lpcs
+		     return LISTBOX_Create( wnd, lphc );
+
+		case WM_LBUTTONDOWN:
+		     return LISTBOX_HandleLButtonDown( wnd, descr, wParam,
+                             (INT16)LOWORD(lParam), (INT16)HIWORD(lParam));
+
+		/* avoid activation at all costs */
+
+		case WM_MOUSEACTIVATE:
+		     return MA_NOACTIVATE;
+
+                case WM_NCACTIVATE:
+                     return FALSE;
+
+		case WM_KEYDOWN:
+		     if( CB_GETTYPE(lphc) != CBS_SIMPLE )
+		     {
+			 /* for some reason(?) Windows makes it possible to
+			  * show/hide ComboLBox by sending it WM_KEYDOWNs */
+
+		         if( (!(lphc->wState & CBF_EUI) && wParam == VK_F4) ||
+			     ( (lphc->wState & CBF_EUI) && !(lphc->wState & CBF_DROPPED)
+			       && (wParam == VK_DOWN || wParam == VK_UP)) )
+			 {
+			     COMBO_FlipListbox( lphc, FALSE );
+			     return 0;
+			 }
+		     }
+		     return LISTBOX_HandleKeyDown( wnd, descr, wParam );
+
+	        default:
+		     return ListBoxWndProc( hwnd, msg, wParam, lParam );
+	    }
+        }
+        lRet = DefWindowProc32A( hwnd, msg, wParam, lParam );
+
+        dprintf_combo(stddeb,"\tComboLBox: default on msg [%04x]\n", (UINT16)msg );
+    }
+
+    return lRet;
+}
+
diff --git a/controls/menu.c b/controls/menu.c
index 29d073c..06db580 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -304,32 +304,39 @@
  * Find the menu item selected by a key press.
  * Return item id, -1 if none, -2 if we should close the menu.
  */
-static UINT32 MENU_FindItemByKey( HWND32 hwndOwner, HMENU32 hmenu, UINT32 key )
+static UINT32 MENU_FindItemByKey( HWND32 hwndOwner, HMENU32 hmenu, 
+				  UINT32 key, BOOL32 forceMenuChar )
 {
-    POPUPMENU *menu;
-    MENUITEM *item;
-    UINT32 i;
-    LONG menuchar;
+    dprintf_menu(stddeb,"\tlooking for '%c' in [%04x]\n", (char)key, (UINT16)hmenu );
 
     if (!IsMenu32( hmenu )) hmenu = WIN_FindWndPtr(hwndOwner)->hSysMenu;
-    if (!hmenu) return -1;
 
-    menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
-    item = menu->items;
-    key = toupper(key);
-    for (i = 0; i < menu->nItems; i++, item++)
+    if (hmenu)
     {
-	if (IS_STRING_ITEM(item->item_flags))
+	POPUPMENU *menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
+	MENUITEM *item = menu->items;
+	LONG menuchar;
+
+	if( !forceMenuChar )
 	{
-	    char *p = strchr( item->text, '&' );
-	    if (p && (p[1] != '&') && (toupper(p[1]) == key)) return i;
+	     UINT32 i;
+
+	     key = toupper(key);
+	     for (i = 0; i < menu->nItems; i++, item++)
+	     {
+		if (IS_STRING_ITEM(item->item_flags))
+		{
+		    char *p = strchr( item->text, '&' );
+		    if (p && (p[1] != '&') && (toupper(p[1]) == key)) return i;
+		}
+	     }
 	}
+	menuchar = SendMessage32A( hwndOwner, WM_MENUCHAR, 
+                                   MAKEWPARAM( key, menu->wFlags ), hmenu );
+	if (HIWORD(menuchar) == 2) return LOWORD(menuchar);
+	if (HIWORD(menuchar) == 1) return (UINT32)(-2);
     }
-    menuchar = SendMessage32A( hwndOwner, WM_MENUCHAR, 
-                               MAKEWPARAM( key, menu->wFlags ), hmenu );
-    if (HIWORD(menuchar) == 2) return LOWORD(menuchar);
-    if (HIWORD(menuchar) == 1) return -2;
-    return -1;
+    return (UINT32)(-1);
 }
 
 
@@ -868,7 +875,7 @@
       /* Display the window */
 
     SetWindowPos32( menu->hWnd, HWND_TOP, 0, 0, 0, 0,
-		    SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
+		    SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
     UpdateWindow32( menu->hWnd );
     return TRUE;
 }
@@ -1310,7 +1317,7 @@
 	if (!(item->item_flags & (MF_GRAYED | MF_DISABLED)))
 	{
 	    PostMessage16( hwndOwner, (menu->wFlags & MF_SYSMENU) ? 
-                           WM_SYSCOMMAND : WM_COMMAND, item->item_id, 0 );
+			WM_SYSCOMMAND : WM_COMMAND, item->item_id, 0 );
 	    return FALSE;
 	}
 	else return TRUE;
@@ -1787,7 +1794,7 @@
 		      /* Hack to avoid control chars. */
 		      /* We will find a better way real soon... */
 		    if ((msg.wParam <= 32) || (msg.wParam >= 127)) break;
-		    pos = MENU_FindItemByKey( hwnd, hmenuCurrent, msg.wParam );
+		    pos = MENU_FindItemByKey( hwnd, hmenuCurrent, msg.wParam, FALSE );
 		    if (pos == (UINT32)-2) fClosed = TRUE;
 		    else if (pos == (UINT32)-1) MessageBeep32(0);
 		    else
@@ -1859,6 +1866,18 @@
 }
 
 /***********************************************************************
+ *           MENU_InitTracking
+ */
+static BOOL32 MENU_InitTracking(HWND32 hWnd, HMENU32 hMenu)
+{
+    HideCaret32(0);
+    SendMessage16( hWnd, WM_ENTERMENULOOP, 0, 0 );
+    SendMessage16( hWnd, WM_SETCURSOR, hWnd, HTCAPTION );
+    SendMessage16( hWnd, WM_INITMENU, hMenu, 0 );
+    return TRUE;
+}
+
+/***********************************************************************
  *           MENU_TrackMouseMenuBar
  *
  * Menu-bar tracking upon a mouse event. Called from NC_HandleSysCommand().
@@ -1872,9 +1891,7 @@
 
     if (IsMenu32(hMenu))
     {
-	HideCaret32(0);
-	SendMessage16( hWnd, WM_ENTERMENULOOP, 0, 0 );
-	SendMessage16( hWnd, WM_INITMENU, hMenu, 0 );
+	MENU_InitTracking( hWnd, hMenu );
 	if( bTrackSys )
 	    MENU_TrackSysPopup( wndPtr );
 	else
@@ -1904,28 +1921,30 @@
           
     if( !wndPtr->wIDmenu && !(wndPtr->dwStyle & WS_SYSMENU) ) return;
 
-    htMenu = ((wndPtr->dwStyle & (WS_CHILD | WS_MINIMIZE)) || 
-	      !wndPtr->wIDmenu) ? HTSYSMENU : HTMENU;
-    hTrackMenu = ( htMenu == HTSYSMENU ) ? wndPtr->hSysMenu : wndPtr->wIDmenu;
+    if((wndPtr->dwStyle & (WS_CHILD | WS_MINIMIZE)) || !wndPtr->wIDmenu) 
+    {
+	hTrackMenu = wndPtr->hSysMenu;
+	htMenu = HTSYSMENU;
+    }
+    else
+    {
+	hTrackMenu = wndPtr->wIDmenu;
+	htMenu = HTMENU;
+    }
 
     if (IsMenu32( hTrackMenu ))
     {
-        HideCaret32(0);
-        SendMessage16( wndPtr->hwndSelf, WM_ENTERMENULOOP, 0, 0 );
-        SendMessage16( wndPtr->hwndSelf, WM_INITMENU, hTrackMenu, 0 );
-
-        /* find suitable menu entry */
+	MENU_InitTracking( wndPtr->hwndSelf, hTrackMenu );
 
         if( vkey == VK_SPACE )
             uItem = SYSMENU_SELECTED;
         else if( vkey )
         {
-            uItem = ( htMenu == HTSYSMENU )
-		    ? 0xFFFE	/* only VK_SPACE in this case */
-		    : MENU_FindItemByKey( wndPtr->hwndSelf, wndPtr->wIDmenu, vkey );
-	    if( uItem >= 0xFFFE )
+            uItem = MENU_FindItemByKey( wndPtr->hwndSelf, hTrackMenu, 
+					vkey, (htMenu == HTSYSMENU) );
+	    if( uItem >= (UINT32)(-2) )
 	    {
-	        if( uItem == 0xFFFF ) MessageBeep32(0);
+	        if( uItem == (UINT32)(-1) ) MessageBeep32(0);
 		htMenu = 0;
 	    }
         }
@@ -2172,25 +2191,36 @@
  */
 BOOL32 EnableMenuItem32( HMENU32 hMenu, UINT32 wItemID, UINT32 wFlags )
 {
-    MENUITEM *item;
-    dprintf_menu(stddeb,"EnableMenuItem (%04x, %04X, %04X) !\n", 
-		 hMenu, wItemID, wFlags);
-    if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return FALSE;
+    BOOL32    bRet = FALSE;
+    MENUITEM *item, *first = NULL;
 
-      /* We can't have MF_GRAYED and MF_DISABLED together */
-    if (wFlags & MF_GRAYED)
+    dprintf_menu(stddeb,"EnableMenuItem (%04x, %04X, %04X) !\n", 
+		                        hMenu, wItemID, wFlags);
+
+    while( (item = MENU_FindItem( &hMenu, &wItemID, wFlags )) )
     {
-	item->item_flags = (item->item_flags & ~MF_DISABLED) | MF_GRAYED;
+      if( !(item->item_flags & MF_POPUP) )
+      {
+           /* We can't have MF_GRAYED and MF_DISABLED together */
+           if (wFlags & MF_GRAYED)
+           {
+  	     item->item_flags = (item->item_flags & ~MF_DISABLED) | MF_GRAYED;
+           }
+           else if (wFlags & MF_DISABLED)
+           {
+	     item->item_flags = (item->item_flags & ~MF_GRAYED) | MF_DISABLED;
+           }
+           else   /* MF_ENABLED */
+           {
+	     item->item_flags &= ~(MF_GRAYED | MF_DISABLED);
+           } 
+	   bRet = TRUE;
+	   break;
+      }
+      if( !first ) first = item;
+      else if( first == item ) break;
     }
-    else if (wFlags & MF_DISABLED)
-    {
-	item->item_flags = (item->item_flags & ~MF_GRAYED) | MF_DISABLED;
-    }
-    else   /* MF_ENABLED */
-    {
-	item->item_flags &= ~(MF_GRAYED | MF_DISABLED);
-    }
-    return TRUE;
+    return bRet;
 }
 
 
diff --git a/controls/oldlbox.c b/controls/oldlbox.c
deleted file mode 100644
index cbecfd9..0000000
--- a/controls/oldlbox.c
+++ /dev/null
@@ -1,767 +0,0 @@
-/*
- * 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 "listbox.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(HWND16 hwnd, WORD CtlType, LONG styles, HWND16 parent)
-{
-  LPHEADLIST lphl;
-  HDC32         hdc;
-
-  lphl = (LPHEADLIST)xmalloc(sizeof(HEADLIST));
-  SetWindowLong32A(hwnd, 0, (LONG)lphl);
-  ListBoxInitialize(lphl);
-  lphl->DrawCtlType    = CtlType;
-  lphl->CtlID          = GetWindowWord16(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);
-}
-
-/* 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;
-}
-
-
-/* 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, UINT16 uIndex)
-{
-  LPLISTSTRUCT lpls;
-  UINT16         Count = 0;
-
-  if (uIndex >= lphl->ItemsCount) return NULL;
-
-  lpls = lphl->lpFirst;
-  while (Count++ < uIndex) lpls = lpls->lpNext;
-  return lpls;
-}
-
-
-void ListBoxDrawItem(HWND16 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 = SetBkMode32(hdc, TRANSPARENT);
-
-      if (itemState != 0) {
-	dwOldTextColor = SetTextColor32(hdc, 0x00FFFFFFL);
-	FillRect16(hdc, rect, GetStockObject32(BLACK_BRUSH));
-      }
-
-      if (lphl->dwStyle & LBS_USETABSTOPS) {
-	TabbedTextOut16(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) {
-	SetTextColor32(hdc, dwOldTextColor);
-      }
-      
-      SetBkMode32(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;
-}
-
-/* -------------------- strings and item data ---------------------- */
-
-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);
-}
-
-static 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;
-}
-
-static int ListBoxAskCompare(LPHEADLIST lphl, int startItem, SEGPTR matchData, BOOL32 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, UINT16 uIndex, LPCSTR newstr)
-{
-  LPLISTSTRUCT *lppls, lplsnew, lpls;
-  HANDLE16 hStr;
-  LPSTR	str;
-  UINT16	Count;
-    
-  dprintf_listbox(stddeb,"ListBoxInsertString(%d, %p);\n", uIndex, newstr);
-    
-  if (!newstr) return -1;
-
-  if (uIndex == (UINT16)-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)
-{
-    UINT16 	pos = (UINT16) -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, UINT16 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, UINT16 uIndex)
-{
-  LPLISTSTRUCT lpls;
-
-  lpls = ListBoxGetItem (lphl, uIndex);
-  if (lpls == NULL) return LB_ERR;
-  return lpls->mis.itemData;
-}
-
-
-int ListBoxSetItemData(LPHEADLIST lphl, UINT16 uIndex, DWORD ItemData)
-{
-  LPLISTSTRUCT lpls = ListBoxGetItem(lphl, uIndex);
-
-  if (lpls == NULL) return LB_ERR;
-  lpls->mis.itemData = ItemData;
-  return 1;
-}
-
-
-int ListBoxDeleteString(LPHEADLIST lphl, UINT16 uIndex)
-{
-  LPLISTSTRUCT lpls, lpls2;
-  UINT16	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;
-}
-
-static int lbFindString(LPHEADLIST lphl, UINT16 nFirst, SEGPTR MatchStr, BOOL32 match)
-{
-  /*  match is either MATCH_SUBSTR or MATCH_EXACT */
-
-  LPLISTSTRUCT lpls;
-  UINT16	       Count;
-  UINT16         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, UINT16 nFirst, SEGPTR MatchStr)
-{
-  return lbFindString(lphl, nFirst, MatchStr, MATCH_SUBSTR );
-}
-
-int ListBoxFindStringExact(LPHEADLIST lphl, UINT16 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 != (UINT16)-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;
-}
-
-
-
-/* ------------------------- dir listing ------------------------ */
-
-LONG ListBoxDirectory(LPHEADLIST lphl, UINT16 attrib, LPCSTR filespec)
-{
-    return 0;
-}
-
-/* ------------------------- 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;
-  UINT16 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;
-}
diff --git a/controls/scroll.c b/controls/scroll.c
index 819ff5d..d2371f1 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -421,11 +421,7 @@
 
       /* Draw the scroll bar frame */
 
-    MoveTo( hdc, r.left, r.top );
-    LineTo32( hdc, r.right-1, r.top );
-    LineTo32( hdc, r.right-1, r.bottom-1 );
-    LineTo32( hdc, r.left, r.bottom-1 );
-    LineTo32( hdc, r.left, r.top );
+    GRAPH_DrawRectangle( hdc, r.left, r.top, r.right - 1, r.bottom - 1, 0);
 
       /* Draw the scroll rectangles and thumb */
 
diff --git a/controls/widgets.c b/controls/widgets.c
index ffc2a23..6f1723f 100644
--- a/controls/widgets.c
+++ b/controls/widgets.c
@@ -4,6 +4,8 @@
  * Copyright 1993 Alexandre Julliard
  */
 
+#include <assert.h>
+
 #include "win.h"
 #include "commctrl.h"
 #include "button.h"
@@ -20,6 +22,10 @@
 
 extern LRESULT EditWndProc( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
                             LPARAM lParam );
+extern LRESULT ComboWndProc( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
+                             LPARAM lParam );
+extern LRESULT ComboLBWndProc( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
+                               LPARAM lParam );
 extern LRESULT ListBoxWndProc( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
                                LPARAM lParam );
 extern LRESULT PopupMenuWndProc( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
@@ -42,10 +48,6 @@
 {
     { CS_GLOBALCLASS | CS_PARENTDC,
        sizeof(STATICINFO), 0, "StaticWndProc", "Static" },
-    { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS,
-      8, 0, "ComboBoxWndProc", "ComboBox" },
-    { CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS,
-      8, 0, "ComboLBoxWndProc", "ComboLBox" },
     { CS_GLOBALCLASS, sizeof(MDICLIENTINFO),
       STOCK_LTGRAY_BRUSH, "MDIClientWndProc", "MDIClient" }
 };
@@ -55,27 +57,38 @@
 
 /* Win32 built-in classes */
 
-static WNDCLASS32A WIDGETS_BuiltinClasses32[] =
+static WNDCLASS32A WIDGETS_BuiltinClasses32[BIC32_NB_CLASSES] =
 {
+    /* BIC32_BUTTON */
     { CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC,
       ButtonWndProc, 0, sizeof(BUTTONINFO), 0, 0, 0, 0, 0, "Button" },
+    /* BIC32_EDIT */
     { CS_GLOBALCLASS | CS_DBLCLKS /*| CS_PARENTDC*/,
       EditWndProc, 0, sizeof(void *), 0, 0, 0, 0, 0, "Edit" },
+    /* BIC32_LISTBOX */
     { CS_GLOBALCLASS | CS_DBLCLKS /*| CS_PARENTDC*/,
       ListBoxWndProc, 0, sizeof(void *), 0, 0, 0, 0, 0, "ListBox" },
+    /* BIC32_COMBO */
+    { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, 
+      ComboWndProc, 0, sizeof(void *), 0, 0, 0, 0, 0, "ComboBox" },
+    /* BIC32_COMBOLB */
+    { CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS,
+      ComboLBWndProc, 0, sizeof(void *), 0, 0, 0, 0, 0, "ComboLBox" },
+    /* BIC32_POPUPMENU */
     { CS_GLOBALCLASS | CS_SAVEBITS, PopupMenuWndProc,
       0, sizeof(HMENU32), 0, 0, 0, 0, 0, POPUPMENU_CLASS_NAME },
+    /* BIC32_SCROLL */
     { CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC,
       ScrollBarWndProc, 0, sizeof(SCROLLBAR_INFO), 0, 0, 0, 0, 0, "ScrollBar"},
+    /* BIC32_DESKTOP */
     { CS_GLOBALCLASS, DesktopWndProc, 0, sizeof(DESKTOPINFO),
       0, 0, 0, 0, 0, DESKTOP_CLASS_NAME },
+    /* BIC32_DIALOG */
     { CS_GLOBALCLASS | CS_SAVEBITS, DefDlgProc32A, 0, DLGWINDOWEXTRA,
       0, 0, 0, 0, 0, DIALOG_CLASS_NAME }
 };
 
-#define NB_BUILTIN_CLASSES32 \
-         (sizeof(WIDGETS_BuiltinClasses32)/sizeof(WIDGETS_BuiltinClasses32[0]))
-
+static ATOM bicAtomTable[BIC32_NB_CLASSES];
 
 /* Win32 common controls */
 
@@ -124,13 +137,13 @@
 
     /* Create 32-bit classes */
 
-    for (i = 0; i < NB_BUILTIN_CLASSES32; i++, class32++)
+    for (i = 0; i < BIC32_NB_CLASSES; i++, class32++)
     {
         /* Just to make sure the string is > 0x10000 */
         strcpy( name, (char *)class32->lpszClassName );
         class32->lpszClassName = name;
         class32->hCursor = LoadCursor16( 0, IDC_ARROW );
-        if (!RegisterClass32A( class32 )) return FALSE;
+        if (!(bicAtomTable[i] = RegisterClass32A( class32 ))) return FALSE;
     }
 
     SEGPTR_FREE(name);
@@ -156,3 +169,15 @@
         RegisterClass32A( class32 );
     }
 }
+
+
+/***********************************************************************
+ *           WIDGETS_IsControl32
+ *
+ * Check whether pWnd is a built-in control or not.
+ */
+BOOL32	WIDGETS_IsControl32( WND* pWnd, BUILTIN_CLASS32 cls )
+{
+    assert( cls < BIC32_NB_CLASSES );
+    return (pWnd->class->atomName == bicAtomTable[cls]);
+}
diff --git a/debugger/msc.c b/debugger/msc.c
index fd8da77..844e642 100644
--- a/debugger/msc.c
+++ b/debugger/msc.c
@@ -1843,6 +1843,11 @@
    */
   addr = mmap(0, statbuf.st_size, PROT_READ, 
 	      MAP_PRIVATE, fd, 0);
+  if( addr == (char *) 0xffffffff )
+    {
+      fprintf(stderr, "Unable to mmap .DBG file %s\n", filename);
+      goto leave;
+    }
 
   /*
    * Now that we have the formalities over and done with, we need
@@ -2166,6 +2171,11 @@
    */
   addr = mmap(0, statbuf.st_size, PROT_READ, 
 	      MAP_PRIVATE, fd, 0);
+  if( addr == (char *) 0xffffffff )
+    {
+      fprintf(stderr, "Unable to mmap .DBG file %s\n", filename);
+      goto leave;
+    }
 
   pdbg = (LPIMAGE_SEPARATE_DEBUG_HEADER) addr;
 
diff --git a/debugger/stabs.c b/debugger/stabs.c
index 9e64a36..83e99bf 100644
--- a/debugger/stabs.c
+++ b/debugger/stabs.c
@@ -1103,6 +1103,10 @@
    */
   addr = mmap(0, statbuf.st_size, PROT_READ, 
 	      MAP_PRIVATE, fd, 0);
+  if( addr == (char *) 0xffffffff )
+    {
+      goto leave;
+    }
 
   /*
    * Give a nice status message here...
@@ -1337,6 +1341,10 @@
    */
   addr = mmap(0, statbuf.st_size, PROT_READ, 
 	      MAP_PRIVATE, fd, 0);
+  if( addr == (char *) 0xffffffff )
+    {
+      goto leave;
+    }
 
   ahdr = (struct exec *) addr;
 
diff --git a/files/dos_fs.c b/files/dos_fs.c
index 46786dd..38a84c8 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -33,6 +33,15 @@
 /* FIXME: is it possible to get this to work on other systems? */
 #ifdef linux
 #define VFAT_IOCTL_READDIR_BOTH  _IOR('r', 1, long)
+/* We want the real kernel dirent structure, not the libc one */
+typedef struct
+{
+    long d_ino;
+    long d_off;
+    unsigned short d_reclen;
+    char d_name[256];
+} KERNEL_DIRENT;
+
 #else   /* linux */
 #undef VFAT_IOCTL_READDIR_BOTH  /* just in case... */
 #endif  /* linux */
@@ -83,7 +92,7 @@
 #ifdef VFAT_IOCTL_READDIR_BOTH
     int            fd;
     char           short_name[12];
-    struct dirent  dirent[2];
+    KERNEL_DIRENT  dirent[2];
 #endif
 } DOS_DIR;
 
@@ -948,16 +957,11 @@
         if (dir) DOSFS_CloseDir(dir);
         if (!*path) path = "/";
         if (!(dir = DOSFS_OpenDir(path))) return 0;
-        drive_path = path;
-        drive_root = 0;
-        if (DRIVE_FindDriveRoot( &drive_path ) != -1)
-        {
-            while ((*drive_path == '/') || (*drive_path == '\\')) drive_path++;
-            if (!*drive_path) drive_root = 1;
-        }
+        drive_path = path + strlen(DRIVE_GetRoot(drive));
+        while ((*drive_path == '/') || (*drive_path == '\\')) drive_path++;
+        drive_root = !*drive_path;
         dprintf_dosfs(stddeb, "DOSFS_FindNext: drive_root = %d\n", drive_root);
         lstrcpyn32A( buffer, path, sizeof(buffer) - 1 );
-        
     }
     strcat( buffer, "/" );
     p = buffer + strlen(buffer);
diff --git a/files/drive.c b/files/drive.c
index dabebf8..3fb43c1 100644
--- a/files/drive.c
+++ b/files/drive.c
@@ -43,6 +43,8 @@
     DWORD     serial;    /* drive serial number */
     DRIVETYPE type;      /* drive type */
     UINT32    flags;     /* drive flags */
+    dev_t     dev;       /* unix device number */
+    ino_t     ino;       /* unix inode number */
 } DOSDRIVE;
 
 
@@ -124,6 +126,7 @@
     char name[] = "Drive A";
     char path[MAX_PATHNAME_LEN];
     char buffer[20];
+    struct stat drive_stat_buffer;
     char *p;
     DOSDRIVE *drive;
 
@@ -134,14 +137,28 @@
         {
             p = path + strlen(path) - 1;
             while ((p > path) && ((*p == '/') || (*p == '\\'))) *p-- = '\0';
-            if (strlen(path))
-                drive->root = HEAP_strdupA( SystemHeap, 0, path );
-            else
-                drive->root = HEAP_strdupA( SystemHeap, 0, "/" );
+            if (!path[0]) strcpy( path, "/" );
+
+            if (stat( path, &drive_stat_buffer ))
+            {
+                fprintf( stderr, "Could not stat %s, ignoring drive %c:\n",
+                         path, 'A' + i );
+                continue;
+            }
+            if (!S_ISDIR(drive_stat_buffer.st_mode))
+            {
+                fprintf( stderr, "%s is not a directory, ignoring drive %c:\n",
+                         path, 'A' + i );
+                continue;
+            }
+
+            drive->root = HEAP_strdupA( SystemHeap, 0, path );
             drive->dos_cwd  = HEAP_strdupA( SystemHeap, 0, "" );
             drive->unix_cwd = HEAP_strdupA( SystemHeap, 0, "" );
             drive->type     = DRIVE_GetDriveType( name );
             drive->flags    = 0;
+            drive->dev      = drive_stat_buffer.st_dev;
+            drive->ino      = drive_stat_buffer.st_ino;
 
             /* Get the drive label */
             PROFILE_GetWineIniString( name, "Label", name, drive->label, 12 );
@@ -167,9 +184,10 @@
                 DRIVE_CurDrive = i;
 
             count++;
-            dprintf_dosfs( stddeb, "%s: path=%s type=%s label='%s' serial=%08lx flags=%08x\n",
+            dprintf_dosfs( stddeb, "%s: path=%s type=%s label='%s' serial=%08lx flags=%08x dev=%x ino=%x\n",
                            name, path, DRIVE_Types[drive->type],
-                           drive->label, drive->serial, drive->flags );
+                           drive->label, drive->serial, drive->flags,
+                           (int)drive->dev, (int)drive->ino );
         }
         else dprintf_dosfs( stddeb, "%s: not defined\n", name );
     }
@@ -252,51 +270,54 @@
  * This can be used to translate a Unix path into a drive + DOS path.
  * Return value is the drive, or -1 on error. On success, path is modified
  * to point to the beginning of the DOS path.
- * FIXME: this only does a textual comparison of the path names, and won't
- *        work well in the presence of symbolic links.
  */
 int DRIVE_FindDriveRoot( const char **path )
 {
+    /* idea: check at all '/' positions.
+     * If the device and inode of that path is identical with the
+     * device and inode of the current drive then we found a solution.
+     * If there is another drive pointing to a deeper position in
+     * the file tree, we want to find that one, not the earlier solution.
+     */
     int drive, rootdrive = -1;
-    const char *p1, *p2;
+    char buffer[MAX_PATHNAME_LEN];
+    char *next = buffer;
+    const char *p = *path;
+    struct stat st;
 
-    dprintf_dosfs( stddeb, "DRIVE_FindDriveRoot: searching '%s'\n", *path );
-    for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
+    strcpy( buffer, "/" );
+    for (;;)
     {
-        if (!DOSDrives[drive].root ||
-            (DOSDrives[drive].flags & DRIVE_DISABLED)) continue;
-        p1 = *path;
-        p2 = DOSDrives[drive].root;
-        dprintf_dosfs( stddeb, "DRIVE_FindDriveRoot: checking %c: '%s'\n",
-                       'A' + drive, p2 );
-        
-        while (*p2 == '/') p2++;
-        if (!*p2)
+        if (stat( buffer, &st ) || !S_ISDIR( st.st_mode )) break;
+
+        /* Find the drive */
+
+        for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
         {
-            rootdrive = drive;
-            continue;  /* Look if there's a better match */
+           if (!DOSDrives[drive].root ||
+               (DOSDrives[drive].flags & DRIVE_DISABLED)) continue;
+
+           if ((DOSDrives[drive].dev == st.st_dev) &&
+               (DOSDrives[drive].ino == st.st_ino))
+           {
+               rootdrive = drive;
+               *path = p;
+           }
         }
-        for (;;)
-        {
-            while ((*p1 == '\\') || (*p1 == '/')) p1++;
-            while (*p2 == '/') p2++;
-            while ((*p1 == *p2) && (*p2) && (*p2 != '/')) p1++, p2++;
-            if (!*p2)
-            {
-                if (IS_END_OF_NAME(*p1)) /* OK, found it */
-                {
-                    *path = p1;
-                    return drive;
-                }
-            }
-            else if (*p2 == '/')
-            {
-                if (IS_END_OF_NAME(*p1))
-                    continue;  /* Go to next path element */
-            }
-            break;  /* No match, go to next drive */
-        }
+
+        /* Get the next path component */
+
+        *next++ = '/';
+        while ((*p == '/') || (*p == '\\')) p++;
+        if (!*p) break;
+        while (!IS_END_OF_NAME(*p)) *next++ = *p++;
+        *next = 0;
     }
+
+    if (rootdrive != -1)
+        dprintf_dosfs( stddeb, "DRIVE_FindDriveRoot: %s -> drive %c:, root='%s', name='%s'\n",
+                       buffer, 'A' + rootdrive,
+                       DOSDrives[rootdrive].root, *path );
     return rootdrive;
 }
 
diff --git a/graphics/metafiledrv/init.c b/graphics/metafiledrv/init.c
index 08dac5d..7851f43 100644
--- a/graphics/metafiledrv/init.c
+++ b/graphics/metafiledrv/init.c
@@ -28,6 +28,7 @@
     NULL,                            /* pExcludeVisRect */
     MFDRV_ExtFloodFill,              /* pExtFloodFill */
     MFDRV_ExtTextOut,                /* pExtTextOut */
+    NULL,                            /* pGetCharWidth */
     NULL /* no implementation */,    /* pGetPixel */
     NULL,                            /* pGetTextExtentPoint */
     NULL,                            /* pGetTextMetrics */
diff --git a/graphics/win16drv/Makefile.in b/graphics/win16drv/Makefile.in
index 0c408ad..895b2bb 100644
--- a/graphics/win16drv/Makefile.in
+++ b/graphics/win16drv/Makefile.in
@@ -9,6 +9,7 @@
 	font.c \
 	init.c \
 	objects.c \
+	prtdrv.c \
 	text.c
 
 all: $(MODULE).o
diff --git a/graphics/win16drv/font.c b/graphics/win16drv/font.c
index 678ed90..09bc7aa 100644
--- a/graphics/win16drv/font.c
+++ b/graphics/win16drv/font.c
@@ -18,6 +18,12 @@
                                     LPSIZE32 size )
 {
     WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
+    DWORD dwRet;
+    extern DRAWMODE DrawMode;
+    LPDRAWMODE lpDrawMode = &DrawMode;
+    TEXTXFORM16 TextXForm;
+    LPTEXTXFORM16 lpTextXForm = &TextXForm;
+    InitTextXForm(lpTextXForm);
     
     printf("LPGDI_GetTextExtPoint: %04x %s %d %p\n", dc->hSelf, str, count, size);
 
@@ -25,7 +31,16 @@
 	/* Assume fixed font */
     size->cx = count * physDev->tm.tmAveCharWidth;
     size->cy = physDev->tm.tmHeight;
+
+
     printf("LPGDI_GetTextExtPoint: cx=%d, cy=%d\n", size->cx,size->cy);
+
+    dwRet = PRTDRV_ExtTextOut(physDev->segptrPDEVICE, 0, 0, 
+			      NULL, str, 
+			      -count,  physDev->segptrFontInfo, lpDrawMode, 
+			      lpTextXForm, NULL, NULL, 0);
+    printf("LPGDI_GetTextExtPoint: cx=0x%x, cy=0x%x Ret 0x%x\n", size->cx,size->cy,dwRet);
+
     return TRUE;
 }
 
@@ -79,3 +94,20 @@
     printf("In WIN16DRV_FONT_SelectObject\n");
     return GetStockObject32(SYSTEM_FIXED_FONT);
 }
+
+/***********************************************************************
+ *           GetCharWidth32A    (GDI32.155)
+ */
+BOOL32 WIN16DRV_GetCharWidth( DC *dc, UINT32 firstChar, UINT32 lastChar,
+			    LPINT32 buffer )
+{
+    int i;
+    WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
+    /* TTD Need to cope with PS fonts */    
+    for (i = firstChar; i <= lastChar; i++)
+         *buffer++ = physDev->tm.tmAveCharWidth;
+    return TRUE;
+}
+
+
+
diff --git a/graphics/win16drv/init.c b/graphics/win16drv/init.c
index fec0eb0..47a397b 100644
--- a/graphics/win16drv/init.c
+++ b/graphics/win16drv/init.c
@@ -22,8 +22,7 @@
 #include "stddebug.h"
 #include "debug.h"
 
-#define SUPPORT_REALIZED_FONTS 1 	
-typedef SEGPTR LPPDEVICE;
+#define SUPPORT_REALIZED_FONTS 1
 
 
 #if 0
@@ -51,6 +50,7 @@
     NULL,                            /* pExcludeVisRect */
     NULL,                            /* pExtFloodFill */
     WIN16DRV_ExtTextOut,             /* pExtTextOut */
+    WIN16DRV_GetCharWidth,           /* pGetCharWidth */
     NULL,                            /* pGetPixel */
     WIN16DRV_GetTextExtentPoint,     /* pGetTextExtentPoint */
     WIN16DRV_GetTextMetrics,         /* pGetTextMetrics */
@@ -101,9 +101,7 @@
 };
 
 
-#define MAX_PRINTER_DRIVERS 	16
 
-static LOADED_PRINTER_DRIVER *gapLoadedPrinterDrivers[MAX_PRINTER_DRIVERS];
 
 
 /**********************************************************************
@@ -149,295 +147,6 @@
     lpDrawMode->LbkColor	= 0x00ffffff;   
     lpDrawMode->LTextColor	= 0x00000000;     
 }
-/* 
- * Thunking utility functions
- */
-
-static BOOL32 AddData(SEGPTR *pSegPtr, const void *pData, int nSize, SEGPTR Limit)
-{
-    BOOL32 bRet = FALSE;
-    char *pBuffer = PTR_SEG_TO_LIN((*pSegPtr));
-    char *pLimit = PTR_SEG_TO_LIN(Limit);
-
-
-    if ((pBuffer + nSize) < pLimit)
-    {
-	DWORD *pdw = (DWORD *)pSegPtr;
-	SEGPTR SegPtrOld = *pSegPtr;
-	SEGPTR SegPtrNew;
-
-	dprintf_win16drv(stddeb, "AddData: Copying %d from %p to %p(0x%x)\n", nSize, pData, pBuffer, (UINT32)*pSegPtr);
-	memcpy(pBuffer, pData, nSize); 
-	SegPtrNew = (SegPtrOld + nSize + 1);
-	*pdw = (DWORD)SegPtrNew;
-    }
-    return bRet;
-}
-
-
-static BOOL32 GetParamData(SEGPTR SegPtrSrc,void *pDataDest, int nSize)
-{
-    char *pSrc =  PTR_SEG_TO_LIN(SegPtrSrc);
-    char *pDest = pDataDest;
-
-    dprintf_win16drv(stddeb, "GetParamData: Copying %d from %lx(%lx) to %lx\n", nSize, (DWORD)pSrc, (DWORD)SegPtrSrc, (DWORD)pDataDest);
-    memcpy(pDest, pSrc, nSize);
-    return TRUE;
-}
-
-
-static void GetPrinterDriverFunctions(HINSTANCE16 hInst, LOADED_PRINTER_DRIVER *pLPD)
-{
-#define LoadPrinterDrvFunc(A,B) pLPD->fn[A] = \
-      GetProcAddress16(hInst, MAKEINTRESOURCE(B))
-
-      LoadPrinterDrvFunc(FUNC_CONTROL, ORD_CONTROL); 	       	/* 3 */
-      LoadPrinterDrvFunc(FUNC_ENABLE, ORD_ENABLE);		/* 5 */
-      LoadPrinterDrvFunc(FUNC_ENUMDFONTS, ORD_ENUMDFONTS);	/* 6 */
-      LoadPrinterDrvFunc(FUNC_REALIZEOBJECT, ORD_REALIZEOBJECT);/* 10 */
-      LoadPrinterDrvFunc(FUNC_EXTTEXTOUT, ORD_EXTTEXTOUT);	/* 14 */
-      dprintf_win16drv (stddeb,"got func CONTROL 0x%p enable 0x%p enumDfonts 0x%p realizeobject 0x%p extextout 0x%p\n",
-              pLPD->fn[FUNC_CONTROL],
-              pLPD->fn[FUNC_ENABLE],
-              pLPD->fn[FUNC_ENUMDFONTS],
-              pLPD->fn[FUNC_REALIZEOBJECT],
-              pLPD->fn[FUNC_EXTTEXTOUT]);
-      
-
-}
-
-static LOADED_PRINTER_DRIVER *FindPrinterDriverFromPDEVICE(SEGPTR segptrPDEVICE)
-{
-    LOADED_PRINTER_DRIVER *pLPD = NULL;
-
-    /* Find the printer driver associated with this PDEVICE */
-    /* Each of the PDEVICE structures has a PDEVICE_HEADER structure */
-    /* just before it */
-    if (segptrPDEVICE != (SEGPTR)NULL)
-    {
-	PDEVICE_HEADER *pPDH = (PDEVICE_HEADER *)
-	  (PTR_SEG_TO_LIN(segptrPDEVICE) - sizeof(PDEVICE_HEADER)); 
-        pLPD = pPDH->pLPD;
-    }
-    return pLPD;
-}
-
-static LOADED_PRINTER_DRIVER *FindPrinterDriverFromName(const char *pszDriver)
-{
-    LOADED_PRINTER_DRIVER *pLPD = NULL;
-    int		nDriverSlot = 0;
-
-    /* Look to see if the printer driver is already loaded */
-    while (pLPD == NULL && nDriverSlot < MAX_PRINTER_DRIVERS)
-    {
-	LOADED_PRINTER_DRIVER *ptmpLPD;
-	ptmpLPD = gapLoadedPrinterDrivers[nDriverSlot++];
-	if (ptmpLPD != NULL)
-	{
-	    dprintf_win16drv(stddeb, "Comparing %s,%s\n",ptmpLPD->szDriver,pszDriver);
-	    /* Found driver store info, exit loop */
-	    if (lstrcmpi32A(ptmpLPD->szDriver, pszDriver) == 0)
-	      pLPD = ptmpLPD;
-	}
-    }
-    if (pLPD == NULL) printf("Couldn't find driver %s\n", pszDriver);
-    return pLPD;
-}
-/* 
- * Load a printer driver, adding it self to the list of loaded drivers.
- */
-
-static LOADED_PRINTER_DRIVER *LoadPrinterDriver(const char *pszDriver)
-{                                        
-    HINSTANCE16	hInst;	
-    LOADED_PRINTER_DRIVER *pLPD = NULL;
-    int		nDriverSlot = 0;
-    BOOL32	bSlotFound = FALSE;
-
-    /* First look to see if driver is loaded */
-    pLPD = FindPrinterDriverFromName(pszDriver);
-    if (pLPD != NULL)
-    {
-	/* Already loaded so increase usage count */
-	pLPD->nUsageCount++;
-	return pLPD;
-    }
-
-    /* Not loaded so try and find an empty slot */
-    while (!bSlotFound && nDriverSlot < MAX_PRINTER_DRIVERS)
-    {
-	if (gapLoadedPrinterDrivers[nDriverSlot] == NULL)
-	  bSlotFound = TRUE;
-	else
-	  nDriverSlot++;
-    }
-    if (!bSlotFound)
-    {
-	printf("Too many printers drivers loaded\n");
-	return NULL;
-    }
-
-    {
-        char *drvName = malloc(strlen(pszDriver)+5);
-        strcpy(drvName, pszDriver);
-        strcat(drvName, ".DRV");
-        hInst = LoadLibrary16(drvName);
-    }
-    dprintf_win16drv(stddeb, "Loaded the library\n");
-
-    
-    if (hInst <= 32)
-    {
-	/* Failed to load driver */
-	fprintf(stderr, "Failed to load printer driver %s\n", pszDriver);
-    }
-    else
-    {
-	HANDLE16 hHandle;
-
-	/* Allocate some memory for printer driver info */
-	pLPD = malloc(sizeof(LOADED_PRINTER_DRIVER));
-	memset(pLPD, 0 , sizeof(LOADED_PRINTER_DRIVER));
-	
-	pLPD->hInst = hInst;
-	strcpy(pLPD->szDriver,pszDriver);
-
-	/* Get DS for the printer module */
-	pLPD->ds_reg = hInst;
-
-	dprintf_win16drv(stddeb, "DS for %s is %x\n", pszDriver, pLPD->ds_reg);
-
-	/* Get address of printer driver functions */
-	GetPrinterDriverFunctions(hInst, pLPD);
-
-	/* Set initial usage count */
-	pLPD->nUsageCount = 1;
-
-	/* Create a thunking buffer */
-	hHandle = GlobalAlloc16(GHND, (1024 * 8));
-	pLPD->hThunk = hHandle;
-	pLPD->ThunkBufSegPtr = WIN16_GlobalLock16(hHandle);
-	pLPD->ThunkBufLimit = pLPD->ThunkBufSegPtr + (1024*8);
-
-	/* Update table of loaded printer drivers */
-	pLPD->nIndex = nDriverSlot;
-	gapLoadedPrinterDrivers[nDriverSlot] = pLPD;
-    }
-
-    return pLPD;
-}
-/*
- *  Control (ordinal 3)
- */
-INT16 PRTDRV_Control(LPPDEVICE lpDestDev, WORD wfunction, SEGPTR lpInData, SEGPTR lpOutData)
-{
-    /* wfunction == Escape code */
-    /* lpInData, lpOutData depend on code */
-
-    WORD wRet = 0;
-    LOADED_PRINTER_DRIVER *pLPD = NULL;
-
-    dprintf_win16drv(stddeb, "PRTDRV_Control: %08x 0x%x %08lx %08lx\n", (unsigned int)lpDestDev, wfunction, lpInData, lpOutData);
-
-    if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
-    {
-	LONG lP1, lP3, lP4;
-	WORD wP2;
-
-	if (pLPD->fn[FUNC_CONTROL] == NULL)
-	{
-	    dprintf_win16drv(stddeb, "PRTDRV_Control: Not supported by driver\n");
-	    return 0;
-	}
-
-	lP1 = (SEGPTR)lpDestDev;
-	wP2 = wfunction;
-	lP3 = (SEGPTR)lpInData;
-	lP4 = (SEGPTR)lpOutData;
-
-	wRet = CallTo16_word_lwll(pLPD->fn[FUNC_CONTROL], 
-                                  lP1, wP2, lP3, lP4);
-    }
-    dprintf_win16drv(stddeb, "PRTDRV_Control: return %x\n", wRet);
-    return wRet;
-
-    return 0;
-}
-
-/*
- *	Enable (ordinal 5)
- */
-static WORD PRTDRV_Enable(LPVOID lpDevInfo, WORD wStyle, LPCSTR  lpDestDevType, 
-                          LPCSTR lpDeviceName, LPCSTR lpOutputFile, LPVOID lpData)
-{
-    WORD wRet = 0;
-    LOADED_PRINTER_DRIVER *pLPD = NULL;
-
-    dprintf_win16drv(stddeb, "PRTDRV_Enable: %s %s\n",lpDestDevType, lpOutputFile);
-
-    /* Get the printer driver info */
-    if (wStyle == INITPDEVICE)
-    {
-	pLPD = FindPrinterDriverFromPDEVICE((SEGPTR)lpDevInfo);
-    }
-    else
-    {
-	pLPD = FindPrinterDriverFromName((char *)lpDeviceName);
-    }
-    if (pLPD != NULL)
-    {
-	LONG lP1, lP3, lP4, lP5;
-	WORD wP2;
-	SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
-	SEGPTR Limit = pLPD->ThunkBufLimit;
-	int   nSize;
-
-	if (pLPD->fn[FUNC_ENABLE] == NULL)
-	{
-	    dprintf_win16drv(stddeb, "PRTDRV_Enable: Not supported by driver\n");
-	    return 0;
-	}
-
-	if (wStyle == INITPDEVICE)
-	{
-	    /* All ready a 16 address */
-	    lP1 = (SEGPTR)lpDevInfo;
-	}
-	else
-	{
-	    /* 32 bit data */
-	    lP1 = SegPtr;
-	    nSize = sizeof(DeviceCaps);
-	    AddData(&SegPtr, lpDevInfo, nSize, Limit);	
-	}
-	
-	wP2 = wStyle;
-	
-	lP3 = SegPtr;
-	nSize = strlen(lpDestDevType) + 1;
-	AddData(&SegPtr, lpDestDevType, nSize, Limit);	
-
-	lP4 = SegPtr; 
-	nSize = strlen(lpOutputFile) + 1;
-	AddData(&SegPtr, lpOutputFile, nSize, Limit);	
-
-	lP5 = (LONG)lpData;
-        
-
-	wRet = CallTo16_word_lwlll(pLPD->fn[FUNC_ENABLE], 
-				   lP1, wP2, lP3, lP4, lP5);
-
-	/* Get the data back */
-	if (lP1 != 0 && wStyle != INITPDEVICE)
-	{
-	    nSize = sizeof(DeviceCaps);
-	    GetParamData(lP1, lpDevInfo, nSize);
-	}
-    }
-    dprintf_win16drv(stddeb, "PRTDRV_Enable: return %x\n", wRet);
-    return wRet;
-}
-
 
 /*
  * EnumCallback (GDI.158)
@@ -493,120 +202,6 @@
     return wRet;
 }
 
-/*
- *	EnumDFonts (ordinal 6)
- */
-WORD PRTDRV_EnumDFonts(LPPDEVICE lpDestDev, LPSTR lpFaceName,  
-		       FARPROC16 lpCallbackFunc, LPVOID lpClientData)
-{
-    WORD wRet = 0;
-    LOADED_PRINTER_DRIVER *pLPD = NULL;
-
-    dprintf_win16drv(stddeb, "PRTDRV_EnumDFonts:\n");
-
-    if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
-    {
-	LONG lP1, lP2, lP3, lP4;
-
-	SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
-	SEGPTR Limit = pLPD->ThunkBufLimit;
-	int   nSize;
-
-	if (pLPD->fn[FUNC_ENUMDFONTS] == NULL)
-	{
-	    dprintf_win16drv(stddeb, "PRTDRV_EnumDFonts: Not supported by driver\n");
-	    return 0;
-	}
-
-	lP1 = (SEGPTR)lpDestDev;
-	
-	if (lpFaceName == NULL)
-	{
-	    lP2 = 0;
-	}
-	else
-	{
-	    lP2 = SegPtr;
-	    nSize = strlen(lpFaceName) + 1;
-	    AddData(&SegPtr, lpFaceName, nSize, Limit);	
-	}
-
-	lP3 = (LONG)lpCallbackFunc; 
-
-	lP4 = (LONG)lpClientData;
-        
-	wRet = CallTo16_word_llll(pLPD->fn[FUNC_ENUMDFONTS], 
-                                  lP1, lP2, lP3, lP4);
-    }
-    else 
-        printf("Failed to find device\n");
-    
-    dprintf_win16drv(stddeb, "PRTDRV_EnumDFonts: return %x\n", wRet);
-    return wRet;
-}
-
-/* 
- * RealizeObject (ordinal 10)
- */
-DWORD PRTDRV_RealizeObject(LPPDEVICE lpDestDev, WORD wStyle, 
-		    LPVOID lpInObj, LPVOID lpOutObj,
-                    LPTEXTXFORM16 lpTextXForm)
-{
-    WORD dwRet = 0;
-    LOADED_PRINTER_DRIVER *pLPD = NULL;
-    
-    dprintf_win16drv(stddeb, "PRTDRV_RealizeObject:\n");
-    
-    if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
-    {
-	LONG lP1, lP3, lP4, lP5;  
-	WORD wP2;
-	SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
-	SEGPTR Limit = pLPD->ThunkBufLimit;
-	int   nSize;
-
-	if (pLPD->fn[FUNC_REALIZEOBJECT] == NULL)
-	{
-	    dprintf_win16drv(stddeb, "PRTDRV_RealizeObject: Not supported by driver\n");
-	    return 0;
-	}
-
-	lP1 = lpDestDev;
-	wP2 = wStyle;
-	
-	lP3 = SegPtr;
-	switch (wStyle)
-	{
-        case 3: 
-            nSize = sizeof(LOGFONT16); 
-            break;
-        default:
-	    printf("PRTDRV_RealizeObject: Object type %d not supported\n", wStyle);
-            nSize = 0;
-            
-	}
-	AddData(&SegPtr, lpInObj, nSize, Limit);	
-	
-	lP4 = (LONG)lpOutObj;
-
-	if (lpTextXForm != NULL)
-	{
-	    lP5 = SegPtr;
-	    nSize = sizeof(TEXTXFORM16);
-	    AddData(&SegPtr, lpTextXForm, nSize, Limit);	
-	}
-	else
-	  lP5 = 0L;
-
-	dwRet = CallTo16_long_lwlll(pLPD->fn[FUNC_REALIZEOBJECT], 
-                                    lP1, wP2, lP3, lP4, lP5);
-
-    }
-    dprintf_win16drv(stddeb, "PRTDRV_RealizeObject: return %x\n", dwRet);
-    return dwRet;
-}
-
-
 BOOL32 WIN16DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device, LPCSTR output,
                           const DEVMODE16* initData )
 {
@@ -798,116 +393,6 @@
     return nRet;
 }
 
-DWORD PRTDRV_ExtTextOut(LPPDEVICE lpDestDev, WORD wDestXOrg, WORD wDestYOrg,
-                        RECT16 *lpClipRect, LPCSTR lpString, WORD wCount, 
-                        SEGPTR lpFontInfo, LPDRAWMODE lpDrawMode, 
-                        LPTEXTXFORM16 lpTextXForm, SHORT *lpCharWidths,
-                        RECT16 *     lpOpaqueRect, WORD wOptions)
-{
-    DWORD dwRet = 0;
-    LOADED_PRINTER_DRIVER *pLPD = NULL;
-    
-    dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut:\n");
-    
-    if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
-    {
-	LONG lP1, lP4, lP5, lP7, lP8, lP9, lP10, lP11;  
-	WORD wP2, wP3, wP6, wP12;
-        INT16 iP6;
-
-	SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
-	SEGPTR Limit = pLPD->ThunkBufLimit;
-	int   nSize;
-
-	if (pLPD->fn[FUNC_EXTTEXTOUT] == NULL)
-	{
-	    dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut: Not supported by driver\n");
-	    return 0;
-	}
-
-	lP1 = lpDestDev;
-	wP2 = wDestXOrg;
-	wP3 = wDestYOrg;
-	
-	if (lpClipRect != NULL)
-	{
-	    lP4 = SegPtr;
-	    nSize = sizeof(RECT16);
-            dprintf_win16drv(stddeb, "Adding lpClipRect\n");
-            
-	    AddData(&SegPtr, lpClipRect, nSize, Limit);	
-	}
-	else
-	  lP4 = 0L;
-
-	if (lpString != NULL)
-	{
-	    /* TTD WARNING THIS STRING ISNT NULL TERMINATED */
-	    lP5 = SegPtr;
-	    nSize = strlen(lpString);
-            nSize = abs(wCount);
-            dprintf_win16drv(stddeb, "Adding string size %d\n",nSize);
-            
-	    AddData(&SegPtr, lpString, nSize, Limit);	
-	}
-	else
-	  lP5 = 0L;
-	
-	iP6 = wCount;
-	
-	/* This should be realized by the driver, so in 16bit data area */
-	lP7 = lpFontInfo;
-	
-	if (lpDrawMode != NULL)
-	{
-	    lP8 = SegPtr;
-	    nSize = sizeof(DRAWMODE);
-            dprintf_win16drv(stddeb, "adding lpDrawMode\n");
-            
-	    AddData(&SegPtr, lpDrawMode, nSize, Limit);	
-	}
-	else
-	  lP8 = 0L;
-	
-	if (lpTextXForm != NULL)
-	{
-	    lP9 = SegPtr;
-	    nSize = sizeof(TEXTXFORM16);
-            dprintf_win16drv(stddeb, "Adding TextXForm\n");
-	    AddData(&SegPtr, lpTextXForm, nSize, Limit);	
-	}
-	else
-	  lP9 = 0L;
-	
-	if (lpCharWidths != NULL) 
-	  dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut: Char widths not supported\n");
-	lP10 = 0;
-	
-	if (lpOpaqueRect != NULL)
-	{
-	    lP11 = SegPtr;
-	    nSize = sizeof(RECT16);
-            dprintf_win16drv(stddeb, "Adding opaqueRect\n");
-	    AddData(&SegPtr, lpOpaqueRect, nSize, Limit);	
-	}
-	else
-	  lP11 = 0L;
-	
-	wP12 = wOptions;
-	dprintf_win16drv(stddeb, "Calling exttextout 0x%lx 0x%x 0x%x 0x%lx\n0x%lx 0x%x 0x%lx 0x%lx\n"
-               "0x%lx 0x%lx 0x%lx 0x%x\n",lP1, wP2, wP3, lP4, 
-					   lP5, iP6, lP7, lP8, lP9, lP10,
-					   lP11, wP12);
-	dwRet = CallTo16_long_lwwllwlllllw(pLPD->fn[FUNC_EXTTEXTOUT], 
-                                           lP1, wP2, wP3, lP4, 
-					   lP5, iP6, lP7, lP8, lP9, lP10,
-					   lP11, wP12);
-        if (lpDrawMode)
-            GetParamData(lP8, lpDrawMode, sizeof(DRAWMODE));
-    }
-    dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut: return %lx\n", dwRet);
-    return dwRet;
-}
 
 
 
diff --git a/graphics/win16drv/prtdrv.c b/graphics/win16drv/prtdrv.c
new file mode 100644
index 0000000..2864742
--- /dev/null
+++ b/graphics/win16drv/prtdrv.c
@@ -0,0 +1,603 @@
+/*
+ * Windows Device Context initialisation functions
+ *
+ * Copyright 1996 John Harvey
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include "windows.h"
+#include "win16drv.h"
+
+#include "callback.h"
+#include "stddebug.h"
+#include "debug.h"
+
+#define MAX_PRINTER_DRIVERS 	16
+static LOADED_PRINTER_DRIVER *gapLoadedPrinterDrivers[MAX_PRINTER_DRIVERS];
+
+
+static void GetPrinterDriverFunctions(HINSTANCE16 hInst, LOADED_PRINTER_DRIVER *pLPD)
+{
+#define LoadPrinterDrvFunc(A) pLPD->fn[FUNC_##A] = \
+      GetProcAddress16(hInst, MAKEINTRESOURCE(ORD_##A))
+
+      LoadPrinterDrvFunc(BITBLT);
+      LoadPrinterDrvFunc(COLORINFO);
+      LoadPrinterDrvFunc(CONTROL);
+      LoadPrinterDrvFunc(DISABLE);
+      LoadPrinterDrvFunc(ENABLE);
+      LoadPrinterDrvFunc(ENUMDFONTS);
+      LoadPrinterDrvFunc(ENUMOBJ);
+      LoadPrinterDrvFunc(OUTPUT);
+      LoadPrinterDrvFunc(PIXEL);
+      LoadPrinterDrvFunc(REALIZEOBJECT);
+      LoadPrinterDrvFunc(STRBLT);
+      LoadPrinterDrvFunc(SCANLR);
+      LoadPrinterDrvFunc(DEVICEMODE);
+      LoadPrinterDrvFunc(EXTTEXTOUT);
+      LoadPrinterDrvFunc(GETCHARWIDTH);
+      LoadPrinterDrvFunc(DEVICEBITMAP);
+      LoadPrinterDrvFunc(FASTBORDER);
+      LoadPrinterDrvFunc(SETATTRIBUTE);
+      LoadPrinterDrvFunc(STRETCHBLT);
+      LoadPrinterDrvFunc(STRETCHDIBITS);
+      LoadPrinterDrvFunc(SELECTBITMAP);
+      LoadPrinterDrvFunc(BITMAPBITS);
+      LoadPrinterDrvFunc(EXTDEVICEMODE);
+      LoadPrinterDrvFunc(DEVICECAPABILITIES);
+      LoadPrinterDrvFunc(ADVANCEDSETUPDIALOG);
+      LoadPrinterDrvFunc(DIALOGFN);
+      LoadPrinterDrvFunc(PSEUDOEDIT);
+      dprintf_win16drv (stddeb,"got func CONTROL 0x%p enable 0x%p enumDfonts 0x%p realizeobject 0x%p extextout 0x%p\n",
+              pLPD->fn[FUNC_CONTROL],
+              pLPD->fn[FUNC_ENABLE],
+              pLPD->fn[FUNC_ENUMDFONTS],
+              pLPD->fn[FUNC_REALIZEOBJECT],
+              pLPD->fn[FUNC_EXTTEXTOUT]);
+      
+
+}
+
+
+static LOADED_PRINTER_DRIVER *FindPrinterDriverFromName(const char *pszDriver)
+{
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+    int		nDriverSlot = 0;
+
+    /* Look to see if the printer driver is already loaded */
+    while (pLPD == NULL && nDriverSlot < MAX_PRINTER_DRIVERS)
+    {
+	LOADED_PRINTER_DRIVER *ptmpLPD;
+	ptmpLPD = gapLoadedPrinterDrivers[nDriverSlot++];
+	if (ptmpLPD != NULL)
+	{
+	    dprintf_win16drv(stddeb, "Comparing %s,%s\n",ptmpLPD->szDriver,pszDriver);
+	    /* Found driver store info, exit loop */
+	    if (lstrcmpi32A(ptmpLPD->szDriver, pszDriver) == 0)
+	      pLPD = ptmpLPD;
+	}
+    }
+    if (pLPD == NULL) printf("Couldn't find driver %s\n", pszDriver);
+    return pLPD;
+}
+
+static LOADED_PRINTER_DRIVER *FindPrinterDriverFromPDEVICE(SEGPTR segptrPDEVICE)
+{
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+
+    /* Find the printer driver associated with this PDEVICE */
+    /* Each of the PDEVICE structures has a PDEVICE_HEADER structure */
+    /* just before it */
+    if (segptrPDEVICE != (SEGPTR)NULL)
+    {
+	PDEVICE_HEADER *pPDH = (PDEVICE_HEADER *)
+	  (PTR_SEG_TO_LIN(segptrPDEVICE) - sizeof(PDEVICE_HEADER)); 
+        pLPD = pPDH->pLPD;
+    }
+    return pLPD;
+}
+
+/* 
+ * Load a printer driver, adding it self to the list of loaded drivers.
+ */
+
+LOADED_PRINTER_DRIVER *LoadPrinterDriver(const char *pszDriver)
+{                                        
+    HINSTANCE16	hInst;	
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+    int		nDriverSlot = 0;
+    BOOL32	bSlotFound = FALSE;
+
+    /* First look to see if driver is loaded */
+    pLPD = FindPrinterDriverFromName(pszDriver);
+    if (pLPD != NULL)
+    {
+	/* Already loaded so increase usage count */
+	pLPD->nUsageCount++;
+	return pLPD;
+    }
+
+    /* Not loaded so try and find an empty slot */
+    while (!bSlotFound && nDriverSlot < MAX_PRINTER_DRIVERS)
+    {
+	if (gapLoadedPrinterDrivers[nDriverSlot] == NULL)
+	  bSlotFound = TRUE;
+	else
+	  nDriverSlot++;
+    }
+    if (!bSlotFound)
+    {
+	printf("Too many printers drivers loaded\n");
+	return NULL;
+    }
+
+    {
+        char *drvName = malloc(strlen(pszDriver)+5);
+        strcpy(drvName, pszDriver);
+        strcat(drvName, ".DRV");
+        hInst = LoadLibrary16(drvName);
+    }
+    dprintf_win16drv(stddeb, "Loaded the library\n");
+
+    
+    if (hInst <= 32)
+    {
+	/* Failed to load driver */
+	fprintf(stderr, "Failed to load printer driver %s\n", pszDriver);
+    }
+    else
+    {
+	HANDLE16 hHandle;
+
+	/* Allocate some memory for printer driver info */
+	pLPD = malloc(sizeof(LOADED_PRINTER_DRIVER));
+	memset(pLPD, 0 , sizeof(LOADED_PRINTER_DRIVER));
+	
+	pLPD->hInst = hInst;
+	strcpy(pLPD->szDriver,pszDriver);
+
+	/* Get DS for the printer module */
+	pLPD->ds_reg = hInst;
+
+	dprintf_win16drv(stddeb, "DS for %s is %x\n", pszDriver, pLPD->ds_reg);
+
+	/* Get address of printer driver functions */
+	GetPrinterDriverFunctions(hInst, pLPD);
+
+	/* Set initial usage count */
+	pLPD->nUsageCount = 1;
+
+	/* Create a thunking buffer */
+	hHandle = GlobalAlloc16(GHND, (1024 * 8));
+	pLPD->hThunk = hHandle;
+	pLPD->ThunkBufSegPtr = WIN16_GlobalLock16(hHandle);
+	pLPD->ThunkBufLimit = pLPD->ThunkBufSegPtr + (1024*8);
+
+	/* Update table of loaded printer drivers */
+	pLPD->nIndex = nDriverSlot;
+	gapLoadedPrinterDrivers[nDriverSlot] = pLPD;
+    }
+
+    return pLPD;
+}
+
+/* 
+ * Thunking utility functions
+ */
+
+static BOOL32 AddData(SEGPTR *pSegPtr, const void *pData, int nSize, SEGPTR Limit)
+{
+    BOOL32 bRet = FALSE;
+    char *pBuffer = PTR_SEG_TO_LIN((*pSegPtr));
+    char *pLimit = PTR_SEG_TO_LIN(Limit);
+
+
+    if ((pBuffer + nSize) < pLimit)
+    {
+	DWORD *pdw = (DWORD *)pSegPtr;
+	SEGPTR SegPtrOld = *pSegPtr;
+	SEGPTR SegPtrNew;
+
+	dprintf_win16drv(stddeb, "AddData: Copying %d from %p to %p(0x%x)\n", nSize, pData, pBuffer, (UINT32)*pSegPtr);
+	memcpy(pBuffer, pData, nSize); 
+	SegPtrNew = (SegPtrOld + nSize + 1);
+	*pdw = (DWORD)SegPtrNew;
+    }
+    return bRet;
+}
+
+
+static BOOL32 GetParamData(SEGPTR SegPtrSrc,void *pDataDest, int nSize)
+{
+    char *pSrc =  PTR_SEG_TO_LIN(SegPtrSrc);
+    char *pDest = pDataDest;
+
+    dprintf_win16drv(stddeb, "GetParamData: Copying %d from %lx(%lx) to %lx\n", nSize, (DWORD)pSrc, (DWORD)SegPtrSrc, (DWORD)pDataDest);
+    memcpy(pDest, pSrc, nSize);
+    return TRUE;
+}
+
+/*
+ *  Control (ordinal 3)
+ */
+INT16 PRTDRV_Control(LPPDEVICE lpDestDev, WORD wfunction, SEGPTR lpInData, SEGPTR lpOutData)
+{
+    /* wfunction == Escape code */
+    /* lpInData, lpOutData depend on code */
+
+    WORD wRet = 0;
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+
+    dprintf_win16drv(stddeb, "PRTDRV_Control: %08x 0x%x %08lx %08lx\n", (unsigned int)lpDestDev, wfunction, lpInData, lpOutData);
+
+    if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
+    {
+	LONG lP1, lP3, lP4;
+	WORD wP2;
+
+	if (pLPD->fn[FUNC_CONTROL] == NULL)
+	{
+	    dprintf_win16drv(stddeb, "PRTDRV_Control: Not supported by driver\n");
+	    return 0;
+	}
+
+	lP1 = (SEGPTR)lpDestDev;
+	wP2 = wfunction;
+	lP3 = (SEGPTR)lpInData;
+	lP4 = (SEGPTR)lpOutData;
+
+	wRet = CallTo16_word_lwll(pLPD->fn[FUNC_CONTROL], 
+                                  lP1, wP2, lP3, lP4);
+    }
+    dprintf_win16drv(stddeb, "PRTDRV_Control: return %x\n", wRet);
+    return wRet;
+
+    return 0;
+}
+
+/*
+ *	Enable (ordinal 5)
+ */
+WORD PRTDRV_Enable(LPVOID lpDevInfo, WORD wStyle, LPCSTR  lpDestDevType, 
+                          LPCSTR lpDeviceName, LPCSTR lpOutputFile, LPVOID lpData)
+{
+    WORD wRet = 0;
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+
+    dprintf_win16drv(stddeb, "PRTDRV_Enable: %s %s\n",lpDestDevType, lpOutputFile);
+
+    /* Get the printer driver info */
+    if (wStyle == INITPDEVICE)
+    {
+	pLPD = FindPrinterDriverFromPDEVICE((SEGPTR)lpDevInfo);
+    }
+    else
+    {
+	pLPD = FindPrinterDriverFromName((char *)lpDeviceName);
+    }
+    if (pLPD != NULL)
+    {
+	LONG lP1, lP3, lP4, lP5;
+	WORD wP2;
+	SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
+	SEGPTR Limit = pLPD->ThunkBufLimit;
+	int   nSize;
+
+	if (pLPD->fn[FUNC_ENABLE] == NULL)
+	{
+	    dprintf_win16drv(stddeb, "PRTDRV_Enable: Not supported by driver\n");
+	    return 0;
+	}
+
+	if (wStyle == INITPDEVICE)
+	{
+	    /* All ready a 16 address */
+	    lP1 = (SEGPTR)lpDevInfo;
+	}
+	else
+	{
+	    /* 32 bit data */
+	    lP1 = SegPtr;
+	    nSize = sizeof(DeviceCaps);
+	    AddData(&SegPtr, lpDevInfo, nSize, Limit);	
+	}
+	
+	wP2 = wStyle;
+	
+	lP3 = SegPtr;
+	nSize = strlen(lpDestDevType) + 1;
+	AddData(&SegPtr, lpDestDevType, nSize, Limit);	
+
+	lP4 = SegPtr; 
+	nSize = strlen(lpOutputFile) + 1;
+	AddData(&SegPtr, lpOutputFile, nSize, Limit);	
+
+	lP5 = (LONG)lpData;
+        
+
+	wRet = CallTo16_word_lwlll(pLPD->fn[FUNC_ENABLE], 
+				   lP1, wP2, lP3, lP4, lP5);
+
+	/* Get the data back */
+	if (lP1 != 0 && wStyle != INITPDEVICE)
+	{
+	    nSize = sizeof(DeviceCaps);
+	    GetParamData(lP1, lpDevInfo, nSize);
+	}
+    }
+    dprintf_win16drv(stddeb, "PRTDRV_Enable: return %x\n", wRet);
+    return wRet;
+}
+
+
+/*
+ *	EnumDFonts (ordinal 6)
+ */
+WORD PRTDRV_EnumDFonts(LPPDEVICE lpDestDev, LPSTR lpFaceName,  
+		       FARPROC16 lpCallbackFunc, LPVOID lpClientData)
+{
+    WORD wRet = 0;
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+
+    dprintf_win16drv(stddeb, "PRTDRV_EnumDFonts:\n");
+
+    if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
+    {
+	LONG lP1, lP2, lP3, lP4;
+
+	SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
+	SEGPTR Limit = pLPD->ThunkBufLimit;
+	int   nSize;
+
+	if (pLPD->fn[FUNC_ENUMDFONTS] == NULL)
+	{
+	    dprintf_win16drv(stddeb, "PRTDRV_EnumDFonts: Not supported by driver\n");
+	    return 0;
+	}
+
+	lP1 = (SEGPTR)lpDestDev;
+	
+	if (lpFaceName == NULL)
+	{
+	    lP2 = 0;
+	}
+	else
+	{
+	    lP2 = SegPtr;
+	    nSize = strlen(lpFaceName) + 1;
+	    AddData(&SegPtr, lpFaceName, nSize, Limit);	
+	}
+
+	lP3 = (LONG)lpCallbackFunc; 
+
+	lP4 = (LONG)lpClientData;
+        
+	wRet = CallTo16_word_llll(pLPD->fn[FUNC_ENUMDFONTS], 
+                                  lP1, lP2, lP3, lP4);
+    }
+    else 
+        printf("Failed to find device\n");
+    
+    dprintf_win16drv(stddeb, "PRTDRV_EnumDFonts: return %x\n", wRet);
+    return wRet;
+}
+/*
+ *	EnumObj (ordinal 7)
+ */
+BOOL16 PRTDRV_EnumObj(LPPDEVICE lpDestDev, WORD iStyle, 
+		       FARPROC16 lpCallbackFunc, LPVOID lpClientData)
+{
+    WORD wRet = 0;
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+
+    dprintf_win16drv(stddeb, "PRTDRV_EnumDFonts:\n");
+
+    if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
+    {
+	LONG lP1, lP3, lP4;
+	WORD wP2;
+
+	if (pLPD->fn[FUNC_ENUMDFONTS] == NULL)
+	{
+	    dprintf_win16drv(stddeb, "PRTDRV_EnumDFonts: Not supported by driver\n");
+	    return 0;
+	}
+
+	lP1 = (SEGPTR)lpDestDev;
+	
+	wP2 = iStyle;
+
+	/* 
+	 * Need to pass addres of function conversion function that will switch back to 32 bit code if necessary
+	 */
+	lP3 = (LONG)lpCallbackFunc; 
+
+	lP4 = (LONG)lpClientData;
+        
+	wRet = CallTo16_word_lwll(pLPD->fn[FUNC_ENUMOBJ], 
+                                  lP1, wP2, lP3, lP4);
+    }
+    else 
+        printf("Failed to find device\n");
+    
+    dprintf_win16drv(stddeb, "PRTDRV_EnumDFonts: return %x\n", wRet);
+    return wRet;
+}
+
+/* 
+ * RealizeObject (ordinal 10)
+ */
+DWORD PRTDRV_RealizeObject(LPPDEVICE lpDestDev, WORD wStyle, 
+		    LPVOID lpInObj, LPVOID lpOutObj,
+                    LPTEXTXFORM16 lpTextXForm)
+{
+    WORD dwRet = 0;
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+    
+    dprintf_win16drv(stddeb, "PRTDRV_RealizeObject:\n");
+    
+    if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
+    {
+	LONG lP1, lP3, lP4, lP5;  
+	WORD wP2;
+	SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
+	SEGPTR Limit = pLPD->ThunkBufLimit;
+	int   nSize;
+
+	if (pLPD->fn[FUNC_REALIZEOBJECT] == NULL)
+	{
+	    dprintf_win16drv(stddeb, "PRTDRV_RealizeObject: Not supported by driver\n");
+	    return 0;
+	}
+
+	lP1 = lpDestDev;
+	wP2 = wStyle;
+	
+	lP3 = SegPtr;
+	switch (wStyle)
+	{
+        case 3: 
+            nSize = sizeof(LOGFONT16); 
+            break;
+        default:
+	    printf("PRTDRV_RealizeObject: Object type %d not supported\n", wStyle);
+            nSize = 0;
+            
+	}
+	AddData(&SegPtr, lpInObj, nSize, Limit);	
+	
+	lP4 = (LONG)lpOutObj;
+
+	if (lpTextXForm != NULL)
+	{
+	    lP5 = SegPtr;
+	    nSize = sizeof(TEXTXFORM16);
+	    AddData(&SegPtr, lpTextXForm, nSize, Limit);	
+	}
+	else
+	  lP5 = 0L;
+
+	dwRet = CallTo16_long_lwlll(pLPD->fn[FUNC_REALIZEOBJECT], 
+                                    lP1, wP2, lP3, lP4, lP5);
+
+    }
+    dprintf_win16drv(stddeb, "PRTDRV_RealizeObject: return %x\n", dwRet);
+    return dwRet;
+}
+
+
+DWORD PRTDRV_ExtTextOut(LPPDEVICE lpDestDev, WORD wDestXOrg, WORD wDestYOrg,
+                        RECT16 *lpClipRect, LPCSTR lpString, WORD wCount, 
+                        SEGPTR lpFontInfo, LPDRAWMODE lpDrawMode, 
+                        LPTEXTXFORM16 lpTextXForm, SHORT *lpCharWidths,
+                        RECT16 *     lpOpaqueRect, WORD wOptions)
+{
+    DWORD dwRet = 0;
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+    
+    dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut:\n");
+    
+    if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
+    {
+	LONG lP1, lP4, lP5, lP7, lP8, lP9, lP10, lP11;  
+	WORD wP2, wP3, wP12;
+        INT16 iP6;
+
+	SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
+	SEGPTR Limit = pLPD->ThunkBufLimit;
+	int   nSize;
+
+	if (pLPD->fn[FUNC_EXTTEXTOUT] == NULL)
+	{
+	    dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut: Not supported by driver\n");
+	    return 0;
+	}
+
+	lP1 = lpDestDev;
+	wP2 = wDestXOrg;
+	wP3 = wDestYOrg;
+	
+	if (lpClipRect != NULL)
+	{
+	    lP4 = SegPtr;
+	    nSize = sizeof(RECT16);
+            dprintf_win16drv(stddeb, "Adding lpClipRect\n");
+            
+	    AddData(&SegPtr, lpClipRect, nSize, Limit);	
+	}
+	else
+	  lP4 = 0L;
+
+	if (lpString != NULL)
+	{
+	    /* TTD WARNING THIS STRING ISNT NULL TERMINATED */
+	    lP5 = SegPtr;
+	    nSize = strlen(lpString);
+            nSize = abs(wCount);
+            dprintf_win16drv(stddeb, "Adding string size %d\n",nSize);
+            
+	    AddData(&SegPtr, lpString, nSize, Limit);	
+	}
+	else
+	  lP5 = 0L;
+	
+	iP6 = wCount;
+	
+	/* This should be realized by the driver, so in 16bit data area */
+	lP7 = lpFontInfo;
+	
+	if (lpDrawMode != NULL)
+	{
+	    lP8 = SegPtr;
+	    nSize = sizeof(DRAWMODE);
+            dprintf_win16drv(stddeb, "adding lpDrawMode\n");
+            
+	    AddData(&SegPtr, lpDrawMode, nSize, Limit);	
+	}
+	else
+	  lP8 = 0L;
+	
+	if (lpTextXForm != NULL)
+	{
+	    lP9 = SegPtr;
+	    nSize = sizeof(TEXTXFORM16);
+            dprintf_win16drv(stddeb, "Adding TextXForm\n");
+	    AddData(&SegPtr, lpTextXForm, nSize, Limit);	
+	}
+	else
+	  lP9 = 0L;
+	
+	if (lpCharWidths != NULL) 
+	  dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut: Char widths not supported\n");
+	lP10 = 0;
+	
+	if (lpOpaqueRect != NULL)
+	{
+	    lP11 = SegPtr;
+	    nSize = sizeof(RECT16);
+            dprintf_win16drv(stddeb, "Adding opaqueRect\n");
+	    AddData(&SegPtr, lpOpaqueRect, nSize, Limit);	
+	}
+	else
+	  lP11 = 0L;
+	
+	wP12 = wOptions;
+	dprintf_win16drv(stddeb, "Calling exttextout 0x%lx 0x%x 0x%x 0x%lx\n0x%lx 0x%x 0x%lx 0x%lx\n"
+               "0x%lx 0x%lx 0x%lx 0x%x\n",lP1, wP2, wP3, lP4, 
+					   lP5, iP6, lP7, lP8, lP9, lP10,
+					   lP11, wP12);
+	dwRet = CallTo16_long_lwwllwlllllw(pLPD->fn[FUNC_EXTTEXTOUT], 
+                                           lP1, wP2, wP3, lP4, 
+					   lP5, iP6, lP7, lP8, lP9, lP10,
+					   lP11, wP12);
+        if (lpDrawMode)
+            GetParamData(lP8, lpDrawMode, sizeof(DRAWMODE));
+    }
+    dprintf_win16drv(stddeb, "PRTDRV_ExtTextOut: return %lx\n", dwRet);
+    return dwRet;
+}
diff --git a/graphics/win16drv/text.c b/graphics/win16drv/text.c
index fe07463..903d6c8 100644
--- a/graphics/win16drv/text.c
+++ b/graphics/win16drv/text.c
@@ -70,13 +70,14 @@
 				  physDev->segptrFontInfo, lpDrawMode, 
 				  lpTextXForm, NULL, NULL, 0);
 */
+#ifdef NOTDEF
 	lpClipRect->left = lprect->left ;
 	lpClipRect->top = lprect->top;
 	lpClipRect->right = lprect->right;
 	lpClipRect->bottom = lprect->bottom;
         dprintf_win16drv(stddeb, "WIN16DRV_ExtTextOut Clip rect left %d top %d rigt %d bottom %d\n",
                          lpClipRect->left,lpClipRect->top,lpClipRect->right,lpClipRect->bottom);
-        
+#endif
 	lpClipRect->left = 0;
 	lpClipRect->top = 0;
 	lpClipRect->right = 0x3fc;
diff --git a/graphics/x11drv/bitblt.c b/graphics/x11drv/bitblt.c
index c4b4f8c..1fbd3c5 100644
--- a/graphics/x11drv/bitblt.c
+++ b/graphics/x11drv/bitblt.c
@@ -1207,12 +1207,24 @@
 
     case PATINVERT:  /* 0x5a */
 	if (Options.perfectGraphics) break;
-        if (!DC_SetupGCForBrush( dcDst )) return TRUE;
-        XSetFunction( display, dcDst->u.x.gc, GXxor );
-        XFillRectangle( display, dcDst->u.x.drawable, dcDst->u.x.gc,
-                        visRectDst.left, visRectDst.top, width, height );
+        if (DC_SetupGCForBrush( dcDst ))
+        {
+            XSetFunction( display, dcDst->u.x.gc, GXxor );
+            XFillRectangle( display, dcDst->u.x.drawable, dcDst->u.x.gc,
+			    visRectDst.left, visRectDst.top, width, height );
+        }
         return TRUE;
 
+    case 0xa50065:
+	if (Options.perfectGraphics) break;
+	if (DC_SetupGCForBrush( dcDst ))
+	{
+	    XSetFunction( display, dcDst->u.x.gc, GXequiv );
+	    XFillRectangle( display, dcDst->u.x.drawable, dcDst->u.x.gc,
+			    visRectDst.left, visRectDst.top, width, height );
+	}
+	return TRUE;
+
     case SRCCOPY:  /* 0xcc */
         if (dcSrc->w.bitsPerPixel == dcDst->w.bitsPerPixel)
         {
diff --git a/graphics/x11drv/font.c b/graphics/x11drv/font.c
index a2f5151..0d4e2c6 100644
--- a/graphics/x11drv/font.c
+++ b/graphics/x11drv/font.c
@@ -23,6 +23,33 @@
 } FontNames[32];
 int FontSize;
 
+#define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
+			     (((cs)->rbearing|(cs)->lbearing| \
+			       (cs)->ascent|(cs)->descent) == 0))
+
+/* 
+ * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
+ * character.  If the character is in the column and exists, then return the
+ * appropriate metrics (note that fonts with common per-character metrics will
+ * return min_bounds).  If none of these hold true, try again with the default
+ * char.
+ */
+#define CI_GET_CHAR_INFO(fs,col,def,cs) \
+{ \
+    cs = def; \
+    if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
+	if (fs->per_char == NULL) { \
+	    cs = &fs->min_bounds; \
+	} else { \
+	    cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
+	    if (CI_NONEXISTCHAR(cs)) cs = def; \
+	} \
+    } \
+}
+
+#define CI_GET_DEFAULT_INFO(fs,cs) \
+  CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
+
 
 /***********************************************************************
  *           X11DRV_FONT_Init
@@ -456,3 +483,37 @@
     }
     return prevHandle;
 }
+
+/***********************************************************************
+ *           GetCharWidth32A    (GDI32.155)
+ */
+BOOL32 X11DRV_GetCharWidth( DC *dc, UINT32 firstChar, UINT32 lastChar,
+			    LPINT32 buffer )
+{
+    int i, width;
+    XFontStruct *xfont;
+    XCharStruct *cs, *def;
+
+    xfont = dc->u.x.font.fstruct;
+    
+    /* fixed font? */
+    if (xfont->per_char == NULL)
+    {
+	for (i = firstChar; i <= lastChar; i++)
+	    *buffer++ = xfont->max_bounds.width;
+	return TRUE;
+    }
+
+    CI_GET_DEFAULT_INFO(xfont, def);
+	
+    for (i = firstChar; i <= lastChar; i++)
+    {
+	CI_GET_CHAR_INFO( xfont, i, def, cs );
+        width = cs ? cs->width : xfont->max_bounds.width;
+        *buffer++ = MAX( width, 0 );
+    }
+    return TRUE;
+}
+
+
+
diff --git a/graphics/x11drv/init.c b/graphics/x11drv/init.c
index 6f34f63..17374ea 100644
--- a/graphics/x11drv/init.c
+++ b/graphics/x11drv/init.c
@@ -28,6 +28,7 @@
     NULL,                            /* pExcludeVisRect */
     X11DRV_ExtFloodFill,             /* pExtFloodFill */
     X11DRV_ExtTextOut,               /* pExtTextOut */
+    NULL,                            /* pGetCharWidth */
     X11DRV_GetPixel,                 /* pGetPixel */
     X11DRV_GetTextExtentPoint,       /* pGetTextExtentPoint */
     X11DRV_GetTextMetrics,           /* pGetTextMetrics */
diff --git a/if1632/crtdll.spec b/if1632/crtdll.spec
index be34155..7e43ce9 100644
--- a/if1632/crtdll.spec
+++ b/if1632/crtdll.spec
@@ -53,7 +53,7 @@
 048 stub _cabs
 049 stub _cexit
 050 stub _cgets
-051 stub _chdir
+051 cdecl _chdir(ptr) CRTDLL__chdir
 052 cdecl _chdrive(long) CRTDLL__chdrive
 053 stub _chgsign
 054 stub _chmod
@@ -236,7 +236,7 @@
 231 stub _mbsupr
 232 stub _memccpy
 233 stub _memicmp
-234 stub _mkdir
+234 cdecl _mkdir(ptr) CRTDLL__mkdir
 235 stub _mktemp
 236 stub _msize
 237 stub _nextafter
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index 71da3bc..8600b43 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -162,7 +162,7 @@
 193 stub SetBoundsRect
 194 stub GetBoundsRect
 195 stub SelectBitmap
-196 stub SetMetaFileBitsBetter
+196 pascal16 SetMetaFileBitsBetter(word) SetMetaFileBitsBetter
 201 stub DMBITBLT
 202 stub DMCOLORINFO
 206 stub DMENUMDFONTS
diff --git a/if1632/kernel32.spec b/if1632/kernel32.spec
index f8281ee..56ad2b0 100644
--- a/if1632/kernel32.spec
+++ b/if1632/kernel32.spec
@@ -45,8 +45,8 @@
 0040 stdcall CreateDirectoryExA(ptr ptr ptr) CreateDirectoryEx32A
 0041 stdcall CreateDirectoryExW(ptr ptr ptr) CreateDirectoryEx32W
 0042 stdcall CreateDirectoryW(ptr ptr) CreateDirectory32W
-0043 	stdcall CreateEventA(ptr long long ptr) CreateEventA
-0044 stub CreateEventW
+0043 stdcall CreateEventA(ptr long long ptr) CreateEvent32A
+0044 stdcall CreateEventW(ptr long long ptr) CreateEvent32W
 0045 stdcall CreateFileA(ptr long long ptr long long long) CreateFile32A
 0046 stdcall CreateFileMappingA(long ptr long long long ptr) CreateFileMapping32A
 0047 stdcall CreateFileMappingW(long ptr long long long ptr) CreateFileMapping32W
@@ -54,16 +54,16 @@
 0049 stub CreateIoCompletionPort
 0050 stub CreateMailslotA
 0051 stub CreateMailslotW
-0052 	stdcall CreateMutexA(ptr long ptr) CreateMutexA
-0053 stub CreateMutexW
+0052 stdcall CreateMutexA(ptr long ptr) CreateMutex32A
+0053 stdcall CreateMutexW(ptr long ptr) CreateMutex32W
 0054 stub CreateNamedPipeA
 0055 stub CreateNamedPipeW
 0056 stub CreatePipe
-0057 stub CreateProcessA
+0057 stdcall CreateProcessA(ptr ptr ptr ptr long long ptr ptr ptr ptr) CreateProcess32A
 0058 stub CreateProcessW
 0059 stub CreateRemoteThread
-0060 stub CreateSemaphoreA
-0061 stub CreateSemaphoreW
+0060 stdcall CreateSemaphoreA(ptr long long ptr) CreateSemaphore32A
+0061 stdcall CreateSemaphoreW(ptr long long ptr) CreateSemaphore32W
 0062 stub CreateTapePartition
 0063 stdcall CreateThread(ptr long ptr long long ptr) CreateThread
 0064 stub CreateVirtualBuffer
@@ -134,7 +134,7 @@
 0129 stdcall FindResourceExA(long ptr ptr long) FindResourceEx32A
 0130 stdcall FindResourceExW(long ptr ptr long) FindResourceEx32W
 0131 stdcall FindResourceW(long ptr ptr) FindResource32W
-0132 stub FlushConsoleInputBuffer
+0132 stdcall FlushConsoleInputBuffer(long) FlushConsoleInputBuffer
 0133 stdcall FlushFileBuffers(long) FlushFileBuffers
 0134 stub FlushInstructionCache
 0135 stub FlushViewOfFile
@@ -362,7 +362,7 @@
 0357 stdcall IsBadWritePtr(ptr long) IsBadWritePtr32
 0358 stdcall IsDBCSLeadByte(long) IsDBCSLeadByte32
 0359 stdcall IsDBCSLeadByteEx(long long) IsDBCSLeadByteEx
-0360 stub IsValidCodePage
+0360 stdcall IsValidCodePage(long) IsValidCodePage
 0361 stdcall IsValidLocale(long long) IsValidLocale
 0362 stub LCMapStringA
 0363 stub LCMapStringW
@@ -396,17 +396,17 @@
 0391 stdcall MulDiv(long long long) MulDiv32
 0392 stdcall MultiByteToWideChar(long long ptr long ptr long) MultiByteToWideChar
 0393 stub OpenConsoleW
-0394 stub OpenEventA
-0395 stub OpenEventW
+0394 stdcall OpenEventA(long long ptr) OpenEvent32A
+0395 stdcall OpenEventW(long long ptr) OpenEvent32W
 0396 stdcall OpenFile(ptr ptr long) OpenFile32
 0397 stdcall OpenFileMappingA(long long ptr) OpenFileMapping32A
 0398 stdcall OpenFileMappingW(long long ptr) OpenFileMapping32W
-0399 stub OpenMutexA
-0400 stub OpenMutexW
+0399 stdcall OpenMutexA(long long ptr) OpenMutex32A
+0400 stdcall OpenMutexW(long long ptr) OpenMutex32W
 0401 stub OpenProcess
 0402 stub OpenProfileUserMapping
-0403 stub OpenSemaphoreA
-0404 stub OpenSemaphoreW
+0403 stdcall OpenSemaphoreA(long long ptr) OpenSemaphore32A
+0404 stdcall OpenSemaphoreW(long long ptr) OpenSemaphore32W
 0405 stdcall OutputDebugStringA(ptr) OutputDebugString32A
 0406 stub OutputDebugStringW
 0407 stub PeekConsoleInputA
@@ -438,7 +438,7 @@
 0433 stub RegisterWowBaseHandlers
 0434 stub RegisterWowExec
 0435 	stdcall ReleaseMutex(long) ReleaseMutex
-0436 stub ReleaseSemaphore
+0436 stdcall ReleaseSemaphore(long long ptr) ReleaseSemaphore
 0437 stdcall RemoveDirectoryA(ptr) RemoveDirectory32A
 0438 stdcall RemoveDirectoryW(ptr) RemoveDirectory32W
 0439 	stdcall ResetEvent(long) ResetEvent
@@ -665,7 +665,7 @@
 0659 stub SUnMapLS_IP_EBP_8
 0660 stub SUnMapLS_IP_EBP_16
 0661 stub SUnMapLS_IP_EBP_20
-0662 stub MapSL
+0662 stdcall MapSL(long) MapSL
 0663 stub K32Thk1632Epilog
 0664 stub K32Thk1632Prolog
 0665 stub GetProcessFlags
@@ -680,3 +680,8 @@
 0674 stub FreeSLCallback
 0675 stub AllocSLCallback
 0676 stub Callback28
+0677 stub UninitializeCriticalSection
+0678 stub FT_Exit4
+0679 stdcall MapLS(ptr) MapLS
+0680 stdcall UnMapLS(long) UnMapLS
+0681 stub OpenVxDHandle
diff --git a/if1632/ntdll.spec b/if1632/ntdll.spec
index 7ac608f..0ccee24 100644
--- a/if1632/ntdll.spec
+++ b/if1632/ntdll.spec
@@ -378,7 +378,7 @@
 374 stdcall RtlFreeHeap(long long long) HeapFree
 375 stub RtlFreeOemString
 376 stub RtlFreeSid
-377 stub RtlFreeUnicodeString
+377 stdcall RtlFreeUnicodeString(ptr) RtlFreeUnicodeString
 378 stub RtlGenerate8dot3Name
 379 stub RtlGetAce
 380 stub RtlGetCallersAddress
@@ -508,7 +508,7 @@
 504 stub RtlTimeToSecondsSince1980
 505 stub RtlTimeToTimeFields
 506 stub RtlUnicodeStringToAnsiSize
-507 stub RtlUnicodeStringToAnsiString
+507 stdcall RtlUnicodeStringToAnsiString(ptr ptr long) RtlUnicodeStringToAnsiString
 508 stub RtlUnicodeStringToCountedOemString
 509 stub RtlUnicodeStringToInteger
 510 stub RtlUnicodeStringToOemSize
diff --git a/if1632/shell.spec b/if1632/shell.spec
index eaf6ec9..6fc4f64 100644
--- a/if1632/shell.spec
+++ b/if1632/shell.spec
@@ -41,7 +41,7 @@
 #  264 SH16TO32INT2526
 #  300 SHGETFILEINFO
 #  400 SHFORMATDRIVE
-#  401 SHCHECKDRIVE
+401 stub SHCHECKDRIVE
 #  402 _RUNDLLCHECKDRIVE
 
 # 8 WEP 
diff --git a/if1632/user.spec b/if1632/user.spec
index 564e790..fe0c4f7 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -171,7 +171,7 @@
 169 pascal16 GetCaretBlinkTime() GetCaretBlinkTime16
 170 pascal16 ArrangeIconicWindows(word) ArrangeIconicWindows16
 171 pascal16 WinHelp(word ptr word long) WinHelp16
-172 stub SwitchToThisWindow
+172 pascal16 SwitchToThisWindow(word word) SwitchToThisWindow16
 173 pascal16 LoadCursor(word segptr) LoadCursor16
 174 pascal16 LoadIcon(word segptr) LoadIcon16
 175 pascal16 LoadBitmap(word segptr) LoadBitmap16
@@ -297,7 +297,7 @@
 291 pascal   SetWindowsHookEx(s_word segptr word word) THUNK_SetWindowsHookEx16
 292 pascal16 UnhookWindowsHookEx(segptr) THUNK_UnhookWindowsHookEx16
 293 pascal   CallNextHookEx(segptr s_word word long) CallNextHookEx16
-294 stub LockWindowUpdate
+294 pascal16 LockWindowUpdate(word) LockWindowUpdate16
 299 register Mouse_Event() Mouse_Event
 300 stub UnloadInstalledDrivers
 #301 BOZOSLIVEHERE :-))	<- this is actually EditWndProc
diff --git a/if1632/user32.spec b/if1632/user32.spec
index 71f7f0b..f6c3ea4 100644
--- a/if1632/user32.spec
+++ b/if1632/user32.spec
@@ -381,7 +381,7 @@
 0374 stdcall LoadStringA(long long ptr long) LoadString32A
 0375 stdcall LoadStringW(long long ptr long) LoadString32W
 0376 stub LockWindowStation
-0377 stub LockWindowUpdate
+0377 stdcall LockWindowUpdate(long) LockWindowUpdate32
 0378 stub LookupIconIdFromDirectory
 0379 stub LookupIconIdFromDirectoryEx
 0380 stub MBToWCSEx
@@ -542,7 +542,7 @@
 0535 stdcall SubtractRect(ptr ptr ptr) SubtractRect32
 0536 stdcall SwapMouseButton(long) SwapMouseButton32
 0537 stub SwitchDesktop
-0538 stub SwitchToThisWindow
+0538 stdcall SwitchToThisWindow(long long) SwitchToThisWindow32
 0539 stdcall SystemParametersInfoA(long long ptr long) SystemParametersInfo32A
 0540 stdcall SystemParametersInfoW(long long ptr long) SystemParametersInfo32W
 0541 stdcall TabbedTextOutA(long long long ptr long long ptr long) TabbedTextOut32A
@@ -605,3 +605,4 @@
 0597 stub ToUnicodeEx
 0598 stub DrawCaptionTempA
 0599 stub RegisterNetworkCapabilities
+0600 stub WNDPROC_CALLBACK
diff --git a/if1632/wprocs.spec b/if1632/wprocs.spec
index 0dee94c..bc676ac 100644
--- a/if1632/wprocs.spec
+++ b/if1632/wprocs.spec
@@ -4,7 +4,6 @@
 1  pascal WINPROC_CallProc16To32A(word word word long long) WINPROC_CallProc16To32A
 2  pascal StaticWndProc(word word word long) StaticWndProc
 3  pascal ScrollBarWndProc(word word word long) ScrollBarWndProc
-5  pascal ComboBoxWndProc(word word word long) ComboBoxWndProc
 10 pascal MDIClientWndProc(word word word long) MDIClientWndProc
 14 pascal FileOpenDlgProc(word word word long) FileOpenDlgProc
 15 pascal FileSaveDlgProc(word word word long) FileSaveDlgProc
@@ -13,7 +12,6 @@
 18 pascal ReplaceTextDlgProc(word word word long) ReplaceTextDlgProc
 19 pascal PrintSetupDlgProc(word word word long) PrintSetupDlgProc
 20 pascal PrintDlgProc(word word word long) PrintDlgProc
-22 pascal ComboLBoxWndProc(word word word long) ComboLBoxWndProc
 24 pascal16 TASK_Reschedule() TASK_Reschedule
 27 pascal EntryAddrProc(word word) MODULE_GetEntryPoint
 28 pascal MyAlloc(word word word) MODULE_AllocateSegment
diff --git a/include/combo.h b/include/combo.h
index 82fe86c..7060bdb 100644
--- a/include/combo.h
+++ b/include/combo.h
@@ -2,20 +2,55 @@
  * Combo box definitions
  */
 
+#ifndef __WINE_COMBO_H
+#define __WINE_COMBO_H
 
-typedef struct {
-  WND*	  wndSelf;
-  DWORD   dwStyle;
-  DWORD   dwState;
-  HWND16  hWndEdit;
-  HWND16  hWndLBox;
-  WORD    LBoxTop;
-  BOOL16  DropDownVisible;
-  short   LastSel;
-  RECT16  RectEdit;
-  RECT16  RectButton;
-  BOOL16  bRedrawFlag;
+#define ID_CB_LISTBOX           1000
+#define ID_CB_EDIT              1001
+
+/* Internal flags */
+
+#define CBF_DROPPED             0x0001
+#define CBF_BUTTONDOWN          0x0002
+#define CBF_NOROLLUP            0x0004
+#define CBF_MEASUREITEM		0x0008
+#define CBF_FOCUSED             0x0010
+#define CBF_CAPTURE             0x0020
+#define CBF_EDIT                0x0040
+#define CBF_NORESIZE		0x0080
+#define CBF_EUI                 0x8000
+
+/* Combo state struct */
+
+typedef struct
+{
+   WND*    	self;
+   HWND32  	owner;
+   UINT32  	dwStyle;
+   HWND32  	hWndEdit;
+   HWND32  	hWndLBox;
+   UINT16  	wState;
+   HFONT16 	hFont;
+   RECT16  	RectCombo;
+   RECT16  	RectEdit;
+   RECT16  	RectButton;
+   INT32   	droppedWidth;		/* last two are not used unless set */
+   INT32   	editHeight;		/* explicitly */
 } HEADCOMBO,*LPHEADCOMBO;
 
-LRESULT ComboBoxWndProc(HWND16 hwnd, UINT16 message, WPARAM16 wParam, LPARAM lParam);
-LRESULT ComboLBoxWndProc(HWND16 hwnd, UINT16 message, WPARAM16 wParam, LPARAM lParam);
+/*
+ * Note, that CBS_DROPDOWNLIST style is actually (CBS_SIMPLE | CBS_DROPDOWN)!
+ */
+
+#define CB_GETTYPE( lphc )    ((lphc)->dwStyle & (CBS_DROPDOWNLIST))
+#define CB_DISABLED( lphc )   ((lphc)->self->dwStyle & WS_DISABLED)
+#define CB_OWNERDRAWN( lphc ) ((lphc)->dwStyle & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE))
+#define CB_HASSTRINGS( lphc ) ((lphc)->dwStyle & CBS_HASSTRINGS)
+#define CB_HWND( lphc )       ((lphc)->self->hwndSelf)
+
+BOOL32 	COMBO_FlipListbox( LPHEADCOMBO, BOOL32 );
+HWND32 	COMBO_GetLBWindow( WND* );
+LRESULT COMBO_Directory( LPHEADCOMBO, UINT32, LPSTR, BOOL32 );
+
+#endif /* __WINE_COMBO_H */
+
diff --git a/include/dialog.h b/include/dialog.h
index a9db72e..ac3a14d 100644
--- a/include/dialog.h
+++ b/include/dialog.h
@@ -28,15 +28,17 @@
     HWND16      hwndFocus;   /* Current control with focus */
     HFONT16     hUserFont;   /* Dialog font */
     HMENU16     hMenu;       /* Dialog menu */
-    WORD        xBaseUnit;   /* Dialog units (depends on the font) */
-    WORD        yBaseUnit;
+    UINT16      xBaseUnit;   /* Dialog units (depends on the font) */
+    UINT16      yBaseUnit;
     INT32	idResult;    /* EndDialog() result / default pushbutton ID */
-    WORD        fEnd;        /* EndDialog() called for this dialog */
+    UINT16      flags;       /* EndDialog() called for this dialog */
     HGLOBAL16   hDialogHeap;
 } DIALOGINFO;
 
 #pragma pack(4)
 
+#define DF_END  0x0001
+
 extern BOOL32 DIALOG_Init(void);
 extern HWND32 DIALOG_CreateIndirect( HINSTANCE32 hInst, LPCSTR dlgTemplate,
                                      BOOL32 win32Template, HWND32 owner,
diff --git a/include/gdi.h b/include/gdi.h
index ad48849..8403005 100644
--- a/include/gdi.h
+++ b/include/gdi.h
@@ -158,6 +158,7 @@
     INT32      (*pExcludeVisRect)(DC*,INT32,INT32,INT32,INT32);
     BOOL32     (*pExtFloodFill)(DC*,INT32,INT32,COLORREF,UINT32);
     BOOL32     (*pExtTextOut)(DC*,INT32,INT32,UINT32,const RECT32*,LPCSTR,UINT32,const INT32*);
+    BOOL32     (*pGetCharWidth)(DC*,UINT32,UINT32,LPINT32);
     COLORREF   (*pGetPixel)(DC*,INT32,INT32);
     BOOL32     (*pGetTextExtentPoint)(DC*,LPCSTR,INT32,LPSIZE32);
     BOOL32     (*pGetTextMetrics)(DC*,TEXTMETRIC32A*);
diff --git a/include/graphics.h b/include/graphics.h
index 9ffdbb3..6d933fd 100644
--- a/include/graphics.h
+++ b/include/graphics.h
@@ -13,8 +13,13 @@
 extern void GRAPH_DrawReliefRect( HDC32 hdc, const RECT32 *rect,
                                   INT32 highlight_size, INT32 shadow_size,
                                   BOOL32 pressed );
+extern BOOL32 GRAPH_DrawLines( HDC32 hdc, LPPOINT32 pXY, INT32 N, HPEN32 hPen);
+extern void GRAPH_DrawRectangle( HDC32 hdc, INT32 x, INT32 y, 
+				 INT32 width, INT32 height, HPEN32 hPen);
 extern BOOL32 GRAPH_DrawBitmap( HDC32 hdc, HBITMAP32 hbitmap,
-                                int xdest, int ydest, int xsrc, int ysrc,
-                                int width, int height );
+                                INT32 xdest, INT32 ydest, INT32 xsrc,
+                                INT32 ysrc, INT32 width, INT32 height );
+extern BOOL32 GRAPH_SelectClipMask( HDC32 hdc, HBITMAP32 hMono,
+                                    INT32 x, INT32 y );
 
 #endif /* __WINE_GRAPHICS_H */
diff --git a/include/options.h b/include/options.h
index 3f051d6..36bfb5c 100644
--- a/include/options.h
+++ b/include/options.h
@@ -24,7 +24,8 @@
     LANG_It,  /* Italian */
     LANG_Ko,  /* Korean */
     LANG_Hu,  /* Hungarian */
-    LANG_Pl   /* Polish */
+    LANG_Pl,  /* Polish */
+    LANG_Po   /* Portuguese */
 } WINE_LANGUAGE;
 
 typedef struct
diff --git a/include/pe_image.h b/include/pe_image.h
index 12f6895..433bcdc 100644
--- a/include/pe_image.h
+++ b/include/pe_image.h
@@ -23,15 +23,15 @@
 extern int PE_unloadImage(HMODULE32 hModule);
 extern FARPROC32 PE_FindExportedFunction(struct pe_data *pe, LPCSTR funcName);
 extern void my_wcstombs(char * result, u_short * source, int len);
-extern PE_EnumResourceTypes32A(HMODULE32,ENUMRESTYPEPROC32A,LONG);
-extern PE_EnumResourceTypes32W(HMODULE32,ENUMRESTYPEPROC32W,LONG);
-extern PE_EnumResourceNames32A(HMODULE32,LPCSTR,ENUMRESNAMEPROC32A,LONG);
-extern PE_EnumResourceNames32W(HMODULE32,LPCWSTR,ENUMRESNAMEPROC32W,LONG);
-extern PE_EnumResourceLanguages32A(HMODULE32,LPCSTR,LPCSTR,ENUMRESLANGPROC32A,LONG);
-extern PE_EnumResourceLanguages32W(HMODULE32,LPCWSTR,LPCWSTR,ENUMRESLANGPROC32W,LONG);
+extern BOOL32 PE_EnumResourceTypes32A(HMODULE32,ENUMRESTYPEPROC32A,LONG);
+extern BOOL32 PE_EnumResourceTypes32W(HMODULE32,ENUMRESTYPEPROC32W,LONG);
+extern BOOL32 PE_EnumResourceNames32A(HMODULE32,LPCSTR,ENUMRESNAMEPROC32A,LONG);
+extern BOOL32 PE_EnumResourceNames32W(HMODULE32,LPCWSTR,ENUMRESNAMEPROC32W,LONG);
+extern BOOL32 PE_EnumResourceLanguages32A(HMODULE32,LPCSTR,LPCSTR,ENUMRESLANGPROC32A,LONG);
+extern BOOL32 PE_EnumResourceLanguages32W(HMODULE32,LPCWSTR,LPCWSTR,ENUMRESLANGPROC32W,LONG);
 extern HRSRC32 PE_FindResourceEx32W(HINSTANCE32,LPCWSTR,LPCWSTR,WORD);
 extern DWORD PE_SizeofResource32(HINSTANCE32,HRSRC32);
 extern HGLOBAL32 PE_LoadResource32(HINSTANCE32,HRSRC32);
-extern void PE_InitializeDLLs(HMODULE16);
+extern void PE_InitializeDLLs(HMODULE16,DWORD,LPVOID);
 
 #endif /* __WINE_PE_IMAGE_H */
diff --git a/include/win.h b/include/win.h
index 0179249..aabfe63 100644
--- a/include/win.h
+++ b/include/win.h
@@ -28,6 +28,21 @@
 #define WINSWITCH_CLASS_ATOM MAKEINTATOM(32771)  /* WinSwitch */
 #define ICONTITLE_CLASS_ATOM MAKEINTATOM(32772)  /* IconTitle */
 
+/* Built-in 32-bit classes */
+typedef enum
+{
+    BIC32_BUTTON,
+    BIC32_EDIT,
+    BIC32_LISTBOX,
+    BIC32_COMBO,
+    BIC32_COMBOLB,
+    BIC32_POPUPMENU,
+    BIC32_SCROLL,
+    BIC32_DESKTOP,
+    BIC32_DIALOG,
+    BIC32_NB_CLASSES
+} BUILTIN_CLASS32;
+
   /* PAINT_RedrawWindow() control flags */
 #define RDW_C_USEHRGN		0x0001
 #define RDW_C_DELETEHRGN	0x0002
@@ -108,6 +123,8 @@
                                   HRGN32 hrgnUpdate, UINT32 flags,
                                   UINT32 control );    /* windows/painting.c */
 
+extern BOOL32 WIDGETS_IsControl32( WND* pWnd, BUILTIN_CLASS32 cls );  /* controls/widgets.c */
+
 extern Display * display;
 extern Screen * screen;
 extern Window rootWindow;
diff --git a/include/win16drv.h b/include/win16drv.h
index 6b2c8a8..04df416 100644
--- a/include/win16drv.h
+++ b/include/win16drv.h
@@ -152,8 +152,34 @@
     SEGPTR	segptrFontInfo; /* Current font realized by printer driver */
 } WIN16DRV_PDEVICE;
 
+/*
+ * Printer driver functions
+ */
+typedef SEGPTR LPPDEVICE;
+LOADED_PRINTER_DRIVER *LoadPrinterDriver(const char *pszDriver);
+
+extern INT16 PRTDRV_Control(LPPDEVICE lpDestDev, WORD wfunction, SEGPTR lpInData, SEGPTR lpOutData);
+extern WORD PRTDRV_Enable(LPVOID lpDevInfo, WORD wStyle, LPCSTR  lpDestDevType, 
+                          LPCSTR lpDeviceName, LPCSTR lpOutputFile, LPVOID lpData);
+extern WORD PRTDRV_EnumDFonts(LPPDEVICE lpDestDev, LPSTR lpFaceName,  
+		       FARPROC16 lpCallbackFunc, LPVOID lpClientData);
+extern DWORD PRTDRV_RealizeObject(LPPDEVICE lpDestDev, WORD wStyle, 
+				  LPVOID lpInObj, LPVOID lpOutObj,
+				  LPTEXTXFORM16 lpTextXForm);
+
+extern BOOL16 PRTDRV_EnumObj(LPPDEVICE lpDestDev, WORD iStyle, FARPROC16 lpfn, LPVOID lpb);
+extern DWORD PRTDRV_ExtTextOut(LPPDEVICE lpDestDev, WORD wDestXOrg, WORD wDestYOrg,
+			       RECT16 *lpClipRect, LPCSTR lpString, WORD wCount, 
+			       SEGPTR lpFontInfo, LPDRAWMODE lpDrawMode, 
+			       LPTEXTXFORM16 lpTextXForm, SHORT *lpCharWidths,
+			       RECT16 *     lpOpaqueRect, WORD wOptions);
+
+
 /* Wine driver functions */
 
+extern BOOL32 WIN16DRV_GetCharWidth( struct tagDC *dc, UINT32 firstChar, UINT32 lastChar,
+				   LPINT32 buffer );
+
 extern BOOL32 WIN16DRV_GetTextExtentPoint( DC *dc, LPCSTR str, INT32 count,
                                            LPSIZE32 size );
 extern BOOL32 WIN16DRV_GetTextMetrics( DC *dc, TEXTMETRIC32A *metrics );
@@ -164,4 +190,5 @@
 extern HGDIOBJ32 WIN16DRV_SelectObject( DC *dc, HGDIOBJ32 handle );
 
 
+
 #endif  /* __WINE_WIN16DRV_H */
diff --git a/include/windows.h b/include/windows.h
index 6448f63..e55bf16 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -3300,6 +3300,10 @@
 #define CBS_NOINTEGRALHEIGHT  0x0400L
 #define CBS_DISABLENOSCROLL   0x0800L
 
+#define CBS_UPPERCASE	      0x2000L
+#define CBS_LOWERCASE	      0x4000L
+
+
 /* Combo box messages */
 #define CB_GETEDITSEL16            (WM_USER+0)
 #define CB_GETEDITSEL32            0x0140
@@ -4777,6 +4781,10 @@
 #define	C3_ALPHA		0x8000
 #define	C3_NOTAPPLICABLE	0x0000
 
+/* flags that can be passed to LoadLibraryEx */
+#define	DONT_RESOLVE_DLL_REFERENCES	0x00000001
+#define	LOAD_LIBRARY_AS_DATAFILE	0x00000002
+#define	LOAD_WITH_ALTERED_SEARCH_PATH	0x00000008
 
 #pragma pack(4)
 
@@ -4918,7 +4926,6 @@
 VOID       Yield(void);
 
 /* Declarations for functions that exist only in Win32 */
-
 BOOL32     Beep(DWORD,DWORD);
 BOOL32     ClearCommError(INT32,LPDWORD,LPCOMSTAT);
 BOOL32     CloseHandle(HANDLE32);
@@ -4926,12 +4933,21 @@
 BOOL32     CopyFile32W(LPCWSTR,LPCWSTR,BOOL32);
 #define    CopyFile WINELIB_NAME_AW(CopyFile)
 INT32      CompareFileTime(LPFILETIME,LPFILETIME);
+HANDLE32   CreateEvent32A(LPSECURITY_ATTRIBUTES,BOOL32,BOOL32,LPCSTR);
+HANDLE32   CreateEvent32W(LPSECURITY_ATTRIBUTES,BOOL32,BOOL32,LPCWSTR);
+#define    CreateEvent WINELIB_NAME_AW(CreateEvent)
 HFILE32    CreateFile32A(LPCSTR,DWORD,DWORD,LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE32);
 HFILE32    CreateFile32W(LPCWSTR,DWORD,DWORD,LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE32);
 #define    CreateFile WINELIB_NAME_AW(CreateFile)
 HANDLE32   CreateFileMapping32A(HANDLE32,LPSECURITY_ATTRIBUTES,DWORD,DWORD,DWORD,LPCSTR);
 HANDLE32   CreateFileMapping32W(HANDLE32,LPSECURITY_ATTRIBUTES,DWORD,DWORD,DWORD,LPCWSTR);
 #define    CreateFileMapping WINELIB_NAME_AW(CreateFileMapping)
+HANDLE32   CreateMutex32A(LPSECURITY_ATTRIBUTES,BOOL32,LPCSTR);
+HANDLE32   CreateMutex32W(LPSECURITY_ATTRIBUTES,BOOL32,LPCWSTR);
+#define    CreateMutex WINELIB_NAME_AW(CreateMutex)
+HANDLE32   CreateSemaphore32A(LPSECURITY_ATTRIBUTES,LONG,LONG,LPCSTR);
+HANDLE32   CreateSemaphore32W(LPSECURITY_ATTRIBUTES,LONG,LONG,LPCWSTR);
+#define    CreateSemaphore WINELIB_NAME_AW(CreateSemaphore)
 BOOL32     DosDateTimeToFileTime(WORD,WORD,LPFILETIME);
 INT32      EnumPropsEx32A(HWND32,PROPENUMPROCEX32A,LPARAM);
 INT32      EnumPropsEx32W(HWND32,PROPENUMPROCEX32W,LPARAM);
@@ -5024,6 +5040,8 @@
 BOOL32     IsWindowUnicode(HWND32);
 BOOL32     IsValidLocale(DWORD,DWORD);
 BOOL32     LocalFileTimeToFileTime(const FILETIME*,LPFILETIME);
+SEGPTR     MapLS(LPVOID);
+LPVOID     MapSL(SEGPTR);
 LPVOID     MapViewOfFile(HANDLE32,DWORD,DWORD,DWORD,DWORD);
 LPVOID     MapViewOfFileEx(HANDLE32,DWORD,DWORD,DWORD,DWORD,LPVOID);
 INT32      MessageBoxEx32A(HWND32,LPCSTR,LPCSTR,UINT32,WORD);
@@ -5032,9 +5050,18 @@
 BOOL32     MoveFile32A(LPCSTR,LPCSTR);
 BOOL32     MoveFile32W(LPCWSTR,LPCWSTR);
 #define    MoveFile WINELIB_NAME_AW(MoveFile)
+HANDLE32   OpenEvent32A(DWORD,BOOL32,LPCSTR);
+HANDLE32   OpenEvent32W(DWORD,BOOL32,LPCWSTR);
+#define    OpenEvent WINELIB_NAME_AW(OpenEvent)
 HANDLE32   OpenFileMapping32A(DWORD,BOOL32,LPCSTR);
 HANDLE32   OpenFileMapping32W(DWORD,BOOL32,LPCWSTR);
 #define    OpenFileMapping WINELIB_NAME_AW(OpenFileMapping)
+HANDLE32   OpenMutex32A(DWORD,BOOL32,LPCSTR);
+HANDLE32   OpenMutex32W(DWORD,BOOL32,LPCWSTR);
+#define    OpenMutex WINELIB_NAME_AW(OpenMutex)
+HANDLE32   OpenSemaphore32A(DWORD,BOOL32,LPCSTR);
+HANDLE32   OpenSemaphore32W(DWORD,BOOL32,LPCWSTR);
+#define    OpenSemaphore WINELIB_NAME_AW(OpenSemaphore)
 DWORD      QueryDosDevice32A(LPCSTR,LPSTR,DWORD);
 DWORD      QueryDosDevice32W(LPCWSTR,LPWSTR,DWORD);
 #define    QueryDosDevice WINELIB_NAME_AW(QueryDosDevice)
@@ -5059,6 +5086,7 @@
 DWORD      RegQueryInfoKey32A(HKEY,LPSTR,LPDWORD,LPDWORD,LPDWORD,LPDWORD,
                             LPDWORD,LPDWORD,LPDWORD,LPDWORD,LPDWORD,LPFILETIME);
 #define    RegQueryInfoKey WINELIB_NAME_AW(RegQueryInfoKey)
+BOOL32     ReleaseSemaphore(HANDLE32,LONG,LPLONG);
 VOID       RtlFillMemory(LPVOID,UINT32,UINT32);
 VOID       RtlMoveMemory(LPVOID,LPCVOID,UINT32);
 VOID       RtlZeroMemory(LPVOID,UINT32);
@@ -5091,6 +5119,7 @@
 BOOL32     TlsFree(DWORD);
 LPVOID     TlsGetValue(DWORD);
 BOOL32     TlsSetValue(DWORD,LPVOID);
+VOID       UnMapLS(SEGPTR);
 BOOL32     UnmapViewOfFile(LPVOID);
 LPVOID     VirtualAlloc(LPVOID,DWORD,DWORD,DWORD);
 BOOL32     VirtualFree(LPVOID,DWORD,DWORD);
@@ -6474,6 +6503,9 @@
 HGLOBAL16  LockSegment16(HGLOBAL16);
 #define    LockSegment32(handle) GlobalFix32((HANDLE32)(handle))
 #define    LockSegment WINELIB_NAME(LockSegment)
+BOOL16     LockWindowUpdate16(HWND16);
+BOOL32     LockWindowUpdate32(HWND32);
+#define    LockWindowUpdate WINELIB_NAME(LockWindowUpdate)
 BOOL16     LPtoDP16(HDC16,LPPOINT16,INT16);
 BOOL32     LPtoDP32(HDC32,LPPOINT32,INT32);
 #define    LPtoDP WINELIB_NAME(LPtoDP)
@@ -7051,6 +7083,9 @@
 BOOL16     SwapMouseButton16(BOOL16);
 BOOL32     SwapMouseButton32(BOOL32);
 #define    SwapMouseButton WINELIB_NAME(SwapMouseButton)
+VOID       SwitchToThisWindow16(HWND16,BOOL16);
+VOID       SwitchToThisWindow32(HWND32,BOOL32);
+#define    SwitchToThisWindow WINELIB_NAME(SwitchToThisWindow)
 INT16      SyncAllVoices16(void);
 DWORD      SyncAllVoices32(void);
 #define    SyncAllVoices WINELIB_NAME(SyncAllVoices)
diff --git a/include/winproc.h b/include/winproc.h
index 1a5ba11..7a1c696 100644
--- a/include/winproc.h
+++ b/include/winproc.h
@@ -17,13 +17,20 @@
     WIN_PROC_32W
 } WINDOWPROCTYPE;
 
+typedef enum
+{
+    WIN_PROC_CLASS,
+    WIN_PROC_WINDOW,
+    WIN_PROC_TIMER
+} WINDOWPROCUSER;
+
 typedef void *HWINDOWPROC;  /* Really a pointer to a WINDOWPROC */
 
 extern BOOL32 WINPROC_Init(void);
 extern WNDPROC16 WINPROC_GetProc( HWINDOWPROC proc, WINDOWPROCTYPE type );
 extern BOOL32 WINPROC_SetProc( HWINDOWPROC *pFirst, WNDPROC16 func,
-                               WINDOWPROCTYPE type );
-extern void WINPROC_FreeProc( HWINDOWPROC proc );
+                               WINDOWPROCTYPE type, WINDOWPROCUSER user );
+extern void WINPROC_FreeProc( HWINDOWPROC proc, WINDOWPROCUSER user );
 extern WINDOWPROCTYPE WINPROC_GetProcType( HWINDOWPROC proc );
 
 extern INT32 WINPROC_MapMsg32ATo32W( UINT32 msg, WPARAM32 wParam,
@@ -51,8 +58,8 @@
 extern void WINPROC_UnmapMsg16To32W( UINT32 msg, WPARAM32 wParam,
                                      LPARAM lParam );
 extern void WINPROC_UnmapMsg32ATo16( UINT32 msg, WPARAM16 wParam,
-                                     LPARAM lParam );
+                                     LPARAM lParam, LRESULT lResult );
 extern void WINPROC_UnmapMsg32WTo16( UINT32 msg, WPARAM16 wParam,
-                                     LPARAM lParam );
+                                     LPARAM lParam, LRESULT lResult );
 
 #endif  /* __WINE_WINPROC_H */
diff --git a/include/x11drv.h b/include/x11drv.h
index a08831e..26336c9 100644
--- a/include/x11drv.h
+++ b/include/x11drv.h
@@ -53,6 +53,8 @@
 extern BOOL32 X11DRV_BitBlt( struct tagDC *dcDst, INT32 xDst, INT32 yDst,
                              INT32 width, INT32 height, struct tagDC *dcSrc,
                              INT32 xSrc, INT32 ySrc, DWORD rop );
+extern BOOL32 X11DRV_GetCharWidth( struct tagDC *dc, UINT32 firstChar,
+                                   UINT32 lastChar, LPINT32 buffer );
 extern BOOL32 X11DRV_GetTextExtentPoint( struct tagDC *dc, LPCSTR str,
                                          INT32 count, LPSIZE32 size );
 extern BOOL32 X11DRV_GetTextMetrics(struct tagDC *dc, TEXTMETRIC32A *metrics);
diff --git a/library/miscstubs.c b/library/miscstubs.c
index 0b021da..693fbcc 100644
--- a/library/miscstubs.c
+++ b/library/miscstubs.c
@@ -46,8 +46,6 @@
 }
 
 extern LRESULT ColorDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
-extern LRESULT ComboBoxWndProc(HWND16,UINT16,WPARAM16,LPARAM);
-extern LRESULT ComboLBoxWndProc(HWND16,UINT16,WPARAM16,LPARAM);
 extern LRESULT FileOpenDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
 extern LRESULT FileSaveDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
 extern LRESULT FindTextDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
@@ -68,8 +66,6 @@
 {
 #define MAP_STR_TO_PROC(str,proc) if(!strcmp(name,str))return (FARPROC16)proc
   MAP_STR_TO_PROC("ColorDlgProc",ColorDlgProc);
-  MAP_STR_TO_PROC("ComboBoxWndProc",ComboBoxWndProc);
-  MAP_STR_TO_PROC("ComboLBoxWndProc",ComboLBoxWndProc);
   MAP_STR_TO_PROC("FileOpenDlgProc",FileOpenDlgProc);
   MAP_STR_TO_PROC("FileSaveDlgProc",FileSaveDlgProc);
   MAP_STR_TO_PROC("FindTextDlgProc",FindTextDlgProc);
diff --git a/loader/ne_image.c b/loader/ne_image.c
index f81cf82..0887a53 100644
--- a/loader/ne_image.c
+++ b/loader/ne_image.c
@@ -60,7 +60,9 @@
     dprintf_module( stddeb, "Loading segment %d, selector=%04x\n",
                     segnum, pSeg->selector );
     lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
-    size = pSeg->size ? pSeg->size : 0x10000;
+    if (pSeg->size) size = pSeg->size;
+    else if (pSeg->minsize) size = pSeg->minsize;
+    else size = 0x10000;
     mem = GlobalLock16(pSeg->selector);
     if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1)
     {
@@ -236,7 +238,7 @@
 	    break;
 	    
 	  case NE_RELTYPE_INTERNAL:
-	    if (rep->target1 == 0x00ff)
+	    if ((rep->target1 & 0xff) == 0xff)
 	    {
 		address  = MODULE_GetEntryPoint( hModule, rep->target2 );
 	    }
diff --git a/loader/pe_image.c b/loader/pe_image.c
index 24cf3e9..efcda7f 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -32,6 +32,9 @@
 #include "debugger.h"
 #include "xmalloc.h"
 
+static void PE_InitDLL(HMODULE16 hModule, DWORD type, LPVOID lpReserved);
+
+
 /* convert PE image VirtualAddress to Real Address */
 #define RVA(x) ((unsigned int)load_addr+(unsigned int)(x))
 
@@ -406,8 +409,7 @@
 	load_addr = pe->load_addr = (int)xmalloc(pe->vma_size);
 	memset( load_addr, 0, pe->vma_size);
 #else
-	load_addr = (int) VirtualAlloc( NULL, pe->vma_size, MEM_COMMIT,
-                                         PAGE_EXECUTE_READWRITE );
+	load_addr = (int) VirtualAlloc( (void*)pe->base_addr, pe->vma_size, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
         pe->load_addr = load_addr;
 #endif
 
@@ -601,7 +603,12 @@
 	return 1;
 }
 
-static void PE_InitDLL(HMODULE16 hModule)
+/* Called if the library is loaded or freed.
+ * NOTE: if a thread attaches a DLL, the current thread will only do
+ * DLL_PROCESS_ATTACH. Only new created threads do DLL_THREAD_ATTACH
+ * (SDK)
+ */
+static void PE_InitDLL(HMODULE16 hModule, DWORD type,LPVOID lpReserved)
 {
     NE_MODULE *pModule;
     PE_MODULE *pe;
@@ -612,8 +619,11 @@
     if (!(pModule->flags & NE_FFLAGS_WIN32) || !(pe = pModule->pe_module))
         return;
 
-    /* FIXME: What is the correct value for parameter 3? 
-     *	      (the MSDN library JAN96 says 'reserved for future use')
+    /*  DLL_ATTACH_PROCESS:
+     *		lpreserved is NULL for dynamic loads, not-NULL for static loads
+     *  DLL_DETACH_PROCESS:
+     *		lpreserved is NULL if called by FreeLibrary, not-NULL otherwise
+     *  the SDK doesn't mention anything for DLL_THREAD_*
      */
         
     /* Is this a library? And has it got an entrypoint? */
@@ -625,13 +635,13 @@
 	CallDLLEntryProc32( 
 	    (FARPROC32)RVA(pe->pe_header->OptionalHeader.AddressOfEntryPoint),
 	    hModule,
-	    DLL_PROCESS_ATTACH,
-	    -1
+	    type,
+	    (DWORD)lpReserved
 	);
     }
 }
 
-void PE_InitializeDLLs(HMODULE16 hModule)
+void PE_InitializeDLLs(HMODULE16 hModule,DWORD type,LPVOID lpReserved)
 {
 	NE_MODULE *pModule;
 	HMODULE16 *pDLL;
@@ -640,14 +650,15 @@
 	{
 		HGLOBAL16 to_init = pModule->dlls_to_init;
 		pModule->dlls_to_init = 0;
+	
 		for (pDLL = (HMODULE16 *)GlobalLock16( to_init ); *pDLL; pDLL++)
 		{
-			PE_InitializeDLLs( *pDLL );
-			PE_InitDLL( *pDLL );
+			PE_InitializeDLLs( *pDLL, type, lpReserved);
+			PE_InitDLL( *pDLL, type, lpReserved );
 		}
 		GlobalFree16( to_init );
 	}
-	PE_InitDLL( hModule );
+	PE_InitDLL( hModule, type, lpReserved );
 }
 
 void PE_InitTls( PE_MODULE *module )
diff --git a/loader/signal.c b/loader/signal.c
index 17739ec..fd2203f 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -1,7 +1,11 @@
 #ifndef WINELIB
 #include <stdio.h>
 #include <stdlib.h>
+#ifdef __GLIBC__
+#include <linux/signal.h>
+#else
 #include <signal.h>
+#endif
 #include <string.h>
 #include <errno.h>
 #include <time.h>
diff --git a/loader/task.c b/loader/task.c
index 38e6028..9895f93 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -365,7 +365,7 @@
         InitTask( NULL );
         InitApp( pTask->hModule );
         __asm__ __volatile__("movw %w0,%%fs"::"r" (pCurrentThread->teb_sel));
-        PE_InitializeDLLs( pTask->hModule );
+        PE_InitializeDLLs( pTask->hModule, DLL_PROCESS_ATTACH, (LPVOID)-1 );
         exit_code = CallTaskStart32((FARPROC32)(pModule->pe_module->load_addr + 
                 pModule->pe_module->pe_header->OptionalHeader.AddressOfEntryPoint) );
         TASK_KillCurrentTask( exit_code );
diff --git a/memory/global.c b/memory/global.c
index 1a5c12e..f5d7d18 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -794,7 +794,11 @@
 {
     MEMORYSTATUS status;
 
-    if (info->dwSize < sizeof(MEMMANINFO)) return FALSE;
+    /*
+     * Not unsurprisingly although the documention says you 
+     * _must_ provide the size in the dwSize field, this function
+     * (under Windows) always fills the structure and returns true.
+     */
     GlobalMemoryStatus( &status );
 #ifdef __svr4__
     info->wPageSize            = sysconf(_SC_PAGESIZE);
diff --git a/memory/selector.c b/memory/selector.c
index 1da0768..b3f2454 100644
--- a/memory/selector.c
+++ b/memory/selector.c
@@ -462,3 +462,43 @@
     memcpy( ((char *)GET_SEL_BASE(sel)) + offset, buffer, count );
     return count;
 }
+
+/************************************* Win95 pointer mapping functions *
+ *
+ * NOTE: MapSLFix and UnMapSLFixArray are probably needed to prevent
+ * unexpected linear address change when GlobalCompact() shuffles
+ * moveable blocks.
+ */
+
+/***********************************************************************
+ *           MapSL   (KERNEL32.662)
+ *
+ * Maps fixed segmented pointer to linear.
+ */
+LPVOID MapSL( SEGPTR sptr )
+{
+    return (LPVOID)PTR_SEG_TO_LIN(sptr);
+}
+
+
+/***********************************************************************
+ *           MapLS   (KERNEL32.679)
+ *
+ * Maps linear pointer to segmented.
+ */
+SEGPTR MapLS( LPVOID ptr )
+{
+    WORD sel = SELECTOR_AllocBlock( ptr, 0x10000, SEGMENT_DATA, FALSE, FALSE );
+    return PTR_SEG_OFF_TO_SEGPTR( sel, 0 );
+}
+
+
+/***********************************************************************
+ *           UnMapLS   (KERNEL32.680)
+ *
+ * Free mapped selector.
+ */
+void UnMapLS( SEGPTR sptr )
+{
+    if (!__winelib) SELECTOR_FreeBlock( SELECTOROF(sptr), 1 );
+}
diff --git a/memory/virtual.c b/memory/virtual.c
index 0cc397a..362fd36 100644
--- a/memory/virtual.c
+++ b/memory/virtual.c
@@ -874,6 +874,8 @@
     }
 
     if (!(mapping = HeapAlloc( SystemHeap, 0, sizeof(*mapping) ))) goto error;
+    mapping->header.type = K32OBJ_MEM_MAPPED_FILE;
+    mapping->header.refcount = 1;
     mapping->protect   = VIRTUAL_GetProt( protect ) | VPROT_COMMITTED;
     mapping->size_high = size_high;
     mapping->size_low  = size_low;
diff --git a/misc/clipboard.c b/misc/clipboard.c
index 9282a44..d4e9276 100644
--- a/misc/clipboard.c
+++ b/misc/clipboard.c
@@ -75,7 +75,7 @@
 /**************************************************************************
  *                      CLIPBOARD_CheckSelection
  */
-void CLIPBOARD_CheckSelection(WND* pWnd)
+static void CLIPBOARD_CheckSelection(WND* pWnd)
 {
   dprintf_clipboard(stddeb,"\tchecking %08x\n", (unsigned)pWnd->window);
 
@@ -141,7 +141,7 @@
 /**************************************************************************
  *			CLIPBOARD_DeleteRecord
  */
-void CLIPBOARD_DeleteRecord(LPCLIPFORMAT lpFormat)
+static void CLIPBOARD_DeleteRecord(LPCLIPFORMAT lpFormat, BOOL32 bChange)
 {
   if( lpFormat->wFormatID >= CF_GDIOBJFIRST &&
       lpFormat->wFormatID <= CF_GDIOBJLAST )
@@ -152,13 +152,13 @@
   lpFormat->wDataPresent = 0; 
   lpFormat->hData = 0;
 
-  bClipChanged = TRUE;
+  if( bChange ) bClipChanged = TRUE;
 }
 
 /**************************************************************************
  *			CLIPBOARD_RequestXSelection
  */
-BOOL32 CLIPBOARD_RequestXSelection()
+static BOOL32 CLIPBOARD_RequestXSelection()
 {
   HWND32 hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow32();
 
@@ -291,7 +291,7 @@
     while(lpFormat) 
       {
 	if ( lpFormat->wDataPresent || lpFormat->hData )
-	     CLIPBOARD_DeleteRecord( lpFormat );
+	     CLIPBOARD_DeleteRecord( lpFormat, TRUE );
 
 	lpFormat = lpFormat->NextFormat;
       }
@@ -368,16 +368,16 @@
 
     if ( lpFormat->wDataPresent || lpFormat->hData ) 
     {
-	CLIPBOARD_DeleteRecord(lpFormat);
+	CLIPBOARD_DeleteRecord(lpFormat, TRUE);
 
 	/* delete existing CF_TEXT/CF_OEMTEXT aliases */
 
 	if( wFormat == CF_TEXT && ClipFormats[CF_OEMTEXT-1].hData
 	    && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
-	    CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1]);
+	    CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
         if( wFormat == CF_OEMTEXT && ClipFormats[CF_TEXT-1].hData
 	    && !ClipFormats[CF_TEXT-1].wDataPresent )
-	    CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1]);
+	    CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
     }
 
     bClipChanged = TRUE;
@@ -401,7 +401,7 @@
 /**************************************************************************
  *                      CLIPBOARD_RenderFormat
  */
-BOOL32 CLIPBOARD_RenderFormat(LPCLIPFORMAT lpFormat)
+static BOOL32 CLIPBOARD_RenderFormat(LPCLIPFORMAT lpFormat)
 {
  if( lpFormat->wDataPresent && !lpFormat->hData )
    if( IsWindow32(hWndClipOwner) )
@@ -420,7 +420,7 @@
 /**************************************************************************
  *                      CLIPBOARD_RenderText
  */
-BOOL32 CLIPBOARD_RenderText(LPCLIPFORMAT lpTarget, LPCLIPFORMAT lpSource)
+static BOOL32 CLIPBOARD_RenderText(LPCLIPFORMAT lpTarget, LPCLIPFORMAT lpSource)
 {
   UINT16 size = GlobalSize16( lpSource->hData );
   LPCSTR	lpstrS = (LPSTR)GlobalLock16(lpSource->hData);
@@ -909,10 +909,10 @@
    {
      lpFormat = &ClipFormats[CF_TEXT-1];
      if (lpFormat->wDataPresent || lpFormat->hData) 
-         CLIPBOARD_DeleteRecord(lpFormat);
+         CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
      lpFormat = &ClipFormats[CF_OEMTEXT-1];
      if (lpFormat->wDataPresent || lpFormat->hData) 
-         CLIPBOARD_DeleteRecord(lpFormat);
+         CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
 
      lpFormat->wDataPresent = 1;
      lpFormat->hData = hText;
diff --git a/misc/crtdll.c b/misc/crtdll.c
index ea185ac..563bd39 100644
--- a/misc/crtdll.c
+++ b/misc/crtdll.c
@@ -946,6 +946,26 @@
 }
 
 /*********************************************************************
+ *                  _chdir           (CRTDLL.51)
+ */
+INT32
+CRTDLL__chdir(LPCSTR newdir) {
+	if (!SetCurrentDirectory32A(newdir))
+		return -1;
+	return 0;
+}
+
+/*********************************************************************
+ *                  _mkdir           (CRTDLL.234)
+ */
+INT32
+CRTDLL__mkdir(LPCSTR newdir) {
+	if (!CreateDirectory32A(newdir,NULL))
+		return -1;
+	return 0;
+}
+
+/*********************************************************************
  *                  _errno           (CRTDLL.52)
  * Yes, this is a function.
  */
diff --git a/misc/main.c b/misc/main.c
index 96a915a..57832ad 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -35,26 +35,31 @@
 #include "xmalloc.h"
 
 const char people[] = "Wine is available thanks to the work of "
-"Bob Amstadt, Dag Asheim, Martin Ayotte, Ross Biro, Uwe Bonnes, Erik Bos, "
-"Fons Botman, John Brezak, Andrew Bulhak, John Burton, "
-"Niels de Carpentier, Roman Dolejsi, Frans van Dorsselaer, Paul Falstad, "
-"Olaf Flebbe, Peter Galbavy, Ramon Garcia, Hans de Graaff, "
-"Charles M. Hannum, John Harvey, Cameron Heide, Jochen Hoenicke, "
-"Onno Hovers, Jeffrey Hsu, Miguel de Icaza, Jukka Iivonen, "
-"Alexandre Julliard, Jochen Karrer, Andreas Kirschbaum, Albrecht Kleine, "
+"Bob Amstadt, Dag Asheim, Martin Ayotte, Peter Bajusz, Ross Biro, "
+"Uwe Bonnes, Erik Bos, Fons Botman, John Brezak, Andrew Bulhak, "
+"John Burton, Niels de Carpentier, Jimen Ching, Huw D. M. Davies, "
+"Roman Dolejsi, Frans van Dorsselaer, Paul Falstad, David Faure, "
+"Olaf Flebbe, Peter Galbavy, Ramon Garcia, Matthew Ghio, "
+"Hans de Graaff, Charles M. Hannum, John Harvey, Cameron Heide, "
+"Jochen Hoenicke, Onno Hovers, Jeffrey Hsu, Miguel de Icaza, "
+"Jukka Iivonen, Lee Jaekil, Alexandre Julliard, Bang Jun-Young, "
+"Pavel Kankovsky, Jochen Karrer, Andreas Kirschbaum, Albrecht Kleine, "
 "Jon Konrath, Alex Korobka, Greg Kreider, Anand Kumria, Scott A. Laird, "
-"Martin von Loewis, Kenneth MacDonald, Peter MacDonald, William Magro, "
-"Juergen Marquardt, Marcus Meissner, Graham Menhennitt, David Metcalfe, "
-"Steffen Moeller, Philippe De Muyter, Itai Nahshon, Michael Patra, "
-"Jim Peterson, Robert Pouliot, Keith Reynolds, John Richardson, "
-"Johannes Ruscheinski, Thomas Sandford, Constantine Sapuntzakis, "
-"Daniel Schepler, Ulrich Schmid, Bernd Schmidt, Yngvi Sigurjonsson, "
-"Rick Sladkey, William Smith, Erik Svendsen, Tristan Tarrant, "
-"Andrew Taylor, Duncan C Thomson, Goran Thyni, Jimmy Tirtawangsa, "
-"Jon Tombs, Linus Torvalds, Gregory Trubetskoy, Michael Veksler, "
-"Sven Verdoolaege, Eric Warnke, Manfred Weichel, Morten Welinder, "
+"Andrew Lewycky, Martin von Loewis, Kenneth MacDonald, Peter MacDonald, "
+"William Magro, Juergen Marquardt, Ricardo Massaro, Marcus Meissner, "
+"Graham Menhennitt, David Metcalfe, Bruce Milner, Steffen Moeller, "
+"Andreas Mohr, Philippe De Muyter, Itai Nahshon, Michael Patra, "
+"Jim Peterson, Robert Pouliot, Keith Reynolds, Slaven Rezic, "
+"John Richardson, Johannes Ruscheinski, Thomas Sandford, "
+"Constantine Sapuntzakis, Pablo Saratxaga, Daniel Schepler, "
+"Ulrich Schmid, Bernd Schmidt, Yngvi Sigurjonsson, Stephen Simmons, "
+"Rick Sladkey, William Smith, Dominik Strasser, Vadim Strizhevsky, "
+"Erik Svendsen, Tristan Tarrant, Andrew Taylor, Duncan C Thomson, "
+"Goran Thyni, Jimmy Tirtawangsa, Jon Tombs, Linus Torvalds, "
+"Gregory Trubetskoy, Petri Tuomola, Michael Veksler, Sven Verdoolaege, "
+"Ronan Waide, Eric Warnke, Manfred Weichel, Morten Welinder, "
 "Jan Willamowius, Carl Williams, Karl Guenter Wuensch, Eric Youngdale, "
-"and James Youngman. ";
+"James Youngman, Mikolaj Zalewski, and John Zero.";
 
 const WINE_LANGUAGE_DEF Languages[] =
 {
@@ -71,6 +76,7 @@
     {"Ko",0x0412},	/* LANG_Ko */
     {"Hu",0x0436},	/* LANG_Hu */
     {"Pl",0x0415},      /* LANG_Pl */
+    {"Po",0x0416},      /* LANG_Po */
     {NULL,0}
 };
 
@@ -163,7 +169,7 @@
   "    -fixedmap       Use a \"standard\" color map\n" \
   "    -iconic         Start as an icon\n" \
   "    -ipc            Enable IPC facilities\n" \
-  "    -language xx    Set the language (one of En,Es,De,No,Fr,Fi,Da,Cz,Eo,It,Ko,\n                    Hu,Pl)\n" \
+  "    -language xx    Set the language (one of En,Es,De,No,Fr,Fi,Da,Cz,Eo,It,Ko,\n                    Hu,Pl,Po)\n" \
   "    -managed        Allow the window manager to manage created windows\n" \
   "    -mode mode      Start Wine in a particular mode (standard or enhanced)\n" \
   "    -name name      Set the application name\n" \
diff --git a/misc/ntdll.c b/misc/ntdll.c
index a83b049..cd430dc 100644
--- a/misc/ntdll.c
+++ b/misc/ntdll.c
@@ -369,12 +369,12 @@
 }
 
 /**************************************************************************
- *                 RtlInitUnicodeString			[NTDLL]
+ *                 RtlFreeUnicodeString			[NTDLL]
  */
 VOID
 RtlFreeUnicodeString(LPUNICODE_STRING str) {
 	if (str->Buffer)
-		HeapFree(GetProcessHeap(),0,str);
+		HeapFree(GetProcessHeap(),0,str->Buffer);
 }
 
 /**************************************************************************
@@ -399,7 +399,22 @@
  *                 RtlUnicodeStringToOemString		[NTDLL]
  */
 DWORD /* NTSTATUS */
-RtlUnicodeStringToOemString(LPUNICODE_STRING uni,LPANSI_STRING oem,BOOL32 alloc)
+RtlUnicodeStringToOemString(LPANSI_STRING oem,LPUNICODE_STRING uni,BOOL32 alloc)
+{
+	if (alloc) {
+		oem->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,uni->Length/2)+1;
+		oem->MaximumLength = uni->Length/2+1;
+	}
+	oem->Length = uni->Length/2;
+	lstrcpynWtoA(oem->Buffer,uni->Buffer,uni->Length/2+1);
+	return 0;
+}
+
+/**************************************************************************
+ *                 RtlUnicodeStringToAnsiString		[NTDLL]
+ */
+DWORD /* NTSTATUS */
+RtlUnicodeStringToAnsiString(LPUNICODE_STRING uni,LPANSI_STRING oem,BOOL32 alloc)
 {
 	if (alloc) {
 		oem->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,uni->Length/2)+1;
@@ -447,11 +462,9 @@
 	if (dest->MaximumLength < len)
 		return STATUS_BUFFER_OVERFLOW;
 	s=dest->Buffer;t=src->Buffer;
-	for (i=0;i<len;i++) {
+	/* len is in bytes */
+	for (i=0;i<len/2;i++)
 		s[i]=toupper(t[i]);
-		s++;
-		t++;
-	}
 	return STATUS_SUCCESS;
 }
 
diff --git a/misc/ole2nls.c b/misc/ole2nls.c
index ebbd70d..66e2f36 100644
--- a/misc/ole2nls.c
+++ b/misc/ole2nls.c
@@ -152,7 +152,7 @@
  /* case LANG_Du: return 0x13; */      /* Dutch */
     case LANG_No: return 0x14;         /* Norwegian */
     case LANG_Pl: return 0x15;         /* Polish */
- /* case LANG_Po: return 0x16; */      /* Portuguese */
+    case LANG_Po: return 0x16;         /* Portuguese */
  /* case LANG_Ro: return 0x18; */      /* Romanian */
  /* case LANG_Ru: return 0x19; */      /* Russian */
  /* case LANG_Cr: return 0x1a; */      /* Croatian */
@@ -1510,6 +1510,112 @@
 	}
     break;  /* LANG(Pl) */
 
+    case LANG_Po:
+    	switch (LCType) {
+LOCVAL(LOCALE_ILANGUAGE, "0416")
+LOCVAL(LOCALE_SLANGUAGE, "Portugu\352s (Brasil)")
+LOCVAL(LOCALE_SENGLANGUAGE, "Protuguese")
+LOCVAL(LOCALE_SABBREVLANGNAME, "POR")
+LOCVAL(LOCALE_SNATIVELANGNAME, "Portugu\352s")
+LOCVAL(LOCALE_ICOUNTRY, "1")
+LOCVAL(LOCALE_SCOUNTRY, "Brasil")
+LOCVAL(LOCALE_SENGCOUNTRY, "Brazil")
+LOCVAL(LOCALE_SABBREVCTRYNAME, "BRA")
+LOCVAL(LOCALE_SNATIVECTRYNAME, "Brasil")
+LOCVAL(LOCALE_IDEFAULTLANGUAGE, "0409")
+LOCVAL(LOCALE_IDEFAULTCOUNTRY, "1")
+LOCVAL(LOCALE_IDEFAULTCODEPAGE, "437")
+LOCVAL(LOCALE_IDEFAULTANSICODEPAGE, "1252")
+LOCVAL(LOCALE_SLIST, ";")
+LOCVAL(LOCALE_IMEASURE, "1")
+LOCVAL(LOCALE_SDECIMAL, ",")
+LOCVAL(LOCALE_STHOUSAND, ".")
+LOCVAL(LOCALE_SGROUPING, "3;0")
+LOCVAL(LOCALE_IDIGITS, "2")
+LOCVAL(LOCALE_ILZERO, "1")
+LOCVAL(LOCALE_INEGNUMBER, "1")
+LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789")
+LOCVAL(LOCALE_SCURRENCY, "$")
+LOCVAL(LOCALE_SINTLSYMBOL, "USD")
+LOCVAL(LOCALE_SMONDECIMALSEP, ",")
+LOCVAL(LOCALE_SMONTHOUSANDSEP, ".")
+LOCVAL(LOCALE_SMONGROUPING, "3;0")
+LOCVAL(LOCALE_ICURRDIGITS, "2")
+LOCVAL(LOCALE_IINTLCURRDIGITS, "2")
+LOCVAL(LOCALE_ICURRENCY, "0")
+LOCVAL(LOCALE_INEGCURR, "0")
+LOCVAL(LOCALE_SDATE, "/")
+LOCVAL(LOCALE_STIME, ":")
+LOCVAL(LOCALE_SSHORTDATE, "dd/MM/yy")
+LOCVAL(LOCALE_SLONGDATE, "dddd, MMMM dd, yyyy")
+LOCVAL(LOCALE_STIMEFORMAT, "h:mm:ss tt")
+LOCVAL(LOCALE_IDATE, "0")
+LOCVAL(LOCALE_ILDATE, "0")
+LOCVAL(LOCALE_ITIME, "0")
+LOCVAL(LOCALE_ITIMEMARKPOSN, "0")
+LOCVAL(LOCALE_ICENTURY, "0")
+LOCVAL(LOCALE_ITLZERO, "0")
+LOCVAL(LOCALE_IDAYLZERO, "0")
+LOCVAL(LOCALE_IMONLZERO, "0")
+LOCVAL(LOCALE_S1159, "AM")
+LOCVAL(LOCALE_S2359, "PM")
+LOCVAL(LOCALE_ICALENDARTYPE, "1")
+LOCVAL(LOCALE_IOPTIONALCALENDAR, "0")
+LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "6")
+LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0")
+LOCVAL(LOCALE_SDAYNAME1, "Segunda")
+LOCVAL(LOCALE_SDAYNAME2, "Ter\347a")
+LOCVAL(LOCALE_SDAYNAME3, "Quarta")
+LOCVAL(LOCALE_SDAYNAME4, "Quinta")
+LOCVAL(LOCALE_SDAYNAME5, "Sexta")
+LOCVAL(LOCALE_SDAYNAME6, "S\341bado")
+LOCVAL(LOCALE_SDAYNAME7, "Domingo")
+LOCVAL(LOCALE_SABBREVDAYNAME1, "Seg")
+LOCVAL(LOCALE_SABBREVDAYNAME2, "Ter")
+LOCVAL(LOCALE_SABBREVDAYNAME3, "Qua")
+LOCVAL(LOCALE_SABBREVDAYNAME4, "Qui")
+LOCVAL(LOCALE_SABBREVDAYNAME5, "Sex")
+LOCVAL(LOCALE_SABBREVDAYNAME6, "S\341b")
+LOCVAL(LOCALE_SABBREVDAYNAME7, "Dom")
+LOCVAL(LOCALE_SMONTHNAME1, "Janeiro")
+LOCVAL(LOCALE_SMONTHNAME2, "Fevereiro")
+LOCVAL(LOCALE_SMONTHNAME3, "Mar\347o")
+LOCVAL(LOCALE_SMONTHNAME4, "Abril")
+LOCVAL(LOCALE_SMONTHNAME5, "Maio")
+LOCVAL(LOCALE_SMONTHNAME6, "Junho")
+LOCVAL(LOCALE_SMONTHNAME7, "Julho")
+LOCVAL(LOCALE_SMONTHNAME8, "Agosto")
+LOCVAL(LOCALE_SMONTHNAME9, "Setembro")
+LOCVAL(LOCALE_SMONTHNAME10, "Outubro")
+LOCVAL(LOCALE_SMONTHNAME11, "Novembro")
+LOCVAL(LOCALE_SMONTHNAME12, "Dezembro")
+LOCVAL(LOCALE_SMONTHNAME13, "")
+LOCVAL(LOCALE_SABBREVMONTHNAME1, "Jan")
+LOCVAL(LOCALE_SABBREVMONTHNAME2, "Fev")
+LOCVAL(LOCALE_SABBREVMONTHNAME3, "Mar")
+LOCVAL(LOCALE_SABBREVMONTHNAME4, "Abr")
+LOCVAL(LOCALE_SABBREVMONTHNAME5, "Mai")
+LOCVAL(LOCALE_SABBREVMONTHNAME6, "Jun")
+LOCVAL(LOCALE_SABBREVMONTHNAME7, "Jul")
+LOCVAL(LOCALE_SABBREVMONTHNAME8, "Ago")
+LOCVAL(LOCALE_SABBREVMONTHNAME9, "Set")
+LOCVAL(LOCALE_SABBREVMONTHNAME10, "Out")
+LOCVAL(LOCALE_SABBREVMONTHNAME11, "Nov")
+LOCVAL(LOCALE_SABBREVMONTHNAME12, "Dez")
+LOCVAL(LOCALE_SABBREVMONTHNAME13, "")
+LOCVAL(LOCALE_SPOSITIVESIGN, "")
+LOCVAL(LOCALE_SNEGATIVESIGN, "-")
+LOCVAL(LOCALE_IPOSSIGNPOSN, "3")
+LOCVAL(LOCALE_INEGSIGNPOSN, "0")
+LOCVAL(LOCALE_IPOSSYMPRECEDES, "1")
+LOCVAL(LOCALE_IPOSSEPBYSPACE, "0")
+LOCVAL(LOCALE_INEGSYMPRECEDES, "1")
+LOCVAL(LOCALE_INEGSEPBYSPACE, "0")
+	default: found=0;break;
+	}
+    break; /* LANG(Po) */
+
+
 /*Insert other languages here*/
 
     default:
diff --git a/misc/ver.c b/misc/ver.c
index 2779a00..b381f35 100644
--- a/misc/ver.c
+++ b/misc/ver.c
@@ -577,7 +577,7 @@
     	buf1 = _fetch_versioninfo(destfn);
 	if (buf1) {
 	    buf2 = _fetch_versioninfo(tmpfn);
-	    if (!buf2) {
+	    if (buf2) {
 	    	char	*tbuf1,*tbuf2;
 		VS_FIXEDFILEINFO *destvffi,*tmpvffi;
 		UINT32	len1,len2;
diff --git a/msdos/int21.c b/msdos/int21.c
index 37dc6f0..caa2e78 100644
--- a/msdos/int21.c
+++ b/msdos/int21.c
@@ -1073,8 +1073,8 @@
 		break;
 
 	      case 0x05: /* GET BOOT DRIVE */
-		DL_reg(context) = 2;
-		/* c: is Wine's bootdrive */
+		DL_reg(context) = 3;
+		/* c: is Wine's bootdrive (a: is 1)*/
 		break;
 				
 	      case 0x06: /* GET TRUE VERSION NUMBER */
@@ -1354,8 +1354,6 @@
             AX_reg(context) = DOS_ExtendedError;
             SET_CFLAG(context);
         }
-        else AX_reg(context) = 0x0100; 
-        /* intlist: many Microsoft products for Windows rely on this */
         break;
 	
     case 0x48: /* ALLOCATE MEMORY */
@@ -1634,12 +1632,53 @@
                 SET_CFLAG(context);
             }
             break;
+        case 0x43:  /* Get/Set file attributes */
+        switch (BL_reg(context))
+        {
+        case 0x00: /* Get file attributes */
+            CX_reg(context) = (WORD)GetFileAttributes32A(
+                                          PTR_SEG_OFF_TO_LIN(DS_reg(context),
+                                                             DX_reg(context)));
+            if (CX_reg(context) == 0xffff)
+            {
+                AX_reg(context) = DOS_ExtendedError;
+                SET_CFLAG(context);
+            }
+            break;
+        case 0x01:
+            if (!SetFileAttributes32A( PTR_SEG_OFF_TO_LIN(DS_reg(context),
+                                                          DX_reg(context)),
+                                       CX_reg(context) ))
+            {
+                AX_reg(context) = DOS_ExtendedError;
+                SET_CFLAG(context);
+            }
+            break;
+	default:
+	  fprintf( stderr, 
+		   "Unimplemented int21 long file name function:\n");
+	  INT_BARF( context, 0x21 );
+	  SET_CFLAG(context);
+	  AL_reg(context) = 0;
+	  break;
+	}
+	break;
+        case 0x47:  /* Get current directory */
+	  if (!INT21_GetCurrentDirectory(context))
+	    {
+	      AX_reg(context) = DOS_ExtendedError;
+	      SET_CFLAG(context);
+	    }
+	  else AX_reg(context) = 0x0100; 
+        /* intlist: many Microsoft products for Windows rely on this */
+        break;
         case 0x4e:  /* Find first file */
             /* FIXME: use attributes in CX */
-            if (!(AX_reg(context) = FindFirstFile16(
+            if ((AX_reg(context) = FindFirstFile16(
                    PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)),
                    (WIN32_FIND_DATA32A *)PTR_SEG_OFF_TO_LIN(ES_reg(context),
-                                                            DI_reg(context)))))
+                                                            DI_reg(context))))
+		== INVALID_HANDLE_VALUE16)
             {
                 AX_reg(context) = DOS_ExtendedError;
                 SET_CFLAG(context);
@@ -1663,12 +1702,37 @@
             break;
 	case 0xa0:
 	    break;
+        case 0x60:  
+	  switch(CL_reg(context))
+	    {
+	    case 0x02:  /*Get canonical long filename or path */
+	      if (!GetFullPathName32A
+		  ( PTR_SEG_OFF_TO_LIN(DS_reg(context),
+				       SI_reg(context)), 128,
+		    PTR_SEG_OFF_TO_LIN(ES_reg(context),
+				       DI_reg(context)),NULL))
+		{
+		  AX_reg(context) = DOS_ExtendedError;
+		  SET_CFLAG(context);
+		}
+	      else AX_reg(context) = 0;
+	      break;
+	    default:
+	      fprintf( stderr, 
+		       "Unimplemented int21 long file name function:\n");
+	      INT_BARF( context, 0x21 );
+	      SET_CFLAG(context);
+	      AL_reg(context) = 0;
+	      break;
+	    }
+	    break;
+        case 0x6c:  /* Create or open file */
+	  /* translate Dos 7 action to Dos 6 action */
+	    ExtendedOpenCreateFile(context);
+	    break;
         case 0x3b:  /* Change directory */
         case 0x41:  /* Delete file */
-        case 0x43:  /* Get/Set file attributes */
-        case 0x47:  /* Get current directory */
         case 0x56:  /* Move (rename) file */
-        case 0x6c:  /* Create/Open file */
         default:
             fprintf( stderr, "Unimplemented int21 long file name function:\n");
             INT_BARF( context, 0x21 );
diff --git a/objects/color.c b/objects/color.c
index 5b8c761..943b1da 100644
--- a/objects/color.c
+++ b/objects/color.c
@@ -861,7 +861,7 @@
 
     if( spec_type > 2 )
     {  
-	fprintf(stderr, "COLOR_ToPhysical : invalid RGB specifier for: %08lx\n", color);
+	dprintf_palette(stddeb, "COLOR_ToPhysical : invalid RGB specifier for: %08lx\n", color);
 	spec_type = 0;
     }
 
diff --git a/objects/dib.c b/objects/dib.c
index 29aba34..76db125 100644
--- a/objects/dib.c
+++ b/objects/dib.c
@@ -29,15 +29,18 @@
 
     switch(depth)
     {
-    case 1:  words = (width + 31) / 32; break;
-    case 4:  words = (width + 7) / 8; break;
-    case 8:  words = (width + 3) / 4; break;
-    case 15:
-    case 16: words = (width + 1) / 2; break;
-    case 24: words = width; break;
-    default:
-        fprintf(stderr, "DIB: unsupported depth %d.\n", depth );
-        exit(1);
+	case 1:  words = (width + 31) / 32; break;
+	case 4:  words = (width + 7) / 8; break;
+	case 8:  words = (width + 3) / 4; break;
+	case 15:
+	case 16: words = (width + 1) / 2; break;
+	case 24: words = (width * 3 + 3)/4; break;
+
+	default:
+        	fprintf(stderr, "DIB: unsupported depth %d.\n", depth );
+	/* fall through */
+	case 32:
+	        words = width;
     }
     return 4 * words;
 }
@@ -71,29 +74,6 @@
 
 
 /***********************************************************************
- *           DIB_DIBmpToImage
- *
- * Create an XImage pointing to the bitmap data.
- */
-static XImage *DIB_DIBmpToImage( BITMAPINFOHEADER * bmp, void * bmpData )
-{
-    extern void _XInitImageFuncPtrs( XImage* );
-    XImage * image;
-
-    image = XCreateImage(display, DefaultVisualOfScreen( screen ),
-                         bmp->biBitCount, ZPixmap, 0, bmpData,
-                         bmp->biWidth, bmp->biHeight, 32,
-                         DIB_GetImageWidthBytes(bmp->biWidth,bmp->biBitCount));
-    if (!image) return 0;
-    image->byte_order = MSBFirst;
-    image->bitmap_bit_order = MSBFirst;
-    image->bitmap_unit = 16;
-    _XInitImageFuncPtrs(image);
-    return image;
-}
-
-
-/***********************************************************************
  *           DIB_GetBitmapInfo
  *
  * Get the info from a bitmap header.
@@ -809,30 +789,95 @@
 	else ((WORD *)info->bmiColors)[i] = (WORD)i;
     }
     
-      /* Transfer the pixels (very slow...) */
-
     if (bits)
     {	
+	BYTE*	bbits = bits;
+	int	pad, yend, xend = bmp->bitmap.bmWidth;
+
+        dprintf_bitmap(stddeb, "GetDIBits: %u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
+			    lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
+			    (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight, startscan );
+
+	/* adjust number of scanlines to copy */
+
+	if( lines > info->bmiHeader.biHeight ) lines = info->bmiHeader.biHeight;
+	yend = startscan + lines;
+	if( startscan >= bmp->bitmap.bmHeight ) 
+	    return FALSE;
+	if( yend > bmp->bitmap.bmHeight ) yend = bmp->bitmap.bmHeight;
+
+	/* adjust scanline width */
+
+	pad = info->bmiHeader.biWidth - bmp->bitmap.bmWidth;
+	if( pad < 0 ) 
+	{
+	    /* bitmap is wider than DIB, copy only a part */
+
+	    pad = 0; xend = info->bmiHeader.biWidth;
+	}
+
 	bmpImage = (XImage *)CallTo32_LargeStack( (int (*)())XGetImage, 8, 
 		               display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth,
 		               bmp->bitmap.bmHeight, AllPlanes, ZPixmap );
-	dibImage = DIB_DIBmpToImage( &info->bmiHeader, bits );
 
-	for (y = 0; y < lines; y++)
+	switch( info->bmiHeader.biBitCount )
 	{
-	    for (x = 0; x < info->bmiHeader.biWidth; x++)
-	    {
-		XPutPixel( dibImage, x, y,
-		  XGetPixel(bmpImage, x, bmp->bitmap.bmHeight-startscan-y-1) );
-		
-	    }
+	   case 8:
+
+		pad += (4 - (info->bmiHeader.biWidth & 3)) & 3;
+		for( y = yend - 1; (int)y >= (int)startscan; y-- )
+		{
+		   for( x = 0; x < xend; x++ )
+			*bbits++ = XGetPixel( bmpImage, x, y );
+		   bbits += pad;
+		}
+		break;
+
+/* add more bpp-specific shortcuts here */
+
+	   default:
+
+		dibImage = XCreateImage(display, DefaultVisualOfScreen( screen ),
+			   info->bmiHeader.biBitCount, ZPixmap, 0, bits,
+			   info->bmiHeader.biWidth, info->bmiHeader.biHeight,
+			   32, DIB_GetImageWidthBytes( info->bmiHeader.biWidth,
+                                                info->bmiHeader.biBitCount ) );
+		if( dibImage )
+		{
+		    extern void _XInitImageFuncPtrs( XImage* );
+
+		    dibImage->byte_order = MSBFirst;
+		    dibImage->bitmap_bit_order = MSBFirst;
+		    dibImage->bitmap_unit = 16;
+		    _XInitImageFuncPtrs( dibImage );
+
+		    for (y = yend - 1; (int)y >= (int)startscan; y--)
+		        for (x = 0; x < xend; x++)
+			    XPutPixel( dibImage, x, yend - y + 1, 
+				       XGetPixel( bmpImage, x, y ));
+		    dibImage->data = NULL;
+		    XDestroyImage( dibImage );
+		}
 	}
-	
-	dibImage->data = NULL;
-	XDestroyImage( dibImage );
+
 	XDestroyImage( bmpImage );
+
+	info->bmiHeader.biCompression = 0;
     }
-    info->bmiHeader.biCompression = 0;
+    else if( info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) ) 
+    {
+	/* fill in struct members */
+	
+	info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
+	info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
+	info->bmiHeader.biPlanes = 1;
+	info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
+	info->bmiHeader.biSizeImage = bmp->bitmap.bmHeight *
+                             DIB_GetImageWidthBytes( bmp->bitmap.bmWidth,
+                                                     bmp->bitmap.bmBitsPixel );
+	info->bmiHeader.biCompression = 0;
+    }
+
     return lines;
 }
 
diff --git a/objects/font.c b/objects/font.c
index 7912362..3ac17db 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -868,31 +868,23 @@
 BOOL16 GetCharWidth16( HDC16 hdc, UINT16 firstChar, UINT16 lastChar,
                        LPINT16 buffer )
 {
-    int i, width;
-    XFontStruct *xfont;
-    XCharStruct *cs, *def;
-
-    DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
-    if (!dc) return FALSE;
-    xfont = dc->u.x.font.fstruct;
-    
-    /* fixed font? */
-    if (xfont->per_char == NULL)
+    LPINT32	 buf32 = (LPINT32)xmalloc(sizeof(INT32)*(1 + (lastChar-firstChar)));
+    LPINT32	 obuf32;
+    BOOL32	 retVal;
+    int		 i;
+    if (!buf32)
+      return FALSE;
+    obuf32 = buf32;
+    retVal = GetCharWidth32A(hdc, firstChar, lastChar, buf32);
+    if (retVal)
     {
 	for (i = firstChar; i <= lastChar; i++)
-	    *buffer++ = xfont->max_bounds.width;
-	return TRUE;
+	{
+	    *buffer++ = *buf32++;
+	}
     }
-
-    CI_GET_DEFAULT_INFO(xfont, def);
-	
-    for (i = firstChar; i <= lastChar; i++)
-    {
-	CI_GET_CHAR_INFO( xfont, i, def, cs );
-        width = cs ? cs->width : xfont->max_bounds.width;
-        *buffer++ = MAX( width, 0 );
-    }
-    return TRUE;
+    free (obuf32);
+    return retVal;
 }
 
 
@@ -902,30 +894,17 @@
 BOOL32 GetCharWidth32A( HDC32 hdc, UINT32 firstChar, UINT32 lastChar,
                         LPINT32 buffer )
 {
-    int i, width;
-    XFontStruct *xfont;
-    XCharStruct *cs, *def;
-
-    DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
-    if (!dc) return FALSE;
-    xfont = dc->u.x.font.fstruct;
-    
-    /* fixed font? */
-    if (xfont->per_char == NULL)
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc)
     {
-	for (i = firstChar; i <= lastChar; i++)
-	    *buffer++ = xfont->max_bounds.width;
-	return TRUE;
+	if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
+            return FALSE;
     }
 
-    CI_GET_DEFAULT_INFO(xfont, def);
-	
-    for (i = firstChar; i <= lastChar; i++)
-    {
-	CI_GET_CHAR_INFO( xfont, i, def, cs );
-        width = cs ? cs->width : xfont->max_bounds.width;
-        *buffer++ = MAX( width, 0 );
-    }
+    if (!dc->funcs->pGetCharWidth ||
+        !dc->funcs->pGetCharWidth( dc, firstChar, lastChar, buffer))
+        return FALSE;
+
     return TRUE;
 }
 
diff --git a/objects/metafile.c b/objects/metafile.c
index 64701e9..928411c 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -750,6 +750,17 @@
 }
 
 /******************************************************************
+ *         SetMetaFileBitsBetter   (GDI.196)
+ */
+HMETAFILE16 SetMetaFileBitsBetter( HMETAFILE16 hMeta )
+{
+   if( IsValidMetaFile( hMeta ) )
+       return (HMETAFILE16)GlobalReAlloc16( hMeta, 0, 
+			   GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
+   return (HMETAFILE16)0;
+}
+
+/******************************************************************
  *         MF_WriteRecord
  *
  * Warning: this function can change the metafile handle.
diff --git a/resources/Makefile.in b/resources/Makefile.in
index 09d0d85..1d3755c 100644
--- a/resources/Makefile.in
+++ b/resources/Makefile.in
@@ -19,7 +19,8 @@
 	sysres_It.c \
 	sysres_Ko.c \
 	sysres_No.c \
-	sysres_Pl.c
+	sysres_Pl.c \
+	sysres_Po.c
 
 C_SRCS = sysres.c
 GEN_C_SRCS = $(SYSRES_SRCS)
diff --git a/resources/sysres.c b/resources/sysres.c
index 03b41e3..36a0ad8 100644
--- a/resources/sysres.c
+++ b/resources/sysres.c
@@ -22,6 +22,7 @@
 #include "sysres_Ko.h"
 #include "sysres_Hu.h"
 #include "sysres_Pl.h"
+#include "sysres_Po.h"
 
 static const struct resource * const * SYSRES_Resources[] =
 {
@@ -37,7 +38,8 @@
     sysres_It_Table,  /* LANG_It */
     sysres_Ko_Table,  /* LANG_Ko */
     sysres_Hu_Table,  /* LANG_Hu */
-    sysres_Pl_Table   /* LANG_Pl */
+    sysres_Pl_Table,  /* LANG_Pl */
+    sysres_Po_Table   /* LANG_Po */
 };
 
 
diff --git a/resources/sysres_Pl.rc b/resources/sysres_Pl.rc
index 1af3dff..1e821f8 100644
--- a/resources/sysres_Pl.rc
+++ b/resources/sysres_Pl.rc
@@ -51,7 +51,7 @@
 	CONTROL "Text", 100, "STATIC", SS_NOPREFIX | WS_GROUP, 11, 40, 200, 200
 	ICON "", 1088, 195, 10, 18, 20
 }
-//LTEXT "Wyswietl pliki &typu:", 1089, 6, 104, 90, 9
+/* LTEXT "Wyswietl pliki &typu:", 1089, 6, 104, 90, 9 */
 OPEN_FILE DIALOG 36, 24, 279, 134
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Otwórz"
@@ -72,7 +72,7 @@
 	CONTROL "&Pomoc", 1038, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 212, 46, 56, 14
 	CONTROL "Tylko do odczytu", 1040, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 208, 68, 69, 12
 END
-//PRINT DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 264, 134
+/* PRINT DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 264, 134 */
 SAVE_FILE DIALOG 36, 24, 278, 134
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Zapisz jako"
@@ -93,7 +93,7 @@
 	CONTROL "&Pomoc", 1038, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 213, 45, 56, 14
 	CONTROL "&Tylko do odczytu", 1040, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 208, 68, 68, 12
 END
-// DEFPUSHBUTTON "Ok", 1, 206, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
+/* DEFPUSHBUTTON "Ok", 1, 206, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP */
 PRINT DIALOG 36, 24, 264, 134
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Drukuj"
@@ -115,7 +115,7 @@
 	CONTROL "Drukuj do Pli&ku", 1040, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 14, 115, 95, 12
 	CONTROL "Sortuj kopie", 1041, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 182, 102, 59, 12
 END
-//    PUSHBUTTON      "Anuluj",IDCANCEL,218,23,40,14,WS_GROUP
+/*    PUSHBUTTON      "Anuluj",IDCANCEL,218,23,40,14,WS_GROUP */
 PRINT_SETUP DIALOG 36, 24, 264, 134
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Print Setup"
@@ -140,7 +140,7 @@
 	CONTROL "", 1137, "COMBOBOX", CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP, 155, 95, 92, 68
 	CONTROL "", 1138, "COMBOBOX", CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP, 155, 110, 92, 68
 END
-// CONTROL "" ,710,"STATIC",WS_BORDER|SS_SIMPLE|WS_TABSTOP|WS_GROUP, 152,4,118,116
+/* CONTROL "" ,710,"STATIC",WS_BORDER|SS_SIMPLE|WS_TABSTOP|WS_GROUP, 152,4,118,116 */
 CHOOSE_FONT DIALOG 13, 54, 264, 147
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Font"
@@ -168,11 +168,12 @@
 	CONTROL "Przyk³ad", 1073, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 98,72,160,49
 	CONTROL "AaBbYyZz\xB3", 1093, "STATIC", SS_NOPREFIX | WS_VISIBLE, 104,81,149,37
 END
-// PUSHBUTTON "&Replace", 1024, 174, 21, 50, 14, WS_GROUP | WS_TABSTOP
-// PUSHBUTTON "Replace &All", 1025, 174, 38, 50, 14, WS_GROUP | WS_TABSTOP
-// PUSHBUTTON "Cancel", 2, 174, 55, 50, 14, WS_GROUP | WS_TABSTOP
-// PUSHBUTTON "&Help", 1038, 174, 75, 50, 14, WS_GROUP | WS_TABSTOP
-//}
+/* PUSHBUTTON "&Replace", 1024, 174, 21, 50, 14, WS_GROUP | WS_TABSTOP
+ * PUSHBUTTON "Replace &All", 1025, 174, 38, 50, 14, WS_GROUP | WS_TABSTOP
+ * PUSHBUTTON "Cancel", 2, 174, 55, 50, 14, WS_GROUP | WS_TABSTOP
+ * PUSHBUTTON "&Help", 1038, 174, 75, 50, 14, WS_GROUP | WS_TABSTOP
+ *}
+ */
 FIND_TEXT DIALOG 34, 24, 251, 62
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "ZnajdŸ"
diff --git a/resources/sysres_Po.rc b/resources/sysres_Po.rc
new file mode 100644
index 0000000..0fca251
--- /dev/null
+++ b/resources/sysres_Po.rc
@@ -0,0 +1,247 @@
+SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE
+{
+ MENUITEM "&Restaurar", 61728
+ MENUITEM "&Mover", 61456
+ MENUITEM "&Tamanho", 61440
+ MENUITEM "Mi&nimizar", 61472
+ MENUITEM "Ma&ximizar", 61488
+ MENUITEM SEPARATOR
+ MENUITEM "&Fechar\tAlt-F4", 61536
+ MENUITEM SEPARATOR
+ MENUITEM "&Alternar Para ...\tCtrl-Esc", 61744
+ MENUITEM SEPARATOR
+ MENUITEM "&Sobre o WINE ...", 61761
+}
+
+EDITMENU MENU LOADONCALL MOVEABLE DISCARDABLE
+{
+	POPUP ""
+	BEGIN
+		MENUITEM "&Voltar", EM_UNDO32
+		MENUITEM SEPARATOR
+		MENUITEM "&Recortar", WM_CUT
+		MENUITEM "&Copiar", WM_COPY
+		MENUITEM "Co&lar", WM_PASTE
+		MENUITEM "&Apagar", WM_CLEAR
+		MENUITEM SEPARATOR
+		MENUITEM "Selecionar &Tudo", EM_SETSEL32
+	END
+}
+
+MSGBOX DIALOG 100, 80, 216, 168
+STYLE DS_SYSMODAL | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+BEGIN
+        ICON "", 1088, 8, 20, 16, 16, WS_CHILD | WS_VISIBLE
+        LTEXT "", 100, 32, 4, 176, 48, WS_CHILD | WS_VISIBLE | WS_GROUP
+        PUSHBUTTON "&Ok", 1, 16, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+        PUSHBUTTON "&Cancelar", 2, 64, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+        PUSHBUTTON "&Abortar", 3, 112, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+        PUSHBUTTON "&Repetir", 4, 160, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+        PUSHBUTTON "&Ignorar", 5, 208, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+        PUSHBUTTON "&Sim", 6, 256, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+        PUSHBUTTON "&Não", 7, 304, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+END
+
+SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 50, 44, 223, 270
+STYLE DS_LOCALEDIT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Sobre %s"
+FONT 10, "Sistema"
+{
+ DEFPUSHBUTTON "OK", 1, 91, 250, 40, 14
+ CONTROL "", -1, "STATIC", SS_BLACKFRAME | WS_CHILD | WS_VISIBLE | WS_DISABLED, 4, 35, 215, 210
+ LTEXT "Text", 100, 11, 40, 200, 200, SS_NOPREFIX | WS_GROUP
+ ICON "", 1088, 195, 10, 18, 20
+}
+
+
+OPEN_FILE DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 275, 134
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Abrir"
+FONT 8, "Helv"
+{
+ LTEXT "Nome do &Arquivo:", 1090, 6, 6, 76, 9
+ EDITTEXT 1152, 6, 16, 90, 12, ES_AUTOHSCROLL | ES_OEMCONVERT | WS_BORDER | WS_TABSTOP
+ LISTBOX 1120, 6, 32, 90, 68, LBS_STANDARD | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_TABSTOP
+ LTEXT "&Diretórios:", -1, 110, 6, 92, 9
+ LTEXT "", 1088, 110, 18, 92, 9, SS_NOPREFIX | WS_GROUP
+ LISTBOX 1121, 110, 32, 92, 68, LBS_STANDARD | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_TABSTOP
+ LTEXT "Listar Arquivos do &Tipo:", 1089, 6, 104, 90, 9
+ COMBOBOX 1136, 6, 114, 90, 36, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Dri&ves:", 1091, 110, 104, 92, 9
+ COMBOBOX 1137, 110, 114, 92, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "Abrir", 1, 208, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Cancelar", 2, 208, 24, 56, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "A&juda", 1038, 208, 46, 56, 14, WS_GROUP | WS_TABSTOP
+ CHECKBOX "&Somente Leitura", 1040, 208, 68, 50, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
+}
+
+
+SAVE_FILE DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 275, 134
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Salvar Como ..."
+FONT 8, "Helv"
+{
+ LTEXT "Nome do &Arquivo:", 1090, 6, 6, 76, 9
+ EDITTEXT 1152, 6, 16, 90, 12, ES_AUTOHSCROLL | ES_OEMCONVERT | WS_BORDER | WS_TABSTOP
+ LISTBOX 1120, 6, 32, 90, 68, LBS_STANDARD | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_TABSTOP
+ LTEXT "&Diretórios:", -1, 110, 6, 92, 9
+ LTEXT "", 1088, 110, 18, 92, 9, SS_NOPREFIX | WS_GROUP
+ LISTBOX 1121, 110, 32, 92, 68, LBS_STANDARD | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_TABSTOP
+ LTEXT "Listar Arquivos do &Tipo:", 1089, 6, 104, 90, 9
+ COMBOBOX 1136, 6, 114, 90, 36, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Dri&ves:", 1091, 110, 104, 92, 9
+ COMBOBOX 1137, 110, 114, 92, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "Salvar &Como", 1, 208, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Cancelar", 2, 208, 24, 56, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "&Ajuda", 1038, 208, 46, 56, 14, WS_GROUP | WS_TABSTOP
+ CHECKBOX "&Somente Leitura", 1040, 208, 68, 50, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
+}
+
+
+PRINT DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 264, 134
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Imprimir"
+FONT 8, "Helv"
+{
+ LTEXT "Impressora:", 1088, 6, 6, 40, 9
+ LTEXT "", 1089, 60, 6, 150, 9
+ GROUPBOX "Faixa de Impressão", 1072, 6, 30, 160, 65, BS_GROUPBOX
+ RADIOBUTTON "&Tudo", 1056, 16, 45, 60, 12
+ RADIOBUTTON "S&eleção", 1057, 16, 60, 60, 12
+ RADIOBUTTON "&Páginas", 1058, 16, 75, 60, 12
+ DEFPUSHBUTTON "Imprimir", 1, 206, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Cancelar", 2, 206, 24, 56, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "&Configurar", 1024, 206, 46, 56, 14, WS_GROUP | WS_TABSTOP
+ LTEXT "&De:", 1090, 60, 80, 30, 9
+ LTEXT "&Ate:", 1091, 120, 80, 30, 9
+ LTEXT "&Qualidade de Impressão:", 1092, 6, 100, 76, 9
+ COMBOBOX 1136, 80, 100, 92, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ CHECKBOX "Imprimir para Arquivo", 1040, 20, 100, 50, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
+ CHECKBOX "C&ondensado", 1041, 160, 100, 50, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
+}
+
+
+PRINT_SETUP DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 264, 134
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Configurações de Impressão"
+FONT 8, "Helv"
+{
+ GROUPBOX "Impressora", 1072, 6, 10, 180, 65, BS_GROUPBOX
+ RADIOBUTTON "&Impressora Padrão", 1056, 16, 20, 80, 12
+ LTEXT "[none]", 1088, 35, 35, 120, 9
+ RADIOBUTTON "Impressora &Específica", 1057, 16, 50, 80, 12
+ COMBOBOX 1136, 35, 65, 149, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "Ok", 1, 206, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Cancelar", 2, 206, 24, 56, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "&Configurar", 1024, 206, 46, 56, 14, WS_GROUP | WS_TABSTOP
+ GROUPBOX "Orientação", 1073, 6, 85, 100, 50, BS_GROUPBOX
+ RADIOBUTTON "&Retrato", 1058, 50, 100, 40, 12
+ RADIOBUTTON "&Paisagem", 1059, 50, 115, 40, 12
+ ICON "LANDSCAP", 1097, 10, 95, 32, 32
+ ICON "PORTRAIT", 1098, 10, 95, 32, 32
+ GROUPBOX "Papel", 1074, 120, 85, 180, 50, BS_GROUPBOX
+ LTEXT "&Tamanho", 1089, 130, 95, 30, 9
+ LTEXT "&Fonte de Alimentação", 1090, 130, 110, 30, 9
+ COMBOBOX 1137, 155, 95, 92, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX 1138, 155, 110, 92, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP
+}
+
+
+CHOOSE_FONT DIALOG DISCARDABLE  13, 54, 264, 147
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Fonte"
+FONT 8, "Helv"
+{
+    LTEXT           "&Fonte:",1088 ,6,3,40,9
+    COMBOBOX        1136 ,6,13,94,54,  CBS_OWNERDRAWFIXED | CBS_HASSTRINGS | CBS_DISABLENOSCROLL |
+                    CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP | CBS_SIMPLE
+    LTEXT           "&Estilo da Fonte:",1089 ,108,3,44,9
+    COMBOBOX        1137,108,13,64,54, CBS_OWNERDRAWFIXED | CBS_HASSTRINGS | CBS_DISABLENOSCROLL |
+                    WS_VSCROLL | WS_TABSTOP | CBS_SIMPLE
+    LTEXT           "&Tamanho:",1090,179,3,30,9
+    COMBOBOX        1138,179,13,32,54, CBS_OWNERDRAWFIXED | CBS_HASSTRINGS | CBS_DISABLENOSCROLL |
+                    WS_VSCROLL | WS_TABSTOP | CBS_SIMPLE | CBS_SORT
+    DEFPUSHBUTTON   "OK",IDOK,218,6,40,14,WS_GROUP
+    PUSHBUTTON      "Cancelar",IDCANCEL,218,23,40,14,WS_GROUP
+    PUSHBUTTON      "&Aplicar", 1026,218,40,40,14,WS_GROUP
+    PUSHBUTTON      "A&juda" , 1038,218,57,40,14,WS_GROUP
+    GROUPBOX        "Efeitos",1072,6,72,84,34,WS_GROUP
+    CHECKBOX	    "&Riscado", 1040, 10,82,50,10, BS_AUTOCHECKBOX | WS_TABSTOP
+    CHECKBOX 	    "&Sublinhado", 1041, 10,94,50,10, BS_AUTOCHECKBOX 
+    LTEXT           "&Cor:", 1091 ,6,110,30,9
+    COMBOBOX        1139,6,120,84,100,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS |
+		    CBS_AUTOHSCROLL |  WS_BORDER | WS_VSCROLL | WS_TABSTOP
+    GROUPBOX        "Amostra",1073,98,72,160,49,WS_GROUP
+    CTEXT           "AaBbYyZz",1093,104,81,149,37,SS_NOPREFIX | WS_VISIBLE
+}
+
+
+CHOOSE_COLOR DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 300, 200
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Cor"
+FONT 8, "Helv"
+{
+ LTEXT "Cores &Básicas:",   1088, 4,    4,  140, 10
+ LTEXT "&Cores do Usuário:",  1089, 4,   106, 140, 10
+ LTEXT "Colorido|Sólid&o",  1090, 150, 151,  48, 10
+ LTEXT   "Ver&melho:", 726 /*1094*/,249,126,24,10
+ EDITTEXT 706, 275,124,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT   "&Verde:",727/*1095*/,249,140,24,10
+ EDITTEXT 707, 275,138,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT   "A&zul:",728 /*1096*/,249,154,24,10
+ EDITTEXT 708, 275,152,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT  "Mat&iz:" ,723 /*1091*/,202,126,22,10
+ EDITTEXT 703, 226,124,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT  "Sa&t:" ,724 /*1092*/,202,140,22,10
+ EDITTEXT 704, 226,138,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT  "&Lum:" ,725 /*1093*/,202,154,22,10
+ EDITTEXT 705, 226,152,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ CONTROL "" ,720,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP,4,14,140,86
+ CONTROL "" ,721,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP,4,116,140,28
+ CONTROL "" ,710,"STATIC",WS_BORDER|SS_SIMPLE|WS_TABSTOP|WS_GROUP, 152,4,118,116
+ CONTROL "" ,702,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP, 278,4,8,116
+ CONTROL "" ,709,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP, 152,124,40,26
+ DEFPUSHBUTTON "Ok",  1,  4, 166, 44, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Cancelar", 2, 52, 166, 44, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Aj&uda", 1038,100,166, 44, 14
+ PUSHBUTTON "&Adicionar Cor",    712/*1024*/, 152, 166, 142, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "&Definir Cores Personalizadas >>", 719/*1025*/,   4, 150, 142, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON  "&o",713,300,200,4,14   /* just a dummy:  'o' is  like  &o  in "solid&o"  */
+}
+
+
+FIND_TEXT DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 236, 62
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Procurar"
+FONT 8, "Helv"
+{
+ LTEXT "&Procurar:", -1, 4, 8, 42, 8
+ EDITTEXT 1152, 47, 7, 128, 12, ES_AUTOHSCROLL | WS_BORDER | WS_GROUP | WS_TABSTOP
+ CHECKBOX "Palavra &Inteira", 1040, 4, 26, 100, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
+ CHECKBOX "&Maiúsculas/minusculas", 1041, 4, 42, 64, 12, BS_AUTOCHECKBOX | WS_TABSTOP
+ GROUPBOX "Direção", 1072, 107, 26, 68, 28
+ CONTROL "A&cima", 1056, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 111, 38, 20, 12
+ CONTROL "A&baixo", 1057, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 138, 38, 30, 12
+ DEFPUSHBUTTON "Procurar a Pró&xima", 1, 182, 5, 50, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Cancelar", 2, 182, 23, 50, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "A&juda", 1038, 182, 45, 50, 14, WS_GROUP | WS_TABSTOP
+}
+
+
+REPLACE_TEXT DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 230, 94
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Alterar"
+FONT 8, "Helv"
+{
+ LTEXT "&Procurar:", -1, 4, 9, 48, 8
+ EDITTEXT 1152, 54, 7, 114, 12, ES_AUTOHSCROLL | WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT "Alterar Pa&ra:", -1, 4, 26, 48, 8
+ EDITTEXT 1153, 54, 24, 114, 12, ES_AUTOHSCROLL | WS_BORDER | WS_GROUP | WS_TABSTOP
+ CHECKBOX "Palavra &inteira", 1040, 5, 46, 104, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
+ CHECKBOX "&Maiúsculas/minúsculas", 1041, 5, 62, 59, 12, BS_AUTOCHECKBOX | WS_TABSTOP
+ DEFPUSHBUTTON "Procurar a Pró&xima", 1, 174, 4, 50, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "&Alterar", 1024, 174, 21, 50, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Alterar &Todas", 1025, 174, 38, 50, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Cancelar", 2, 174, 55, 50, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "A&juda", 1038, 174, 75, 50, 14, WS_GROUP | WS_TABSTOP
+}
diff --git a/win32/code_page.c b/win32/code_page.c
index 951874c..c9b0f9f 100644
--- a/win32/code_page.c
+++ b/win32/code_page.c
@@ -67,6 +67,22 @@
 }
 
 /***********************************************************************
+ *           IsValidCodePage   (KERNEL32.360)
+ */
+BOOL32 IsValidCodePage(UINT32 CodePage)
+{
+    switch ( CodePage )
+    {
+    case 1252 :
+    case 437 :
+        return TRUE;
+    default :
+        return FALSE;
+    }
+}
+
+
+/***********************************************************************
  *              MultiByteToWideChar                (KERNEL32.392)
  */
 int MultiByteToWideChar(UINT32 page, DWORD flags, char *src, int srclen,
diff --git a/win32/console.c b/win32/console.c
index 63e5fa4..6889b5f 100644
--- a/win32/console.c
+++ b/win32/console.c
@@ -207,3 +207,11 @@
     HeapFree( GetProcessHeap(), 0, titleA );
     return TRUE;
 }
+
+/***********************************************************************
+ *            FlushConsoleInputBuffer   (KERNEL32.132)
+ */
+BOOL32 FlushConsoleInputBuffer(HANDLE32 hConsoleInput){
+    fprintf(stderr,"FlushConsoleInputBuffer(%d)\n",hConsoleInput);
+    return TRUE;
+}
diff --git a/win32/k32obj.c b/win32/k32obj.c
index bcb0565..944ecd7 100644
--- a/win32/k32obj.c
+++ b/win32/k32obj.c
@@ -97,10 +97,10 @@
  */
 BOOL32 K32OBJ_AddName( K32OBJ *obj, LPCSTR name )
 {
-    NAME_ENTRY *entry = K32OBJ_FirstEntry;
+    NAME_ENTRY *entry;
     UINT32 len = strlen( name );
 
-    if (!(entry = HeapAlloc( SystemHeap, 0, sizeof(entry) + len )))
+    if (!(entry = HeapAlloc( SystemHeap, 0, sizeof(NAME_ENTRY) + len )))
     {
         SetLastError( ERROR_OUTOFMEMORY );
         return FALSE;
diff --git a/win32/process.c b/win32/process.c
index 58f8dc3..7178bf7 100644
--- a/win32/process.c
+++ b/win32/process.c
@@ -10,40 +10,298 @@
 #include "windows.h"
 #include "winerror.h"
 #include "heap.h"
+#include "thread.h"
 #include "handle32.h"
 #include "pe_image.h"
 #include "stddebug.h"
 #include "debug.h"
 
+typedef struct {
+	K32OBJ	header;
+	DWORD	maxcount;
+	DWORD	count;
+	DWORD	initial;
+} K32SEMAPHORE;
+
+typedef struct {
+	K32OBJ	header;
+	THDB	*owning_thread; /* we are locked by this thread */
+} K32MUTEX;
+
+typedef struct {
+	K32OBJ	header;
+} K32EVENT;
+
 /***********************************************************************
  *           CreateMutexA    (KERNEL32.52)
  */
-HANDLE32 CreateMutexA (SECURITY_ATTRIBUTES *sa, BOOL32 on, const char *a)
+HANDLE32 CreateMutex32A(SECURITY_ATTRIBUTES *sa,BOOL32 on,LPCSTR name)
 {
+	K32MUTEX	*mut;
+	HANDLE32	handle;
+	K32OBJ 		*obj = K32OBJ_FindName( name );
+
+	if (obj) {
+		if (obj->type == K32OBJ_MUTEX) {
+			SetLastError( ERROR_ALREADY_EXISTS );
+			return PROCESS_AllocHandle( obj,0 );
+		}
+		SetLastError( ERROR_DUP_NAME );
+		return 0;
+	}
+	mut = (K32MUTEX*)HeapAlloc(GetProcessHeap(),0,sizeof(K32MUTEX));
+	mut->header.type = K32OBJ_MUTEX;
+	mut->header.refcount  = 1;
+	mut->owning_thread = NULL;
+	if (name)
+		K32OBJ_AddName(&(mut->header),name);
+	handle = PROCESS_AllocHandle(&(mut->header),0);
+	if (handle != INVALID_HANDLE_VALUE32) {
+		if (on)
+			mut->owning_thread = (THDB *)GetCurrentThreadId();
+		return handle;
+	}
+	K32OBJ_DecCount(&(mut->header)); /* also frees name */
+	HeapFree(GetProcessHeap(),0,mut);
 	return 0;
 }
 
 /***********************************************************************
+ *           CreateMutexW    (KERNEL32.53)
+ */
+HANDLE32 CreateMutex32W(SECURITY_ATTRIBUTES *sa, BOOL32 on, LPCWSTR a)
+{
+	LPSTR		name = a?HEAP_strdupWtoA(GetProcessHeap(),0,a):NULL;
+	HANDLE32	ret;
+
+	ret = CreateMutex32A(sa,on,name);
+	if (name) HeapFree(GetProcessHeap(),0,name);
+	return ret;
+}
+
+/***********************************************************************
+ *           CreateSemaphoreA    (KERNEL32.60)
+ */
+HANDLE32 CreateSemaphore32A(
+	LPSECURITY_ATTRIBUTES sa,LONG initial,LONG max,LPCSTR name
+) {
+	K32SEMAPHORE	*sem;
+	HANDLE32	handle;
+	K32OBJ 		*obj = K32OBJ_FindName( name );
+
+	if (obj) {
+		if (obj->type == K32OBJ_SEMAPHORE) {
+			SetLastError( ERROR_ALREADY_EXISTS );
+			return PROCESS_AllocHandle( obj,0 );
+		}
+		SetLastError( ERROR_DUP_NAME );
+		return 0;
+	}
+	sem = (K32SEMAPHORE*)HeapAlloc(GetProcessHeap(),0,sizeof(K32SEMAPHORE));
+	sem->header.type = K32OBJ_SEMAPHORE;
+	sem->header.refcount  = 1;
+
+	sem->maxcount 	= max;
+	sem->count	= initial;
+	sem->initial	= initial;
+	if (name)
+		K32OBJ_AddName(&(sem->header),name);
+	handle = PROCESS_AllocHandle(&(sem->header),0);
+	if (handle != INVALID_HANDLE_VALUE32)
+		return handle;
+	K32OBJ_DecCount(&(sem->header)); /* also frees name */
+	HeapFree(GetProcessHeap(),0,sem);
+	return 0;
+}
+
+/***********************************************************************
+ *           CreateSemaphoreW    (KERNEL32.61)
+ */
+HANDLE32 CreateSemaphore32W(SECURITY_ATTRIBUTES *sa,LONG initial,LONG max,LPCWSTR a)
+{
+	LPSTR		name =a?HEAP_strdupWtoA(GetProcessHeap(),0,a):NULL;
+	HANDLE32	ret;
+
+	ret = CreateSemaphore32A(sa,initial,max,name);
+	if (a) HeapFree(GetProcessHeap(),0,name);
+	return ret;
+}
+
+
+/***********************************************************************
+ *           OpenSemaphoreA    (KERNEL32.403)
+ */
+HANDLE32 OpenSemaphore32A(DWORD desired,BOOL32 inherit,LPCSTR name)
+{
+	K32OBJ 		*obj = K32OBJ_FindName( name );
+
+	if (obj) {
+		if (obj->type == K32OBJ_SEMAPHORE)
+			return PROCESS_AllocHandle( obj,0 );
+		SetLastError( ERROR_DUP_NAME );
+		return 0;
+	}
+	return 0;
+}
+
+/***********************************************************************
+ *           OpenSemaphoreA    (KERNEL32.404)
+ */
+HANDLE32 OpenSemaphore32W(DWORD desired,BOOL32 inherit,LPCWSTR name)
+{
+	LPSTR	nameA = name?HEAP_strdupWtoA(GetProcessHeap(),0,name):NULL;
+	HANDLE32	ret = OpenSemaphore32A(desired,inherit,nameA);
+
+	if (name) HeapFree(GetProcessHeap(),0,nameA);
+	return ret;
+}
+
+/***********************************************************************
+ *           ReleaseSemaphore    (KERNEL32.403)
+ */
+BOOL32 ReleaseSemaphore(HANDLE32 hSemaphore,LONG lReleaseCount,LPLONG lpPreviousCount) {
+	K32SEMAPHORE	*sem;
+
+	sem = (K32SEMAPHORE*)PROCESS_GetObjPtr(hSemaphore,K32OBJ_SEMAPHORE);
+	if (!sem)
+		return FALSE;
+	if (lpPreviousCount) *lpPreviousCount = sem->count;
+	sem->count += lReleaseCount;
+	if (sem->count>sem->maxcount) {
+		fprintf(stderr,"ReleaseSemaphore(%d,%ld,.), released more then possible??\n",hSemaphore,lReleaseCount);
+		sem->count = sem->maxcount;
+	}
+
+	/* FIXME: wake up all threads blocked on that semaphore */
+
+	K32OBJ_DecCount(&(sem->header));
+	return TRUE;
+}
+
+/***********************************************************************
+ *           OpenMutexA    (KERNEL32.399)
+ */
+HANDLE32 OpenMutex32A(DWORD desiredaccess, BOOL32 inherithandle, LPCSTR name)
+{
+	K32OBJ 		*obj = K32OBJ_FindName( name );
+
+	if (obj) {
+		if (obj->type == K32OBJ_MUTEX)
+			return PROCESS_AllocHandle( obj,0 );
+		SetLastError( ERROR_DUP_NAME );
+		return 0;
+	}
+	return 0;
+}
+
+/***********************************************************************
+ *           OpenMutexW    (KERNEL32.400)
+ */
+HANDLE32 OpenMutex32W(DWORD desiredaccess, BOOL32 inherithandle, LPCWSTR name)
+{
+	LPSTR		nameA=name?HEAP_strdupWtoA(GetProcessHeap(),0,name):NULL;
+	HANDLE32	ret = OpenMutex32A(desiredaccess,inherithandle,nameA);
+
+	if (name) HeapFree(GetProcessHeap(),0,nameA);
+	return ret;
+}
+
+/***********************************************************************
  *           ReleaseMutex    (KERNEL32.435)
  */
 BOOL32 ReleaseMutex (HANDLE32 h)
 {
-	return 0;
+	K32MUTEX	*mut = (K32MUTEX*)PROCESS_GetObjPtr(h,K32OBJ_MUTEX);
+
+	if (!mut)
+		return 0;
+	if (mut->owning_thread != (THDB *)GetCurrentThreadId()) {
+		/* set error ... */
+		K32OBJ_DecCount(&(mut->header));
+		return 0;
+	}
+	mut->owning_thread = NULL;
+
+	/* FIXME: wake up all threads blocked on this mutex */
+
+	K32OBJ_DecCount(&(mut->header));
+	return TRUE;
 }
 
 /***********************************************************************
  *           CreateEventA    (KERNEL32.43)
  */
-HANDLE32 CreateEventA (SECURITY_ATTRIBUTES *sa, BOOL32 au, BOOL32 on, const char
-*name)
+HANDLE32 CreateEvent32A(SECURITY_ATTRIBUTES *sa,BOOL32 au,BOOL32 on,LPCSTR name)
 {
+	K32EVENT	*evt;
+	HANDLE32	handle;
+	K32OBJ 		*obj = K32OBJ_FindName( name );
+
+	if (obj) {
+		if (obj->type == K32OBJ_EVENT) {
+			SetLastError( ERROR_ALREADY_EXISTS );
+			return PROCESS_AllocHandle( obj,0 );
+		}
+		SetLastError( ERROR_DUP_NAME );
+		return 0;
+	}
+	evt = (K32EVENT*)HeapAlloc(GetProcessHeap(),0,sizeof(K32EVENT));
+	evt->header.type = K32OBJ_EVENT;
+	evt->header.refcount  = 1;
+	if (name)
+		K32OBJ_AddName(&(evt->header),name);
+	handle = PROCESS_AllocHandle(&(evt->header),0);
+	if (handle != INVALID_HANDLE_VALUE32)
+		return handle;
+	K32OBJ_DecCount(&(evt->header)); /* also frees name */
+	HeapFree(GetProcessHeap(),0,evt);
 	return 0;
 }
+
+/***********************************************************************
+ *           CreateEventW    (KERNEL32.43)
+ */
+HANDLE32 CreateEvent32W(SECURITY_ATTRIBUTES *sa, BOOL32 au, BOOL32 on,LPCWSTR name)
+{
+	LPSTR nameA=name?HEAP_strdupWtoA(GetProcessHeap(),0,name):NULL;
+	HANDLE32 ret = CreateEvent32A(sa,au,on,nameA);
+
+	if (name) HeapFree(GetProcessHeap(),0,nameA);
+	return ret;
+}
+
+/***********************************************************************
+ *           OpenEventA    (KERNEL32.394)
+ */
+HANDLE32 OpenEvent32A(DWORD desiredaccess,BOOL32 inherithandle,LPCSTR name) {
+	K32OBJ 		*obj = K32OBJ_FindName( name );
+
+	if (obj) {
+		if (obj->type == K32OBJ_EVENT)
+			return PROCESS_AllocHandle( obj,0 );
+		SetLastError( ERROR_DUP_NAME );
+		return 0;
+	}
+	return 0;
+}
+
+/***********************************************************************
+ *           OpenEventW    (KERNEL32.395)
+ */
+HANDLE32 OpenEvent32W(DWORD desiredaccess,BOOL32 inherithandle,LPCWSTR name) {
+	LPSTR	nameA = name?HEAP_strdupWtoA(GetProcessHeap(),0,name):NULL;
+	HANDLE32	ret = OpenEvent32A(desiredaccess,inherithandle,nameA);
+
+	if (name) HeapFree(GetProcessHeap(),0,nameA);
+	return ret;
+}
+
 /***********************************************************************
  *           SetEvent    (KERNEL32.487)
  */
 BOOL32 SetEvent (HANDLE32 h)
 {
+	fprintf(stderr,"SetEvent(%d) stub\n",h);
 	return 0;
 }
 /***********************************************************************
@@ -51,13 +309,15 @@
  */
 BOOL32 ResetEvent (HANDLE32 h)
 {
+	fprintf(stderr,"ResetEvent(%d) stub\n",h);
 	return 0;
 }
 /***********************************************************************
  *           WaitForSingleObject    (KERNEL32.561)
  */
-DWORD WaitForSingleObject(HANDLE32 h, DWORD a)
+DWORD WaitForSingleObject(HANDLE32 h, DWORD timeout)
 {
+	fprintf(stderr,"WaitForSingleObject(%d,%ld) stub\n",h,timeout);
 	return 0;
 }
 /***********************************************************************
@@ -65,8 +325,9 @@
  */
 BOOL32 DuplicateHandle(HANDLE32 a, HANDLE32 b, HANDLE32 c, HANDLE32 * d, DWORD e, BOOL32 f, DWORD g)
 {
+	fprintf(stderr,"DuplicateHandle(%d,%d,%d,%p,%ld,%d,%ld) stub\n",a,b,c,d,e,f,g);
 	*d = b;
-	return 1;
+	return TRUE;
 }
 
 
@@ -89,7 +350,7 @@
 	}
 	/* Obtain module handle and call initialization function */
 #ifndef WINELIB
-	if (handle >= (HINSTANCE32)32) PE_InitializeDLLs( GetExePtr(handle));
+	if (handle >= (HINSTANCE32)32) PE_InitializeDLLs( GetExePtr(handle), DLL_PROCESS_ATTACH, NULL);
 #endif
 	return handle;
 }
@@ -134,11 +395,33 @@
 
 /**********************************************************************
  *           SetThreadAffinityMask
+ * Works now like the Windows95 (no MP support) version
  */
 BOOL32 SetThreadAffinityMask(HANDLE32 hThread, DWORD dwThreadAffinityMask)
 {
-	dprintf_task(stddeb,"SetThreadAffinityMask(%x,%lx)\n",hThread,
-		dwThreadAffinityMask);
-	/* FIXME: We let it fail */
-	return 1;
+	THDB	*thdb = (THDB*)PROCESS_GetObjPtr(hThread,K32OBJ_THREAD);
+
+	if (!thdb) 
+		return FALSE;
+	if (dwThreadAffinityMask!=1) {
+		fprintf(stderr,"SetThreadAffinityMask(%d,%ld), only 1 processor supported.\n",(int)hThread,dwThreadAffinityMask);
+		K32OBJ_DecCount((K32OBJ*)thdb);
+		return FALSE;
+	}
+	K32OBJ_DecCount((K32OBJ*)thdb);
+	return TRUE;
+}
+
+BOOL32
+CreateProcess32A(
+	LPCSTR appname,LPSTR cmdline,LPSECURITY_ATTRIBUTES processattributes,
+        LPSECURITY_ATTRIBUTES threadattributes,BOOL32 inherithandles,
+	DWORD creationflags,LPVOID env,LPCSTR curdir,
+	LPSTARTUPINFO32A startupinfo,LPPROCESS_INFORMATION processinfo
+) {
+	fprintf(stderr,"CreateProcess(%s,%s,%p,%p,%d,%08lx,%p,%s,%p,%p)\n",
+		appname,cmdline,processattributes,threadattributes,
+		inherithandles,creationflags,env,curdir,startupinfo,processinfo
+	);
+	return TRUE;
 }
diff --git a/win32/thread.c b/win32/thread.c
index 2acf856..93153a0 100644
--- a/win32/thread.c
+++ b/win32/thread.c
@@ -160,7 +160,7 @@
 
 void DeleteCriticalSection(CRITICAL_SECTION *pcritical)
 {
-   semctl((int) pcritical->LockSemaphore,0,IPC_RMID,NULL);
+   semctl((int) pcritical->LockSemaphore,0,IPC_RMID,(union semun)NULL);
    pcritical->Reserved=-1;
 }
 
diff --git a/win32/time.c b/win32/time.c
index 6b38eb8..4994190 100644
--- a/win32/time.c
+++ b/win32/time.c
@@ -123,10 +123,10 @@
     struct timezone tz;
 
     tz.tz_minuteswest = tzinfo->Bias;
-#ifdef __EMX__ /* FIXME */
-    tz.tz_dsttime = 0;
-#else
+#ifdef DST_NONE
     tz.tz_dsttime = DST_NONE;
+#else
+    tz.tz_dsttime = 0;
 #endif
     return !settimeofday(NULL, &tz);
 }
diff --git a/windows/class.c b/windows/class.c
index fa0d470..c6fa82e 100644
--- a/windows/class.c
+++ b/windows/class.c
@@ -185,7 +185,7 @@
     if (classPtr->hbrBackground) DeleteObject32( classPtr->hbrBackground );
     GlobalDeleteAtom( classPtr->atomName );
     CLASS_SetMenuNameA( classPtr, NULL );
-    WINPROC_FreeProc( classPtr->winproc );
+    WINPROC_FreeProc( classPtr->winproc, WIN_PROC_CLASS );
     HeapFree( SystemHeap, 0, classPtr );
     return TRUE;
 }
@@ -291,7 +291,7 @@
     classPtr->dce         = (style & CS_CLASSDC) ?
                                  DCE_AllocDCE( 0, DCE_CLASS_DC ) : NULL;
 
-    WINPROC_SetProc( &classPtr->winproc, wndProc, wndProcType );
+    WINPROC_SetProc( &classPtr->winproc, wndProc, wndProcType, WIN_PROC_CLASS);
 
     /* Other values must be set by caller */
 
@@ -743,7 +743,7 @@
         if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
         retval = (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_16 );
         WINPROC_SetProc( &wndPtr->class->winproc, (WNDPROC16)newval,
-                         WIN_PROC_16 );
+                         WIN_PROC_16, WIN_PROC_CLASS );
         return retval;
     case GCL_MENUNAME:
         return SetClassLong32A( hwnd, offset, (LONG)PTR_SEG_TO_LIN(newval) );
@@ -783,7 +783,7 @@
             retval = (LONG)WINPROC_GetProc( wndPtr->class->winproc,
                                             WIN_PROC_32A );
             WINPROC_SetProc( &wndPtr->class->winproc, (WNDPROC16)newval,
-                             WIN_PROC_32A );
+                             WIN_PROC_32A, WIN_PROC_CLASS );
             return retval;
         case GCL_HBRBACKGROUND:
         case GCL_HCURSOR:
@@ -819,7 +819,7 @@
         if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
         retval = (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_32W );
         WINPROC_SetProc( &wndPtr->class->winproc, (WNDPROC16)newval,
-                         WIN_PROC_32W );
+                         WIN_PROC_32W, WIN_PROC_CLASS );
         return retval;
     case GCL_MENUNAME:
         if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
diff --git a/windows/dce.c b/windows/dce.c
index cc92e5c..8452147 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -727,3 +727,21 @@
   return 0;
 }
 
+
+/***********************************************************************
+ *           LockWindowUpdate16   (USER.294)
+ */
+BOOL16 LockWindowUpdate16( HWND16 hwnd )
+{
+    return LockWindowUpdate32( hwnd );
+}
+
+
+/***********************************************************************
+ *           LockWindowUpdate32   (USER32.377)
+ */
+BOOL32 LockWindowUpdate32( HWND32 hwnd )
+{
+    /* FIXME? DCX_LOCKWINDOWUPDATE is unimplemented */
+    return TRUE;
+}
diff --git a/windows/defdlg.c b/windows/defdlg.c
index 618e3df..3c5c082 100644
--- a/windows/defdlg.c
+++ b/windows/defdlg.c
@@ -114,8 +114,6 @@
 static LRESULT DEFDLG_Proc( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
                             LPARAM lParam, DIALOGINFO *dlgInfo )
 {
-    HWND32 hwndDefId;
-
     switch(msg)
     {
         case WM_ERASEBKGND:
@@ -147,9 +145,9 @@
 	    }
 
             /* Delete window procedure */
-            WINPROC_FreeProc( dlgInfo->dlgProc );
+            WINPROC_FreeProc( dlgInfo->dlgProc, WIN_PROC_WINDOW );
             dlgInfo->dlgProc = (HWINDOWPROC)0;
-	    dlgInfo->fEnd    = TRUE;	/* just in case */
+            dlgInfo->flags |= DF_END;  /* just in case */
 
 	      /* Window clean-up */
 	    return DefWindowProc32A( hwnd, msg, wParam, lParam );
@@ -168,18 +166,20 @@
 	    return 0;
 
         case DM_SETDEFID:
-            if (dlgInfo->fEnd) return 1;
+            if (dlgInfo->flags & DF_END) return 1;
             DEFDLG_SetDefButton( hwnd, dlgInfo,
                                  wParam ? GetDlgItem32( hwnd, wParam ) : 0 );
             return 1;
 
         case DM_GETDEFID:
-            if (dlgInfo->fEnd) return 0;
-	    if (dlgInfo->idResult)
-	      return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
-	    hwndDefId = DEFDLG_FindDefButton( hwnd );
-	    if (hwndDefId)
-	      return MAKELONG( GetDlgCtrlID32( hwndDefId ), DC_HASDEFID);
+            {
+                HWND32 hwndDefId;
+                if (dlgInfo->flags & DF_END) return 0;
+                if (dlgInfo->idResult)
+                    return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
+                if ((hwndDefId = DEFDLG_FindDefButton( hwnd )))
+                    return MAKELONG( GetDlgCtrlID32( hwndDefId ), DC_HASDEFID);
+            }
 	    return 0;
 
 	case WM_NEXTDLGCTL:
@@ -192,6 +192,32 @@
             }
             return 0;
 
+        case WM_ENTERMENULOOP:
+        case WM_LBUTTONDOWN:
+        case WM_NCLBUTTONDOWN:
+            {
+                HWND32 hwndFocus = GetFocus32();
+                if (hwndFocus)
+                {
+                    WND *wnd = WIN_FindWndPtr( hwndFocus );
+
+                    if( wnd )
+                    {
+                        /* always make combo box hide its listbox control */
+
+                        if( WIDGETS_IsControl32( wnd, BIC32_COMBO ) )
+                            SendMessage32A( hwndFocus, CB_SHOWDROPDOWN32,
+                                            FALSE, 0 );
+                        else if( WIDGETS_IsControl32( wnd, BIC32_EDIT ) &&
+                                 WIDGETS_IsControl32( wnd->parent,
+                                                      BIC32_COMBO ))
+                            SendMessage32A( wnd->parent->hwndSelf, 
+                                            CB_SHOWDROPDOWN32, FALSE, 0 );
+                    }
+                }
+            }
+	    return DefWindowProc32A( hwnd, msg, wParam, lParam );
+
 	case WM_GETFONT: 
 	    return dlgInfo->hUserFont;
 
@@ -204,9 +230,9 @@
 }
 
 /***********************************************************************
- *           DEFDLG_Signoff
+ *           DEFDLG_Epilog
  */
-static LRESULT DEFDLG_Signoff(DIALOGINFO* dlgInfo, UINT32 msg, BOOL16 fResult)
+static LRESULT DEFDLG_Epilog(DIALOGINFO* dlgInfo, UINT32 msg, BOOL16 fResult)
 {
     /* see SDK 3.1 */
 
@@ -254,6 +280,9 @@
             case WM_GETFONT:
             case WM_CLOSE:
             case WM_NCDESTROY:
+            case WM_ENTERMENULOOP:
+            case WM_LBUTTONDOWN:
+            case WM_NCLBUTTONDOWN:
                 return DEFDLG_Proc( (HWND32)hwnd, msg, 
                                     (WPARAM32)wParam, lParam, dlgInfo );
             case WM_INITDIALOG:
@@ -266,7 +295,7 @@
                 return DefWindowProc16( hwnd, msg, wParam, lParam );
         }
     }   
-    return DEFDLG_Signoff(dlgInfo, msg, result);
+    return DEFDLG_Epilog(dlgInfo, msg, result);
 }
 
 
@@ -305,6 +334,9 @@
             case WM_GETFONT:
             case WM_CLOSE:
             case WM_NCDESTROY:
+            case WM_ENTERMENULOOP:
+            case WM_LBUTTONDOWN:
+            case WM_NCLBUTTONDOWN:
                  return DEFDLG_Proc( (HWND32)hwnd, msg,
                                      (WPARAM32)wParam, lParam, dlgInfo );
             case WM_INITDIALOG:
@@ -317,7 +349,7 @@
                  return DefWindowProc32A( hwnd, msg, wParam, lParam );
         }
     }
-    return DEFDLG_Signoff(dlgInfo, msg, result);
+    return DEFDLG_Epilog(dlgInfo, msg, result);
 }
 
 
@@ -356,6 +388,9 @@
             case WM_GETFONT:
             case WM_CLOSE:
             case WM_NCDESTROY:
+            case WM_ENTERMENULOOP:
+            case WM_LBUTTONDOWN:
+            case WM_NCLBUTTONDOWN:
                  return DEFDLG_Proc( (HWND32)hwnd, msg,
                                      (WPARAM32)wParam, lParam, dlgInfo );
             case WM_INITDIALOG:
@@ -368,5 +403,5 @@
                  return DefWindowProc32W( hwnd, msg, wParam, lParam );
         }
     }
-    return DEFDLG_Signoff(dlgInfo, msg, result);
+    return DEFDLG_Epilog(dlgInfo, msg, result);
 }
diff --git a/windows/defwnd.c b/windows/defwnd.c
index fec17be..66b8aae 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -263,7 +263,7 @@
 
     case WM_SYSKEYDOWN:
 	if( HIWORD(lParam) & KEYDATA_ALT )
-	  {
+	{
 	    /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
 	      if( wParam == VK_MENU && !iMenuSysKey )
 		iMenuSysKey = 1;
@@ -272,13 +272,20 @@
 	    
 	    iF10Key = 0;
 
-	  } 
+	    if( wParam == VK_F4 )	/* try to close the window */
+	    {
+		HWND32 hWnd = WIN_GetTopParent( wndPtr->hwndSelf );
+		wndPtr = WIN_FindWndPtr( hWnd );
+		if( wndPtr && !(wndPtr->class->style & CS_NOCLOSE) )
+		    PostMessage16( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
+	    }
+	} 
 	else if( wParam == VK_F10 )
-	         iF10Key = 1;
+	        iF10Key = 1;
 	     else
-	         if( wParam == VK_ESCAPE && (GetKeyState32(VK_SHIFT) & 0x8000))
-		     SendMessage16( wndPtr->hwndSelf, WM_SYSCOMMAND,
-                                    (WPARAM16)SC_KEYMENU, (LPARAM)VK_SPACE);
+	        if( wParam == VK_ESCAPE && (GetKeyState32(VK_SHIFT) & 0x8000))
+		    SendMessage16( wndPtr->hwndSelf, WM_SYSCOMMAND,
+                                  (WPARAM16)SC_KEYMENU, (LPARAM)VK_SPACE);
 	break;
 
     case WM_KEYUP:
diff --git a/windows/dialog.c b/windows/dialog.c
index 366dd8a..ca234ad 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -582,13 +582,14 @@
       /* Initialise dialog extra data */
 
     dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
-    WINPROC_SetProc( &dlgInfo->dlgProc, dlgProc, procType );
+    WINPROC_SetProc( &dlgInfo->dlgProc, dlgProc, procType, WIN_PROC_WINDOW );
     dlgInfo->hUserFont = hFont;
     dlgInfo->hMenu     = hMenu;
     dlgInfo->xBaseUnit = xUnit;
     dlgInfo->yBaseUnit = yUnit;
-    dlgInfo->msgResult = 0; 
+    dlgInfo->msgResult = 0;
     dlgInfo->idResult  = 0;
+    dlgInfo->flags     = 0;
     dlgInfo->hDialogHeap = 0;
 
     if (dlgInfo->hUserFont)
@@ -596,21 +597,21 @@
 
     /* Create controls */
 
-    if (!DIALOG_CreateControls( wndPtr, dlgTemplate, template.nbItems,
+    if (DIALOG_CreateControls( wndPtr, dlgTemplate, template.nbItems,
                                 hInst, win32Template ))
     {
-        DestroyWindow32( hwnd );
-        return 0;
+       /* Send initialisation messages and set focus */
+
+       dlgInfo->hwndFocus = GetNextDlgTabItem32( hwnd, 0, FALSE );
+       if (SendMessage32A( hwnd, WM_INITDIALOG,
+                           (WPARAM32)dlgInfo->hwndFocus, param ))
+           SetFocus32( dlgInfo->hwndFocus );
+       if (template.style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
+       return hwnd;
     }
 
-    /* Send initialisation messages and set focus */
-
-    dlgInfo->hwndFocus = GetNextDlgTabItem32( hwnd, 0, FALSE );
-    if (SendMessage32A( hwnd, WM_INITDIALOG,
-                        (WPARAM32)dlgInfo->hwndFocus, param ))
-	SetFocus32( dlgInfo->hwndFocus );
-    if (template.style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
-    return hwnd;
+    if( IsWindow32(hwnd) ) DestroyWindow32( hwnd );
+    return 0;
 }
 
 
@@ -750,7 +751,7 @@
 	    TranslateMessage16( &msg );
 	    DispatchMessage16( &msg );
 	}
-	if (dlgInfo->fEnd) break;
+	if (dlgInfo->flags & DF_END) break;
     }
     retval = dlgInfo->idResult;
     EnableWindow32( owner, TRUE );
@@ -874,9 +875,14 @@
 {
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     DIALOGINFO * dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
-    dlgInfo->idResult = retval;
-    dlgInfo->fEnd = TRUE;
+
     dprintf_dialog(stddeb, "EndDialog: %04x %d\n", hwnd, retval );
+
+    if( dlgInfo )
+    {
+        dlgInfo->idResult = retval;
+        dlgInfo->flags |= DF_END;
+    }
     return TRUE;
 }
 
diff --git a/windows/graphics.c b/windows/graphics.c
index 6169fa7..2de7bd9 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -4,6 +4,7 @@
  * Copyright 1993, 1994 Alexandre Julliard
  */
 
+#include <assert.h>
 #include <math.h>
 #include <stdlib.h>
 #include <X11/Xlib.h>
@@ -26,6 +27,8 @@
 #include "debug.h"
 #include "xmalloc.h"
 
+#define MAX_DRAWLINES		8
+
 /***********************************************************************
  *           LineTo16    (GDI.19)
  */
@@ -231,8 +234,8 @@
 {
     HBRUSH16 prevBrush;
 
-    /* coordinates are logical so we cannot fast-check rectangle
-     * - do it in PatBlt() after LPtoDP().
+    /* coordinates are logical so we cannot fast-check 'rect',
+     * it will be done later in the PatBlt().
      */
 
     if (!(prevBrush = SelectObject16( hdc, hbrush ))) return 0;
@@ -513,75 +516,6 @@
 
 
 /**********************************************************************
- *          GRAPH_DrawBitmap
- *
- * Short-cut function to blit a bitmap into a device.
- * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
- */
-BOOL32 GRAPH_DrawBitmap( HDC32 hdc, HBITMAP32 hbitmap, int xdest, int ydest,
-                         int xsrc, int ysrc, int width, int height )
-{
-    BITMAPOBJ *bmp;
-    DC *dc;
-    
-    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
-    if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
-	return FALSE;
-    XSetFunction( display, dc->u.x.gc, GXcopy );
-    if (bmp->bitmap.bmBitsPixel == 1)
-    {
-        XSetForeground( display, dc->u.x.gc, dc->w.backgroundPixel );
-        XSetBackground( display, dc->u.x.gc, dc->w.textPixel );
-	XCopyPlane( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
-		    xsrc, ysrc, width, height,
-		    dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest, 1 );
-	return TRUE;
-    }
-    else if (bmp->bitmap.bmBitsPixel == dc->w.bitsPerPixel)
-    {
-	XCopyArea( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
-		   xsrc, ysrc, width, height,
-		   dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest );
-	return TRUE;
-    }
-    else return FALSE;
-}
-
-
-/**********************************************************************
- *          GRAPH_DrawReliefRect  (Not a MSWin Call)
- */
-void GRAPH_DrawReliefRect( HDC32 hdc, const RECT32 *rect, INT32 highlight_size,
-                           INT32 shadow_size, BOOL32 pressed )
-{
-    HBRUSH32 hbrushOld;
-    INT32 i;
-
-    hbrushOld = SelectObject32(hdc, pressed ? sysColorObjects.hbrushBtnShadow :
-			                  sysColorObjects.hbrushBtnHighlight );
-    for (i = 0; i < highlight_size; i++)
-    {
-	PatBlt32( hdc, rect->left + i, rect->top,
-                  1, rect->bottom - rect->top - i, PATCOPY );
-	PatBlt32( hdc, rect->left, rect->top + i,
-                  rect->right - rect->left - i, 1, PATCOPY );
-    }
-
-    SelectObject32( hdc, pressed ? sysColorObjects.hbrushBtnHighlight :
-		                   sysColorObjects.hbrushBtnShadow );
-    for (i = 0; i < shadow_size; i++)
-    {
-	PatBlt32( hdc, rect->right - i - 1, rect->top + i,
-                  1, rect->bottom - rect->top - i, PATCOPY );
-	PatBlt32( hdc, rect->left + i, rect->bottom - i - 1,
-                  rect->right - rect->left - i, 1, PATCOPY );
-    }
-
-    SelectObject32( hdc, hbrushOld );
-}
-
-
-/**********************************************************************
  *          Polyline16  (GDI.37)
  */
 BOOL16 Polyline16( HDC16 hdc, LPPOINT16 pt, INT16 count )
@@ -833,3 +767,181 @@
              hdc,rc,edge,flags );
     return TRUE;
 }
+
+/******************************* X-specific shortcuts to speed up WM code.
+ *                              `----------------------------------------
+ *
+ * Caveat: no coordinate transformations except origin translation.
+ */
+
+/**********************************************************************
+ *
+ *          GRAPH_DrawLines
+ *
+ * Draw multiple unconnected lines (limited by MAX_DRAWLINES).
+ */
+BOOL32 GRAPH_DrawLines( HDC32 hdc, LPPOINT32 pXY, INT32 N, HPEN32 hPen )
+{
+    BOOL32	bRet = FALSE;
+    DC*         dc;
+
+    assert( N <= MAX_DRAWLINES );
+    if( (dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC )) )
+    {
+	HPEN32  hPrevPen  = 0;
+
+	if( hPen ) hPrevPen = SelectObject32( hdc, hPen );
+	if( DC_SetupGCForPen( dc ) )
+	{
+	    XSegment	l[MAX_DRAWLINES];
+	    INT32 	i, j;
+
+	    for( i = 0; i < N; i++ )
+	    {
+		 j = 2 * i;
+		 l[i].x1 = pXY[j].x + dc->w.DCOrgX; 
+		 l[i].x2 = pXY[j + 1].x + dc->w.DCOrgX;
+		 l[i].y1 = pXY[j].y + dc->w.DCOrgY;
+		 l[i].y2 = pXY[j + 1].y + dc->w.DCOrgY;
+	    }
+	    XDrawSegments( display, dc->u.x.drawable, dc->u.x.gc, l, N );
+	    bRet = TRUE;
+	}
+	if( hPrevPen ) SelectObject32( hdc, hPrevPen );
+    }
+    return bRet;
+}
+
+/**********************************************************************
+ * 
+ *          GRAPH_DrawBitmap
+ *
+ * Short-cut function to blit a bitmap into a device.
+ * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
+ */
+BOOL32 GRAPH_DrawBitmap( HDC32 hdc, HBITMAP32 hbitmap, 
+			 INT32 xdest, INT32 ydest, INT32 xsrc, INT32 ysrc, 
+                         INT32 width, INT32 height )
+{
+    BITMAPOBJ *bmp;
+    DC *dc;
+
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
+    if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
+        return FALSE;
+    XSetFunction( display, dc->u.x.gc, GXcopy );
+    if (bmp->bitmap.bmBitsPixel == 1)
+    {
+        XSetForeground( display, dc->u.x.gc, dc->w.backgroundPixel );
+        XSetBackground( display, dc->u.x.gc, dc->w.textPixel );
+        XCopyPlane( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
+                    xsrc, ysrc, width, height,
+                    dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest, 1 );
+        return TRUE;
+    }
+    else if (bmp->bitmap.bmBitsPixel == dc->w.bitsPerPixel)
+    {
+        XCopyArea( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
+                   xsrc, ysrc, width, height,
+                   dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest );
+        return TRUE;
+    }
+    else return FALSE;
+}
+
+
+/**********************************************************************
+ *          GRAPH_DrawReliefRect
+ *
+ * Used in the standard control code for button edge drawing.
+ */
+void GRAPH_DrawReliefRect( HDC32 hdc, const RECT32 *rect, INT32 highlight_size,
+                           INT32 shadow_size, BOOL32 pressed )
+{
+    DC*		dc;
+    HBRUSH32 	hPrevBrush;
+    INT32 	w, h;
+    RECT32	r = *rect;
+
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return;
+
+    OffsetRect32( &r, dc->w.DCOrgX, dc->w.DCOrgY);
+    h = rect->bottom - rect->top;  w = rect->right - rect->left;
+
+    hPrevBrush = SelectObject32(hdc, pressed ? sysColorObjects.hbrushBtnShadow :
+                                               sysColorObjects.hbrushBtnHighlight );
+    if ( DC_SetupGCForBrush( dc ) )
+    {
+         INT32	i;
+
+	 XSetFunction( display, dc->u.x.gc, GXcopy );
+         for (i = 0; i < highlight_size; i++)
+         {
+	      XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+					r.left + i, r.top, 1, h - i );
+	      XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+					r.left, r.top + i, w - i, 1 );
+         }
+    }
+
+    SelectObject32( hdc, pressed ? sysColorObjects.hbrushBtnHighlight :
+                                   sysColorObjects.hbrushBtnShadow );
+    if ( DC_SetupGCForBrush( dc ) )
+    {
+	 INT32	i;
+
+	 XSetFunction( display, dc->u.x.gc, GXcopy );
+         for (i = 0; i < shadow_size; i++)
+         {
+	      XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+			      r.right - i - 1, r.top + i, 1, h - i );
+	      XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+			      r.left + i, r.bottom - i - 1, w - i, 1 );
+         }
+    }
+
+    SelectObject32( hdc, hPrevBrush );
+}
+
+/**********************************************************************
+ *          GRAPH_DrawRectangle
+ */
+void GRAPH_DrawRectangle( HDC32 hdc, INT32 x, INT32 y, 
+				     INT32 w, INT32 h, HPEN32 hPen )
+{
+    DC* dc;
+
+    if( (dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC )) ) 
+    {
+        HPEN32	hPrevPen  = 0; 
+
+	if( hPen ) hPrevPen = SelectObject32( hdc, hPen );
+	if( DC_SetupGCForPen( dc ) )
+	    XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc, 
+			    x + dc->w.DCOrgX, y + dc->w.DCOrgY, w - 1, h - 1);
+	if( hPrevPen ) SelectObject32( hdc, hPrevPen );
+    }
+}
+
+/**********************************************************************
+ *          GRAPH_SelectClipMask
+ */
+BOOL32 GRAPH_SelectClipMask( HDC32 hdc, HBITMAP32 hMonoBitmap, INT32 x, INT32 y)
+{
+    BITMAPOBJ *bmp = NULL;
+    DC *dc;
+
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
+    if ( hMonoBitmap ) 
+    {
+       if ( !(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hMonoBitmap, BITMAP_MAGIC)) 
+	   || bmp->bitmap.bmBitsPixel != 1 ) return FALSE;
+	  
+       XSetClipOrigin( display, dc->u.x.gc, dc->w.DCOrgX + x, dc->w.DCOrgY + y);
+    }
+
+    XSetClipMask( display, dc->u.x.gc, (bmp) ? bmp->pixmap : None );
+
+    return TRUE;
+}
+
diff --git a/windows/hook.c b/windows/hook.c
index e01d3b7..2e07fe4 100644
--- a/windows/hook.c
+++ b/windows/hook.c
@@ -575,12 +575,12 @@
 
       case WH_CALLWNDPROC:
       {
-          void          (*localUnMap)(UINT32, WPARAM16, LPARAM)
+          void          (*localUnMap)(UINT32, WPARAM16, LPARAM, LRESULT)
                           = (bA) ? WINPROC_UnmapMsg32ATo16 : WINPROC_UnmapMsg32WTo16;
           LPCWPSTRUCT16   lpcwp16 = (LPCWPSTRUCT16)PTR_SEG_TO_LIN(lParam);
 	  LPCWPSTRUCT32   lpcwp32 = (LPCWPSTRUCT32)lParamOrig;
 
-          (*localUnMap)(lpcwp32->message, lpcwp16->wParam, lpcwp16->lParam );
+          (*localUnMap)(lpcwp32->message, lpcwp16->wParam, lpcwp16->lParam, 0 );
 	  SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
           break;
       }
diff --git a/windows/keyboard.c b/windows/keyboard.c
index d1c0c98..01853aa 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -543,7 +543,7 @@
 	break;
      default:
 	retval = AsyncKeyStateTable[nKey] | 
-	(InputKeyStateTable[nKey] ? 0x8000 : 0);
+	  	((InputKeyStateTable[nKey] & 0x80) ? 0x8000 : 0); 
 	break;
     }
 
diff --git a/windows/message.c b/windows/message.c
index ace5200..38deb9e 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -606,7 +606,7 @@
       queue->wakeBits &= ~QS_SMRESULT;
 
       if( queue->smResult != &qCtrl )
-	  dprintf_msg(stddeb,"%*ssm: weird scenes inside the goldmine!\n", prevSMRL, "");
+	  dprintf_sendmsg(stddeb,"%*ssm: weird scenes inside the goldmine!\n", prevSMRL, "");
     }
     queue->smResultInit = NULL;
     
@@ -675,8 +675,6 @@
     mask = QS_POSTMESSAGE | QS_SENDMESSAGE;  /* Always selected */
     if (first || last)
     {
-        /* MSWord gets stuck if we do not check for nonclient mouse messages */
-
         if ((first <= WM_KEYLAST) && (last >= WM_KEYFIRST)) mask |= QS_KEY;
         if ( ((first <= WM_MOUSELAST) && (last >= WM_MOUSEFIRST)) ||
              ((first <= WM_NCMOUSELAST) && (last >= WM_NCMOUSEFIRST)) ) mask |= QS_MOUSE;
@@ -700,11 +698,7 @@
 	while (msgQueue->wakeBits & QS_SENDMESSAGE)
             QUEUE_ReceiveMessage( msgQueue );
 
-        /* Now handle a WM_QUIT message 
-	 *
-	 * FIXME: PostQuitMessage() should post WM_QUIT and 
-	 *	  set QS_POSTMESSAGE wakebit instead of this.
-	 */
+        /* Now handle a WM_QUIT message */
 
         if (msgQueue->wPostQMsg &&
 	   (!first || WM_QUIT >= first) && 
@@ -1419,7 +1413,6 @@
     {
 	if (msg->lParam)
         {
-/*            HOOK_CallHooks16( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
 	    return CallWindowProc16( (WNDPROC16)msg->lParam, msg->hwnd,
                                    msg->message, msg->wParam, GetTickCount() );
         }
@@ -1430,7 +1423,6 @@
     if (!wndPtr->winproc) return 0;
     painting = (msg->message == WM_PAINT);
     if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
-/*    HOOK_CallHooks16( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
 
     SPY_EnterMessage( SPY_DISPATCHMESSAGE16, msg->hwnd, msg->message,
                       msg->wParam, msg->lParam );
diff --git a/windows/nonclient.c b/windows/nonclient.c
index d04d7df..085b817 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -500,10 +500,10 @@
  * Draw a window frame inside the given rectangle, and update the rectangle.
  * The correct pen for the frame must be selected in the DC.
  */
-static void NC_DrawFrame( HDC16 hdc, RECT16 *rect, BOOL32 dlgFrame,
+static void NC_DrawFrame( HDC32 hdc, RECT32 *rect, BOOL32 dlgFrame,
                           BOOL32 active )
 {
-    short width, height, tmp;
+    INT32 width, height;
 
     if (dlgFrame)
     {
@@ -532,43 +532,45 @@
 
     if (dlgFrame)
     {
-	InflateRect16( rect, -width, -height );
-	return;
-    }
+	InflateRect32( rect, -width, -height );
+    } 
+    else
+    {
+	POINT32 lpt[16];
     
       /* Draw inner rectangle */
-    MoveTo( hdc, rect->left+width, rect->top+height );
-    LineTo32( hdc, rect->right-width-1, rect->top+height );
-    LineTo32( hdc, rect->right-width-1, rect->bottom-height-1 );
-    LineTo32( hdc, rect->left+width, rect->bottom-height-1 );
-    LineTo32( hdc, rect->left+width, rect->top+height );
+
+	GRAPH_DrawRectangle( hdc, rect->left + width,
+                                  rect->top + height,
+                                  rect->right - rect->left - 2*width ,
+                                  rect->bottom - rect->top - 2*height,
+                                  (HPEN32)0 );
 
       /* Draw the decorations */
-    tmp = rect->top + SYSMETRICS_CYFRAME + SYSMETRICS_CYSIZE;
-    MoveTo( hdc, rect->left, tmp);
-    LineTo32( hdc, rect->left+width, tmp );
-    MoveTo( hdc, rect->right-width-1, tmp );
-    LineTo32( hdc, rect->right-1, tmp );
 
-    tmp = rect->bottom - 1 - SYSMETRICS_CYFRAME - SYSMETRICS_CYSIZE;
-    MoveTo( hdc, rect->left, tmp );
-    LineTo32( hdc, rect->left+width, tmp );
-    MoveTo( hdc, rect->right-width-1, tmp );
-    LineTo32( hdc, rect->right-1, tmp );
+	lpt[4].x = lpt[0].x = rect->left;
+	lpt[5].x = lpt[1].x = rect->left + width;
+	lpt[6].x = lpt[2].x = rect->right - width - 1;
+	lpt[7].x = lpt[3].x = rect->right - 1;
 
-    tmp = rect->left + SYSMETRICS_CXFRAME + SYSMETRICS_CXSIZE;
-    MoveTo( hdc, tmp, rect->top );
-    LineTo32( hdc, tmp, rect->top+height );
-    MoveTo( hdc, tmp, rect->bottom-height-1 );
-    LineTo32( hdc, tmp, rect->bottom-1 );
+	lpt[0].y = lpt[1].y = lpt[2].y = lpt[3].y = 
+		  rect->top + SYSMETRICS_CYFRAME + SYSMETRICS_CYSIZE;
+	lpt[4].y = lpt[5].y = lpt[6].y = lpt[7].y =
+		  rect->bottom - 1 - SYSMETRICS_CYFRAME - SYSMETRICS_CYSIZE;
 
-    tmp = rect->right - 1 - SYSMETRICS_CXFRAME - SYSMETRICS_CYSIZE;
-    MoveTo( hdc, tmp, rect->top );
-    LineTo32( hdc, tmp, rect->top+height );
-    MoveTo( hdc, tmp, rect->bottom-height-1 );
-    LineTo32( hdc, tmp, rect->bottom-1 );
+        lpt[8].x = lpt[9].x = lpt[10].x = lpt[11].x =
+		  rect->left + SYSMETRICS_CXFRAME + SYSMETRICS_CXSIZE;
+	lpt[12].x = lpt[13].x = lpt[14].x = lpt[15].x = 
+		  rect->right - 1 - SYSMETRICS_CXFRAME - SYSMETRICS_CYSIZE;
 
-    InflateRect16( rect, -width-1, -height-1 );
+	lpt[12].y = lpt[8].y = rect->top; 
+	lpt[13].y = lpt[9].y = rect->top + height;
+	lpt[14].y = lpt[10].y = rect->bottom - height - 1; 
+	lpt[15].y = lpt[11].y = rect->bottom - 1;
+
+	GRAPH_DrawLines( hdc, lpt, 8, (HPEN32)0 );	/* 8 is the maximum */
+	InflateRect32( rect, -width - 1, -height - 1 );
+    }
 }
 
 
@@ -591,10 +593,10 @@
  * Draw the window caption.
  * The correct pen for the window frame must be selected in the DC.
  */
-static void NC_DrawCaption( HDC16 hdc, RECT16 *rect, HWND32 hwnd,
+static void NC_DrawCaption( HDC32 hdc, RECT32 *rect, HWND32 hwnd,
 			    DWORD style, BOOL32 active )
 {
-    RECT16 r = *rect;
+    RECT32 r = *rect;
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     char buffer[256];
 
@@ -644,7 +646,7 @@
 	r.right -= SYSMETRICS_CXSIZE + 1;
     }
 
-    FillRect16( hdc, &r, active ? sysColorObjects.hbrushActiveCaption : 
+    FillRect32( hdc, &r, active ? sysColorObjects.hbrushActiveCaption : 
 	                          sysColorObjects.hbrushInactiveCaption );
 
     if (GetWindowText32A( hwnd, buffer, sizeof(buffer) ))
@@ -652,8 +654,8 @@
 	if (active) SetTextColor32( hdc, GetSysColor32( COLOR_CAPTIONTEXT ) );
 	else SetTextColor32( hdc, GetSysColor32( COLOR_INACTIVECAPTIONTEXT ) );
 	SetBkMode32( hdc, TRANSPARENT );
-	DrawText16( hdc, buffer, -1, &r,
-                    DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
+	DrawText32A( hdc, buffer, -1, &r,
+                     DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
     }
 }
 
@@ -666,7 +668,7 @@
 void NC_DoNCPaint( HWND32 hwnd, HRGN32 clip, BOOL32 suppress_menupaint )
 {
     HDC32 hdc;
-    RECT16 rect;
+    RECT32 rect;
     BOOL32 active;
 
     WND *wndPtr = WIN_FindWndPtr( hwnd );
@@ -701,12 +703,9 @@
         if ((wndPtr->dwStyle & WS_BORDER) || (wndPtr->dwStyle & WS_DLGFRAME) ||
             (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
         {
-            MoveTo( hdc, 0, 0 );
-            LineTo32( hdc, rect.right-1, 0 );
-            LineTo32( hdc, rect.right-1, rect.bottom-1 );
-            LineTo32( hdc, 0, rect.bottom-1 );
-            LineTo32( hdc, 0, 0 );
-            InflateRect16( &rect, -1, -1 );
+            GRAPH_DrawRectangle( hdc, 0, 0,
+                                 rect.right, rect.bottom, (HPEN32)0 );
+            InflateRect32( &rect, -1, -1 );
         }
 
         if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle )) 
@@ -716,7 +715,7 @@
 
         if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
         {
-            RECT16 r = rect;
+            RECT32 r = rect;
             r.bottom = rect.top + SYSMETRICS_CYSIZE;
             rect.top += SYSMETRICS_CYSIZE + SYSMETRICS_CYBORDER;
             NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
@@ -725,8 +724,7 @@
 
     if (HAS_MENU(wndPtr))
     {
-	RECT32 r;
-        CONV_RECT16TO32( &rect, &r );
+	RECT32 r = rect;
 	r.bottom = rect.top + SYSMETRICS_CYMENU;  /* default height */
 	rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
     }
@@ -742,10 +740,10 @@
 
     if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
     {
-        RECT16 r = rect;
+        RECT32 r = rect;
         r.left = r.right - SYSMETRICS_CXVSCROLL + 1;
         r.top  = r.bottom - SYSMETRICS_CYHSCROLL + 1;
-        FillRect16( hdc, &r, sysColorObjects.hbrushScrollbar );
+        FillRect32( hdc, &r, sysColorObjects.hbrushScrollbar );
     }    
 
     ReleaseDC32( hwnd, hdc );
diff --git a/windows/painting.c b/windows/painting.c
index 78f6062..1196b8f 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -235,7 +235,7 @@
 /***********************************************************************
  *           PAINT_RedrawWindow
  *
- * Note: Windows uses WM_SYNCPAINT to cut down the number of intertask
+ * FIXME: Windows uses WM_SYNCPAINT to cut down the number of intertask
  * SendMessage() calls. From SDK:
  *   This message avoids lots of inter-app message traffic
  *   by switching to the other task and continuing the
@@ -256,8 +256,8 @@
 
     if (!hwnd) hwnd = GetDesktopWindow32();
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
-    if (!IsWindowVisible32(hwnd) || (wndPtr->flags & WIN_NO_REDRAW))
-        return TRUE;  /* No redraw needed */
+    if (!WIN_IsWindowDrawable( wndPtr, !(flags & RDW_FRAME) ) 
+	|| (wndPtr->flags & WIN_NO_REDRAW)) return TRUE;  /* No redraw needed */
 
     bIcon = (wndPtr->dwStyle & WS_MINIMIZE && wndPtr->class->hIcon);
     if (rectUpdate)
@@ -455,13 +455,7 @@
 BOOL32 RedrawWindow32( HWND32 hwnd, const RECT32 *rectUpdate,
                        HRGN32 hrgnUpdate, UINT32 flags )
 {
-    WND* wnd = WIN_FindWndPtr( hwnd );
-
-    /* check if there is something to redraw */
-
-    return ( wnd && WIN_IsWindowDrawable( wnd, !(flags & RDW_FRAME) ) )
-           ? PAINT_RedrawWindow( hwnd, rectUpdate, hrgnUpdate, flags, 0 )
-	   : 1;
+    return PAINT_RedrawWindow( hwnd, rectUpdate, hrgnUpdate, flags, 0 );
 }
 
 
@@ -477,7 +471,8 @@
         CONV_RECT16TO32( rectUpdate, &r );
         return (BOOL16)RedrawWindow32( (HWND32)hwnd, &r, hrgnUpdate, flags );
     }
-    return (BOOL16)RedrawWindow32( (HWND32)hwnd, NULL, hrgnUpdate, flags );
+    return (BOOL16)PAINT_RedrawWindow( (HWND32)hwnd, NULL, 
+				       (HRGN32)hrgnUpdate, flags, 0 );
 }
 
 
@@ -486,25 +481,24 @@
  */
 void UpdateWindow16( HWND16 hwnd )
 {
-    RedrawWindow32( hwnd, NULL, 0, RDW_UPDATENOW | RDW_NOCHILDREN );
+    PAINT_RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_NOCHILDREN, 0 );
 }
 
-
 /***********************************************************************
  *           UpdateWindow32   (USER32.566)
  */
 void UpdateWindow32( HWND32 hwnd )
 {
-    RedrawWindow32( hwnd, NULL, 0, RDW_UPDATENOW | RDW_NOCHILDREN );
+    PAINT_RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_NOCHILDREN, 0 );
 }
 
-
 /***********************************************************************
  *           InvalidateRgn16   (USER.126)
  */
 void InvalidateRgn16( HWND16 hwnd, HRGN16 hrgn, BOOL16 erase )
 {
-    RedrawWindow32(hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
+    PAINT_RedrawWindow((HWND32)hwnd, NULL, (HRGN32)hrgn, 
+		       RDW_INVALIDATE | (erase ? RDW_ERASE : 0), 0 );
 }
 
 
@@ -513,7 +507,7 @@
  */
 void InvalidateRgn32( HWND32 hwnd, HRGN32 hrgn, BOOL32 erase )
 {
-    RedrawWindow32(hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
+    PAINT_RedrawWindow(hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0), 0 );
 }
 
 
@@ -531,7 +525,8 @@
  */
 void InvalidateRect32( HWND32 hwnd, const RECT32 *rect, BOOL32 erase )
 {
-    RedrawWindow32( hwnd, rect, 0, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
+    PAINT_RedrawWindow( hwnd, rect, 0, 
+			RDW_INVALIDATE | (erase ? RDW_ERASE : 0), 0 );
 }
 
 
@@ -540,7 +535,8 @@
  */
 void ValidateRgn16( HWND16 hwnd, HRGN16 hrgn )
 {
-    RedrawWindow32( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
+    PAINT_RedrawWindow( (HWND32)hwnd, NULL, (HRGN32)hrgn, 
+			RDW_VALIDATE | RDW_NOCHILDREN, 0 );
 }
 
 
@@ -549,7 +545,7 @@
  */
 void ValidateRgn32( HWND32 hwnd, HRGN32 hrgn )
 {
-    RedrawWindow32( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
+    PAINT_RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN, 0 );
 }
 
 
@@ -567,7 +563,7 @@
  */
 void ValidateRect32( HWND32 hwnd, const RECT32 *rect )
 {
-    RedrawWindow32( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN );
+    PAINT_RedrawWindow( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN, 0 );
 }
 
 
diff --git a/windows/timer.c b/windows/timer.c
index 93f8563..b08e892 100644
--- a/windows/timer.c
+++ b/windows/timer.c
@@ -87,7 +87,7 @@
     pTimer->msg     = 0;
     pTimer->id      = 0;
     pTimer->timeout = 0;
-    WINPROC_FreeProc( pTimer->proc );
+    WINPROC_FreeProc( pTimer->proc, WIN_PROC_TIMER );
 }
 
 
@@ -235,9 +235,10 @@
               /* Got one: set new values and return */
             TIMER_RemoveTimer( pTimer );
             pTimer->timeout = timeout;
-            WINPROC_FreeProc( pTimer->proc );
+            WINPROC_FreeProc( pTimer->proc, WIN_PROC_TIMER );
             pTimer->proc = (HWINDOWPROC)0;
-            if (proc) WINPROC_SetProc( &pTimer->proc, proc, type );
+            if (proc) WINPROC_SetProc( &pTimer->proc, proc,
+                                       type, WIN_PROC_TIMER );
             pTimer->expires = GetTickCount() + timeout;
             TIMER_InsertTimer( pTimer );
             return id;
@@ -262,7 +263,7 @@
     pTimer->timeout = timeout;
     pTimer->expires = GetTickCount() + timeout;
     pTimer->proc    = (HWINDOWPROC)0;
-    if (proc) WINPROC_SetProc( &pTimer->proc, proc, type );
+    if (proc) WINPROC_SetProc( &pTimer->proc, proc, type, WIN_PROC_TIMER );
     dprintf_timer( stddeb, "Timer added: %p, %04x, %04x, %04x, %08lx\n", 
 		   pTimer, pTimer->hwnd, pTimer->msg, pTimer->id,
                    (DWORD)pTimer->proc );
diff --git a/windows/win.c b/windows/win.c
index d273b2b..e5be6f4 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -363,7 +363,7 @@
     if (wndPtr->window) EVENT_DestroyWindow( wndPtr );
     if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->dce );
 
-    WINPROC_FreeProc( wndPtr->winproc );
+    WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
 
     wndPtr->class->cWindows--;
     wndPtr->class = NULL;
@@ -415,7 +415,6 @@
     pWndDesktop->parent            = NULL;
     pWndDesktop->owner             = NULL;
     pWndDesktop->class             = class;
-    pWndDesktop->winproc           = NULL;
     pWndDesktop->dwMagic           = WND_MAGIC;
     pWndDesktop->hwndSelf          = hwndDesktop;
     pWndDesktop->hInstance         = 0;
@@ -446,7 +445,8 @@
     pWndDesktop->hSysMenu          = 0;
     pWndDesktop->userdata          = 0;
 
-    WINPROC_SetProc( &pWndDesktop->winproc, (WNDPROC16)class->winproc, 0 );
+    pWndDesktop->winproc = (WNDPROC16)class->winproc;
+
     EVENT_RegisterWindow( pWndDesktop );
     SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
     pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
@@ -550,7 +550,7 @@
 
     wndPtr->window         = 0;
     wndPtr->class          = classPtr;
-    wndPtr->winproc        = NULL;
+    wndPtr->winproc        = classPtr->winproc;
     wndPtr->dwMagic        = WND_MAGIC;
     wndPtr->hwndSelf       = hwnd;
     wndPtr->hInstance      = cs->hInstance;
@@ -592,10 +592,9 @@
 	}
     }
 
-    /* Set the window procedure */
+    /* Increment class window counter */
 
     classPtr->cWindows++;
-    WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)classPtr->winproc, 0 );
 
     /* Correct the window style */
 
@@ -1509,7 +1508,8 @@
         if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
         {
             retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
-            WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval, type );
+            WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval, 
+                             type, WIN_PROC_WINDOW );
             return retval;
         }
     }
@@ -1520,7 +1520,8 @@
             return SetWindowWord32( hwnd, offset, (WORD)newval );
 	case GWL_WNDPROC:
             retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
-            WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval, type );
+            WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval, 
+						type, WIN_PROC_WINDOW );
             return retval;
 	case GWL_STYLE:
 
@@ -1814,27 +1815,23 @@
 
 /***********************************************************************
  *           WIN_IsWindowDrawable
- * 
- * hwnd is drawable when it is visible, all parents are not 
- * minimized, and it is itself not minimized unless we are 
+ *
+ * hwnd is drawable when it is visible, all parents are not
+ * minimized, and it is itself not minimized unless we are
  * trying to draw icon and the default class icon is set.
  */
 BOOL32 WIN_IsWindowDrawable( WND* wnd , BOOL32 icon )
 {
-  HWND32 hwnd = wnd->hwndSelf;
-  BOOL32 yes = TRUE;
-
-  while(wnd && yes)
-  { 
-    if( wnd->dwStyle & WS_MINIMIZE )
-	if( wnd->hwndSelf != hwnd ) break;
-	else if( icon && wnd->class->hIcon ) break;
-
-    yes = yes && (wnd->dwStyle & WS_VISIBLE);
-    wnd = wnd->parent; }      
-  return (!wnd && yes);
+  if( (wnd->dwStyle & WS_MINIMIZE &&
+       icon && wnd->class->hIcon) ||
+     !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
+  for(wnd = wnd->parent; wnd; wnd = wnd->parent)
+    if( wnd->dwStyle & WS_MINIMIZE ||
+      !(wnd->dwStyle & WS_VISIBLE) ) break;
+  return (wnd == NULL);
 }
 
+
 /*******************************************************************
  *         GetTopWindow16    (USER.229)
  */
diff --git a/windows/winpos.c b/windows/winpos.c
index 876e65b..97bbb24 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -157,6 +157,24 @@
 
 
 /***********************************************************************
+ *             SwitchToThisWindow16   (USER.172)
+ */
+void SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
+{
+    SwitchToThisWindow32( hwnd, restore );
+}
+
+
+/***********************************************************************
+ *             SwitchToThisWindow32   (USER32.538)
+ */
+void SwitchToThisWindow32( HWND32 hwnd, BOOL32 restore )
+{
+    ShowWindow32( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
+}
+
+
+/***********************************************************************
  *           GetWindowRect16   (USER.32)
  */
 void GetWindowRect16( HWND16 hwnd, LPRECT16 rect ) 
diff --git a/windows/winproc.c b/windows/winproc.c
index d7a196a..7b56197 100644
--- a/windows/winproc.c
+++ b/windows/winproc.c
@@ -17,7 +17,9 @@
 #include "stddebug.h"
 #include "debug.h"
 
-/* Window procedure 16-bit thunk; see BuildSpec16Files() in tools/build.c */
+/* Window procedure 16--to-32-bit thunk,
+ * see BuildSpec16Files() in tools/build.c */
+
 typedef struct
 {
     BYTE       popl_eax;             /* popl  %eax (return address) */
@@ -28,11 +30,13 @@
     BYTE       pushl_thunk;          /* pushl $thunkfrom16 */
     void     (*thunk32)() WINE_PACKED;
     BYTE       lcall;                /* lcall cs:relay */
-    void     (*relay)() WINE_PACKED;
+    void     (*relay)() WINE_PACKED; /* WINPROC_CallProc16To32A/W() */
     WORD       cs WINE_PACKED;
 } WINPROC_THUNK_FROM16;
 
-/* Window procedure 32-bit thunk; see BuildSpec32Files() in tools/build.c */
+/* Window procedure 32-to-16-bit thunk,
+ * see BuildSpec32Files() in tools/build.c */
+
 typedef struct
 {
     BYTE       popl_eax;             /* popl  %eax (return address) */
@@ -45,7 +49,7 @@
     BYTE       pushl_thunk;          /* pushl $thunkfrom32 */
     void     (*thunk32)() WINE_PACKED;
     BYTE       jmp;                  /* jmp   relay (relative jump)*/
-    void     (*relay)() WINE_PACKED;
+    void     (*relay)() WINE_PACKED; /* WINPROC_CallProc32ATo16() */
 } WINPROC_THUNK_FROM32;
 
 /* Simple jmp to call 32-bit procedure directly */
@@ -68,6 +72,7 @@
     struct tagWINDOWPROC *next;     /* Next window proc */
     UINT32                magic;    /* Magic number */
     WINDOWPROCTYPE        type;     /* Function type */
+    WINDOWPROCUSER        user;     /* Function user */
 } WINDOWPROC;
 
 #define WINPROC_MAGIC  ('W' | ('P' << 8) | ('R' << 16) | ('C' << 24))
@@ -162,7 +167,8 @@
  *
  * Allocate a new window procedure.
  */
-static WINDOWPROC *WINPROC_AllocWinProc( WNDPROC16 func, WINDOWPROCTYPE type )
+static WINDOWPROC *WINPROC_AllocWinProc( WNDPROC16 func, WINDOWPROCTYPE type,
+                                         WINDOWPROCUSER user )
 {
     WINDOWPROC *proc, *oldproc;
 
@@ -220,6 +226,7 @@
         }
         proc->magic = WINPROC_MAGIC;
         proc->type  = type;
+        proc->user  = user;
     }
     proc->next  = NULL;
     dprintf_win( stddeb, "WINPROC_AllocWinProc(%08x,%d): returning %08x\n",
@@ -257,11 +264,28 @@
 /**********************************************************************
  *	     WINPROC_SetProc
  *
- * Set the window procedure for a window or class.
+ * Set the window procedure for a window or class. There are
+ * three tree classes of winproc callbacks:
+ *
+ * 1) class  -> wp                 	-	not subclassed
+ *    class  -> wp -> wp -> wp -> wp 	-	SetClassLong()
+ *             /           /
+ * 2) window -'           /		-	not subclassed
+ *    window -> wp -> wp '           	-	SetWindowLong()
+ *
+ * 3) timer  -> wp                   	-	SetTimer()
+ *
+ * Initially, winproc of the window points to the current winproc 
+ * thunk of its class. Subclassing prepends a new thunk to the 
+ * window winproc chain at the head of the list. Thus, window thunk 
+ * list includes class thunks and the latter are preserved when the 
+ * window is destroyed.
+ *
  */
 BOOL32 WINPROC_SetProc( HWINDOWPROC *pFirst, WNDPROC16 func,
-                        WINDOWPROCTYPE type )
+                        WINDOWPROCTYPE type, WINDOWPROCUSER user )
 {
+    BOOL32 bRecycle = FALSE;
     WINDOWPROC *proc, **ppPrev;
 
     /* Check if function is already in the list */
@@ -272,18 +296,38 @@
     {
         if (proc)
         {
-            if (*ppPrev == proc) break;
+            if (*ppPrev == proc)
+            {
+                if ((*ppPrev)->user != user)
+		{
+		    /* terminal thunk is being restored */
+
+		    WINPROC_FreeProc( *pFirst, (*ppPrev)->user );
+		    *(WINDOWPROC **)pFirst = *ppPrev;
+		    return TRUE;
+		}
+		bRecycle = TRUE;
+		break;
+	    }
         }
         else
         {
             if (((*ppPrev)->type == type) &&
-                (func == WINPROC_THUNKPROC(*ppPrev))) break;
+                (func == WINPROC_THUNKPROC(*ppPrev)))
+            {
+                bRecycle = TRUE;
+                break;
+            }
         }
+            
+        /* WPF_CLASS thunk terminates window thunk list */
+        if ((*ppPrev)->user != user) break;
         ppPrev = &(*ppPrev)->next;
     }
 
-    if (*ppPrev)  /* Remove it from the list */
+    if (bRecycle)
     {
+        /* Extract this thunk from the list */
         proc = *ppPrev;
         *ppPrev = proc->next;
     }
@@ -294,7 +338,7 @@
             type = proc->type;
             func = WINPROC_THUNKPROC(proc);
         }
-        proc = WINPROC_AllocWinProc( func, type );
+        proc = WINPROC_AllocWinProc( func, type, user );
         if (!proc) return FALSE;
     }
 
@@ -313,11 +357,12 @@
  *
  * Free a list of win procs.
  */
-void WINPROC_FreeProc( HWINDOWPROC proc )
+void WINPROC_FreeProc( HWINDOWPROC proc, WINDOWPROCUSER user )
 {
     while (proc)
     {
         WINDOWPROC *next = ((WINDOWPROC *)proc)->next;
+        if (((WINDOWPROC *)proc)->user != user) break;
         dprintf_win( stddeb, "WINPROC_FreeProc: freeing %08x\n", (UINT32)proc);
         HeapFree( WinProcHeap, 0, proc );
         proc = next;
@@ -987,6 +1032,40 @@
     case BM_SETSTYLE32:
         *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK32);
         return 0;
+
+    case EM_GETSEL32:
+    case EM_GETRECT32:
+    case EM_SETRECT32:
+    case EM_SETRECTNP32:
+    case EM_SCROLL32:
+    case EM_LINESCROLL32:
+    case EM_SCROLLCARET32:
+    case EM_GETMODIFY32:
+    case EM_SETMODIFY32:
+    case EM_GETLINECOUNT32:
+    case EM_LINEINDEX32:
+    case EM_SETHANDLE32:
+    case EM_GETHANDLE32:
+    case EM_GETTHUMB32:
+    case EM_LINELENGTH32:
+    case EM_REPLACESEL32:
+    case EM_GETLINE32:
+    case EM_LIMITTEXT32:
+    case EM_CANUNDO32:
+    case EM_UNDO32:
+    case EM_FMTLINES32:
+    case EM_LINEFROMCHAR32:
+    case EM_SETTABSTOPS32:
+    case EM_SETPASSWORDCHAR32:
+    case EM_EMPTYUNDOBUFFER32:
+    case EM_GETFIRSTVISIBLELINE32:
+    case EM_SETREADONLY32:
+    case EM_SETWORDBREAKPROC32:
+    case EM_GETWORDBREAKPROC32:
+    case EM_GETPASSWORDCHAR32:
+        *pmsg16 = (UINT16)msg32 + (EM_GETSEL16 - EM_GETSEL32);
+        return 0;
+
     case LB_CARETOFF32:
     case LB_CARETON32:
     case LB_DELETESTRING32:
@@ -1015,6 +1094,27 @@
     case LB_SETTOPINDEX32:
         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
         return 0;
+    case CB_DELETESTRING32:
+    case CB_GETCOUNT32:
+    case CB_GETLBTEXTLEN32:
+    case CB_LIMITTEXT32:
+    case CB_RESETCONTENT32:
+    case CB_SETEDITSEL32:
+    case CB_GETCURSEL32:
+    case CB_SETCURSEL32:
+    case CB_SHOWDROPDOWN32:
+    case CB_SETITEMDATA32:
+    case CB_SETITEMHEIGHT32:
+    case CB_GETITEMHEIGHT32:
+    case CB_SETEXTENDEDUI32:
+    case CB_GETEXTENDEDUI32:
+    case CB_GETDROPPEDSTATE32:
+	*pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL32);
+	return 0;
+    case CB_GETEDITSEL32:
+	*pmsg16 = CB_GETEDITSEL16;
+	return 1;
+
     case LB_ADDSTRING32:
     case LB_FINDSTRING32:
     case LB_FINDSTRINGEXACT32:
@@ -1022,7 +1122,6 @@
     case LB_SELECTSTRING32:
     case LB_DIR32:
     case LB_ADDFILE32:
-/*    case LB_GETTEXT32: FIXME */
         {
             LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
             if (!str) return -1;
@@ -1030,6 +1129,21 @@
         }
         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
         return 1;
+
+    case CB_ADDSTRING32:
+    case CB_FINDSTRING32:
+    case CB_FINDSTRINGEXACT32:
+    case CB_INSERTSTRING32:
+    case CB_SELECTSTRING32:
+    case CB_DIR32:
+	{
+	    LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
+	    if (!str) return -1;
+	    *plparam = (LPARAM)SEGPTR_GET(str);
+	}
+	*pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL32);
+	return 1;
+
     case LB_GETITEMRECT32:
         {
             RECT16 *rect;
@@ -1038,6 +1152,7 @@
             *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
             *plparam = (LPARAM)SEGPTR_GET(rect);
         }
+	*pmsg16 = LB_GETITEMRECT16;
         return 1;
     case LB_GETSELITEMS32:
         {
@@ -1048,6 +1163,7 @@
             *((LPARAM *)items)++ = *plparam;  /* Store the previous lParam */
             *plparam = (LPARAM)SEGPTR_GET(items);
         }
+	*pmsg16 = LB_GETSELITEMS16;
         return 1;
     case LB_SETTABSTOPS32:
         if (wParam32)
@@ -1063,6 +1179,34 @@
         }
         *pmsg16 = LB_SETTABSTOPS16;
         return 0;
+
+    case CB_GETDROPPEDCONTROLRECT32:
+        {
+	    RECT16 *rect;
+	    rect = (RECT16 *)SEGPTR_ALLOC( sizeof(RECT16) + sizeof(LPARAM) );
+	    if (!rect) return -1;
+	    *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
+	    *plparam = (LPARAM)SEGPTR_GET(rect);
+        }
+	*pmsg16 = CB_GETDROPPEDCONTROLRECT16;
+        return 1;
+
+    case LB_GETTEXT32:
+	*plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
+	*pmsg16 = LB_GETTEXT16;
+	return 1;
+
+    case CB_GETLBTEXT32:
+	*plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
+	*pmsg16 = CB_GETLBTEXT16;
+	return 1;
+
+    case EM_SETSEL32:
+	*pwparam16 = 0;
+	*plparam = MAKELONG( (INT16)(INT32)wParam32, (INT16)*plparam );
+	*pmsg16 = EM_SETSEL16;
+	return 0;
+
     case WM_ACTIVATE:
     case WM_CHARTOITEM:
     case WM_COMMAND:
@@ -1272,7 +1416,8 @@
  *
  * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
  */
-void WINPROC_UnmapMsg32ATo16( UINT32 msg, WPARAM16 wParam, LPARAM lParam )
+void WINPROC_UnmapMsg32ATo16( UINT32 msg, WPARAM16 wParam, 
+					  LPARAM lParam, LRESULT lResult )
 {
     switch(msg)
     {
@@ -1284,12 +1429,20 @@
     case LB_INSERTSTRING32:
     case LB_SELECTSTRING32:
     case LB_SETTABSTOPS32:
+    case CB_ADDSTRING32:
+    case CB_FINDSTRING32:
+    case CB_FINDSTRINGEXACT32:
+    case CB_INSERTSTRING32:
+    case CB_SELECTSTRING32:
+    case CB_DIR32:
     case WM_COMPAREITEM:
     case WM_DELETEITEM:
     case WM_DRAWITEM:
     case WM_SETTEXT:
         SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
         break;
+
+    case CB_GETDROPPEDCONTROLRECT32:
     case LB_GETITEMRECT32:
         {
             RECT16 *rect = (RECT16 *)PTR_SEG_TO_LIN(lParam);
@@ -1307,6 +1460,21 @@
             SEGPTR_FREE( (LPARAM *)items - 1 );
         }
         break;
+
+    case CB_GETEDITSEL32:
+/*
+	if( wParam )
+	    *((LPUINT32)wParam) = LOWORD(lResult);
+	if( lParam )
+	    *((LPUINT32)lParam) = HIWORD(lResult);
+*/
+	break;
+
+    case LB_GETTEXT32:
+    case CB_GETLBTEXT32:
+	UnMapLS( (SEGPTR)lParam );
+	break;
+
     case WM_MEASUREITEM:
         {
             MEASUREITEMSTRUCT16 *mis = (MEASUREITEMSTRUCT16 *)PTR_SEG_TO_LIN(lParam);
@@ -1401,11 +1569,27 @@
         {
             LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
             if (!str) return -1;
-            *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
             *pwparam16 = (WPARAM16)LOWORD(wParam32);
             *plparam   = (LPARAM)SEGPTR_GET(str);
         }
+	*pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
         return 1;
+
+    case CB_ADDSTRING32:
+    case CB_FINDSTRING32:
+    case CB_FINDSTRINGEXACT32:
+    case CB_INSERTSTRING32:
+    case CB_SELECTSTRING32:
+    case CB_DIR32:
+        {
+            LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
+            if (!str) return -1;
+            *pwparam16 = (WPARAM16)LOWORD(wParam32);
+            *plparam   = (LPARAM)SEGPTR_GET(str);
+        }
+	*pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING32);
+        return 1;
+
     case WM_NCCREATE:
     case WM_CREATE:
         {
@@ -1462,7 +1646,8 @@
  *
  * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
  */
-void WINPROC_UnmapMsg32WTo16( UINT32 msg, WPARAM16 wParam, LPARAM lParam )
+void WINPROC_UnmapMsg32WTo16( UINT32 msg, WPARAM16 wParam, 
+					  LPARAM lParam, LRESULT lResult )
 {
     switch(msg)
     {
@@ -1475,7 +1660,7 @@
         }
         break;
     default:
-        WINPROC_UnmapMsg32ATo16( msg, wParam, lParam );
+        WINPROC_UnmapMsg32ATo16( msg, wParam, lParam, lResult );
         break;
     }
 }
@@ -1579,7 +1764,7 @@
     if (wndPtr) CURRENT_DS = wndPtr->hInstance;
     result = CallWndProc16( func, hwnd, msg16, wParam16, lParam );
     CURRENT_DS = ds;
-    WINPROC_UnmapMsg32ATo16( msg, wParam16, lParam );
+    WINPROC_UnmapMsg32ATo16( msg, wParam16, lParam, result );
     return result;
 }
 
@@ -1604,7 +1789,7 @@
     if (wndPtr) CURRENT_DS = wndPtr->hInstance;
     result = CallWndProc16( func, hwnd, msg16, wParam16, lParam );
     CURRENT_DS = ds;
-    WINPROC_UnmapMsg32WTo16( msg, wParam16, lParam );
+    WINPROC_UnmapMsg32WTo16( msg, wParam16, lParam, result );
     return result;
 }
 
diff --git a/wine.man b/wine.man
index fa20fd4..9984823 100644
--- a/wine.man
+++ b/wine.man
@@ -109,7 +109,7 @@
 .I -language xx
 Set the language to
 .I xx
-(one of En, Es, De, No, Fr, Fi, Da, Cz, Eo, It, Ko, Hu, Pl)
+(one of En, Es, De, No, Fr, Fi, Da, Cz, Eo, It, Ko, Hu, Pl, Po)
 .TP
 .I -managed
 Create each top-level window as a properly managed X window