- Sync up with wine controls. See http://www.winehq.org/pipermail/wine-cvs/ for log data.

svn path=/trunk/; revision=54604
This commit is contained in:
James Tabor 2011-12-07 09:23:04 +00:00
parent b069e5d538
commit 0f285fa795
12 changed files with 627 additions and 469 deletions

View file

@ -72,7 +72,7 @@ target_link_libraries(user32
win32ksys
${PSEH_LIB})
add_delay_importlibs(user32 imm32)
add_delay_importlibs(user32 imm32 usp10)
add_importlibs(user32 gdi32 advapi32 msvcrt kernel32 ntdll)
add_pch(user32 include/user32.h)
add_cd_file(TARGET user32 DESTINATION reactos/system32 FOR all)

View file

@ -31,7 +31,6 @@
* Styles
* - BS_NOTIFY: is it complete?
* - BS_RIGHTBUTTON: same as BS_LEFTTEXT
* - BS_TYPEMASK
*
* Messages
* - WM_CHAR: Checks a (manual or automatic) check box on '+' or '=', clears it on '-' key.
@ -75,14 +74,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(button);
#define UISTATE_GWL_OFFSET (HIMAGE_GWL_OFFSET+sizeof(HFONT))
#define NB_EXTRA_BYTES (UISTATE_GWL_OFFSET+sizeof(LONG))
/* Button state values */
#define BUTTON_UNCHECKED 0x00
#define BUTTON_CHECKED 0x01
#define BUTTON_3STATE 0x02
#define BUTTON_HIGHLIGHTED 0x04
#define BUTTON_HASFOCUS 0x08
#define BUTTON_NSTATES 0x0F
/* undocumented flags */
#define BUTTON_NSTATES 0x0F
#define BUTTON_BTNPRESSED 0x40
#define BUTTON_UNKNOWN2 0x20
#define BUTTON_UNKNOWN3 0x10
@ -103,22 +96,22 @@ static void UB_Paint( HWND hwnd, HDC hDC, UINT action );
static void OB_Paint( HWND hwnd, HDC hDC, UINT action );
static void BUTTON_CheckAutoRadioButton( HWND hwnd );
#define MAX_BTN_TYPE 12
#define MAX_BTN_TYPE 16
static const WORD maxCheckState[MAX_BTN_TYPE] =
{
BUTTON_UNCHECKED, /* BS_PUSHBUTTON */
BUTTON_UNCHECKED, /* BS_DEFPUSHBUTTON */
BUTTON_CHECKED, /* BS_CHECKBOX */
BUTTON_CHECKED, /* BS_AUTOCHECKBOX */
BUTTON_CHECKED, /* BS_RADIOBUTTON */
BUTTON_3STATE, /* BS_3STATE */
BUTTON_3STATE, /* BS_AUTO3STATE */
BUTTON_UNCHECKED, /* BS_GROUPBOX */
BUTTON_UNCHECKED, /* BS_USERBUTTON */
BUTTON_CHECKED, /* BS_AUTORADIOBUTTON */
BUTTON_UNCHECKED, /* Not defined */
BUTTON_UNCHECKED /* BS_OWNERDRAW */
BST_UNCHECKED, /* BS_PUSHBUTTON */
BST_UNCHECKED, /* BS_DEFPUSHBUTTON */
BST_CHECKED, /* BS_CHECKBOX */
BST_CHECKED, /* BS_AUTOCHECKBOX */
BST_CHECKED, /* BS_RADIOBUTTON */
BST_INDETERMINATE, /* BS_3STATE */
BST_INDETERMINATE, /* BS_AUTO3STATE */
BST_UNCHECKED, /* BS_GROUPBOX */
BST_UNCHECKED, /* BS_USERBUTTON */
BST_CHECKED, /* BS_AUTORADIOBUTTON */
BST_UNCHECKED, /* BS_PUSHBOX */
BST_UNCHECKED /* BS_OWNERDRAW */
};
typedef void (*pfPaint)( HWND hwnd, HDC hdc, UINT action );
@ -135,7 +128,7 @@ static const pfPaint btnPaintFunc[MAX_BTN_TYPE] =
GB_Paint, /* BS_GROUPBOX */
UB_Paint, /* BS_USERBUTTON */
CB_Paint, /* BS_AUTORADIOBUTTON */
NULL, /* Not defined */
NULL, /* BS_PUSHBOX */
OB_Paint /* BS_OWNERDRAW */
};
@ -191,7 +184,7 @@ static inline void set_button_font( HWND hwnd, HFONT font )
static inline UINT get_button_type( LONG window_style )
{
return (window_style & 0x0f);
return (window_style & BS_TYPEMASK);
}
/* paint a button of any type */
@ -214,15 +207,6 @@ static inline WCHAR *get_button_text( HWND hwnd )
return buffer;
}
static void setup_clipping( HWND hwnd, HDC hdc )
{
RECT rc;
GetClientRect( hwnd, &rc );
DPtoLP( hdc, (POINT *)&rc, 2 );
IntersectClipRect( hdc, rc.left, rc.top, rc.right, rc.bottom );
}
/* Retrieve the UI state for the control */
static BOOL button_update_uistate(HWND hwnd, BOOL unicode)
{
@ -313,10 +297,15 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
/* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */
if (btn_type == BS_USERBUTTON )
{
style = (style & ~0x0f) | BS_PUSHBUTTON;
#ifdef __REACTOS__
style = (style & ~BS_TYPEMASK) | BS_PUSHBUTTON;
SetWindowLongPtrW( hWnd, GWL_STYLE, style );
#else
style = (style & ~BS_TYPEMASK) | BS_PUSHBUTTON;
WIN_SetStyle( hWnd, style, BS_TYPEMASK & ~style );
#endif
}
set_button_state( hWnd, BUTTON_UNCHECKED );
set_button_state( hWnd, BST_UNCHECKED );
button_update_uistate( hWnd, unicode );
return 0;
@ -389,7 +378,7 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
if (!(state & BUTTON_BTNPRESSED)) break;
state &= BUTTON_NSTATES;
set_button_state( hWnd, state );
if (!(state & BUTTON_HIGHLIGHTED))
if (!(state & BST_PUSHED))
{
ReleaseCapture();
break;
@ -403,14 +392,14 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
switch(btn_type)
{
case BS_AUTOCHECKBOX:
SendMessageW( hWnd, BM_SETCHECK, !(state & BUTTON_CHECKED), 0 );
SendMessageW( hWnd, BM_SETCHECK, !(state & BST_CHECKED), 0 );
break;
case BS_AUTORADIOBUTTON:
SendMessageW( hWnd, BM_SETCHECK, TRUE, 0 );
break;
case BS_AUTO3STATE:
SendMessageW( hWnd, BM_SETCHECK,
(state & BUTTON_3STATE) ? 0 : ((state & 3) + 1), 0 );
(state & BST_INDETERMINATE) ? 0 : ((state & 3) + 1), 0 );
break;
}
BUTTON_NOTIFY_PARENT(hWnd, BN_CLICKED);
@ -424,7 +413,7 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
{
state &= BUTTON_NSTATES;
set_button_state( hWnd, state );
if (state & BUTTON_HIGHLIGHTED) SendMessageW( hWnd, BM_SETSTATE, FALSE, 0 );
if (state & BST_PUSHED) SendMessageW( hWnd, BM_SETSTATE, FALSE, 0 );
}
break;
@ -490,7 +479,7 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
case WM_SETFOCUS:
TRACE("WM_SETFOCUS %p\n",hWnd);
set_button_state( hWnd, get_button_state(hWnd) | BUTTON_HASFOCUS );
set_button_state( hWnd, get_button_state(hWnd) | BST_FOCUS );
paint_button( hWnd, btn_type, ODA_FOCUS );
if (style & BS_NOTIFY)
BUTTON_NOTIFY_PARENT(hWnd, BN_SETFOCUS);
@ -499,7 +488,7 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
case WM_KILLFOCUS:
TRACE("WM_KILLFOCUS %p\n",hWnd);
state = get_button_state( hWnd );
set_button_state( hWnd, state & ~BUTTON_HASFOCUS );
set_button_state( hWnd, state & ~BST_FOCUS );
paint_button( hWnd, btn_type, ODA_FOCUS );
if ((state & BUTTON_BTNPRESSED) && GetCapture() == hWnd)
@ -515,10 +504,11 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
break;
case BM_SETSTYLE:
if ((wParam & 0x0f) >= MAX_BTN_TYPE) break;
btn_type = wParam & 0x0f;
style = (style & ~0x0f) | btn_type;
if ((wParam & BS_TYPEMASK) >= MAX_BTN_TYPE) break;
btn_type = wParam & BS_TYPEMASK;
style = (style & ~BS_TYPEMASK) | btn_type;
SetWindowLongPtrW( hWnd, GWL_STYLE, style );
//WIN_SetStyle( hWnd, style, BS_TYPEMASK & ~style );
/* Only redraw if lParam flag is set.*/
if (lParam)
@ -559,16 +549,21 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
state = get_button_state( hWnd );
if ((btn_type == BS_RADIOBUTTON) || (btn_type == BS_AUTORADIOBUTTON))
{
#ifdef __REACTOS__
if (wParam) style |= WS_TABSTOP;
else style &= ~WS_TABSTOP;
SetWindowLongPtrW( hWnd, GWL_STYLE, style );
#else
if (wParam) WIN_SetStyle( hWnd, WS_TABSTOP, 0 );
else WIN_SetStyle( hWnd, 0, WS_TABSTOP );
#endif
}
if ((state & 3) != wParam)
{
set_button_state( hWnd, (state & ~3) | wParam );
paint_button( hWnd, btn_type, ODA_SELECT );
}
if ((btn_type == BS_AUTORADIOBUTTON) && (wParam == BUTTON_CHECKED) && (style & WS_CHILD))
if ((btn_type == BS_AUTORADIOBUTTON) && (wParam == BST_CHECKED) && (style & WS_CHILD))
BUTTON_CheckAutoRadioButton( hWnd );
break;
@ -578,15 +573,10 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
case BM_SETSTATE:
state = get_button_state( hWnd );
if (wParam)
{
if (state & BUTTON_HIGHLIGHTED) break;
set_button_state( hWnd, state | BUTTON_HIGHLIGHTED );
}
set_button_state( hWnd, state | BST_PUSHED );
else
{
if (!(state & BUTTON_HIGHLIGHTED)) break;
set_button_state( hWnd, state & ~BUTTON_HIGHLIGHTED );
}
set_button_state( hWnd, state & ~BST_PUSHED );
paint_button( hWnd, btn_type, ODA_SELECT );
break;
@ -642,7 +632,7 @@ static UINT BUTTON_BStoDT( DWORD style, DWORD ex_style )
/* "Convert" pushlike buttons to pushbuttons */
if (style & BS_PUSHLIKE)
style &= ~0x0F;
style &= ~BS_TYPEMASK;
if (!(style & BS_MULTILINE))
dtStyle |= DT_SINGLELINE;
@ -821,7 +811,7 @@ static void BUTTON_DrawLabel(HWND hwnd, HDC hdc, UINT dtFlags, const RECT *rc)
* I don't have Win31 on hand to verify that, so I leave it as is.
*/
if ((style & BS_PUSHLIKE) && (state & BUTTON_3STATE))
if ((style & BS_PUSHLIKE) && (state & BST_INDETERMINATE))
{
hbr = GetSysColorBrush(COLOR_GRAYTEXT);
flags |= DSS_MONO;
@ -873,8 +863,9 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action )
HFONT hFont;
LONG state = get_button_state( hwnd );
LONG style = GetWindowLongPtrW( hwnd, GWL_STYLE );
BOOL pushedState = (state & BUTTON_HIGHLIGHTED);
BOOL pushedState = (state & BST_PUSHED);
HWND parent;
HRGN hrgn;
GetClientRect( hwnd, &rc );
@ -884,7 +875,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action )
if (!parent) parent = hwnd;
GetControlColor( parent, hwnd, hDC, WM_CTLCOLORBTN);
setup_clipping( hwnd, hDC );
hrgn = set_control_clipping( hDC, &rc );
#ifdef __REACTOS__
hOldPen = SelectObject(hDC, GetStockObject(DC_PEN));
SetDCPenColor(hDC, GetSysColor(COLOR_WINDOWFRAME));
@ -916,7 +907,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action )
uState |= DFCS_PUSHED;
}
if (state & (BUTTON_CHECKED | BUTTON_3STATE))
if (state & (BST_CHECKED | BST_INDETERMINATE))
uState |= DFCS_CHECKED;
DrawFrameControl( hDC, &rc, DFC_BUTTON, uState );
@ -938,8 +929,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action )
SetTextColor( hDC, oldTxtColor );
draw_focus:
if ((action == ODA_FOCUS) ||
((action == ODA_DRAWENTIRE) && (state & BUTTON_HASFOCUS)))
if (action == ODA_FOCUS || (state & BST_FOCUS))
{
if (!(get_ui_state(hwnd) & UISF_HIDEFOCUS))
{
@ -952,6 +942,8 @@ draw_focus:
SelectObject( hDC, hOldPen );
SelectObject( hDC, hOldBrush );
SetBkMode(hDC, oldBkMode);
SelectClipRgn( hDC, hrgn );
if (hrgn) DeleteObject( hrgn );
}
/**********************************************************************
@ -968,6 +960,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
LONG state = get_button_state( hwnd );
LONG style = GetWindowLongPtrW( hwnd, GWL_STYLE );
HWND parent;
HRGN hrgn;
if (style & BS_PUSHLIKE)
{
@ -983,7 +976,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
parent = GetParent(hwnd);
if (!parent) parent = hwnd;
hBrush = GetControlColor( parent, hwnd, hDC, WM_CTLCOLORSTATIC);
setup_clipping( hwnd, hDC );
hrgn = set_control_clipping( hDC, &client );
if (style & BS_LEFTTEXT)
{
@ -1020,11 +1013,11 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
if ((get_button_type(style) == BS_RADIOBUTTON) ||
(get_button_type(style) == BS_AUTORADIOBUTTON)) flags = DFCS_BUTTONRADIO;
else if (state & BUTTON_3STATE) flags = DFCS_BUTTON3STATE;
else if (state & BST_INDETERMINATE) flags = DFCS_BUTTON3STATE;
else flags = DFCS_BUTTONCHECK;
if (state & (BUTTON_CHECKED | BUTTON_3STATE)) flags |= DFCS_CHECKED;
if (state & BUTTON_HIGHLIGHTED) flags |= DFCS_PUSHED;
if (state & (BST_CHECKED | BST_INDETERMINATE)) flags |= DFCS_CHECKED;
if (state & BST_PUSHED) flags |= DFCS_PUSHED;
if (style & WS_DISABLED) flags |= DFCS_INACTIVE;
@ -1067,8 +1060,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
BUTTON_DrawLabel(hwnd, hDC, dtFlags, &rtext);
/* ... and focus */
if ((action == ODA_FOCUS) ||
((action == ODA_DRAWENTIRE) && (state & BUTTON_HASFOCUS)))
if (action == ODA_FOCUS || (state & BST_FOCUS))
{
if (!(get_ui_state(hwnd) & UISF_HIDEFOCUS))
{
@ -1078,6 +1070,8 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
DrawFocusRect( hDC, &rtext );
}
}
SelectClipRgn( hDC, hrgn );
if (hrgn) DeleteObject( hrgn );
}
@ -1097,8 +1091,8 @@ static void BUTTON_CheckAutoRadioButton( HWND hwnd )
{
if (!sibling) break;
if ((hwnd != sibling) &&
((GetWindowLongPtrW( sibling, GWL_STYLE) & 0x0f) == BS_AUTORADIOBUTTON))
SendMessageW( sibling, BM_SETCHECK, BUTTON_UNCHECKED, 0 );
((GetWindowLongPtrW( sibling, GWL_STYLE) & BS_TYPEMASK) == BS_AUTORADIOBUTTON))
SendMessageW( sibling, BM_SETCHECK, BST_UNCHECKED, 0 );
sibling = GetNextDlgGroupItem( parent, sibling, FALSE );
} while (sibling != start);
}
@ -1117,16 +1111,17 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action )
TEXTMETRICW tm;
LONG style = GetWindowLongPtrW( hwnd, GWL_STYLE );
HWND parent;
HRGN hrgn;
if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont );
/* GroupBox acts like static control, so it sends CTLCOLORSTATIC */
parent = GetParent(hwnd);
if (!parent) parent = hwnd;
hbr = GetControlColor( parent, hwnd, hDC, WM_CTLCOLORSTATIC);
setup_clipping( hwnd, hDC );
GetClientRect( hwnd, &rc);
rcFrame = rc;
hrgn = set_control_clipping( hDC, &rc );
GetTextMetricsW (hDC, &tm);
rcFrame.top += (tm.tmHeight / 2) - 1;
@ -1135,20 +1130,22 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action )
InflateRect(&rc, -7, 1);
dtFlags = BUTTON_CalcLabelRect(hwnd, hDC, &rc);
if (dtFlags == (UINT)-1L)
return;
if (dtFlags != (UINT)-1L)
{
/* Because buttons have CS_PARENTDC class style, there is a chance
* that label will be drawn out of client rect.
* But Windows doesn't clip label's rect, so do I.
*/
/* Because buttons have CS_PARENTDC class style, there is a chance
* that label will be drawn out of client rect.
* But Windows doesn't clip label's rect, so do I.
*/
/* There is 1-pixel margin at the left, right, and bottom */
rc.left--; rc.right++; rc.bottom++;
FillRect(hDC, &rc, hbr);
rc.left++; rc.right--; rc.bottom--;
/* There is 1-pixel margin at the left, right, and bottom */
rc.left--; rc.right++; rc.bottom++;
FillRect(hDC, &rc, hbr);
rc.left++; rc.right--; rc.bottom--;
BUTTON_DrawLabel(hwnd, hDC, dtFlags, &rc);
BUTTON_DrawLabel(hwnd, hDC, dtFlags, &rc);
}
SelectClipRgn( hDC, hrgn );
if (hrgn) DeleteObject( hrgn );
}
@ -1164,8 +1161,6 @@ static void UB_Paint( HWND hwnd, HDC hDC, UINT action )
LONG state = get_button_state( hwnd );
HWND parent;
if (action == ODA_SELECT) return;
GetClientRect( hwnd, &rc);
if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont );
@ -1175,14 +1170,26 @@ static void UB_Paint( HWND hwnd, HDC hDC, UINT action )
hBrush = GetControlColor( parent, hwnd, hDC, WM_CTLCOLORBTN);
FillRect( hDC, &rc, hBrush );
if ((action == ODA_FOCUS) ||
((action == ODA_DRAWENTIRE) && (state & BUTTON_HASFOCUS)))
if (action == ODA_FOCUS || (state & BST_FOCUS))
{
if (!(get_ui_state(hwnd) & UISF_HIDEFOCUS))
DrawFocusRect( hDC, &rc );
}
BUTTON_NOTIFY_PARENT( hwnd, BN_PAINT );
switch (action)
{
case ODA_FOCUS:
BUTTON_NOTIFY_PARENT( hwnd, (state & BST_FOCUS) ? BN_SETFOCUS : BN_KILLFOCUS );
break;
case ODA_SELECT:
BUTTON_NOTIFY_PARENT( hwnd, (state & BST_PUSHED) ? BN_HILITE : BN_UNHILITE );
break;
default:
BUTTON_NOTIFY_PARENT( hwnd, BN_PAINT );
break;
}
}
@ -1197,13 +1204,14 @@ static void OB_Paint( HWND hwnd, HDC hDC, UINT action )
LONG_PTR id = GetWindowLongPtrW( hwnd, GWLP_ID );
HWND parent;
HFONT hFont, hPrevFont = 0;
HRGN hrgn;
dis.CtlType = ODT_BUTTON;
dis.CtlID = id;
dis.itemID = 0;
dis.itemAction = action;
dis.itemState = ((state & BUTTON_HASFOCUS) ? ODS_FOCUS : 0) |
((state & BUTTON_HIGHLIGHTED) ? ODS_SELECTED : 0) |
dis.itemState = ((state & BST_FOCUS) ? ODS_FOCUS : 0) |
((state & BST_PUSHED) ? ODS_SELECTED : 0) |
(IsWindowEnabled(hwnd) ? 0: ODS_DISABLED);
dis.hwndItem = hwnd;
dis.hDC = hDC;
@ -1215,8 +1223,10 @@ static void OB_Paint( HWND hwnd, HDC hDC, UINT action )
if (!parent) parent = hwnd;
GetControlColor( parent, hwnd, hDC, WM_CTLCOLORBTN);
setup_clipping( hwnd, hDC );
hrgn = set_control_clipping( hDC, &dis.rcItem );
SendMessageW( GetParent(hwnd), WM_DRAWITEM, id, (LPARAM)&dis );
if (hPrevFont) SelectObject(hDC, hPrevFont);
SelectClipRgn( hDC, hrgn );
if (hrgn) DeleteObject( hrgn );
}

View file

@ -751,19 +751,6 @@ static void CBPaintText(
!(lphc->wState & CBF_DROPPED) )
itemState |= ODS_SELECTED | ODS_FOCUS;
/*
* Save the current clip region.
* To retrieve the clip region, we need to create one "dummy"
* clip region.
*/
clipRegion = CreateRectRgnIndirect(&rectEdit);
if (GetClipRgn(hdc, clipRegion)!=1)
{
DeleteObject(clipRegion);
clipRegion=NULL;
}
if (!IsWindowEnabled(lphc->self)) itemState |= ODS_DISABLED;
dis.CtlType = ODT_COMBOBOX;
@ -774,22 +761,17 @@ static void CBPaintText(
dis.itemState = itemState;
dis.hDC = hdc;
dis.rcItem = rectEdit;
dis.itemData = SendMessageW(lphc->hWndLBox, LB_GETITEMDATA,
(WPARAM)id, 0 );
dis.itemData = SendMessageW(lphc->hWndLBox, LB_GETITEMDATA, id, 0 );
/*
* Clip the DC and have the parent draw the item.
*/
IntersectClipRect(hdc,
rectEdit.left, rectEdit.top,
rectEdit.right, rectEdit.bottom);
clipRegion = set_control_clipping( hdc, &rectEdit );
SendMessageW(lphc->owner, WM_DRAWITEM, ctlid, (LPARAM)&dis );
/*
* Reset the clipping region.
*/
SelectClipRgn(hdc, clipRegion);
SelectClipRgn( hdc, clipRegion);
if (clipRegion) DeleteObject( clipRegion );
}
else
{
@ -2153,14 +2135,24 @@ LRESULT WINAPI ComboWndProc_common( HWND hwnd, UINT message,
return SendMessageW(lphc->hWndLBox, LB_GETLOCALE, 0, 0);
case CB_SETLOCALE:
return SendMessageW(lphc->hWndLBox, LB_SETLOCALE, wParam, 0);
case CB_SETDROPPEDWIDTH:
if( (CB_GETTYPE(lphc) == CBS_SIMPLE) ||
(INT)wParam >= 32768 )
return CB_ERR;
/* new value must be higher than combobox width */
if((INT)wParam >= lphc->droppedRect.right - lphc->droppedRect.left)
lphc->droppedWidth = wParam;
else if(wParam)
lphc->droppedWidth = 0;
/* recalculate the combobox area */
CBCalcPlacement(hwnd, lphc, &lphc->textRect, &lphc->buttonRect, &lphc->droppedRect );
/* fall through */
case CB_GETDROPPEDWIDTH:
if( lphc->droppedWidth )
return lphc->droppedWidth;
return lphc->droppedRect.right - lphc->droppedRect.left;
case CB_SETDROPPEDWIDTH:
if( (CB_GETTYPE(lphc) != CBS_SIMPLE) &&
(INT)wParam < 32768 ) lphc->droppedWidth = (INT)wParam;
return CB_ERR;
case CB_GETDROPPEDCONTROLRECT:
if( lParam ) CBGetDroppedControlRect(lphc, (LPRECT)lParam );
return CB_OKAY;
@ -2233,7 +2225,7 @@ LRESULT WINAPI ComboWndProc_common( HWND hwnd, UINT message,
case CB_LIMITTEXT:
if( lphc->wState & CBF_EDIT )
return SendMessageW(lphc->hWndEdit, EM_LIMITTEXT, wParam, lParam);
break; // ReactOS!!! removed at revision 38715
return TRUE;
case WM_UPDATEUISTATE:
if (unicode)

View file

@ -85,6 +85,7 @@ typedef struct tagLINEDEF {
LINE_END ending;
INT width; /* width of the line in pixels */
INT index; /* line index into the buffer */
SCRIPT_STRING_ANALYSIS ssa; /* Uniscribe Data */
struct tagLINEDEF *next;
} LINEDEF;
@ -141,6 +142,11 @@ typedef struct
*/
UINT composition_len; /* length of composition, 0 == no composition */
int composition_start; /* the character position for the composition */
/*
* Uniscribe Data
*/
SCRIPT_LOGATTR *logAttr;
SCRIPT_STRING_ANALYSIS ssa; /* Uniscribe Data for single line controls */
} EDITSTATE;
@ -158,6 +164,7 @@ typedef struct
} while(0)
static const WCHAR empty_stringW[] = {0};
static LRESULT EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap);
/*********************************************************************
*
@ -233,6 +240,14 @@ static HBRUSH EDIT_NotifyCtlColor(EDITSTATE *es, HDC hdc)
}
static inline UINT get_text_length(EDITSTATE *es)
{
if(es->text_length == (UINT)-1)
es->text_length = strlenW(es->text);
return es->text_length;
}
/*********************************************************************
*
* EDIT_WordBreakProc
@ -242,61 +257,51 @@ static HBRUSH EDIT_NotifyCtlColor(EDITSTATE *es, HDC hdc)
* allows to be called without linebreaks between s[0] up to
* s[count - 1]. Remember it is only called
* internally, so we can decide this for ourselves.
* Additional we will always be breaking the full string.
*
*/
static INT EDIT_WordBreakProc(LPWSTR s, INT index, INT count, INT action)
static INT EDIT_WordBreakProc(EDITSTATE *es, LPWSTR s, INT index, INT count, INT action)
{
INT ret = 0;
INT ret = 0;
TRACE("s=%p, index=%d, count=%d, action=%d\n", s, index, count, action);
TRACE("s=%p, index=%d, count=%d, action=%d\n", s, index, count, action);
if(!s) return 0;
if(!s) return 0;
switch (action) {
case WB_LEFT:
if (!count)
break;
if (index)
index--;
if (s[index] == ' ') {
while (index && (s[index] == ' '))
index--;
if (index) {
while (index && (s[index] != ' '))
index--;
if (s[index] == ' ')
index++;
}
} else {
while (index && (s[index] != ' '))
index--;
if (s[index] == ' ')
index++;
}
ret = index;
break;
case WB_RIGHT:
if (!count)
break;
if (index)
index--;
if (s[index] == ' ')
while ((index < count) && (s[index] == ' ')) index++;
else {
while (s[index] && (s[index] != ' ') && (index < count))
index++;
while ((s[index] == ' ') && (index < count)) index++;
}
ret = index;
break;
case WB_ISDELIMITER:
ret = (s[index] == ' ');
break;
default:
ERR("unknown action code, please report !\n");
break;
}
return ret;
if (!es->logAttr)
{
SCRIPT_ANALYSIS psa;
memset(&psa,0,sizeof(SCRIPT_ANALYSIS));
psa.eScript = SCRIPT_UNDEFINED;
es->logAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPT_LOGATTR) * get_text_length(es));
ScriptBreak(es->text, get_text_length(es), &psa, es->logAttr);
}
switch (action) {
case WB_LEFT:
if (index)
index--;
while (index && !es->logAttr[index].fSoftBreak)
index--;
ret = index;
break;
case WB_RIGHT:
if (!count)
break;
while (s[index] && index < count && !es->logAttr[index].fSoftBreak)
index++;
ret = index;
break;
case WB_ISDELIMITER:
ret = es->logAttr[index].fWhiteSpace;
break;
default:
ERR("unknown action code, please report !\n");
break;
}
return ret;
}
@ -344,11 +349,110 @@ static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count
}
}
else
ret = EDIT_WordBreakProc(es->text + start, index, count, action);
ret = EDIT_WordBreakProc(es, es->text, index+start, count+start, action) - start;
return ret;
}
static inline void EDIT_InvalidateUniscribeData_linedef(LINEDEF *line_def)
{
if (line_def->ssa)
{
ScriptStringFree(&line_def->ssa);
line_def->ssa = NULL;
}
}
static inline void EDIT_InvalidateUniscribeData(EDITSTATE *es)
{
LINEDEF *line_def = es->first_line_def;
while (line_def)
{
EDIT_InvalidateUniscribeData_linedef(line_def);
line_def = line_def->next;
}
if (es->ssa)
{
ScriptStringFree(&es->ssa);
es->ssa = NULL;
}
}
static SCRIPT_STRING_ANALYSIS EDIT_UpdateUniscribeData_linedef(EDITSTATE *es, HDC dc, LINEDEF *line_def)
{
if (!line_def)
return NULL;
if (line_def->net_length && !line_def->ssa)
{
int index = line_def->index;
HFONT old_font = NULL;
HDC udc = dc;
SCRIPT_TABDEF tabdef;
if (!udc)
udc = GetDC(es->hwndSelf);
if (es->font)
old_font = SelectObject(udc, es->font);
tabdef.cTabStops = es->tabs_count;
tabdef.iScale = 0;
tabdef.pTabStops = es->tabs;
tabdef.iTabOrigin = 0;
ScriptStringAnalyse(udc, &es->text[index], line_def->net_length, (1.5*line_def->net_length+16), -1, SSA_LINK|SSA_FALLBACK|SSA_GLYPHS|SSA_TAB, -1, NULL, NULL, NULL, &tabdef, NULL, &line_def->ssa);
if (es->font)
SelectObject(udc, old_font);
if (udc != dc)
ReleaseDC(es->hwndSelf, udc);
}
return line_def->ssa;
}
static SCRIPT_STRING_ANALYSIS EDIT_UpdateUniscribeData(EDITSTATE *es, HDC dc, INT line)
{
LINEDEF *line_def;
if (!(es->style & ES_MULTILINE))
{
if (!es->ssa)
{
INT length = get_text_length(es);
HFONT old_font = NULL;
HDC udc = dc;
if (!udc)
udc = GetDC(es->hwndSelf);
if (es->font)
old_font = SelectObject(udc, es->font);
if (es->style & ES_PASSWORD)
ScriptStringAnalyse(udc, &es->password_char, length, (1.5*length+16), -1, SSA_LINK|SSA_FALLBACK|SSA_GLYPHS|SSA_PASSWORD, -1, NULL, NULL, NULL, NULL, NULL, &es->ssa);
else
ScriptStringAnalyse(udc, es->text, length, (1.5*length+16), -1, SSA_LINK|SSA_FALLBACK|SSA_GLYPHS, -1, NULL, NULL, NULL, NULL, NULL, &es->ssa);
if (es->font)
SelectObject(udc, old_font);
if (udc != dc)
ReleaseDC(es->hwndSelf, udc);
}
return es->ssa;
}
else
{
line_def = es->first_line_def;
while (line_def && line)
{
line_def = line_def->next;
line--;
}
return EDIT_UpdateUniscribeData_linedef(es,dc,line_def);
}
}
/*********************************************************************
*
* EDIT_BuildLineDefs_ML
@ -360,8 +464,6 @@ static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count
*/
static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta, HRGN hrgn)
{
HDC dc;
HFONT old_font = 0;
LPWSTR current_position, cp;
INT fw;
LINEDEF *current_line;
@ -375,10 +477,6 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
if (istart == iend && delta == 0)
return;
dc = GetDC(es->hwndSelf);
if (es->font)
old_font = SelectObject(dc, es->font);
previous_line = NULL;
current_line = es->first_line_def;
@ -397,7 +495,6 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
if (!current_line) /* Error occurred start is not inside previous buffer */
{
FIXME(" modification occurred outside buffer\n");
ReleaseDC(es->hwndSelf, dc);
return;
}
@ -423,9 +520,9 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
{
/* The buffer has been expanded, create a new line and
insert it into the link list */
LINEDEF *new_line = HeapAlloc(GetProcessHeap(), 0, sizeof(LINEDEF));
if (new_line == NULL) // reactos r33509
break; // reactos r33509
LINEDEF *new_line = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LINEDEF));
if (new_line == NULL) // reactos r33509
break; // reactos r33509
new_line->next = previous_line->next;
previous_line->next = new_line;
current_line = new_line;
@ -475,33 +572,69 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
current_line->net_length = cp - current_position;
}
/* Calculate line width */
current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc,
current_position, current_line->net_length,
es->tabs_count, es->tabs));
if (current_line->net_length)
{
const SIZE *sz;
EDIT_InvalidateUniscribeData_linedef(current_line);
EDIT_UpdateUniscribeData_linedef(es, NULL, current_line);
sz = ScriptString_pSize(current_line->ssa);
/* Calculate line width */
current_line->width = sz->cx;
}
else current_line->width = 0;
/* FIXME: check here for lines that are too wide even in AUTOHSCROLL (> 32767 ???) */
/* Line breaks just look back from the end and find the next break and try that. */
if (!(es->style & ES_AUTOHSCROLL)) {
if (current_line->width > fw) {
INT next = 0;
INT prev;
if (current_line->width > fw && fw > es->char_width) {
INT prev, next;
int w;
const SIZE *sz;
float d;
prev = current_line->net_length - 1;
w = current_line->net_length;
d = (float)current_line->width/(float)fw;
if (d > 1.2) d -= 0.2;
next = prev/d;
if (next >= prev) next = prev-1;
do {
prev = next;
next = EDIT_CallWordBreakProc(es, current_position - es->text,
prev + 1, current_line->net_length, WB_RIGHT);
current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc,
current_position, next, es->tabs_count, es->tabs));
} while (current_line->width <= fw);
if (!prev) { /* Didn't find a line break so force a break */
next = 0;
prev = EDIT_CallWordBreakProc(es, current_position - es->text,
next, current_line->net_length, WB_LEFT);
current_line->net_length = prev;
EDIT_InvalidateUniscribeData_linedef(current_line);
EDIT_UpdateUniscribeData_linedef(es, NULL, current_line);
sz = ScriptString_pSize(current_line->ssa);
if (sz)
current_line->width = sz->cx;
else
prev = 0;
next = prev - 1;
} while (prev && current_line->width > fw);
current_line->net_length = w;
if (prev == 0) { /* Didn't find a line break so force a break */
INT *piDx;
const INT *count;
EDIT_InvalidateUniscribeData_linedef(current_line);
EDIT_UpdateUniscribeData_linedef(es, NULL, current_line);
count = ScriptString_pcOutChars(current_line->ssa);
piDx = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * (*count));
ScriptStringGetLogicalWidths(current_line->ssa,piDx);
prev = current_line->net_length-1;
do {
prev = next;
next++;
current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc,
current_position, next, es->tabs_count, es->tabs));
} while (current_line->width <= fw);
if (!prev)
current_line->width -= piDx[prev];
prev--;
} while ( prev > 0 && current_line->width > fw);
if (prev<=0)
prev = 1;
HeapFree(GetProcessHeap(),0,piDx);
}
/* If the first line we are calculating, wrapped before istart, we must
@ -522,8 +655,14 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
current_line->net_length = prev;
current_line->ending = END_WRAP;
current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc, current_position,
current_line->net_length, es->tabs_count, es->tabs));
if (current_line->net_length > 0)
{
EDIT_UpdateUniscribeData_linedef(es, NULL, current_line);
sz = ScriptString_pSize(current_line->ssa);
current_line->width = sz->cx;
}
else current_line->width = 0;
}
else if (current_line == start_line &&
current_line->index != nstart_index &&
@ -570,6 +709,7 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
while (current_line)
{
pnext = current_line->next;
EDIT_InvalidateUniscribeData_linedef(current_line);
HeapFree(GetProcessHeap(), 0, current_line);
current_line = pnext;
es->line_count--;
@ -599,9 +739,7 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
if ((es->style & ES_CENTER) || (es->style & ES_RIGHT))
rc.left = es->format_rect.left;
else
rc.left = es->format_rect.left + (INT)LOWORD(GetTabbedTextExtentW(dc,
es->text + nstart_index, istart - nstart_index,
es->tabs_count, es->tabs)) - es->x_offset; /* Adjust for horz scroll */
rc.left = LOWORD(EDIT_EM_PosFromChar(es, nstart_index, FALSE));
rc.right = es->format_rect.right;
SetRectRgn(hrgn, rc.left, rc.top, rc.right, rc.bottom);
@ -624,40 +762,6 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
CombineRgn(hrgn, hrgn, tmphrgn, RGN_OR);
DeleteObject(tmphrgn);
}
if (es->font)
SelectObject(dc, old_font);
ReleaseDC(es->hwndSelf, dc);
}
static inline UINT get_text_length(EDITSTATE *es)
{
if(es->text_length == (UINT)-1)
es->text_length = strlenW(es->text);
return es->text_length;
}
/*********************************************************************
*
* EDIT_GetPasswordPointer_SL
*
* note: caller should free the (optionally) allocated buffer
*
*/
static LPWSTR EDIT_GetPasswordPointer_SL(EDITSTATE *es)
{
if (es->style & ES_PASSWORD) {
INT len = get_text_length(es);
LPWSTR text = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
if (text == NULL)
return NULL;
text[len] = '\0';
while(len) text[--len] = es->password_char;
return text;
} else
return es->text;
}
@ -668,27 +772,15 @@ static LPWSTR EDIT_GetPasswordPointer_SL(EDITSTATE *es)
*/
static void EDIT_CalcLineWidth_SL(EDITSTATE *es)
{
SIZE size;
LPWSTR text;
HDC dc;
HFONT old_font = 0;
text = EDIT_GetPasswordPointer_SL(es);
dc = GetDC(es->hwndSelf);
if (es->font)
old_font = SelectObject(dc, es->font);
GetTextExtentPoint32W(dc, text, strlenW(text), &size);
if (es->font)
SelectObject(dc, old_font);
ReleaseDC(es->hwndSelf, dc);
if (es->style & ES_PASSWORD)
HeapFree(GetProcessHeap(), 0, text);
es->text_width = size.cx;
EDIT_UpdateUniscribeData(es, NULL, 0);
if (es->ssa)
{
const SIZE *size;
size = ScriptString_pSize(es->ssa);
es->text_width = size->cx;
}
else
es->text_width = 0;
}
/*********************************************************************
@ -704,20 +796,19 @@ static void EDIT_CalcLineWidth_SL(EDITSTATE *es)
static INT EDIT_CharFromPos(EDITSTATE *es, INT x, INT y, LPBOOL after_wrap)
{
INT index;
HDC dc;
HFONT old_font = 0;
INT x_high = 0, x_low = 0;
if (es->style & ES_MULTILINE) {
int trailing;
INT line = (y - es->format_rect.top) / es->line_height + es->y_offset;
INT line_index = 0;
LINEDEF *line_def = es->first_line_def;
INT low, high;
EDIT_UpdateUniscribeData(es, NULL, line);
while ((line > 0) && line_def->next) {
line_index += line_def->length;
line_def = line_def->next;
line--;
}
x += es->x_offset - es->format_rect.left;
if (es->style & ES_RIGHT)
x -= (es->format_rect.right - es->format_rect.left) - line_def->width;
@ -728,39 +819,21 @@ static INT EDIT_CharFromPos(EDITSTATE *es, INT x, INT y, LPBOOL after_wrap)
*after_wrap = (line_def->ending == END_WRAP);
return line_index + line_def->net_length;
}
if (x <= 0) {
if (x <= 0 || !line_def->ssa) {
if (after_wrap)
*after_wrap = FALSE;
return line_index;
}
dc = GetDC(es->hwndSelf);
if (es->font)
old_font = SelectObject(dc, es->font);
low = line_index;
high = line_index + line_def->net_length + 1;
while (low < high - 1)
{
INT mid = (low + high) / 2;
INT x_now = LOWORD(GetTabbedTextExtentW(dc, es->text + line_index, mid - line_index, es->tabs_count, es->tabs));
if (x_now > x) {
high = mid;
x_high = x_now;
} else {
low = mid;
x_low = x_now;
}
}
if (abs(x_high - x) + 1 <= abs(x_low - x))
index = high;
else
index = low;
ScriptStringXtoCP(line_def->ssa, x , &index, &trailing);
if (trailing) index++;
index += line_index;
if (after_wrap)
*after_wrap = ((index == line_index + line_def->net_length) &&
(line_def->ending == END_WRAP));
} else {
LPWSTR text;
SIZE size;
INT xoff = 0;
INT trailing;
if (after_wrap)
*after_wrap = FALSE;
x -= es->format_rect.left;
@ -776,60 +849,55 @@ static INT EDIT_CharFromPos(EDITSTATE *es, INT x, INT y, LPBOOL after_wrap)
x -= indent / 2;
}
text = EDIT_GetPasswordPointer_SL(es);
dc = GetDC(es->hwndSelf);
if (es->font)
old_font = SelectObject(dc, es->font);
EDIT_UpdateUniscribeData(es, NULL, 0);
if (es->x_offset)
{
if (es->ssa)
{
if (es->x_offset>= get_text_length(es))
{
const SIZE *size;
size = ScriptString_pSize(es->ssa);
xoff = size->cx;
}
ScriptStringCPtoX(es->ssa, es->x_offset, FALSE, &xoff);
}
else
xoff = 0;
}
if (x < 0)
{
INT low = 0;
INT high = es->x_offset;
while (low < high - 1)
{
INT mid = (low + high) / 2;
GetTextExtentPoint32W( dc, text + mid,
es->x_offset - mid, &size );
if (size.cx > -x) {
low = mid;
x_low = size.cx;
} else {
high = mid;
x_high = size.cx;
}
}
if (abs(x_high + x) <= abs(x_low + x) + 1)
index = high;
else
index = low;
{
if (x + xoff > 0 || !es->ssa)
{
ScriptStringXtoCP(es->ssa, x+xoff, &index, &trailing);
if (trailing) index++;
}
else
index = 0;
}
else
{
INT low = es->x_offset;
INT high = get_text_length(es) + 1;
while (low < high - 1)
{
INT mid = (low + high) / 2;
GetTextExtentPoint32W( dc, text + es->x_offset,
mid - es->x_offset, &size );
if (size.cx > x) {
high = mid;
x_high = size.cx;
} else {
low = mid;
x_low = size.cx;
}
}
if (abs(x_high - x) <= abs(x_low - x) + 1)
index = high;
else
index = low;
else
{
if (x)
{
const SIZE *size = NULL;
if (es->ssa)
size = ScriptString_pSize(es->ssa);
if (!size)
index = 0;
else if (x > size->cx)
index = get_text_length(es);
else if (es->ssa)
{
ScriptStringXtoCP(es->ssa, x+xoff, &index, &trailing);
if (trailing) index++;
}
else
index = 0;
}
else
index = es->x_offset;
}
if (es->style & ES_PASSWORD)
HeapFree(GetProcessHeap(), 0, text);
}
if (es->font)
SelectObject(dc, old_font);
ReleaseDC(es->hwndSelf, dc);
return index;
}
@ -959,22 +1027,17 @@ static LRESULT EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap)
INT len = get_text_length(es);
INT l;
INT li;
INT x;
INT x = 0;
INT y = 0;
INT w;
INT lw = 0;
INT ll = 0;
HDC dc;
HFONT old_font = 0;
SIZE size;
LINEDEF *line_def;
index = min(index, len);
dc = GetDC(es->hwndSelf);
if (es->font)
old_font = SelectObject(dc, es->font);
if (es->style & ES_MULTILINE) {
l = EDIT_EM_LineFromChar(es, index);
EDIT_UpdateUniscribeData(es, NULL, l);
y = (l - es->y_offset) * es->line_height;
li = EDIT_EM_LineIndex(es, l);
if (after_wrap && (li == index) && l) {
@ -995,38 +1058,63 @@ static LRESULT EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap)
while (line_def->index != li)
line_def = line_def->next;
ll = line_def->net_length;
if (!line_def->ssa)
return 0;
lw = line_def->width;
w = es->format_rect.right - es->format_rect.left;
if (es->style & ES_RIGHT)
{
x = LOWORD(GetTabbedTextExtentW(dc, es->text + li + (index - li), ll - (index - li),
es->tabs_count, es->tabs)) - es->x_offset;
x = w - x;
}
else if (es->style & ES_CENTER)
{
x = LOWORD(GetTabbedTextExtentW(dc, es->text + li, index - li,
es->tabs_count, es->tabs)) - es->x_offset;
x += (w - lw) / 2;
}
else /* ES_LEFT */
{
x = LOWORD(GetTabbedTextExtentW(dc, es->text + li, index - li,
es->tabs_count, es->tabs)) - es->x_offset;
}
} else {
LPWSTR text = EDIT_GetPasswordPointer_SL(es);
if (index < es->x_offset) {
GetTextExtentPoint32W(dc, text + index,
es->x_offset - index, &size);
x = -size.cx;
} else {
GetTextExtentPoint32W(dc, text + es->x_offset,
index - es->x_offset, &size);
x = size.cx;
ScriptStringCPtoX(line_def->ssa, (index - 1) - li, TRUE, &x);
x -= es->x_offset;
if (es->style & ES_RIGHT)
x = w - (lw - x);
else if (es->style & ES_CENTER)
x += (w - lw) / 2;
} else {
INT xoff = 0;
INT xi = 0;
EDIT_UpdateUniscribeData(es, NULL, 0);
if (es->x_offset)
{
if (es->ssa)
{
if (es->x_offset >= get_text_length(es))
{
if (es->ssa)
{
const SIZE *size;
size = ScriptString_pSize(es->ssa);
xoff = size->cx;
}
else
xoff = 0;
}
ScriptStringCPtoX(es->ssa, es->x_offset, FALSE, &xoff);
}
else
xoff = 0;
}
if (index)
{
if (index >= get_text_length(es))
{
if (es->ssa)
{
const SIZE *size;
size = ScriptString_pSize(es->ssa);
xi = size->cx;
}
else
xi = 0;
}
else if (es->ssa)
ScriptStringCPtoX(es->ssa, index, FALSE, &xi);
else
xi = 0;
}
x = xi - xoff;
if (index >= es->x_offset) {
if (!es->x_offset && (es->style & (ES_RIGHT | ES_CENTER)))
{
w = es->format_rect.right - es->format_rect.left;
@ -1040,14 +1128,9 @@ static LRESULT EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap)
}
}
y = 0;
if (es->style & ES_PASSWORD)
HeapFree(GetProcessHeap(), 0, text);
}
x += es->format_rect.left;
y += es->format_rect.top;
if (es->font)
SelectObject(dc, old_font);
ReleaseDC(es->hwndSelf, dc);
return MAKELONG((INT16)x, (INT16)y);
}
@ -1063,20 +1146,27 @@ static LRESULT EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap)
static void EDIT_GetLineRect(EDITSTATE *es, INT line, INT scol, INT ecol, LPRECT rc)
{
INT line_index = EDIT_EM_LineIndex(es, line);
INT pt1, pt2;
if (es->style & ES_MULTILINE)
rc->top = es->format_rect.top + (line - es->y_offset) * es->line_height;
else
rc->top = es->format_rect.top;
rc->bottom = rc->top + es->line_height;
rc->left = (scol == 0) ? es->format_rect.left : (short)LOWORD(EDIT_EM_PosFromChar(es, line_index + scol, TRUE));
rc->right = (ecol == -1) ? es->format_rect.right : (short)LOWORD(EDIT_EM_PosFromChar(es, line_index + ecol, TRUE));
pt1 = (scol == 0) ? es->format_rect.left : (short)LOWORD(EDIT_EM_PosFromChar(es, line_index + scol, TRUE));
pt2 = (ecol == -1) ? es->format_rect.right : (short)LOWORD(EDIT_EM_PosFromChar(es, line_index + ecol, TRUE));
rc->right = max(pt1 , pt2);
rc->left = min(pt1, pt2);
}
static inline void text_buffer_changed(EDITSTATE *es)
{
es->text_length = (UINT)-1;
HeapFree( GetProcessHeap(), 0, es->logAttr );
es->logAttr = NULL;
EDIT_InvalidateUniscribeData(es);
}
/*********************************************************************
@ -2035,7 +2125,7 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col
ret = (INT)LOWORD(TabbedTextOutW(dc, x, y, es->text + li + col, count,
es->tabs_count, es->tabs, es->format_rect.left - es->x_offset));
} else {
LPWSTR text = EDIT_GetPasswordPointer_SL(es);
LPWSTR text = es->text;
TextOutW(dc, x, y, text + li + col, count);
GetTextExtentPoint32W(dc, text + li + col, count, &size);
ret = size.cx;
@ -2068,13 +2158,14 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col
*/
static void EDIT_PaintLine(EDITSTATE *es, HDC dc, INT line, BOOL rev)
{
INT s = es->selection_start;
INT e = es->selection_end;
INT li;
INT ll;
INT s = 0;
INT e = 0;
INT li = 0;
INT ll = 0;
INT x;
INT y;
LRESULT pos;
SCRIPT_STRING_ANALYSIS ssa;
if (es->style & ES_MULTILINE) {
INT vlc = get_vertical_line_count(es);
@ -2086,16 +2177,49 @@ static void EDIT_PaintLine(EDITSTATE *es, HDC dc, INT line, BOOL rev)
TRACE("line=%d\n", line);
ssa = EDIT_UpdateUniscribeData(es, dc, line);
pos = EDIT_EM_PosFromChar(es, EDIT_EM_LineIndex(es, line), FALSE);
x = (short)LOWORD(pos);
y = (short)HIWORD(pos);
li = EDIT_EM_LineIndex(es, line);
ll = EDIT_EM_LineLength(es, li);
s = min(es->selection_start, es->selection_end);
e = max(es->selection_start, es->selection_end);
s = min(li + ll, max(li, s));
e = min(li + ll, max(li, e));
if (rev && (s != e) &&
if (es->style & ES_MULTILINE)
{
int line_idx = line;
x = -es->x_offset;
if (es->style & ES_RIGHT || es->style & ES_CENTER)
{
LINEDEF *line_def = es->first_line_def;
int w, lw;
while (line_def && line_idx)
{
line_def = line_def->next;
line_idx--;
}
w = es->format_rect.right - es->format_rect.left;
lw = line_def->width;
if (es->style & ES_RIGHT)
x = w - (lw - x);
else if (es->style & ES_CENTER)
x += (w - lw) / 2;
}
x += es->format_rect.left;
}
if (rev)
{
li = EDIT_EM_LineIndex(es, line);
ll = EDIT_EM_LineLength(es, li);
s = min(es->selection_start, es->selection_end);
e = max(es->selection_start, es->selection_end);
s = min(li + ll, max(li, s));
e = min(li + ll, max(li, e));
}
if (ssa)
ScriptStringOut(ssa, x, y, 0, &es->format_rect, s - li, e - li, FALSE);
else if (rev && (s != e) &&
((es->flags & EF_FOCUSED) || (es->style & ES_NOHIDESEL))) {
x += EDIT_PaintText(es, dc, x, y, line, 0, s - li, FALSE);
x += EDIT_PaintText(es, dc, x, y, line, s - li, e - s, TRUE);
@ -2391,6 +2515,7 @@ static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replac
s = es->selection_start;
e = es->selection_end;
EDIT_InvalidateUniscribeData(es);
if ((s == e) && !strl)
return;
@ -2466,12 +2591,15 @@ static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replac
}
else {
INT fw = es->format_rect.right - es->format_rect.left;
EDIT_InvalidateUniscribeData(es);
EDIT_CalcLineWidth_SL(es);
/* remove chars that don't fit */
if (honor_limit && !(es->style & ES_AUTOHSCROLL) && (es->text_width > fw)) {
while ((es->text_width > fw) && s + strl >= s) {
strcpyW(es->text + s + strl - 1, es->text + s + strl);
strl--;
es->text_length = -1;
EDIT_InvalidateUniscribeData(es);
EDIT_CalcLineWidth_SL(es);
}
text_buffer_changed(es);
@ -2569,6 +2697,7 @@ static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replac
es->flags &= ~EF_UPDATE;
EDIT_NOTIFY_PARENT(es, EN_CHANGE);
}
EDIT_InvalidateUniscribeData(es);
}
@ -2769,6 +2898,7 @@ static void EDIT_EM_SetPasswordChar(EDITSTATE *es, WCHAR c)
SetWindowLongW( es->hwndSelf, GWL_STYLE, style & ~ES_PASSWORD );
es->style &= ~ES_PASSWORD;
}
EDIT_InvalidateUniscribeData(es);
EDIT_UpdateText(es, NULL, TRUE);
}
@ -2795,6 +2925,7 @@ static BOOL EDIT_EM_SetTabStops(EDITSTATE *es, INT count, const INT *tabs)
} // reactos r33503
memcpy(es->tabs, tabs, count * sizeof(INT));
}
EDIT_InvalidateUniscribeData(es);
return TRUE;
}
@ -3125,6 +3256,7 @@ static void EDIT_WM_ContextMenu(EDITSTATE *es, INT x, INT y)
/* Windows places the menu at the edit's center in this case */
GetClientRect(es->hwndSelf, &rc);
MapWindowPoints(es->hwndSelf, 0, (POINT *)&rc, 2);
//WIN_GetRectangles( es->hwndSelf, COORDS_SCREEN, NULL, &rc );
x = rc.left + (rc.right - rc.left) / 2;
y = rc.top + (rc.bottom - rc.top) / 2;
}
@ -3534,6 +3666,9 @@ static void EDIT_WM_Paint(EDITSTATE *es, HDC hdc)
(es->style & ES_NOHIDESEL));
dc = hdc ? hdc : BeginPaint(es->hwndSelf, &ps);
/* The dc we use for calcualting may not be the one we paint into.
This is the safest action. */
EDIT_InvalidateUniscribeData(es);
GetClientRect(es->hwndSelf, &rcClient);
/* get the background brush */
@ -3646,6 +3781,7 @@ static void EDIT_WM_SetFont(EDITSTATE *es, HFONT font, BOOL redraw)
RECT clientRect;
es->font = font;
EDIT_InvalidateUniscribeData(es);
dc = GetDC(es->hwndSelf);
if (font)
old_font = SelectObject(dc, font);
@ -3736,7 +3872,8 @@ static void EDIT_WM_SetText(EDITSTATE *es, LPCWSTR text, BOOL unicode)
EDIT_NOTIFY_PARENT(es, EN_CHANGE);
}
EDIT_EM_ScrollCaret(es);
EDIT_UpdateScrollInfo(es);
EDIT_UpdateScrollInfo(es);
EDIT_InvalidateUniscribeData(es);
}
@ -4357,9 +4494,11 @@ static LRESULT EDIT_WM_NCCreate(HWND hwnd, LPCREATESTRUCTW lpcs, BOOL unicode)
cleanup:
SetWindowLongPtrW(es->hwndSelf, 0, 0);
EDIT_InvalidateUniscribeData(es);
HeapFree(GetProcessHeap(), 0, es->first_line_def);
HeapFree(GetProcessHeap(), 0, es->undo_text);
if (es->hloc32W) LocalFree(es->hloc32W);
HeapFree(GetProcessHeap(), 0, es->logAttr);
HeapFree(GetProcessHeap(), 0, es);
return FALSE;
}

View file

@ -540,9 +540,7 @@ static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc, const RECT *rect,
after they are done, so a region has better to exist
else everything ends clipped */
GetClientRect(descr->self, &r);
hrgn = CreateRectRgnIndirect(&r);
SelectClipRgn( hdc, hrgn);
DeleteObject( hrgn );
hrgn = set_control_clipping( hdc, &r );
dis.CtlType = ODT_LISTBOX;
dis.CtlID = GetWindowLongPtrW( descr->self, GWLP_ID );
@ -562,6 +560,8 @@ static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc, const RECT *rect,
descr->self, index, item ? debugstr_w(item->str) : "", action,
dis.itemState, wine_dbgstr_rect(rect) );
SendMessageW(descr->owner, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis);
SelectClipRgn( hdc, hrgn );
if (hrgn) DeleteObject( hrgn );
}
else
{

View file

@ -19,12 +19,33 @@ static PFNCLIENT pfnClientA;
static PFNCLIENT pfnClientW;
static PFNCLIENTWORKER pfnClientWorker;
//
// FIXME!
// These are not "System Classes" but Global Classes that are registered
// every time a process is created, so these can be unregistered as the msdn
// documents states.
//
/***********************************************************************
* set_control_clipping
*
* Set clipping for a builtin control that uses CS_PARENTDC.
* Return the previous clip region if any.
*/
HRGN set_control_clipping( HDC hdc, const RECT *rect )
{
RECT rc = *rect;
HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
if (GetClipRgn( hdc, hrgn ) != 1)
{
DeleteObject( hrgn );
hrgn = 0;
}
DPtoLP( hdc, (POINT *)&rc, 2 );
if (GetLayout( hdc ) & LAYOUT_RTL) /* compensate for the shifting done by IntersectClipRect */
{
rc.left++;
rc.right++;
}
IntersectClipRect( hdc, rc.left, rc.top, rc.right, rc.bottom );
return hrgn;
}
static const struct
{
const struct builtin_class_descr *desc;

View file

@ -105,34 +105,6 @@ const struct builtin_class_descr STATIC_builtin_class =
0 /* brush */
};
static void setup_clipping(HWND hwnd, HDC hdc, HRGN *orig)
{
RECT rc;
HRGN hrgn;
/* Native control has always a clipping region set (this may be because
* builtin controls uses CS_PARENTDC) and an application depends on it
*/
hrgn = CreateRectRgn(0, 0, 1, 1);
if (GetClipRgn(hdc, hrgn) != 1)
{
DeleteObject(hrgn);
*orig = NULL;
} else
*orig = hrgn;
GetClientRect(hwnd, &rc);
DPtoLP(hdc, (POINT *)&rc, 2);
IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
}
static void restore_clipping(HDC hdc, HRGN hrgn)
{
SelectClipRgn(hdc, hrgn);
if (hrgn != NULL)
DeleteObject(hrgn);
}
/***********************************************************************
* STATIC_SetIcon
*
@ -314,12 +286,13 @@ static VOID STATIC_TryPaintFcn(HWND hwnd, LONG full_style)
if (!IsRectEmpty(&rc) && IsWindowVisible(hwnd) && staticPaintFunc[style])
{
HDC hdc;
HRGN hOrigClipping;
HRGN hrgn;
hdc = GetDC( hwnd );
setup_clipping(hwnd, hdc, &hOrigClipping);
hrgn = set_control_clipping( hdc, &rc );
(staticPaintFunc[style])( hwnd, hdc, full_style );
restore_clipping(hdc, hOrigClipping);
SelectClipRgn( hdc, hrgn );
if (hrgn) DeleteObject( hrgn );
ReleaseDC( hwnd, hdc );
}
}
@ -426,13 +399,15 @@ LRESULT WINAPI StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rect;
HDC hdc = wParam ? (HDC)wParam : BeginPaint(hwnd, &ps);
GetClientRect( hwnd, &rect );
if (staticPaintFunc[style])
{
HRGN hOrigClipping;
setup_clipping(hwnd, hdc, &hOrigClipping);
HRGN hrgn = set_control_clipping( hdc, &rect );
(staticPaintFunc[style])( hwnd, hdc, full_style );
restore_clipping(hdc, hOrigClipping);
SelectClipRgn( hdc, hrgn );
if (hrgn) DeleteObject( hrgn );
}
if (!wParam) EndPaint(hwnd, &ps);
}

View file

@ -88,6 +88,8 @@ extern BOOL COMBO_FlipListbox( LPHEADCOMBO, BOOL, BOOL );
#define LB_ADDSTRING_UPPER 0x1AC
#define LB_ADDSTRING_LOWER 0x1AD
HRGN set_control_clipping( HDC hdc, const RECT *rect );
LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );
LRESULT WINAPI User32DefWindowProc(HWND,UINT,WPARAM,LPARAM,BOOL);
BOOL WINAPI RegisterClientPFN(VOID);

View file

@ -22,6 +22,7 @@
#include <windowsx.h>
#include <winnls32.h>
#include <strsafe.h>
#include <usp10.h>
#include <ndk/cmfuncs.h>
#include <ndk/kefuncs.h>
#include <ndk/obfuncs.h>

View file

@ -9,6 +9,7 @@
<library>gdi32</library>
<library>advapi32</library>
<library>imm32</library>
<library>usp10</library>
<library>win32ksys</library>
<library>pseh</library>
<library>ntdll</library>

View file

@ -1453,31 +1453,31 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
// the size of the mask bitmap always determines the icon size!
width = bmpAnd.bmWidth;
height = bmpAnd.bmHeight;
if (bmpXor.bmPlanes * bmpXor.bmBitsPixel != 1)
if (bmpXor.bmPlanes * bmpXor.bmBitsPixel != 1 )
{
color = CreateBitmap( width, height, bmpXor.bmPlanes, bmpXor.bmBitsPixel, NULL );
if(!color)
{
ERR("Unable to create color bitmap!\n");
return NULL;
}
if(!color)
{
ERR("Unable to create color bitmap!\n");
return NULL;
}
mask = CreateBitmap( width, height, 1, 1, NULL );
if(!mask)
{
ERR("Unable to create mask bitmap!\n");
DeleteObject(color);
return NULL;
}
if(!mask)
{
ERR("Unable to create mask bitmap!\n");
DeleteObject(color);
return NULL;
}
}
else
{
mask = CreateBitmap( width, height * 2, 1, 1, NULL );
if(!mask)
{
ERR("Unable to create mask bitmap!\n");
return NULL;
}
}
{
mask = CreateBitmap( width, height * 2, 1, 1, NULL );
if(!mask)
{
ERR("Unable to create mask bitmap!\n");
return NULL;
}
}
}
else
{

View file

@ -342,7 +342,9 @@ static BOOL DIALOG_CreateControls32( HWND hwnd, LPCSTR template, const DLG_TEMPL
{
template = (LPCSTR)DIALOG_GetControl32( (const WORD *)template, &info,
dlgTemplate->dialogEx );
/* Is this it? */
info.style &= ~WS_POPUP;
info.style |= WS_CHILD;
if (info.style & WS_BORDER)
{
info.style &= ~WS_BORDER;
@ -405,6 +407,8 @@ static BOOL DIALOG_CreateControls32( HWND hwnd, LPCSTR template, const DLG_TEMPL
if (!hwndCtrl)
{
WARN("control %s %s creation failed\n", debugstr_w(info.className),
debugstr_w(info.windowName));
if (dlgTemplate->style & DS_NOFAILCREATE) continue;
return FALSE;
}
@ -1013,6 +1017,7 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
if (dlgProc)
{
HWND focus = GetNextDlgTabItem( hwnd, 0, FALSE );
if (!focus) focus = GetNextDlgGroupItem( hwnd, 0, FALSE );
if (SendMessageW( hwnd, WM_INITDIALOG, (WPARAM)focus, param ) && IsWindow( hwnd ) &&
((~template.style & DS_CONTROL) || (template.style & WS_VISIBLE)))
{
@ -1020,6 +1025,7 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
* WM_INITDIALOG may have changed the tab order, so find the first
* tabstop control again. */
dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE );
if (!dlgInfo->hwndFocus) dlgInfo->hwndFocus = GetNextDlgGroupItem( hwnd, 0, FALSE );
if( dlgInfo->hwndFocus )
SetFocus( dlgInfo->hwndFocus );
}
@ -1983,41 +1989,52 @@ DlgDirSelectExW(
BOOL
WINAPI
EndDialog(
HWND hDlg,
INT_PTR nResult)
HWND hwnd,
INT_PTR retval)
{
BOOL wasEnabled = TRUE;
DIALOGINFO * dlgInfo;
HWND owner;
if (!(dlgInfo = GETDLGINFO(hDlg)))
TRACE("%p %ld\n", hwnd, retval );
if (!(dlgInfo = GETDLGINFO(hwnd)))
{
ERR("got invalid window handle (%p); buggy app !?\n", hDlg);
ERR("got invalid window handle (%p); buggy app !?\n", hwnd);
return FALSE;
}
dlgInfo->idResult = nResult;
dlgInfo->idResult = retval;
dlgInfo->flags |= DF_END;
wasEnabled = (dlgInfo->flags & DF_OWNERENABLED);
if (wasEnabled && (owner = GetWindow( hDlg, GW_OWNER )))
owner = GetWindow( hwnd, GW_OWNER );
if (wasEnabled && owner)
DIALOG_EnableOwner( owner );
/* Windows sets the focus to the dialog itself in EndDialog */
if (IsChild(hDlg, GetFocus()))
SetFocus( hDlg );
if (IsChild(hwnd, GetFocus()))
SetFocus( hwnd );
/* Don't have to send a ShowWindow(SW_HIDE), just do
SetWindowPos with SWP_HIDEWINDOW as done in Windows */
SetWindowPos(hDlg, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE
SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE
| SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW);
if (hDlg == GetActiveWindow()) WinPosActivateOtherWindow( hDlg );
if (hwnd == GetActiveWindow())
{
/* If this dialog was given an owner then set the focus to that owner
even when the owner is disabled (normally when a window closes any
disabled windows cannot receive the focus). */
if (owner)
SetForegroundWindow( owner );
else
WinPosActivateOtherWindow( hwnd );
}
/* unblock dialog loop */
PostMessageA(hDlg, WM_NULL, 0, 0);
PostMessageA(hwnd, WM_NULL, 0, 0);
return TRUE;
}