diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c
index 2d526fc040c..8a47207f5bb 100644
--- a/dlls/mshtml/tests/dom.c
+++ b/dlls/mshtml/tests/dom.c
@@ -4901,6 +4901,30 @@ static IHTMLTxtRange *test_create_body_range(IHTMLDocument2 *doc)
return range;
}
+#define range_duplicate(a) _range_duplicate(__LINE__,a)
+static IHTMLTxtRange *_range_duplicate(unsigned line, IHTMLTxtRange *range)
+{
+ IHTMLTxtRange *ret;
+ HRESULT hres;
+
+ hres = IHTMLTxtRange_duplicate(range, &ret);
+ ok_(__FILE__,line)(hres == S_OK, "duplicate failed: %08x\n", hres);
+
+ return ret;
+}
+
+#define test_range_set_end_point(a,b,c,d) _test_range_set_end_point(__LINE__,a,b,c,d)
+static void _test_range_set_end_point(unsigned line, IHTMLTxtRange *range, const char *how,
+ IHTMLTxtRange *ref_range, HRESULT exhres)
+{
+ BSTR str = a2bstr(how);
+ HRESULT hres;
+
+ hres = IHTMLTxtRange_setEndPoint(range, str, ref_range);
+ ok_(__FILE__,line)(hres == exhres, "setEndPoint failed: %08x, expected %08x\n", hres, exhres);
+ SysFreeString(str);
+}
+
static void test_txtrange(IHTMLDocument2 *doc)
{
IHTMLTxtRange *body_range, *range, *range2;
@@ -4915,11 +4939,9 @@ static void test_txtrange(IHTMLDocument2 *doc)
test_range_text(body_range, "test abc 123\r\nit's text");
- hres = IHTMLTxtRange_duplicate(body_range, &range);
- ok(hres == S_OK, "duplicate failed: %08x\n", hres);
+ range = range_duplicate(body_range);
+ range2 = range_duplicate(body_range);
- hres = IHTMLTxtRange_duplicate(body_range, &range2);
- ok(hres == S_OK, "duplicate failed: %08x\n", hres);
test_range_isequal(range, range2, VARIANT_TRUE);
test_range_text(range, "test abc 123\r\nit's text");
@@ -4959,8 +4981,7 @@ static void test_txtrange(IHTMLDocument2 *doc)
IHTMLTxtRange_Release(range);
- hres = IHTMLTxtRange_duplicate(body_range, &range);
- ok(hres == S_OK, "duplicate failed: %08x\n", hres);
+ range = range_duplicate(body_range);
test_range_text(range, "test abc 123\r\nit's text");
test_range_move(range, characterW, 3, 3);
@@ -4978,8 +4999,7 @@ static void test_txtrange(IHTMLDocument2 *doc)
IHTMLTxtRange_Release(range);
- hres = IHTMLTxtRange_duplicate(body_range, &range);
- ok(hres == S_OK, "duplicate failed: %08x\n", hres);
+ range = range_duplicate(body_range);
test_range_move(range, wordW, 1, 1);
test_range_moveend(range, characterW, 2, 2);
@@ -5005,8 +5025,7 @@ static void test_txtrange(IHTMLDocument2 *doc)
IHTMLTxtRange_Release(range);
- hres = IHTMLTxtRange_duplicate(body_range, &range);
- ok(hres == S_OK, "duplicate failed: %08x\n", hres);
+ range = range_duplicate(body_range);
test_range_move(range, wordW, 2, 2);
test_range_moveend(range, characterW, 2, 2);
@@ -5030,8 +5049,7 @@ static void test_txtrange(IHTMLDocument2 *doc)
IHTMLTxtRange_Release(range);
- hres = IHTMLTxtRange_duplicate(body_range, &range);
- ok(hres == S_OK, "duplicate failed: %08x\n", hres);
+ range = range_duplicate(body_range);
test_range_collapse(range, TRUE);
test_range_expand(range, wordW, VARIANT_TRUE, "test ");
@@ -5054,7 +5072,6 @@ static void test_txtrange(IHTMLDocument2 *doc)
test_range_text(range, NULL);
IHTMLTxtRange_Release(range);
- IHTMLTxtRange_Release(body_range);
hres = IHTMLDocument2_get_selection(doc, &selection);
ok(hres == S_OK, "IHTMLDocument2_get_selection failed: %08x\n", hres);
@@ -5116,9 +5133,39 @@ static void test_txtrange(IHTMLDocument2 *doc)
test_range_text(range, "abc \r\npaste\r\nxyz abc 123\r\nit's text");
- IHTMLElement_Release(body);
+ test_range_move(range, wordW, 2, 2);
+ test_range_collapse(range, VARIANT_TRUE);
+ test_range_moveend(range, characterW, 5, 5);
+ test_range_text(range, "paste");
+
+ range2 = range_duplicate(range);
+
+ test_range_set_end_point(range, "starttostart", body_range, S_OK);
+ test_range_text(range, "abc \r\npaste");
+
+ test_range_set_end_point(range, "endtoend", body_range, S_OK);
+ test_range_text(range, "abc \r\npaste\r\nxyz abc 123\r\nit's text");
+
+ test_range_set_end_point(range, "starttoend", range2, S_OK);
+ test_range_text(range, "\r\nxyz abc 123\r\nit's text");
+
+ test_range_set_end_point(range, "starttostart", body_range, S_OK);
+ test_range_set_end_point(range, "endtostart", range2, S_OK);
+ test_range_text(range, "abc ");
+
+ test_range_set_end_point(range, "starttoend", body_range, S_OK);
+ test_range_text(range, "paste\r\nxyz abc 123\r\nit's text");
+
+ test_range_set_end_point(range, "EndToStart", body_range, S_OK);
+ test_range_text(range, "abc ");
+
+ test_range_set_end_point(range, "xxx", body_range, E_INVALIDARG);
IHTMLTxtRange_Release(range);
+ IHTMLTxtRange_Release(range2);
+ IHTMLTxtRange_Release(body_range);
+ IHTMLElement_Release(body);
+
}
static void test_txtrange2(IHTMLDocument2 *doc)
diff --git a/dlls/mshtml/txtrange.c b/dlls/mshtml/txtrange.c
index 43c9f1a5f60..0dd3aaeb82c 100644
--- a/dlls/mshtml/txtrange.c
+++ b/dlls/mshtml/txtrange.c
@@ -1627,8 +1627,74 @@ static HRESULT WINAPI HTMLTxtRange_setEndPoint(IHTMLTxtRange *iface, BSTR how,
IHTMLTxtRange *SourceRange)
{
HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
- FIXME("(%p)->(%s %p)\n", This, debugstr_w(how), SourceRange);
- return E_NOTIMPL;
+ HTMLTxtRange *src_range;
+ nsIDOMNode *ref_node;
+ INT32 ref_offset;
+ BOOL set_start;
+ int how_type;
+ INT16 cmp;
+ nsresult nsres;
+
+ TRACE("(%p)->(%s %p)\n", This, debugstr_w(how), SourceRange);
+
+ how_type = string_to_nscmptype(how);
+ if(how_type == -1)
+ return E_INVALIDARG;
+
+ src_range = get_range_object(This->doc, SourceRange);
+ if(!src_range)
+ return E_FAIL;
+
+ switch(how_type) {
+ case NS_START_TO_START:
+ case NS_END_TO_START:
+ nsres = nsIDOMRange_GetStartContainer(src_range->nsrange, &ref_node);
+ assert(nsres == NS_OK);
+
+ nsres = nsIDOMRange_GetStartOffset(src_range->nsrange, &ref_offset);
+ assert(nsres == NS_OK);
+
+ set_start = how_type == NS_START_TO_START;
+ break;
+ case NS_END_TO_END:
+ case NS_START_TO_END:
+ nsres = nsIDOMRange_GetEndContainer(src_range->nsrange, &ref_node);
+ assert(nsres == NS_OK);
+
+ nsres = nsIDOMRange_GetEndOffset(src_range->nsrange, &ref_offset);
+ assert(nsres == NS_OK);
+
+ set_start = how_type == NS_START_TO_END;
+ break;
+ DEFAULT_UNREACHABLE;
+ }
+
+ nsres = nsIDOMRange_ComparePoint(This->nsrange, ref_node, ref_offset, &cmp);
+ assert(nsres == NS_OK);
+
+ if(set_start) {
+ if(cmp <= 0) {
+ nsres = nsIDOMRange_SetStart(This->nsrange, ref_node, ref_offset);
+ }else {
+ nsres = nsIDOMRange_Collapse(This->nsrange, FALSE);
+ assert(nsres == NS_OK);
+
+ nsres = nsIDOMRange_SetEnd(This->nsrange, ref_node, ref_offset);
+ }
+ }else {
+ if(cmp >= 0) {
+ nsres = nsIDOMRange_SetEnd(This->nsrange, ref_node, ref_offset);
+ }else {
+ nsres = nsIDOMRange_Collapse(This->nsrange, TRUE);
+ assert(nsres == NS_OK);
+
+ nsres = nsIDOMRange_SetStart(This->nsrange, ref_node, ref_offset);
+ }
+ }
+ assert(nsres == NS_OK);
+
+ nsIDOMNode_Release(ref_node);
+ return S_OK;
}
static HRESULT WINAPI HTMLTxtRange_compareEndPoints(IHTMLTxtRange *iface, BSTR how,