From 08c4de06a1acb6109e665ab40218d88b2680c0d7 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Tue, 30 Mar 2021 12:36:47 +0100 Subject: [PATCH] riched20: Add support for EN_[HV]SCROLL notifications. Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/riched20/editor.c | 20 +++++------ dlls/riched20/editor.h | 6 ++-- dlls/riched20/paint.c | 47 +++++++++++++------------- dlls/riched20/richole.c | 2 +- dlls/riched20/tests/txtsrv.c | 64 ++++++++++++++++++++++++++++++++++-- 5 files changed, 99 insertions(+), 40 deletions(-) diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index 28b5cb1512d..dccc431f041 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -3377,7 +3377,7 @@ LRESULT editor_handle_message( ME_TextEditor *editor, UINT msg, WPARAM wParam, case EM_SETSCROLLPOS: { POINT *point = (POINT *)lParam; - ME_ScrollAbs(editor, point->x, point->y); + scroll_abs( editor, point->x, point->y, TRUE ); return 0; } case EM_AUTOURLDETECT: @@ -3986,12 +3986,11 @@ LRESULT editor_handle_message( ME_TextEditor *editor, UINT msg, WPARAM wParam, switch(LOWORD(wParam)) { case SB_LEFT: - ME_ScrollAbs(editor, 0, 0); + scroll_abs( editor, 0, 0, TRUE ); break; case SB_RIGHT: - ME_ScrollAbs(editor, - editor->horz_si.nMax - (int)editor->horz_si.nPage, - editor->vert_si.nMax - (int)editor->vert_si.nPage); + scroll_abs( editor, editor->horz_si.nMax - (int)editor->horz_si.nPage, + editor->vert_si.nMax - (int)editor->vert_si.nPage, TRUE ); break; case SB_LINELEFT: ME_ScrollLeft(editor, scrollUnit); @@ -4011,7 +4010,7 @@ LRESULT editor_handle_message( ME_TextEditor *editor, UINT msg, WPARAM wParam, int pos = HIWORD(wParam); if (editor->horz_si.nMax > 0xffff) pos = MulDiv(pos, editor->horz_si.nMax, 0xffff); - ME_HScrollAbs(editor, pos); + scroll_h_abs( editor, pos, FALSE ); break; } } @@ -4028,12 +4027,11 @@ LRESULT editor_handle_message( ME_TextEditor *editor, UINT msg, WPARAM wParam, switch(LOWORD(wParam)) { case SB_TOP: - ME_ScrollAbs(editor, 0, 0); + scroll_abs( editor, 0, 0, TRUE ); break; case SB_BOTTOM: - ME_ScrollAbs(editor, - editor->horz_si.nMax - (int)editor->horz_si.nPage, - editor->vert_si.nMax - (int)editor->vert_si.nPage); + scroll_abs( editor, editor->horz_si.nMax - (int)editor->horz_si.nPage, + editor->vert_si.nMax - (int)editor->vert_si.nPage, TRUE ); break; case SB_LINEUP: ME_ScrollUp(editor,lineHeight); @@ -4053,7 +4051,7 @@ LRESULT editor_handle_message( ME_TextEditor *editor, UINT msg, WPARAM wParam, int pos = HIWORD(wParam); if (editor->vert_si.nMax > 0xffff) pos = MulDiv(pos, editor->vert_si.nMax, 0xffff); - ME_VScrollAbs(editor, pos); + scroll_v_abs( editor, pos, FALSE ); break; } } diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index 7a79df83c99..fa1e22f9b48 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -250,9 +250,9 @@ int ME_twips2pointsY(const ME_Context *c, int y) DECLSPEC_HIDDEN; /* scroll functions in paint.c */ -void ME_ScrollAbs(ME_TextEditor *editor, int x, int y) DECLSPEC_HIDDEN; -void ME_HScrollAbs(ME_TextEditor *editor, int x) DECLSPEC_HIDDEN; -void ME_VScrollAbs(ME_TextEditor *editor, int y) DECLSPEC_HIDDEN; +void scroll_abs( ME_TextEditor *editor, int x, int y, BOOL notify ) DECLSPEC_HIDDEN; +void scroll_h_abs( ME_TextEditor *editor, int x, BOOL notify ) DECLSPEC_HIDDEN; +void scroll_v_abs( ME_TextEditor *editor, int y, BOOL notify ) DECLSPEC_HIDDEN; void ME_ScrollUp(ME_TextEditor *editor, int cy) DECLSPEC_HIDDEN; void ME_ScrollDown(ME_TextEditor *editor, int cy) DECLSPEC_HIDDEN; void ME_ScrollLeft(ME_TextEditor *editor, int cx) DECLSPEC_HIDDEN; diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c index ad9f504db8e..550c3c97045 100644 --- a/dlls/riched20/paint.c +++ b/dlls/riched20/paint.c @@ -1070,7 +1070,7 @@ static void enable_show_scrollbar( ME_TextEditor *editor, INT bar, BOOL enable ) ITextHost_TxShowScrollBar( editor->texthost, bar, enable ); } -static void set_scroll_range_pos( ITextHost2 *host, INT bar, SCROLLINFO *info, BOOL set_range ) +static void set_scroll_range_pos( ME_TextEditor *editor, INT bar, SCROLLINFO *info, BOOL set_range, BOOL notify ) { LONG max_pos = info->nMax, pos = info->nPos; @@ -1080,11 +1080,14 @@ static void set_scroll_range_pos( ITextHost2 *host, INT bar, SCROLLINFO *info, B pos = MulDiv( pos, 0xffff, max_pos ); max_pos = 0xffff; } - if (set_range) ITextHost_TxSetScrollRange( host, bar, 0, max_pos, FALSE ); - ITextHost_TxSetScrollPos( host, bar, pos, TRUE ); + if (set_range) ITextHost_TxSetScrollRange( editor->texthost, bar, 0, max_pos, FALSE ); + ITextHost_TxSetScrollPos( editor->texthost, bar, pos, TRUE ); + + if (notify && editor->nEventMask & ENM_SCROLL) + ITextHost_TxNotify( editor->texthost, bar == SB_VERT ? EN_VSCROLL : EN_HSCROLL, NULL ); } -void ME_ScrollAbs(ME_TextEditor *editor, int x, int y) +void scroll_abs( ME_TextEditor *editor, int x, int y, BOOL notify ) { int scrollX = 0, scrollY = 0; @@ -1093,7 +1096,7 @@ void ME_ScrollAbs(ME_TextEditor *editor, int x, int y) x = max(x, editor->horz_si.nMin); scrollX = editor->horz_si.nPos - x; editor->horz_si.nPos = x; - set_scroll_range_pos( editor->texthost, SB_HORZ, &editor->horz_si, FALSE ); + set_scroll_range_pos( editor, SB_HORZ, &editor->horz_si, FALSE, notify ); } if (editor->vert_si.nPos != y) { @@ -1101,7 +1104,7 @@ void ME_ScrollAbs(ME_TextEditor *editor, int x, int y) y = max(y, editor->vert_si.nMin); scrollY = editor->vert_si.nPos - y; editor->vert_si.nPos = y; - set_scroll_range_pos( editor->texthost, SB_VERT, &editor->vert_si, FALSE ); + set_scroll_range_pos( editor, SB_VERT, &editor->vert_si, FALSE, notify ); } if (abs(scrollX) > editor->sizeWindow.cx || abs(scrollY) > editor->sizeWindow.cy) @@ -1114,34 +1117,34 @@ void ME_ScrollAbs(ME_TextEditor *editor, int x, int y) ME_Repaint(editor); } -void ME_HScrollAbs(ME_TextEditor *editor, int x) +void scroll_h_abs( ME_TextEditor *editor, int x, BOOL notify ) { - ME_ScrollAbs(editor, x, editor->vert_si.nPos); + scroll_abs( editor, x, editor->vert_si.nPos, notify ); } -void ME_VScrollAbs(ME_TextEditor *editor, int y) +void scroll_v_abs( ME_TextEditor *editor, int y, BOOL notify ) { - ME_ScrollAbs(editor, editor->horz_si.nPos, y); + scroll_abs( editor, editor->horz_si.nPos, y, notify ); } void ME_ScrollUp(ME_TextEditor *editor, int cy) { - ME_VScrollAbs(editor, editor->vert_si.nPos - cy); + scroll_v_abs( editor, editor->vert_si.nPos - cy, TRUE ); } void ME_ScrollDown(ME_TextEditor *editor, int cy) { - ME_VScrollAbs(editor, editor->vert_si.nPos + cy); + scroll_v_abs( editor, editor->vert_si.nPos + cy, TRUE ); } void ME_ScrollLeft(ME_TextEditor *editor, int cx) { - ME_HScrollAbs(editor, editor->horz_si.nPos - cx); + scroll_h_abs( editor, editor->horz_si.nPos - cx, TRUE ); } void ME_ScrollRight(ME_TextEditor *editor, int cx) { - ME_HScrollAbs(editor, editor->horz_si.nPos + cx); + scroll_h_abs( editor, editor->horz_si.nPos + cx, TRUE ); } void ME_UpdateScrollBar(ME_TextEditor *editor) @@ -1157,7 +1160,7 @@ void ME_UpdateScrollBar(ME_TextEditor *editor) enable = editor->nTotalWidth > editor->sizeWindow.cx; if (editor->horz_si.nPos && !enable) { - ME_HScrollAbs(editor, 0); + scroll_h_abs( editor, 0, TRUE ); /* ME_HScrollAbs will call this function, so nothing else needs to be done here. */ return; } @@ -1174,7 +1177,7 @@ void ME_UpdateScrollBar(ME_TextEditor *editor) editor->horz_si.nPage = editor->sizeWindow.cx; TRACE( "min = %d max = %d page = %d\n", editor->horz_si.nMin, editor->horz_si.nMax, editor->horz_si.nPage ); if ((enable || editor->horz_sb_enabled) && editor->scrollbars & WS_HSCROLL) - set_scroll_range_pos( editor->texthost, SB_HORZ, &editor->horz_si, TRUE ); + set_scroll_range_pos( editor, SB_HORZ, &editor->horz_si, TRUE, TRUE ); } /* Update vertical scrollbar */ @@ -1182,7 +1185,7 @@ void ME_UpdateScrollBar(ME_TextEditor *editor) if (editor->vert_si.nPos && !enable) { - ME_VScrollAbs(editor, 0); + scroll_v_abs( editor, 0, TRUE ); /* ME_VScrollAbs will call this function, so nothing else needs to be done here. */ return; } @@ -1199,7 +1202,7 @@ void ME_UpdateScrollBar(ME_TextEditor *editor) editor->vert_si.nPage = editor->sizeWindow.cy; TRACE( "min = %d max = %d page = %d\n", editor->vert_si.nMin, editor->vert_si.nMax, editor->vert_si.nPage ); if ((enable || editor->vert_sb_enabled) && editor->scrollbars & WS_VSCROLL) - set_scroll_range_pos( editor->texthost, SB_VERT, &editor->vert_si, TRUE ); + set_scroll_range_pos( editor, SB_VERT, &editor->vert_si, TRUE, TRUE ); } } @@ -1221,7 +1224,7 @@ void editor_ensure_visible( ME_TextEditor *editor, ME_Cursor *cursor ) if (~editor->scrollbars & ES_AUTOVSCROLL) { - ME_HScrollAbs(editor, x); + scroll_h_abs( editor, x, TRUE ); return; } } @@ -1235,11 +1238,11 @@ void editor_ensure_visible( ME_TextEditor *editor, ME_Cursor *cursor ) yheight = row->nHeight; if (y < editor->vert_si.nPos) - ME_ScrollAbs(editor, x, y); + scroll_abs( editor, x, y, TRUE ); else if (y + yheight > editor->vert_si.nPos + editor->sizeWindow.cy) - ME_ScrollAbs(editor, x, y + yheight - editor->sizeWindow.cy); + scroll_abs( editor, x, y + yheight - editor->sizeWindow.cy, TRUE ); else if (x != editor->horz_si.nPos) - ME_ScrollAbs(editor, x, editor->vert_si.nPos); + scroll_abs( editor, x, editor->vert_si.nPos, TRUE ); } diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c index b652d5a753a..2bb15bb4504 100644 --- a/dlls/riched20/richole.c +++ b/dlls/riched20/richole.c @@ -2743,7 +2743,7 @@ static HRESULT WINAPI ITextRange_fnScrollIntoView(ITextRange *me, LONG value) FIXME("bStart value %d not handled\n", value); return E_NOTIMPL; } - ME_ScrollAbs(editor, x, y); + scroll_abs( editor, x, y, TRUE ); return S_OK; } diff --git a/dlls/riched20/tests/txtsrv.c b/dlls/riched20/tests/txtsrv.c index 3cfd5e63753..45e48a734fa 100644 --- a/dlls/riched20/tests/txtsrv.c +++ b/dlls/riched20/tests/txtsrv.c @@ -398,11 +398,19 @@ static HRESULT __thiscall ITextHostImpl_TxGetPropertyBits(ITextHost *iface, DWOR return S_OK; } -static HRESULT __thiscall ITextHostImpl_TxNotify(ITextHost *iface, DWORD iNotify, void *pv) +static int en_vscroll_sent; +static HRESULT __thiscall ITextHostImpl_TxNotify( ITextHost *iface, DWORD code, void *data ) { ITextHostTestImpl *This = impl_from_ITextHost(iface); - TRACECALL("Call to TxNotify(%p, iNotify=%d, pv=%p)\n", This, iNotify, pv); - return E_NOTIMPL; + TRACECALL( "Call to TxNotify(%p, code = %#x, data = %p)\n", This, code, data ); + switch (code) + { + case EN_VSCROLL: + en_vscroll_sent++; + ok( !data, "got %p\n", data ); + break; + } + return S_OK; } static HIMC __thiscall ITextHostImpl_TxImmGetContext(ITextHost *iface) @@ -1100,6 +1108,55 @@ todo_wine ITextHost_Release(host); } +static void test_notifications( void ) +{ + ITextServices *txtserv; + ITextHost *host; + LRESULT res; + HRESULT hr; + RECT client = { 0, 0, 100, 100 }; + ITextHostTestImpl *host_impl; + + init_texthost( &txtserv, &host ); + host_impl = impl_from_ITextHost( host ); + + host_impl->scrollbars = WS_VSCROLL; + host_impl->props = TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP; + ITextServices_OnTxPropertyBitsChange( txtserv, TXTBIT_SCROLLBARCHANGE | TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP, host_impl->props ); + + ITextServices_TxSetText( txtserv, lorem ); + + host_impl->window = CreateWindowExA( 0, "static", NULL, WS_POPUP | WS_VISIBLE, + 0, 0, 400, 400, 0, 0, 0, NULL ); + host_impl->client_rect = client; + hr = ITextServices_OnTxInPlaceActivate( txtserv, &client ); + ok( hr == S_OK, "got 0x%08x.\n", hr ); + + hr = ITextServices_TxSendMessage( txtserv, EM_SETEVENTMASK, 0, ENM_SCROLL, &res ); + ok( hr == S_OK, "got %08x\n", hr ); + + /* check EN_VSCROLL notification is sent */ + en_vscroll_sent = 0; + hr = ITextServices_TxSendMessage( txtserv, WM_VSCROLL, SB_LINEDOWN, 0, &res ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( en_vscroll_sent == 1, "got %d\n", en_vscroll_sent ); + + hr = ITextServices_TxSendMessage( txtserv, WM_VSCROLL, SB_BOTTOM, 0, &res ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( en_vscroll_sent == 2, "got %d\n", en_vscroll_sent ); + + /* but not when the thumb is moved */ + hr = ITextServices_TxSendMessage( txtserv, WM_VSCROLL, MAKEWPARAM( SB_THUMBTRACK, 0 ), 0, &res ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = ITextServices_TxSendMessage( txtserv, WM_VSCROLL, MAKEWPARAM( SB_THUMBPOSITION, 0 ), 0, &res ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( en_vscroll_sent == 2, "got %d\n", en_vscroll_sent ); + + DestroyWindow( host_impl->window ); + ITextServices_Release( txtserv ); + ITextHost_Release( host ); +} + START_TEST( txtsrv ) { ITextServices *txtserv; @@ -1132,6 +1189,7 @@ START_TEST( txtsrv ) test_QueryInterface(); test_default_format(); test_TxGetScroll(); + test_notifications(); } if (wrapperCodeMem) VirtualFree(wrapperCodeMem, 0, MEM_RELEASE); }