From f5f9f2cc515815025e79d8a6f2cf29ac26d2138a Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Fri, 5 Jan 2001 22:21:18 +0000 Subject: [PATCH] Added unicode window proc for combobox control. Replaced ansi calls by their unicode equivalents. --- controls/combo.c | 407 +++++++++++++++++++++++++++++------------------ 1 file changed, 255 insertions(+), 152 deletions(-) diff --git a/controls/combo.c b/controls/combo.c index 2ca664a8e06..55a64cc4b6a 100644 --- a/controls/combo.c +++ b/controls/combo.c @@ -33,10 +33,10 @@ DEFAULT_DEBUG_CHANNEL(combo); #define CB_GETPTR( wnd ) (*(LPHEADCOMBO*)((wnd)->wExtra)) #define CB_NOTIFY( lphc, code ) \ - (SendMessageA( (lphc)->owner, WM_COMMAND, \ + (SendMessageW((lphc)->owner, WM_COMMAND, \ MAKEWPARAM((lphc)->self->wIDmenu, (code)), (lphc)->self->hwndSelf)) #define CB_GETEDITTEXTLENGTH( lphc ) \ - (SendMessageA( (lphc)->hWndEdit, WM_GETTEXTLENGTH, 0, 0 )) + (SendMessageW((lphc)->hWndEdit, WM_GETTEXTLENGTH, 0, 0 )) #define ISWIN31 (LOWORD(GetVersion()) == 0x0a03) @@ -57,7 +57,7 @@ static UINT CBitHeight, CBitWidth; #define EDIT_CONTROL_PADDING() ( (TWEAK_WineLook == WIN31_LOOK) ? 0 : 1 ) static LRESULT WINAPI ComboWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ); - +static LRESULT WINAPI ComboWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ); /********************************************************************* * combo class descriptor @@ -67,7 +67,7 @@ const struct builtin_class_descr COMBO_builtin_class = "ComboBox", /* name */ CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, /* style */ ComboWndProcA, /* procA */ - NULL, /* procW (FIXME) */ + ComboWndProcW, /* procW */ sizeof(HEADCOMBO *), /* extra */ IDC_ARROWA, /* cursor */ 0 /* brush */ @@ -87,13 +87,13 @@ static BOOL COMBO_Init() if( (hDC = CreateCompatibleDC(0)) ) { BOOL bRet = FALSE; - if( (hComboBmp = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_COMBO))) ) + if( (hComboBmp = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_COMBO))) ) { BITMAP bm; HBITMAP hPrevB; RECT r; - GetObjectA( hComboBmp, sizeof(bm), &bm ); + GetObjectW( hComboBmp, sizeof(bm), &bm ); CBitHeight = bm.bmHeight; CBitWidth = bm.bmWidth; @@ -114,21 +114,19 @@ static BOOL COMBO_Init() /*********************************************************************** * COMBO_NCCreate */ -static LRESULT COMBO_NCCreate(WND* wnd, LPARAM lParam) +static LRESULT COMBO_NCCreate(WND* wnd, LONG style) { LPHEADCOMBO lphc; if ( wnd && COMBO_Init() && (lphc = HeapAlloc(GetProcessHeap(), 0, sizeof(HEADCOMBO))) ) { - LPCREATESTRUCTA lpcs = (CREATESTRUCTA*)lParam; - memset( lphc, 0, sizeof(HEADCOMBO) ); *(LPHEADCOMBO*)wnd->wExtra = lphc; /* some braindead apps do try to use scrollbar/border flags */ - lphc->dwStyle = (lpcs->style & ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL)); + lphc->dwStyle = style & ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL); wnd->dwStyle &= ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL); /* @@ -137,7 +135,7 @@ static LRESULT COMBO_NCCreate(WND* wnd, LPARAM lParam) */ wnd->dwExStyle &= ~(WS_EX_CLIENTEDGE); - if( !(lpcs->style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) ) + if( !(style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) ) lphc->dwStyle |= CBS_HASSTRINGS; if( !(wnd->dwExStyle & WS_EX_NOPARENTNOTIFY) ) lphc->wState |= CBF_NOTIFY; @@ -194,7 +192,7 @@ static INT CBGetTextAreaHeight( } else { - TEXTMETRICA tm; + TEXTMETRICW tm; HDC hDC = GetDC(hwnd); HFONT hPrevFont = 0; INT baseUnitY; @@ -202,7 +200,7 @@ static INT CBGetTextAreaHeight( if (lphc->hFont) hPrevFont = SelectObject( hDC, lphc->hFont ); - GetTextMetricsA(hDC, &tm); + GetTextMetricsW(hDC, &tm); baseUnitY = tm.tmHeight; @@ -248,7 +246,7 @@ static INT CBGetTextAreaHeight( measureItem.itemWidth = clientRect.right; measureItem.itemHeight = iTextItemHeight - 6; /* ownerdrawn cb is taller */ measureItem.itemData = 0; - SendMessageA(lphc->owner, WM_MEASUREITEM, + SendMessageW(lphc->owner, WM_MEASUREITEM, (WPARAM)measureItem.CtlID, (LPARAM)&measureItem); iTextItemHeight = 6 + measureItem.itemHeight; @@ -264,7 +262,7 @@ static INT CBGetTextAreaHeight( measureItem.itemWidth = clientRect.right; measureItem.itemHeight = originalItemHeight; measureItem.itemData = 0; - SendMessageA(lphc->owner, WM_MEASUREITEM, + SendMessageW(lphc->owner, WM_MEASUREITEM, (WPARAM)measureItem.CtlID, (LPARAM)&measureItem); lphc->fixedOwnerDrawHeight = measureItem.itemHeight; } @@ -481,18 +479,16 @@ static LRESULT COMBO_WindowPosChanging( /*********************************************************************** * COMBO_Create */ -static LRESULT COMBO_Create( LPHEADCOMBO lphc, WND* wnd, LPARAM lParam) +static LRESULT COMBO_Create( LPHEADCOMBO lphc, WND* wnd, HWND hwndParent, LONG style ) { - static char clbName[] = "ComboLBox"; - static char editName[] = "Edit"; + static const WCHAR clbName[] = {'C','o','m','b','o','L','B','o','x',0}; + static const WCHAR editName[] = {'E','d','i','t',0}; - LPCREATESTRUCTA lpcs = (CREATESTRUCTA*)lParam; - if( !CB_GETTYPE(lphc) ) lphc->dwStyle |= CBS_SIMPLE; if( CB_GETTYPE(lphc) != CBS_DROPDOWNLIST ) lphc->wState |= CBF_EDIT; lphc->self = wnd; - lphc->owner = lpcs->hwndParent; + lphc->owner = hwndParent; /* * The item height and dropped width are not set when the control @@ -507,7 +503,7 @@ static LRESULT COMBO_Create( LPHEADCOMBO lphc, WND* wnd, LPARAM lParam) /* M$ IE 3.01 actually creates (and rapidly destroys) an ownerless combobox */ - if( lphc->owner || !(lpcs->style & WS_VISIBLE) ) + if( lphc->owner || !(style & WS_VISIBLE) ) { UINT lbeStyle = 0; UINT lbeExStyle = 0; @@ -545,7 +541,7 @@ static LRESULT COMBO_Create( LPHEADCOMBO lphc, WND* wnd, LPARAM lParam) /* create listbox popup */ lbeStyle = (LBS_NOTIFY | WS_BORDER | WS_CLIPSIBLINGS | WS_CHILD) | - (lpcs->style & (WS_VSCROLL | CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)); + (style & (WS_VSCROLL | CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)); if( lphc->dwStyle & CBS_SORT ) lbeStyle |= LBS_SORT; @@ -571,7 +567,7 @@ static LRESULT COMBO_Create( LPHEADCOMBO lphc, WND* wnd, LPARAM lParam) } } - lphc->hWndLBox = CreateWindowExA(lbeExStyle, + lphc->hWndLBox = CreateWindowExW(lbeExStyle, clbName, NULL, lbeStyle, @@ -607,7 +603,7 @@ static LRESULT COMBO_Create( LPHEADCOMBO lphc, WND* wnd, LPARAM lParam) else if( lphc->dwStyle & CBS_UPPERCASE ) lbeStyle |= ES_UPPERCASE; - lphc->hWndEdit = CreateWindowExA(0, + lphc->hWndEdit = CreateWindowExW(0, editName, NULL, lbeStyle, @@ -746,28 +742,29 @@ static void CBPaintText( RECT rectEdit) { INT id, size = 0; - LPSTR pText = NULL; + LPWSTR pText = NULL; if( lphc->wState & CBF_NOREDRAW ) return; /* follow Windows combobox that sends a bunch of text * inquiries to its listbox while processing WM_PAINT. */ - if( (id = SendMessageA(lphc->hWndLBox, LB_GETCURSEL, 0, 0) ) != LB_ERR ) + if( (id = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0) ) != LB_ERR ) { - size = SendMessageA( lphc->hWndLBox, LB_GETTEXTLEN, id, 0); - if( (pText = HeapAlloc( GetProcessHeap(), 0, size + 1)) ) + size = SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, id, 0); + if( (pText = HeapAlloc( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR))) ) { - SendMessageA( lphc->hWndLBox, LB_GETTEXT, (WPARAM)id, (LPARAM)pText ); + SendMessageW(lphc->hWndLBox, LB_GETTEXT, (WPARAM)id, (LPARAM)pText); pText[size] = '\0'; /* just in case */ } else return; } if( lphc->wState & CBF_EDIT ) { - if( CB_HASSTRINGS(lphc) ) SetWindowTextA( lphc->hWndEdit, pText ? pText : "" ); + static const WCHAR empty_stringW[] = { 0 }; + if( CB_HASSTRINGS(lphc) ) SetWindowTextW( lphc->hWndEdit, pText ? pText : empty_stringW ); if( lphc->wState & CBF_FOCUSED ) - SendMessageA( lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1)); + SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1)); } else /* paint text field ourselves */ { @@ -821,7 +818,7 @@ static void CBPaintText( dis.itemState = itemState; dis.hDC = hdc; dis.rcItem = rectEdit; - dis.itemData = SendMessageA( lphc->hWndLBox, LB_GETITEMDATA, + dis.itemData = SendMessageW(lphc->hWndLBox, LB_GETITEMDATA, (WPARAM)id, 0 ); /* @@ -831,7 +828,7 @@ static void CBPaintText( rectEdit.left, rectEdit.top, rectEdit.right, rectEdit.bottom); - SendMessageA(lphc->owner, WM_DRAWITEM, + SendMessageW(lphc->owner, WM_DRAWITEM, lphc->self->wIDmenu, (LPARAM)&dis ); /* @@ -841,12 +838,13 @@ static void CBPaintText( } else { - ExtTextOutA( hdc, + static const WCHAR empty_stringW[] = { 0 }; + ExtTextOutW( hdc, rectEdit.left + 1, rectEdit.top + 1, ETO_OPAQUE | ETO_CLIPPED, &rectEdit, - pText ? pText : "" , size, NULL ); + pText ? pText : empty_stringW , size, NULL ); if(lphc->wState & CBF_FOCUSED && !(lphc->wState & CBF_DROPPED)) DrawFocusRect( hdc, &rectEdit ); @@ -893,7 +891,6 @@ static void CBPaintBorder( * It also returns the brush to use for the background. */ static HBRUSH COMBO_PrepareColors( - HWND hwnd, LPHEADCOMBO lphc, HDC hDC) { @@ -904,7 +901,7 @@ static HBRUSH COMBO_PrepareColors( */ if (CB_DISABLED(lphc)) { - hBkgBrush = SendMessageA( lphc->owner, WM_CTLCOLORSTATIC, + hBkgBrush = SendMessageW(lphc->owner, WM_CTLCOLORSTATIC, hDC, lphc->self->hwndSelf ); /* @@ -918,12 +915,12 @@ static HBRUSH COMBO_PrepareColors( { if (lphc->wState & CBF_EDIT) { - hBkgBrush = SendMessageA( lphc->owner, WM_CTLCOLOREDIT, + hBkgBrush = SendMessageW(lphc->owner, WM_CTLCOLOREDIT, hDC, lphc->self->hwndSelf ); } else { - hBkgBrush = SendMessageA( lphc->owner, WM_CTLCOLORLISTBOX, + hBkgBrush = SendMessageW(lphc->owner, WM_CTLCOLORLISTBOX, hDC, lphc->self->hwndSelf ); } } @@ -969,7 +966,7 @@ static LRESULT COMBO_EraseBackground( /* * Retrieve the background brush */ - hBkgBrush = COMBO_PrepareColors(hwnd, lphc, hDC); + hBkgBrush = COMBO_PrepareColors(lphc, hDC); FillRect(hDC, &clientRect, hBkgBrush); @@ -999,7 +996,7 @@ static LRESULT COMBO_Paint(LPHEADCOMBO lphc, HDC hParamDC) * Retrieve the background brush and select it in the * DC. */ - hBkgBrush = COMBO_PrepareColors(lphc->self->hwndSelf, lphc, hDC); + hBkgBrush = COMBO_PrepareColors(lphc, hDC); hPrevBrush = SelectObject( hDC, hBkgBrush ); @@ -1053,32 +1050,32 @@ static LRESULT COMBO_Paint(LPHEADCOMBO lphc, HDC hParamDC) static INT CBUpdateLBox( LPHEADCOMBO lphc, BOOL bSelect ) { INT length, idx; - LPSTR pText = NULL; + LPWSTR pText = NULL; idx = LB_ERR; length = CB_GETEDITTEXTLENGTH( lphc ); if( length > 0 ) - pText = (LPSTR) HeapAlloc( GetProcessHeap(), 0, length + 1); + pText = HeapAlloc( GetProcessHeap(), 0, (length + 1) * sizeof(WCHAR)); TRACE("\t edit text length %i\n", length ); if( pText ) { - if( length ) GetWindowTextA( lphc->hWndEdit, pText, length + 1); + if( length ) GetWindowTextW( lphc->hWndEdit, pText, length + 1); else pText[0] = '\0'; - idx = SendMessageA( lphc->hWndLBox, LB_FINDSTRING, + idx = SendMessageW(lphc->hWndLBox, LB_FINDSTRING, (WPARAM)(-1), (LPARAM)pText ); HeapFree( GetProcessHeap(), 0, pText ); } if (idx >= 0) { - SendMessageA( lphc->hWndLBox, LB_SETCURSEL, (WPARAM)(bSelect ? idx : -1), 0 ); + SendMessageW(lphc->hWndLBox, LB_SETCURSEL, (WPARAM)(bSelect ? idx : -1), 0); /* probably superfluous but Windows sends this too */ - SendMessageA( lphc->hWndLBox, LB_SETCARETINDEX, (WPARAM)(idx < 0 ? 0 : idx), 0 ); - SendMessageA( lphc->hWndLBox, LB_SETTOPINDEX, (WPARAM)(idx < 0 ? 0 : idx), 0 ); + SendMessageW(lphc->hWndLBox, LB_SETCARETINDEX, (WPARAM)(idx < 0 ? 0 : idx), 0); + SendMessageW(lphc->hWndLBox, LB_SETTOPINDEX, (WPARAM)(idx < 0 ? 0 : idx), 0); } return idx; } @@ -1091,31 +1088,33 @@ static INT CBUpdateLBox( LPHEADCOMBO lphc, BOOL bSelect ) static void CBUpdateEdit( LPHEADCOMBO lphc , INT index ) { INT length; - LPSTR pText = NULL; + LPWSTR pText = NULL; TRACE("\t %i\n", index ); if( index >= 0 ) /* got an entry */ { - length = SendMessageA( lphc->hWndLBox, LB_GETTEXTLEN, (WPARAM)index, 0); + static const WCHAR empty_stringW[] = { 0 }; + + length = SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, (WPARAM)index, 0); if( length ) { - if( (pText = (LPSTR) HeapAlloc( GetProcessHeap(), 0, length + 1)) ) + if( (pText = HeapAlloc( GetProcessHeap(), 0, (length + 1) * sizeof(WCHAR))) ) { - SendMessageA( lphc->hWndLBox, LB_GETTEXT, + SendMessageW(lphc->hWndLBox, LB_GETTEXT, (WPARAM)index, (LPARAM)pText ); } } lphc->wState |= (CBF_NOEDITNOTIFY | CBF_NOLBSELECT); - SendMessageA( lphc->hWndEdit, WM_SETTEXT, 0, pText ? (LPARAM)pText : (LPARAM)"" ); + SendMessageW(lphc->hWndEdit, WM_SETTEXT, 0, pText ? (LPARAM)pText : (LPARAM)empty_stringW); lphc->wState &= ~(CBF_NOEDITNOTIFY | CBF_NOLBSELECT); } else InvalidateRect(CB_HWND(lphc), &lphc->textRect, TRUE); if( lphc->wState & CBF_FOCUSED ) - SendMessageA( lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1) ); + SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1)); if( pText ) HeapFree( GetProcessHeap(), 0, pText ); @@ -1148,11 +1147,11 @@ static void CBDropDown( LPHEADCOMBO lphc ) } else { - lphc->droppedIndex = SendMessageA( lphc->hWndLBox, LB_GETCURSEL, 0, 0 ); + lphc->droppedIndex = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0); - SendMessageA( lphc->hWndLBox, LB_SETTOPINDEX, + SendMessageW(lphc->hWndLBox, LB_SETTOPINDEX, (WPARAM)(lphc->droppedIndex == LB_ERR ? 0 : lphc->droppedIndex), 0 ); - SendMessageA( lphc->hWndLBox, LB_CARETON, 0, 0 ); + SendMessageW(lphc->hWndLBox, LB_CARETON, 0, 0); } /* now set popup position */ @@ -1174,13 +1173,13 @@ static void CBDropDown( LPHEADCOMBO lphc ) GetWindowRect(lphc->hWndLBox, &r); if (nDroppedHeight < r.bottom - r.top) nDroppedHeight = r.bottom - r.top; - nItems = (int)SendMessageA (lphc->hWndLBox, LB_GETCOUNT, 0, 0); + nItems = (int)SendMessageW(lphc->hWndLBox, LB_GETCOUNT, 0, 0); if (nItems > 0) { int nHeight; - nHeight = (int)SendMessageA (lphc->hWndLBox, LB_GETITEMHEIGHT, 0, 0); + nHeight = (int)SendMessageW(lphc->hWndLBox, LB_GETITEMHEIGHT, 0, 0); nHeight *= nItems; if (nHeight < nDroppedHeight - COMBO_YBORDERSIZE()) @@ -1293,7 +1292,7 @@ static void COMBO_SetFocus( LPHEADCOMBO lphc ) if( !(lphc->wState & CBF_FOCUSED) ) { if( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST ) - SendMessageA( lphc->hWndLBox, LB_CARETON, 0, 0 ); + SendMessageW(lphc->hWndLBox, LB_CARETON, 0, 0); lphc->wState |= CBF_FOCUSED; @@ -1317,7 +1316,7 @@ static void COMBO_KillFocus( LPHEADCOMBO lphc ) if( IsWindow( hWnd ) ) { if( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST ) - SendMessageA( lphc->hWndLBox, LB_CARETOFF, 0, 0 ); + SendMessageW(lphc->hWndLBox, LB_CARETOFF, 0, 0); lphc->wState &= ~CBF_FOCUSED; @@ -1416,11 +1415,11 @@ static LRESULT COMBO_Command( LPHEADCOMBO lphc, WPARAM wParam, HWND hWnd ) { if( lphc->wState & CBF_EDIT ) { - INT index = SendMessageA(lphc->hWndLBox, LB_GETCURSEL, 0, 0); + INT index = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0); lphc->wState |= CBF_NOLBSELECT; CBUpdateEdit( lphc, index ); /* select text in edit, as Windows does */ - SendMessageA( lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1) ); + SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1)); } else InvalidateRect(CB_HWND(lphc), &lphc->textRect, TRUE); @@ -1455,8 +1454,7 @@ static LRESULT COMBO_Command( LPHEADCOMBO lphc, WPARAM wParam, HWND hWnd ) * * Fixup an ownerdrawn item operation and pass it up to the combobox owner. */ -static LRESULT COMBO_ItemOp( LPHEADCOMBO lphc, UINT msg, - WPARAM wParam, LPARAM lParam ) +static LRESULT COMBO_ItemOp( LPHEADCOMBO lphc, UINT msg, LPARAM lParam ) { HWND hWnd = lphc->self->hwndSelf; @@ -1486,52 +1484,84 @@ static LRESULT COMBO_ItemOp( LPHEADCOMBO lphc, UINT msg, break; } - return SendMessageA( lphc->owner, msg, lphc->self->wIDmenu, lParam ); + return SendMessageW(lphc->owner, msg, lphc->self->wIDmenu, lParam); } /*********************************************************************** * COMBO_GetText */ -static LRESULT COMBO_GetText( LPHEADCOMBO lphc, UINT N, LPSTR lpText) +static LRESULT COMBO_GetText( LPHEADCOMBO lphc, INT N, LPARAM lParam, BOOL unicode) { if( lphc->wState & CBF_EDIT ) - return SendMessageA( lphc->hWndEdit, WM_GETTEXT, - (WPARAM)N, (LPARAM)lpText ); + return unicode ? SendMessageW(lphc->hWndEdit, WM_GETTEXT, (WPARAM)N, lParam) : + SendMessageA(lphc->hWndEdit, WM_GETTEXT, (WPARAM)N, lParam); /* get it from the listbox */ if( lphc->hWndLBox ) { - INT idx = SendMessageA( lphc->hWndLBox, LB_GETCURSEL, 0, 0 ); + INT idx = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0); if( idx != LB_ERR ) { - LPSTR lpBuffer; - INT length = SendMessageA( lphc->hWndLBox, LB_GETTEXTLEN, + INT n = 0; + INT length = SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, (WPARAM)idx, 0 ); - /* 'length' is without the terminating character */ - if( length >= N ) - lpBuffer = (LPSTR) HeapAlloc( GetProcessHeap(), 0, length + 1 ); - else - lpBuffer = lpText; + if(unicode) + { + LPWSTR lpBuffer, lpText = (LPWSTR)lParam; - if( lpBuffer ) - { - INT n = SendMessageA( lphc->hWndLBox, LB_GETTEXT, - (WPARAM)idx, (LPARAM)lpBuffer ); + /* 'length' is without the terminating character */ + if(length >= N) + lpBuffer = HeapAlloc(GetProcessHeap(), 0, (length + 1) * sizeof(WCHAR)); + else + lpBuffer = lpText; - /* truncate if buffer is too short */ + if(lpBuffer) + { + n = SendMessageW(lphc->hWndLBox, LB_GETTEXT, (WPARAM)idx, (LPARAM)lpBuffer); - if( length >= N ) - { - if (N && lpText) { - if( n != LB_ERR ) memcpy( lpText, lpBuffer, (N>n) ? n+1 : N-1 ); - lpText[N - 1] = '\0'; + /* truncate if buffer is too short */ + if(length >= N) + { + if(N && lpText) + { + if(n != LB_ERR) + strncpyW(lpText, lpBuffer, (N > n) ? n+1 : N-1); + lpText[N - 1] = '\0'; + } } HeapFree( GetProcessHeap(), 0, lpBuffer ); } - return (LRESULT)n; } + else + { + LPSTR lpBuffer, lpText = (LPSTR)lParam; + + /* 'length' is without the terminating character */ + if(length >= N) + lpBuffer = HeapAlloc(GetProcessHeap(), 0, length + 1); + else + lpBuffer = lpText; + + if(lpBuffer) + { + n = SendMessageA(lphc->hWndLBox, LB_GETTEXT, (WPARAM)idx, (LPARAM)lpBuffer); + + /* truncate if buffer is too short */ + if(length >= N) + { + if(N && lpText) + { + if(n != LB_ERR) + strncpy(lpText, lpBuffer, (N > n) ? n+1 : N-1); + lpText[N - 1] = '\0'; + } + } + HeapFree( GetProcessHeap(), 0, lpBuffer ); + } + } + return (LRESULT)n; } } return 0; @@ -1612,8 +1642,8 @@ static void COMBO_Font( LPHEADCOMBO lphc, HFONT hFont, BOOL bRedraw ) * Propagate to owned windows. */ if( lphc->wState & CBF_EDIT ) - SendMessageA( lphc->hWndEdit, WM_SETFONT, (WPARAM)hFont, bRedraw ); - SendMessageA( lphc->hWndLBox, WM_SETFONT, (WPARAM)hFont, bRedraw ); + SendMessageW(lphc->hWndEdit, WM_SETFONT, (WPARAM)hFont, bRedraw); + SendMessageW(lphc->hWndLBox, WM_SETFONT, (WPARAM)hFont, bRedraw); /* * Redo the layout of the control. @@ -1670,7 +1700,7 @@ static LRESULT COMBO_SetItemHeight( LPHEADCOMBO lphc, INT index, INT height ) } } else if ( CB_OWNERDRAWN(lphc) ) /* set listbox item height */ - lRet = SendMessageA( lphc->hWndLBox, LB_SETITEMHEIGHT, + lRet = SendMessageW(lphc->hWndLBox, LB_SETITEMHEIGHT, (WPARAM)index, (LPARAM)height ); return lRet; } @@ -1678,10 +1708,10 @@ static LRESULT COMBO_SetItemHeight( LPHEADCOMBO lphc, INT index, INT height ) /*********************************************************************** * COMBO_SelectString */ -static LRESULT COMBO_SelectString( LPHEADCOMBO lphc, INT start, LPCSTR pText ) +static LRESULT COMBO_SelectString( LPHEADCOMBO lphc, INT start, LPARAM pText, BOOL unicode ) { - INT index = SendMessageA( lphc->hWndLBox, LB_SELECTSTRING, - (WPARAM)start, (LPARAM)pText ); + INT index = unicode ? SendMessageW(lphc->hWndLBox, LB_SELECTSTRING, (WPARAM)start, pText) : + SendMessageA(lphc->hWndLBox, LB_SELECTSTRING, (WPARAM)start, pText); if( index >= 0 ) { if( lphc->wState & CBF_EDIT ) @@ -1742,7 +1772,7 @@ static void COMBO_LButtonDown( LPHEADCOMBO lphc, LPARAM lParam ) * * Release capture and stop tracking if needed. */ -static void COMBO_LButtonUp( LPHEADCOMBO lphc, LPARAM lParam ) +static void COMBO_LButtonUp( LPHEADCOMBO lphc ) { if( lphc->wState & CBF_CAPTURE ) { @@ -1802,7 +1832,7 @@ static void COMBO_MouseMove( LPHEADCOMBO lphc, WPARAM wParam, LPARAM lParam ) if( CB_GETTYPE(lphc) == CBS_DROPDOWN ) CBUpdateLBox( lphc, TRUE ); /* hand over pointer tracking */ - SendMessageA( lphc->hWndLBox, WM_LBUTTONDOWN, wParam, lParam ); + SendMessageW(lphc->hWndLBox, WM_LBUTTONDOWN, wParam, lParam); } } @@ -1812,8 +1842,8 @@ static void COMBO_MouseMove( LPHEADCOMBO lphc, WPARAM wParam, LPARAM lParam ) * * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/ctrl/src/combobox_15.htm */ -static inline LRESULT WINAPI ComboWndProc_locked( WND* pWnd, UINT message, - WPARAM wParam, LPARAM lParam ) +static LRESULT ComboWndProc_locked( WND* pWnd, UINT message, + WPARAM wParam, LPARAM lParam, BOOL unicode ) { if( pWnd ) { LPHEADCOMBO lphc = CB_GETPTR(pWnd); @@ -1829,13 +1859,31 @@ static inline LRESULT WINAPI ComboWndProc_locked( WND* pWnd, UINT message, /* System messages */ case WM_NCCREATE: - return COMBO_NCCreate(pWnd, lParam); + { + LONG style = unicode ? ((LPCREATESTRUCTW)lParam)->style : + ((LPCREATESTRUCTA)lParam)->style; + return COMBO_NCCreate(pWnd, style); + } case WM_NCDESTROY: COMBO_NCDestroy(lphc); break;/* -> DefWindowProc */ case WM_CREATE: - return COMBO_Create(lphc, pWnd, lParam); + { + HWND hwndParent; + LONG style; + if(unicode) + { + hwndParent = ((LPCREATESTRUCTW)lParam)->hwndParent; + style = ((LPCREATESTRUCTW)lParam)->style; + } + else + { + hwndParent = ((LPCREATESTRUCTA)lParam)->hwndParent; + style = ((LPCREATESTRUCTA)lParam)->style; + } + return COMBO_Create(lphc, pWnd, hwndParent, style); + } case WM_PRINTCLIENT: if (lParam & PRF_ERASEBKGND) @@ -1893,21 +1941,22 @@ static inline LRESULT WINAPI ComboWndProc_locked( WND* pWnd, UINT message, case WM_COMMAND: return COMBO_Command( lphc, wParam, (HWND)lParam ); case WM_GETTEXT: - return COMBO_GetText( lphc, (UINT)wParam, (LPSTR)lParam ); + return COMBO_GetText( lphc, (INT)wParam, lParam, unicode ); case WM_SETTEXT: case WM_GETTEXTLENGTH: case WM_CLEAR: if ((message == WM_GETTEXTLENGTH) && !ISWIN31 && !(lphc->wState & CBF_EDIT)) { - int j = SendMessageA( lphc->hWndLBox, LB_GETCURSEL, 0, 0 ); + int j = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0); if (j == -1) return 0; - return SendMessageA( lphc->hWndLBox, LB_GETTEXTLEN, j, 0); + return SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, j, 0); } else if( lphc->wState & CBF_EDIT ) { LRESULT ret; lphc->wState |= CBF_NOEDITNOTIFY; - ret = SendMessageA( lphc->hWndEdit, message, wParam, lParam ); + ret = unicode ? SendMessageW(lphc->hWndEdit, message, wParam, lParam) : + SendMessageA(lphc->hWndEdit, message, wParam, lParam); lphc->wState &= ~CBF_NOEDITNOTIFY; return ret; } @@ -1916,14 +1965,17 @@ static inline LRESULT WINAPI ComboWndProc_locked( WND* pWnd, UINT message, case WM_PASTE: case WM_COPY: if( lphc->wState & CBF_EDIT ) - return SendMessageA( lphc->hWndEdit, message, wParam, lParam ); + { + return unicode ? SendMessageW(lphc->hWndEdit, message, wParam, lParam) : + SendMessageA(lphc->hWndEdit, message, wParam, lParam); + } else return CB_ERR; case WM_DRAWITEM: case WM_DELETEITEM: case WM_COMPAREITEM: case WM_MEASUREITEM: - return COMBO_ItemOp( lphc, message, wParam, lParam ); + return COMBO_ItemOp(lphc, message, lParam); case WM_ENABLE: if( lphc->wState & CBF_EDIT ) EnableWindow( lphc->hWndEdit, (BOOL)wParam ); @@ -1939,8 +1991,8 @@ static inline LRESULT WINAPI ComboWndProc_locked( WND* pWnd, UINT message, lphc->wState |= CBF_NOREDRAW; if( lphc->wState & CBF_EDIT ) - SendMessageA( lphc->hWndEdit, message, wParam, lParam ); - SendMessageA( lphc->hWndLBox, message, wParam, lParam ); + SendMessageW(lphc->hWndEdit, message, wParam, lParam); + SendMessageW(lphc->hWndLBox, message, wParam, lParam); return 0; case WM_SYSKEYDOWN: if( KEYDATA_ALT & HIWORD(lParam) ) @@ -1950,7 +2002,10 @@ static inline LRESULT WINAPI ComboWndProc_locked( WND* pWnd, UINT message, case WM_CHAR: case WM_KEYDOWN: - if (((CHAR)wParam == VK_RETURN || (CHAR)wParam == VK_ESCAPE) && + { + HWND hwndTarget; + + if ((wParam == VK_RETURN || wParam == VK_ESCAPE) && (lphc->wState & CBF_DROPPED)) { CBRollUp( lphc, (CHAR)wParam == VK_RETURN, FALSE ); @@ -1958,15 +2013,19 @@ static inline LRESULT WINAPI ComboWndProc_locked( WND* pWnd, UINT message, } if( lphc->wState & CBF_EDIT ) - return SendMessageA( lphc->hWndEdit, message, wParam, lParam ); + hwndTarget = lphc->hWndEdit; else - return SendMessageA( lphc->hWndLBox, message, wParam, lParam ); + hwndTarget = lphc->hWndLBox; + + return unicode ? SendMessageW(hwndTarget, message, wParam, lParam) : + SendMessageA(hwndTarget, message, wParam, lParam); + } case WM_LBUTTONDOWN: if( !(lphc->wState & CBF_FOCUSED) ) SetFocus( lphc->self->hwndSelf ); if( lphc->wState & CBF_FOCUSED ) COMBO_LButtonDown( lphc, lParam ); return TRUE; case WM_LBUTTONUP: - COMBO_LButtonUp( lphc, lParam ); + COMBO_LButtonUp( lphc ); return TRUE; case WM_MOUSEMOVE: if( lphc->wState & CBF_CAPTURE ) @@ -1975,71 +2034,86 @@ static inline LRESULT WINAPI ComboWndProc_locked( WND* pWnd, UINT message, case WM_MOUSEWHEEL: if (wParam & (MK_SHIFT | MK_CONTROL)) - return DefWindowProcA( hwnd, message, wParam, lParam ); - if ((short) HIWORD(wParam) > 0) return SendMessageA(hwnd,WM_KEYDOWN,VK_UP,0); - if ((short) HIWORD(wParam) < 0) return SendMessageA(hwnd,WM_KEYDOWN,VK_DOWN,0); + return unicode ? DefWindowProcW(hwnd, message, wParam, lParam) : + DefWindowProcA(hwnd, message, wParam, lParam); + if (SHIWORD(wParam) > 0) return SendMessageW(hwnd, WM_KEYDOWN, VK_UP, 0); + if (SHIWORD(wParam) < 0) return SendMessageW(hwnd, WM_KEYDOWN, VK_DOWN, 0); return TRUE; /* Combo messages */ case CB_ADDSTRING16: if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)MapSL(lParam); + /* fall through */ case CB_ADDSTRING: - return SendMessageA( lphc->hWndLBox, LB_ADDSTRING, 0, lParam); + return unicode ? SendMessageW(lphc->hWndLBox, LB_ADDSTRING, 0, lParam) : + SendMessageA(lphc->hWndLBox, LB_ADDSTRING, 0, lParam); case CB_INSERTSTRING16: wParam = (INT)(INT16)wParam; if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)MapSL(lParam); + /* fall through */ case CB_INSERTSTRING: - return SendMessageA( lphc->hWndLBox, LB_INSERTSTRING, wParam, lParam); + return unicode ? SendMessageW(lphc->hWndLBox, LB_INSERTSTRING, wParam, lParam) : + SendMessageA(lphc->hWndLBox, LB_INSERTSTRING, wParam, lParam); case CB_DELETESTRING16: case CB_DELETESTRING: - return SendMessageA( lphc->hWndLBox, LB_DELETESTRING, wParam, 0); + return unicode ? SendMessageW(lphc->hWndLBox, LB_DELETESTRING, wParam, 0) : + SendMessageA(lphc->hWndLBox, LB_DELETESTRING, wParam, 0); case CB_SELECTSTRING16: wParam = (INT)(INT16)wParam; if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)MapSL(lParam); + /* fall through */ case CB_SELECTSTRING: - return COMBO_SelectString( lphc, (INT)wParam, (LPSTR)lParam ); + return COMBO_SelectString(lphc, (INT)wParam, lParam, unicode); case CB_FINDSTRING16: wParam = (INT)(INT16)wParam; if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)MapSL(lParam); + /* fall through */ case CB_FINDSTRING: - return SendMessageA( lphc->hWndLBox, LB_FINDSTRING, wParam, lParam); + return unicode ? SendMessageW(lphc->hWndLBox, LB_FINDSTRING, wParam, lParam) : + SendMessageA(lphc->hWndLBox, LB_FINDSTRING, wParam, lParam); case CB_FINDSTRINGEXACT16: wParam = (INT)(INT16)wParam; if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)MapSL(lParam); + /* fall through */ case CB_FINDSTRINGEXACT: - return SendMessageA( lphc->hWndLBox, LB_FINDSTRINGEXACT, - wParam, lParam ); + return unicode ? SendMessageW(lphc->hWndLBox, LB_FINDSTRINGEXACT, wParam, lParam) : + SendMessageA(lphc->hWndLBox, LB_FINDSTRINGEXACT, wParam, lParam); case CB_SETITEMHEIGHT16: wParam = (INT)(INT16)wParam; /* signed integer */ + /* fall through */ case CB_SETITEMHEIGHT: return COMBO_SetItemHeight( lphc, (INT)wParam, (INT)lParam); case CB_GETITEMHEIGHT16: wParam = (INT)(INT16)wParam; + /* fall through */ case CB_GETITEMHEIGHT: if( (INT)wParam >= 0 ) /* listbox item */ - return SendMessageA( lphc->hWndLBox, LB_GETITEMHEIGHT, wParam, 0); + return SendMessageW(lphc->hWndLBox, LB_GETITEMHEIGHT, wParam, 0); return CBGetTextAreaHeight(hwnd, lphc); case CB_RESETCONTENT16: case CB_RESETCONTENT: - SendMessageA( lphc->hWndLBox, LB_RESETCONTENT, 0, 0 ); + SendMessageW(lphc->hWndLBox, LB_RESETCONTENT, 0, 0); if( CB_HASSTRINGS(lphc) ) - SendMessageA( lphc->hWndEdit, WM_SETTEXT, 0, (LPARAM)"" ); + { + static const WCHAR empty_stringW[] = { 0 }; + SendMessageW(lphc->hWndEdit, WM_SETTEXT, 0, (LPARAM)empty_stringW); + } else InvalidateRect(CB_HWND(lphc), NULL, TRUE); return TRUE; case CB_INITSTORAGE: - return SendMessageA( lphc->hWndLBox, LB_INITSTORAGE, wParam, lParam); + return SendMessageW(lphc->hWndLBox, LB_INITSTORAGE, wParam, lParam); case CB_GETHORIZONTALEXTENT: - return SendMessageA( lphc->hWndLBox, LB_GETHORIZONTALEXTENT, 0, 0); + return SendMessageW(lphc->hWndLBox, LB_GETHORIZONTALEXTENT, 0, 0); case CB_SETHORIZONTALEXTENT: - return SendMessageA( lphc->hWndLBox, LB_SETHORIZONTALEXTENT, wParam, 0); + return SendMessageW(lphc->hWndLBox, LB_SETHORIZONTALEXTENT, wParam, 0); case CB_GETTOPINDEX: - return SendMessageA( lphc->hWndLBox, LB_GETTOPINDEX, 0, 0); + return SendMessageW(lphc->hWndLBox, LB_GETTOPINDEX, 0, 0); case CB_GETLOCALE: - return SendMessageA( lphc->hWndLBox, LB_GETLOCALE, 0, 0); + return SendMessageW(lphc->hWndLBox, LB_GETLOCALE, 0, 0); case CB_SETLOCALE: - return SendMessageA( lphc->hWndLBox, LB_SETLOCALE, wParam, 0); + return SendMessageW(lphc->hWndLBox, LB_SETLOCALE, wParam, 0); case CB_GETDROPPEDWIDTH: if( lphc->droppedWidth ) return lphc->droppedWidth; @@ -2067,8 +2141,23 @@ static inline LRESULT WINAPI ComboWndProc_locked( WND* pWnd, UINT message, lParam = (LPARAM)MapSL(lParam); /* fall through */ case CB_DIR: - return COMBO_Directory( lphc, (UINT)wParam, - (LPSTR)lParam, (message == CB_DIR)); + { + LRESULT res; + LPSTR dir; /* temporary, until listbox is unicoded */ + if(unicode) + { + LPWSTR textW = (LPWSTR)lParam; + INT countA = WideCharToMultiByte(CP_ACP, 0, textW, -1, NULL, 0, NULL, NULL); + dir = HeapAlloc(GetProcessHeap(), 0, countA); + WideCharToMultiByte(CP_ACP, 0, textW, -1, dir, countA, NULL, NULL); + } + else + dir = (LPSTR)lParam; + res = COMBO_Directory(lphc, (UINT)wParam, dir, (message == CB_DIR)); + if(unicode) + HeapFree(GetProcessHeap(), 0, dir); + return res; + } case CB_SHOWDROPDOWN16: case CB_SHOWDROPDOWN: if( CB_GETTYPE(lphc) != CBS_SIMPLE ) @@ -2085,16 +2174,17 @@ static inline LRESULT WINAPI ComboWndProc_locked( WND* pWnd, UINT message, return TRUE; case CB_GETCOUNT16: case CB_GETCOUNT: - return SendMessageA( lphc->hWndLBox, LB_GETCOUNT, 0, 0); + return SendMessageW(lphc->hWndLBox, LB_GETCOUNT, 0, 0); case CB_GETCURSEL16: case CB_GETCURSEL: - return SendMessageA( lphc->hWndLBox, LB_GETCURSEL, 0, 0); + return SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0); case CB_SETCURSEL16: wParam = (INT)(INT16)wParam; + /* fall through */ case CB_SETCURSEL: - lParam = SendMessageA( lphc->hWndLBox, LB_SETCURSEL, wParam, 0); + lParam = SendMessageW(lphc->hWndLBox, LB_SETCURSEL, wParam, 0); if( lParam >= 0 ) - SendMessageA( lphc->hWndLBox, LB_SETTOPINDEX, wParam, 0); + SendMessageW(lphc->hWndLBox, LB_SETTOPINDEX, wParam, 0); if( lphc->wState & CBF_SELCHANGE ) { /* no LBN_SELCHANGE in this case, update manually */ @@ -2108,36 +2198,37 @@ static inline LRESULT WINAPI ComboWndProc_locked( WND* pWnd, UINT message, case CB_GETLBTEXT16: wParam = (INT)(INT16)wParam; lParam = (LPARAM)MapSL(lParam); + /* fall through */ case CB_GETLBTEXT: - return SendMessageA( lphc->hWndLBox, LB_GETTEXT, wParam, lParam); + return unicode ? SendMessageW(lphc->hWndLBox, LB_GETTEXT, wParam, lParam) : + SendMessageA(lphc->hWndLBox, LB_GETTEXT, wParam, lParam); case CB_GETLBTEXTLEN16: wParam = (INT)(INT16)wParam; + /* fall through */ case CB_GETLBTEXTLEN: - return SendMessageA( lphc->hWndLBox, LB_GETTEXTLEN, wParam, 0); + return SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, wParam, 0); case CB_GETITEMDATA16: wParam = (INT)(INT16)wParam; + /* fall through */ case CB_GETITEMDATA: - return SendMessageA( lphc->hWndLBox, LB_GETITEMDATA, wParam, 0); + return SendMessageW(lphc->hWndLBox, LB_GETITEMDATA, wParam, 0); case CB_SETITEMDATA16: wParam = (INT)(INT16)wParam; + /* fall through */ case CB_SETITEMDATA: - return SendMessageA( lphc->hWndLBox, LB_SETITEMDATA, wParam, lParam); + return SendMessageW(lphc->hWndLBox, LB_SETITEMDATA, wParam, lParam); case CB_GETEDITSEL16: wParam = lParam = 0; /* just in case */ + /* fall through */ case CB_GETEDITSEL: + /* Edit checks passed parameters itself */ if( lphc->wState & CBF_EDIT ) - { - INT a, b; - - return SendMessageA( lphc->hWndEdit, EM_GETSEL, - (wParam) ? wParam : (WPARAM)&a, - (lParam) ? lParam : (LPARAM)&b ); - } + return SendMessageW(lphc->hWndEdit, EM_GETSEL, wParam, lParam); return CB_ERR; case CB_SETEDITSEL16: case CB_SETEDITSEL: if( lphc->wState & CBF_EDIT ) - return SendMessageA( lphc->hWndEdit, EM_SETSEL, + return SendMessageW(lphc->hWndEdit, EM_SETSEL, (INT)(INT16)LOWORD(lParam), (INT)(INT16)HIWORD(lParam) ); return CB_ERR; case CB_SETEXTENDEDUI16: @@ -2158,7 +2249,8 @@ static inline LRESULT WINAPI ComboWndProc_locked( WND* pWnd, UINT message, message - WM_USER, wParam, lParam ); break; } - return DefWindowProcA(hwnd, message, wParam, lParam); + return unicode ? DefWindowProcW(hwnd, message, wParam, lParam) : + DefWindowProcA(hwnd, message, wParam, lParam); } return CB_ERR; } @@ -2172,9 +2264,20 @@ static inline LRESULT WINAPI ComboWndProc_locked( WND* pWnd, UINT message, static LRESULT WINAPI ComboWndProcA( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { WND* pWnd = WIN_FindWndPtr(hwnd); - LRESULT retvalue = ComboWndProc_locked(pWnd,message,wParam,lParam); + LRESULT retvalue = ComboWndProc_locked(pWnd, message, wParam, lParam, FALSE); WIN_ReleaseWndPtr(pWnd); return retvalue; } +/*********************************************************************** + * ComboWndProcW + */ +static LRESULT WINAPI ComboWndProcW( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) +{ + WND* pWnd = WIN_FindWndPtr(hwnd); + LRESULT retvalue = ComboWndProc_locked(pWnd, message, wParam, lParam, TRUE); + + WIN_ReleaseWndPtr(pWnd); + return retvalue; +}