From: Jactry Zeng Subject: [PATCH 2/2] riched20: Implement ITextSelection::GetText. (try 4) Message-Id: <53CD42B9.2090003@jactry.com> Date: Tue, 22 Jul 2014 00:41:29 +0800 Superseded patch 105416. Thanks Huw! ChangeLog: try 4: - Fix leak in tests - Append a '\r' to the last paragraph try 3: - Remove an unuseful trace try 2: - Simplify by SysAllocStringLen() --- dlls/riched20/clipboard.c | 2 +- dlls/riched20/editor.c | 22 +++++++---- dlls/riched20/editor.h | 2 +- dlls/riched20/richole.c | 27 ++++++++++++- dlls/riched20/tests/richole.c | 90 +++++++++++++++++++++++++++++++++++++++++++ dlls/riched20/txtsrv.c | 2 +- 6 files changed, 132 insertions(+), 13 deletions(-) diff --git a/dlls/riched20/clipboard.c b/dlls/riched20/clipboard.c index f7514a2..250a233 100644 --- a/dlls/riched20/clipboard.c +++ b/dlls/riched20/clipboard.c @@ -352,7 +352,7 @@ static HGLOBAL get_unicode_text(ME_TextEditor *editor, const ME_Cursor *start, i ret = GlobalAlloc(GMEM_MOVEABLE, sizeof(WCHAR) * (nChars + pars + 1)); data = GlobalLock(ret); - ME_GetTextW(editor, data, nChars + pars, start, nChars, TRUE); + ME_GetTextW(editor, data, nChars + pars, start, nChars, TRUE, FALSE); GlobalUnlock(ret); return ret; } diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index 43d74ec..3c0d970 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -1630,7 +1630,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre ME_Cursor linebreakCursor = *selEnd; ME_MoveCursorChars(editor, &linebreakCursor, -linebreakSize); - ME_GetTextW(editor, lastchar, 2, &linebreakCursor, linebreakSize, FALSE); + ME_GetTextW(editor, lastchar, 2, &linebreakCursor, linebreakSize, FALSE, FALSE); if (lastchar[0] == '\r' && (lastchar[1] == '\n' || lastchar[1] == '\0')) { ME_InternalDeleteText(editor, &linebreakCursor, linebreakSize, FALSE); } @@ -1968,7 +1968,7 @@ static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText) if (ex->codepage == CP_UNICODE) { return ME_GetTextW(editor, (LPWSTR)pText, ex->cb / sizeof(WCHAR) - 1, - &start, nChars, ex->flags & GT_USECRLF); + &start, nChars, ex->flags & GT_USECRLF, FALSE); } else { @@ -1985,7 +1985,7 @@ static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText) buflen = min(crlfmul * nChars, ex->cb - 1); buffer = heap_alloc((buflen + 1) * sizeof(WCHAR)); - nChars = ME_GetTextW(editor, buffer, buflen, &start, nChars, ex->flags & GT_USECRLF); + nChars = ME_GetTextW(editor, buffer, buflen, &start, nChars, ex->flags & GT_USECRLF, FALSE); rc = WideCharToMultiByte(ex->codepage, 0, buffer, nChars + 1, (LPSTR)pText, ex->cb, ex->lpDefaultChar, ex->lpUsedDefChar); if (rc) rc--; /* do not count 0 terminator */ @@ -2000,12 +2000,12 @@ static int ME_GetTextRange(ME_TextEditor *editor, WCHAR *strText, { if (!strText) return 0; if (unicode) { - return ME_GetTextW(editor, strText, INT_MAX, start, nLen, FALSE); + return ME_GetTextW(editor, strText, INT_MAX, start, nLen, FALSE, FALSE); } else { int nChars; WCHAR *p = ALLOC_N_OBJ(WCHAR, nLen+1); if (!p) return 0; - nChars = ME_GetTextW(editor, p, nLen, start, nLen, FALSE); + nChars = ME_GetTextW(editor, p, nLen, start, nLen, FALSE, FALSE); WideCharToMultiByte(CP_ACP, 0, p, nChars+1, (char *)strText, nLen+1, NULL, NULL); FREE_OBJ(p); @@ -4747,7 +4747,8 @@ void ME_SendOldNotify(ME_TextEditor *editor, int nCode) * The written text is always NULL terminated. */ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, - const ME_Cursor *start, int srcChars, BOOL bCRLF) + const ME_Cursor *start, int srcChars, BOOL bCRLF, + BOOL bEOP) { ME_DisplayItem *pRun, *pNextRun; const WCHAR *pStart = buffer; @@ -4765,7 +4766,6 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, nLen = pRun->member.run.len - start->nOffset; str = get_text( &pRun->member.run, start->nOffset ); - /* No '\r' is appended to the last paragraph. */ while (srcChars && buflen && pNextRun) { int nFlags = pRun->member.run.nFlags; @@ -4797,6 +4797,12 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, nLen = pRun->member.run.len; str = get_text( &pRun->member.run, 0 ); } + /* append '\r' to the last paragraph. */ + if (pRun->next->type == diTextEnd && bEOP) + { + *buffer = '\r'; + buffer ++; + } *buffer = 0; return buffer - pStart; } @@ -5041,7 +5047,7 @@ static BOOL ME_IsCandidateAnURL(ME_TextEditor *editor, const ME_Cursor *start, i WCHAR bufferW[MAX_PREFIX_LEN + 1]; unsigned int i; - ME_GetTextW(editor, bufferW, MAX_PREFIX_LEN, start, nChars, FALSE); + ME_GetTextW(editor, bufferW, MAX_PREFIX_LEN, start, nChars, FALSE, FALSE); for (i = 0; i < sizeof(prefixes) / sizeof(*prefixes); i++) { if (nChars < prefixes[i].length) continue; diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index af7291f..edbac8e 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -252,7 +252,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode, HRESULT* phresult) DECLSPEC_HIDDEN; void ME_SendOldNotify(ME_TextEditor *editor, int nCode) DECLSPEC_HIDDEN; int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, - const ME_Cursor *start, int srcChars, BOOL bCRLF) DECLSPEC_HIDDEN; + const ME_Cursor *start, int srcChars, BOOL bCRLF, BOOL bEOP) DECLSPEC_HIDDEN; void ME_RTFCharAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN; void ME_RTFParAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN; void ME_RTFTblAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN; diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c index 6f2d579..487fcda 100644 --- a/dlls/riched20/richole.c +++ b/dlls/riched20/richole.c @@ -783,11 +783,34 @@ static HRESULT WINAPI ITextSelection_fnInvoke( static HRESULT WINAPI ITextSelection_fnGetText(ITextSelection *me, BSTR *pbstr) { ITextSelectionImpl *This = impl_from_ITextSelection(me); + ME_Cursor *start = NULL, *end = NULL; + int nChars, endOfs; + BOOL bEOP; + if (!This->reOle) return CO_E_RELEASED; + TRACE("%p\n", pbstr); + if (!pbstr) + return E_INVALIDARG; - FIXME("not implemented\n"); - return E_NOTIMPL; + ME_GetSelection(This->reOle->editor, &start, &end); + endOfs = ME_GetCursorOfs(end); + nChars = endOfs - ME_GetCursorOfs(start); + if (!nChars) + { + *pbstr = NULL; + return S_OK; + } + + *pbstr = SysAllocStringLen(NULL, nChars); + if (!*pbstr) + return E_OUTOFMEMORY; + + bEOP = (end->pRun->next->type == diTextEnd && endOfs > ME_GetTextLength(This->reOle->editor)); + ME_GetTextW(This->reOle->editor, *pbstr, nChars, start, nChars, FALSE, bEOP); + TRACE("%s\n", wine_dbgstr_w(*pbstr)); + + return S_OK; } static HRESULT WINAPI ITextSelection_fnSetText(ITextSelection *me, BSTR bstr) diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c index d10c063..98ac50d 100644 --- a/dlls/riched20/tests/richole.c +++ b/dlls/riched20/tests/richole.c @@ -402,6 +402,95 @@ static void test_ITextDocument_Open(void) VariantClear(&testfile); } +static void test_ITextSelection_GetText(void) +{ + HWND w; + IRichEditOle *reOle = NULL; + ITextDocument *txtDoc = NULL; + ITextSelection *txtSel = NULL; + HRESULT hres; + BSTR bstr = NULL; + int first, lim; + static const CHAR test_text1[] = "TestSomeText"; + static const WCHAR bufW1[] = {'T', 'e', 's', 't', 0}; + static const WCHAR bufW2[] = {'T', 'e', 'x', 't', '\r', 0}; + static const WCHAR bufW3[] = {'T', 'e', 'x', 't', 0}; + static const WCHAR bufW4[] = {'T', 'e', 's', 't', 'S', 'o', 'm', + 'e', 'T', 'e', 'x', 't', '\r', 0}; + static const WCHAR bufW5[] = {'\r', 0}; + SYSTEM_INFO sysinfo; + int is64bit; + GetSystemInfo(&sysinfo); + is64bit = (sysinfo.wProcessorArchitecture & PROCESSOR_ARCHITECTURE_AMD64); + + create_interfaces(&w, &reOle, &txtDoc, &txtSel); + SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); + + first = 0, lim = 4; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_GetText(txtSel, &bstr); + ok(hres == S_OK, "ITextSelection_GetText\n"); + ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + first = 4, lim = 0; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_GetText(txtSel, &bstr); + ok(hres == S_OK, "ITextSelection_GetText\n"); + ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + first = 1, lim = 1; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_GetText(txtSel, &bstr); + ok(hres == S_OK, "ITextSelection_GetText\n"); + ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr)); + + if(is64bit) + win_skip("native 64bit riched20 can't support a NULL parameter\n"); + else + { + hres = ITextSelection_GetText(txtSel, NULL); + ok(hres == E_INVALIDARG, "ITextSelection_GetText\n"); + } + + first = 8, lim = 12; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_GetText(txtSel, &bstr); + ok(hres == S_OK, "ITextSelection_GetText\n"); + ok(!lstrcmpW(bstr, bufW3), "got wrong text: %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + first = 8, lim = 13; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_GetText(txtSel, &bstr); + ok(hres == S_OK, "ITextSelection_GetText\n"); + ok(!lstrcmpW(bstr, bufW2), "got wrong text: %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + first = 12, lim = 13; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_GetText(txtSel, &bstr); + ok(hres == S_OK, "ITextSelection_GetText\n"); + ok(!lstrcmpW(bstr, bufW5), "got wrong text: %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + first = 0, lim = -1; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_GetText(txtSel, &bstr); + ok(hres == S_OK, "ITextSelection_GetText\n"); + ok(!lstrcmpW(bstr, bufW4), "got wrong text: %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + first = -1, lim = 9; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_GetText(txtSel, &bstr); + ok(hres == S_OK, "ITextSelection_GetText\n"); + ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr)); + + release_interfaces(&w, &reOle, &txtDoc, &txtSel); +} + START_TEST(richole) { /* Must explicitly LoadLibrary(). The test has no references to functions in @@ -411,4 +500,5 @@ START_TEST(richole) test_Interfaces(); test_ITextDocument_Open(); + test_ITextSelection_GetText(); } diff --git a/dlls/riched20/txtsrv.c b/dlls/riched20/txtsrv.c index 1f78405..636efff 100644 --- a/dlls/riched20/txtsrv.c +++ b/dlls/riched20/txtsrv.c @@ -264,7 +264,7 @@ DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetText(ITextServices *iface, BSTR *p return E_OUTOFMEMORY; ME_CursorFromCharOfs(This->editor, 0, &start); - ME_GetTextW(This->editor, bstr, length, &start, INT_MAX, FALSE); + ME_GetTextW(This->editor, bstr, length, &start, INT_MAX, FALSE, FALSE); *pbstrText = bstr; } else { *pbstrText = NULL;