Commit 297716e0 authored by Dylan Smith's avatar Dylan Smith Committed by Alexandre Julliard

richedit: Made sure text is offset by formatting rectangle.

The formatting rectangle is set with EM_SETRECT, and retrieved with EM_GETRECT, so it corresponds to rcFormat in the code. This defines the area that the richedit control should draw the text so that it is offset by the top-left corner of the formatting rectangle, and clipped so that it doesn't draw past the bottom or right hand side. Thus this is important for implementing windowless richedit controls to not interfere with the rest of the window.
parent ced9bde4
......@@ -214,8 +214,9 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
}
*height = pSizeRun->member.run.nAscent + pSizeRun->member.run.nDescent;
*x = run->member.run.pt.x + sz.cx;
*y = para->member.para.pt.y + row->member.row.nBaseline + run->member.run.pt.y - pSizeRun->member.run.nAscent - ME_GetYScrollPos(editor);
*x = c.rcView.left + run->member.run.pt.x + sz.cx;
*y = c.rcView.top + para->member.para.pt.y + row->member.row.nBaseline
+ run->member.run.pt.y - pSizeRun->member.run.nAscent - ME_GetYScrollPos(editor);
ME_DestroyContext(&c, editor->hWnd);
return;
}
......@@ -236,10 +237,7 @@ ME_MoveCaret(ME_TextEditor *editor)
ME_GetCursorCoordinates(editor, &editor->pCursors[0], &x, &y, &height);
if(editor->bHaveFocus && !ME_IsSelection(editor))
{
RECT rect;
GetClientRect(editor->hWnd, &rect);
x = min(x, rect.right-2);
x = min(x, editor->rcFormat.right-1);
CreateCaret(editor->hWnd, NULL, 0, height);
SetCaretPos(x, y);
}
......@@ -922,6 +920,9 @@ static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y,
int rx = 0;
BOOL isExact = TRUE;
x -= editor->rcFormat.left;
y -= editor->rcFormat.top;
if (is_eol)
*is_eol = 0;
......@@ -1109,13 +1110,13 @@ void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum)
ME_FindPixelPos(editor, x, y, &editor->pCursors[0], &editor->bCaretAtEnd);
if (x >= editor->selofs || is_shift)
if (x >= editor->rcFormat.left || is_shift)
{
if (clickNum > 1)
{
editor->pCursors[1] = editor->pCursors[0];
if (is_shift) {
if (x >= editor->selofs)
if (x >= editor->rcFormat.left)
ME_SelectByType(editor, stWord);
else
ME_SelectByType(editor, stParagraph);
......
......@@ -2492,9 +2492,26 @@ static BOOL ME_SetCursor(ME_TextEditor *editor)
}
ScreenToClient(editor->hWnd, &pt);
if ((GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_SELECTIONBAR) &&
(pt.x < editor->selofs ||
(editor->nSelectionType == stLine && GetCapture() == editor->hWnd)))
if (editor->nSelectionType == stLine && GetCapture() == editor->hWnd) {
SetCursor(hLeft);
return TRUE;
}
if (!editor->bEmulateVersion10 /* v4.1 */ &&
pt.y < editor->rcFormat.top &&
pt.x < editor->rcFormat.left)
{
SetCursor(hLeft);
return TRUE;
}
if (pt.y < editor->rcFormat.top || pt.y > editor->rcFormat.bottom)
{
if (editor->bEmulateVersion10) /* v1.0 - 3.0 */
SetCursor(LoadCursorW(NULL, (WCHAR*)IDC_ARROW));
else /* v4.1 */
SetCursor(LoadCursorW(NULL, (WCHAR*)IDC_IBEAM));
return TRUE;
}
if (pt.x < editor->rcFormat.left)
{
SetCursor(hLeft);
return TRUE;
......@@ -2530,6 +2547,16 @@ static BOOL ME_SetCursor(ME_TextEditor *editor)
return TRUE;
}
static void ME_SetDefaultFormatRect(ME_TextEditor *editor)
{
DWORD exstyle = GetWindowLongW(editor->hWnd, GWL_EXSTYLE);
GetClientRect(editor->hWnd, &editor->rcFormat);
editor->rcFormat.top += (exstyle & WS_EX_CLIENTEDGE ? 1 : 0);
editor->rcFormat.left += 1 + editor->selofs;
editor->rcFormat.right -= 1;
}
static BOOL ME_ShowContextMenu(ME_TextEditor *editor, int x, int y)
{
CHARRANGE selrange;
......@@ -2614,6 +2641,7 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) {
ed->selofs = SELECTIONBAR_WIDTH;
else
ed->selofs = 0;
ed->bDefaultFormatRect = TRUE;
ed->nSelectionType = stPosition;
if (GetWindowLongW(hWnd, GWL_STYLE) & ES_PASSWORD)
......@@ -2961,7 +2989,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
{
/* these flags are equivalent to the ES_* counterparts */
DWORD mask = ECO_VERTICAL | ECO_AUTOHSCROLL | ECO_AUTOVSCROLL |
ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN;
ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN | ECO_SELECTIONBAR;
DWORD settings = GetWindowLongW(hWnd, GWL_STYLE) & mask;
return settings;
......@@ -2976,6 +3004,8 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN | ECO_SELECTIONBAR;
DWORD raw = GetWindowLongW(hWnd, GWL_STYLE);
DWORD settings = mask & raw;
DWORD oldSettings = settings;
DWORD changedSettings;
switch(wParam)
{
......@@ -2993,13 +3023,21 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
}
SetWindowLongW(hWnd, GWL_STYLE, (raw & ~mask) | (settings & mask));
changedSettings = oldSettings ^ settings;
if (settings & ECO_AUTOWORDSELECTION)
FIXME("ECO_AUTOWORDSELECTION not implemented yet!\n");
if (settings & ECO_SELECTIONBAR)
if (oldSettings ^ settings) {
if (settings & ECO_SELECTIONBAR) {
editor->selofs = SELECTIONBAR_WIDTH;
else
editor->rcFormat.left += SELECTIONBAR_WIDTH;
} else {
editor->selofs = 0;
ME_WrapMarkedParagraphs(editor);
editor->rcFormat.left -= SELECTIONBAR_WIDTH;
}
ME_WrapMarkedParagraphs(editor);
}
if (settings & ECO_VERTICAL)
FIXME("ECO_VERTICAL not implemented yet!\n");
......@@ -3716,9 +3754,8 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
assert(pRun->type == diRun);
pt.y = pRun->member.run.pt.y;
pt.x = pRun->member.run.pt.x + ME_PointFromChar(editor, &pRun->member.run, nOffset);
pt.y += ME_GetParagraph(pRun)->member.para.pt.y;
pt.x += editor->selofs;
pt.x++; /* for some reason native offsets x by one */
pt.y += ME_GetParagraph(pRun)->member.para.pt.y + editor->rcFormat.top;
pt.x += editor->rcFormat.left;
pt.y -= editor->vert_si.nPos;
si.cbSize = sizeof(si);
......@@ -3734,7 +3771,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
{
SCROLLINFO si;
GetClientRect(hWnd, &editor->rcFormat);
ME_SetDefaultFormatRect(editor);
if (GetWindowLongW(hWnd, GWL_STYLE) & WS_HSCROLL)
{ /* Squelch the default horizontal scrollbar it would make */
ShowScrollBar(editor->hWnd, SB_HORZ, FALSE);
......@@ -3816,9 +3853,37 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
case WM_PAINT:
{
HDC hDC;
RECT rc;
PAINTSTRUCT ps;
hDC = BeginPaint(hWnd, &ps);
/* Erase area outside of the formatting rectangle */
if (ps.rcPaint.top < editor->rcFormat.top)
{
rc = ps.rcPaint;
rc.bottom = editor->rcFormat.top;
FillRect(hDC, &rc, editor->hbrBackground);
ps.rcPaint.top = editor->rcFormat.top;
}
if (ps.rcPaint.bottom > editor->rcFormat.bottom) {
rc = ps.rcPaint;
rc.top = editor->rcFormat.bottom;
FillRect(hDC, &rc, editor->hbrBackground);
ps.rcPaint.bottom = editor->rcFormat.bottom;
}
if (ps.rcPaint.left < editor->rcFormat.left) {
rc = ps.rcPaint;
rc.right = editor->rcFormat.left;
FillRect(hDC, &rc, editor->hbrBackground);
ps.rcPaint.left = editor->rcFormat.left;
}
if (ps.rcPaint.right > editor->rcFormat.right) {
rc = ps.rcPaint;
rc.left = editor->rcFormat.right;
FillRect(hDC, &rc, editor->hbrBackground);
ps.rcPaint.right = editor->rcFormat.right;
}
ME_PaintContent(editor, hDC, FALSE, &ps.rcPaint);
EndPaint(hWnd, &ps);
}
......@@ -3940,6 +4005,8 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
case EM_GETRECT:
{
*((RECT *)lParam) = editor->rcFormat;
if (editor->bDefaultFormatRect)
((RECT *)lParam)->left -= editor->selofs;
return 0;
}
case EM_SETRECT:
......@@ -3947,23 +4014,36 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
{
if (lParam)
{
DWORD exstyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
int border = (exstyle & WS_EX_CLIENTEDGE) ? 1 : 0;
RECT clientRect;
RECT *rc = (RECT *)lParam;
if (wParam)
{
editor->rcFormat.left += rc->left;
editor->rcFormat.top += rc->top;
editor->rcFormat.right += rc->right;
editor->rcFormat.bottom += rc->bottom;
}
else
GetClientRect(hWnd, &clientRect);
if (wParam == 0)
{
editor->rcFormat = *rc;
editor->rcFormat.top = max(0, rc->top - border);
editor->rcFormat.left = max(0, rc->left - border);
editor->rcFormat.bottom = min(clientRect.bottom, rc->bottom);
editor->rcFormat.right = min(clientRect.right, rc->right + border);
} else if (wParam == 1) {
/* MSDN incorrectly says a wParam value of 1 causes the
* lParam rect to be used as a relative offset,
* however, the tests show it just prevents min/max bound
* checking. */
editor->rcFormat.top = rc->top - border;
editor->rcFormat.left = rc->left - border;
editor->rcFormat.bottom = rc->bottom;
editor->rcFormat.right = rc->right + border;
} else {
return 0;
}
editor->bDefaultFormatRect = FALSE;
}
else
{
GetClientRect(hWnd, &editor->rcFormat);
ME_SetDefaultFormatRect(editor);
editor->bDefaultFormatRect = TRUE;
}
if (msg != EM_SETRECTNP)
ME_RewrapRepaint(editor);
......@@ -3976,7 +4056,16 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
return DefWindowProcW(hWnd, msg, wParam, lParam);
case WM_SIZE:
{
GetClientRect(hWnd, &editor->rcFormat);
RECT clientRect;
GetClientRect(hWnd, &clientRect);
if (editor->bDefaultFormatRect) {
ME_SetDefaultFormatRect(editor);
} else {
editor->rcFormat.right += clientRect.right - editor->prevClientRect.right;
editor->rcFormat.bottom += clientRect.bottom - editor->prevClientRect.bottom;
}
editor->prevClientRect = clientRect;
ME_RewrapRepaint(editor);
return DefWindowProcW(hWnd, msg, wParam, lParam);
}
......
......@@ -90,7 +90,7 @@ typedef enum {
diUndoPotentialEndTransaction, /* 20 - allows grouping typed chars for undo */
} ME_DIType;
#define SELECTIONBAR_WIDTH 9
#define SELECTIONBAR_WIDTH 8
/******************************** run flags *************************/
#define MERF_STYLEFLAGS 0x0FFF
......@@ -350,7 +350,9 @@ typedef struct tagME_TextEditor
ME_DisplayItem *pLastSelStartPara, *pLastSelEndPara;
ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE];
int nZoomNumerator, nZoomDenominator;
RECT prevClientRect;
RECT rcFormat;
BOOL bDefaultFormatRect;
BOOL bWordWrap;
int nInvalidOfs;
int nTextLimit;
......
......@@ -692,7 +692,7 @@ static SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run
{
pos += lDefaultTab - (pos % lDefaultTab);
}
ppos = ME_twips2pointsX(c, pos) + c->editor->selofs;
ppos = ME_twips2pointsX(c, pos);
if (ppos > startx + run->pt.x) {
size.cx = ppos - startx - run->pt.x;
break;
......
......@@ -5854,7 +5854,7 @@ static void test_format_rect(void)
expected.left += 1;
expected.right -= 1;
SendMessageW(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
todo_wine ok(rc.top == expected.top && rc.left == expected.left &&
ok(rc.top == expected.top && rc.left == expected.left &&
rc.bottom == expected.bottom && rc.right == expected.right,
"rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
rc.top, rc.left, rc.bottom, rc.right,
......@@ -5875,18 +5875,11 @@ static void test_format_rect(void)
expected.bottom = min(clientRect.bottom, rc.bottom);
expected.right = min(clientRect.right, rc.right);
SendMessageW(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
if (n >= 0)
ok(rc.top == expected.top && rc.left == expected.left &&
rc.bottom == expected.bottom && rc.right == expected.right,
"[n=%d] rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
n, rc.top, rc.left, rc.bottom, rc.right,
expected.top, expected.left, expected.bottom, expected.right);
else
todo_wine ok(rc.top == expected.top && rc.left == expected.left &&
rc.bottom == expected.bottom && rc.right == expected.right,
"[n=%d] rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
n, rc.top, rc.left, rc.bottom, rc.right,
expected.top, expected.left, expected.bottom, expected.right);
ok(rc.top == expected.top && rc.left == expected.left &&
rc.bottom == expected.bottom && rc.right == expected.right,
"[n=%d] rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
n, rc.top, rc.left, rc.bottom, rc.right,
expected.top, expected.left, expected.bottom, expected.right);
}
rc = clientRect;
......@@ -5902,10 +5895,10 @@ static void test_format_rect(void)
/* Adding the selectionbar adds the selectionbar width to the left side. */
SendMessageW(hwnd, EM_SETOPTIONS, ECOOP_OR, ECO_SELECTIONBAR);
options = SendMessageW(hwnd, EM_GETOPTIONS, 0, 0);
todo_wine ok(options & ECO_SELECTIONBAR, "EM_SETOPTIONS failed to add selectionbar.\n");
ok(options & ECO_SELECTIONBAR, "EM_SETOPTIONS failed to add selectionbar.\n");
expected.left += 8; /* selection bar width */
SendMessageW(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
todo_wine ok(rc.top == expected.top && rc.left == expected.left &&
ok(rc.top == expected.top && rc.left == expected.left &&
rc.bottom == expected.bottom && rc.right == expected.right,
"rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
rc.top, rc.left, rc.bottom, rc.right,
......@@ -5928,7 +5921,7 @@ static void test_format_rect(void)
ok(!(options & ECO_SELECTIONBAR), "EM_SETOPTIONS failed to remove selectionbar.\n");
expected.left -= 8; /* selection bar width */
SendMessageW(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
todo_wine ok(rc.top == expected.top && rc.left == expected.left &&
ok(rc.top == expected.top && rc.left == expected.left &&
rc.bottom == expected.bottom && rc.right == expected.right,
"rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
rc.top, rc.left, rc.bottom, rc.right,
......@@ -5955,7 +5948,7 @@ static void test_format_rect(void)
expected = rc;
SendMessageW(hwnd, EM_SETRECT, 1, (LPARAM)&rc);
SendMessageW(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
todo_wine ok(rc.top == expected.top && rc.left == expected.left &&
ok(rc.top == expected.top && rc.left == expected.left &&
rc.bottom == expected.bottom && rc.right == expected.right,
"rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
rc.top, rc.left, rc.bottom, rc.right,
......@@ -5970,7 +5963,7 @@ static void test_format_rect(void)
expected = rc;
SendMessageW(hwnd, EM_SETRECT, 1, (LPARAM)&rc);
SendMessageW(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
todo_wine ok(rc.top == expected.top && rc.left == expected.left &&
ok(rc.top == expected.top && rc.left == expected.left &&
rc.bottom == expected.bottom && rc.right == expected.right,
"rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
rc.top, rc.left, rc.bottom, rc.right,
......@@ -5991,7 +5984,7 @@ static void test_format_rect(void)
expected.top += 1;
expected.right -= 1;
SendMessageW(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
todo_wine ok(rc.top == expected.top && rc.left == expected.left &&
ok(rc.top == expected.top && rc.left == expected.left &&
rc.bottom == expected.bottom && rc.right == expected.right,
"rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
rc.top, rc.left, rc.bottom, rc.right,
......@@ -6008,7 +6001,7 @@ static void test_format_rect(void)
expected.right += 1;
SendMessageW(hwnd, EM_SETRECT, 0, (LPARAM)&rc);
SendMessageW(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
todo_wine ok(rc.top == expected.top && rc.left == expected.left &&
ok(rc.top == expected.top && rc.left == expected.left &&
rc.bottom == expected.bottom && rc.right == expected.right,
"rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
rc.top, rc.left, rc.bottom, rc.right,
......
......@@ -78,8 +78,7 @@ static void ME_BeginRow(ME_WrapContext *wc, ME_DisplayItem *para)
wc->bWordWrap = TRUE;
} else {
wc->nAvailWidth = wc->context->rcView.right - wc->context->rcView.left
- (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin
- wc->context->editor->selofs;
- (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin;
}
wc->pt.x = wc->context->pt.x;
if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
......@@ -458,7 +457,7 @@ static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p)
static void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp);
static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp, DWORD beginofs) {
static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
ME_DisplayItem *p;
ME_WrapContext wc;
int border = 0;
......@@ -573,7 +572,8 @@ static void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp) {
}
}
BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor)
{
ME_DisplayItem *item;
ME_Context c;
BOOL bModified = FALSE;
......@@ -581,7 +581,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
int yLastPos = 0;
ME_InitContext(&c, editor, GetDC(editor->hWnd));
c.pt.x = editor->selofs;
c.pt.x = 0;
editor->nHeight = 0;
item = editor->pBuffer->pFirst->next;
while(item != editor->pBuffer->pLast) {
......@@ -594,7 +594,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
bRedraw = TRUE;
item->member.para.pt = c.pt;
ME_WrapTextParagraph(&c, item, editor->selofs);
ME_WrapTextParagraph(&c, item);
if (bRedraw)
{
......@@ -707,7 +707,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
c.pt.x = item->member.para.pCell->member.cell.pt.x;
} else {
/* Normal paragraph */
c.pt.x = editor->selofs;
c.pt.x = 0;
}
c.pt.y += item->member.para.nHeight;
}
......@@ -749,16 +749,18 @@ void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor)
item = editor->pBuffer->pFirst;
while(item != editor->pBuffer->pLast) {
if (item->member.para.nFlags & MEPF_REPAINT) {
rc.top = item->member.para.pt.y - ofs;
rc.bottom = item->member.para.pt.y + item->member.para.nHeight - ofs;
rc.top = c.rcView.top + item->member.para.pt.y - ofs;
rc.bottom = max(c.rcView.top + item->member.para.pt.y
+ item->member.para.nHeight - ofs,
c.rcView.bottom);
InvalidateRect(editor->hWnd, &rc, TRUE);
}
item = item->member.para.next_para;
}
if (editor->nTotalLength < editor->nLastTotalLength)
{
rc.top = editor->nTotalLength - ofs;
rc.bottom = editor->nLastTotalLength - ofs;
rc.top = c.rcView.top + editor->nTotalLength - ofs;
rc.bottom = c.rcView.top + editor->nLastTotalLength - ofs;
InvalidateRect(editor->hWnd, &rc, TRUE);
}
ME_DestroyContext(&c, editor->hWnd);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment