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