Author: jimtabor
Date: Wed Dec 7 09:23:04 2011
New Revision: 54604
URL:
http://svn.reactos.org/svn/reactos?rev=54604&view=rev
Log:
[User32]
- Sync up with wine controls. See
http://www.winehq.org/pipermail/wine-cvs/ for log data.
Modified:
trunk/reactos/dll/win32/user32/CMakeLists.txt
trunk/reactos/dll/win32/user32/controls/button.c
trunk/reactos/dll/win32/user32/controls/combo.c
trunk/reactos/dll/win32/user32/controls/edit.c
trunk/reactos/dll/win32/user32/controls/listbox.c
trunk/reactos/dll/win32/user32/controls/regcontrol.c
trunk/reactos/dll/win32/user32/controls/static.c
trunk/reactos/dll/win32/user32/include/controls.h
trunk/reactos/dll/win32/user32/include/user32.h
trunk/reactos/dll/win32/user32/user32.rbuild
trunk/reactos/dll/win32/user32/windows/cursoricon.c
trunk/reactos/dll/win32/user32/windows/dialog.c
Modified: trunk/reactos/dll/win32/user32/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/CMakeList…
==============================================================================
--- trunk/reactos/dll/win32/user32/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/user32/CMakeLists.txt [iso-8859-1] Wed Dec 7 09:23:04 2011
@@ -72,7 +72,7 @@
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)
Modified: trunk/reactos/dll/win32/user32/controls/button.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/controls/…
==============================================================================
--- trunk/reactos/dll/win32/user32/controls/button.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/user32/controls/button.c [iso-8859-1] Wed Dec 7 09:23:04
2011
@@ -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 @@
#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
+ /* undocumented flags */
#define BUTTON_NSTATES 0x0F
- /* undocumented flags */
#define BUTTON_BTNPRESSED 0x40
#define BUTTON_UNKNOWN2 0x20
#define BUTTON_UNKNOWN3 0x10
@@ -103,22 +96,22 @@
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 @@
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 UINT get_button_type( LONG window_style )
{
- return (window_style & 0x0f);
+ return (window_style & BS_TYPEMASK);
}
/* paint a button of any type */
@@ -212,15 +205,6 @@
WCHAR *buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) );
if (buffer) InternalGetWindowText( hwnd, buffer, len + 1 );
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 */
@@ -313,10 +297,15 @@
/* 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 );
- }
- set_button_state( hWnd, BUTTON_UNCHECKED );
+#else
+ style = (style & ~BS_TYPEMASK) | BS_PUSHBUTTON;
+ WIN_SetStyle( hWnd, style, BS_TYPEMASK & ~style );
+#endif
+ }
+ set_button_state( hWnd, BST_UNCHECKED );
button_update_uistate( hWnd, unicode );
return 0;
@@ -389,7 +378,7 @@
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 @@
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 @@
{
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
/* "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 @@
* 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 @@
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 @@
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 @@
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 @@
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 @@
SelectObject( hDC, hOldPen );
SelectObject( hDC, hOldBrush );
SetBkMode(hDC, oldBkMode);
+ SelectClipRgn( hDC, hrgn );
+ if (hrgn) DeleteObject( hrgn );
}
/**********************************************************************
@@ -968,6 +960,7 @@
LONG state = get_button_state( hwnd );
LONG style = GetWindowLongPtrW( hwnd, GWL_STYLE );
HWND parent;
+ HRGN hrgn;
if (style & BS_PUSHLIKE)
{
@@ -983,7 +976,7 @@
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 @@
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 @@
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 @@
DrawFocusRect( hDC, &rtext );
}
}
+ SelectClipRgn( hDC, hrgn );
+ if (hrgn) DeleteObject( hrgn );
}
@@ -1097,8 +1091,8 @@
{
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 @@
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 @@
InflateRect(&rc, -7, 1);
dtFlags = BUTTON_CalcLabelRect(hwnd, hDC, &rc);
- if (dtFlags == (UINT)-1L)
- return;
-
- /* 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--;
-
- BUTTON_DrawLabel(hwnd, hDC, dtFlags, &rc);
+ 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.
+ */
+
+ /* 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);
+ }
+ SelectClipRgn( hDC, hrgn );
+ if (hrgn) DeleteObject( hrgn );
}
@@ -1164,8 +1161,6 @@
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 @@
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 @@
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 @@
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 );
+}
Modified: trunk/reactos/dll/win32/user32/controls/combo.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/controls/…
==============================================================================
--- trunk/reactos/dll/win32/user32/controls/combo.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/user32/controls/combo.c [iso-8859-1] Wed Dec 7 09:23:04 2011
@@ -751,19 +751,6 @@
!(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 @@
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 @@
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 @@
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)
Modified: trunk/reactos/dll/win32/user32/controls/edit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/controls/…
==============================================================================
--- trunk/reactos/dll/win32/user32/controls/edit.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/user32/controls/edit.c [iso-8859-1] Wed Dec 7 09:23:04 2011
@@ -85,6 +85,7 @@
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 @@
*/
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 @@
} 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 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 @@
* 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.
- *
- */
-static INT EDIT_WordBreakProc(LPWSTR s, INT index, INT count, INT action)
-{
- INT ret = 0;
-
- TRACE("s=%p, index=%d, count=%d, action=%d\n", s, index, count, action);
-
- 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;
+ * Additional we will always be breaking the full string.
+ *
+ */
+static INT EDIT_WordBreakProc(EDITSTATE *es, LPWSTR s, INT index, INT count, INT action)
+{
+ INT ret = 0;
+
+ TRACE("s=%p, index=%d, count=%d, action=%d\n", s, index, count, action);
+
+ if(!s) return 0;
+
+ 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,9 +349,108 @@
}
}
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);
+ }
}
/*********************************************************************
@@ -360,8 +464,6 @@
*/
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 @@
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 @@
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 @@
{
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 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 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 @@
*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 @@
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;
- }
- 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;
- }
- if (es->style & ES_PASSWORD)
- HeapFree(GetProcessHeap(), 0, text);
- }
- if (es->font)
- SelectObject(dc, old_font);
- ReleaseDC(es->hwndSelf, dc);
+ {
+ if (x + xoff > 0 || !es->ssa)
+ {
+ ScriptStringXtoCP(es->ssa, x+xoff, &index, &trailing);
+ if (trailing) index++;
+ }
+ else
+ index = 0;
+ }
+ 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;
+ }
+ }
return index;
}
@@ -959,22 +1027,17 @@
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 @@
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;
+ 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)
{
- 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)
+ 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)
{
- 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;
-
+ 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 @@
}
}
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 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 @@
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 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 @@
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 @@
s = es->selection_start;
e = es->selection_end;
+ EDIT_InvalidateUniscribeData(es);
if ((s == e) && !strl)
return;
@@ -2466,12 +2591,15 @@
}
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 @@
es->flags &= ~EF_UPDATE;
EDIT_NOTIFY_PARENT(es, EN_CHANGE);
}
+ EDIT_InvalidateUniscribeData(es);
}
@@ -2769,6 +2898,7 @@
SetWindowLongW( es->hwndSelf, GWL_STYLE, style & ~ES_PASSWORD );
es->style &= ~ES_PASSWORD;
}
+ EDIT_InvalidateUniscribeData(es);
EDIT_UpdateText(es, NULL, TRUE);
}
@@ -2795,6 +2925,7 @@
} // reactos r33503
memcpy(es->tabs, tabs, count * sizeof(INT));
}
+ EDIT_InvalidateUniscribeData(es);
return TRUE;
}
@@ -3125,6 +3256,7 @@
/* 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 @@
(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 @@
RECT clientRect;
es->font = font;
+ EDIT_InvalidateUniscribeData(es);
dc = GetDC(es->hwndSelf);
if (font)
old_font = SelectObject(dc, font);
@@ -3736,7 +3872,8 @@
EDIT_NOTIFY_PARENT(es, EN_CHANGE);
}
EDIT_EM_ScrollCaret(es);
- EDIT_UpdateScrollInfo(es);
+ EDIT_UpdateScrollInfo(es);
+ EDIT_InvalidateUniscribeData(es);
}
@@ -4357,9 +4494,11 @@
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;
}
Modified: trunk/reactos/dll/win32/user32/controls/listbox.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/controls/…
==============================================================================
--- trunk/reactos/dll/win32/user32/controls/listbox.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/user32/controls/listbox.c [iso-8859-1] Wed Dec 7 09:23:04
2011
@@ -540,9 +540,7 @@
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 @@
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
{
Modified: trunk/reactos/dll/win32/user32/controls/regcontrol.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/controls/…
==============================================================================
--- trunk/reactos/dll/win32/user32/controls/regcontrol.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/user32/controls/regcontrol.c [iso-8859-1] Wed Dec 7 09:23:04
2011
@@ -19,12 +19,33 @@
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;
Modified: trunk/reactos/dll/win32/user32/controls/static.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/controls/…
==============================================================================
--- trunk/reactos/dll/win32/user32/controls/static.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/user32/controls/static.c [iso-8859-1] Wed Dec 7 09:23:04
2011
@@ -105,34 +105,6 @@
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 @@
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 @@
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);
}
Modified: trunk/reactos/dll/win32/user32/include/controls.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/include/c…
==============================================================================
--- trunk/reactos/dll/win32/user32/include/controls.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/user32/include/controls.h [iso-8859-1] Wed Dec 7 09:23:04
2011
@@ -88,6 +88,8 @@
#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);
Modified: trunk/reactos/dll/win32/user32/include/user32.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/include/u…
==============================================================================
--- trunk/reactos/dll/win32/user32/include/user32.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/user32/include/user32.h [iso-8859-1] Wed Dec 7 09:23:04 2011
@@ -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>
Modified: trunk/reactos/dll/win32/user32/user32.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/user32.rb…
==============================================================================
--- trunk/reactos/dll/win32/user32/user32.rbuild [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/user32/user32.rbuild [iso-8859-1] Wed Dec 7 09:23:04 2011
@@ -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>
Modified: trunk/reactos/dll/win32/user32/windows/cursoricon.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/c…
==============================================================================
--- trunk/reactos/dll/win32/user32/windows/cursoricon.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/user32/windows/cursoricon.c [iso-8859-1] Wed Dec 7 09:23:04
2011
@@ -1453,31 +1453,31 @@
// 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
{
Modified: trunk/reactos/dll/win32/user32/windows/dialog.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/d…
==============================================================================
--- trunk/reactos/dll/win32/user32/windows/dialog.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/user32/windows/dialog.c [iso-8859-1] Wed Dec 7 09:23:04 2011
@@ -342,7 +342,9 @@
{
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 @@
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 @@
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 @@
* 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 @@
BOOL
WINAPI
EndDialog(
- HWND hDlg,
- INT_PTR nResult)
+ HWND hwnd,
+ INT_PTR retval)
{
BOOL wasEnabled = TRUE;
DIALOGINFO * dlgInfo;
HWND owner;
- if (!(dlgInfo = GETDLGINFO(hDlg)))
- {
- ERR("got invalid window handle (%p); buggy app !?\n", hDlg);
+ TRACE("%p %ld\n", hwnd, retval );
+
+ if (!(dlgInfo = GETDLGINFO(hwnd)))
+ {
+ 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;
}