mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +00:00
[User32]
- 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:
parent
b069e5d538
commit
0f285fa795
12 changed files with 627 additions and 469 deletions
|
@ -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)
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue