Nikolay Sivov : riched20: Implement SetText for regular range.
Alexandre Julliard
julliard at wine.codeweavers.com
Wed May 27 09:30:58 CDT 2015
Module: wine
Branch: master
Commit: d27234617cbcf1bc0f9ecefe7087fb928b1ecb33
URL: http://source.winehq.org/git/wine.git/?a=commit;h=d27234617cbcf1bc0f9ecefe7087fb928b1ecb33
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Wed May 27 00:45:25 2015 +0300
riched20: Implement SetText for regular range.
---
dlls/riched20/richole.c | 73 ++++++++++++++++++++++++++++++++++--
dlls/riched20/tests/richole.c | 87 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 157 insertions(+), 3 deletions(-)
diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c
index a34c210..06ff9aa 100644
--- a/dlls/riched20/richole.c
+++ b/dlls/riched20/richole.c
@@ -201,6 +201,10 @@ typedef union {
BSTR str;
} textfont_prop_val;
+enum range_update_op {
+ RANGE_UPDATE_DELETE
+};
+
typedef struct IRichEditOleImpl {
IUnknown IUnknown_inner;
IRichEditOle IRichEditOle_iface;
@@ -304,6 +308,35 @@ static inline ITextParaImpl *impl_from_ITextPara(ITextPara *iface)
static HRESULT create_textfont(ITextRange*, const ITextFontImpl*, ITextFont**);
static HRESULT create_textpara(ITextRange*, ITextPara**);
+static void textranges_update_ranges(IRichEditOleImpl *reole, LONG start, LONG end, enum range_update_op op)
+{
+ ITextRangeImpl *range;
+
+ LIST_FOR_EACH_ENTRY(range, &reole->rangelist, ITextRangeImpl, entry) {
+ switch (op)
+ {
+ case RANGE_UPDATE_DELETE:
+ /* range fully covered by deleted range - collapse to insertion point */
+ if (range->start >= start && range->end <= end)
+ range->start = range->end = start;
+ /* deleted range cuts from the right */
+ else if (range->start < start && range->end <= end)
+ range->end = start;
+ /* deleted range cuts from the left */
+ else if (range->start >= start && range->end > end) {
+ range->start = start;
+ range->end -= end - start;
+ }
+ /* deleted range cuts within */
+ else
+ range->end -= end - start;
+ break;
+ default:
+ FIXME("unknown update op, %d\n", op);
+ }
+ }
+}
+
static inline BOOL is_equal_textfont_prop_value(enum textfont_prop_id propid, textfont_prop_val *left,
textfont_prop_val *right)
{
@@ -1376,14 +1409,48 @@ static HRESULT WINAPI ITextRange_fnGetText(ITextRange *me, BSTR *pbstr)
return E_NOTIMPL;
}
-static HRESULT WINAPI ITextRange_fnSetText(ITextRange *me, BSTR bstr)
+static HRESULT WINAPI ITextRange_fnSetText(ITextRange *me, BSTR str)
{
ITextRangeImpl *This = impl_from_ITextRange(me);
+ ME_TextEditor *editor;
+ ME_Cursor cursor;
+ ME_Style *style;
+ int len;
+
+ TRACE("(%p)->(%s)\n", This, debugstr_w(str));
+
if (!This->reOle)
return CO_E_RELEASED;
- FIXME("not implemented %p\n", This);
- return E_NOTIMPL;
+ editor = This->reOle->editor;
+
+ /* delete only where's something to delete */
+ if (This->start != This->end) {
+ ME_CursorFromCharOfs(editor, This->start, &cursor);
+ ME_InternalDeleteText(editor, &cursor, This->end - This->start, FALSE);
+ }
+
+ if (!str || !*str) {
+ /* will update this range as well */
+ textranges_update_ranges(This->reOle, This->start, This->end, RANGE_UPDATE_DELETE);
+ return S_OK;
+ }
+
+ /* it's safer not to rely on stored BSTR length */
+ len = strlenW(str);
+ cursor = editor->pCursors[0];
+ ME_CursorFromCharOfs(editor, This->start, &editor->pCursors[0]);
+ style = ME_GetInsertStyle(editor, 0);
+ ME_InsertTextFromCursor(editor, 0, str, len, style);
+ ME_ReleaseStyle(style);
+ editor->pCursors[0] = cursor;
+
+ if (len < This->end - This->start)
+ textranges_update_ranges(This->reOle, This->start + len, This->end, RANGE_UPDATE_DELETE);
+ else
+ This->end = len - This->start;
+
+ return S_OK;
}
static HRESULT range_GetChar(ME_TextEditor *editor, ME_Cursor *cursor, LONG *pch)
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index adb96c3..7d90a98 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -2401,6 +2401,92 @@ todo_wine
release_interfaces(&hwnd, &reOle, &doc, NULL);
}
+static void test_SetText(void)
+{
+ static const CHAR test_text1[] = "TestSomeText";
+ static const WCHAR textW[] = {'a','b','c','d','e','f','g','h','i',0};
+ IRichEditOle *reOle = NULL;
+ ITextDocument *doc = NULL;
+ ITextRange *range, *range2;
+ LONG value;
+ HRESULT hr;
+ HWND hwnd;
+ BSTR str;
+
+ create_interfaces(&hwnd, &reOle, &doc, NULL);
+ SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
+
+ hr = ITextDocument_Range(doc, 0, 4, &range);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = ITextDocument_Range(doc, 0, 4, &range2);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ value = 1;
+ hr = ITextRange_GetStart(range2, &value);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(value == 0, "got %d\n", value);
+
+ value = 0;
+ hr = ITextRange_GetEnd(range2, &value);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(value == 4, "got %d\n", value);
+
+ hr = ITextRange_SetText(range, NULL);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ value = 1;
+ hr = ITextRange_GetEnd(range2, &value);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(value == 0, "got %d\n", value);
+
+ str = SysAllocString(textW);
+ hr = ITextRange_SetText(range, str);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ value = 1;
+ hr = ITextRange_GetStart(range, &value);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(value == 0, "got %d\n", value);
+
+ value = 0;
+ hr = ITextRange_GetEnd(range, &value);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(value == 9, "got %d\n", value);
+
+ value = 1;
+ hr = ITextRange_GetStart(range2, &value);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(value == 0, "got %d\n", value);
+
+ value = 0;
+ hr = ITextRange_GetEnd(range2, &value);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(value == 0, "got %d\n", value);
+
+ str = SysAllocStringLen(NULL, 0);
+ hr = ITextRange_SetText(range, str);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ value = 1;
+ hr = ITextRange_GetEnd(range, &value);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(value == 0, "got %d\n", value);
+ SysFreeString(str);
+
+ ITextRange_Release(range2);
+ release_interfaces(&hwnd, &reOle, &doc, NULL);
+
+ hr = ITextRange_SetText(range, NULL);
+ ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
+
+ str = SysAllocStringLen(NULL, 0);
+ hr = ITextRange_SetText(range, str);
+ ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
+ SysFreeString(str);
+
+ ITextRange_Release(range);
+}
+
START_TEST(richole)
{
/* Must explicitly LoadLibrary(). The test has no references to functions in
@@ -2427,4 +2513,5 @@ START_TEST(richole)
test_dispatch();
test_ITextFont();
test_Delete();
+ test_SetText();
}
More information about the wine-cvs
mailing list