Edit control: Fix margin bugs
Michael Kaufmann
hallo at michael-kaufmann.ch
Sat Jun 25 05:49:32 CDT 2005
Changelog:
- Remove the old margins from the format rectangle before adding the
new margins
- Adjust the format rectangle and repaint the control after the
margins have been set
- New tests
-------------- next part --------------
Index: dlls/user/edit.c
===================================================================
RCS file: /home/wine/wine/dlls/user/edit.c,v
retrieving revision 1.32
diff -u -r1.32 edit.c
--- dlls/user/edit.c 24 Jun 2005 11:33:23 -0000 1.32
+++ dlls/user/edit.c 24 Jun 2005 23:20:07 -0000
@@ -213,6 +213,7 @@
static void EDIT_PaintLine(EDITSTATE *es, HDC hdc, INT line, BOOL rev);
static INT EDIT_PaintText(EDITSTATE *es, HDC hdc, INT x, INT y, INT line, INT col, INT count, BOOL rev);
static void EDIT_SetCaretPos(EDITSTATE *es, INT pos, BOOL after_wrap);
+static void EDIT_AdjustFormatRect(EDITSTATE *es);
static void EDIT_SetRectNP(EDITSTATE *es, LPRECT lprc);
static void EDIT_UnlockBuffer(EDITSTATE *es, BOOL force);
static void EDIT_UpdateScrollInfo(EDITSTATE *es);
@@ -239,7 +240,7 @@
static void EDIT_EM_SetHandle(EDITSTATE *es, HLOCAL hloc);
static void EDIT_EM_SetHandle16(EDITSTATE *es, HLOCAL16 hloc);
static void EDIT_EM_SetLimitText(EDITSTATE *es, INT limit);
-static void EDIT_EM_SetMargins(EDITSTATE *es, INT action, INT left, INT right);
+static void EDIT_EM_SetMargins(EDITSTATE *es, INT action, INT left, INT right, BOOL repaint);
static void EDIT_EM_SetPasswordChar(EDITSTATE *es, WCHAR c);
static void EDIT_EM_SetSel(EDITSTATE *es, UINT start, UINT end, BOOL after_wrap);
static BOOL EDIT_EM_SetTabStops(EDITSTATE *es, INT count, LPINT tabs);
@@ -735,7 +736,7 @@
/* The following EM_xxx are new to win95 and don't exist for 16 bit */
case EM_SETMARGINS:
- EDIT_EM_SetMargins(es, (INT)wParam, (short)LOWORD(lParam), (short)HIWORD(lParam));
+ EDIT_EM_SetMargins(es, (INT)wParam, (short)LOWORD(lParam), (short)HIWORD(lParam), TRUE);
break;
case EM_GETMARGINS:
@@ -2233,41 +2234,16 @@
/*********************************************************************
*
- * EDIT_SetRectNP
+ * EDIT_AdjustFormatRect
*
- * note: this is not (exactly) the handler called on EM_SETRECTNP
- * it is also used to set the rect of a single line control
+ * Adjusts the format rectangle for the current font and the
+ * current client rectangle.
*
*/
-static void EDIT_SetRectNP(EDITSTATE *es, LPRECT rc)
+static void EDIT_AdjustFormatRect(EDITSTATE *es)
{
RECT ClientRect;
- LONG_PTR ExStyle;
-
- CopyRect(&es->format_rect, rc);
- ExStyle = GetWindowLongPtrW(es->hwndSelf, GWL_EXSTYLE);
- if ((es->style & WS_POPUP) && !(ExStyle & WS_EX_CLIENTEDGE)) {
- if (es->style & WS_BORDER) {
- INT bw = GetSystemMetrics(SM_CXBORDER) + 1;
- es->format_rect.left += bw;
- es->format_rect.right -= bw;
- if (es->line_height + 2 * bw <=
- es->format_rect.bottom - es->format_rect.top) {
- es->format_rect.top += bw;
- es->format_rect.bottom -= bw;
- }
- }
- } else {
- if (es->line_height + 2 <=
- es->format_rect.bottom - es->format_rect.top) {
- es->format_rect.top++;
- es->format_rect.bottom--;
- }
- es->format_rect.left++;
- es->format_rect.right--;
- }
- es->format_rect.left += es->left_margin;
- es->format_rect.right -= es->right_margin;
+
es->format_rect.right = max(es->format_rect.right, es->format_rect.left + es->char_width);
if (es->style & ES_MULTILINE)
{
@@ -2309,6 +2285,47 @@
/*********************************************************************
*
+ * EDIT_SetRectNP
+ *
+ * note: this is not (exactly) the handler called on EM_SETRECTNP
+ * it is also used to set the rect of a single line control
+ *
+ */
+static void EDIT_SetRectNP(EDITSTATE *es, LPRECT rc)
+{
+ LONG_PTR ExStyle;
+
+ CopyRect(&es->format_rect, rc);
+ ExStyle = GetWindowLongPtrW(es->hwndSelf, GWL_EXSTYLE);
+ if ((es->style & WS_POPUP) && !(ExStyle & WS_EX_CLIENTEDGE)) {
+ if (es->style & WS_BORDER) {
+ INT bw = GetSystemMetrics(SM_CXBORDER) + 1;
+ es->format_rect.left += bw;
+ es->format_rect.right -= bw;
+ if (es->line_height + 2 * bw <=
+ es->format_rect.bottom - es->format_rect.top) {
+ es->format_rect.top += bw;
+ es->format_rect.bottom -= bw;
+ }
+ }
+ } else {
+ if (es->line_height + 2 <=
+ es->format_rect.bottom - es->format_rect.top) {
+ es->format_rect.top++;
+ es->format_rect.bottom--;
+ }
+ es->format_rect.left++;
+ es->format_rect.right--;
+ }
+
+ es->format_rect.left += es->left_margin;
+ es->format_rect.right -= es->right_margin;
+ EDIT_AdjustFormatRect(es);
+}
+
+
+/*********************************************************************
+ *
* EDIT_UnlockBuffer
*
*/
@@ -3557,7 +3574,7 @@
*
*/
static void EDIT_EM_SetMargins(EDITSTATE *es, INT action,
- INT left, INT right)
+ INT left, INT right, BOOL repaint)
{
TEXTMETRICW tm;
INT default_left_margin = 0; /* in pixels */
@@ -3579,18 +3596,28 @@
}
if (action & EC_LEFTMARGIN) {
+ es->format_rect.left -= es->left_margin;
if (left != EC_USEFONTINFO)
es->left_margin = left;
else
es->left_margin = default_left_margin;
+ es->format_rect.left += es->left_margin;
}
if (action & EC_RIGHTMARGIN) {
+ es->format_rect.right += es->right_margin;
if (right != EC_USEFONTINFO)
es->right_margin = right;
else
es->right_margin = default_right_margin;
+ es->format_rect.right -= es->right_margin;
}
+
+ if (action & (EC_LEFTMARGIN | EC_RIGHTMARGIN)) {
+ EDIT_AdjustFormatRect(es);
+ if (repaint) EDIT_UpdateText(es, NULL, TRUE);
+ }
+
TRACE("left=%d, right=%d\n", es->left_margin, es->right_margin);
}
@@ -4005,6 +4032,8 @@
*/
static LRESULT EDIT_WM_Create(EDITSTATE *es, LPCWSTR name)
{
+ RECT clientRect;
+
TRACE("%s\n", debugstr_w(name));
/*
* To initialize some final structure members, we call some helper
@@ -4014,6 +4043,11 @@
*/
EDIT_WM_SetFont(es, 0, FALSE);
EDIT_EM_EmptyUndoBuffer(es);
+
+ /* We need to calculate the format rect
+ (applications may send EM_SETMARGINS before the control gets visible) */
+ GetClientRect(es->hwndSelf, &clientRect);
+ EDIT_SetRectNP(es, &clientRect);
if (name && *name) {
EDIT_EM_ReplaceSel(es, FALSE, name, FALSE, TRUE);
@@ -4796,7 +4830,7 @@
TEXTMETRICW tm;
HDC dc;
HFONT old_font = 0;
- RECT r;
+ RECT clientRect;
es->font = font;
dc = GetDC(es->hwndSelf);
@@ -4808,12 +4842,12 @@
if (font)
SelectObject(dc, old_font);
ReleaseDC(es->hwndSelf, dc);
+
+ /* Reset the format rect and the margins */
+ GetClientRect(es->hwndSelf, &clientRect);
+ EDIT_SetRectNP(es, &clientRect);
EDIT_EM_SetMargins(es, EC_LEFTMARGIN | EC_RIGHTMARGIN,
- EC_USEFONTINFO, EC_USEFONTINFO);
-
- /* Force the recalculation of the format rect for each font change */
- GetClientRect(es->hwndSelf, &r);
- EDIT_SetRectNP(es, &r);
+ EC_USEFONTINFO, EC_USEFONTINFO, FALSE);
if (es->style & ES_MULTILINE)
EDIT_BuildLineDefs_ML(es, 0, strlenW(es->text), 0, NULL);
Index: dlls/user/tests/edit.c
===================================================================
RCS file: /home/wine/wine/dlls/user/tests/edit.c,v
retrieving revision 1.9
diff -u -r1.9 edit.c
--- dlls/user/tests/edit.c 20 Jun 2005 14:18:03 -0000 1.9
+++ dlls/user/tests/edit.c 24 Jun 2005 23:20:08 -0000
@@ -916,6 +916,64 @@
DestroyWindow(hwEdit);
}
+static void test_margins(void)
+{
+ HWND hwEdit;
+ RECT old_rect, new_rect;
+ INT old_left_margin, old_right_margin;
+ DWORD old_margins, new_margins;
+
+ hwEdit = create_editcontrol(WS_BORDER, 0);
+
+ old_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
+ old_left_margin = LOWORD(old_margins);
+ old_right_margin = HIWORD(old_margins);
+
+ /* Check if setting the margins works */
+
+ SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN, MAKELONG(10, 0));
+ new_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
+ ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
+ ok(HIWORD(new_margins) == old_right_margin, "Wrong right margin: %d\n", HIWORD(new_margins));
+
+ SendMessage(hwEdit, EM_SETMARGINS, EC_RIGHTMARGIN, MAKELONG(0, 10));
+ new_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
+ ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
+ ok(HIWORD(new_margins) == 10, "Wrong right margin: %d\n", HIWORD(new_margins));
+
+
+ /* The size of the rectangle must decrease if we increase the margin */
+
+ SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(5, 5));
+ SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
+ SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(15, 20));
+ SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
+ ok(new_rect.left == old_rect.left + 10, "The left border of the rectangle is wrong\n");
+ ok(new_rect.right == old_rect.right - 15, "The right border of the rectangle is wrong\n");
+ ok(new_rect.top == old_rect.top, "The top border of the rectangle must not change\n");
+ ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle must not change\n");
+
+
+ /* If we set the margin to same value as the current margin,
+ the rectangle must not change */
+
+ SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
+ old_rect.left = 1;
+ old_rect.right = 99;
+ old_rect.top = 1;
+ old_rect.bottom = 99;
+ SendMessage(hwEdit, EM_SETRECT, 0, (LPARAM)&old_rect);
+ SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
+ SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
+ SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
+ ok(new_rect.left == old_rect.left, "The left border of the rectangle has changed\n");
+ ok(new_rect.right == old_rect.right, "The right border of the rectangle has changed\n");
+ ok(new_rect.top == old_rect.top, "The top border of the rectangle has changed\n");
+ ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle has changed\n");
+
+ DestroyWindow (hwEdit);
+}
+
START_TEST(edit)
{
hinst = GetModuleHandleA (NULL);
@@ -926,4 +984,5 @@
test_edit_control_2();
test_edit_control_3();
test_edit_control_4();
+ test_margins();
}
More information about the wine-patches
mailing list