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