Today, CreateTextServices() returns an Rich Edit object without row start and end marks, which are expected to exist by many Rich Edit operations as well as EM_* message handlers.
This leads to a crash when certain messages (e.g., EM_SCROLLCARET) are sent to the Rich Edit object via ITextServices::TxSendMessage(), unless ME_WrapMarkedParagraphs() has been called beforehand.
Fix this by calling wrap_marked_paras_dc() early in the initialization process.
This is not a problem for windowed Rich Edit controls, which already calls ME_WrapMarkedParagraphs() before the user or application starts interacting with it.
From: Jinoh Kang jinoh.kang.kr@gmail.com
Today, CreateTextServices() returns an Rich Edit object without row start and end marks, which are expected to exist by many Rich Edit operations as well as EM_* message handlers.
This leads to a crash when certain messages (e.g., EM_SCROLLCARET) are sent to the Rich Edit object via ITextServices::TxSendMessage(), unless ME_WrapMarkedParagraphs() has been called beforehand.
Fix this by calling wrap_marked_paras_dc() early in the initialization process.
This is not a problem for windowed Rich Edit controls, which already calls ME_WrapMarkedParagraphs() before the user or application starts interacting with it. --- dlls/riched20/para.c | 1 + dlls/riched20/tests/txtsrv.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+)
diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c index 357d6797c8c..6085816f315 100644 --- a/dlls/riched20/para.c +++ b/dlls/riched20/para.c @@ -222,6 +222,7 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor) wine_rb_init( &editor->marked_paras, para_mark_compare ); para_mark_add( editor, para ); ME_DestroyContext(&c); + wrap_marked_paras_dc( editor, hdc, FALSE ); ITextHost_TxReleaseDC( editor->texthost, hdc ); }
diff --git a/dlls/riched20/tests/txtsrv.c b/dlls/riched20/tests/txtsrv.c index 830a95e37c5..63d622a6755 100644 --- a/dlls/riched20/tests/txtsrv.c +++ b/dlls/riched20/tests/txtsrv.c @@ -1292,6 +1292,23 @@ static void test_set_selection_message( void ) ITextHost_Release( host ); }
+static void test_scrollcaret( void ) +{ + ITextServices *txtserv; + ITextHost *host; + LRESULT result; + HRESULT hr; + + if (!init_texthost(&txtserv, &host)) + return; + + hr = ITextServices_TxSendMessage(txtserv, EM_SCROLLCARET, 0, 0, &result); + ok( hr == S_OK, "got %08lx\n", hr ); + + ITextServices_Release( txtserv ); + ITextHost_Release( host ); +} + START_TEST( txtsrv ) { ITextServices *txtserv; @@ -1326,6 +1343,7 @@ START_TEST( txtsrv ) test_TxGetScroll(); test_notifications(); test_set_selection_message(); + test_scrollcaret(); } if (wrapperCodeMem) VirtualFree(wrapperCodeMem, 0, MEM_RELEASE); }
From: Jinoh Kang jinoh.kang.kr@gmail.com
--- dlls/riched20/tests/txtsrv.c | 91 ++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+)
diff --git a/dlls/riched20/tests/txtsrv.c b/dlls/riched20/tests/txtsrv.c index 63d622a6755..ec2997cb2df 100644 --- a/dlls/riched20/tests/txtsrv.c +++ b/dlls/riched20/tests/txtsrv.c @@ -424,6 +424,8 @@ static HRESULT __thiscall ITextHostImpl_TxGetPropertyBits(ITextHost *iface, DWOR
static int en_vscroll_sent; static int en_update_sent; +static int en_change_sent; +static int en_selchange_sent; static HRESULT __thiscall ITextHostImpl_TxNotify( ITextHost *iface, DWORD code, void *data ) { ITextHostTestImpl *This = impl_from_ITextHost(iface); @@ -438,6 +440,15 @@ static HRESULT __thiscall ITextHostImpl_TxNotify( ITextHost *iface, DWORD code, en_update_sent++; ok( !data, "got %p\n", data ); break; + case EN_CHANGE: + en_change_sent++; + todo_wine + ok( data != NULL, "got %p\n", data ); + break; + case EN_SELCHANGE: + en_selchange_sent++; + ok( data != NULL, "got %p\n", data ); + break; } return S_OK; } @@ -1268,25 +1279,105 @@ static void test_set_selection_message( void ) { ITextServices *txtserv; ITextHost *host; + CHARRANGE range; LRESULT result; HRESULT hr;
if (!init_texthost(&txtserv, &host)) return;
+ ITextServices_TxSetText(txtserv, L""); + + if (winetest_debug > 1) trace("TxSendMessage EM_SETEVENTMASK"); + + hr = ITextServices_TxSendMessage( txtserv, EM_SETEVENTMASK, 0, ENM_CHANGE | ENM_SELCHANGE, &result ); + ok( hr == S_OK, "got %08lx\n", hr ); + + if (winetest_debug > 1) trace("TxSendMessage EM_SETSEL 0 20"); + CLEAR_COUNTER(ITextHostImpl_TxViewChange); + en_change_sent = 0; + en_selchange_sent = 0; + hr = ITextServices_TxSendMessage(txtserv, EM_SETSEL, 0, 20, &result); ok( hr == S_OK, "got %08lx\n", hr ); + CHECK_CALLED(ITextHostImpl_TxViewChange); + todo_wine + ok(en_change_sent == 0, "got %d\n", en_change_sent); + todo_wine + ok(en_selchange_sent == 0, "got %d\n", en_selchange_sent); + + hr = ITextServices_TxSendMessage(txtserv, EM_EXGETSEL, 0, (LPARAM)&range, &result); ok( hr == S_OK, "got %08lx\n", hr ); trace("getsel: %lu, %lu\n", range.cpMin, range.cpMax); + + if (winetest_debug > 1) trace("TxSendMessage EM_SETSELEX 0 20"); + + CLEAR_COUNTER(ITextHostImpl_TxViewChange); + en_change_sent = 0; + en_selchange_sent = 0; + + range.cpMin = 0; + range.cpMax = 20; + hr = ITextServices_TxSendMessage(txtserv, EM_EXSETSEL, 0, (LPARAM)&range, &result); + ok( hr == S_OK, "got %08lx\n", hr ); + + CHECK_CALLED(ITextHostImpl_TxViewChange); + todo_wine + ok(en_change_sent == 0, "got %d\n", en_change_sent); + ok(en_selchange_sent == 0, "got %d\n", en_selchange_sent); + + if (winetest_debug > 1) trace("TxSetText");
CLEAR_COUNTER(ITextHostImpl_TxViewChange); + en_change_sent = 0; + en_selchange_sent = 0; + + hr = ITextServices_TxSendMessage(txtserv, EM_EXGETSEL, 0, (LPARAM)&range, &result); ok( hr == S_OK, "got %08lx\n", hr ); trace("getsel: %lu, %lu\n", range.cpMin, range.cpMax); + ITextServices_TxSetText(txtserv, lorem); + + hr = ITextServices_TxSendMessage(txtserv, EM_EXGETSEL, 0, (LPARAM)&range, &result); ok( hr == S_OK, "got %08lx\n", hr ); trace("getsel: %lu, %lu\n", range.cpMin, range.cpMax); + CHECK_CALLED(ITextHostImpl_TxViewChange); + ok(en_change_sent == 1, "got %d\n", en_change_sent); + todo_wine + ok(en_selchange_sent == 0, "got %d\n", en_selchange_sent); + + if (winetest_debug > 1) trace("TxSendMessage EM_SETSEL 0 20");
CLEAR_COUNTER(ITextHostImpl_TxViewChange); + en_change_sent = 0; + en_selchange_sent = 0; + hr = ITextServices_TxSendMessage(txtserv, EM_SETSEL, 0, 20, &result); ok( hr == S_OK, "got %08lx\n", hr ); + + CHECK_CALLED(ITextHostImpl_TxViewChange); + todo_wine + ok(en_change_sent == 0, "got %d\n", en_change_sent); + ok(en_selchange_sent == 1, "got %d\n", en_selchange_sent); + + hr = ITextServices_TxSendMessage(txtserv, EM_EXGETSEL, 0, (LPARAM)&range, &result); ok( hr == S_OK, "got %08lx\n", hr ); trace("getsel: %lu, %lu\n", range.cpMin, range.cpMax); + + if (winetest_debug > 1) trace("TxSendMessage EM_SETSELEX 0 20"); + + CLEAR_COUNTER(ITextHostImpl_TxViewChange); + en_change_sent = 0; + en_selchange_sent = 0; + + range.cpMin = 0; + range.cpMax = 20; + hr = ITextServices_TxSendMessage(txtserv, EM_EXSETSEL, 0, (LPARAM)&range, &result); + ok( hr == S_OK, "got %08lx\n", hr ); + CHECK_CALLED(ITextHostImpl_TxViewChange); + todo_wine + ok(en_change_sent == 0, "got %d\n", en_change_sent); + ok(en_selchange_sent == 0, "got %d\n", en_selchange_sent); + + hr = ITextServices_TxSendMessage(txtserv, EM_EXGETSEL, 0, (LPARAM)&range, &result); ok( hr == S_OK, "got %08lx\n", hr ); trace("getsel: %lu, %lu\n", range.cpMin, range.cpMax); + + if (winetest_debug > 1) trace("release interfaces");
ITextServices_Release( txtserv ); ITextHost_Release( host );
From: Jinoh Kang jinoh.kang.kr@gmail.com
This partially reverts c5daf6a30f21 (riched20: Call ME_UpdateRepaint instead of editor_ensure_visible in set_selection.)
Fixes: c5daf6a30f21acd20263692b278acba49e014cc1 --- dlls/riched20/editor.c | 3 ++- dlls/riched20/tests/txtsrv.c | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index 8ac71379533..696fe3ffeda 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -2150,9 +2150,10 @@ int set_selection( ME_TextEditor *editor, int to, int from )
if (!editor->bHideSelection) ME_InvalidateSelection( editor ); end = set_selection_cursors( editor, to, from ); - ME_UpdateRepaint( editor, FALSE ); + editor_ensure_visible( editor, &editor->pCursors[0] ); if (!editor->bHideSelection) ME_InvalidateSelection( editor ); update_caret( editor ); + ME_Repaint( editor ); ME_SendSelChange( editor );
return end; diff --git a/dlls/riched20/tests/txtsrv.c b/dlls/riched20/tests/txtsrv.c index ec2997cb2df..adb36642f4f 100644 --- a/dlls/riched20/tests/txtsrv.c +++ b/dlls/riched20/tests/txtsrv.c @@ -1303,7 +1303,6 @@ static void test_set_selection_message( void ) ok( hr == S_OK, "got %08lx\n", hr );
CHECK_CALLED(ITextHostImpl_TxViewChange); - todo_wine ok(en_change_sent == 0, "got %d\n", en_change_sent); todo_wine ok(en_selchange_sent == 0, "got %d\n", en_selchange_sent); @@ -1322,7 +1321,6 @@ static void test_set_selection_message( void ) ok( hr == S_OK, "got %08lx\n", hr );
CHECK_CALLED(ITextHostImpl_TxViewChange); - todo_wine ok(en_change_sent == 0, "got %d\n", en_change_sent); ok(en_selchange_sent == 0, "got %d\n", en_selchange_sent);
@@ -1353,7 +1351,6 @@ static void test_set_selection_message( void ) ok( hr == S_OK, "got %08lx\n", hr );
CHECK_CALLED(ITextHostImpl_TxViewChange); - todo_wine ok(en_change_sent == 0, "got %d\n", en_change_sent); ok(en_selchange_sent == 1, "got %d\n", en_selchange_sent);
@@ -1371,7 +1368,6 @@ static void test_set_selection_message( void ) ok( hr == S_OK, "got %08lx\n", hr );
CHECK_CALLED(ITextHostImpl_TxViewChange); - todo_wine ok(en_change_sent == 0, "got %d\n", en_change_sent); ok(en_selchange_sent == 0, "got %d\n", en_selchange_sent);
This merge request was approved by Huw Davies.