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.
oldstable
Dylan Smith 2008-12-18 01:56:49 -05:00 committed by Alexandre Julliard
parent ced9bde4c0
commit 297716e01c
7 changed files with 213 additions and 109 deletions

View File

@ -214,8 +214,9 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
} }
*height = pSizeRun->member.run.nAscent + pSizeRun->member.run.nDescent; *height = pSizeRun->member.run.nAscent + pSizeRun->member.run.nDescent;
*x = run->member.run.pt.x + sz.cx; *x = c.rcView.left + 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); *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); ME_DestroyContext(&c, editor->hWnd);
return; return;
} }
@ -236,10 +237,7 @@ ME_MoveCaret(ME_TextEditor *editor)
ME_GetCursorCoordinates(editor, &editor->pCursors[0], &x, &y, &height); ME_GetCursorCoordinates(editor, &editor->pCursors[0], &x, &y, &height);
if(editor->bHaveFocus && !ME_IsSelection(editor)) if(editor->bHaveFocus && !ME_IsSelection(editor))
{ {
RECT rect; x = min(x, editor->rcFormat.right-1);
GetClientRect(editor->hWnd, &rect);
x = min(x, rect.right-2);
CreateCaret(editor->hWnd, NULL, 0, height); CreateCaret(editor->hWnd, NULL, 0, height);
SetCaretPos(x, y); SetCaretPos(x, y);
} }
@ -922,6 +920,9 @@ static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y,
int rx = 0; int rx = 0;
BOOL isExact = TRUE; BOOL isExact = TRUE;
x -= editor->rcFormat.left;
y -= editor->rcFormat.top;
if (is_eol) if (is_eol)
*is_eol = 0; *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); 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) if (clickNum > 1)
{ {
editor->pCursors[1] = editor->pCursors[0]; editor->pCursors[1] = editor->pCursors[0];
if (is_shift) { if (is_shift) {
if (x >= editor->selofs) if (x >= editor->rcFormat.left)
ME_SelectByType(editor, stWord); ME_SelectByType(editor, stWord);
else else
ME_SelectByType(editor, stParagraph); ME_SelectByType(editor, stParagraph);

View File

@ -2492,9 +2492,26 @@ static BOOL ME_SetCursor(ME_TextEditor *editor)
} }
ScreenToClient(editor->hWnd, &pt); ScreenToClient(editor->hWnd, &pt);
if ((GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_SELECTIONBAR) && if (editor->nSelectionType == stLine && GetCapture() == editor->hWnd) {
(pt.x < editor->selofs || SetCursor(hLeft);
(editor->nSelectionType == stLine && GetCapture() == editor->hWnd))) 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); SetCursor(hLeft);
return TRUE; return TRUE;
@ -2530,6 +2547,16 @@ static BOOL ME_SetCursor(ME_TextEditor *editor)
return TRUE; 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) static BOOL ME_ShowContextMenu(ME_TextEditor *editor, int x, int y)
{ {
CHARRANGE selrange; CHARRANGE selrange;
@ -2614,6 +2641,7 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) {
ed->selofs = SELECTIONBAR_WIDTH; ed->selofs = SELECTIONBAR_WIDTH;
else else
ed->selofs = 0; ed->selofs = 0;
ed->bDefaultFormatRect = TRUE;
ed->nSelectionType = stPosition; ed->nSelectionType = stPosition;
if (GetWindowLongW(hWnd, GWL_STYLE) & ES_PASSWORD) 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 */ /* these flags are equivalent to the ES_* counterparts */
DWORD mask = ECO_VERTICAL | ECO_AUTOHSCROLL | ECO_AUTOVSCROLL | 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; DWORD settings = GetWindowLongW(hWnd, GWL_STYLE) & mask;
return settings; return settings;
@ -2976,6 +3004,8 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN | ECO_SELECTIONBAR; ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN | ECO_SELECTIONBAR;
DWORD raw = GetWindowLongW(hWnd, GWL_STYLE); DWORD raw = GetWindowLongW(hWnd, GWL_STYLE);
DWORD settings = mask & raw; DWORD settings = mask & raw;
DWORD oldSettings = settings;
DWORD changedSettings;
switch(wParam) switch(wParam)
{ {
@ -2993,13 +3023,21 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
} }
SetWindowLongW(hWnd, GWL_STYLE, (raw & ~mask) | (settings & mask)); SetWindowLongW(hWnd, GWL_STYLE, (raw & ~mask) | (settings & mask));
changedSettings = oldSettings ^ settings;
if (settings & ECO_AUTOWORDSELECTION) if (settings & ECO_AUTOWORDSELECTION)
FIXME("ECO_AUTOWORDSELECTION not implemented yet!\n"); FIXME("ECO_AUTOWORDSELECTION not implemented yet!\n");
if (settings & ECO_SELECTIONBAR)
if (oldSettings ^ settings) {
if (settings & ECO_SELECTIONBAR) {
editor->selofs = SELECTIONBAR_WIDTH; editor->selofs = SELECTIONBAR_WIDTH;
else editor->rcFormat.left += SELECTIONBAR_WIDTH;
} else {
editor->selofs = 0; editor->selofs = 0;
ME_WrapMarkedParagraphs(editor); editor->rcFormat.left -= SELECTIONBAR_WIDTH;
}
ME_WrapMarkedParagraphs(editor);
}
if (settings & ECO_VERTICAL) if (settings & ECO_VERTICAL)
FIXME("ECO_VERTICAL not implemented yet!\n"); 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); assert(pRun->type == diRun);
pt.y = pRun->member.run.pt.y; pt.y = pRun->member.run.pt.y;
pt.x = pRun->member.run.pt.x + ME_PointFromChar(editor, &pRun->member.run, nOffset); pt.x = pRun->member.run.pt.x + ME_PointFromChar(editor, &pRun->member.run, nOffset);
pt.y += ME_GetParagraph(pRun)->member.para.pt.y; pt.y += ME_GetParagraph(pRun)->member.para.pt.y + editor->rcFormat.top;
pt.x += editor->selofs; pt.x += editor->rcFormat.left;
pt.x++; /* for some reason native offsets x by one */
pt.y -= editor->vert_si.nPos; pt.y -= editor->vert_si.nPos;
si.cbSize = sizeof(si); si.cbSize = sizeof(si);
@ -3734,7 +3771,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
{ {
SCROLLINFO si; SCROLLINFO si;
GetClientRect(hWnd, &editor->rcFormat); ME_SetDefaultFormatRect(editor);
if (GetWindowLongW(hWnd, GWL_STYLE) & WS_HSCROLL) if (GetWindowLongW(hWnd, GWL_STYLE) & WS_HSCROLL)
{ /* Squelch the default horizontal scrollbar it would make */ { /* Squelch the default horizontal scrollbar it would make */
ShowScrollBar(editor->hWnd, SB_HORZ, FALSE); ShowScrollBar(editor->hWnd, SB_HORZ, FALSE);
@ -3816,9 +3853,37 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
case WM_PAINT: case WM_PAINT:
{ {
HDC hDC; HDC hDC;
RECT rc;
PAINTSTRUCT ps; PAINTSTRUCT ps;
hDC = BeginPaint(hWnd, &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); ME_PaintContent(editor, hDC, FALSE, &ps.rcPaint);
EndPaint(hWnd, &ps); EndPaint(hWnd, &ps);
} }
@ -3940,6 +4005,8 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
case EM_GETRECT: case EM_GETRECT:
{ {
*((RECT *)lParam) = editor->rcFormat; *((RECT *)lParam) = editor->rcFormat;
if (editor->bDefaultFormatRect)
((RECT *)lParam)->left -= editor->selofs;
return 0; return 0;
} }
case EM_SETRECT: case EM_SETRECT:
@ -3947,23 +4014,36 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
{ {
if (lParam) if (lParam)
{ {
DWORD exstyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
int border = (exstyle & WS_EX_CLIENTEDGE) ? 1 : 0;
RECT clientRect;
RECT *rc = (RECT *)lParam; RECT *rc = (RECT *)lParam;
if (wParam) GetClientRect(hWnd, &clientRect);
if (wParam == 0)
{ {
editor->rcFormat.left += rc->left; editor->rcFormat.top = max(0, rc->top - border);
editor->rcFormat.top += rc->top; editor->rcFormat.left = max(0, rc->left - border);
editor->rcFormat.right += rc->right; editor->rcFormat.bottom = min(clientRect.bottom, rc->bottom);
editor->rcFormat.bottom += rc->bottom; editor->rcFormat.right = min(clientRect.right, rc->right + border);
} } else if (wParam == 1) {
else /* MSDN incorrectly says a wParam value of 1 causes the
{ * lParam rect to be used as a relative offset,
editor->rcFormat = *rc; * 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 else
{ {
GetClientRect(hWnd, &editor->rcFormat); ME_SetDefaultFormatRect(editor);
editor->bDefaultFormatRect = TRUE;
} }
if (msg != EM_SETRECTNP) if (msg != EM_SETRECTNP)
ME_RewrapRepaint(editor); ME_RewrapRepaint(editor);
@ -3976,7 +4056,16 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
return DefWindowProcW(hWnd, msg, wParam, lParam); return DefWindowProcW(hWnd, msg, wParam, lParam);
case WM_SIZE: 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); ME_RewrapRepaint(editor);
return DefWindowProcW(hWnd, msg, wParam, lParam); return DefWindowProcW(hWnd, msg, wParam, lParam);
} }

View File

@ -90,7 +90,7 @@ typedef enum {
diUndoPotentialEndTransaction, /* 20 - allows grouping typed chars for undo */ diUndoPotentialEndTransaction, /* 20 - allows grouping typed chars for undo */
} ME_DIType; } ME_DIType;
#define SELECTIONBAR_WIDTH 9 #define SELECTIONBAR_WIDTH 8
/******************************** run flags *************************/ /******************************** run flags *************************/
#define MERF_STYLEFLAGS 0x0FFF #define MERF_STYLEFLAGS 0x0FFF
@ -350,7 +350,9 @@ typedef struct tagME_TextEditor
ME_DisplayItem *pLastSelStartPara, *pLastSelEndPara; ME_DisplayItem *pLastSelStartPara, *pLastSelEndPara;
ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE]; ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE];
int nZoomNumerator, nZoomDenominator; int nZoomNumerator, nZoomDenominator;
RECT prevClientRect;
RECT rcFormat; RECT rcFormat;
BOOL bDefaultFormatRect;
BOOL bWordWrap; BOOL bWordWrap;
int nInvalidOfs; int nInvalidOfs;
int nTextLimit; int nTextLimit;

View File

@ -37,7 +37,7 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *
c.pt.y -= yoffset; c.pt.y -= yoffset;
while(item != editor->pBuffer->pLast) { while(item != editor->pBuffer->pLast) {
int yTextOffset = 0; int yTextOffset = 0;
int ye; int ys, ye;
assert(item->type == diParagraph); assert(item->type == diParagraph);
if (item->member.para.pCell if (item->member.para.pCell
!= item->member.para.next_para->member.para.pCell) != item->member.para.next_para->member.para.pCell)
@ -63,14 +63,20 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *
} }
if (!bOnlyNew || (item->member.para.nFlags & MEPF_REPAINT)) if (!bOnlyNew || (item->member.para.nFlags & MEPF_REPAINT))
{ {
/* Draw the pargraph if any of the paragraph is in the update region. */
BOOL bPaint = (rcUpdate == NULL); BOOL bPaint = (rcUpdate == NULL);
ys = c.pt.y;
if (rcUpdate) if (rcUpdate)
bPaint = c.pt.y<rcUpdate->bottom && ye>rcUpdate->top; bPaint = ys + c.rcView.top < rcUpdate->bottom &&
ye + c.rcView.top > rcUpdate->top;
if (bPaint) if (bPaint)
{ {
c.pt.y += yTextOffset; c.pt.y += yTextOffset;
ME_DrawParagraph(&c, item); ME_DrawParagraph(&c, item);
if (!rcUpdate || (rcUpdate->top<=c.pt.y-yTextOffset && rcUpdate->bottom>=ye)) /* Clear the repaint flag if the whole paragraph is in the
* update region. */
if (!rcUpdate || (rcUpdate->top <= ys + c.rcView.top &&
rcUpdate->bottom >= ye + c.rcView.top))
item->member.para.nFlags &= ~MEPF_REPAINT; item->member.para.nFlags &= ~MEPF_REPAINT;
} }
} }
@ -103,30 +109,34 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *
} }
item = item->member.para.next_para; item = item->member.para.next_para;
} }
if (c.pt.y<c.rcView.bottom) { if (c.pt.y < c.rcView.bottom - c.rcView.top)
RECT rc; {
int xs = c.rcView.left, xe = c.rcView.right; /* Fill space after the end of the text. */
int ys = c.pt.y, ye = c.rcView.bottom; int xs = c.rcView.left, xe = c.rcView.right;
int ys = c.rcView.top + c.pt.y, ye = c.rcView.bottom;
if (bOnlyNew) if (bOnlyNew)
{ {
/* Only erase region drawn from previous call to ME_PaintContent */
int y1 = editor->nTotalLength-yoffset, y2 = editor->nLastTotalLength-yoffset; int y1 = editor->nTotalLength-yoffset, y2 = editor->nLastTotalLength-yoffset;
if (y1<y2) if (y1<y2)
ys = y1, ye = y2+1; ys = y1, ye = y2+1;
else else
ys = ye; ys = ye; /* empty fill area */
}
if (rcUpdate && ys!=ye)
{
xs = rcUpdate->left, xe = rcUpdate->right;
if (rcUpdate->top > ys)
ys = rcUpdate->top;
if (rcUpdate->bottom < ye)
ye = rcUpdate->bottom;
} }
if (ye>ys) { if (rcUpdate)
{
/* Clip to update region */
xs = max(xs, rcUpdate->left);
xe = min(xe, rcUpdate->right);
ys = max(ys, rcUpdate->top);
ye = min(ye, rcUpdate->bottom);
}
if (xe > xs && ye > ys)
{
RECT rc;
rc.left = xs; rc.left = xs;
rc.top = ys; rc.top = ys;
rc.right = xe; rc.right = xe;
@ -441,7 +451,7 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa
if (runofs >= nSelFrom && runofs < nSelTo) if (runofs >= nSelFrom && runofs < nSelTo)
{ {
ME_HighlightSpace(c, x, y, wszSpace, 1, run->style, 0, 0, 1, ME_HighlightSpace(c, x, y, wszSpace, 1, run->style, 0, 0, 1,
c->pt.y + start->member.row.pt.y, c->rcView.top + c->pt.y + start->member.row.pt.y,
start->member.row.nHeight); start->member.row.nHeight);
} }
return; return;
@ -452,8 +462,8 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa
/* wszSpace is used instead of the tab character because otherwise /* wszSpace is used instead of the tab character because otherwise
* an unwanted symbol can be inserted instead. */ * an unwanted symbol can be inserted instead. */
ME_DrawTextWithStyle(c, x, y, wszSpace, 1, run->style, run->nWidth, ME_DrawTextWithStyle(c, x, y, wszSpace, 1, run->style, run->nWidth,
nSelFrom-runofs,nSelTo-runofs, nSelFrom-runofs, nSelTo-runofs,
c->pt.y + start->member.row.pt.y, c->rcView.top + c->pt.y + start->member.row.pt.y,
start->member.row.nHeight); start->member.row.nHeight);
return; return;
} }
@ -467,13 +477,17 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa
ME_String *szMasked = ME_MakeStringR(c->editor->cPasswordMask,ME_StrVLen(run->strText)); ME_String *szMasked = ME_MakeStringR(c->editor->cPasswordMask,ME_StrVLen(run->strText));
ME_DrawTextWithStyle(c, x, y, ME_DrawTextWithStyle(c, x, y,
szMasked->szData, ME_StrVLen(szMasked), run->style, run->nWidth, szMasked->szData, ME_StrVLen(szMasked), run->style, run->nWidth,
nSelFrom-runofs,nSelTo-runofs, c->pt.y+start->member.row.pt.y, start->member.row.nHeight); nSelFrom-runofs,nSelTo-runofs,
c->rcView.top + c->pt.y + start->member.row.pt.y,
start->member.row.nHeight);
ME_DestroyString(szMasked); ME_DestroyString(szMasked);
} }
else else
ME_DrawTextWithStyle(c, x, y, ME_DrawTextWithStyle(c, x, y,
run->strText->szData, ME_StrVLen(run->strText), run->style, run->nWidth, run->strText->szData, ME_StrVLen(run->strText), run->style, run->nWidth,
nSelFrom-runofs,nSelTo-runofs, c->pt.y+start->member.row.pt.y, start->member.row.nHeight); nSelFrom-runofs,nSelTo-runofs,
c->rcView.top + c->pt.y + start->member.row.pt.y,
start->member.row.nHeight);
} }
} }
@ -728,11 +742,11 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
int width; int width;
BOOL atTop = (para->pCell != para->prev_para->member.para.pCell); BOOL atTop = (para->pCell != para->prev_para->member.para.pCell);
BOOL atBottom = (para->pCell != para->next_para->member.para.pCell); BOOL atBottom = (para->pCell != para->next_para->member.para.pCell);
int top = (atTop ? cell->pt.y : para->pt.y) - ME_GetYScrollPos(c->editor); int top = c->rcView.top + (atTop ? cell->pt.y : para->pt.y) - ME_GetYScrollPos(c->editor);
int bottom = (atBottom ? int bottom = (atBottom ?
cell->pt.y + cell->nHeight - ME_GetYScrollPos(c->editor): c->rcView.top + cell->pt.y + cell->nHeight - ME_GetYScrollPos(c->editor):
top + para->nHeight + (atTop ? cell->yTextOffset : 0)); top + para->nHeight + (atTop ? cell->yTextOffset : 0));
rc.left = cell->pt.x; rc.left = c->rcView.left + cell->pt.x;
rc.right = rc.left + cell->nWidth; rc.right = rc.left + cell->nWidth;
if (atTop) { if (atTop) {
/* Erase gap before text if not all borders are the same height. */ /* Erase gap before text if not all borders are the same height. */
@ -798,10 +812,10 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
ME_DisplayItem *nextEndCell; ME_DisplayItem *nextEndCell;
nextEndCell = ME_FindItemBack(ME_GetTableRowEnd(paraAfterRow), diCell); nextEndCell = ME_FindItemBack(ME_GetTableRowEnd(paraAfterRow), diCell);
assert(nextEndCell && !nextEndCell->member.cell.next_cell); assert(nextEndCell && !nextEndCell->member.cell.next_cell);
rc.left = nextEndCell->member.cell.pt.x; rc.left = c->rcView.left + nextEndCell->member.cell.pt.x;
/* FIXME: Native draws FROM the bottom of the table rather than /* FIXME: Native draws FROM the bottom of the table rather than
* TO the bottom of the table in this case, but just doing so here * TO the bottom of the table in this case, but just doing so here
* will case the next row to erase the border. */ * will cause the next row to erase the border. */
/* /*
rc.top = bottom; rc.top = bottom;
rc.bottom = rc.top + width; rc.bottom = rc.top + width;
@ -860,12 +874,12 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
oldpen = SelectObject(c->hDC, pen); oldpen = SelectObject(c->hDC, pen);
/* Find the start relative to the text */ /* Find the start relative to the text */
firstX = ME_FindItemFwd(paragraph, diRun)->member.run.pt.x; firstX = c->rcView.left + ME_FindItemFwd(paragraph, diRun)->member.run.pt.x;
/* Go back by the horizontal gap, which is stored in dxOffset */ /* Go back by the horizontal gap, which is stored in dxOffset */
firstX -= ME_twips2pointsX(c, para->pFmt->dxOffset); firstX -= ME_twips2pointsX(c, para->pFmt->dxOffset);
/* The left edge, stored in dxStartIndent affected just the first edge */ /* The left edge, stored in dxStartIndent affected just the first edge */
startX = firstX - ME_twips2pointsX(c, para->pFmt->dxStartIndent); startX = firstX - ME_twips2pointsX(c, para->pFmt->dxStartIndent);
rowY = c->pt.y; rowY = c->rcView.top + c->pt.y;
if (para->pFmt->dwMask & PFM_SPACEBEFORE) if (para->pFmt->dwMask & PFM_SPACEBEFORE)
rowY += ME_twips2pointsY(c, para->pFmt->dySpaceBefore); rowY += ME_twips2pointsY(c, para->pFmt->dySpaceBefore);
nHeight = ME_FindItemFwd(paragraph, diStartRow)->member.row.nHeight; nHeight = ME_FindItemFwd(paragraph, diStartRow)->member.row.nHeight;
@ -907,13 +921,14 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
} }
} }
void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) { void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph)
{
int align = SetTextAlign(c->hDC, TA_BASELINE); int align = SetTextAlign(c->hDC, TA_BASELINE);
ME_DisplayItem *p; ME_DisplayItem *p;
ME_Run *run; ME_Run *run;
ME_Paragraph *para = NULL; ME_Paragraph *para = NULL;
RECT rc, bounds; RECT rc, bounds;
int y = c->pt.y; int y = c->rcView.top + c->pt.y;
int height = 0, baseline = 0, no=0; int height = 0, baseline = 0, no=0;
BOOL visible = FALSE; BOOL visible = FALSE;
@ -928,15 +943,15 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) {
if (para->pCell) if (para->pCell)
{ {
ME_Cell *cell = &para->pCell->member.cell; ME_Cell *cell = &para->pCell->member.cell;
rc.left = cell->pt.x; rc.left = c->rcView.left + cell->pt.x;
rc.right = rc.left + cell->nWidth; rc.right = rc.left + cell->nWidth;
} }
if (para->nFlags & MEPF_ROWSTART) { if (para->nFlags & MEPF_ROWSTART) {
ME_Cell *cell = &para->next_para->member.para.pCell->member.cell; ME_Cell *cell = &para->next_para->member.para.pCell->member.cell;
rc.right = cell->pt.x; rc.right = c->rcView.left + cell->pt.x;
} else if (para->nFlags & MEPF_ROWEND) { } else if (para->nFlags & MEPF_ROWEND) {
ME_Cell *cell = &para->prev_para->member.para.pCell->member.cell; ME_Cell *cell = &para->prev_para->member.para.pCell->member.cell;
rc.left = cell->pt.x + cell->nWidth; rc.left = c->rcView.left + cell->pt.x + cell->nWidth;
} }
ME_DrawParaDecoration(c, para, y, &bounds); ME_DrawParaDecoration(c, para, y, &bounds);
y += bounds.top; y += bounds.top;
@ -953,7 +968,7 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) {
ME_Cell *cell = &para->prev_para->member.para.pCell->member.cell; ME_Cell *cell = &para->prev_para->member.para.pCell->member.cell;
rc.bottom = y + cell->nHeight; rc.bottom = y + cell->nHeight;
} else { } else {
rc.bottom = y+p->member.row.nHeight; rc.bottom = y + p->member.row.nHeight;
} }
visible = RectVisible(c->hDC, &rc); visible = RectVisible(c->hDC, &rc);
if (visible) { if (visible) {
@ -976,10 +991,10 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) {
assert(para); assert(para);
run = &p->member.run; run = &p->member.run;
if (visible && me_debug) { if (visible && me_debug) {
rc.left = c->rcView.left+run->pt.x; rc.left = c->rcView.left + run->pt.x;
rc.right = c->rcView.left+run->pt.x+run->nWidth; rc.right = rc.left + run->nWidth;
rc.top = c->pt.y+run->pt.y; rc.top = c->rcView.top + c->pt.y + run->pt.y;
rc.bottom = c->pt.y+run->pt.y+height; rc.bottom = rc.bottom + height;
TRACE("rc = (%d, %d, %d, %d)\n", rc.left, rc.top, rc.right, rc.bottom); TRACE("rc = (%d, %d, %d, %d)\n", rc.left, rc.top, rc.right, rc.bottom);
if (run->nFlags & MERF_SKIPPED) if (run->nFlags & MERF_SKIPPED)
DrawFocusRect(c->hDC, &rc); DrawFocusRect(c->hDC, &rc);
@ -987,7 +1002,9 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) {
FrameRect(c->hDC, &rc, GetSysColorBrush(COLOR_GRAYTEXT)); FrameRect(c->hDC, &rc, GetSysColorBrush(COLOR_GRAYTEXT));
} }
if (visible) if (visible)
ME_DrawRun(c, run->pt.x, c->pt.y+run->pt.y+baseline, p, &paragraph->member.para); ME_DrawRun(c, c->rcView.left + run->pt.x,
c->rcView.top + c->pt.y + run->pt.y + baseline,
p, &paragraph->member.para);
if (me_debug) if (me_debug)
{ {
/* I'm using %ls, hope wsprintfW is not going to use wrong (4-byte) WCHAR version */ /* I'm using %ls, hope wsprintfW is not going to use wrong (4-byte) WCHAR version */
@ -995,7 +1012,7 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) {
WCHAR buf[2560]; WCHAR buf[2560];
POINT pt; POINT pt;
pt.x = run->pt.x; pt.x = run->pt.x;
pt.y = c->pt.y + run->pt.y; pt.y = c->rcView.top + c->pt.y + run->pt.y;
wsprintfW(buf, wszRunDebug, no, p->member.run.nFlags, p->member.run.strText->szData); wsprintfW(buf, wszRunDebug, no, p->member.run.nFlags, p->member.run.strText->szData);
ME_DebugWrite(c->hDC, &pt, buf); ME_DebugWrite(c->hDC, &pt, buf);
} }
@ -1007,8 +1024,8 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) {
break; break;
y += height; y += height;
rc.top = y; rc.top = y;
rc.bottom = p->member.cell.pt.y + p->member.cell.nHeight rc.bottom = c->rcView.top + p->member.cell.pt.y
- ME_GetYScrollPos(c->editor); + p->member.cell.nHeight - ME_GetYScrollPos(c->editor);
if (RectVisible(c->hDC, &rc)) if (RectVisible(c->hDC, &rc))
{ {
FillRect(c->hDC, &rc, c->editor->hbrBackground); FillRect(c->hDC, &rc, c->editor->hbrBackground);

View File

@ -692,7 +692,7 @@ static SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run
{ {
pos += lDefaultTab - (pos % lDefaultTab); pos += lDefaultTab - (pos % lDefaultTab);
} }
ppos = ME_twips2pointsX(c, pos) + c->editor->selofs; ppos = ME_twips2pointsX(c, pos);
if (ppos > startx + run->pt.x) { if (ppos > startx + run->pt.x) {
size.cx = ppos - startx - run->pt.x; size.cx = ppos - startx - run->pt.x;
break; break;

View File

@ -5854,7 +5854,7 @@ static void test_format_rect(void)
expected.left += 1; expected.left += 1;
expected.right -= 1; expected.right -= 1;
SendMessageW(hwnd, EM_GETRECT, 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, 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", "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, 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.bottom = min(clientRect.bottom, rc.bottom);
expected.right = min(clientRect.right, rc.right); expected.right = min(clientRect.right, rc.right);
SendMessageW(hwnd, EM_GETRECT, 0, (LPARAM)&rc); SendMessageW(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
if (n >= 0) 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,
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=%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,
n, rc.top, rc.left, rc.bottom, rc.right, expected.top, expected.left, expected.bottom, expected.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);
} }
rc = clientRect; rc = clientRect;
@ -5902,10 +5895,10 @@ static void test_format_rect(void)
/* Adding the selectionbar adds the selectionbar width to the left side. */ /* Adding the selectionbar adds the selectionbar width to the left side. */
SendMessageW(hwnd, EM_SETOPTIONS, ECOOP_OR, ECO_SELECTIONBAR); SendMessageW(hwnd, EM_SETOPTIONS, ECOOP_OR, ECO_SELECTIONBAR);
options = SendMessageW(hwnd, EM_GETOPTIONS, 0, 0); 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 */ expected.left += 8; /* selection bar width */
SendMessageW(hwnd, EM_GETRECT, 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, 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", "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, 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"); ok(!(options & ECO_SELECTIONBAR), "EM_SETOPTIONS failed to remove selectionbar.\n");
expected.left -= 8; /* selection bar width */ expected.left -= 8; /* selection bar width */
SendMessageW(hwnd, EM_GETRECT, 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, 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", "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, rc.top, rc.left, rc.bottom, rc.right,
@ -5955,7 +5948,7 @@ static void test_format_rect(void)
expected = rc; expected = rc;
SendMessageW(hwnd, EM_SETRECT, 1, (LPARAM)&rc); SendMessageW(hwnd, EM_SETRECT, 1, (LPARAM)&rc);
SendMessageW(hwnd, EM_GETRECT, 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, 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", "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, rc.top, rc.left, rc.bottom, rc.right,
@ -5970,7 +5963,7 @@ static void test_format_rect(void)
expected = rc; expected = rc;
SendMessageW(hwnd, EM_SETRECT, 1, (LPARAM)&rc); SendMessageW(hwnd, EM_SETRECT, 1, (LPARAM)&rc);
SendMessageW(hwnd, EM_GETRECT, 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, 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", "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, rc.top, rc.left, rc.bottom, rc.right,
@ -5991,7 +5984,7 @@ static void test_format_rect(void)
expected.top += 1; expected.top += 1;
expected.right -= 1; expected.right -= 1;
SendMessageW(hwnd, EM_GETRECT, 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, 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", "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, rc.top, rc.left, rc.bottom, rc.right,
@ -6008,7 +6001,7 @@ static void test_format_rect(void)
expected.right += 1; expected.right += 1;
SendMessageW(hwnd, EM_SETRECT, 0, (LPARAM)&rc); SendMessageW(hwnd, EM_SETRECT, 0, (LPARAM)&rc);
SendMessageW(hwnd, EM_GETRECT, 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, 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", "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, rc.top, rc.left, rc.bottom, rc.right,

View File

@ -78,8 +78,7 @@ static void ME_BeginRow(ME_WrapContext *wc, ME_DisplayItem *para)
wc->bWordWrap = TRUE; wc->bWordWrap = TRUE;
} else { } else {
wc->nAvailWidth = wc->context->rcView.right - wc->context->rcView.left wc->nAvailWidth = wc->context->rcView.right - wc->context->rcView.left
- (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin - (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin;
- wc->context->editor->selofs;
} }
wc->pt.x = wc->context->pt.x; wc->pt.x = wc->context->pt.x;
if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */ 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_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_DisplayItem *p;
ME_WrapContext wc; ME_WrapContext wc;
int border = 0; 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_DisplayItem *item;
ME_Context c; ME_Context c;
BOOL bModified = FALSE; BOOL bModified = FALSE;
@ -581,7 +581,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
int yLastPos = 0; int yLastPos = 0;
ME_InitContext(&c, editor, GetDC(editor->hWnd)); ME_InitContext(&c, editor, GetDC(editor->hWnd));
c.pt.x = editor->selofs; c.pt.x = 0;
editor->nHeight = 0; editor->nHeight = 0;
item = editor->pBuffer->pFirst->next; item = editor->pBuffer->pFirst->next;
while(item != editor->pBuffer->pLast) { while(item != editor->pBuffer->pLast) {
@ -594,7 +594,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
bRedraw = TRUE; bRedraw = TRUE;
item->member.para.pt = c.pt; item->member.para.pt = c.pt;
ME_WrapTextParagraph(&c, item, editor->selofs); ME_WrapTextParagraph(&c, item);
if (bRedraw) if (bRedraw)
{ {
@ -707,7 +707,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
c.pt.x = item->member.para.pCell->member.cell.pt.x; c.pt.x = item->member.para.pCell->member.cell.pt.x;
} else { } else {
/* Normal paragraph */ /* Normal paragraph */
c.pt.x = editor->selofs; c.pt.x = 0;
} }
c.pt.y += item->member.para.nHeight; c.pt.y += item->member.para.nHeight;
} }
@ -749,16 +749,18 @@ void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor)
item = editor->pBuffer->pFirst; item = editor->pBuffer->pFirst;
while(item != editor->pBuffer->pLast) { while(item != editor->pBuffer->pLast) {
if (item->member.para.nFlags & MEPF_REPAINT) { if (item->member.para.nFlags & MEPF_REPAINT) {
rc.top = item->member.para.pt.y - ofs; rc.top = c.rcView.top + item->member.para.pt.y - ofs;
rc.bottom = item->member.para.pt.y + item->member.para.nHeight - 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); InvalidateRect(editor->hWnd, &rc, TRUE);
} }
item = item->member.para.next_para; item = item->member.para.next_para;
} }
if (editor->nTotalLength < editor->nLastTotalLength) if (editor->nTotalLength < editor->nLastTotalLength)
{ {
rc.top = editor->nTotalLength - ofs; rc.top = c.rcView.top + editor->nTotalLength - ofs;
rc.bottom = editor->nLastTotalLength - ofs; rc.bottom = c.rcView.top + editor->nLastTotalLength - ofs;
InvalidateRect(editor->hWnd, &rc, TRUE); InvalidateRect(editor->hWnd, &rc, TRUE);
} }
ME_DestroyContext(&c, editor->hWnd); ME_DestroyContext(&c, editor->hWnd);