mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / mshtml / range.c
blob8c802ee9ede3ca6cf313b79a7c4e199bda6b34cf
1 /*
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
19 #include <stdarg.h>
20 #include <assert.h>
22 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "ole2.h"
28 #include "mshtmcid.h"
30 #include "wine/debug.h"
32 #include "mshtml_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
36 typedef struct {
37 DispatchEx dispex;
38 IHTMLTxtRange IHTMLTxtRange_iface;
39 IOleCommandTarget IOleCommandTarget_iface;
41 LONG ref;
43 nsIDOMRange *nsrange;
44 HTMLDocumentNode *doc;
46 struct list entry;
47 } HTMLTxtRange;
49 typedef struct {
50 DispatchEx dispex;
51 IHTMLDOMRange IHTMLDOMRange_iface;
53 LONG ref;
55 nsIDOMRange *nsrange;
56 } HTMLDOMRange;
58 typedef struct {
59 WCHAR *buf;
60 DWORD len;
61 DWORD size;
62 } wstrbuf_t;
64 typedef struct {
65 UINT16 type;
66 nsIDOMNode *node;
67 UINT32 off;
68 } rangepoint_t;
70 typedef enum {
71 RU_UNKNOWN,
72 RU_CHAR,
73 RU_WORD,
74 RU_SENTENCE,
75 RU_TEXTEDIT
76 } range_unit_t;
78 static HTMLTxtRange *get_range_object(HTMLDocumentNode *doc, IHTMLTxtRange *iface)
80 HTMLTxtRange *iter;
82 LIST_FOR_EACH_ENTRY(iter, &doc->range_list, HTMLTxtRange, entry) {
83 if(&iter->IHTMLTxtRange_iface == iface)
84 return iter;
87 ERR("Could not find range in document\n");
88 return NULL;
91 static range_unit_t string_to_unit(LPCWSTR str)
93 if(!wcsicmp(str, L"character")) return RU_CHAR;
94 if(!wcsicmp(str, L"word")) return RU_WORD;
95 if(!wcsicmp(str, L"sentence")) return RU_SENTENCE;
96 if(!wcsicmp(str, L"textedit")) return RU_TEXTEDIT;
98 return RU_UNKNOWN;
101 static int string_to_nscmptype(LPCWSTR str)
103 if(!wcsicmp(str, L"StartToEnd")) return NS_START_TO_END;
104 if(!wcsicmp(str, L"StartToStart")) return NS_START_TO_START;
105 if(!wcsicmp(str, L"EndToStart")) return NS_END_TO_START;
106 if(!wcsicmp(str, L"EndToEnd")) return NS_END_TO_END;
108 return -1;
111 static UINT16 get_node_type(nsIDOMNode *node)
113 UINT16 type = 0;
115 if(node)
116 nsIDOMNode_GetNodeType(node, &type);
118 return type;
121 static void get_text_node_data(nsIDOMNode *node, nsAString *nsstr, const PRUnichar **str)
123 nsIDOMText *nstext;
124 nsresult nsres;
126 nsres = nsIDOMNode_QueryInterface(node, &IID_nsIDOMText, (void**)&nstext);
127 assert(nsres == NS_OK);
129 nsAString_Init(nsstr, NULL);
130 nsres = nsIDOMText_GetData(nstext, nsstr);
131 nsIDOMText_Release(nstext);
132 if(NS_FAILED(nsres))
133 ERR("GetData failed: %08x\n", nsres);
135 nsAString_GetData(nsstr, str);
138 static nsIDOMNode *get_child_node(nsIDOMNode *node, UINT32 off)
140 nsIDOMNodeList *node_list;
141 nsIDOMNode *ret = NULL;
143 nsIDOMNode_GetChildNodes(node, &node_list);
144 nsIDOMNodeList_Item(node_list, off, &ret);
145 nsIDOMNodeList_Release(node_list);
147 return ret;
150 /* This is very inefficient, but there is no faster way to compute index in
151 * child node list using public API. Gecko has internal nsINode::IndexOf
152 * function that we could consider exporting and use instead. */
153 static int get_child_index(nsIDOMNode *parent, nsIDOMNode *child)
155 nsIDOMNodeList *node_list;
156 nsIDOMNode *node;
157 int ret = 0;
158 nsresult nsres;
160 nsres = nsIDOMNode_GetChildNodes(parent, &node_list);
161 assert(nsres == NS_OK);
163 while(1) {
164 nsres = nsIDOMNodeList_Item(node_list, ret, &node);
165 assert(nsres == NS_OK && node);
166 if(node == child) {
167 nsIDOMNode_Release(node);
168 break;
170 nsIDOMNode_Release(node);
171 ret++;
174 nsIDOMNodeList_Release(node_list);
175 return ret;
178 static void init_rangepoint(rangepoint_t *rangepoint, nsIDOMNode *node, UINT32 off)
180 nsIDOMNode_AddRef(node);
182 rangepoint->type = get_node_type(node);
183 rangepoint->node = node;
184 rangepoint->off = off;
187 static inline void free_rangepoint(rangepoint_t *rangepoint)
189 nsIDOMNode_Release(rangepoint->node);
192 static inline BOOL rangepoint_cmp(const rangepoint_t *point1, const rangepoint_t *point2)
194 return point1->node == point2->node && point1->off == point2->off;
197 static BOOL rangepoint_next_node(rangepoint_t *iter)
199 nsIDOMNode *node;
200 UINT32 off;
201 nsresult nsres;
203 /* Try to move to the child node. */
204 node = get_child_node(iter->node, iter->off);
205 if(node) {
206 free_rangepoint(iter);
207 init_rangepoint(iter, node, 0);
208 nsIDOMNode_Release(node);
209 return TRUE;
212 /* There are no more children in the node. Move to parent. */
213 nsres = nsIDOMNode_GetParentNode(iter->node, &node);
214 assert(nsres == NS_OK);
215 if(!node)
216 return FALSE;
218 off = get_child_index(node, iter->node)+1;
219 free_rangepoint(iter);
220 init_rangepoint(iter, node, off);
221 nsIDOMNode_Release(node);
222 return TRUE;
225 static UINT32 get_child_count(nsIDOMNode *node)
227 nsIDOMNodeList *node_list;
228 UINT32 ret;
229 nsresult nsres;
231 nsres = nsIDOMNode_GetChildNodes(node, &node_list);
232 assert(nsres == NS_OK);
234 nsres = nsIDOMNodeList_GetLength(node_list, &ret);
235 nsIDOMNodeList_Release(node_list);
236 assert(nsres == NS_OK);
238 return ret;
241 static UINT32 get_text_length(nsIDOMNode *node)
243 nsIDOMText *nstext;
244 UINT32 ret;
245 nsresult nsres;
247 nsres = nsIDOMNode_QueryInterface(node, &IID_nsIDOMText, (void**)&nstext);
248 assert(nsres == NS_OK);
250 nsres = nsIDOMText_GetLength(nstext, &ret);
251 nsIDOMText_Release(nstext);
252 assert(nsres == NS_OK);
254 return ret;
257 static BOOL rangepoint_prev_node(rangepoint_t *iter)
259 nsIDOMNode *node;
260 UINT32 off;
261 nsresult nsres;
263 /* Try to move to the child node. */
264 if(iter->off) {
265 node = get_child_node(iter->node, iter->off-1);
266 assert(node != NULL);
268 off = get_node_type(node) == TEXT_NODE ? get_text_length(node) : get_child_count(node);
269 free_rangepoint(iter);
270 init_rangepoint(iter, node, off);
271 nsIDOMNode_Release(node);
272 return TRUE;
275 /* There are no more children in the node. Move to parent. */
276 nsres = nsIDOMNode_GetParentNode(iter->node, &node);
277 assert(nsres == NS_OK);
278 if(!node)
279 return FALSE;
281 off = get_child_index(node, iter->node);
282 free_rangepoint(iter);
283 init_rangepoint(iter, node, off);
284 return TRUE;
287 static void get_start_point(HTMLTxtRange *This, rangepoint_t *ret)
289 nsIDOMNode *node;
290 LONG off;
292 nsIDOMRange_GetStartContainer(This->nsrange, &node);
293 nsIDOMRange_GetStartOffset(This->nsrange, &off);
295 init_rangepoint(ret, node, off);
297 nsIDOMNode_Release(node);
300 static void get_end_point(HTMLTxtRange *This, rangepoint_t *ret)
302 nsIDOMNode *node;
303 LONG off;
305 nsIDOMRange_GetEndContainer(This->nsrange, &node);
306 nsIDOMRange_GetEndOffset(This->nsrange, &off);
308 init_rangepoint(ret, node, off);
310 nsIDOMNode_Release(node);
313 static void set_start_point(HTMLTxtRange *This, const rangepoint_t *start)
315 nsresult nsres = nsIDOMRange_SetStart(This->nsrange, start->node, start->off);
316 if(NS_FAILED(nsres))
317 ERR("failed: %08x\n", nsres);
320 static void set_end_point(HTMLTxtRange *This, const rangepoint_t *end)
322 nsresult nsres = nsIDOMRange_SetEnd(This->nsrange, end->node, end->off);
323 if(NS_FAILED(nsres))
324 ERR("failed: %08x\n", nsres);
327 static BOOL is_elem_tag(nsIDOMNode *node, LPCWSTR istag)
329 nsIDOMElement *elem;
330 nsAString tag_str;
331 const PRUnichar *tag;
332 BOOL ret = FALSE;
333 nsresult nsres;
335 nsres = nsIDOMNode_QueryInterface(node, &IID_nsIDOMElement, (void**)&elem);
336 if(NS_FAILED(nsres))
337 return FALSE;
339 nsAString_Init(&tag_str, NULL);
340 nsIDOMElement_GetTagName(elem, &tag_str);
341 nsIDOMElement_Release(elem);
342 nsAString_GetData(&tag_str, &tag);
344 ret = !wcsicmp(tag, istag);
346 nsAString_Finish(&tag_str);
348 return ret;
351 static inline BOOL wstrbuf_init(wstrbuf_t *buf)
353 buf->len = 0;
354 buf->size = 16;
355 buf->buf = heap_alloc(buf->size * sizeof(WCHAR));
356 if (!buf->buf) return FALSE;
357 *buf->buf = 0;
358 return TRUE;
361 static inline void wstrbuf_finish(wstrbuf_t *buf)
363 heap_free(buf->buf);
366 static void wstrbuf_append_len(wstrbuf_t *buf, LPCWSTR str, int len)
368 if(buf->len+len >= buf->size) {
369 buf->size = 2*buf->size+len;
370 buf->buf = heap_realloc(buf->buf, buf->size * sizeof(WCHAR));
373 memcpy(buf->buf+buf->len, str, len*sizeof(WCHAR));
374 buf->len += len;
375 buf->buf[buf->len] = 0;
378 static void wstrbuf_append_nodetxt(wstrbuf_t *buf, LPCWSTR str, int len)
380 const WCHAR *s = str;
381 WCHAR *d;
383 TRACE("%s\n", debugstr_wn(str, len));
385 if(buf->len+len >= buf->size) {
386 buf->size = 2*buf->size+len;
387 buf->buf = heap_realloc(buf->buf, buf->size * sizeof(WCHAR));
390 if(buf->len && iswspace(buf->buf[buf->len-1])) {
391 while(s < str+len && iswspace(*s))
392 s++;
395 d = buf->buf+buf->len;
396 while(s < str+len) {
397 if(iswspace(*s)) {
398 *d++ = ' ';
399 s++;
400 while(s < str+len && iswspace(*s))
401 s++;
402 }else {
403 *d++ = *s++;
407 buf->len = d - buf->buf;
408 *d = 0;
411 static void wstrbuf_append_node(wstrbuf_t *buf, nsIDOMNode *node, BOOL ignore_text)
414 switch(get_node_type(node)) {
415 case TEXT_NODE: {
416 nsIDOMText *nstext;
417 nsAString data_str;
418 const PRUnichar *data;
420 if(ignore_text)
421 break;
423 nsIDOMNode_QueryInterface(node, &IID_nsIDOMText, (void**)&nstext);
425 nsAString_Init(&data_str, NULL);
426 nsIDOMText_GetData(nstext, &data_str);
427 nsAString_GetData(&data_str, &data);
428 wstrbuf_append_nodetxt(buf, data, lstrlenW(data));
429 nsAString_Finish(&data_str);
431 nsIDOMText_Release(nstext);
433 break;
435 case ELEMENT_NODE:
436 if(is_elem_tag(node, L"br")) {
437 static const WCHAR endlW[] = {'\r','\n'};
438 wstrbuf_append_len(buf, endlW, 2);
439 }else if(is_elem_tag(node, L"hr")) {
440 static const WCHAR endl2W[] = {'\r','\n','\r','\n'};
441 wstrbuf_append_len(buf, endl2W, 4);
446 static void wstrbuf_append_node_rec(wstrbuf_t *buf, nsIDOMNode *node)
448 nsIDOMNode *iter, *tmp;
450 wstrbuf_append_node(buf, node, FALSE);
452 nsIDOMNode_GetFirstChild(node, &iter);
453 while(iter) {
454 wstrbuf_append_node_rec(buf, iter);
455 nsIDOMNode_GetNextSibling(iter, &tmp);
456 nsIDOMNode_Release(iter);
457 iter = tmp;
461 static void range_to_string(HTMLTxtRange *This, wstrbuf_t *buf)
463 rangepoint_t end_pos, iter;
464 cpp_bool collapsed;
466 nsIDOMRange_GetCollapsed(This->nsrange, &collapsed);
467 if(collapsed) {
468 wstrbuf_finish(buf);
469 buf->buf = NULL;
470 buf->size = 0;
471 return;
474 get_end_point(This, &end_pos);
475 get_start_point(This, &iter);
477 do {
478 if(iter.type == TEXT_NODE) {
479 const PRUnichar *str;
480 nsAString nsstr;
482 get_text_node_data(iter.node, &nsstr, &str);
484 if(iter.node == end_pos.node) {
485 wstrbuf_append_nodetxt(buf, str+iter.off, end_pos.off-iter.off);
486 nsAString_Finish(&nsstr);
487 break;
490 wstrbuf_append_nodetxt(buf, str+iter.off, lstrlenW(str+iter.off));
491 nsAString_Finish(&nsstr);
492 }else {
493 nsIDOMNode *node;
495 node = get_child_node(iter.node, iter.off);
496 if(node) {
497 wstrbuf_append_node(buf, node, TRUE);
498 nsIDOMNode_Release(node);
502 if(!rangepoint_next_node(&iter)) {
503 ERR("End of document?\n");
504 break;
506 }while(!rangepoint_cmp(&iter, &end_pos));
508 free_rangepoint(&iter);
509 free_rangepoint(&end_pos);
511 if(buf->len) {
512 WCHAR *p;
514 for(p = buf->buf+buf->len-1; p >= buf->buf && iswspace(*p); p--);
516 p = wcschr(p, '\r');
517 if(p)
518 *p = 0;
522 HRESULT get_node_text(HTMLDOMNode *node, BSTR *ret)
524 wstrbuf_t buf;
525 HRESULT hres = S_OK;
527 if (!wstrbuf_init(&buf))
528 return E_OUTOFMEMORY;
529 wstrbuf_append_node_rec(&buf, node->nsnode);
530 if(buf.buf && *buf.buf) {
531 *ret = SysAllocString(buf.buf);
532 if(!*ret)
533 hres = E_OUTOFMEMORY;
534 } else {
535 *ret = NULL;
537 wstrbuf_finish(&buf);
539 if(SUCCEEDED(hres))
540 TRACE("ret %s\n", debugstr_w(*ret));
541 return hres;
544 static WCHAR move_next_char(rangepoint_t *iter)
546 rangepoint_t last_space;
547 nsIDOMNode *node;
548 WCHAR cspace = 0;
549 const WCHAR *p;
551 do {
552 switch(iter->type) {
553 case TEXT_NODE: {
554 const PRUnichar *str;
555 nsAString nsstr;
556 WCHAR c;
558 get_text_node_data(iter->node, &nsstr, &str);
559 p = str+iter->off;
560 if(!*p) {
561 nsAString_Finish(&nsstr);
562 break;
565 c = *p;
566 if(iswspace(c)) {
567 while(iswspace(*p))
568 p++;
570 if(cspace)
571 free_rangepoint(&last_space);
572 else
573 cspace = ' ';
575 iter->off = p-str;
576 c = *p;
577 nsAString_Finish(&nsstr);
578 if(!c) { /* continue to skip spaces */
579 init_rangepoint(&last_space, iter->node, iter->off);
580 break;
583 return cspace;
584 }else {
585 nsAString_Finish(&nsstr);
588 /* If we have a non-space char and we're skipping spaces, stop and return the last found space. */
589 if(cspace) {
590 free_rangepoint(iter);
591 *iter = last_space;
592 return cspace;
595 iter->off++;
596 return c;
598 case ELEMENT_NODE:
599 node = get_child_node(iter->node, iter->off);
600 if(!node)
601 break;
603 if(is_elem_tag(node, L"br")) {
604 if(cspace) {
605 nsIDOMNode_Release(node);
606 free_rangepoint(iter);
607 *iter = last_space;
608 return cspace;
611 cspace = '\n';
612 init_rangepoint(&last_space, iter->node, iter->off+1);
613 }else if(is_elem_tag(node, L"hr")) {
614 nsIDOMNode_Release(node);
615 if(cspace) {
616 free_rangepoint(iter);
617 *iter = last_space;
618 return cspace;
621 iter->off++;
622 return '\n';
625 nsIDOMNode_Release(node);
627 }while(rangepoint_next_node(iter));
629 return cspace;
632 static WCHAR move_prev_char(rangepoint_t *iter)
634 rangepoint_t last_space;
635 nsIDOMNode *node;
636 WCHAR cspace = 0;
637 const WCHAR *p;
639 do {
640 switch(iter->type) {
641 case TEXT_NODE: {
642 const PRUnichar *str;
643 nsAString nsstr;
644 WCHAR c;
646 if(!iter->off)
647 break;
649 get_text_node_data(iter->node, &nsstr, &str);
651 p = str+iter->off-1;
652 c = *p;
654 if(iswspace(c)) {
655 while(p > str && iswspace(*(p-1)))
656 p--;
658 if(cspace)
659 free_rangepoint(&last_space);
660 else
661 cspace = ' ';
663 iter->off = p-str;
664 nsAString_Finish(&nsstr);
665 if(p == str) { /* continue to skip spaces */
666 init_rangepoint(&last_space, iter->node, iter->off);
667 break;
670 return cspace;
671 }else {
672 nsAString_Finish(&nsstr);
675 /* If we have a non-space char and we're skipping spaces, stop and return the last found space. */
676 if(cspace) {
677 free_rangepoint(iter);
678 *iter = last_space;
679 return cspace;
682 iter->off--;
683 return c;
685 case ELEMENT_NODE:
686 if(!iter->off)
687 break;
689 node = get_child_node(iter->node, iter->off-1);
690 if(!node)
691 break;
693 if(is_elem_tag(node, L"br")) {
694 if(cspace)
695 free_rangepoint(&last_space);
696 cspace = '\n';
697 init_rangepoint(&last_space, iter->node, iter->off-1);
698 }else if(is_elem_tag(node, L"hr")) {
699 nsIDOMNode_Release(node);
700 if(cspace) {
701 free_rangepoint(iter);
702 *iter = last_space;
703 return cspace;
706 iter->off--;
707 return '\n';
710 nsIDOMNode_Release(node);
712 }while(rangepoint_prev_node(iter));
714 if(cspace) {
715 free_rangepoint(iter);
716 *iter = last_space;
717 return cspace;
720 return 0;
723 static LONG move_by_chars(rangepoint_t *iter, LONG cnt)
725 LONG ret = 0;
727 if(cnt >= 0) {
728 while(ret < cnt && move_next_char(iter))
729 ret++;
730 }else {
731 while(ret > cnt && move_prev_char(iter))
732 ret--;
735 return ret;
738 static LONG find_prev_space(rangepoint_t *iter, BOOL first_space)
740 rangepoint_t prev;
741 WCHAR c;
743 init_rangepoint(&prev, iter->node, iter->off);
744 c = move_prev_char(&prev);
745 if(!c || (first_space && iswspace(c)))
746 return FALSE;
748 do {
749 free_rangepoint(iter);
750 init_rangepoint(iter, prev.node, prev.off);
751 c = move_prev_char(&prev);
752 }while(c && !iswspace(c));
754 free_rangepoint(&prev);
755 return TRUE;
758 static BOOL find_word_end(rangepoint_t *iter, BOOL is_collapsed)
760 rangepoint_t prev_iter;
761 WCHAR c;
762 BOOL ret = FALSE;
764 if(!is_collapsed) {
765 init_rangepoint(&prev_iter, iter->node, iter->off);
766 c = move_prev_char(&prev_iter);
767 free_rangepoint(&prev_iter);
768 if(iswspace(c))
769 return FALSE;
772 do {
773 init_rangepoint(&prev_iter, iter->node, iter->off);
774 c = move_next_char(iter);
775 if(c == '\n') {
776 free_rangepoint(iter);
777 *iter = prev_iter;
778 return ret;
780 if(!c) {
781 if(!ret)
782 ret = !rangepoint_cmp(iter, &prev_iter);
783 }else {
784 ret = TRUE;
786 free_rangepoint(&prev_iter);
787 }while(c && !iswspace(c));
789 return ret;
792 static LONG move_by_words(rangepoint_t *iter, LONG cnt)
794 LONG ret = 0;
796 if(cnt >= 0) {
797 WCHAR c;
799 while(ret < cnt && (c = move_next_char(iter))) {
800 if(iswspace(c))
801 ret++;
803 }else {
804 while(ret > cnt && find_prev_space(iter, FALSE))
805 ret--;
808 return ret;
811 static inline HTMLTxtRange *impl_from_IHTMLTxtRange(IHTMLTxtRange *iface)
813 return CONTAINING_RECORD(iface, HTMLTxtRange, IHTMLTxtRange_iface);
816 static HRESULT WINAPI HTMLTxtRange_QueryInterface(IHTMLTxtRange *iface, REFIID riid, void **ppv)
818 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
820 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
822 if(IsEqualGUID(&IID_IUnknown, riid)) {
823 *ppv = &This->IHTMLTxtRange_iface;
824 }else if(IsEqualGUID(&IID_IHTMLTxtRange, riid)) {
825 *ppv = &This->IHTMLTxtRange_iface;
826 }else if(IsEqualGUID(&IID_IOleCommandTarget, riid)) {
827 *ppv = &This->IOleCommandTarget_iface;
828 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
829 return *ppv ? S_OK : E_NOINTERFACE;
830 }else {
831 *ppv = NULL;
832 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
833 return E_NOINTERFACE;
836 IUnknown_AddRef((IUnknown*)*ppv);
837 return S_OK;
840 static ULONG WINAPI HTMLTxtRange_AddRef(IHTMLTxtRange *iface)
842 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
843 LONG ref = InterlockedIncrement(&This->ref);
845 TRACE("(%p) ref=%d\n", This, ref);
847 return ref;
850 static ULONG WINAPI HTMLTxtRange_Release(IHTMLTxtRange *iface)
852 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
853 LONG ref = InterlockedDecrement(&This->ref);
855 TRACE("(%p) ref=%d\n", This, ref);
857 if(!ref) {
858 if(This->nsrange)
859 nsIDOMRange_Release(This->nsrange);
860 if(This->doc)
861 list_remove(&This->entry);
862 release_dispex(&This->dispex);
863 heap_free(This);
866 return ref;
869 static HRESULT WINAPI HTMLTxtRange_GetTypeInfoCount(IHTMLTxtRange *iface, UINT *pctinfo)
871 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
873 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
876 static HRESULT WINAPI HTMLTxtRange_GetTypeInfo(IHTMLTxtRange *iface, UINT iTInfo,
877 LCID lcid, ITypeInfo **ppTInfo)
879 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
881 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
884 static HRESULT WINAPI HTMLTxtRange_GetIDsOfNames(IHTMLTxtRange *iface, REFIID riid,
885 LPOLESTR *rgszNames, UINT cNames,
886 LCID lcid, DISPID *rgDispId)
888 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
890 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames,
891 cNames, lcid, rgDispId);
894 static HRESULT WINAPI HTMLTxtRange_Invoke(IHTMLTxtRange *iface, DISPID dispIdMember,
895 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
896 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
898 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
900 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid,
901 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
904 static HRESULT WINAPI HTMLTxtRange_get_htmlText(IHTMLTxtRange *iface, BSTR *p)
906 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
908 TRACE("(%p)->(%p)\n", This, p);
910 *p = NULL;
912 if(This->nsrange) {
913 nsIDOMDocumentFragment *fragment;
914 nsresult nsres;
916 nsres = nsIDOMRange_CloneContents(This->nsrange, &fragment);
917 if(NS_SUCCEEDED(nsres)) {
918 const PRUnichar *nstext;
919 nsAString nsstr;
921 nsAString_Init(&nsstr, NULL);
922 nsnode_to_nsstring((nsIDOMNode*)fragment, &nsstr);
923 nsIDOMDocumentFragment_Release(fragment);
925 nsAString_GetData(&nsstr, &nstext);
926 *p = SysAllocString(nstext);
928 nsAString_Finish(&nsstr);
932 if(!*p) {
933 *p = SysAllocString(L"");
936 TRACE("return %s\n", debugstr_w(*p));
937 return S_OK;
940 static HRESULT WINAPI HTMLTxtRange_put_text(IHTMLTxtRange *iface, BSTR v)
942 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
943 nsIDOMText *text_node;
944 nsAString text_str;
945 nsresult nsres;
947 TRACE("(%p)->(%s)\n", This, debugstr_w(v));
949 if(!This->doc)
950 return MSHTML_E_NODOC;
952 nsAString_InitDepend(&text_str, v);
953 nsres = nsIDOMHTMLDocument_CreateTextNode(This->doc->nsdoc, &text_str, &text_node);
954 nsAString_Finish(&text_str);
955 if(NS_FAILED(nsres)) {
956 ERR("CreateTextNode failed: %08x\n", nsres);
957 return S_OK;
959 nsres = nsIDOMRange_DeleteContents(This->nsrange);
960 if(NS_FAILED(nsres))
961 ERR("DeleteContents failed: %08x\n", nsres);
963 nsres = nsIDOMRange_InsertNode(This->nsrange, (nsIDOMNode*)text_node);
964 if(NS_FAILED(nsres))
965 ERR("InsertNode failed: %08x\n", nsres);
967 nsres = nsIDOMRange_SetEndAfter(This->nsrange, (nsIDOMNode*)text_node);
968 if(NS_FAILED(nsres))
969 ERR("SetEndAfter failed: %08x\n", nsres);
971 return IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, VARIANT_FALSE);
974 static HRESULT WINAPI HTMLTxtRange_get_text(IHTMLTxtRange *iface, BSTR *p)
976 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
977 wstrbuf_t buf;
979 TRACE("(%p)->(%p)\n", This, p);
981 *p = NULL;
982 if(!This->nsrange)
983 return S_OK;
985 if (!wstrbuf_init(&buf))
986 return E_OUTOFMEMORY;
987 range_to_string(This, &buf);
988 if (buf.buf)
989 *p = SysAllocString(buf.buf);
990 wstrbuf_finish(&buf);
992 TRACE("ret %s\n", debugstr_w(*p));
993 return S_OK;
996 static HRESULT WINAPI HTMLTxtRange_parentElement(IHTMLTxtRange *iface, IHTMLElement **parent)
998 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
999 nsIDOMNode *nsnode, *tmp;
1000 HTMLDOMNode *node;
1001 HRESULT hres;
1003 TRACE("(%p)->(%p)\n", This, parent);
1005 nsIDOMRange_GetCommonAncestorContainer(This->nsrange, &nsnode);
1006 while(nsnode && get_node_type(nsnode) != ELEMENT_NODE) {
1007 nsIDOMNode_GetParentNode(nsnode, &tmp);
1008 nsIDOMNode_Release(nsnode);
1009 nsnode = tmp;
1012 if(!nsnode) {
1013 *parent = NULL;
1014 return S_OK;
1017 hres = get_node(nsnode, TRUE, &node);
1018 nsIDOMNode_Release(nsnode);
1019 if(FAILED(hres))
1020 return hres;
1022 hres = IHTMLDOMNode_QueryInterface(&node->IHTMLDOMNode_iface, &IID_IHTMLElement, (void**)parent);
1023 node_release(node);
1024 return hres;
1027 static HRESULT WINAPI HTMLTxtRange_duplicate(IHTMLTxtRange *iface, IHTMLTxtRange **Duplicate)
1029 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1030 nsIDOMRange *nsrange = NULL;
1031 HRESULT hres;
1033 TRACE("(%p)->(%p)\n", This, Duplicate);
1035 nsIDOMRange_CloneRange(This->nsrange, &nsrange);
1036 hres = HTMLTxtRange_Create(This->doc, nsrange, Duplicate);
1037 nsIDOMRange_Release(nsrange);
1039 return hres;
1042 static HRESULT WINAPI HTMLTxtRange_inRange(IHTMLTxtRange *iface, IHTMLTxtRange *Range,
1043 VARIANT_BOOL *InRange)
1045 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1046 HTMLTxtRange *src_range;
1047 short nsret = 0;
1048 nsresult nsres;
1050 TRACE("(%p)->(%p %p)\n", This, Range, InRange);
1052 *InRange = VARIANT_FALSE;
1054 src_range = get_range_object(This->doc, Range);
1055 if(!src_range)
1056 return E_FAIL;
1058 nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, NS_START_TO_START,
1059 src_range->nsrange, &nsret);
1060 if(NS_SUCCEEDED(nsres) && nsret <= 0) {
1061 nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, NS_END_TO_END,
1062 src_range->nsrange, &nsret);
1063 if(NS_SUCCEEDED(nsres) && nsret >= 0)
1064 *InRange = VARIANT_TRUE;
1067 if(NS_FAILED(nsres))
1068 ERR("CompareBoundaryPoints failed: %08x\n", nsres);
1070 return S_OK;
1073 static HRESULT WINAPI HTMLTxtRange_isEqual(IHTMLTxtRange *iface, IHTMLTxtRange *Range,
1074 VARIANT_BOOL *IsEqual)
1076 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1077 HTMLTxtRange *src_range;
1078 short nsret = 0;
1079 nsresult nsres;
1081 TRACE("(%p)->(%p %p)\n", This, Range, IsEqual);
1083 *IsEqual = VARIANT_FALSE;
1085 src_range = get_range_object(This->doc, Range);
1086 if(!src_range)
1087 return E_FAIL;
1089 nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, NS_START_TO_START,
1090 src_range->nsrange, &nsret);
1091 if(NS_SUCCEEDED(nsres) && !nsret) {
1092 nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, NS_END_TO_END,
1093 src_range->nsrange, &nsret);
1094 if(NS_SUCCEEDED(nsres) && !nsret)
1095 *IsEqual = VARIANT_TRUE;
1098 if(NS_FAILED(nsres))
1099 ERR("CompareBoundaryPoints failed: %08x\n", nsres);
1101 return S_OK;
1104 static HRESULT WINAPI HTMLTxtRange_scrollIntoView(IHTMLTxtRange *iface, VARIANT_BOOL fStart)
1106 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1107 FIXME("(%p)->(%x)\n", This, fStart);
1108 return E_NOTIMPL;
1111 static HRESULT WINAPI HTMLTxtRange_collapse(IHTMLTxtRange *iface, VARIANT_BOOL Start)
1113 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1115 TRACE("(%p)->(%x)\n", This, Start);
1117 nsIDOMRange_Collapse(This->nsrange, Start != VARIANT_FALSE);
1118 return S_OK;
1121 static HRESULT WINAPI HTMLTxtRange_expand(IHTMLTxtRange *iface, BSTR Unit, VARIANT_BOOL *Success)
1123 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1124 range_unit_t unit;
1126 TRACE("(%p)->(%s %p)\n", This, debugstr_w(Unit), Success);
1128 unit = string_to_unit(Unit);
1129 if(unit == RU_UNKNOWN)
1130 return E_INVALIDARG;
1132 *Success = VARIANT_FALSE;
1134 switch(unit) {
1135 case RU_WORD: {
1136 rangepoint_t end, start;
1137 cpp_bool is_collapsed;
1139 get_start_point(This, &start);
1140 get_end_point(This, &end);
1142 nsIDOMRange_GetCollapsed(This->nsrange, &is_collapsed);
1144 if(find_word_end(&end, is_collapsed)) {
1145 set_end_point(This, &end);
1146 *Success = VARIANT_TRUE;
1149 if(find_prev_space(&start, TRUE)) {
1150 set_start_point(This, &start);
1151 *Success = VARIANT_TRUE;
1154 free_rangepoint(&end);
1155 free_rangepoint(&start);
1156 break;
1159 case RU_TEXTEDIT: {
1160 nsIDOMHTMLElement *nsbody = NULL;
1161 nsresult nsres;
1163 nsres = nsIDOMHTMLDocument_GetBody(This->doc->nsdoc, &nsbody);
1164 if(NS_FAILED(nsres) || !nsbody) {
1165 ERR("Could not get body: %08x\n", nsres);
1166 break;
1169 nsres = nsIDOMRange_SelectNodeContents(This->nsrange, (nsIDOMNode*)nsbody);
1170 nsIDOMHTMLElement_Release(nsbody);
1171 if(NS_FAILED(nsres)) {
1172 ERR("Collapse failed: %08x\n", nsres);
1173 break;
1176 *Success = VARIANT_TRUE;
1177 break;
1180 default:
1181 FIXME("Unimplemented unit %s\n", debugstr_w(Unit));
1184 return S_OK;
1187 static HRESULT WINAPI HTMLTxtRange_move(IHTMLTxtRange *iface, BSTR Unit,
1188 LONG Count, LONG *ActualCount)
1190 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1191 range_unit_t unit;
1193 TRACE("(%p)->(%s %d %p)\n", This, debugstr_w(Unit), Count, ActualCount);
1195 unit = string_to_unit(Unit);
1196 if(unit == RU_UNKNOWN)
1197 return E_INVALIDARG;
1199 if(!Count) {
1200 *ActualCount = 0;
1201 return IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, VARIANT_TRUE);
1204 switch(unit) {
1205 case RU_CHAR: {
1206 rangepoint_t start;
1208 get_start_point(This, &start);
1210 *ActualCount = move_by_chars(&start, Count);
1212 set_start_point(This, &start);
1213 IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, VARIANT_TRUE);
1214 free_rangepoint(&start);
1215 break;
1218 case RU_WORD: {
1219 rangepoint_t start;
1221 get_start_point(This, &start);
1223 *ActualCount = move_by_words(&start, Count);
1225 set_start_point(This, &start);
1226 IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, VARIANT_TRUE);
1227 free_rangepoint(&start);
1228 break;
1231 default:
1232 FIXME("unimplemented unit %s\n", debugstr_w(Unit));
1235 TRACE("ret %d\n", *ActualCount);
1236 return S_OK;
1239 static HRESULT WINAPI HTMLTxtRange_moveStart(IHTMLTxtRange *iface, BSTR Unit,
1240 LONG Count, LONG *ActualCount)
1242 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1243 range_unit_t unit;
1245 TRACE("(%p)->(%s %d %p)\n", This, debugstr_w(Unit), Count, ActualCount);
1247 unit = string_to_unit(Unit);
1248 if(unit == RU_UNKNOWN)
1249 return E_INVALIDARG;
1251 if(!Count) {
1252 *ActualCount = 0;
1253 return S_OK;
1256 switch(unit) {
1257 case RU_CHAR: {
1258 rangepoint_t start;
1260 get_start_point(This, &start);
1262 *ActualCount = move_by_chars(&start, Count);
1264 set_start_point(This, &start);
1265 free_rangepoint(&start);
1266 break;
1269 default:
1270 FIXME("unimplemented unit %s\n", debugstr_w(Unit));
1271 return E_NOTIMPL;
1274 return S_OK;
1277 static HRESULT WINAPI HTMLTxtRange_moveEnd(IHTMLTxtRange *iface, BSTR Unit,
1278 LONG Count, LONG *ActualCount)
1280 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1281 range_unit_t unit;
1283 TRACE("(%p)->(%s %d %p)\n", This, debugstr_w(Unit), Count, ActualCount);
1285 unit = string_to_unit(Unit);
1286 if(unit == RU_UNKNOWN)
1287 return E_INVALIDARG;
1289 if(!Count) {
1290 *ActualCount = 0;
1291 return S_OK;
1294 switch(unit) {
1295 case RU_CHAR: {
1296 rangepoint_t end;
1298 get_end_point(This, &end);
1300 *ActualCount = move_by_chars(&end, Count);
1302 set_end_point(This, &end);
1303 free_rangepoint(&end);
1304 break;
1307 default:
1308 FIXME("unimplemented unit %s\n", debugstr_w(Unit));
1311 return S_OK;
1314 static HRESULT WINAPI HTMLTxtRange_select(IHTMLTxtRange *iface)
1316 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1317 nsISelection *nsselection;
1318 nsresult nsres;
1320 TRACE("(%p)\n", This);
1322 nsres = nsIDOMWindow_GetSelection(This->doc->basedoc.window->nswindow, &nsselection);
1323 if(NS_FAILED(nsres)) {
1324 ERR("GetSelection failed: %08x\n", nsres);
1325 return E_FAIL;
1328 nsISelection_RemoveAllRanges(nsselection);
1329 nsISelection_AddRange(nsselection, This->nsrange);
1330 nsISelection_Release(nsselection);
1331 return S_OK;
1334 static HRESULT WINAPI HTMLTxtRange_pasteHTML(IHTMLTxtRange *iface, BSTR html)
1336 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1337 nsIDOMDocumentFragment *doc_frag;
1338 nsAString nsstr;
1339 nsresult nsres;
1341 TRACE("(%p)->(%s)\n", This, debugstr_w(html));
1343 nsres = nsIDOMRange_Collapse(This->nsrange, TRUE);
1344 assert(nsres == NS_OK);
1346 nsAString_InitDepend(&nsstr, html);
1347 nsres = nsIDOMRange_CreateContextualFragment(This->nsrange, &nsstr, &doc_frag);
1348 nsAString_Finish(&nsstr);
1349 if(NS_FAILED(nsres)) {
1350 ERR("CreateContextualFragment failed: %08x\n", nsres);
1351 return E_FAIL;
1354 nsres = nsIDOMRange_InsertNode(This->nsrange, (nsIDOMNode*)doc_frag);
1355 nsIDOMDocumentFragment_Release(doc_frag);
1356 if(NS_FAILED(nsres)) {
1357 ERR("InsertNode failed: %08x\n", nsres);
1358 return E_FAIL;
1361 nsres = nsIDOMRange_Collapse(This->nsrange, FALSE);
1362 assert(nsres == NS_OK);
1363 return S_OK;
1366 static HRESULT WINAPI HTMLTxtRange_moveToElementText(IHTMLTxtRange *iface, IHTMLElement *element)
1368 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1369 HTMLElement *elem;
1370 nsresult nsres;
1372 TRACE("(%p)->(%p)\n", This, element);
1374 elem = unsafe_impl_from_IHTMLElement(element);
1375 if(!elem)
1376 return E_INVALIDARG;
1378 nsres = nsIDOMRange_SelectNodeContents(This->nsrange, elem->node.nsnode);
1379 if(NS_FAILED(nsres)) {
1380 ERR("SelectNodeContents failed: %08x\n", nsres);
1381 return E_FAIL;
1384 return S_OK;
1387 static HRESULT WINAPI HTMLTxtRange_setEndPoint(IHTMLTxtRange *iface, BSTR how,
1388 IHTMLTxtRange *SourceRange)
1390 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1391 HTMLTxtRange *src_range;
1392 nsIDOMNode *ref_node;
1393 INT32 ref_offset;
1394 BOOL set_start;
1395 int how_type;
1396 INT16 cmp;
1397 nsresult nsres;
1399 TRACE("(%p)->(%s %p)\n", This, debugstr_w(how), SourceRange);
1401 how_type = string_to_nscmptype(how);
1402 if(how_type == -1)
1403 return E_INVALIDARG;
1405 src_range = get_range_object(This->doc, SourceRange);
1406 if(!src_range)
1407 return E_FAIL;
1409 switch(how_type) {
1410 case NS_START_TO_START:
1411 case NS_END_TO_START:
1412 nsres = nsIDOMRange_GetStartContainer(src_range->nsrange, &ref_node);
1413 assert(nsres == NS_OK);
1415 nsres = nsIDOMRange_GetStartOffset(src_range->nsrange, &ref_offset);
1416 assert(nsres == NS_OK);
1418 set_start = how_type == NS_START_TO_START;
1419 break;
1420 case NS_END_TO_END:
1421 case NS_START_TO_END:
1422 nsres = nsIDOMRange_GetEndContainer(src_range->nsrange, &ref_node);
1423 assert(nsres == NS_OK);
1425 nsres = nsIDOMRange_GetEndOffset(src_range->nsrange, &ref_offset);
1426 assert(nsres == NS_OK);
1428 set_start = how_type == NS_START_TO_END;
1429 break;
1430 DEFAULT_UNREACHABLE;
1433 nsres = nsIDOMRange_ComparePoint(This->nsrange, ref_node, ref_offset, &cmp);
1434 assert(nsres == NS_OK);
1436 if(set_start) {
1437 if(cmp <= 0) {
1438 nsres = nsIDOMRange_SetStart(This->nsrange, ref_node, ref_offset);
1439 }else {
1440 nsres = nsIDOMRange_Collapse(This->nsrange, FALSE);
1441 assert(nsres == NS_OK);
1443 nsres = nsIDOMRange_SetEnd(This->nsrange, ref_node, ref_offset);
1445 }else {
1446 if(cmp >= 0) {
1447 nsres = nsIDOMRange_SetEnd(This->nsrange, ref_node, ref_offset);
1448 }else {
1449 nsres = nsIDOMRange_Collapse(This->nsrange, TRUE);
1450 assert(nsres == NS_OK);
1452 nsres = nsIDOMRange_SetStart(This->nsrange, ref_node, ref_offset);
1455 assert(nsres == NS_OK);
1457 nsIDOMNode_Release(ref_node);
1458 return S_OK;
1461 static HRESULT WINAPI HTMLTxtRange_compareEndPoints(IHTMLTxtRange *iface, BSTR how,
1462 IHTMLTxtRange *SourceRange, LONG *ret)
1464 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1465 HTMLTxtRange *src_range;
1466 short nsret = 0;
1467 int nscmpt;
1468 nsresult nsres;
1470 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(how), SourceRange, ret);
1472 nscmpt = string_to_nscmptype(how);
1473 if(nscmpt == -1)
1474 return E_INVALIDARG;
1476 src_range = get_range_object(This->doc, SourceRange);
1477 if(!src_range)
1478 return E_FAIL;
1480 nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, nscmpt, src_range->nsrange, &nsret);
1481 if(NS_FAILED(nsres))
1482 ERR("CompareBoundaryPoints failed: %08x\n", nsres);
1484 *ret = nsret;
1485 return S_OK;
1488 static HRESULT WINAPI HTMLTxtRange_findText(IHTMLTxtRange *iface, BSTR String,
1489 LONG count, LONG Flags, VARIANT_BOOL *Success)
1491 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1492 FIXME("(%p)->(%s %d %08x %p)\n", This, debugstr_w(String), count, Flags, Success);
1493 return E_NOTIMPL;
1496 static HRESULT WINAPI HTMLTxtRange_moveToPoint(IHTMLTxtRange *iface, LONG x, LONG y)
1498 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1499 FIXME("(%p)->(%d %d)\n", This, x, y);
1500 return E_NOTIMPL;
1503 static HRESULT WINAPI HTMLTxtRange_getBookmark(IHTMLTxtRange *iface, BSTR *Bookmark)
1505 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1506 FIXME("(%p)->(%p)\n", This, Bookmark);
1507 return E_NOTIMPL;
1510 static HRESULT WINAPI HTMLTxtRange_moveToBookmark(IHTMLTxtRange *iface, BSTR Bookmark,
1511 VARIANT_BOOL *Success)
1513 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1514 FIXME("(%p)->(%s %p)\n", This, debugstr_w(Bookmark), Success);
1515 return E_NOTIMPL;
1518 static HRESULT WINAPI HTMLTxtRange_queryCommandSupported(IHTMLTxtRange *iface, BSTR cmdID,
1519 VARIANT_BOOL *pfRet)
1521 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1522 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1523 return E_NOTIMPL;
1526 static HRESULT WINAPI HTMLTxtRange_queryCommandEnabled(IHTMLTxtRange *iface, BSTR cmdID,
1527 VARIANT_BOOL *pfRet)
1529 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1530 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1531 return E_NOTIMPL;
1534 static HRESULT WINAPI HTMLTxtRange_queryCommandState(IHTMLTxtRange *iface, BSTR cmdID,
1535 VARIANT_BOOL *pfRet)
1537 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1538 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1539 return E_NOTIMPL;
1542 static HRESULT WINAPI HTMLTxtRange_queryCommandIndeterm(IHTMLTxtRange *iface, BSTR cmdID,
1543 VARIANT_BOOL *pfRet)
1545 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1546 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1547 return E_NOTIMPL;
1550 static HRESULT WINAPI HTMLTxtRange_queryCommandText(IHTMLTxtRange *iface, BSTR cmdID,
1551 BSTR *pcmdText)
1553 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1554 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pcmdText);
1555 return E_NOTIMPL;
1558 static HRESULT WINAPI HTMLTxtRange_queryCommandValue(IHTMLTxtRange *iface, BSTR cmdID,
1559 VARIANT *pcmdValue)
1561 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1562 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pcmdValue);
1563 return E_NOTIMPL;
1566 static HRESULT WINAPI HTMLTxtRange_execCommand(IHTMLTxtRange *iface, BSTR cmdID,
1567 VARIANT_BOOL showUI, VARIANT value, VARIANT_BOOL *pfRet)
1569 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1570 FIXME("(%p)->(%s %x v %p)\n", This, debugstr_w(cmdID), showUI, pfRet);
1571 return E_NOTIMPL;
1574 static HRESULT WINAPI HTMLTxtRange_execCommandShowHelp(IHTMLTxtRange *iface, BSTR cmdID,
1575 VARIANT_BOOL *pfRet)
1577 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1578 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1579 return E_NOTIMPL;
1582 static const IHTMLTxtRangeVtbl HTMLTxtRangeVtbl = {
1583 HTMLTxtRange_QueryInterface,
1584 HTMLTxtRange_AddRef,
1585 HTMLTxtRange_Release,
1586 HTMLTxtRange_GetTypeInfoCount,
1587 HTMLTxtRange_GetTypeInfo,
1588 HTMLTxtRange_GetIDsOfNames,
1589 HTMLTxtRange_Invoke,
1590 HTMLTxtRange_get_htmlText,
1591 HTMLTxtRange_put_text,
1592 HTMLTxtRange_get_text,
1593 HTMLTxtRange_parentElement,
1594 HTMLTxtRange_duplicate,
1595 HTMLTxtRange_inRange,
1596 HTMLTxtRange_isEqual,
1597 HTMLTxtRange_scrollIntoView,
1598 HTMLTxtRange_collapse,
1599 HTMLTxtRange_expand,
1600 HTMLTxtRange_move,
1601 HTMLTxtRange_moveStart,
1602 HTMLTxtRange_moveEnd,
1603 HTMLTxtRange_select,
1604 HTMLTxtRange_pasteHTML,
1605 HTMLTxtRange_moveToElementText,
1606 HTMLTxtRange_setEndPoint,
1607 HTMLTxtRange_compareEndPoints,
1608 HTMLTxtRange_findText,
1609 HTMLTxtRange_moveToPoint,
1610 HTMLTxtRange_getBookmark,
1611 HTMLTxtRange_moveToBookmark,
1612 HTMLTxtRange_queryCommandSupported,
1613 HTMLTxtRange_queryCommandEnabled,
1614 HTMLTxtRange_queryCommandState,
1615 HTMLTxtRange_queryCommandIndeterm,
1616 HTMLTxtRange_queryCommandText,
1617 HTMLTxtRange_queryCommandValue,
1618 HTMLTxtRange_execCommand,
1619 HTMLTxtRange_execCommandShowHelp
1622 static inline HTMLTxtRange *impl_from_IOleCommandTarget(IOleCommandTarget *iface)
1624 return CONTAINING_RECORD(iface, HTMLTxtRange, IOleCommandTarget_iface);
1627 static HRESULT WINAPI RangeCommandTarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv)
1629 HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1630 return IHTMLTxtRange_QueryInterface(&This->IHTMLTxtRange_iface, riid, ppv);
1633 static ULONG WINAPI RangeCommandTarget_AddRef(IOleCommandTarget *iface)
1635 HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1636 return IHTMLTxtRange_AddRef(&This->IHTMLTxtRange_iface);
1639 static ULONG WINAPI RangeCommandTarget_Release(IOleCommandTarget *iface)
1641 HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1642 return IHTMLTxtRange_Release(&This->IHTMLTxtRange_iface);
1645 static HRESULT WINAPI RangeCommandTarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
1646 ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
1648 HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1649 FIXME("(%p)->(%s %d %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
1650 return E_NOTIMPL;
1653 static HRESULT exec_indent(HTMLTxtRange *This, VARIANT *in, VARIANT *out)
1655 nsIDOMElement *blockquote_elem, *p_elem;
1656 nsIDOMDocumentFragment *fragment;
1657 nsIDOMNode *tmp;
1659 TRACE("(%p)->(%p %p)\n", This, in, out);
1661 if(!This->doc->nsdoc) {
1662 WARN("NULL nsdoc\n");
1663 return E_NOTIMPL;
1666 create_nselem(This->doc, L"BLOCKQUOTE", &blockquote_elem);
1667 create_nselem(This->doc, L"P", &p_elem);
1669 nsIDOMRange_ExtractContents(This->nsrange, &fragment);
1670 nsIDOMElement_AppendChild(p_elem, (nsIDOMNode*)fragment, &tmp);
1671 nsIDOMDocumentFragment_Release(fragment);
1672 nsIDOMNode_Release(tmp);
1674 nsIDOMElement_AppendChild(blockquote_elem, (nsIDOMNode*)p_elem, &tmp);
1675 nsIDOMElement_Release(p_elem);
1676 nsIDOMNode_Release(tmp);
1678 nsIDOMRange_InsertNode(This->nsrange, (nsIDOMNode*)blockquote_elem);
1679 nsIDOMElement_Release(blockquote_elem);
1681 return S_OK;
1684 static HRESULT WINAPI RangeCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
1685 DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
1687 HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1689 TRACE("(%p)->(%s %d %x %p %p)\n", This, debugstr_guid(pguidCmdGroup), nCmdID,
1690 nCmdexecopt, pvaIn, pvaOut);
1692 if(pguidCmdGroup && IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
1693 switch(nCmdID) {
1694 case IDM_INDENT:
1695 return exec_indent(This, pvaIn, pvaOut);
1696 default:
1697 FIXME("Unsupported cmdid %d of CGID_MSHTML\n", nCmdID);
1699 }else {
1700 FIXME("Unsupported cmd %d of group %s\n", nCmdID, debugstr_guid(pguidCmdGroup));
1703 return E_NOTIMPL;
1706 static const IOleCommandTargetVtbl OleCommandTargetVtbl = {
1707 RangeCommandTarget_QueryInterface,
1708 RangeCommandTarget_AddRef,
1709 RangeCommandTarget_Release,
1710 RangeCommandTarget_QueryStatus,
1711 RangeCommandTarget_Exec
1714 static const tid_t HTMLTxtRange_iface_tids[] = {
1715 IHTMLTxtRange_tid,
1718 static dispex_static_data_t HTMLTxtRange_dispex = {
1719 NULL,
1720 IHTMLTxtRange_tid,
1721 HTMLTxtRange_iface_tids
1724 HRESULT HTMLTxtRange_Create(HTMLDocumentNode *doc, nsIDOMRange *nsrange, IHTMLTxtRange **p)
1726 HTMLTxtRange *ret;
1728 ret = heap_alloc(sizeof(HTMLTxtRange));
1729 if(!ret)
1730 return E_OUTOFMEMORY;
1732 init_dispatch(&ret->dispex, (IUnknown*)&ret->IHTMLTxtRange_iface, &HTMLTxtRange_dispex,
1733 dispex_compat_mode(&doc->node.event_target.dispex));
1735 ret->IHTMLTxtRange_iface.lpVtbl = &HTMLTxtRangeVtbl;
1736 ret->IOleCommandTarget_iface.lpVtbl = &OleCommandTargetVtbl;
1737 ret->ref = 1;
1739 if(nsrange)
1740 nsIDOMRange_AddRef(nsrange);
1741 ret->nsrange = nsrange;
1743 ret->doc = doc;
1744 list_add_head(&doc->range_list, &ret->entry);
1746 *p = &ret->IHTMLTxtRange_iface;
1747 return S_OK;
1750 static inline HTMLDOMRange *impl_from_IHTMLDOMRange(IHTMLDOMRange *iface)
1752 return CONTAINING_RECORD(iface, HTMLDOMRange, IHTMLDOMRange_iface);
1755 static HRESULT WINAPI HTMLDOMRange_QueryInterface(IHTMLDOMRange *iface, REFIID riid, void **ppv)
1757 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1759 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1761 if(IsEqualGUID(&IID_IUnknown, riid)) {
1762 *ppv = &This->IHTMLDOMRange_iface;
1763 }else if(IsEqualGUID(&IID_IHTMLDOMRange, riid)) {
1764 *ppv = &This->IHTMLDOMRange_iface;
1765 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
1766 return *ppv ? S_OK : E_NOINTERFACE;
1767 }else {
1768 *ppv = NULL;
1769 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1770 return E_NOINTERFACE;
1773 IUnknown_AddRef((IUnknown*)*ppv);
1774 return S_OK;
1777 static ULONG WINAPI HTMLDOMRange_AddRef(IHTMLDOMRange *iface)
1779 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1780 LONG ref = InterlockedIncrement(&This->ref);
1782 TRACE("(%p) ref=%d\n", This, ref);
1784 return ref;
1787 static ULONG WINAPI HTMLDOMRange_Release(IHTMLDOMRange *iface)
1789 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1790 LONG ref = InterlockedDecrement(&This->ref);
1792 TRACE("(%p) ref=%d\n", This, ref);
1794 if(!ref) {
1795 if(This->nsrange)
1796 nsIDOMRange_Release(This->nsrange);
1797 release_dispex(&This->dispex);
1798 heap_free(This);
1801 return ref;
1804 static HRESULT WINAPI HTMLDOMRange_GetTypeInfoCount(IHTMLDOMRange *iface, UINT *pctinfo)
1806 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1808 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
1811 static HRESULT WINAPI HTMLDOMRange_GetTypeInfo(IHTMLDOMRange *iface, UINT iTInfo,
1812 LCID lcid, ITypeInfo **ppTInfo)
1814 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1816 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1819 static HRESULT WINAPI HTMLDOMRange_GetIDsOfNames(IHTMLDOMRange *iface, REFIID riid,
1820 LPOLESTR *rgszNames, UINT cNames,
1821 LCID lcid, DISPID *rgDispId)
1823 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1825 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames,
1826 cNames, lcid, rgDispId);
1829 static HRESULT WINAPI HTMLDOMRange_Invoke(IHTMLDOMRange *iface, DISPID dispIdMember,
1830 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1831 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1833 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1835 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid,
1836 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1839 static HRESULT WINAPI HTMLDOMRange_get_startContainer(IHTMLDOMRange *iface, IHTMLDOMNode **p)
1841 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1842 FIXME("(%p)->(%p)\n", This, p);
1843 return E_NOTIMPL;
1846 static HRESULT WINAPI HTMLDOMRange_get_startOffset(IHTMLDOMRange *iface, LONG *p)
1848 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1849 FIXME("(%p)->(%p)\n", This, p);
1850 return E_NOTIMPL;
1853 static HRESULT WINAPI HTMLDOMRange_get_endContainer(IHTMLDOMRange *iface, IHTMLDOMNode **p)
1855 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1856 FIXME("(%p)->(%p)\n", This, p);
1857 return E_NOTIMPL;
1860 static HRESULT WINAPI HTMLDOMRange_get_endOffset(IHTMLDOMRange *iface, LONG *p)
1862 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1863 FIXME("(%p)->(%p)\n", This, p);
1864 return E_NOTIMPL;
1867 static HRESULT WINAPI HTMLDOMRange_get_collapsed(IHTMLDOMRange *iface, VARIANT_BOOL *p)
1869 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1870 FIXME("(%p)->(%p)\n", This, p);
1871 return E_NOTIMPL;
1874 static HRESULT WINAPI HTMLDOMRange_get_commonAncestorContainer(IHTMLDOMRange *iface, IHTMLDOMNode **p)
1876 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1877 FIXME("(%p)->(%p)\n", This, p);
1878 return E_NOTIMPL;
1881 static HRESULT WINAPI HTMLDOMRange_setStart(IHTMLDOMRange *iface, IDispatch *node, LONG offset)
1883 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1884 FIXME("(%p)->(%p, %d)\n", This, node, offset);
1885 return E_NOTIMPL;
1888 static HRESULT WINAPI HTMLDOMRange_setEnd(IHTMLDOMRange *iface, IDispatch *node, LONG offset)
1890 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1891 FIXME("(%p)->(%p, %d)\n", This, node, offset);
1892 return E_NOTIMPL;
1895 static HRESULT WINAPI HTMLDOMRange_setStartBefore(IHTMLDOMRange *iface, IDispatch *node)
1897 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1898 FIXME("(%p)->(%p)\n", This, node);
1899 return E_NOTIMPL;
1902 static HRESULT WINAPI HTMLDOMRange_setStartAfter(IHTMLDOMRange *iface, IDispatch *node)
1904 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1905 FIXME("(%p)->(%p)\n", This, node);
1906 return E_NOTIMPL;
1909 static HRESULT WINAPI HTMLDOMRange_setEndBefore(IHTMLDOMRange *iface, IDispatch *node)
1911 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1912 FIXME("(%p)->(%p)\n", This, node);
1913 return E_NOTIMPL;
1916 static HRESULT WINAPI HTMLDOMRange_setEndAfter(IHTMLDOMRange *iface, IDispatch *node)
1918 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1919 FIXME("(%p)->(%p)\n", This, node);
1920 return E_NOTIMPL;
1923 static HRESULT WINAPI HTMLDOMRange_collapse(IHTMLDOMRange *iface, VARIANT_BOOL tostart)
1925 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1926 FIXME("(%p)->(%x)\n", This, tostart);
1927 return E_NOTIMPL;
1930 static HRESULT WINAPI HTMLDOMRange_selectNode(IHTMLDOMRange *iface, IDispatch *node)
1932 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1933 FIXME("(%p)->(%p)\n", This, node);
1934 return E_NOTIMPL;
1937 static HRESULT WINAPI HTMLDOMRange_selectNodeContents(IHTMLDOMRange *iface, IDispatch *node)
1939 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1940 FIXME("(%p)->(%p)\n", This, node);
1941 return E_NOTIMPL;
1944 static HRESULT WINAPI HTMLDOMRange_compareBoundaryPoints(IHTMLDOMRange *iface, short how,
1945 IDispatch *src_range, LONG *result)
1947 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1948 FIXME("(%p)->(%x, %p, %p)\n", This, how, src_range, result);
1949 return E_NOTIMPL;
1952 static HRESULT WINAPI HTMLDOMRange_deleteContents(IHTMLDOMRange *iface)
1954 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1955 FIXME("(%p)\n", This);
1956 return E_NOTIMPL;
1959 static HRESULT WINAPI HTMLDOMRange_extractContents(IHTMLDOMRange *iface, IDispatch **p)
1961 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1962 FIXME("(%p)->(%p)\n", This, p);
1963 return E_NOTIMPL;
1966 static HRESULT WINAPI HTMLDOMRange_cloneContents(IHTMLDOMRange *iface, IDispatch **p)
1968 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1969 FIXME("(%p)->(%p)\n", This, p);
1970 return E_NOTIMPL;
1973 static HRESULT WINAPI HTMLDOMRange_insertNode(IHTMLDOMRange *iface, IDispatch *node)
1975 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1976 FIXME("(%p)->(%p)\n", This, node);
1977 return E_NOTIMPL;
1980 static HRESULT WINAPI HTMLDOMRange_surroundContents(IHTMLDOMRange *iface, IDispatch *parent)
1982 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1983 FIXME("(%p)->(%p)\n", This, parent);
1984 return E_NOTIMPL;
1987 static HRESULT WINAPI HTMLDOMRange_cloneRange(IHTMLDOMRange *iface, IHTMLDOMRange **p)
1989 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1990 FIXME("(%p)->(%p)\n", This, p);
1991 return E_NOTIMPL;
1994 static HRESULT WINAPI HTMLDOMRange_toString(IHTMLDOMRange *iface, BSTR *p)
1996 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1997 FIXME("(%p)->(%p)\n", This, p);
1998 return E_NOTIMPL;
2001 static HRESULT WINAPI HTMLDOMRange_detach(IHTMLDOMRange *iface)
2003 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
2004 FIXME("(%p)\n", This);
2005 return E_NOTIMPL;
2008 static HRESULT WINAPI HTMLDOMRange_getClientRects(IHTMLDOMRange *iface, IHTMLRectCollection **p)
2010 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
2011 FIXME("(%p)->(%p)\n", This, p);
2012 return E_NOTIMPL;
2015 static HRESULT WINAPI HTMLDOMRange_getBoundingClientRect(IHTMLDOMRange *iface, IHTMLRect **p)
2017 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
2018 FIXME("(%p)->(%p)\n", This, p);
2019 return E_NOTIMPL;
2022 static const IHTMLDOMRangeVtbl HTMLDOMRangeVtbl = {
2023 HTMLDOMRange_QueryInterface,
2024 HTMLDOMRange_AddRef,
2025 HTMLDOMRange_Release,
2026 HTMLDOMRange_GetTypeInfoCount,
2027 HTMLDOMRange_GetTypeInfo,
2028 HTMLDOMRange_GetIDsOfNames,
2029 HTMLDOMRange_Invoke,
2030 HTMLDOMRange_get_startContainer,
2031 HTMLDOMRange_get_startOffset,
2032 HTMLDOMRange_get_endContainer,
2033 HTMLDOMRange_get_endOffset,
2034 HTMLDOMRange_get_collapsed,
2035 HTMLDOMRange_get_commonAncestorContainer,
2036 HTMLDOMRange_setStart,
2037 HTMLDOMRange_setEnd,
2038 HTMLDOMRange_setStartBefore,
2039 HTMLDOMRange_setStartAfter,
2040 HTMLDOMRange_setEndBefore,
2041 HTMLDOMRange_setEndAfter,
2042 HTMLDOMRange_collapse,
2043 HTMLDOMRange_selectNode,
2044 HTMLDOMRange_selectNodeContents,
2045 HTMLDOMRange_compareBoundaryPoints,
2046 HTMLDOMRange_deleteContents,
2047 HTMLDOMRange_extractContents,
2048 HTMLDOMRange_cloneContents,
2049 HTMLDOMRange_insertNode,
2050 HTMLDOMRange_surroundContents,
2051 HTMLDOMRange_cloneRange,
2052 HTMLDOMRange_toString,
2053 HTMLDOMRange_detach,
2054 HTMLDOMRange_getClientRects,
2055 HTMLDOMRange_getBoundingClientRect,
2058 static const tid_t HTMLDOMRange_iface_tids[] = {
2059 IHTMLDOMRange_tid,
2063 static dispex_static_data_t HTMLDOMRange_dispex = {
2064 NULL,
2065 DispHTMLDOMRange_tid,
2066 HTMLDOMRange_iface_tids
2069 HRESULT create_dom_range(nsIDOMRange *nsrange, compat_mode_t compat_mode, IHTMLDOMRange **p)
2071 HTMLDOMRange *ret;
2073 ret = heap_alloc(sizeof(*ret));
2074 if(!ret)
2075 return E_OUTOFMEMORY;
2077 init_dispatch(&ret->dispex, (IUnknown*)&ret->IHTMLDOMRange_iface, &HTMLDOMRange_dispex, compat_mode);
2079 ret->IHTMLDOMRange_iface.lpVtbl = &HTMLDOMRangeVtbl;
2080 ret->ref = 1;
2082 if(nsrange)
2083 nsIDOMRange_AddRef(nsrange);
2084 ret->nsrange = nsrange;
2086 *p = &ret->IHTMLDOMRange_iface;
2087 return S_OK;
2090 void detach_ranges(HTMLDocumentNode *This)
2092 HTMLTxtRange *iter, *next;
2094 LIST_FOR_EACH_ENTRY_SAFE(iter, next, &This->range_list, HTMLTxtRange, entry) {
2095 iter->doc = NULL;
2096 list_remove(&iter->entry);
2100 typedef struct {
2101 IMarkupPointer2 IMarkupPointer2_iface;
2102 LONG ref;
2103 } MarkupPointer;
2105 static inline MarkupPointer *impl_from_IMarkupPointer2(IMarkupPointer2 *iface)
2107 return CONTAINING_RECORD(iface, MarkupPointer, IMarkupPointer2_iface);
2110 static HRESULT WINAPI MarkupPointer2_QueryInterface(IMarkupPointer2 *iface, REFIID riid, void **ppv)
2112 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2114 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
2116 if(IsEqualGUID(&IID_IUnknown, riid)) {
2117 *ppv = &This->IMarkupPointer2_iface;
2118 }else if(IsEqualGUID(&IID_IMarkupPointer, riid)) {
2119 *ppv = &This->IMarkupPointer2_iface;
2120 }else if(IsEqualGUID(&IID_IMarkupPointer2, riid)) {
2121 *ppv = &This->IMarkupPointer2_iface;
2122 }else {
2123 *ppv = NULL;
2124 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
2125 return E_NOINTERFACE;
2128 IUnknown_AddRef((IUnknown*)*ppv);
2129 return S_OK;
2132 static ULONG WINAPI MarkupPointer2_AddRef(IMarkupPointer2 *iface)
2134 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2135 LONG ref = InterlockedIncrement(&This->ref);
2137 TRACE("(%p) ref=%d\n", This, ref);
2139 return ref;
2142 static ULONG WINAPI MarkupPointer2_Release(IMarkupPointer2 *iface)
2144 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2145 LONG ref = InterlockedDecrement(&This->ref);
2147 TRACE("(%p) ref=%d\n", This, ref);
2149 if(!ref)
2150 heap_free(This);
2152 return ref;
2155 static HRESULT WINAPI MarkupPointer2_OwningDoc(IMarkupPointer2 *iface, IHTMLDocument2 **p)
2157 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2158 FIXME("(%p)->(%p)\n", This, p);
2159 return E_NOTIMPL;
2162 static HRESULT WINAPI MarkupPointer2_Gravity(IMarkupPointer2 *iface, POINTER_GRAVITY *p)
2164 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2165 FIXME("(%p)->(%p)\n", This, p);
2166 return E_NOTIMPL;
2169 static HRESULT WINAPI MarkupPointer2_SetGravity(IMarkupPointer2 *iface, POINTER_GRAVITY gravity)
2171 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2172 FIXME("(%p)->(%u)\n", This, gravity);
2173 return E_NOTIMPL;
2176 static HRESULT WINAPI MarkupPointer2_Cling(IMarkupPointer2 *iface, BOOL *p)
2178 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2179 FIXME("(%p)->(%p)\n", This, p);
2180 return E_NOTIMPL;
2183 static HRESULT WINAPI MarkupPointer2_SetCling(IMarkupPointer2 *iface, BOOL cling)
2185 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2186 FIXME("(%p)->(%x)\n", This, cling);
2187 return E_NOTIMPL;
2190 static HRESULT WINAPI MarkupPointer2_Unposition(IMarkupPointer2 *iface)
2192 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2193 FIXME("(%p)\n", This);
2194 return E_NOTIMPL;
2197 static HRESULT WINAPI MarkupPointer2_IsPositioned(IMarkupPointer2 *iface, BOOL *p)
2199 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2200 FIXME("(%p)->(%p)\n", This, p);
2201 return E_NOTIMPL;
2204 static HRESULT WINAPI MarkupPointer2_GetContainer(IMarkupPointer2 *iface, IMarkupContainer **p)
2206 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2207 FIXME("(%p)->(%p)\n", This, p);
2208 return E_NOTIMPL;
2211 static HRESULT WINAPI MarkupPointer2_MoveAdjacentToElement(IMarkupPointer2 *iface, IHTMLElement *element, ELEMENT_ADJACENCY adj)
2213 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2214 FIXME("(%p)->(%p %u)\n", This, element, adj);
2215 return E_NOTIMPL;
2218 static HRESULT WINAPI MarkupPointer2_MoveToPointer(IMarkupPointer2 *iface, IMarkupPointer *pointer)
2220 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2221 FIXME("(%p)->(%p)\n", This, pointer);
2222 return E_NOTIMPL;
2225 static HRESULT WINAPI MarkupPointer2_MoveToContainer(IMarkupPointer2 *iface, IMarkupContainer *container, BOOL at_start)
2227 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2228 FIXME("(%p)->(%p %x)\n", This, container, at_start);
2229 return E_NOTIMPL;
2232 static HRESULT WINAPI MarkupPointer2_Left(IMarkupPointer2 *iface, BOOL move, MARKUP_CONTEXT_TYPE *context,
2233 IHTMLElement **element, LONG *len, OLECHAR *text)
2235 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2236 FIXME("(%p)->(%x %p %p %p %p)\n", This, move, context, element, len, text);
2237 return E_NOTIMPL;
2240 static HRESULT WINAPI MarkupPointer2_Right(IMarkupPointer2 *iface, BOOL move, MARKUP_CONTEXT_TYPE *context,
2241 IHTMLElement **element, LONG *len, OLECHAR *text)
2243 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2244 FIXME("(%p)->(%x %p %p %p %p)\n", This, move, context, element, len, text);
2245 return E_NOTIMPL;
2248 static HRESULT WINAPI MarkupPointer2_CurrentScope(IMarkupPointer2 *iface, IHTMLElement **p)
2250 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2251 FIXME("(%p)->(%p)\n", This, p);
2252 return E_NOTIMPL;
2255 static HRESULT WINAPI MarkupPointer2_IsLeftOf(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2257 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2258 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2259 return E_NOTIMPL;
2262 static HRESULT WINAPI MarkupPointer2_IsLeftOfOrEqualTo(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2264 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2265 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2266 return E_NOTIMPL;
2269 static HRESULT WINAPI MarkupPointer2_IsRightOf(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2271 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2272 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2273 return E_NOTIMPL;
2276 static HRESULT WINAPI MarkupPointer2_IsRightOfOrEqualTo(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2278 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2279 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2280 return E_NOTIMPL;
2283 static HRESULT WINAPI MarkupPointer2_IsEqualTo(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2285 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2286 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2287 return E_NOTIMPL;
2290 static HRESULT WINAPI MarkupPointer2_MoveUnit(IMarkupPointer2 *iface, MOVEUNIT_ACTION action)
2292 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2293 FIXME("(%p)->(%u)\n", This, action);
2294 return E_NOTIMPL;
2297 static HRESULT WINAPI MarkupPointer2_FindText(IMarkupPointer2 *iface, OLECHAR *text, DWORD flags,
2298 IMarkupPointer *end_match, IMarkupPointer *end_search)
2300 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2301 FIXME("(%p)->(%s %x %p %p)\n", This, debugstr_w(text), flags, end_match, end_search);
2302 return E_NOTIMPL;
2305 static HRESULT WINAPI MarkupPointer2_IsAtWordBreak(IMarkupPointer2 *iface, BOOL *p)
2307 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2308 FIXME("(%p)->(%p)\n", This, p);
2309 return E_NOTIMPL;
2312 static HRESULT WINAPI MarkupPointer2_GetMarkupPosition(IMarkupPointer2 *iface, LONG *p)
2314 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2315 FIXME("(%p)->(%p)\n", This, p);
2316 return E_NOTIMPL;
2319 static HRESULT WINAPI MarkupPointer2_MoveToMarkupPosition(IMarkupPointer2 *iface, IMarkupContainer *container, LONG mp)
2321 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2322 FIXME("(%p)->(%p %d)\n", This, container, mp);
2323 return E_NOTIMPL;
2326 static HRESULT WINAPI MarkupPointer2_MoveUnitBounded(IMarkupPointer2 *iface, MOVEUNIT_ACTION action, IMarkupPointer *boundary)
2328 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2329 FIXME("(%p)->(%u %p)\n", This, action, boundary);
2330 return E_NOTIMPL;
2333 static HRESULT WINAPI MarkupPointer2_IsInsideURL(IMarkupPointer2 *iface, IMarkupPointer *right, BOOL *p)
2335 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2336 FIXME("(%p)->(%p %p)\n", This, right, p);
2337 return E_NOTIMPL;
2340 static HRESULT WINAPI MarkupPointer2_MoveToContent(IMarkupPointer2 *iface, IHTMLElement *element, BOOL at_start)
2342 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2343 FIXME("(%p)->(%p %x)\n", This, element, at_start);
2344 return E_NOTIMPL;
2347 static const IMarkupPointer2Vtbl MarkupPointer2Vtbl = {
2348 MarkupPointer2_QueryInterface,
2349 MarkupPointer2_AddRef,
2350 MarkupPointer2_Release,
2351 MarkupPointer2_OwningDoc,
2352 MarkupPointer2_Gravity,
2353 MarkupPointer2_SetGravity,
2354 MarkupPointer2_Cling,
2355 MarkupPointer2_SetCling,
2356 MarkupPointer2_Unposition,
2357 MarkupPointer2_IsPositioned,
2358 MarkupPointer2_GetContainer,
2359 MarkupPointer2_MoveAdjacentToElement,
2360 MarkupPointer2_MoveToPointer,
2361 MarkupPointer2_MoveToContainer,
2362 MarkupPointer2_Left,
2363 MarkupPointer2_Right,
2364 MarkupPointer2_CurrentScope,
2365 MarkupPointer2_IsLeftOf,
2366 MarkupPointer2_IsLeftOfOrEqualTo,
2367 MarkupPointer2_IsRightOf,
2368 MarkupPointer2_IsRightOfOrEqualTo,
2369 MarkupPointer2_IsEqualTo,
2370 MarkupPointer2_MoveUnit,
2371 MarkupPointer2_FindText,
2372 MarkupPointer2_IsAtWordBreak,
2373 MarkupPointer2_GetMarkupPosition,
2374 MarkupPointer2_MoveToMarkupPosition,
2375 MarkupPointer2_MoveUnitBounded,
2376 MarkupPointer2_IsInsideURL,
2377 MarkupPointer2_MoveToContent
2380 HRESULT create_markup_pointer(IMarkupPointer **ret)
2382 MarkupPointer *markup_pointer;
2384 if(!(markup_pointer = heap_alloc(sizeof(*markup_pointer))))
2385 return E_OUTOFMEMORY;
2387 markup_pointer->IMarkupPointer2_iface.lpVtbl = &MarkupPointer2Vtbl;
2388 markup_pointer->ref = 1;
2390 *ret = (IMarkupPointer*)&markup_pointer->IMarkupPointer2_iface;
2391 return S_OK;