2 * Copyright 2006-2007 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wine/debug.h"
33 #include "wine/unicode.h"
35 #include "mshtml_private.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(mshtml
);
39 static const WCHAR brW
[] = {'b','r',0};
42 const IHTMLTxtRangeVtbl
*lpHTMLTxtRangeVtbl
;
52 #define HTMLTXTRANGE(x) ((IHTMLTxtRange*) &(x)->lpHTMLTxtRangeVtbl)
76 static HTMLTxtRange
*get_range_object(HTMLDocument
*doc
, IHTMLTxtRange
*iface
)
80 LIST_FOR_EACH_ENTRY(iter
, &doc
->range_list
, HTMLTxtRange
, entry
) {
81 if(HTMLTXTRANGE(iter
) == iface
)
85 ERR("Could not find range in document\n");
89 static range_unit_t
string_to_unit(LPCWSTR str
)
91 static const WCHAR characterW
[] =
92 {'c','h','a','r','a','c','t','e','r',0};
93 static const WCHAR wordW
[] =
95 static const WCHAR sentenceW
[] =
96 {'s','e','n','t','e','n','c','e',0};
97 static const WCHAR texteditW
[] =
98 {'t','e','x','t','e','d','i','t',0};
100 if(!strcmpiW(str
, characterW
)) return RU_CHAR
;
101 if(!strcmpiW(str
, wordW
)) return RU_WORD
;
102 if(!strcmpiW(str
, sentenceW
)) return RU_SENTENCE
;
103 if(!strcmpiW(str
, texteditW
)) return RU_TEXTEDIT
;
108 static int string_to_nscmptype(LPCWSTR str
)
110 static const WCHAR seW
[] = {'S','t','a','r','t','T','o','E','n','d',0};
111 static const WCHAR ssW
[] = {'S','t','a','r','t','T','o','S','t','a','r','t',0};
112 static const WCHAR esW
[] = {'E','n','d','T','o','S','t','a','r','t',0};
113 static const WCHAR eeW
[] = {'E','n','d','T','o','E','n','d',0};
115 if(!strcmpiW(str
, seW
)) return NS_START_TO_END
;
116 if(!strcmpiW(str
, ssW
)) return NS_START_TO_START
;
117 if(!strcmpiW(str
, esW
)) return NS_END_TO_START
;
118 if(!strcmpiW(str
, eeW
)) return NS_END_TO_END
;
123 static PRUint16
get_node_type(nsIDOMNode
*node
)
125 PRUint16 type
= 0xfff;
128 nsIDOMNode_GetNodeType(node
, &type
);
133 static BOOL
is_br_node(nsIDOMNode
*node
)
137 const PRUnichar
*tag
;
141 nsres
= nsIDOMNode_QueryInterface(node
, &IID_nsIDOMElement
, (void**)&elem
);
145 nsAString_Init(&tag_str
, NULL
);
146 nsIDOMElement_GetTagName(elem
, &tag_str
);
147 nsIDOMElement_Release(elem
);
148 nsAString_GetData(&tag_str
, &tag
, 0);
150 if(!strcmpiW(tag
, brW
))
153 nsAString_Finish(&tag_str
);
158 static inline void wstrbuf_init(wstrbuf_t
*buf
)
162 buf
->buf
= mshtml_alloc(buf
->size
* sizeof(WCHAR
));
166 static inline void wstrbuf_finish(wstrbuf_t
*buf
)
168 mshtml_free(buf
->buf
);
171 static void wstrbuf_append_len(wstrbuf_t
*buf
, LPCWSTR str
, int len
)
173 if(buf
->len
+len
>= buf
->size
) {
174 buf
->size
= 2*buf
->len
+len
;
175 buf
->buf
= mshtml_realloc(buf
->buf
, buf
->size
* sizeof(WCHAR
));
178 memcpy(buf
->buf
+buf
->len
, str
, len
*sizeof(WCHAR
));
180 buf
->buf
[buf
->len
] = 0;
183 static inline void wstrbuf_append(wstrbuf_t
*buf
, LPCWSTR str
)
185 wstrbuf_append_len(buf
, str
, strlenW(str
));
188 static void wstrbuf_append_node(wstrbuf_t
*buf
, nsIDOMNode
*node
)
191 switch(get_node_type(node
)) {
195 const PRUnichar
*data
;
197 nsIDOMNode_QueryInterface(node
, &IID_nsIDOMText
, (void**)&nstext
);
199 nsAString_Init(&data_str
, NULL
);
200 nsIDOMText_GetData(nstext
, &data_str
);
201 nsAString_GetData(&data_str
, &data
, NULL
);
202 wstrbuf_append(buf
, data
);
203 nsAString_Finish(&data_str
);
205 nsIDOMText_Release(nstext
);
210 if(is_br_node(node
)) {
211 static const WCHAR endlW
[] = {'\r','\n'};
212 wstrbuf_append_len(buf
, endlW
, 2);
217 static BOOL
fill_nodestr(dompos_t
*pos
)
222 if(pos
->type
!= TEXT_NODE
)
225 nsres
= nsIDOMNode_QueryInterface(pos
->node
, &IID_nsIDOMText
, (void**)&text
);
229 nsAString_Init(&pos
->str
, NULL
);
230 nsIDOMText_GetData(text
, &pos
->str
);
231 nsIDOMText_Release(text
);
232 nsAString_GetData(&pos
->str
, &pos
->p
, NULL
);
237 static nsIDOMNode
*next_node(nsIDOMNode
*iter
)
239 nsIDOMNode
*ret
, *tmp
;
245 nsres
= nsIDOMNode_GetFirstChild(iter
, &ret
);
246 if(NS_SUCCEEDED(nsres
) && ret
)
249 nsIDOMNode_AddRef(iter
);
252 nsres
= nsIDOMNode_GetNextSibling(iter
, &ret
);
253 if(NS_SUCCEEDED(nsres
) && ret
) {
254 nsIDOMNode_Release(iter
);
258 nsres
= nsIDOMNode_GetParentNode(iter
, &tmp
);
259 nsIDOMNode_Release(iter
);
261 }while(NS_SUCCEEDED(nsres
) && iter
);
266 static nsIDOMNode
*prev_node(HTMLTxtRange
*This
, nsIDOMNode
*iter
)
268 nsIDOMNode
*ret
, *tmp
;
272 nsIDOMHTMLDocument
*nshtmldoc
;
273 nsIDOMHTMLElement
*nselem
;
274 nsIDOMDocument
*nsdoc
;
276 nsIWebNavigation_GetDocument(This
->doc
->nscontainer
->navigation
, &nsdoc
);
277 nsIDOMDocument_QueryInterface(nsdoc
, &IID_nsIDOMHTMLDocument
, (void**)&nshtmldoc
);
278 nsIDOMDocument_Release(nsdoc
);
279 nsIDOMHTMLDocument_GetBody(nshtmldoc
, &nselem
);
280 nsIDOMHTMLDocument_Release(nshtmldoc
);
282 nsIDOMElement_GetLastChild(nselem
, &tmp
);
284 return (nsIDOMNode
*)nselem
;
288 nsIDOMNode_GetLastChild(ret
, &tmp
);
291 nsIDOMElement_Release(nselem
);
296 nsres
= nsIDOMNode_GetLastChild(iter
, &ret
);
297 if(NS_SUCCEEDED(nsres
) && ret
)
300 nsIDOMNode_AddRef(iter
);
303 nsres
= nsIDOMNode_GetPreviousSibling(iter
, &ret
);
304 if(NS_SUCCEEDED(nsres
) && ret
) {
305 nsIDOMNode_Release(iter
);
309 nsres
= nsIDOMNode_GetParentNode(iter
, &tmp
);
310 nsIDOMNode_Release(iter
);
312 }while(NS_SUCCEEDED(nsres
) && iter
);
317 static nsIDOMNode
*get_child_node(nsIDOMNode
*node
, PRUint32 off
)
319 nsIDOMNodeList
*node_list
;
320 nsIDOMNode
*ret
= NULL
;
322 nsIDOMNode_GetChildNodes(node
, &node_list
);
323 nsIDOMNodeList_Item(node_list
, off
, &ret
);
324 nsIDOMNodeList_Release(node_list
);
329 static void get_cur_pos(HTMLTxtRange
*This
, BOOL start
, dompos_t
*pos
)
338 nsIDOMRange_GetCollapsed(This
->nsrange
, &collapsed
);
343 nsIDOMRange_GetStartContainer(This
->nsrange
, &node
);
344 nsIDOMRange_GetStartOffset(This
->nsrange
, &off
);
346 nsIDOMRange_GetEndContainer(This
->nsrange
, &node
);
347 nsIDOMRange_GetEndOffset(This
->nsrange
, &off
);
350 pos
->type
= get_node_type(node
);
351 if(pos
->type
== ELEMENT_NODE
) {
353 pos
->node
= get_child_node(node
, off
);
356 pos
->node
= off
? get_child_node(node
, off
-1) : prev_node(This
, node
);
360 pos
->type
= get_node_type(pos
->node
);
361 nsIDOMNode_Release(node
);
369 pos
->node
= prev_node(This
, node
);
371 nsIDOMNode_Release(node
);
374 if(pos
->type
== TEXT_NODE
)
378 static void set_range_pos(HTMLTxtRange
*This
, BOOL start
, dompos_t
*pos
)
383 if(pos
->type
== TEXT_NODE
)
384 nsres
= nsIDOMRange_SetStart(This
->nsrange
, pos
->node
, pos
->off
);
386 nsres
= nsIDOMRange_SetStartBefore(This
->nsrange
, pos
->node
);
388 if(pos
->type
== TEXT_NODE
)
389 nsres
= nsIDOMRange_SetEnd(This
->nsrange
, pos
->node
, pos
->off
+1);
391 nsres
= nsIDOMRange_SetEndAfter(This
->nsrange
, pos
->node
);
395 ERR("failed: %p %08x\n", pos
->node
, nsres
);
398 static inline void dompos_release(dompos_t
*pos
)
401 nsIDOMNode_Release(pos
->node
);
404 nsAString_Finish(&pos
->str
);
407 static inline void dompos_addref(dompos_t
*pos
)
410 nsIDOMNode_AddRef(pos
->node
);
412 if(pos
->type
== TEXT_NODE
)
416 static inline BOOL
dompos_cmp(const dompos_t
*pos1
, const dompos_t
*pos2
)
418 return pos1
->node
== pos2
->node
&& pos1
->off
== pos2
->off
;
421 static void range_to_string(HTMLTxtRange
*This
, wstrbuf_t
*buf
)
423 nsIDOMNode
*iter
, *tmp
;
424 dompos_t start_pos
, end_pos
;
427 nsIDOMRange_GetCollapsed(This
->nsrange
, &collapsed
);
435 get_cur_pos(This
, FALSE
, &end_pos
);
436 get_cur_pos(This
, TRUE
, &start_pos
);
438 if(start_pos
.type
== TEXT_NODE
) {
439 if(start_pos
.node
== end_pos
.node
) {
440 wstrbuf_append_len(buf
, start_pos
.p
+start_pos
.off
, end_pos
.off
-start_pos
.off
+1);
441 iter
= start_pos
.node
;
442 nsIDOMNode_AddRef(iter
);
444 wstrbuf_append(buf
, start_pos
.p
+start_pos
.off
);
445 iter
= next_node(start_pos
.node
);
448 iter
= start_pos
.node
;
449 nsIDOMNode_AddRef(iter
);
452 while(iter
!= end_pos
.node
) {
453 wstrbuf_append_node(buf
, iter
);
454 tmp
= next_node(iter
);
455 nsIDOMNode_Release(iter
);
459 nsIDOMNode_AddRef(end_pos
.node
);
461 if(start_pos
.node
!= end_pos
.node
&& !is_br_node(end_pos
.node
))
462 wstrbuf_append_len(buf
, end_pos
.p
, end_pos
.off
+1);
464 nsIDOMNode_Release(iter
);
465 dompos_release(&start_pos
);
466 dompos_release(&end_pos
);
469 static WCHAR
get_pos_char(const dompos_t
*pos
)
473 return pos
->p
[pos
->off
];
475 if(is_br_node(pos
->node
))
482 static WCHAR
next_char(const dompos_t
*pos
, dompos_t
*new_pos
)
484 nsIDOMNode
*iter
, *tmp
;
486 if(pos
->type
== TEXT_NODE
&& pos
->off
!= -1 && pos
->p
[pos
->off
+1]) {
489 dompos_addref(new_pos
);
490 return new_pos
->p
[new_pos
->off
];
493 iter
= next_node(pos
->node
);
498 switch(get_node_type(iter
)) {
500 new_pos
->node
= iter
;
501 new_pos
->type
= TEXT_NODE
;
503 fill_nodestr(new_pos
);
507 if(!is_br_node(iter
))
510 new_pos
->node
= iter
;
511 new_pos
->type
= ELEMENT_NODE
;
518 iter
= next_node(iter
);
519 nsIDOMNode_Release(tmp
);
528 static WCHAR
prev_char(HTMLTxtRange
*This
, const dompos_t
*pos
, dompos_t
*new_pos
)
530 nsIDOMNode
*iter
, *tmp
;
532 if(pos
->type
== TEXT_NODE
&& pos
->off
> 0) {
535 dompos_addref(new_pos
);
536 return new_pos
->p
[new_pos
->off
];
539 iter
= prev_node(This
, pos
->node
);
544 switch(get_node_type(iter
)) {
546 new_pos
->node
= iter
;
547 new_pos
->type
= TEXT_NODE
;
548 fill_nodestr(new_pos
);
549 new_pos
->off
= strlenW(new_pos
->p
)-1;
550 return new_pos
->p
[new_pos
->off
];
553 if(!is_br_node(iter
))
556 new_pos
->node
= iter
;
557 new_pos
->type
= ELEMENT_NODE
;
564 iter
= prev_node(This
, iter
);
565 nsIDOMNode_Release(tmp
);
572 dompos_addref(new_pos
);
576 static long move_next_chars(long cnt
, const dompos_t
*pos
, BOOL col
, const dompos_t
*bound_pos
,
577 BOOL
*bounded
, dompos_t
*new_pos
)
591 dompos_addref(new_pos
);
595 c
= next_char(pos
, &iter
);
600 c
= next_char(&tmp
, &iter
);
606 dompos_release(&tmp
);
607 if(bound_pos
&& dompos_cmp(&tmp
, bound_pos
)) {
617 static long move_prev_chars(HTMLTxtRange
*This
, long cnt
, const dompos_t
*pos
, BOOL end
,
618 const dompos_t
*bound_pos
, BOOL
*bounded
, dompos_t
*new_pos
)
627 c
= prev_char(This
, pos
, &iter
);
631 while(c
&& ret
< cnt
) {
633 c
= prev_char(This
, &tmp
, &iter
);
642 dompos_release(&tmp
);
644 if(bound_pos
&& dompos_cmp(&iter
, bound_pos
))
652 static BOOL
find_next_space(const dompos_t
*pos
, BOOL first_space
, dompos_t
*ret
)
658 c
= get_pos_char(pos
);
659 if(c
&& isspaceW(c
)) {
666 c
= next_char(pos
, &iter
);
673 while(!isspaceW(c
)) {
675 c
= next_char(&tmp
, &iter
);
680 dompos_release(&tmp
);
687 static long find_prev_space(HTMLTxtRange
*This
, const dompos_t
*pos
, BOOL first_space
, dompos_t
*ret
)
692 c
= prev_char(This
, pos
, &iter
);
693 if(!c
|| (first_space
&& isspaceW(c
))) {
701 c
= prev_char(This
, &tmp
, &iter
);
702 if(!c
|| isspaceW(c
)) {
703 dompos_release(&iter
);
706 dompos_release(&tmp
);
713 static long move_next_words(long cnt
, const dompos_t
*pos
, dompos_t
*new_pos
)
719 dompos_addref(&iter
);
722 if(!find_next_space(&iter
, FALSE
, &tmp
))
726 dompos_release(&iter
);
734 static long move_prev_words(HTMLTxtRange
*This
, long cnt
, const dompos_t
*pos
, dompos_t
*new_pos
)
740 dompos_addref(&iter
);
743 if(!find_prev_space(This
, &iter
, FALSE
, &tmp
))
746 dompos_release(&iter
);
755 #define HTMLTXTRANGE_THIS(iface) DEFINE_THIS(HTMLTxtRange, HTMLTxtRange, iface)
757 static HRESULT WINAPI
HTMLTxtRange_QueryInterface(IHTMLTxtRange
*iface
, REFIID riid
, void **ppv
)
759 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
763 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
764 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
765 *ppv
= HTMLTXTRANGE(This
);
766 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
767 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
768 *ppv
= HTMLTXTRANGE(This
);
769 }else if(IsEqualGUID(&IID_IHTMLTxtRange
, riid
)) {
770 TRACE("(%p)->(IID_IHTMLTxtRange %p)\n", This
, ppv
);
771 *ppv
= HTMLTXTRANGE(This
);
775 IUnknown_AddRef((IUnknown
*)*ppv
);
779 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
780 return E_NOINTERFACE
;
783 static ULONG WINAPI
HTMLTxtRange_AddRef(IHTMLTxtRange
*iface
)
785 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
786 LONG ref
= InterlockedIncrement(&This
->ref
);
788 TRACE("(%p) ref=%d\n", This
, ref
);
793 static ULONG WINAPI
HTMLTxtRange_Release(IHTMLTxtRange
*iface
)
795 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
796 LONG ref
= InterlockedDecrement(&This
->ref
);
798 TRACE("(%p) ref=%d\n", This
, ref
);
802 nsISelection_Release(This
->nsrange
);
804 list_remove(&This
->entry
);
811 static HRESULT WINAPI
HTMLTxtRange_GetTypeInfoCount(IHTMLTxtRange
*iface
, UINT
*pctinfo
)
813 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
814 FIXME("(%p)->(%p)\n", This
, pctinfo
);
818 static HRESULT WINAPI
HTMLTxtRange_GetTypeInfo(IHTMLTxtRange
*iface
, UINT iTInfo
,
819 LCID lcid
, ITypeInfo
**ppTInfo
)
821 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
822 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
826 static HRESULT WINAPI
HTMLTxtRange_GetIDsOfNames(IHTMLTxtRange
*iface
, REFIID riid
,
827 LPOLESTR
*rgszNames
, UINT cNames
,
828 LCID lcid
, DISPID
*rgDispId
)
830 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
831 FIXME("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
836 static HRESULT WINAPI
HTMLTxtRange_Invoke(IHTMLTxtRange
*iface
, DISPID dispIdMember
,
837 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
838 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
840 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
841 FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
842 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
846 static HRESULT WINAPI
HTMLTxtRange_get_htmlText(IHTMLTxtRange
*iface
, BSTR
*p
)
848 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
850 TRACE("(%p)->(%p)\n", This
, p
);
855 nsIDOMDocumentFragment
*fragment
;
858 nsres
= nsIDOMRange_CloneContents(This
->nsrange
, &fragment
);
859 if(NS_SUCCEEDED(nsres
)) {
860 const PRUnichar
*nstext
;
863 nsAString_Init(&nsstr
, NULL
);
864 nsnode_to_nsstring((nsIDOMNode
*)fragment
, &nsstr
);
865 nsIDOMDocumentFragment_Release(fragment
);
867 nsAString_GetData(&nsstr
, &nstext
, NULL
);
868 *p
= SysAllocString(nstext
);
870 nsAString_Finish(&nsstr
);
875 const WCHAR emptyW
[] = {0};
876 *p
= SysAllocString(emptyW
);
879 TRACE("return %s\n", debugstr_w(*p
));
883 static HRESULT WINAPI
HTMLTxtRange_put_text(IHTMLTxtRange
*iface
, BSTR v
)
885 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
886 nsIDOMDocument
*nsdoc
;
887 nsIDOMText
*text_node
;
891 TRACE("(%p)->(%s)\n", This
, debugstr_w(v
));
894 return MSHTML_E_NODOC
;
896 nsres
= nsIWebNavigation_GetDocument(This
->doc
->nscontainer
->navigation
, &nsdoc
);
897 if(NS_FAILED(nsres
)) {
898 ERR("GetDocument failed: %08x\n", nsres
);
902 nsAString_Init(&text_str
, v
);
903 nsres
= nsIDOMDocument_CreateTextNode(nsdoc
, &text_str
, &text_node
);
904 nsIDOMDocument_Release(nsdoc
);
905 nsAString_Finish(&text_str
);
906 if(NS_FAILED(nsres
)) {
907 ERR("CreateTextNode failed: %08x\n", nsres
);
910 nsres
= nsIDOMRange_DeleteContents(This
->nsrange
);
912 ERR("DeleteContents failed: %08x\n", nsres
);
914 nsres
= nsIDOMRange_InsertNode(This
->nsrange
, (nsIDOMNode
*)text_node
);
916 ERR("InsertNode failed: %08x\n", nsres
);
918 nsres
= nsIDOMRange_SetEndAfter(This
->nsrange
, (nsIDOMNode
*)text_node
);
920 ERR("SetEndAfter failed: %08x\n", nsres
);
922 return IHTMLTxtRange_collapse(HTMLTXTRANGE(This
), VARIANT_FALSE
);
925 static HRESULT WINAPI
HTMLTxtRange_get_text(IHTMLTxtRange
*iface
, BSTR
*p
)
927 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
930 TRACE("(%p)->(%p)\n", This
, p
);
937 range_to_string(This
, &buf
);
939 *p
= SysAllocString(buf
.buf
);
940 wstrbuf_finish(&buf
);
942 TRACE("ret %s\n", debugstr_w(*p
));
946 static HRESULT WINAPI
HTMLTxtRange_parentElement(IHTMLTxtRange
*iface
, IHTMLElement
**parent
)
948 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
949 nsIDOMNode
*nsnode
, *tmp
;
952 TRACE("(%p)->(%p)\n", This
, parent
);
954 nsIDOMRange_GetCommonAncestorContainer(This
->nsrange
, &nsnode
);
955 while(nsnode
&& get_node_type(nsnode
) != ELEMENT_NODE
) {
956 nsIDOMNode_GetParentNode(nsnode
, &tmp
);
957 nsIDOMNode_Release(nsnode
);
966 node
= get_node(This
->doc
, nsnode
);
967 nsIDOMNode_Release(nsnode
);
969 return IHTMLDOMNode_QueryInterface(HTMLDOMNODE(node
), &IID_IHTMLElement
, (void**)parent
);
972 static HRESULT WINAPI
HTMLTxtRange_duplicate(IHTMLTxtRange
*iface
, IHTMLTxtRange
**Duplicate
)
974 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
975 nsIDOMRange
*nsrange
= NULL
;
977 TRACE("(%p)->(%p)\n", This
, Duplicate
);
979 nsIDOMRange_CloneRange(This
->nsrange
, &nsrange
);
980 *Duplicate
= HTMLTxtRange_Create(This
->doc
, nsrange
);
981 nsIDOMRange_Release(nsrange
);
986 static HRESULT WINAPI
HTMLTxtRange_inRange(IHTMLTxtRange
*iface
, IHTMLTxtRange
*Range
,
987 VARIANT_BOOL
*InRange
)
989 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
990 HTMLTxtRange
*src_range
;
994 TRACE("(%p)->(%p %p)\n", This
, Range
, InRange
);
996 *InRange
= VARIANT_FALSE
;
998 src_range
= get_range_object(This
->doc
, Range
);
1002 nsres
= nsIDOMRange_CompareBoundaryPoints(This
->nsrange
, NS_START_TO_START
,
1003 src_range
->nsrange
, &nsret
);
1004 if(NS_SUCCEEDED(nsres
) && nsret
<= 0) {
1005 nsres
= nsIDOMRange_CompareBoundaryPoints(This
->nsrange
, NS_END_TO_END
,
1006 src_range
->nsrange
, &nsret
);
1007 if(NS_SUCCEEDED(nsres
) && nsret
>= 0)
1008 *InRange
= VARIANT_TRUE
;
1011 if(NS_FAILED(nsres
))
1012 ERR("CompareBoundaryPoints failed: %08x\n", nsres
);
1017 static HRESULT WINAPI
HTMLTxtRange_isEqual(IHTMLTxtRange
*iface
, IHTMLTxtRange
*Range
,
1018 VARIANT_BOOL
*IsEqual
)
1020 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1021 HTMLTxtRange
*src_range
;
1025 TRACE("(%p)->(%p %p)\n", This
, Range
, IsEqual
);
1027 *IsEqual
= VARIANT_FALSE
;
1029 src_range
= get_range_object(This
->doc
, Range
);
1033 nsres
= nsIDOMRange_CompareBoundaryPoints(This
->nsrange
, NS_START_TO_START
,
1034 src_range
->nsrange
, &nsret
);
1035 if(NS_SUCCEEDED(nsres
) && !nsret
) {
1036 nsres
= nsIDOMRange_CompareBoundaryPoints(This
->nsrange
, NS_END_TO_END
,
1037 src_range
->nsrange
, &nsret
);
1038 if(NS_SUCCEEDED(nsres
) && !nsret
)
1039 *IsEqual
= VARIANT_TRUE
;
1042 if(NS_FAILED(nsres
))
1043 ERR("CompareBoundaryPoints failed: %08x\n", nsres
);
1048 static HRESULT WINAPI
HTMLTxtRange_scrollIntoView(IHTMLTxtRange
*iface
, VARIANT_BOOL fStart
)
1050 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1051 FIXME("(%p)->(%x)\n", This
, fStart
);
1055 static HRESULT WINAPI
HTMLTxtRange_collapse(IHTMLTxtRange
*iface
, VARIANT_BOOL Start
)
1057 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1059 TRACE("(%p)->(%x)\n", This
, Start
);
1061 nsIDOMRange_Collapse(This
->nsrange
, Start
!= VARIANT_FALSE
);
1065 static HRESULT WINAPI
HTMLTxtRange_expand(IHTMLTxtRange
*iface
, BSTR Unit
, VARIANT_BOOL
*Success
)
1067 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1070 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(Unit
), Success
);
1072 unit
= string_to_unit(Unit
);
1073 if(unit
== RU_UNKNOWN
)
1074 return E_INVALIDARG
;
1078 dompos_t end_pos
, start_pos
, new_pos
;
1080 *Success
= VARIANT_FALSE
;
1082 get_cur_pos(This
, TRUE
, &start_pos
);
1083 get_cur_pos(This
, FALSE
, &end_pos
);
1084 if(find_next_space(&end_pos
, TRUE
, &new_pos
)) {
1085 set_range_pos(This
, FALSE
, &new_pos
);
1086 *Success
= VARIANT_TRUE
;
1088 dompos_release(&new_pos
);
1090 if(find_prev_space(This
, &start_pos
, TRUE
, &new_pos
)) {
1091 set_range_pos(This
, TRUE
, &new_pos
);
1092 *Success
= VARIANT_TRUE
;
1095 dompos_release(&new_pos
);
1096 dompos_release(&end_pos
);
1101 FIXME("Unimplemented unit %s\n", debugstr_w(Unit
));
1107 static HRESULT WINAPI
HTMLTxtRange_move(IHTMLTxtRange
*iface
, BSTR Unit
,
1108 long Count
, long *ActualCount
)
1110 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1113 TRACE("(%p)->(%s %ld %p)\n", This
, debugstr_w(Unit
), Count
, ActualCount
);
1115 unit
= string_to_unit(Unit
);
1116 if(unit
== RU_UNKNOWN
)
1117 return E_INVALIDARG
;
1119 IHTMLTxtRange_collapse(HTMLTXTRANGE(This
), TRUE
);
1128 dompos_t cur_pos
, new_pos
;
1130 get_cur_pos(This
, TRUE
, &cur_pos
);
1133 *ActualCount
= move_next_chars(Count
, &cur_pos
, TRUE
, NULL
, NULL
, &new_pos
);
1134 set_range_pos(This
, FALSE
, &new_pos
);
1135 IHTMLTxtRange_collapse(HTMLTXTRANGE(This
), FALSE
);
1136 dompos_release(&new_pos
);
1138 *ActualCount
= -move_prev_chars(This
, -Count
, &cur_pos
, FALSE
, NULL
, NULL
, &new_pos
);
1139 set_range_pos(This
, TRUE
, &new_pos
);
1140 IHTMLTxtRange_collapse(HTMLTXTRANGE(This
), TRUE
);
1141 dompos_release(&new_pos
);
1144 dompos_release(&cur_pos
);
1149 dompos_t cur_pos
, new_pos
;
1151 get_cur_pos(This
, TRUE
, &cur_pos
);
1154 *ActualCount
= move_next_words(Count
, &cur_pos
, &new_pos
);
1155 set_range_pos(This
, FALSE
, &new_pos
);
1156 IHTMLTxtRange_collapse(HTMLTXTRANGE(This
), FALSE
);
1157 dompos_release(&new_pos
);
1159 *ActualCount
= -move_prev_words(This
, -Count
, &cur_pos
, &new_pos
);
1160 set_range_pos(This
, TRUE
, &new_pos
);
1161 IHTMLTxtRange_collapse(HTMLTXTRANGE(This
), TRUE
);
1162 dompos_release(&new_pos
);
1165 dompos_release(&cur_pos
);
1170 FIXME("unimplemented unit %s\n", debugstr_w(Unit
));
1173 TRACE("ret %ld\n", *ActualCount
);
1177 static HRESULT WINAPI
HTMLTxtRange_moveStart(IHTMLTxtRange
*iface
, BSTR Unit
,
1178 long Count
, long *ActualCount
)
1180 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1183 TRACE("(%p)->(%s %ld %p)\n", This
, debugstr_w(Unit
), Count
, ActualCount
);
1185 unit
= string_to_unit(Unit
);
1186 if(unit
== RU_UNKNOWN
)
1187 return E_INVALIDARG
;
1196 dompos_t start_pos
, end_pos
, new_pos
;
1199 get_cur_pos(This
, TRUE
, &start_pos
);
1200 get_cur_pos(This
, FALSE
, &end_pos
);
1201 nsIDOMRange_GetCollapsed(This
->nsrange
, &collapsed
);
1206 *ActualCount
= move_next_chars(Count
, &start_pos
, collapsed
, &end_pos
, &bounded
, &new_pos
);
1207 set_range_pos(This
, !bounded
, &new_pos
);
1209 IHTMLTxtRange_collapse(HTMLTXTRANGE(This
), FALSE
);
1211 *ActualCount
= -move_prev_chars(This
, -Count
, &start_pos
, FALSE
, NULL
, NULL
, &new_pos
);
1212 set_range_pos(This
, TRUE
, &new_pos
);
1215 dompos_release(&start_pos
);
1216 dompos_release(&end_pos
);
1217 dompos_release(&new_pos
);
1222 FIXME("unimplemented unit %s\n", debugstr_w(Unit
));
1228 static HRESULT WINAPI
HTMLTxtRange_moveEnd(IHTMLTxtRange
*iface
, BSTR Unit
,
1229 long Count
, long *ActualCount
)
1231 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1234 TRACE("(%p)->(%s %ld %p)\n", This
, debugstr_w(Unit
), Count
, ActualCount
);
1236 unit
= string_to_unit(Unit
);
1237 if(unit
== RU_UNKNOWN
)
1238 return E_INVALIDARG
;
1247 dompos_t start_pos
, end_pos
, new_pos
;
1250 get_cur_pos(This
, TRUE
, &start_pos
);
1251 get_cur_pos(This
, FALSE
, &end_pos
);
1252 nsIDOMRange_GetCollapsed(This
->nsrange
, &collapsed
);
1255 *ActualCount
= move_next_chars(Count
, &end_pos
, collapsed
, NULL
, NULL
, &new_pos
);
1256 set_range_pos(This
, FALSE
, &new_pos
);
1260 *ActualCount
= -move_prev_chars(This
, -Count
, &end_pos
, TRUE
, &start_pos
, &bounded
, &new_pos
);
1261 set_range_pos(This
, bounded
, &new_pos
);
1263 IHTMLTxtRange_collapse(HTMLTXTRANGE(This
), TRUE
);
1266 dompos_release(&start_pos
);
1267 dompos_release(&end_pos
);
1268 dompos_release(&new_pos
);
1273 FIXME("unimplemented unit %s\n", debugstr_w(Unit
));
1279 static HRESULT WINAPI
HTMLTxtRange_select(IHTMLTxtRange
*iface
)
1281 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1283 TRACE("(%p)\n", This
);
1285 if(This
->doc
->nscontainer
) {
1286 nsIDOMWindow
*dom_window
= NULL
;
1287 nsISelection
*nsselection
;
1289 nsIWebBrowser_GetContentDOMWindow(This
->doc
->nscontainer
->webbrowser
, &dom_window
);
1290 nsIDOMWindow_GetSelection(dom_window
, &nsselection
);
1291 nsIDOMWindow_Release(dom_window
);
1293 nsISelection_RemoveAllRanges(nsselection
);
1294 nsISelection_AddRange(nsselection
, This
->nsrange
);
1296 nsISelection_Release(nsselection
);
1302 static HRESULT WINAPI
HTMLTxtRange_pasteHTML(IHTMLTxtRange
*iface
, BSTR html
)
1304 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1305 FIXME("(%p)->(%s)\n", This
, debugstr_w(html
));
1309 static HRESULT WINAPI
HTMLTxtRange_moveToElementText(IHTMLTxtRange
*iface
, IHTMLElement
*element
)
1311 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1312 FIXME("(%p)->(%p)\n", This
, element
);
1316 static HRESULT WINAPI
HTMLTxtRange_setEndPoint(IHTMLTxtRange
*iface
, BSTR how
,
1317 IHTMLTxtRange
*SourceRange
)
1319 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1320 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(how
), SourceRange
);
1324 static HRESULT WINAPI
HTMLTxtRange_compareEndPoints(IHTMLTxtRange
*iface
, BSTR how
,
1325 IHTMLTxtRange
*SourceRange
, long *ret
)
1327 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1328 HTMLTxtRange
*src_range
;
1333 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_w(how
), SourceRange
, ret
);
1335 nscmpt
= string_to_nscmptype(how
);
1337 return E_INVALIDARG
;
1339 src_range
= get_range_object(This
->doc
, SourceRange
);
1343 nsres
= nsIDOMRange_CompareBoundaryPoints(This
->nsrange
, nscmpt
, src_range
->nsrange
, &nsret
);
1344 if(NS_FAILED(nsres
))
1345 ERR("CompareBoundaryPoints failed: %08x\n", nsres
);
1351 static HRESULT WINAPI
HTMLTxtRange_findText(IHTMLTxtRange
*iface
, BSTR String
,
1352 long count
, long Flags
, VARIANT_BOOL
*Success
)
1354 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1355 FIXME("(%p)->(%s %ld %08lx %p)\n", This
, debugstr_w(String
), count
, Flags
, Success
);
1359 static HRESULT WINAPI
HTMLTxtRange_moveToPoint(IHTMLTxtRange
*iface
, long x
, long y
)
1361 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1362 FIXME("(%p)->(%ld %ld)\n", This
, x
, y
);
1366 static HRESULT WINAPI
HTMLTxtRange_getBookmark(IHTMLTxtRange
*iface
, BSTR
*Bookmark
)
1368 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1369 FIXME("(%p)->(%p)\n", This
, Bookmark
);
1373 static HRESULT WINAPI
HTMLTxtRange_moveToBookmark(IHTMLTxtRange
*iface
, BSTR Bookmark
,
1374 VARIANT_BOOL
*Success
)
1376 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1377 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(Bookmark
), Success
);
1381 static HRESULT WINAPI
HTMLTxtRange_queryCommandSupported(IHTMLTxtRange
*iface
, BSTR cmdID
,
1382 VARIANT_BOOL
*pfRet
)
1384 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1385 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(cmdID
), pfRet
);
1389 static HRESULT WINAPI
HTMLTxtRange_queryCommandEnabled(IHTMLTxtRange
*iface
, BSTR cmdID
,
1390 VARIANT_BOOL
*pfRet
)
1392 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1393 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(cmdID
), pfRet
);
1397 static HRESULT WINAPI
HTMLTxtRange_queryCommandState(IHTMLTxtRange
*iface
, BSTR cmdID
,
1398 VARIANT_BOOL
*pfRet
)
1400 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1401 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(cmdID
), pfRet
);
1405 static HRESULT WINAPI
HTMLTxtRange_queryCommandIndeterm(IHTMLTxtRange
*iface
, BSTR cmdID
,
1406 VARIANT_BOOL
*pfRet
)
1408 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1409 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(cmdID
), pfRet
);
1413 static HRESULT WINAPI
HTMLTxtRange_queryCommandText(IHTMLTxtRange
*iface
, BSTR cmdID
,
1416 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1417 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(cmdID
), pcmdText
);
1421 static HRESULT WINAPI
HTMLTxtRange_queryCommandValue(IHTMLTxtRange
*iface
, BSTR cmdID
,
1424 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1425 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(cmdID
), pcmdValue
);
1429 static HRESULT WINAPI
HTMLTxtRange_execCommand(IHTMLTxtRange
*iface
, BSTR cmdID
,
1430 VARIANT_BOOL showUI
, VARIANT value
, VARIANT_BOOL
*pfRet
)
1432 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1433 FIXME("(%p)->(%s %x v %p)\n", This
, debugstr_w(cmdID
), showUI
, pfRet
);
1437 static HRESULT WINAPI
HTMLTxtRange_execCommandShowHelp(IHTMLTxtRange
*iface
, BSTR cmdID
,
1438 VARIANT_BOOL
*pfRet
)
1440 HTMLTxtRange
*This
= HTMLTXTRANGE_THIS(iface
);
1441 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(cmdID
), pfRet
);
1445 #undef HTMLTXTRANGE_THIS
1447 static const IHTMLTxtRangeVtbl HTMLTxtRangeVtbl
= {
1448 HTMLTxtRange_QueryInterface
,
1449 HTMLTxtRange_AddRef
,
1450 HTMLTxtRange_Release
,
1451 HTMLTxtRange_GetTypeInfoCount
,
1452 HTMLTxtRange_GetTypeInfo
,
1453 HTMLTxtRange_GetIDsOfNames
,
1454 HTMLTxtRange_Invoke
,
1455 HTMLTxtRange_get_htmlText
,
1456 HTMLTxtRange_put_text
,
1457 HTMLTxtRange_get_text
,
1458 HTMLTxtRange_parentElement
,
1459 HTMLTxtRange_duplicate
,
1460 HTMLTxtRange_inRange
,
1461 HTMLTxtRange_isEqual
,
1462 HTMLTxtRange_scrollIntoView
,
1463 HTMLTxtRange_collapse
,
1464 HTMLTxtRange_expand
,
1466 HTMLTxtRange_moveStart
,
1467 HTMLTxtRange_moveEnd
,
1468 HTMLTxtRange_select
,
1469 HTMLTxtRange_pasteHTML
,
1470 HTMLTxtRange_moveToElementText
,
1471 HTMLTxtRange_setEndPoint
,
1472 HTMLTxtRange_compareEndPoints
,
1473 HTMLTxtRange_findText
,
1474 HTMLTxtRange_moveToPoint
,
1475 HTMLTxtRange_getBookmark
,
1476 HTMLTxtRange_moveToBookmark
,
1477 HTMLTxtRange_queryCommandSupported
,
1478 HTMLTxtRange_queryCommandEnabled
,
1479 HTMLTxtRange_queryCommandState
,
1480 HTMLTxtRange_queryCommandIndeterm
,
1481 HTMLTxtRange_queryCommandText
,
1482 HTMLTxtRange_queryCommandValue
,
1483 HTMLTxtRange_execCommand
,
1484 HTMLTxtRange_execCommandShowHelp
1487 IHTMLTxtRange
*HTMLTxtRange_Create(HTMLDocument
*doc
, nsIDOMRange
*nsrange
)
1489 HTMLTxtRange
*ret
= mshtml_alloc(sizeof(HTMLTxtRange
));
1491 ret
->lpHTMLTxtRangeVtbl
= &HTMLTxtRangeVtbl
;
1495 nsIDOMRange_AddRef(nsrange
);
1496 ret
->nsrange
= nsrange
;
1499 list_add_head(&doc
->range_list
, &ret
->entry
);
1501 return HTMLTXTRANGE(ret
);
1504 void detach_ranges(HTMLDocument
*This
)
1508 LIST_FOR_EACH_ENTRY(iter
, &This
->range_list
, HTMLTxtRange
, entry
) {