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
30 #include "wine/debug.h"
32 #include "mshtml_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(mshtml
);
36 static const WCHAR brW
[] = {'b','r',0};
37 static const WCHAR hrW
[] = {'h','r',0};
41 IHTMLTxtRange IHTMLTxtRange_iface
;
42 IOleCommandTarget IOleCommandTarget_iface
;
47 HTMLDocumentNode
*doc
;
72 static HTMLTxtRange
*get_range_object(HTMLDocumentNode
*doc
, IHTMLTxtRange
*iface
)
76 LIST_FOR_EACH_ENTRY(iter
, &doc
->range_list
, HTMLTxtRange
, entry
) {
77 if(&iter
->IHTMLTxtRange_iface
== iface
)
81 ERR("Could not find range in document\n");
85 static range_unit_t
string_to_unit(LPCWSTR str
)
87 static const WCHAR characterW
[] =
88 {'c','h','a','r','a','c','t','e','r',0};
89 static const WCHAR wordW
[] =
91 static const WCHAR sentenceW
[] =
92 {'s','e','n','t','e','n','c','e',0};
93 static const WCHAR texteditW
[] =
94 {'t','e','x','t','e','d','i','t',0};
96 if(!strcmpiW(str
, characterW
)) return RU_CHAR
;
97 if(!strcmpiW(str
, wordW
)) return RU_WORD
;
98 if(!strcmpiW(str
, sentenceW
)) return RU_SENTENCE
;
99 if(!strcmpiW(str
, texteditW
)) return RU_TEXTEDIT
;
104 static int string_to_nscmptype(LPCWSTR str
)
106 static const WCHAR seW
[] = {'S','t','a','r','t','T','o','E','n','d',0};
107 static const WCHAR ssW
[] = {'S','t','a','r','t','T','o','S','t','a','r','t',0};
108 static const WCHAR esW
[] = {'E','n','d','T','o','S','t','a','r','t',0};
109 static const WCHAR eeW
[] = {'E','n','d','T','o','E','n','d',0};
111 if(!strcmpiW(str
, seW
)) return NS_START_TO_END
;
112 if(!strcmpiW(str
, ssW
)) return NS_START_TO_START
;
113 if(!strcmpiW(str
, esW
)) return NS_END_TO_START
;
114 if(!strcmpiW(str
, eeW
)) return NS_END_TO_END
;
119 static UINT16
get_node_type(nsIDOMNode
*node
)
124 nsIDOMNode_GetNodeType(node
, &type
);
129 static void get_text_node_data(nsIDOMNode
*node
, nsAString
*nsstr
, const PRUnichar
**str
)
134 nsres
= nsIDOMNode_QueryInterface(node
, &IID_nsIDOMText
, (void**)&nstext
);
135 assert(nsres
== NS_OK
);
137 nsAString_Init(nsstr
, NULL
);
138 nsres
= nsIDOMText_GetData(nstext
, nsstr
);
139 nsIDOMText_Release(nstext
);
141 ERR("GetData failed: %08x\n", nsres
);
143 nsAString_GetData(nsstr
, str
);
146 static nsIDOMNode
*get_child_node(nsIDOMNode
*node
, UINT32 off
)
148 nsIDOMNodeList
*node_list
;
149 nsIDOMNode
*ret
= NULL
;
151 nsIDOMNode_GetChildNodes(node
, &node_list
);
152 nsIDOMNodeList_Item(node_list
, off
, &ret
);
153 nsIDOMNodeList_Release(node_list
);
158 /* This is very inefficient, but there is no faster way to compute index in
159 * child node list using public API. Gecko has internal nsINode::IndexOf
160 * function that we could consider exporting and use instead. */
161 static int get_child_index(nsIDOMNode
*parent
, nsIDOMNode
*child
)
163 nsIDOMNodeList
*node_list
;
168 nsres
= nsIDOMNode_GetChildNodes(parent
, &node_list
);
169 assert(nsres
== NS_OK
);
172 nsres
= nsIDOMNodeList_Item(node_list
, ret
, &node
);
173 assert(nsres
== NS_OK
&& node
);
175 nsIDOMNode_Release(node
);
178 nsIDOMNode_Release(node
);
182 nsIDOMNodeList_Release(node_list
);
186 static void init_rangepoint(rangepoint_t
*rangepoint
, nsIDOMNode
*node
, UINT32 off
)
188 nsIDOMNode_AddRef(node
);
190 rangepoint
->type
= get_node_type(node
);
191 rangepoint
->node
= node
;
192 rangepoint
->off
= off
;
195 static inline void free_rangepoint(rangepoint_t
*rangepoint
)
197 nsIDOMNode_Release(rangepoint
->node
);
200 static inline BOOL
rangepoint_cmp(const rangepoint_t
*point1
, const rangepoint_t
*point2
)
202 return point1
->node
== point2
->node
&& point1
->off
== point2
->off
;
205 static BOOL
rangepoint_next_node(rangepoint_t
*iter
)
211 /* Try to move to the child node. */
212 node
= get_child_node(iter
->node
, iter
->off
);
214 free_rangepoint(iter
);
215 init_rangepoint(iter
, node
, 0);
216 nsIDOMNode_Release(node
);
220 /* There are no more children in the node. Move to parent. */
221 nsres
= nsIDOMNode_GetParentNode(iter
->node
, &node
);
222 assert(nsres
== NS_OK
);
226 off
= get_child_index(node
, iter
->node
)+1;
227 free_rangepoint(iter
);
228 init_rangepoint(iter
, node
, off
);
229 nsIDOMNode_Release(node
);
233 static UINT32
get_child_count(nsIDOMNode
*node
)
235 nsIDOMNodeList
*node_list
;
239 nsres
= nsIDOMNode_GetChildNodes(node
, &node_list
);
240 assert(nsres
== NS_OK
);
242 nsres
= nsIDOMNodeList_GetLength(node_list
, &ret
);
243 nsIDOMNodeList_Release(node_list
);
244 assert(nsres
== NS_OK
);
249 static UINT32
get_text_length(nsIDOMNode
*node
)
255 nsres
= nsIDOMNode_QueryInterface(node
, &IID_nsIDOMText
, (void**)&nstext
);
256 assert(nsres
== NS_OK
);
258 nsres
= nsIDOMText_GetLength(nstext
, &ret
);
259 nsIDOMText_Release(nstext
);
260 assert(nsres
== NS_OK
);
265 static BOOL
rangepoint_prev_node(rangepoint_t
*iter
)
271 /* Try to move to the child node. */
273 node
= get_child_node(iter
->node
, iter
->off
-1);
274 assert(node
!= NULL
);
276 off
= get_node_type(node
) == TEXT_NODE
? get_text_length(node
) : get_child_count(node
);
277 free_rangepoint(iter
);
278 init_rangepoint(iter
, node
, off
);
279 nsIDOMNode_Release(node
);
283 /* There are no more children in the node. Move to parent. */
284 nsres
= nsIDOMNode_GetParentNode(iter
->node
, &node
);
285 assert(nsres
== NS_OK
);
289 off
= get_child_index(node
, iter
->node
);
290 free_rangepoint(iter
);
291 init_rangepoint(iter
, node
, off
);
295 static void get_start_point(HTMLTxtRange
*This
, rangepoint_t
*ret
)
300 nsIDOMRange_GetStartContainer(This
->nsrange
, &node
);
301 nsIDOMRange_GetStartOffset(This
->nsrange
, &off
);
303 init_rangepoint(ret
, node
, off
);
305 nsIDOMNode_Release(node
);
308 static void get_end_point(HTMLTxtRange
*This
, rangepoint_t
*ret
)
313 nsIDOMRange_GetEndContainer(This
->nsrange
, &node
);
314 nsIDOMRange_GetEndOffset(This
->nsrange
, &off
);
316 init_rangepoint(ret
, node
, off
);
318 nsIDOMNode_Release(node
);
321 static void set_start_point(HTMLTxtRange
*This
, const rangepoint_t
*start
)
323 nsresult nsres
= nsIDOMRange_SetStart(This
->nsrange
, start
->node
, start
->off
);
325 ERR("failed: %08x\n", nsres
);
328 static void set_end_point(HTMLTxtRange
*This
, const rangepoint_t
*end
)
330 nsresult nsres
= nsIDOMRange_SetEnd(This
->nsrange
, end
->node
, end
->off
);
332 ERR("failed: %08x\n", nsres
);
335 static BOOL
is_elem_tag(nsIDOMNode
*node
, LPCWSTR istag
)
339 const PRUnichar
*tag
;
343 nsres
= nsIDOMNode_QueryInterface(node
, &IID_nsIDOMElement
, (void**)&elem
);
347 nsAString_Init(&tag_str
, NULL
);
348 nsIDOMElement_GetTagName(elem
, &tag_str
);
349 nsIDOMElement_Release(elem
);
350 nsAString_GetData(&tag_str
, &tag
);
352 ret
= !strcmpiW(tag
, istag
);
354 nsAString_Finish(&tag_str
);
359 static inline BOOL
wstrbuf_init(wstrbuf_t
*buf
)
363 buf
->buf
= heap_alloc(buf
->size
* sizeof(WCHAR
));
364 if (!buf
->buf
) return FALSE
;
369 static inline void wstrbuf_finish(wstrbuf_t
*buf
)
374 static void wstrbuf_append_len(wstrbuf_t
*buf
, LPCWSTR str
, int len
)
376 if(buf
->len
+len
>= buf
->size
) {
377 buf
->size
= 2*buf
->size
+len
;
378 buf
->buf
= heap_realloc(buf
->buf
, buf
->size
* sizeof(WCHAR
));
381 memcpy(buf
->buf
+buf
->len
, str
, len
*sizeof(WCHAR
));
383 buf
->buf
[buf
->len
] = 0;
386 static void wstrbuf_append_nodetxt(wstrbuf_t
*buf
, LPCWSTR str
, int len
)
388 const WCHAR
*s
= str
;
391 TRACE("%s\n", debugstr_wn(str
, len
));
393 if(buf
->len
+len
>= buf
->size
) {
394 buf
->size
= 2*buf
->size
+len
;
395 buf
->buf
= heap_realloc(buf
->buf
, buf
->size
* sizeof(WCHAR
));
398 if(buf
->len
&& isspaceW(buf
->buf
[buf
->len
-1])) {
399 while(s
< str
+len
&& isspaceW(*s
))
403 d
= buf
->buf
+buf
->len
;
408 while(s
< str
+len
&& isspaceW(*s
))
415 buf
->len
= d
- buf
->buf
;
419 static void wstrbuf_append_node(wstrbuf_t
*buf
, nsIDOMNode
*node
, BOOL ignore_text
)
422 switch(get_node_type(node
)) {
426 const PRUnichar
*data
;
431 nsIDOMNode_QueryInterface(node
, &IID_nsIDOMText
, (void**)&nstext
);
433 nsAString_Init(&data_str
, NULL
);
434 nsIDOMText_GetData(nstext
, &data_str
);
435 nsAString_GetData(&data_str
, &data
);
436 wstrbuf_append_nodetxt(buf
, data
, strlenW(data
));
437 nsAString_Finish(&data_str
);
439 nsIDOMText_Release(nstext
);
444 if(is_elem_tag(node
, brW
)) {
445 static const WCHAR endlW
[] = {'\r','\n'};
446 wstrbuf_append_len(buf
, endlW
, 2);
447 }else if(is_elem_tag(node
, hrW
)) {
448 static const WCHAR endl2W
[] = {'\r','\n','\r','\n'};
449 wstrbuf_append_len(buf
, endl2W
, 4);
454 static void wstrbuf_append_node_rec(wstrbuf_t
*buf
, nsIDOMNode
*node
)
456 nsIDOMNode
*iter
, *tmp
;
458 wstrbuf_append_node(buf
, node
, FALSE
);
460 nsIDOMNode_GetFirstChild(node
, &iter
);
462 wstrbuf_append_node_rec(buf
, iter
);
463 nsIDOMNode_GetNextSibling(iter
, &tmp
);
464 nsIDOMNode_Release(iter
);
469 static void range_to_string(HTMLTxtRange
*This
, wstrbuf_t
*buf
)
471 rangepoint_t end_pos
, iter
;
474 nsIDOMRange_GetCollapsed(This
->nsrange
, &collapsed
);
482 get_end_point(This
, &end_pos
);
483 get_start_point(This
, &iter
);
486 if(iter
.type
== TEXT_NODE
) {
487 const PRUnichar
*str
;
490 get_text_node_data(iter
.node
, &nsstr
, &str
);
492 if(iter
.node
== end_pos
.node
) {
493 wstrbuf_append_nodetxt(buf
, str
+iter
.off
, end_pos
.off
-iter
.off
);
494 nsAString_Finish(&nsstr
);
498 wstrbuf_append_nodetxt(buf
, str
+iter
.off
, strlenW(str
+iter
.off
));
499 nsAString_Finish(&nsstr
);
503 node
= get_child_node(iter
.node
, iter
.off
);
505 wstrbuf_append_node(buf
, node
, TRUE
);
506 nsIDOMNode_Release(node
);
510 if(!rangepoint_next_node(&iter
)) {
511 ERR("End of document?\n");
514 }while(!rangepoint_cmp(&iter
, &end_pos
));
516 free_rangepoint(&iter
);
517 free_rangepoint(&end_pos
);
522 for(p
= buf
->buf
+buf
->len
-1; p
>= buf
->buf
&& isspaceW(*p
); p
--);
524 p
= strchrW(p
, '\r');
530 HRESULT
get_node_text(HTMLDOMNode
*node
, BSTR
*ret
)
535 if (!wstrbuf_init(&buf
))
536 return E_OUTOFMEMORY
;
537 wstrbuf_append_node_rec(&buf
, node
->nsnode
);
538 if(buf
.buf
&& *buf
.buf
) {
539 *ret
= SysAllocString(buf
.buf
);
541 hres
= E_OUTOFMEMORY
;
545 wstrbuf_finish(&buf
);
548 TRACE("ret %s\n", debugstr_w(*ret
));
552 static WCHAR
move_next_char(rangepoint_t
*iter
)
554 rangepoint_t last_space
;
562 const PRUnichar
*str
;
566 get_text_node_data(iter
->node
, &nsstr
, &str
);
569 nsAString_Finish(&nsstr
);
579 free_rangepoint(&last_space
);
585 nsAString_Finish(&nsstr
);
586 if(!c
) { /* continue to skip spaces */
587 init_rangepoint(&last_space
, iter
->node
, iter
->off
);
593 nsAString_Finish(&nsstr
);
596 /* If we have a non-space char and we're skipping spaces, stop and return the last found space. */
598 free_rangepoint(iter
);
607 node
= get_child_node(iter
->node
, iter
->off
);
611 if(is_elem_tag(node
, brW
)) {
613 nsIDOMNode_Release(node
);
614 free_rangepoint(iter
);
620 init_rangepoint(&last_space
, iter
->node
, iter
->off
+1);
621 }else if(is_elem_tag(node
, hrW
)) {
622 nsIDOMNode_Release(node
);
624 free_rangepoint(iter
);
633 nsIDOMNode_Release(node
);
635 }while(rangepoint_next_node(iter
));
640 static WCHAR
move_prev_char(rangepoint_t
*iter
)
642 rangepoint_t last_space
;
650 const PRUnichar
*str
;
657 get_text_node_data(iter
->node
, &nsstr
, &str
);
663 while(p
> str
&& isspaceW(*(p
-1)))
667 free_rangepoint(&last_space
);
672 nsAString_Finish(&nsstr
);
673 if(p
== str
) { /* continue to skip spaces */
674 init_rangepoint(&last_space
, iter
->node
, iter
->off
);
680 nsAString_Finish(&nsstr
);
683 /* If we have a non-space char and we're skipping spaces, stop and return the last found space. */
685 free_rangepoint(iter
);
697 node
= get_child_node(iter
->node
, iter
->off
-1);
701 if(is_elem_tag(node
, brW
)) {
703 free_rangepoint(&last_space
);
705 init_rangepoint(&last_space
, iter
->node
, iter
->off
-1);
706 }else if(is_elem_tag(node
, hrW
)) {
707 nsIDOMNode_Release(node
);
709 free_rangepoint(iter
);
718 nsIDOMNode_Release(node
);
720 }while(rangepoint_prev_node(iter
));
723 free_rangepoint(iter
);
731 static LONG
move_by_chars(rangepoint_t
*iter
, LONG cnt
)
736 while(ret
< cnt
&& move_next_char(iter
))
739 while(ret
> cnt
&& move_prev_char(iter
))
746 static LONG
find_prev_space(rangepoint_t
*iter
, BOOL first_space
)
751 init_rangepoint(&prev
, iter
->node
, iter
->off
);
752 c
= move_prev_char(&prev
);
753 if(!c
|| (first_space
&& isspaceW(c
)))
757 free_rangepoint(iter
);
758 init_rangepoint(iter
, prev
.node
, prev
.off
);
759 c
= move_prev_char(&prev
);
760 }while(c
&& !isspaceW(c
));
762 free_rangepoint(&prev
);
766 static BOOL
find_word_end(rangepoint_t
*iter
, BOOL is_collapsed
)
768 rangepoint_t prev_iter
;
773 init_rangepoint(&prev_iter
, iter
->node
, iter
->off
);
774 c
= move_prev_char(&prev_iter
);
775 free_rangepoint(&prev_iter
);
781 init_rangepoint(&prev_iter
, iter
->node
, iter
->off
);
782 c
= move_next_char(iter
);
784 free_rangepoint(iter
);
790 ret
= !rangepoint_cmp(iter
, &prev_iter
);
794 free_rangepoint(&prev_iter
);
795 }while(c
&& !isspaceW(c
));
800 static LONG
move_by_words(rangepoint_t
*iter
, LONG cnt
)
807 while(ret
< cnt
&& (c
= move_next_char(iter
))) {
812 while(ret
> cnt
&& find_prev_space(iter
, FALSE
))
819 static inline HTMLTxtRange
*impl_from_IHTMLTxtRange(IHTMLTxtRange
*iface
)
821 return CONTAINING_RECORD(iface
, HTMLTxtRange
, IHTMLTxtRange_iface
);
824 static HRESULT WINAPI
HTMLTxtRange_QueryInterface(IHTMLTxtRange
*iface
, REFIID riid
, void **ppv
)
826 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
828 TRACE("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
830 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
831 *ppv
= &This
->IHTMLTxtRange_iface
;
832 }else if(IsEqualGUID(&IID_IHTMLTxtRange
, riid
)) {
833 *ppv
= &This
->IHTMLTxtRange_iface
;
834 }else if(IsEqualGUID(&IID_IOleCommandTarget
, riid
)) {
835 *ppv
= &This
->IOleCommandTarget_iface
;
836 }else if(dispex_query_interface(&This
->dispex
, riid
, ppv
)) {
837 return *ppv
? S_OK
: E_NOINTERFACE
;
840 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
841 return E_NOINTERFACE
;
844 IUnknown_AddRef((IUnknown
*)*ppv
);
848 static ULONG WINAPI
HTMLTxtRange_AddRef(IHTMLTxtRange
*iface
)
850 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
851 LONG ref
= InterlockedIncrement(&This
->ref
);
853 TRACE("(%p) ref=%d\n", This
, ref
);
858 static ULONG WINAPI
HTMLTxtRange_Release(IHTMLTxtRange
*iface
)
860 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
861 LONG ref
= InterlockedDecrement(&This
->ref
);
863 TRACE("(%p) ref=%d\n", This
, ref
);
867 nsIDOMRange_Release(This
->nsrange
);
869 list_remove(&This
->entry
);
870 release_dispex(&This
->dispex
);
877 static HRESULT WINAPI
HTMLTxtRange_GetTypeInfoCount(IHTMLTxtRange
*iface
, UINT
*pctinfo
)
879 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
881 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
884 static HRESULT WINAPI
HTMLTxtRange_GetTypeInfo(IHTMLTxtRange
*iface
, UINT iTInfo
,
885 LCID lcid
, ITypeInfo
**ppTInfo
)
887 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
889 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
892 static HRESULT WINAPI
HTMLTxtRange_GetIDsOfNames(IHTMLTxtRange
*iface
, REFIID riid
,
893 LPOLESTR
*rgszNames
, UINT cNames
,
894 LCID lcid
, DISPID
*rgDispId
)
896 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
898 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
, riid
, rgszNames
,
899 cNames
, lcid
, rgDispId
);
902 static HRESULT WINAPI
HTMLTxtRange_Invoke(IHTMLTxtRange
*iface
, DISPID dispIdMember
,
903 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
904 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
906 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
908 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
, dispIdMember
, riid
,
909 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
912 static HRESULT WINAPI
HTMLTxtRange_get_htmlText(IHTMLTxtRange
*iface
, BSTR
*p
)
914 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
916 TRACE("(%p)->(%p)\n", This
, p
);
921 nsIDOMDocumentFragment
*fragment
;
924 nsres
= nsIDOMRange_CloneContents(This
->nsrange
, &fragment
);
925 if(NS_SUCCEEDED(nsres
)) {
926 const PRUnichar
*nstext
;
929 nsAString_Init(&nsstr
, NULL
);
930 nsnode_to_nsstring((nsIDOMNode
*)fragment
, &nsstr
);
931 nsIDOMDocumentFragment_Release(fragment
);
933 nsAString_GetData(&nsstr
, &nstext
);
934 *p
= SysAllocString(nstext
);
936 nsAString_Finish(&nsstr
);
941 const WCHAR emptyW
[] = {0};
942 *p
= SysAllocString(emptyW
);
945 TRACE("return %s\n", debugstr_w(*p
));
949 static HRESULT WINAPI
HTMLTxtRange_put_text(IHTMLTxtRange
*iface
, BSTR v
)
951 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
952 nsIDOMText
*text_node
;
956 TRACE("(%p)->(%s)\n", This
, debugstr_w(v
));
959 return MSHTML_E_NODOC
;
961 nsAString_InitDepend(&text_str
, v
);
962 nsres
= nsIDOMHTMLDocument_CreateTextNode(This
->doc
->nsdoc
, &text_str
, &text_node
);
963 nsAString_Finish(&text_str
);
964 if(NS_FAILED(nsres
)) {
965 ERR("CreateTextNode failed: %08x\n", nsres
);
968 nsres
= nsIDOMRange_DeleteContents(This
->nsrange
);
970 ERR("DeleteContents failed: %08x\n", nsres
);
972 nsres
= nsIDOMRange_InsertNode(This
->nsrange
, (nsIDOMNode
*)text_node
);
974 ERR("InsertNode failed: %08x\n", nsres
);
976 nsres
= nsIDOMRange_SetEndAfter(This
->nsrange
, (nsIDOMNode
*)text_node
);
978 ERR("SetEndAfter failed: %08x\n", nsres
);
980 return IHTMLTxtRange_collapse(&This
->IHTMLTxtRange_iface
, VARIANT_FALSE
);
983 static HRESULT WINAPI
HTMLTxtRange_get_text(IHTMLTxtRange
*iface
, BSTR
*p
)
985 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
988 TRACE("(%p)->(%p)\n", This
, p
);
994 if (!wstrbuf_init(&buf
))
995 return E_OUTOFMEMORY
;
996 range_to_string(This
, &buf
);
998 *p
= SysAllocString(buf
.buf
);
999 wstrbuf_finish(&buf
);
1001 TRACE("ret %s\n", debugstr_w(*p
));
1005 static HRESULT WINAPI
HTMLTxtRange_parentElement(IHTMLTxtRange
*iface
, IHTMLElement
**parent
)
1007 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1008 nsIDOMNode
*nsnode
, *tmp
;
1012 TRACE("(%p)->(%p)\n", This
, parent
);
1014 nsIDOMRange_GetCommonAncestorContainer(This
->nsrange
, &nsnode
);
1015 while(nsnode
&& get_node_type(nsnode
) != ELEMENT_NODE
) {
1016 nsIDOMNode_GetParentNode(nsnode
, &tmp
);
1017 nsIDOMNode_Release(nsnode
);
1026 hres
= get_node(nsnode
, TRUE
, &node
);
1027 nsIDOMNode_Release(nsnode
);
1031 hres
= IHTMLDOMNode_QueryInterface(&node
->IHTMLDOMNode_iface
, &IID_IHTMLElement
, (void**)parent
);
1036 static HRESULT WINAPI
HTMLTxtRange_duplicate(IHTMLTxtRange
*iface
, IHTMLTxtRange
**Duplicate
)
1038 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1039 nsIDOMRange
*nsrange
= NULL
;
1042 TRACE("(%p)->(%p)\n", This
, Duplicate
);
1044 nsIDOMRange_CloneRange(This
->nsrange
, &nsrange
);
1045 hres
= HTMLTxtRange_Create(This
->doc
, nsrange
, Duplicate
);
1046 nsIDOMRange_Release(nsrange
);
1051 static HRESULT WINAPI
HTMLTxtRange_inRange(IHTMLTxtRange
*iface
, IHTMLTxtRange
*Range
,
1052 VARIANT_BOOL
*InRange
)
1054 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1055 HTMLTxtRange
*src_range
;
1059 TRACE("(%p)->(%p %p)\n", This
, Range
, InRange
);
1061 *InRange
= VARIANT_FALSE
;
1063 src_range
= get_range_object(This
->doc
, Range
);
1067 nsres
= nsIDOMRange_CompareBoundaryPoints(This
->nsrange
, NS_START_TO_START
,
1068 src_range
->nsrange
, &nsret
);
1069 if(NS_SUCCEEDED(nsres
) && nsret
<= 0) {
1070 nsres
= nsIDOMRange_CompareBoundaryPoints(This
->nsrange
, NS_END_TO_END
,
1071 src_range
->nsrange
, &nsret
);
1072 if(NS_SUCCEEDED(nsres
) && nsret
>= 0)
1073 *InRange
= VARIANT_TRUE
;
1076 if(NS_FAILED(nsres
))
1077 ERR("CompareBoundaryPoints failed: %08x\n", nsres
);
1082 static HRESULT WINAPI
HTMLTxtRange_isEqual(IHTMLTxtRange
*iface
, IHTMLTxtRange
*Range
,
1083 VARIANT_BOOL
*IsEqual
)
1085 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1086 HTMLTxtRange
*src_range
;
1090 TRACE("(%p)->(%p %p)\n", This
, Range
, IsEqual
);
1092 *IsEqual
= VARIANT_FALSE
;
1094 src_range
= get_range_object(This
->doc
, Range
);
1098 nsres
= nsIDOMRange_CompareBoundaryPoints(This
->nsrange
, NS_START_TO_START
,
1099 src_range
->nsrange
, &nsret
);
1100 if(NS_SUCCEEDED(nsres
) && !nsret
) {
1101 nsres
= nsIDOMRange_CompareBoundaryPoints(This
->nsrange
, NS_END_TO_END
,
1102 src_range
->nsrange
, &nsret
);
1103 if(NS_SUCCEEDED(nsres
) && !nsret
)
1104 *IsEqual
= VARIANT_TRUE
;
1107 if(NS_FAILED(nsres
))
1108 ERR("CompareBoundaryPoints failed: %08x\n", nsres
);
1113 static HRESULT WINAPI
HTMLTxtRange_scrollIntoView(IHTMLTxtRange
*iface
, VARIANT_BOOL fStart
)
1115 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1116 FIXME("(%p)->(%x)\n", This
, fStart
);
1120 static HRESULT WINAPI
HTMLTxtRange_collapse(IHTMLTxtRange
*iface
, VARIANT_BOOL Start
)
1122 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1124 TRACE("(%p)->(%x)\n", This
, Start
);
1126 nsIDOMRange_Collapse(This
->nsrange
, Start
!= VARIANT_FALSE
);
1130 static HRESULT WINAPI
HTMLTxtRange_expand(IHTMLTxtRange
*iface
, BSTR Unit
, VARIANT_BOOL
*Success
)
1132 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1135 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(Unit
), Success
);
1137 unit
= string_to_unit(Unit
);
1138 if(unit
== RU_UNKNOWN
)
1139 return E_INVALIDARG
;
1141 *Success
= VARIANT_FALSE
;
1145 rangepoint_t end
, start
;
1146 cpp_bool is_collapsed
;
1148 get_start_point(This
, &start
);
1149 get_end_point(This
, &end
);
1151 nsIDOMRange_GetCollapsed(This
->nsrange
, &is_collapsed
);
1153 if(find_word_end(&end
, is_collapsed
)) {
1154 set_end_point(This
, &end
);
1155 *Success
= VARIANT_TRUE
;
1158 if(find_prev_space(&start
, TRUE
)) {
1159 set_start_point(This
, &start
);
1160 *Success
= VARIANT_TRUE
;
1163 free_rangepoint(&end
);
1164 free_rangepoint(&start
);
1169 nsIDOMHTMLElement
*nsbody
= NULL
;
1172 nsres
= nsIDOMHTMLDocument_GetBody(This
->doc
->nsdoc
, &nsbody
);
1173 if(NS_FAILED(nsres
) || !nsbody
) {
1174 ERR("Could not get body: %08x\n", nsres
);
1178 nsres
= nsIDOMRange_SelectNodeContents(This
->nsrange
, (nsIDOMNode
*)nsbody
);
1179 nsIDOMHTMLElement_Release(nsbody
);
1180 if(NS_FAILED(nsres
)) {
1181 ERR("Collapse failed: %08x\n", nsres
);
1185 *Success
= VARIANT_TRUE
;
1190 FIXME("Unimplemented unit %s\n", debugstr_w(Unit
));
1196 static HRESULT WINAPI
HTMLTxtRange_move(IHTMLTxtRange
*iface
, BSTR Unit
,
1197 LONG Count
, LONG
*ActualCount
)
1199 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1202 TRACE("(%p)->(%s %d %p)\n", This
, debugstr_w(Unit
), Count
, ActualCount
);
1204 unit
= string_to_unit(Unit
);
1205 if(unit
== RU_UNKNOWN
)
1206 return E_INVALIDARG
;
1210 return IHTMLTxtRange_collapse(&This
->IHTMLTxtRange_iface
, VARIANT_TRUE
);
1217 get_start_point(This
, &start
);
1219 *ActualCount
= move_by_chars(&start
, Count
);
1221 set_start_point(This
, &start
);
1222 IHTMLTxtRange_collapse(&This
->IHTMLTxtRange_iface
, VARIANT_TRUE
);
1223 free_rangepoint(&start
);
1230 get_start_point(This
, &start
);
1232 *ActualCount
= move_by_words(&start
, Count
);
1234 set_start_point(This
, &start
);
1235 IHTMLTxtRange_collapse(&This
->IHTMLTxtRange_iface
, VARIANT_TRUE
);
1236 free_rangepoint(&start
);
1241 FIXME("unimplemented unit %s\n", debugstr_w(Unit
));
1244 TRACE("ret %d\n", *ActualCount
);
1248 static HRESULT WINAPI
HTMLTxtRange_moveStart(IHTMLTxtRange
*iface
, BSTR Unit
,
1249 LONG Count
, LONG
*ActualCount
)
1251 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1254 TRACE("(%p)->(%s %d %p)\n", This
, debugstr_w(Unit
), Count
, ActualCount
);
1256 unit
= string_to_unit(Unit
);
1257 if(unit
== RU_UNKNOWN
)
1258 return E_INVALIDARG
;
1269 get_start_point(This
, &start
);
1271 *ActualCount
= move_by_chars(&start
, Count
);
1273 set_start_point(This
, &start
);
1274 free_rangepoint(&start
);
1279 FIXME("unimplemented unit %s\n", debugstr_w(Unit
));
1286 static HRESULT WINAPI
HTMLTxtRange_moveEnd(IHTMLTxtRange
*iface
, BSTR Unit
,
1287 LONG Count
, LONG
*ActualCount
)
1289 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1292 TRACE("(%p)->(%s %d %p)\n", This
, debugstr_w(Unit
), Count
, ActualCount
);
1294 unit
= string_to_unit(Unit
);
1295 if(unit
== RU_UNKNOWN
)
1296 return E_INVALIDARG
;
1307 get_end_point(This
, &end
);
1309 *ActualCount
= move_by_chars(&end
, Count
);
1311 set_end_point(This
, &end
);
1312 free_rangepoint(&end
);
1317 FIXME("unimplemented unit %s\n", debugstr_w(Unit
));
1323 static HRESULT WINAPI
HTMLTxtRange_select(IHTMLTxtRange
*iface
)
1325 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1326 nsISelection
*nsselection
;
1329 TRACE("(%p)\n", This
);
1331 nsres
= nsIDOMWindow_GetSelection(This
->doc
->basedoc
.window
->nswindow
, &nsselection
);
1332 if(NS_FAILED(nsres
)) {
1333 ERR("GetSelection failed: %08x\n", nsres
);
1337 nsISelection_RemoveAllRanges(nsselection
);
1338 nsISelection_AddRange(nsselection
, This
->nsrange
);
1339 nsISelection_Release(nsselection
);
1343 static HRESULT WINAPI
HTMLTxtRange_pasteHTML(IHTMLTxtRange
*iface
, BSTR html
)
1345 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1346 nsIDOMDocumentFragment
*doc_frag
;
1350 TRACE("(%p)->(%s)\n", This
, debugstr_w(html
));
1352 nsres
= nsIDOMRange_Collapse(This
->nsrange
, TRUE
);
1353 assert(nsres
== NS_OK
);
1355 nsAString_InitDepend(&nsstr
, html
);
1356 nsres
= nsIDOMRange_CreateContextualFragment(This
->nsrange
, &nsstr
, &doc_frag
);
1357 nsAString_Finish(&nsstr
);
1358 if(NS_FAILED(nsres
)) {
1359 ERR("CreateContextualFragment failed: %08x\n", nsres
);
1363 nsres
= nsIDOMRange_InsertNode(This
->nsrange
, (nsIDOMNode
*)doc_frag
);
1364 nsIDOMDocumentFragment_Release(doc_frag
);
1365 if(NS_FAILED(nsres
)) {
1366 ERR("InsertNode failed: %08x\n", nsres
);
1370 nsres
= nsIDOMRange_Collapse(This
->nsrange
, FALSE
);
1371 assert(nsres
== NS_OK
);
1375 static HRESULT WINAPI
HTMLTxtRange_moveToElementText(IHTMLTxtRange
*iface
, IHTMLElement
*element
)
1377 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1381 TRACE("(%p)->(%p)\n", This
, element
);
1383 elem
= unsafe_impl_from_IHTMLElement(element
);
1385 return E_INVALIDARG
;
1387 nsres
= nsIDOMRange_SelectNodeContents(This
->nsrange
, elem
->node
.nsnode
);
1388 if(NS_FAILED(nsres
)) {
1389 ERR("SelectNodeContents failed: %08x\n", nsres
);
1396 static HRESULT WINAPI
HTMLTxtRange_setEndPoint(IHTMLTxtRange
*iface
, BSTR how
,
1397 IHTMLTxtRange
*SourceRange
)
1399 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1400 HTMLTxtRange
*src_range
;
1401 nsIDOMNode
*ref_node
;
1408 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(how
), SourceRange
);
1410 how_type
= string_to_nscmptype(how
);
1412 return E_INVALIDARG
;
1414 src_range
= get_range_object(This
->doc
, SourceRange
);
1419 case NS_START_TO_START
:
1420 case NS_END_TO_START
:
1421 nsres
= nsIDOMRange_GetStartContainer(src_range
->nsrange
, &ref_node
);
1422 assert(nsres
== NS_OK
);
1424 nsres
= nsIDOMRange_GetStartOffset(src_range
->nsrange
, &ref_offset
);
1425 assert(nsres
== NS_OK
);
1427 set_start
= how_type
== NS_START_TO_START
;
1430 case NS_START_TO_END
:
1431 nsres
= nsIDOMRange_GetEndContainer(src_range
->nsrange
, &ref_node
);
1432 assert(nsres
== NS_OK
);
1434 nsres
= nsIDOMRange_GetEndOffset(src_range
->nsrange
, &ref_offset
);
1435 assert(nsres
== NS_OK
);
1437 set_start
= how_type
== NS_START_TO_END
;
1439 DEFAULT_UNREACHABLE
;
1442 nsres
= nsIDOMRange_ComparePoint(This
->nsrange
, ref_node
, ref_offset
, &cmp
);
1443 assert(nsres
== NS_OK
);
1447 nsres
= nsIDOMRange_SetStart(This
->nsrange
, ref_node
, ref_offset
);
1449 nsres
= nsIDOMRange_Collapse(This
->nsrange
, FALSE
);
1450 assert(nsres
== NS_OK
);
1452 nsres
= nsIDOMRange_SetEnd(This
->nsrange
, ref_node
, ref_offset
);
1456 nsres
= nsIDOMRange_SetEnd(This
->nsrange
, ref_node
, ref_offset
);
1458 nsres
= nsIDOMRange_Collapse(This
->nsrange
, TRUE
);
1459 assert(nsres
== NS_OK
);
1461 nsres
= nsIDOMRange_SetStart(This
->nsrange
, ref_node
, ref_offset
);
1464 assert(nsres
== NS_OK
);
1466 nsIDOMNode_Release(ref_node
);
1470 static HRESULT WINAPI
HTMLTxtRange_compareEndPoints(IHTMLTxtRange
*iface
, BSTR how
,
1471 IHTMLTxtRange
*SourceRange
, LONG
*ret
)
1473 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1474 HTMLTxtRange
*src_range
;
1479 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_w(how
), SourceRange
, ret
);
1481 nscmpt
= string_to_nscmptype(how
);
1483 return E_INVALIDARG
;
1485 src_range
= get_range_object(This
->doc
, SourceRange
);
1489 nsres
= nsIDOMRange_CompareBoundaryPoints(This
->nsrange
, nscmpt
, src_range
->nsrange
, &nsret
);
1490 if(NS_FAILED(nsres
))
1491 ERR("CompareBoundaryPoints failed: %08x\n", nsres
);
1497 static HRESULT WINAPI
HTMLTxtRange_findText(IHTMLTxtRange
*iface
, BSTR String
,
1498 LONG count
, LONG Flags
, VARIANT_BOOL
*Success
)
1500 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1501 FIXME("(%p)->(%s %d %08x %p)\n", This
, debugstr_w(String
), count
, Flags
, Success
);
1505 static HRESULT WINAPI
HTMLTxtRange_moveToPoint(IHTMLTxtRange
*iface
, LONG x
, LONG y
)
1507 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1508 FIXME("(%p)->(%d %d)\n", This
, x
, y
);
1512 static HRESULT WINAPI
HTMLTxtRange_getBookmark(IHTMLTxtRange
*iface
, BSTR
*Bookmark
)
1514 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1515 FIXME("(%p)->(%p)\n", This
, Bookmark
);
1519 static HRESULT WINAPI
HTMLTxtRange_moveToBookmark(IHTMLTxtRange
*iface
, BSTR Bookmark
,
1520 VARIANT_BOOL
*Success
)
1522 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1523 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(Bookmark
), Success
);
1527 static HRESULT WINAPI
HTMLTxtRange_queryCommandSupported(IHTMLTxtRange
*iface
, BSTR cmdID
,
1528 VARIANT_BOOL
*pfRet
)
1530 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1531 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(cmdID
), pfRet
);
1535 static HRESULT WINAPI
HTMLTxtRange_queryCommandEnabled(IHTMLTxtRange
*iface
, BSTR cmdID
,
1536 VARIANT_BOOL
*pfRet
)
1538 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1539 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(cmdID
), pfRet
);
1543 static HRESULT WINAPI
HTMLTxtRange_queryCommandState(IHTMLTxtRange
*iface
, BSTR cmdID
,
1544 VARIANT_BOOL
*pfRet
)
1546 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1547 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(cmdID
), pfRet
);
1551 static HRESULT WINAPI
HTMLTxtRange_queryCommandIndeterm(IHTMLTxtRange
*iface
, BSTR cmdID
,
1552 VARIANT_BOOL
*pfRet
)
1554 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1555 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(cmdID
), pfRet
);
1559 static HRESULT WINAPI
HTMLTxtRange_queryCommandText(IHTMLTxtRange
*iface
, BSTR cmdID
,
1562 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1563 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(cmdID
), pcmdText
);
1567 static HRESULT WINAPI
HTMLTxtRange_queryCommandValue(IHTMLTxtRange
*iface
, BSTR cmdID
,
1570 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1571 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(cmdID
), pcmdValue
);
1575 static HRESULT WINAPI
HTMLTxtRange_execCommand(IHTMLTxtRange
*iface
, BSTR cmdID
,
1576 VARIANT_BOOL showUI
, VARIANT value
, VARIANT_BOOL
*pfRet
)
1578 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1579 FIXME("(%p)->(%s %x v %p)\n", This
, debugstr_w(cmdID
), showUI
, pfRet
);
1583 static HRESULT WINAPI
HTMLTxtRange_execCommandShowHelp(IHTMLTxtRange
*iface
, BSTR cmdID
,
1584 VARIANT_BOOL
*pfRet
)
1586 HTMLTxtRange
*This
= impl_from_IHTMLTxtRange(iface
);
1587 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(cmdID
), pfRet
);
1591 static const IHTMLTxtRangeVtbl HTMLTxtRangeVtbl
= {
1592 HTMLTxtRange_QueryInterface
,
1593 HTMLTxtRange_AddRef
,
1594 HTMLTxtRange_Release
,
1595 HTMLTxtRange_GetTypeInfoCount
,
1596 HTMLTxtRange_GetTypeInfo
,
1597 HTMLTxtRange_GetIDsOfNames
,
1598 HTMLTxtRange_Invoke
,
1599 HTMLTxtRange_get_htmlText
,
1600 HTMLTxtRange_put_text
,
1601 HTMLTxtRange_get_text
,
1602 HTMLTxtRange_parentElement
,
1603 HTMLTxtRange_duplicate
,
1604 HTMLTxtRange_inRange
,
1605 HTMLTxtRange_isEqual
,
1606 HTMLTxtRange_scrollIntoView
,
1607 HTMLTxtRange_collapse
,
1608 HTMLTxtRange_expand
,
1610 HTMLTxtRange_moveStart
,
1611 HTMLTxtRange_moveEnd
,
1612 HTMLTxtRange_select
,
1613 HTMLTxtRange_pasteHTML
,
1614 HTMLTxtRange_moveToElementText
,
1615 HTMLTxtRange_setEndPoint
,
1616 HTMLTxtRange_compareEndPoints
,
1617 HTMLTxtRange_findText
,
1618 HTMLTxtRange_moveToPoint
,
1619 HTMLTxtRange_getBookmark
,
1620 HTMLTxtRange_moveToBookmark
,
1621 HTMLTxtRange_queryCommandSupported
,
1622 HTMLTxtRange_queryCommandEnabled
,
1623 HTMLTxtRange_queryCommandState
,
1624 HTMLTxtRange_queryCommandIndeterm
,
1625 HTMLTxtRange_queryCommandText
,
1626 HTMLTxtRange_queryCommandValue
,
1627 HTMLTxtRange_execCommand
,
1628 HTMLTxtRange_execCommandShowHelp
1631 static inline HTMLTxtRange
*impl_from_IOleCommandTarget(IOleCommandTarget
*iface
)
1633 return CONTAINING_RECORD(iface
, HTMLTxtRange
, IOleCommandTarget_iface
);
1636 static HRESULT WINAPI
RangeCommandTarget_QueryInterface(IOleCommandTarget
*iface
, REFIID riid
, void **ppv
)
1638 HTMLTxtRange
*This
= impl_from_IOleCommandTarget(iface
);
1639 return IHTMLTxtRange_QueryInterface(&This
->IHTMLTxtRange_iface
, riid
, ppv
);
1642 static ULONG WINAPI
RangeCommandTarget_AddRef(IOleCommandTarget
*iface
)
1644 HTMLTxtRange
*This
= impl_from_IOleCommandTarget(iface
);
1645 return IHTMLTxtRange_AddRef(&This
->IHTMLTxtRange_iface
);
1648 static ULONG WINAPI
RangeCommandTarget_Release(IOleCommandTarget
*iface
)
1650 HTMLTxtRange
*This
= impl_from_IOleCommandTarget(iface
);
1651 return IHTMLTxtRange_Release(&This
->IHTMLTxtRange_iface
);
1654 static HRESULT WINAPI
RangeCommandTarget_QueryStatus(IOleCommandTarget
*iface
, const GUID
*pguidCmdGroup
,
1655 ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)
1657 HTMLTxtRange
*This
= impl_from_IOleCommandTarget(iface
);
1658 FIXME("(%p)->(%s %d %p %p)\n", This
, debugstr_guid(pguidCmdGroup
), cCmds
, prgCmds
, pCmdText
);
1662 static HRESULT
exec_indent(HTMLTxtRange
*This
, VARIANT
*in
, VARIANT
*out
)
1664 nsIDOMElement
*blockquote_elem
, *p_elem
;
1665 nsIDOMDocumentFragment
*fragment
;
1668 static const PRUnichar blockquoteW
[] = {'B','L','O','C','K','Q','U','O','T','E',0};
1669 static const PRUnichar pW
[] = {'P',0};
1671 TRACE("(%p)->(%p %p)\n", This
, in
, out
);
1673 if(!This
->doc
->nsdoc
) {
1674 WARN("NULL nsdoc\n");
1678 create_nselem(This
->doc
, blockquoteW
, &blockquote_elem
);
1679 create_nselem(This
->doc
, pW
, &p_elem
);
1681 nsIDOMRange_ExtractContents(This
->nsrange
, &fragment
);
1682 nsIDOMElement_AppendChild(p_elem
, (nsIDOMNode
*)fragment
, &tmp
);
1683 nsIDOMDocumentFragment_Release(fragment
);
1684 nsIDOMNode_Release(tmp
);
1686 nsIDOMElement_AppendChild(blockquote_elem
, (nsIDOMNode
*)p_elem
, &tmp
);
1687 nsIDOMElement_Release(p_elem
);
1688 nsIDOMNode_Release(tmp
);
1690 nsIDOMRange_InsertNode(This
->nsrange
, (nsIDOMNode
*)blockquote_elem
);
1691 nsIDOMElement_Release(blockquote_elem
);
1696 static HRESULT WINAPI
RangeCommandTarget_Exec(IOleCommandTarget
*iface
, const GUID
*pguidCmdGroup
,
1697 DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
)
1699 HTMLTxtRange
*This
= impl_from_IOleCommandTarget(iface
);
1701 TRACE("(%p)->(%s %d %x %p %p)\n", This
, debugstr_guid(pguidCmdGroup
), nCmdID
,
1702 nCmdexecopt
, pvaIn
, pvaOut
);
1704 if(pguidCmdGroup
&& IsEqualGUID(&CGID_MSHTML
, pguidCmdGroup
)) {
1707 return exec_indent(This
, pvaIn
, pvaOut
);
1709 FIXME("Unsupported cmdid %d of CGID_MSHTML\n", nCmdID
);
1712 FIXME("Unsupported cmd %d of group %s\n", nCmdID
, debugstr_guid(pguidCmdGroup
));
1718 static const IOleCommandTargetVtbl OleCommandTargetVtbl
= {
1719 RangeCommandTarget_QueryInterface
,
1720 RangeCommandTarget_AddRef
,
1721 RangeCommandTarget_Release
,
1722 RangeCommandTarget_QueryStatus
,
1723 RangeCommandTarget_Exec
1726 static const tid_t HTMLTxtRange_iface_tids
[] = {
1730 static dispex_static_data_t HTMLTxtRange_dispex
= {
1733 HTMLTxtRange_iface_tids
1736 HRESULT
HTMLTxtRange_Create(HTMLDocumentNode
*doc
, nsIDOMRange
*nsrange
, IHTMLTxtRange
**p
)
1740 ret
= heap_alloc(sizeof(HTMLTxtRange
));
1742 return E_OUTOFMEMORY
;
1744 init_dispex(&ret
->dispex
, (IUnknown
*)&ret
->IHTMLTxtRange_iface
, &HTMLTxtRange_dispex
);
1746 ret
->IHTMLTxtRange_iface
.lpVtbl
= &HTMLTxtRangeVtbl
;
1747 ret
->IOleCommandTarget_iface
.lpVtbl
= &OleCommandTargetVtbl
;
1751 nsIDOMRange_AddRef(nsrange
);
1752 ret
->nsrange
= nsrange
;
1755 list_add_head(&doc
->range_list
, &ret
->entry
);
1757 *p
= &ret
->IHTMLTxtRange_iface
;
1761 void detach_ranges(HTMLDocumentNode
*This
)
1765 LIST_FOR_EACH_ENTRY(iter
, &This
->range_list
, HTMLTxtRange
, entry
) {