diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c index ca50f189e9..4b0bfcf4ce 100644 --- a/dlls/riched20/caret.c +++ b/dlls/riched20/caret.c @@ -216,9 +216,8 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to) } -static void -ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor, - int *x, int *y, int *height) +void ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor, + int *x, int *y, int *height) { ME_DisplayItem *row; ME_DisplayItem *run = pCursor->pRun; diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index a63dea6637..e9d1e478c5 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -192,6 +192,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, int nChars, int ME_GetTextLength(ME_TextEditor *editor) DECLSPEC_HIDDEN; int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how) DECLSPEC_HIDDEN; ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor) DECLSPEC_HIDDEN; +void ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor, int *x, int *y, int *height) DECLSPEC_HIDDEN; /* context.c */ void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC) DECLSPEC_HIDDEN; diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c index be35521e02..1013e6792c 100644 --- a/dlls/riched20/richole.c +++ b/dlls/riched20/richole.c @@ -2428,13 +2428,29 @@ static HRESULT WINAPI ITextRange_fnSetPoint(ITextRange *me, LONG x, LONG y, LONG static HRESULT WINAPI ITextRange_fnScrollIntoView(ITextRange *me, LONG value) { ITextRangeImpl *This = impl_from_ITextRange(me); + ME_TextEditor *editor; + ME_Cursor cursor; + int x, y, height; - FIXME("(%p)->(%d): stub\n", This, value); + TRACE("(%p)->(%d)\n", This, value); if (!This->child.reole) return CO_E_RELEASED; - return E_NOTIMPL; + editor = This->child.reole->editor; + + switch (value) + { + case tomStart: + ME_CursorFromCharOfs(editor, This->start, &cursor); + ME_GetCursorCoordinates(editor, &cursor, &x, &y, &height); + break; + default: + FIXME("bStart value %d not handled\n", value); + return E_NOTIMPL; + } + ME_ScrollAbs(editor, x, y); + return S_OK; } static HRESULT WINAPI ITextRange_fnGetEmbeddedObject(ITextRange *me, IUnknown **ppv) diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c index 7c6c5d5c1e..6da3ce3004 100644 --- a/dlls/riched20/tests/richole.c +++ b/dlls/riched20/tests/richole.c @@ -53,6 +53,7 @@ static HWND new_window(LPCSTR lpClassName, DWORD dwStyle, HWND parent) HWND hwnd = CreateWindowA(lpClassName, NULL, dwStyle | WS_POPUP | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE, 0, 0, 200, 60, parent, NULL, hmoduleRichEdit, NULL); + ok(hwnd != NULL, "class: %s, error: %d\n", lpClassName, (int) GetLastError()); return hwnd; } @@ -761,6 +762,65 @@ static void test_ITextRange_GetChar(void) ITextRange_Release(txtRge); } +/* Helper function for testing ITextRange_ScrollIntoView */ +static void check_range(HWND w, ITextDocument* doc, int first, int lim, + LONG bStart, int expected_nonzero) +{ + SCROLLINFO si; + ITextRange *txtRge = NULL; + HRESULT hres; + + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_POS | SIF_RANGE; + + hres = ITextDocument_Range(doc, first, lim, &txtRge); + ok(hres == S_OK, "got 0x%08x\n", hres); + hres = ITextRange_ScrollIntoView(txtRge, bStart); + ok(hres == S_OK, "got 0x%08x\n", hres); + GetScrollInfo(w, SB_VERT, &si); + if (expected_nonzero) { + ok(si.nPos != 0, + "Scrollbar at 0, should be >0. (TextRange %d-%d, scroll range %d-%d.)\n", + first, lim, si.nMin, si.nMax); + } else { + ok(si.nPos == 0, + "Scrollbar at %d, should be 0. (TextRange %d-%d, scroll range %d-%d.)\n", + si.nPos, first, lim, si.nMin, si.nMax); + } +} + +static void test_ITextRange_ScrollIntoView(void) +{ + HWND w; + IRichEditOle *reOle = NULL; + ITextDocument *txtDoc = NULL; + ITextRange *txtRge = NULL; + HRESULT hres; + static const CHAR test_text1[] = "1\n2\n3\n4\n5\n6\n7\n8\n9\n10"; + + create_interfaces(&w, &reOle, &txtDoc, NULL); + SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); + + /* Scroll to the top. */ + check_range(w, txtDoc, 0, 1, tomStart, 0); + + /* Scroll to the bottom. */ + check_range(w, txtDoc, 19, 20, tomStart, 1); + + /* Back up to the top. */ + check_range(w, txtDoc, 0, 1, tomStart, 0); + + /* Large range */ + check_range(w, txtDoc, 0, 20, tomStart, 0); + + hres = ITextDocument_Range(txtDoc, 0, 0, &txtRge); + ok(hres == S_OK, "got 0x%08x\n", hres); + release_interfaces(&w, &reOle, &txtDoc, NULL); + hres = ITextRange_ScrollIntoView(txtRge, tomStart); + ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres); + ITextRange_Release(txtRge); +} + static void test_ITextSelection_GetChar(void) { HWND w; @@ -3352,6 +3412,7 @@ START_TEST(richole) test_ITextSelection_Collapse(); test_ITextDocument_Range(); test_ITextRange_GetChar(); + test_ITextRange_ScrollIntoView(); test_ITextRange_GetStart_GetEnd(); test_ITextRange_GetDuplicate(); test_ITextRange_Collapse();