- made string operations consistent wrt whitespace handling (which should greatly improve stability of the wrap code and eliminate regressions of the most recent versions) - completely new scrollbar handling (much more reliable) and related redraw fixes - Page Down handler (no Page Up yet, fixing wrap/redraw/scrollbar bugs was of higher priority)
diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c index 98a638e..8ebac54 100644 --- a/dlls/riched20/caret.c +++ b/dlls/riched20/caret.c
@@ -697,6 +697,54 @@ assert(pCursor->pRun->type == diRun); } +void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor) +{ + ME_DisplayItem *pRun = pCursor->pRun; + ME_DisplayItem *pLast, *p; + int x, y, ys, yd, yp, yprev; + ME_Cursor tmp_curs = *pCursor; + + x = ME_GetXForArrow(editor, pCursor); + if (!pCursor->nOffset && editor->bCaretAtEnd) + pRun = ME_FindItemBack(pRun, diRun); + + p = ME_FindItemBack(pRun, diStartRowOrParagraph); + assert(p->type == diStartRow); + yp = ME_FindItemBack(p, diParagraph)->member.para.nYPos; + yprev = ys = y = yp + p->member.row.nYPos; + yd = y + editor->sizeWindow.cy; + pLast = p; + + do { + p = ME_FindItemFwd(p, diStartRowOrParagraph); + if (!p) + break; + if (p->type == diParagraph) { + yp = p->member.para.nYPos; + continue; + } + y = yp + p->member.row.nYPos; + if (y >= yd) + break; + pLast = p; + yprev = y; + } while(1); + + pCursor->pRun = ME_FindRunInRow(editor, pLast, x, &pCursor->nOffset, &editor->bCaretAtEnd); + ME_UpdateSelection(editor, &tmp_curs); + if (yprev >= editor->nTotalLength-editor->sizeWindow.cy) + { + ME_EnsureVisible(editor, ME_FindItemBack(editor->pBuffer->pLast, diRun)); + ME_Repaint(editor); + } + else { + ME_Repaint(editor); + ME_Scroll(editor, 0, ys-yprev); + } + assert(pCursor->pRun); + assert(pCursor->pRun->type == diRun); +} + void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_DisplayItem *pRow = ME_FindItemBack(pCursor->pRun, diStartRow); @@ -798,7 +846,7 @@ return TRUE; } -void ME_RepaintSelection(ME_TextEditor *editor, ME_Cursor *pTempCursor) +BOOL ME_UpdateSelection(ME_TextEditor *editor, ME_Cursor *pTempCursor) { ME_Cursor old_anchor = editor->pCursors[1]; @@ -807,20 +855,30 @@ /* any selection was present ? if so, it's no more, repaint ! */ editor->pCursors[1] = editor->pCursors[0]; if (memcmp(pTempCursor, &old_anchor, sizeof(ME_Cursor))) { - ME_Repaint(editor); - return; + return TRUE; } - return; + return FALSE; } else { if (!memcmp(pTempCursor, &editor->pCursors[1], sizeof(ME_Cursor))) /* starting selection */ { editor->pCursors[1] = *pTempCursor; + return TRUE; +/* ME_EnsureVisible(editor, editor->pCursors[0].pRun); */ } } ME_Repaint(editor); + return TRUE; +} + +void ME_RepaintSelection(ME_TextEditor *editor, ME_Cursor *pTempCursor) +{ + if (ME_UpdateSelection(editor, pTempCursor)) { + ME_EnsureVisible(editor, editor->pCursors[0].pRun); + ME_Repaint(editor); + } } void ME_DeleteSelection(ME_TextEditor *editor) @@ -883,6 +941,11 @@ ME_RepaintSelection(editor, &tmp_curs); ME_SendSelChange(editor); return TRUE; + case VK_NEXT: + ME_ArrowPageDown(editor, p); + ME_ClearTempStyle(editor); + ME_SendSelChange(editor); + return TRUE; } editor->nUDArrowX = -1;
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index 6775986..7484522 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c
@@ -505,10 +505,10 @@ ME_CommitUndo(editor); ME_ReleaseStyle(style); editor->nEventMask = nEventMask; + InvalidateRect(editor->hWnd, NULL, TRUE); ME_UpdateRepaint(editor); if (!(format & SFF_SELECTION)) { ME_ClearTempStyle(editor); - ME_EnsureVisible(editor, editor->pCursors[0].pRun); } ME_MoveCaret(editor); ME_SendSelChange(editor); @@ -1147,6 +1147,8 @@ case WM_SIZE: { ME_MarkAllForWrapping(editor); + ME_WrapMarkedParagraphs(editor); + ME_UpdateScrollBar(editor); ME_Repaint(editor); return DefWindowProcW(hWnd, msg, wParam, lParam); }
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index 0a2b8ae..6590482 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h
@@ -161,13 +161,14 @@ void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars); int ME_GetTextLength(ME_TextEditor *editor); ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor); +BOOL ME_UpdateSelection(ME_TextEditor *editor, ME_Cursor *pTempCursor); /* wrap.c */ void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp); ME_DisplayItem *ME_MakeRow(int height, int baseline, int width); void ME_InsertRowStart(ME_WrapContext *wc, ME_DisplayItem *pEnd); void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp); -void ME_WrapMarkedParagraphs(ME_TextEditor *editor); +BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor); /* para.c */ ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *run); @@ -189,10 +190,11 @@ void ME_Repaint(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 ypos); +void ME_UpdateScrollBar(ME_TextEditor *editor); int ME_GetScrollPos(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); /* richole.c */ extern LRESULT CreateIRichEditOle(LPVOID *);
diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h index 92acb12..b9fe8b9 100644 --- a/dlls/riched20/editstr.h +++ b/dlls/riched20/editstr.h
@@ -246,6 +246,7 @@ int nLastSelStart, nLastSelEnd; ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE]; ME_OutStream *pStream; + BOOL bScrollX, bScrollY; } ME_TextEditor; typedef struct tagME_Context
diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c index 21c7a79..1a0f04c 100644 --- a/dlls/riched20/paint.c +++ b/dlls/riched20/paint.c
@@ -35,7 +35,9 @@ item = editor->pBuffer->pFirst->next; c.pt.y -= yoffset; while(item != editor->pBuffer->pLast) { + int ye; assert(item->type == diParagraph); + ye = c.pt.y + item->member.para.nHeight; if (!bOnlyNew || (item->member.para.nFlags & MEPF_REPAINT)) { BOOL bPaint = (rcUpdate == NULL); @@ -45,10 +47,11 @@ if (bPaint) { ME_DrawParagraph(&c, item); - item->member.para.nFlags &= ~MEPF_REPAINT; + if (!rcUpdate || (rcUpdate->top<=c.pt.y && rcUpdate->bottom>=ye)) + item->member.para.nFlags &= ~MEPF_REPAINT; } } - c.pt.y += item->member.para.nHeight; + c.pt.y = ye; item = item->member.para.next_para; } if (c.pt.y<c.rcView.bottom) { @@ -152,12 +155,15 @@ assert(pRun == pCursor->pRun); assert(nOffset == pCursor->nOffset); ME_MarkSelectionForRepaint(editor); - ME_WrapMarkedParagraphs(editor); + if (ME_WrapMarkedParagraphs(editor)) { + ME_UpdateScrollBar(editor); + } hDC = GetDC(editor->hWnd); ME_HideCaret(editor); ME_PaintContent(editor, hDC, TRUE, NULL); ReleaseDC(editor->hWnd, hDC); ME_ShowCaret(editor); + ME_EnsureVisible(editor, pCursor->pRun); } void ME_UpdateRepaint(ME_TextEditor *editor) @@ -372,38 +378,67 @@ SetTextAlign(c->hDC, align); } -void ME_UpdateScrollBar(ME_TextEditor *editor, int ypos) +void ME_Scroll(ME_TextEditor *editor, int cx, int cy) { - float perc = 0.0; SCROLLINFO si; HWND hWnd = editor->hWnd; - int overflow = editor->nTotalLength - editor->sizeWindow.cy; - si.cbSize = sizeof(SCROLLINFO); - si.fMask = SIF_PAGE|SIF_POS|SIF_RANGE|SIF_TRACKPOS; - GetScrollInfo(hWnd, SB_VERT, &si); - - if (ypos < 0) { - if (si.nMax<1) si.nMax = 1; - perc = 1.0*si.nPos/si.nMax; - ypos = perc*overflow; - } - if (ypos >= overflow && overflow > 0) - ypos = overflow - 1; - if (overflow > 0) { - EnableScrollBar(hWnd, SB_VERT, ESB_ENABLE_BOTH); - SetScrollRange(hWnd, SB_VERT, 0, overflow, FALSE); - SetScrollPos(hWnd, SB_VERT, ypos, TRUE); - } else { - EnableScrollBar(hWnd, SB_VERT, ESB_DISABLE_BOTH); - SetScrollRange(hWnd, SB_VERT, 0, 0, FALSE); - SetScrollPos(hWnd, SB_VERT, 0, TRUE); - } - if (ypos != si.nPos) + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_POS; + GetScrollInfo(hWnd, SB_VERT, &si); + si.nPos -= cy; + SetScrollInfo(hWnd, SB_VERT, &si, TRUE); + ScrollWindow(hWnd, cx, cy, NULL, NULL); +} + +void ME_UpdateScrollBar(ME_TextEditor *editor) +{ + HWND hWnd = editor->hWnd; + SCROLLINFO si; + int nOldLen = editor->nTotalLength; + BOOL bScrollY = (editor->nTotalLength > editor->sizeWindow.cy); + BOOL bUpdateScrollBars; + si.cbSize = sizeof(si); + si.fMask = SIF_POS | SIF_RANGE; + GetScrollInfo(hWnd, SB_VERT, &si); + bUpdateScrollBars = (bScrollY || editor->bScrollY)&& ((si.nMax != nOldLen) || (si.nPage != editor->sizeWindow.cy)); + + if (bScrollY != editor->bScrollY) { - TRACE("ScrollWindow(%d, %d, %d, %0.4f)\n", si.nPos, si.nMax, ypos, perc); - ScrollWindow(hWnd, 0, si.nPos - ypos, NULL, NULL); - UpdateWindow(hWnd); + si.fMask = SIF_RANGE | SIF_PAGE; + si.nMin = 0; + si.nPage = editor->sizeWindow.cy; + if (bScrollY) { + si.nMax = editor->nTotalLength; + } else { + si.nMax = 0; + } + SetScrollInfo(hWnd, SB_VERT, &si, FALSE); + ME_MarkAllForWrapping(editor); + editor->bScrollY = bScrollY; + ME_WrapMarkedParagraphs(editor); + bUpdateScrollBars = TRUE; + } + if (bUpdateScrollBars) { + int nScroll = 0; + si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; + if (editor->nTotalLength > editor->sizeWindow.cy) { + 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); + SetScrollInfo(hWnd, SB_VERT, &si, TRUE); + if (nScroll) + ScrollWindow(hWnd, 0, -nScroll, NULL, NULL); } } @@ -416,18 +451,24 @@ { ME_DisplayItem *pRow = ME_FindItemBack(pRun, diStartRow); ME_DisplayItem *pPara = ME_FindItemBack(pRun, diParagraph); - int y, yrel, yheight; + int y, yrel, yheight, yold; + HWND hWnd = editor->hWnd; assert(pRow); assert(pPara); y = pPara->member.para.nYPos+pRow->member.row.nYPos; yheight = pRow->member.row.nHeight; - yrel = y - ME_GetScrollPos(editor); - if (yrel < 0) - ME_UpdateScrollBar(editor, y); - else if (yrel + yheight > editor->sizeWindow.cy) - { - ME_UpdateScrollBar(editor, y + yheight - editor->sizeWindow.cy); + yold = ME_GetScrollPos(editor); + yrel = y - yold; + if (yrel < 0) { + SetScrollPos(hWnd, SB_VERT, y, TRUE); + ScrollWindow(hWnd, 0, -yrel, NULL, NULL); + UpdateWindow(hWnd); + } else if (yrel + yheight > editor->sizeWindow.cy) { + int newy = y+yheight-editor->sizeWindow.cy; + SetScrollPos(hWnd, SB_VERT, newy, TRUE); + ScrollWindow(hWnd, 0, -(newy-yold), NULL, NULL); + UpdateWindow(hWnd); } }
diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c index 0bc2a8e..6440b6d 100644 --- a/dlls/riched20/run.c +++ b/dlls/riched20/run.c
@@ -174,6 +174,8 @@ assert(p->member.run.nCharOfs != -1); ME_GetParagraph(p)->member.para.nFlags |= MEPF_REWRAP; + if (editor->bCaretAtEnd && editor->pCursors[0].pRun == pNext) + editor->bCaretAtEnd = FALSE; for (i=0; i<editor->nCursors; i++) { if (editor->pCursors[i].pRun == pNext) { editor->pCursors[i].pRun = p;
diff --git a/dlls/riched20/string.c b/dlls/riched20/string.c index 42ba34c..6abd22a 100644 --- a/dlls/riched20/string.c +++ b/dlls/riched20/string.c
@@ -123,7 +123,6 @@ int ME_IsSplitable(ME_String *s) { - /* FIXME multibyte */ WCHAR *pos = s->szData; WCHAR ch; while(ME_IsWSpace(*pos++)) @@ -131,7 +130,7 @@ pos--; while((ch = *pos++) != 0) { - if (ME_IsWSpace(*pos++)) + if (ME_IsWSpace(ch)) return 1; } return 0; @@ -255,7 +254,7 @@ int ME_FindNonWhitespaceV(ME_String *s, int nVChar) { int i; - for (i = nVChar; isspace(s->szData[i]) && i<s->nLen; i++) + for (i = nVChar; i<s->nLen && ME_IsWSpace(s->szData[i]); i++) ; return i; @@ -264,7 +263,7 @@ /* note: returns offset of the first trailing whitespace */ int ME_ReverseFindNonWhitespaceV(ME_String *s, int nVChar) { int i; - for (i = nVChar; i>0 && isspace(s->szData[i-1]); i--) + for (i = nVChar; i>0 && ME_IsWSpace(s->szData[i-1]); i--) ; return i; @@ -273,7 +272,7 @@ /* note: returns offset of the first trailing nonwhitespace */ int ME_ReverseFindWhitespaceV(ME_String *s, int nVChar) { int i; - for (i = nVChar; i>0 && !isspace(s->szData[i-1]); i--) + for (i = nVChar; i>0 && !ME_IsWSpace(s->szData[i-1]); i--) ; return i;
diff --git a/dlls/riched20/wrap.c b/dlls/riched20/wrap.c index 5f48e17..db92951 100644 --- a/dlls/riched20/wrap.c +++ b/dlls/riched20/wrap.c
@@ -409,11 +409,12 @@ } } -void ME_WrapMarkedParagraphs(ME_TextEditor *editor) { +BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) { HWND hWnd = editor->hWnd; HDC hDC = GetDC(hWnd); ME_DisplayItem *item; ME_Context c; + BOOL bModified = FALSE; ME_InitContext(&c, editor, hDC); c.pt.x = 0; @@ -433,6 +434,8 @@ if (bRedraw) item->member.para.nFlags |= MEPF_REPAINT; + bModified = bModified | bRedraw; + c.pt.y += item->member.para.nHeight; item = item->member.para.next_para; } @@ -442,4 +445,5 @@ ME_DestroyContext(&c); ReleaseDC(hWnd, hDC); + return bModified; }