riched20: Rewrite of scrolling and some redrawing code.

Replaces duplicated scrolling code with re-usable functions.
Removes excessive boundary checking on scroll code, since that's done
in the scrollbar control anyways.
Properly separates repaint calls based on what has changed.
Send EN_UPDATE and EN_CHANGE at the right places.
Only call EnsureVisible on changes, not all repaints.
This commit is contained in:
Matt Finnicum 2006-09-08 16:37:25 -05:00 committed by Alexandre Julliard
parent 6393fed2d4
commit abecd9e393
5 changed files with 189 additions and 241 deletions

View File

@ -948,9 +948,9 @@ static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
ME_EnsureVisible(editor, ME_FindItemFwd(editor->pBuffer->pFirst, diRun));
ME_Repaint(editor);
}
else {
ME_Scroll(editor, 0, ys-yprev);
ME_Repaint(editor);
else
{
ME_ScrollUp(editor, ys-yprev);
}
assert(pCursor->pRun);
assert(pCursor->pRun->type == diRun);
@ -1001,9 +1001,9 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
ME_EnsureVisible(editor, ME_FindItemBack(editor->pBuffer->pLast, diRun));
ME_Repaint(editor);
}
else {
ME_Scroll(editor, 0, ys-yprev);
ME_Repaint(editor);
else
{
ME_ScrollUp(editor,ys-yprev);
}
assert(pCursor->pRun);
assert(pCursor->pRun->type == diRun);

View File

@ -1135,7 +1135,6 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) {
ed->nParagraphs = 1;
ed->nLastSelStart = ed->nLastSelEnd = 0;
ed->pLastSelStartPara = ed->pLastSelEndPara = ME_FindItemFwd(ed->pBuffer->pFirst, diParagraph);
ed->nScrollPosY = 0;
ed->nZoomNumerator = ed->nZoomDenominator = 0;
ed->bRedraw = TRUE;
ed->bHideSelection = FALSE;
@ -1151,11 +1150,6 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) {
ed->pFontCache[i].hFont = NULL;
}
if (GetWindowLongW(hWnd, GWL_STYLE) & WS_HSCROLL)
FIXME("WS_HSCROLL requested, but horizontal scrolling isn't implemented yet.\n");
ed->bScrollX = 0;
ed->bScrollY = GetWindowLongW(hWnd, GWL_STYLE) & WS_VSCROLL;
ME_CheckCharOffsets(ed);
if (GetWindowLongW(hWnd, GWL_STYLE) & ES_PASSWORD)
@ -1410,7 +1404,6 @@ get_msg_name(UINT msg)
* RichEditANSIWndProc (RICHED20.10)
*/
LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
SCROLLINFO si;
ME_TextEditor *editor = (ME_TextEditor *)GetWindowLongPtrW(hWnd, 0);
TRACE("hWnd %p msg %04x (%s) %08x %08lx\n",
@ -1583,9 +1576,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
case EM_SETSCROLLPOS:
{
POINT *point = (POINT *)lParam;
/* Native behavior when point->y is too large is very odd / dosn't follow MSDN.
This seems to be a pretty close approximation of what it does. */
ME_Scroll(editor, 0, -(min(point->y, (editor->nTotalLength - 1)) - editor->nScrollPosY));
ME_ScrollAbs(editor, point->y);
return 0;
}
case EM_AUTOURLDETECT:
@ -1630,11 +1621,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
}
case EM_SHOWSCROLLBAR:
{
if (wParam == SB_VERT)
editor->bScrollY = lParam;
else if (wParam == SB_HORZ)
editor->bScrollX = lParam;
ME_UpdateScrollBar(editor);
ShowScrollBar(editor->hWnd, wParam, lParam);
return 0;
}
case EM_SETTEXTEX:
@ -1769,7 +1756,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
case EM_GETFIRSTVISIBLELINE:
{
ME_DisplayItem *p = editor->pBuffer->pFirst;
int y = editor->nScrollPosY;
int y = ME_GetYScrollPos(editor);
int ypara = 0;
int count = 0;
int ystart, yend;
@ -1798,22 +1785,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
}
case EM_LINESCROLL:
{
int nPos = editor->nScrollPosY, nEnd= editor->nTotalLength - editor->sizeWindow.cy;
nPos += 8 * lParam; /* FIXME follow the original */
if (nPos>=nEnd)
nPos = nEnd;
if (nPos<0)
nPos = 0;
if (nPos != editor->nScrollPosY) {
int dy = editor->nScrollPosY - nPos;
editor->nScrollPosY = nPos;
SetScrollPos(hWnd, SB_VERT, nPos, TRUE);
if (editor->bRedraw)
{
ScrollWindow(hWnd, 0, dy, NULL, NULL);
UpdateWindow(hWnd);
}
}
ME_ScrollDown(editor, lParam * 8); /* FIXME follow the original */
return TRUE; /* Should return false if a single line richedit control */
}
case WM_CLEAR:
@ -1853,36 +1825,19 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
case EM_SCROLLCARET:
{
int top, bottom; /* row's edges relative to document top */
int nPos;
ME_DisplayItem *para, *row;
nPos = ME_GetYScrollPos(editor);
row = ME_RowStart(editor->pCursors[0].pRun);
para = ME_GetParagraph(row);
top = para->member.para.nYPos + row->member.row.nYPos;
bottom = top + row->member.row.nHeight;
if ((top < editor->nScrollPosY)
|| (editor->nScrollPosY + editor->sizeWindow.cy < bottom))
{
int dy;
int prevScrollPosY = editor->nScrollPosY;
if (top < editor->nScrollPosY) /* caret above window */
editor->nScrollPosY = top;
else /* caret below window */
editor->nScrollPosY = bottom - editor->sizeWindow.cy;
if (editor->nScrollPosY < 0)
editor->nScrollPosY = 0;
dy = prevScrollPosY - editor->nScrollPosY;
SetScrollPos(hWnd, SB_VERT, editor->nScrollPosY, TRUE);
if (editor->bRedraw)
{
ScrollWindow(hWnd, 0, dy, NULL, NULL);
UpdateWindow(hWnd);
}
}
if (top < nPos) /* caret above window */
ME_ScrollAbs(editor, top);
else if (nPos + editor->sizeWindow.cy < bottom) /*below*/
ME_ScrollAbs(editor, bottom - editor->sizeWindow.cy);
return 0;
}
case WM_SETFONT:
@ -2066,7 +2021,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
{
POINT *point = (POINT *)lParam;
point->x = 0; /* FIXME side scrolling not implemented */
point->y = editor->nScrollPosY;
point->y = ME_GetYScrollPos(editor);
return 1;
}
case EM_GETTEXTRANGE:
@ -2300,12 +2255,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
case WM_CREATE:
if (GetWindowLongW(hWnd, GWL_STYLE) & WS_HSCROLL)
{ /* Squelch the default horizontal scrollbar it would make */
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_POS | SIF_RANGE;
si.nMax = 0;
si.nMin = 0;
si.nPos = 0;
SetScrollInfo(hWnd, SB_HORZ, &si, FALSE);
ShowScrollBar(editor->hWnd, SB_HORZ, FALSE);
}
ME_CommitUndo(editor);
ME_WrapMarkedParagraphs(editor);
@ -2428,79 +2378,51 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
case EM_SCROLL: /* fall through */
case WM_VSCROLL:
{
int nEnd;
int nPos = editor->nScrollPosY;
int origNPos = nPos;
int lineHeight = 24;
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_PAGE|SIF_POS|SIF_RANGE|SIF_TRACKPOS;
GetScrollInfo(hWnd, SB_VERT, &si);
int origNPos;
int lineHeight;
origNPos = ME_GetYScrollPos(editor);
lineHeight = 24;
if (editor && editor->pBuffer && editor->pBuffer->pDefaultStyle)
lineHeight = editor->pBuffer->pDefaultStyle->tm.tmHeight;
if (lineHeight <= 0) lineHeight = 24;
switch(LOWORD(wParam)) {
switch(LOWORD(wParam))
{
case SB_LINEUP:
nPos -= lineHeight;
if (nPos<0) nPos = 0;
ME_ScrollUp(editor,lineHeight);
break;
case SB_LINEDOWN:
{
nEnd = editor->nTotalLength - editor->sizeWindow.cy;
if (nEnd < 0) nEnd = 0;
nPos += lineHeight;
if (nPos>=nEnd) nPos = nEnd;
ME_ScrollDown(editor,lineHeight);
break;
}
case SB_PAGEUP:
nPos -= editor->sizeWindow.cy;
if (nPos<0) nPos = 0;
ME_ScrollUp(editor,editor->sizeWindow.cy);
break;
case SB_PAGEDOWN:
nEnd = editor->nTotalLength - editor->sizeWindow.cy;
if (nEnd < 0) nEnd = 0;
nPos += editor->sizeWindow.cy;
if (nPos>=nEnd) nPos = nEnd;
ME_ScrollDown(editor,editor->sizeWindow.cy);
break;
case SB_THUMBTRACK:
case SB_THUMBPOSITION:
nPos = si.nTrackPos;
ME_ScrollAbs(editor,HIWORD(wParam));
break;
}
if (nPos != editor->nScrollPosY) {
int dy = editor->nScrollPosY - nPos;
editor->nScrollPosY = nPos;
SetScrollPos(hWnd, SB_VERT, nPos, TRUE);
if (editor->bRedraw)
{
ScrollWindow(hWnd, 0, dy, NULL, NULL);
UpdateWindow(hWnd);
}
}
if (msg == EM_SCROLL)
return 0x00010000 | (((nPos - origNPos)/lineHeight) & 0xffff);
return 0x00010000 | (((ME_GetYScrollPos(editor) - origNPos)/lineHeight) & 0xffff);
break;
}
case WM_MOUSEWHEEL:
{
int gcWheelDelta = 0, nPos = editor->nScrollPosY, nEnd = editor->nTotalLength - editor->sizeWindow.cy;
int gcWheelDelta;
UINT pulScrollLines;
SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
gcWheelDelta -= GET_WHEEL_DELTA_WPARAM(wParam);
gcWheelDelta = -GET_WHEEL_DELTA_WPARAM(wParam);
if (abs(gcWheelDelta) >= WHEEL_DELTA && pulScrollLines)
nPos += pulScrollLines * (gcWheelDelta / WHEEL_DELTA) * 8; /* FIXME follow the original */
if (nPos>=nEnd)
nPos = nEnd;
if (nPos<0)
nPos = 0;
if (nPos != editor->nScrollPosY) {
int dy = editor->nScrollPosY - nPos;
editor->nScrollPosY = nPos;
SetScrollPos(hWnd, SB_VERT, nPos, TRUE);
if (editor->bRedraw)
{
ScrollWindow(hWnd, 0, dy, NULL, NULL);
UpdateWindow(hWnd);
}
/* FIXME follow the original */
ME_ScrollDown(editor,pulScrollLines * (gcWheelDelta / WHEEL_DELTA) * 8);
}
break;
}
@ -2933,7 +2855,7 @@ int ME_AutoURLDetect(ME_TextEditor *editor, WCHAR curChar)
url.cpMin=text_pos;
url.cpMax=car_pos-1;
ME_SetCharFormat(editor, text_pos, (URLmax-text_pos), &link);
ME_Repaint(editor);
ME_RewrapRepaint(editor);
break;
}
}

View File

@ -173,7 +173,6 @@ void ME_MouseMove(ME_TextEditor *editor, int x, int y);
void ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars);
void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
const WCHAR *str, int len, ME_Style *style);
void ME_SetCharFormat(ME_TextEditor *editor, int nOfs, int nChars, CHARFORMAT2W *pFmt);
BOOL ME_ArrowKey(ME_TextEditor *ed, int nVKey, BOOL extend, BOOL ctrl);
void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC);
@ -228,15 +227,22 @@ void ME_Repaint(ME_TextEditor *editor);
void ME_RewrapRepaint(ME_TextEditor *editor);
void ME_UpdateRepaint(ME_TextEditor *editor);
void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph);
void ME_UpdateScrollBar(ME_TextEditor *editor);
int ME_GetYScrollPos(ME_TextEditor *editor);
void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun);
COLORREF ME_GetBackColor(ME_TextEditor *editor);
void ME_Scroll(ME_TextEditor *editor, int cx, int cy);
void ME_InvalidateSelection(ME_TextEditor *editor);
void ME_QueueInvalidateFromCursor(ME_TextEditor *editor, int nCursor);
BOOL ME_SetZoom(ME_TextEditor *editor, int numerator, int denominator);
/* scroll functions in paint.c */
void ME_ScrollAbs(ME_TextEditor *editor, int absY);
void ME_ScrollUp(ME_TextEditor *editor, int cy);
void ME_ScrollDown(ME_TextEditor *editor, int cy);
void ME_Scroll(ME_TextEditor *editor, int value, int type);
void ME_UpdateScrollBar(ME_TextEditor *editor);
int ME_GetYScrollPos(ME_TextEditor *editor);
BOOL ME_GetYScrollVisible(ME_TextEditor *editor);
/* richole.c */
extern LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *);

View File

@ -306,8 +306,6 @@ typedef struct tagME_TextEditor
int nLastSelStart, nLastSelEnd;
ME_DisplayItem *pLastSelStartPara, *pLastSelEndPara;
ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE];
BOOL bScrollX, bScrollY;
int nScrollPosY;
int nZoomNumerator, nZoomDenominator;
RECT rcFormat;
BOOL bRedraw;

View File

@ -96,36 +96,42 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, RECT *rcUpda
void ME_Repaint(ME_TextEditor *editor)
{
ME_Cursor *pCursor = &editor->pCursors[0];
if (ME_WrapMarkedParagraphs(editor)) {
ME_UpdateScrollBar(editor);
}
if (editor->bRedraw)
if (ME_WrapMarkedParagraphs(editor))
{
ME_EnsureVisible(editor, pCursor->pRun);
UpdateWindow(editor->hWnd);
ME_UpdateScrollBar(editor);
FIXME("ME_Repaint had to call ME_WrapMarkedParagraphs\n");
}
ME_SendOldNotify(editor, EN_UPDATE);
UpdateWindow(editor->hWnd);
}
void ME_UpdateRepaint(ME_TextEditor *editor)
{
/*
InvalidateRect(editor->hWnd, NULL, TRUE);
*/
/* Should be called whenever the contents of the control have changed */
ME_Cursor *pCursor;
if (ME_WrapMarkedParagraphs(editor))
ME_UpdateScrollBar(editor);
/* Ensure that the cursor is visible */
pCursor = &editor->pCursors[0];
ME_EnsureVisible(editor, pCursor->pRun);
ME_SendOldNotify(editor, EN_CHANGE);
ME_Repaint(editor);
ME_SendOldNotify(editor, EN_UPDATE);
ME_SendSelChange(editor);
}
void
ME_RewrapRepaint(ME_TextEditor *editor)
{
/* RewrapRepaint should be called whenever the control has changed in
* looks, but not content. Like resizing. */
ME_MarkAllForWrapping(editor);
ME_WrapMarkedParagraphs(editor);
ME_UpdateScrollBar(editor);
ME_Repaint(editor);
}
@ -375,88 +381,118 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) {
SetTextAlign(c->hDC, align);
}
void ME_Scroll(ME_TextEditor *editor, int cx, int cy)
void ME_ScrollAbs(ME_TextEditor *editor, int absY)
{
ME_Scroll(editor, absY, 1);
}
void ME_ScrollUp(ME_TextEditor *editor, int cy)
{
ME_Scroll(editor, cy, 2);
}
void ME_ScrollDown(ME_TextEditor *editor, int cy)
{
ME_Scroll(editor, cy, 3);
}
void ME_Scroll(ME_TextEditor *editor, int value, int type)
{
SCROLLINFO si;
HWND hWnd = editor->hWnd;
int nOrigPos, nNewPos, nActualScroll;
nOrigPos = ME_GetYScrollPos(editor);
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_POS;
GetScrollInfo(hWnd, SB_VERT, &si);
si.nPos = editor->nScrollPosY -= cy;
SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
switch (type)
{
case 1:
/*Scroll absolutly*/
si.nPos = value;
break;
case 2:
/* Scroll up - towards the beginning of the document */
si.nPos = nOrigPos - value;
break;
case 3:
/* Scroll down - towards the end of the document */
si.nPos = nOrigPos + value;
break;
default:
FIXME("ME_Scroll called incorrectly\n");
si.nPos = 0;
}
nNewPos = SetScrollInfo(editor->hWnd, SB_VERT, &si, editor->bRedraw);
nActualScroll = nOrigPos - nNewPos;
if (editor->bRedraw)
{
if (abs(cy) > editor->sizeWindow.cy)
if (abs(nActualScroll) > editor->sizeWindow.cy)
InvalidateRect(editor->hWnd, NULL, TRUE);
else
ScrollWindowEx(hWnd, cx, cy, NULL, NULL, NULL, NULL, SW_ERASE|SW_INVALIDATE);
ScrollWindowEx(editor->hWnd, 0, nActualScroll, NULL, NULL, NULL, NULL, SW_INVALIDATE);
ME_Repaint(editor);
}
ME_UpdateScrollBar(editor);
}
void ME_UpdateScrollBar(ME_TextEditor *editor)
{
HWND hWnd = editor->hWnd;
SCROLLINFO si;
BOOL bUpdateScrollBars;
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
GetScrollInfo(hWnd, SB_VERT, &si);
bUpdateScrollBars = (editor->bScrollY)&& ((si.nMax != editor->nTotalLength) || (si.nPage != editor->sizeWindow.cy));
if (editor->bScrollY != (si.nMax > 0))
{ /* The scroll bar needs to be shown or hidden */
si.fMask = SIF_RANGE | SIF_PAGE;
void ME_UpdateScrollBar(ME_TextEditor *editor)
{
/* Note that this is the only funciton that should ever call SetScrolLInfo
* with SIF_PAGE or SIF_RANGE. SetScrollPos and SetScrollRange should never
* be used at all. */
HWND hWnd;
SCROLLINFO si;
BOOL bScrollBarWasVisible,bScrollBarWillBeVisible;
if (ME_WrapMarkedParagraphs(editor))
FIXME("ME_UpdateScrollBar had to call ME_WrapMarkedParagraphs\n");
hWnd = editor->hWnd;
si.cbSize = sizeof(si);
bScrollBarWasVisible = ME_GetYScrollVisible(editor);
bScrollBarWillBeVisible = editor->nTotalLength > editor->sizeWindow.cy;
if (bScrollBarWasVisible != bScrollBarWillBeVisible)
{
ShowScrollBar(hWnd, SB_VERT, bScrollBarWillBeVisible);
ME_MarkAllForWrapping(editor);
ME_WrapMarkedParagraphs(editor);
}
si.fMask = SIF_PAGE | SIF_RANGE;
if (GetWindowLongW(hWnd, GWL_STYLE) & ES_DISABLENOSCROLL)
si.fMask |= SIF_DISABLENOSCROLL;
si.nMin = 0;
si.nMax = editor->nTotalLength;
si.nPage = editor->sizeWindow.cy;
if (editor->bScrollY)
si.nMax = editor->nTotalLength;
else
si.nMax = 0;
SetScrollInfo(hWnd, SB_VERT, &si, FALSE);
ME_MarkAllForWrapping(editor);
ME_WrapMarkedParagraphs(editor);
bUpdateScrollBars = TRUE;
}
if (bUpdateScrollBars)
{
int nScroll = 0;
si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
if (GetWindowLongW(hWnd, GWL_STYLE) & ES_DISABLENOSCROLL)
si.fMask |= SIF_DISABLENOSCROLL;
if (editor->bScrollY)
{
si.nMax = editor->nTotalLength;
si.nPage = editor->sizeWindow.cy;
if (si.nPos > si.nMax-si.nPage)
{
nScroll = (si.nMax-si.nPage)-si.nPos;
si.nPos = si.nMax-si.nPage;
}
}
else
{
si.nMax = 0;
si.nPage = 0;
si.nPos = 0;
}
TRACE("min=%d max=%d page=%d pos=%d shift=%d\n", si.nMin, si.nMax, si.nPage, si.nPos, nScroll);
editor->nScrollPosY = si.nPos;
TRACE("min=%d max=%d page=%d\n", si.nMin, si.nMax, si.nPage);
SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
if (nScroll)
ScrollWindow(hWnd, 0, -nScroll, NULL, NULL);
}
}
int ME_GetYScrollPos(ME_TextEditor *editor)
{
return editor->nScrollPosY;
SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
GetScrollInfo(editor->hWnd, SB_VERT, &si);
return si.nPos;
}
BOOL ME_GetYScrollVisible(ME_TextEditor *editor)
{ /* Returns true if the scrollbar is visible */
SCROLLBARINFO sbi;
sbi.cbSize = sizeof(sbi);
GetScrollBarInfo(editor->hWnd, OBJID_VSCROLL, &sbi);
return ((sbi.rgstate[0] & STATE_SYSTEM_INVISIBLE) == 0);
}
void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun)
@ -464,7 +500,6 @@ void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun)
ME_DisplayItem *pRow = ME_FindItemBack(pRun, diStartRow);
ME_DisplayItem *pPara = ME_FindItemBack(pRun, diParagraph);
int y, yrel, yheight, yold;
HWND hWnd = editor->hWnd;
assert(pRow);
assert(pPara);
@ -473,24 +508,11 @@ void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun)
yheight = pRow->member.row.nHeight;
yold = ME_GetYScrollPos(editor);
yrel = y - yold;
if (yrel < 0) {
editor->nScrollPosY = y;
SetScrollPos(hWnd, SB_VERT, y, TRUE);
if (editor->bRedraw)
{
ScrollWindow(hWnd, 0, -yrel, NULL, NULL);
UpdateWindow(hWnd);
}
} else if (yrel + yheight > editor->sizeWindow.cy) {
int newy = y+yheight-editor->sizeWindow.cy;
editor->nScrollPosY = newy;
SetScrollPos(hWnd, SB_VERT, newy, TRUE);
if (editor->bRedraw)
{
ScrollWindow(hWnd, 0, -(newy-yold), NULL, NULL);
UpdateWindow(hWnd);
}
}
if (y < yold)
ME_ScrollAbs(editor,y);
else if (yrel + yheight > editor->sizeWindow.cy)
ME_ScrollAbs(editor,y+yheight-editor->sizeWindow.cy);
}