From 11591e77205adfb30d9a7b94d3a08f7eabdf11ba Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 12 Sep 2007 23:35:11 +0200 Subject: [PATCH] mshtml: Added IHTMLTxtRange::move("character") implementation. --- dlls/mshtml/tests/dom.c | 32 ++++++++++++ dlls/mshtml/txtrange.c | 105 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 135 insertions(+), 2 deletions(-) diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index f4a2f67f78b..5c087f7bd20 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -33,6 +33,7 @@ static const char doc_str1[] = "test"; static const char doc_str2[] = "test abc 123
it's
text
"; +static WCHAR characterW[] = {'c','h','a','r','a','c','t','e','r',0}; static WCHAR wordW[] = {'w','o','r','d',0}; static const char *dbgstr_w(LPCWSTR str) @@ -142,6 +143,18 @@ static void _test_range_expand(unsigned line, IHTMLTxtRange *range, LPWSTR unit, _test_range_text(line, range, extext); } +#define test_range_move(r,u,c,e) _test_range_move(__LINE__,r,u,c,e) +static void _test_range_move(unsigned line, IHTMLTxtRange *range, LPWSTR unit, long cnt, long excnt) +{ + long c = 0xdeadbeef; + HRESULT hres; + + hres = IHTMLTxtRange_move(range, unit, cnt, &c); + ok_(__FILE__,line) (hres == S_OK, "move failed: %08x\n", hres); + ok_(__FILE__,line) (c == excnt, "count=%ld, expected %ld\n", c, excnt); + _test_range_text(line, range, NULL); +} + #define test_range_inrange(r1,r2,b) _test_range_inrange(__LINE__,r1,r2,b) static void _test_range_inrange(unsigned line, IHTMLTxtRange *range1, IHTMLTxtRange *range2, VARIANT_BOOL exb) { @@ -213,6 +226,25 @@ static void test_txtrange(IHTMLDocument2 *doc) test_range_expand(range, wordW, VARIANT_TRUE, "test "); test_range_expand(range, wordW, VARIANT_FALSE, "test "); + test_range_move(range, characterW, 2, 2); + test_range_expand(range, wordW, VARIANT_TRUE, "test "); + + test_range_collapse(range, FALSE); + test_range_expand(range, wordW, VARIANT_TRUE, "abc "); + + test_range_collapse(range, FALSE); + test_range_expand(range, wordW, VARIANT_TRUE, "123"); + test_range_expand(range, wordW, VARIANT_FALSE, "123"); + test_range_move(range, characterW, 2, 2); + test_range_expand(range, wordW, VARIANT_TRUE, "123"); + + IHTMLTxtRange_Release(range); + + hres = IHTMLTxtRange_duplicate(body_range, &range); + ok(hres == S_OK, "duplicate failed: %08x\n", hres); + + test_range_text(range, "test abc 123\r\nit's text"); + test_range_move(range, characterW, 3, 3); IHTMLTxtRange_Release(range); IHTMLTxtRange_Release(body_range); diff --git a/dlls/mshtml/txtrange.c b/dlls/mshtml/txtrange.c index 7c7dad825c3..6865efd2198 100644 --- a/dlls/mshtml/txtrange.c +++ b/dlls/mshtml/txtrange.c @@ -568,6 +568,66 @@ static WCHAR prev_char(HTMLTxtRange *This, const dompos_t *pos, dompos_t *new_po return 0; } +static long move_next_chars(long cnt, const dompos_t *pos, BOOL col, dompos_t *new_pos) +{ + dompos_t iter, tmp; + long ret = 0; + WCHAR c; + + if(col) + ret++; + + if(ret >= cnt) { + *new_pos = *pos; + dompos_addref(new_pos); + return ret; + } + + c = next_char(pos, &iter); + ret++; + + while(ret < cnt) { + tmp = iter; + c = next_char(&tmp, &iter); + if(!c) { + iter = tmp; + break; + } + ret++; + dompos_release(&tmp); + } + + *new_pos = iter; + return ret; +} + +static long move_prev_chars(HTMLTxtRange *This, long cnt, const dompos_t *pos, BOOL end, dompos_t *new_pos) +{ + dompos_t iter, tmp; + long ret = 0; + WCHAR c; + + c = prev_char(This, pos, &iter); + if(c) + ret++; + + while(c && ret < cnt) { + tmp = iter; + c = prev_char(This, &tmp, &iter); + if(!c) { + iter = tmp; + if(end) + ret++; + break; + } + ret++; + dompos_release(&tmp); + } + + *new_pos = iter; + return ret; +} + static BOOL find_next_space(const dompos_t *pos, BOOL first_space, dompos_t *ret) { dompos_t iter, tmp; @@ -978,8 +1038,49 @@ static HRESULT WINAPI HTMLTxtRange_move(IHTMLTxtRange *iface, BSTR Unit, long Count, long *ActualCount) { HTMLTxtRange *This = HTMLTXTRANGE_THIS(iface); - FIXME("(%p)->(%s %ld %p)\n", This, debugstr_w(Unit), Count, ActualCount); - return E_NOTIMPL; + range_unit_t unit; + + TRACE("(%p)->(%s %ld %p)\n", This, debugstr_w(Unit), Count, ActualCount); + + unit = string_to_unit(Unit); + if(unit == RU_UNKNOWN) + return E_INVALIDARG; + + IHTMLTxtRange_collapse(HTMLTXTRANGE(This), TRUE); + + if(!Count) { + *ActualCount = 0; + return S_OK; + } + + switch(unit) { + case RU_CHAR: { + dompos_t cur_pos, new_pos; + + get_cur_pos(This, TRUE, &cur_pos); + + if(Count > 0) { + *ActualCount = move_next_chars(Count, &cur_pos, TRUE, &new_pos); + set_range_pos(This, FALSE, &new_pos); + IHTMLTxtRange_collapse(HTMLTXTRANGE(This), FALSE); + dompos_release(&new_pos); + }else { + *ActualCount = -move_prev_chars(This, -Count, &cur_pos, FALSE, &new_pos); + set_range_pos(This, TRUE, &new_pos); + IHTMLTxtRange_collapse(HTMLTXTRANGE(This), TRUE); + dompos_release(&new_pos); + } + + dompos_release(&cur_pos); + break; + } + + default: + FIXME("unimplemented unit %s\n", debugstr_w(Unit)); + } + + TRACE("ret %ld\n", *ActualCount); + return S_OK; } static HRESULT WINAPI HTMLTxtRange_moveStart(IHTMLTxtRange *iface, BSTR Unit,