xinput1_3/tests: Add some HID report tests.
[wine.git] / dlls / mshtml / range.c
blob89f68046a337df9330b81646e61908433743e9bb
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>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "ole2.h"
27 #include "mshtmcid.h"
29 #include "wine/debug.h"
31 #include "mshtml_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
35 typedef struct {
36 DispatchEx dispex;
37 IHTMLTxtRange IHTMLTxtRange_iface;
38 IOleCommandTarget IOleCommandTarget_iface;
40 LONG ref;
42 nsIDOMRange *nsrange;
43 HTMLDocumentNode *doc;
45 struct list entry;
46 } HTMLTxtRange;
48 typedef struct {
49 DispatchEx dispex;
50 IHTMLDOMRange IHTMLDOMRange_iface;
52 LONG ref;
54 nsIDOMRange *nsrange;
55 } HTMLDOMRange;
57 typedef struct {
58 WCHAR *buf;
59 DWORD len;
60 DWORD size;
61 } wstrbuf_t;
63 typedef struct {
64 UINT16 type;
65 nsIDOMNode *node;
66 UINT32 off;
67 } rangepoint_t;
69 typedef enum {
70 RU_UNKNOWN,
71 RU_CHAR,
72 RU_WORD,
73 RU_SENTENCE,
74 RU_TEXTEDIT
75 } range_unit_t;
77 static HTMLTxtRange *get_range_object(HTMLDocumentNode *doc, IHTMLTxtRange *iface)
79 HTMLTxtRange *iter;
81 LIST_FOR_EACH_ENTRY(iter, &doc->range_list, HTMLTxtRange, entry) {
82 if(&iter->IHTMLTxtRange_iface == iface)
83 return iter;
86 ERR("Could not find range in document\n");
87 return NULL;
90 static range_unit_t string_to_unit(LPCWSTR str)
92 if(!wcsicmp(str, L"character")) return RU_CHAR;
93 if(!wcsicmp(str, L"word")) return RU_WORD;
94 if(!wcsicmp(str, L"sentence")) return RU_SENTENCE;
95 if(!wcsicmp(str, L"textedit")) return RU_TEXTEDIT;
97 return RU_UNKNOWN;
100 static int string_to_nscmptype(LPCWSTR str)
102 if(!wcsicmp(str, L"StartToEnd")) return NS_START_TO_END;
103 if(!wcsicmp(str, L"StartToStart")) return NS_START_TO_START;
104 if(!wcsicmp(str, L"EndToStart")) return NS_END_TO_START;
105 if(!wcsicmp(str, L"EndToEnd")) return NS_END_TO_END;
107 return -1;
110 static UINT16 get_node_type(nsIDOMNode *node)
112 UINT16 type = 0;
114 if(node)
115 nsIDOMNode_GetNodeType(node, &type);
117 return type;
120 static void get_text_node_data(nsIDOMNode *node, nsAString *nsstr, const PRUnichar **str)
122 nsIDOMText *nstext;
123 nsresult nsres;
125 nsres = nsIDOMNode_QueryInterface(node, &IID_nsIDOMText, (void**)&nstext);
126 assert(nsres == NS_OK);
128 nsAString_Init(nsstr, NULL);
129 nsres = nsIDOMText_GetData(nstext, nsstr);
130 nsIDOMText_Release(nstext);
131 if(NS_FAILED(nsres))
132 ERR("GetData failed: %08x\n", nsres);
134 nsAString_GetData(nsstr, str);
137 static nsIDOMNode *get_child_node(nsIDOMNode *node, UINT32 off)
139 nsIDOMNodeList *node_list;
140 nsIDOMNode *ret = NULL;
142 nsIDOMNode_GetChildNodes(node, &node_list);
143 nsIDOMNodeList_Item(node_list, off, &ret);
144 nsIDOMNodeList_Release(node_list);
146 return ret;
149 /* This is very inefficient, but there is no faster way to compute index in
150 * child node list using public API. Gecko has internal nsINode::IndexOf
151 * function that we could consider exporting and use instead. */
152 static int get_child_index(nsIDOMNode *parent, nsIDOMNode *child)
154 nsIDOMNodeList *node_list;
155 nsIDOMNode *node;
156 int ret = 0;
157 nsresult nsres;
159 nsres = nsIDOMNode_GetChildNodes(parent, &node_list);
160 assert(nsres == NS_OK);
162 while(1) {
163 nsres = nsIDOMNodeList_Item(node_list, ret, &node);
164 assert(nsres == NS_OK && node);
165 if(node == child) {
166 nsIDOMNode_Release(node);
167 break;
169 nsIDOMNode_Release(node);
170 ret++;
173 nsIDOMNodeList_Release(node_list);
174 return ret;
177 static void init_rangepoint(rangepoint_t *rangepoint, nsIDOMNode *node, UINT32 off)
179 nsIDOMNode_AddRef(node);
181 rangepoint->type = get_node_type(node);
182 rangepoint->node = node;
183 rangepoint->off = off;
186 static inline void free_rangepoint(rangepoint_t *rangepoint)
188 nsIDOMNode_Release(rangepoint->node);
191 static inline BOOL rangepoint_cmp(const rangepoint_t *point1, const rangepoint_t *point2)
193 return point1->node == point2->node && point1->off == point2->off;
196 static BOOL rangepoint_next_node(rangepoint_t *iter)
198 nsIDOMNode *node;
199 UINT32 off;
200 nsresult nsres;
202 /* Try to move to the child node. */
203 node = get_child_node(iter->node, iter->off);
204 if(node) {
205 free_rangepoint(iter);
206 init_rangepoint(iter, node, 0);
207 nsIDOMNode_Release(node);
208 return TRUE;
211 /* There are no more children in the node. Move to parent. */
212 nsres = nsIDOMNode_GetParentNode(iter->node, &node);
213 assert(nsres == NS_OK);
214 if(!node)
215 return FALSE;
217 off = get_child_index(node, iter->node)+1;
218 free_rangepoint(iter);
219 init_rangepoint(iter, node, off);
220 nsIDOMNode_Release(node);
221 return TRUE;
224 static UINT32 get_child_count(nsIDOMNode *node)
226 nsIDOMNodeList *node_list;
227 UINT32 ret;
228 nsresult nsres;
230 nsres = nsIDOMNode_GetChildNodes(node, &node_list);
231 assert(nsres == NS_OK);
233 nsres = nsIDOMNodeList_GetLength(node_list, &ret);
234 nsIDOMNodeList_Release(node_list);
235 assert(nsres == NS_OK);
237 return ret;
240 static UINT32 get_text_length(nsIDOMNode *node)
242 nsIDOMText *nstext;
243 UINT32 ret;
244 nsresult nsres;
246 nsres = nsIDOMNode_QueryInterface(node, &IID_nsIDOMText, (void**)&nstext);
247 assert(nsres == NS_OK);
249 nsres = nsIDOMText_GetLength(nstext, &ret);
250 nsIDOMText_Release(nstext);
251 assert(nsres == NS_OK);
253 return ret;
256 static BOOL rangepoint_prev_node(rangepoint_t *iter)
258 nsIDOMNode *node;
259 UINT32 off;
260 nsresult nsres;
262 /* Try to move to the child node. */
263 if(iter->off) {
264 node = get_child_node(iter->node, iter->off-1);
265 assert(node != NULL);
267 off = get_node_type(node) == TEXT_NODE ? get_text_length(node) : get_child_count(node);
268 free_rangepoint(iter);
269 init_rangepoint(iter, node, off);
270 nsIDOMNode_Release(node);
271 return TRUE;
274 /* There are no more children in the node. Move to parent. */
275 nsres = nsIDOMNode_GetParentNode(iter->node, &node);
276 assert(nsres == NS_OK);
277 if(!node)
278 return FALSE;
280 off = get_child_index(node, iter->node);
281 free_rangepoint(iter);
282 init_rangepoint(iter, node, off);
283 return TRUE;
286 static void get_start_point(HTMLTxtRange *This, rangepoint_t *ret)
288 nsIDOMNode *node;
289 LONG off;
291 nsIDOMRange_GetStartContainer(This->nsrange, &node);
292 nsIDOMRange_GetStartOffset(This->nsrange, &off);
294 init_rangepoint(ret, node, off);
296 nsIDOMNode_Release(node);
299 static void get_end_point(HTMLTxtRange *This, rangepoint_t *ret)
301 nsIDOMNode *node;
302 LONG off;
304 nsIDOMRange_GetEndContainer(This->nsrange, &node);
305 nsIDOMRange_GetEndOffset(This->nsrange, &off);
307 init_rangepoint(ret, node, off);
309 nsIDOMNode_Release(node);
312 static void set_start_point(HTMLTxtRange *This, const rangepoint_t *start)
314 nsresult nsres = nsIDOMRange_SetStart(This->nsrange, start->node, start->off);
315 if(NS_FAILED(nsres))
316 ERR("failed: %08x\n", nsres);
319 static void set_end_point(HTMLTxtRange *This, const rangepoint_t *end)
321 nsresult nsres = nsIDOMRange_SetEnd(This->nsrange, end->node, end->off);
322 if(NS_FAILED(nsres))
323 ERR("failed: %08x\n", nsres);
326 static BOOL is_elem_tag(nsIDOMNode *node, LPCWSTR istag)
328 nsIDOMElement *elem;
329 nsAString tag_str;
330 const PRUnichar *tag;
331 BOOL ret = FALSE;
332 nsresult nsres;
334 nsres = nsIDOMNode_QueryInterface(node, &IID_nsIDOMElement, (void**)&elem);
335 if(NS_FAILED(nsres))
336 return FALSE;
338 nsAString_Init(&tag_str, NULL);
339 nsIDOMElement_GetTagName(elem, &tag_str);
340 nsIDOMElement_Release(elem);
341 nsAString_GetData(&tag_str, &tag);
343 ret = !wcsicmp(tag, istag);
345 nsAString_Finish(&tag_str);
347 return ret;
350 static inline BOOL wstrbuf_init(wstrbuf_t *buf)
352 buf->len = 0;
353 buf->size = 16;
354 buf->buf = heap_alloc(buf->size * sizeof(WCHAR));
355 if (!buf->buf) return FALSE;
356 *buf->buf = 0;
357 return TRUE;
360 static inline void wstrbuf_finish(wstrbuf_t *buf)
362 heap_free(buf->buf);
365 static void wstrbuf_append_len(wstrbuf_t *buf, LPCWSTR str, int len)
367 if(buf->len+len >= buf->size) {
368 buf->size = 2*buf->size+len;
369 buf->buf = heap_realloc(buf->buf, buf->size * sizeof(WCHAR));
372 memcpy(buf->buf+buf->len, str, len*sizeof(WCHAR));
373 buf->len += len;
374 buf->buf[buf->len] = 0;
377 static void wstrbuf_append_nodetxt(wstrbuf_t *buf, LPCWSTR str, int len)
379 const WCHAR *s = str;
380 WCHAR *d;
382 TRACE("%s\n", debugstr_wn(str, len));
384 if(buf->len+len >= buf->size) {
385 buf->size = 2*buf->size+len;
386 buf->buf = heap_realloc(buf->buf, buf->size * sizeof(WCHAR));
389 if(buf->len && iswspace(buf->buf[buf->len-1])) {
390 while(s < str+len && iswspace(*s))
391 s++;
394 d = buf->buf+buf->len;
395 while(s < str+len) {
396 if(iswspace(*s)) {
397 *d++ = ' ';
398 s++;
399 while(s < str+len && iswspace(*s))
400 s++;
401 }else {
402 *d++ = *s++;
406 buf->len = d - buf->buf;
407 *d = 0;
410 static void wstrbuf_append_node(wstrbuf_t *buf, nsIDOMNode *node, BOOL ignore_text)
413 switch(get_node_type(node)) {
414 case TEXT_NODE: {
415 nsIDOMText *nstext;
416 nsAString data_str;
417 const PRUnichar *data;
419 if(ignore_text)
420 break;
422 nsIDOMNode_QueryInterface(node, &IID_nsIDOMText, (void**)&nstext);
424 nsAString_Init(&data_str, NULL);
425 nsIDOMText_GetData(nstext, &data_str);
426 nsAString_GetData(&data_str, &data);
427 wstrbuf_append_nodetxt(buf, data, lstrlenW(data));
428 nsAString_Finish(&data_str);
430 nsIDOMText_Release(nstext);
432 break;
434 case ELEMENT_NODE:
435 if(is_elem_tag(node, L"br")) {
436 static const WCHAR endlW[] = {'\r','\n'};
437 wstrbuf_append_len(buf, endlW, 2);
438 }else if(is_elem_tag(node, L"hr")) {
439 static const WCHAR endl2W[] = {'\r','\n','\r','\n'};
440 wstrbuf_append_len(buf, endl2W, 4);
445 static void wstrbuf_append_node_rec(wstrbuf_t *buf, nsIDOMNode *node)
447 nsIDOMNode *iter, *tmp;
449 wstrbuf_append_node(buf, node, FALSE);
451 nsIDOMNode_GetFirstChild(node, &iter);
452 while(iter) {
453 wstrbuf_append_node_rec(buf, iter);
454 nsIDOMNode_GetNextSibling(iter, &tmp);
455 nsIDOMNode_Release(iter);
456 iter = tmp;
460 static void range_to_string(HTMLTxtRange *This, wstrbuf_t *buf)
462 rangepoint_t end_pos, iter;
463 cpp_bool collapsed;
465 nsIDOMRange_GetCollapsed(This->nsrange, &collapsed);
466 if(collapsed) {
467 wstrbuf_finish(buf);
468 buf->buf = NULL;
469 buf->size = 0;
470 return;
473 get_end_point(This, &end_pos);
474 get_start_point(This, &iter);
476 do {
477 if(iter.type == TEXT_NODE) {
478 const PRUnichar *str;
479 nsAString nsstr;
481 get_text_node_data(iter.node, &nsstr, &str);
483 if(iter.node == end_pos.node) {
484 wstrbuf_append_nodetxt(buf, str+iter.off, end_pos.off-iter.off);
485 nsAString_Finish(&nsstr);
486 break;
489 wstrbuf_append_nodetxt(buf, str+iter.off, lstrlenW(str+iter.off));
490 nsAString_Finish(&nsstr);
491 }else {
492 nsIDOMNode *node;
494 node = get_child_node(iter.node, iter.off);
495 if(node) {
496 wstrbuf_append_node(buf, node, TRUE);
497 nsIDOMNode_Release(node);
501 if(!rangepoint_next_node(&iter)) {
502 ERR("End of document?\n");
503 break;
505 }while(!rangepoint_cmp(&iter, &end_pos));
507 free_rangepoint(&iter);
508 free_rangepoint(&end_pos);
510 if(buf->len) {
511 WCHAR *p;
513 for(p = buf->buf+buf->len-1; p >= buf->buf && iswspace(*p); p--);
515 p = wcschr(p, '\r');
516 if(p)
517 *p = 0;
521 HRESULT get_node_text(HTMLDOMNode *node, BSTR *ret)
523 wstrbuf_t buf;
524 HRESULT hres = S_OK;
526 if (!wstrbuf_init(&buf))
527 return E_OUTOFMEMORY;
528 wstrbuf_append_node_rec(&buf, node->nsnode);
529 if(buf.buf && *buf.buf) {
530 *ret = SysAllocString(buf.buf);
531 if(!*ret)
532 hres = E_OUTOFMEMORY;
533 } else {
534 *ret = NULL;
536 wstrbuf_finish(&buf);
538 if(SUCCEEDED(hres))
539 TRACE("ret %s\n", debugstr_w(*ret));
540 return hres;
543 static WCHAR move_next_char(rangepoint_t *iter)
545 rangepoint_t last_space;
546 nsIDOMNode *node;
547 WCHAR cspace = 0;
548 const WCHAR *p;
550 do {
551 switch(iter->type) {
552 case TEXT_NODE: {
553 const PRUnichar *str;
554 nsAString nsstr;
555 WCHAR c;
557 get_text_node_data(iter->node, &nsstr, &str);
558 p = str+iter->off;
559 if(!*p) {
560 nsAString_Finish(&nsstr);
561 break;
564 c = *p;
565 if(iswspace(c)) {
566 while(iswspace(*p))
567 p++;
569 if(cspace)
570 free_rangepoint(&last_space);
571 else
572 cspace = ' ';
574 iter->off = p-str;
575 c = *p;
576 nsAString_Finish(&nsstr);
577 if(!c) { /* continue to skip spaces */
578 init_rangepoint(&last_space, iter->node, iter->off);
579 break;
582 return cspace;
583 }else {
584 nsAString_Finish(&nsstr);
587 /* If we have a non-space char and we're skipping spaces, stop and return the last found space. */
588 if(cspace) {
589 free_rangepoint(iter);
590 *iter = last_space;
591 return cspace;
594 iter->off++;
595 return c;
597 case ELEMENT_NODE:
598 node = get_child_node(iter->node, iter->off);
599 if(!node)
600 break;
602 if(is_elem_tag(node, L"br")) {
603 if(cspace) {
604 nsIDOMNode_Release(node);
605 free_rangepoint(iter);
606 *iter = last_space;
607 return cspace;
610 cspace = '\n';
611 init_rangepoint(&last_space, iter->node, iter->off+1);
612 }else if(is_elem_tag(node, L"hr")) {
613 nsIDOMNode_Release(node);
614 if(cspace) {
615 free_rangepoint(iter);
616 *iter = last_space;
617 return cspace;
620 iter->off++;
621 return '\n';
624 nsIDOMNode_Release(node);
626 }while(rangepoint_next_node(iter));
628 return cspace;
631 static WCHAR move_prev_char(rangepoint_t *iter)
633 rangepoint_t last_space;
634 nsIDOMNode *node;
635 WCHAR cspace = 0;
636 const WCHAR *p;
638 do {
639 switch(iter->type) {
640 case TEXT_NODE: {
641 const PRUnichar *str;
642 nsAString nsstr;
643 WCHAR c;
645 if(!iter->off)
646 break;
648 get_text_node_data(iter->node, &nsstr, &str);
650 p = str+iter->off-1;
651 c = *p;
653 if(iswspace(c)) {
654 while(p > str && iswspace(*(p-1)))
655 p--;
657 if(cspace)
658 free_rangepoint(&last_space);
659 else
660 cspace = ' ';
662 iter->off = p-str;
663 nsAString_Finish(&nsstr);
664 if(p == str) { /* continue to skip spaces */
665 init_rangepoint(&last_space, iter->node, iter->off);
666 break;
669 return cspace;
670 }else {
671 nsAString_Finish(&nsstr);
674 /* If we have a non-space char and we're skipping spaces, stop and return the last found space. */
675 if(cspace) {
676 free_rangepoint(iter);
677 *iter = last_space;
678 return cspace;
681 iter->off--;
682 return c;
684 case ELEMENT_NODE:
685 if(!iter->off)
686 break;
688 node = get_child_node(iter->node, iter->off-1);
689 if(!node)
690 break;
692 if(is_elem_tag(node, L"br")) {
693 if(cspace)
694 free_rangepoint(&last_space);
695 cspace = '\n';
696 init_rangepoint(&last_space, iter->node, iter->off-1);
697 }else if(is_elem_tag(node, L"hr")) {
698 nsIDOMNode_Release(node);
699 if(cspace) {
700 free_rangepoint(iter);
701 *iter = last_space;
702 return cspace;
705 iter->off--;
706 return '\n';
709 nsIDOMNode_Release(node);
711 }while(rangepoint_prev_node(iter));
713 if(cspace) {
714 free_rangepoint(iter);
715 *iter = last_space;
716 return cspace;
719 return 0;
722 static LONG move_by_chars(rangepoint_t *iter, LONG cnt)
724 LONG ret = 0;
726 if(cnt >= 0) {
727 while(ret < cnt && move_next_char(iter))
728 ret++;
729 }else {
730 while(ret > cnt && move_prev_char(iter))
731 ret--;
734 return ret;
737 static LONG find_prev_space(rangepoint_t *iter, BOOL first_space)
739 rangepoint_t prev;
740 WCHAR c;
742 init_rangepoint(&prev, iter->node, iter->off);
743 c = move_prev_char(&prev);
744 if(!c || (first_space && iswspace(c)))
745 return FALSE;
747 do {
748 free_rangepoint(iter);
749 init_rangepoint(iter, prev.node, prev.off);
750 c = move_prev_char(&prev);
751 }while(c && !iswspace(c));
753 free_rangepoint(&prev);
754 return TRUE;
757 static BOOL find_word_end(rangepoint_t *iter, BOOL is_collapsed)
759 rangepoint_t prev_iter;
760 WCHAR c;
761 BOOL ret = FALSE;
763 if(!is_collapsed) {
764 init_rangepoint(&prev_iter, iter->node, iter->off);
765 c = move_prev_char(&prev_iter);
766 free_rangepoint(&prev_iter);
767 if(iswspace(c))
768 return FALSE;
771 do {
772 init_rangepoint(&prev_iter, iter->node, iter->off);
773 c = move_next_char(iter);
774 if(c == '\n') {
775 free_rangepoint(iter);
776 *iter = prev_iter;
777 return ret;
779 if(!c) {
780 if(!ret)
781 ret = !rangepoint_cmp(iter, &prev_iter);
782 }else {
783 ret = TRUE;
785 free_rangepoint(&prev_iter);
786 }while(c && !iswspace(c));
788 return ret;
791 static LONG move_by_words(rangepoint_t *iter, LONG cnt)
793 LONG ret = 0;
795 if(cnt >= 0) {
796 WCHAR c;
798 while(ret < cnt && (c = move_next_char(iter))) {
799 if(iswspace(c))
800 ret++;
802 }else {
803 while(ret > cnt && find_prev_space(iter, FALSE))
804 ret--;
807 return ret;
810 static inline HTMLTxtRange *impl_from_IHTMLTxtRange(IHTMLTxtRange *iface)
812 return CONTAINING_RECORD(iface, HTMLTxtRange, IHTMLTxtRange_iface);
815 static HRESULT WINAPI HTMLTxtRange_QueryInterface(IHTMLTxtRange *iface, REFIID riid, void **ppv)
817 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
819 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
821 if(IsEqualGUID(&IID_IUnknown, riid)) {
822 *ppv = &This->IHTMLTxtRange_iface;
823 }else if(IsEqualGUID(&IID_IHTMLTxtRange, riid)) {
824 *ppv = &This->IHTMLTxtRange_iface;
825 }else if(IsEqualGUID(&IID_IOleCommandTarget, riid)) {
826 *ppv = &This->IOleCommandTarget_iface;
827 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
828 return *ppv ? S_OK : E_NOINTERFACE;
829 }else {
830 *ppv = NULL;
831 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
832 return E_NOINTERFACE;
835 IUnknown_AddRef((IUnknown*)*ppv);
836 return S_OK;
839 static ULONG WINAPI HTMLTxtRange_AddRef(IHTMLTxtRange *iface)
841 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
842 LONG ref = InterlockedIncrement(&This->ref);
844 TRACE("(%p) ref=%d\n", This, ref);
846 return ref;
849 static ULONG WINAPI HTMLTxtRange_Release(IHTMLTxtRange *iface)
851 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
852 LONG ref = InterlockedDecrement(&This->ref);
854 TRACE("(%p) ref=%d\n", This, ref);
856 if(!ref) {
857 if(This->nsrange)
858 nsIDOMRange_Release(This->nsrange);
859 if(This->doc)
860 list_remove(&This->entry);
861 release_dispex(&This->dispex);
862 heap_free(This);
865 return ref;
868 static HRESULT WINAPI HTMLTxtRange_GetTypeInfoCount(IHTMLTxtRange *iface, UINT *pctinfo)
870 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
872 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
875 static HRESULT WINAPI HTMLTxtRange_GetTypeInfo(IHTMLTxtRange *iface, UINT iTInfo,
876 LCID lcid, ITypeInfo **ppTInfo)
878 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
880 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
883 static HRESULT WINAPI HTMLTxtRange_GetIDsOfNames(IHTMLTxtRange *iface, REFIID riid,
884 LPOLESTR *rgszNames, UINT cNames,
885 LCID lcid, DISPID *rgDispId)
887 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
889 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames,
890 cNames, lcid, rgDispId);
893 static HRESULT WINAPI HTMLTxtRange_Invoke(IHTMLTxtRange *iface, DISPID dispIdMember,
894 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
895 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
897 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
899 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid,
900 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
903 static HRESULT WINAPI HTMLTxtRange_get_htmlText(IHTMLTxtRange *iface, BSTR *p)
905 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
907 TRACE("(%p)->(%p)\n", This, p);
909 *p = NULL;
911 if(This->nsrange) {
912 nsIDOMDocumentFragment *fragment;
913 nsresult nsres;
915 nsres = nsIDOMRange_CloneContents(This->nsrange, &fragment);
916 if(NS_SUCCEEDED(nsres)) {
917 const PRUnichar *nstext;
918 nsAString nsstr;
920 nsAString_Init(&nsstr, NULL);
921 nsnode_to_nsstring((nsIDOMNode*)fragment, &nsstr);
922 nsIDOMDocumentFragment_Release(fragment);
924 nsAString_GetData(&nsstr, &nstext);
925 *p = SysAllocString(nstext);
927 nsAString_Finish(&nsstr);
931 if(!*p) {
932 *p = SysAllocString(L"");
935 TRACE("return %s\n", debugstr_w(*p));
936 return S_OK;
939 static HRESULT WINAPI HTMLTxtRange_put_text(IHTMLTxtRange *iface, BSTR v)
941 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
942 nsIDOMText *text_node;
943 nsAString text_str;
944 nsresult nsres;
946 TRACE("(%p)->(%s)\n", This, debugstr_w(v));
948 if(!This->doc)
949 return MSHTML_E_NODOC;
951 nsAString_InitDepend(&text_str, v);
952 nsres = nsIDOMHTMLDocument_CreateTextNode(This->doc->nsdoc, &text_str, &text_node);
953 nsAString_Finish(&text_str);
954 if(NS_FAILED(nsres)) {
955 ERR("CreateTextNode failed: %08x\n", nsres);
956 return S_OK;
958 nsres = nsIDOMRange_DeleteContents(This->nsrange);
959 if(NS_FAILED(nsres))
960 ERR("DeleteContents failed: %08x\n", nsres);
962 nsres = nsIDOMRange_InsertNode(This->nsrange, (nsIDOMNode*)text_node);
963 if(NS_FAILED(nsres))
964 ERR("InsertNode failed: %08x\n", nsres);
966 nsres = nsIDOMRange_SetEndAfter(This->nsrange, (nsIDOMNode*)text_node);
967 if(NS_FAILED(nsres))
968 ERR("SetEndAfter failed: %08x\n", nsres);
970 return IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, VARIANT_FALSE);
973 static HRESULT WINAPI HTMLTxtRange_get_text(IHTMLTxtRange *iface, BSTR *p)
975 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
976 wstrbuf_t buf;
978 TRACE("(%p)->(%p)\n", This, p);
980 *p = NULL;
981 if(!This->nsrange)
982 return S_OK;
984 if (!wstrbuf_init(&buf))
985 return E_OUTOFMEMORY;
986 range_to_string(This, &buf);
987 if (buf.buf)
988 *p = SysAllocString(buf.buf);
989 wstrbuf_finish(&buf);
991 TRACE("ret %s\n", debugstr_w(*p));
992 return S_OK;
995 static HRESULT WINAPI HTMLTxtRange_parentElement(IHTMLTxtRange *iface, IHTMLElement **parent)
997 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
998 nsIDOMNode *nsnode, *tmp;
999 HTMLDOMNode *node;
1000 HRESULT hres;
1002 TRACE("(%p)->(%p)\n", This, parent);
1004 nsIDOMRange_GetCommonAncestorContainer(This->nsrange, &nsnode);
1005 while(nsnode && get_node_type(nsnode) != ELEMENT_NODE) {
1006 nsIDOMNode_GetParentNode(nsnode, &tmp);
1007 nsIDOMNode_Release(nsnode);
1008 nsnode = tmp;
1011 if(!nsnode) {
1012 *parent = NULL;
1013 return S_OK;
1016 hres = get_node(nsnode, TRUE, &node);
1017 nsIDOMNode_Release(nsnode);
1018 if(FAILED(hres))
1019 return hres;
1021 hres = IHTMLDOMNode_QueryInterface(&node->IHTMLDOMNode_iface, &IID_IHTMLElement, (void**)parent);
1022 node_release(node);
1023 return hres;
1026 static HRESULT WINAPI HTMLTxtRange_duplicate(IHTMLTxtRange *iface, IHTMLTxtRange **Duplicate)
1028 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1029 nsIDOMRange *nsrange = NULL;
1030 HRESULT hres;
1032 TRACE("(%p)->(%p)\n", This, Duplicate);
1034 nsIDOMRange_CloneRange(This->nsrange, &nsrange);
1035 hres = HTMLTxtRange_Create(This->doc, nsrange, Duplicate);
1036 nsIDOMRange_Release(nsrange);
1038 return hres;
1041 static HRESULT WINAPI HTMLTxtRange_inRange(IHTMLTxtRange *iface, IHTMLTxtRange *Range,
1042 VARIANT_BOOL *InRange)
1044 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1045 HTMLTxtRange *src_range;
1046 short nsret = 0;
1047 nsresult nsres;
1049 TRACE("(%p)->(%p %p)\n", This, Range, InRange);
1051 *InRange = VARIANT_FALSE;
1053 src_range = get_range_object(This->doc, Range);
1054 if(!src_range)
1055 return E_FAIL;
1057 nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, NS_START_TO_START,
1058 src_range->nsrange, &nsret);
1059 if(NS_SUCCEEDED(nsres) && nsret <= 0) {
1060 nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, NS_END_TO_END,
1061 src_range->nsrange, &nsret);
1062 if(NS_SUCCEEDED(nsres) && nsret >= 0)
1063 *InRange = VARIANT_TRUE;
1066 if(NS_FAILED(nsres))
1067 ERR("CompareBoundaryPoints failed: %08x\n", nsres);
1069 return S_OK;
1072 static HRESULT WINAPI HTMLTxtRange_isEqual(IHTMLTxtRange *iface, IHTMLTxtRange *Range,
1073 VARIANT_BOOL *IsEqual)
1075 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1076 HTMLTxtRange *src_range;
1077 short nsret = 0;
1078 nsresult nsres;
1080 TRACE("(%p)->(%p %p)\n", This, Range, IsEqual);
1082 *IsEqual = VARIANT_FALSE;
1084 src_range = get_range_object(This->doc, Range);
1085 if(!src_range)
1086 return E_FAIL;
1088 nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, NS_START_TO_START,
1089 src_range->nsrange, &nsret);
1090 if(NS_SUCCEEDED(nsres) && !nsret) {
1091 nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, NS_END_TO_END,
1092 src_range->nsrange, &nsret);
1093 if(NS_SUCCEEDED(nsres) && !nsret)
1094 *IsEqual = VARIANT_TRUE;
1097 if(NS_FAILED(nsres))
1098 ERR("CompareBoundaryPoints failed: %08x\n", nsres);
1100 return S_OK;
1103 static HRESULT WINAPI HTMLTxtRange_scrollIntoView(IHTMLTxtRange *iface, VARIANT_BOOL fStart)
1105 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1106 FIXME("(%p)->(%x)\n", This, fStart);
1107 return E_NOTIMPL;
1110 static HRESULT WINAPI HTMLTxtRange_collapse(IHTMLTxtRange *iface, VARIANT_BOOL Start)
1112 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1114 TRACE("(%p)->(%x)\n", This, Start);
1116 nsIDOMRange_Collapse(This->nsrange, Start != VARIANT_FALSE);
1117 return S_OK;
1120 static HRESULT WINAPI HTMLTxtRange_expand(IHTMLTxtRange *iface, BSTR Unit, VARIANT_BOOL *Success)
1122 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1123 range_unit_t unit;
1125 TRACE("(%p)->(%s %p)\n", This, debugstr_w(Unit), Success);
1127 unit = string_to_unit(Unit);
1128 if(unit == RU_UNKNOWN)
1129 return E_INVALIDARG;
1131 *Success = VARIANT_FALSE;
1133 switch(unit) {
1134 case RU_WORD: {
1135 rangepoint_t end, start;
1136 cpp_bool is_collapsed;
1138 get_start_point(This, &start);
1139 get_end_point(This, &end);
1141 nsIDOMRange_GetCollapsed(This->nsrange, &is_collapsed);
1143 if(find_word_end(&end, is_collapsed)) {
1144 set_end_point(This, &end);
1145 *Success = VARIANT_TRUE;
1148 if(find_prev_space(&start, TRUE)) {
1149 set_start_point(This, &start);
1150 *Success = VARIANT_TRUE;
1153 free_rangepoint(&end);
1154 free_rangepoint(&start);
1155 break;
1158 case RU_TEXTEDIT: {
1159 nsIDOMHTMLElement *nsbody = NULL;
1160 nsresult nsres;
1162 nsres = nsIDOMHTMLDocument_GetBody(This->doc->nsdoc, &nsbody);
1163 if(NS_FAILED(nsres) || !nsbody) {
1164 ERR("Could not get body: %08x\n", nsres);
1165 break;
1168 nsres = nsIDOMRange_SelectNodeContents(This->nsrange, (nsIDOMNode*)nsbody);
1169 nsIDOMHTMLElement_Release(nsbody);
1170 if(NS_FAILED(nsres)) {
1171 ERR("Collapse failed: %08x\n", nsres);
1172 break;
1175 *Success = VARIANT_TRUE;
1176 break;
1179 default:
1180 FIXME("Unimplemented unit %s\n", debugstr_w(Unit));
1183 return S_OK;
1186 static HRESULT WINAPI HTMLTxtRange_move(IHTMLTxtRange *iface, BSTR Unit,
1187 LONG Count, LONG *ActualCount)
1189 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1190 range_unit_t unit;
1192 TRACE("(%p)->(%s %d %p)\n", This, debugstr_w(Unit), Count, ActualCount);
1194 unit = string_to_unit(Unit);
1195 if(unit == RU_UNKNOWN)
1196 return E_INVALIDARG;
1198 if(!Count) {
1199 *ActualCount = 0;
1200 return IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, VARIANT_TRUE);
1203 switch(unit) {
1204 case RU_CHAR: {
1205 rangepoint_t start;
1207 get_start_point(This, &start);
1209 *ActualCount = move_by_chars(&start, Count);
1211 set_start_point(This, &start);
1212 IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, VARIANT_TRUE);
1213 free_rangepoint(&start);
1214 break;
1217 case RU_WORD: {
1218 rangepoint_t start;
1220 get_start_point(This, &start);
1222 *ActualCount = move_by_words(&start, Count);
1224 set_start_point(This, &start);
1225 IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, VARIANT_TRUE);
1226 free_rangepoint(&start);
1227 break;
1230 default:
1231 FIXME("unimplemented unit %s\n", debugstr_w(Unit));
1234 TRACE("ret %d\n", *ActualCount);
1235 return S_OK;
1238 static HRESULT WINAPI HTMLTxtRange_moveStart(IHTMLTxtRange *iface, BSTR Unit,
1239 LONG Count, LONG *ActualCount)
1241 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1242 range_unit_t unit;
1244 TRACE("(%p)->(%s %d %p)\n", This, debugstr_w(Unit), Count, ActualCount);
1246 unit = string_to_unit(Unit);
1247 if(unit == RU_UNKNOWN)
1248 return E_INVALIDARG;
1250 if(!Count) {
1251 *ActualCount = 0;
1252 return S_OK;
1255 switch(unit) {
1256 case RU_CHAR: {
1257 rangepoint_t start;
1259 get_start_point(This, &start);
1261 *ActualCount = move_by_chars(&start, Count);
1263 set_start_point(This, &start);
1264 free_rangepoint(&start);
1265 break;
1268 default:
1269 FIXME("unimplemented unit %s\n", debugstr_w(Unit));
1270 return E_NOTIMPL;
1273 return S_OK;
1276 static HRESULT WINAPI HTMLTxtRange_moveEnd(IHTMLTxtRange *iface, BSTR Unit,
1277 LONG Count, LONG *ActualCount)
1279 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1280 range_unit_t unit;
1282 TRACE("(%p)->(%s %d %p)\n", This, debugstr_w(Unit), Count, ActualCount);
1284 unit = string_to_unit(Unit);
1285 if(unit == RU_UNKNOWN)
1286 return E_INVALIDARG;
1288 if(!Count) {
1289 *ActualCount = 0;
1290 return S_OK;
1293 switch(unit) {
1294 case RU_CHAR: {
1295 rangepoint_t end;
1297 get_end_point(This, &end);
1299 *ActualCount = move_by_chars(&end, Count);
1301 set_end_point(This, &end);
1302 free_rangepoint(&end);
1303 break;
1306 default:
1307 FIXME("unimplemented unit %s\n", debugstr_w(Unit));
1310 return S_OK;
1313 static HRESULT WINAPI HTMLTxtRange_select(IHTMLTxtRange *iface)
1315 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1316 nsISelection *nsselection;
1317 nsresult nsres;
1319 TRACE("(%p)\n", This);
1321 nsres = nsIDOMWindow_GetSelection(This->doc->basedoc.window->nswindow, &nsselection);
1322 if(NS_FAILED(nsres)) {
1323 ERR("GetSelection failed: %08x\n", nsres);
1324 return E_FAIL;
1327 nsISelection_RemoveAllRanges(nsselection);
1328 nsISelection_AddRange(nsselection, This->nsrange);
1329 nsISelection_Release(nsselection);
1330 return S_OK;
1333 static HRESULT WINAPI HTMLTxtRange_pasteHTML(IHTMLTxtRange *iface, BSTR html)
1335 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1336 nsIDOMDocumentFragment *doc_frag;
1337 nsAString nsstr;
1338 nsresult nsres;
1340 TRACE("(%p)->(%s)\n", This, debugstr_w(html));
1342 nsres = nsIDOMRange_Collapse(This->nsrange, TRUE);
1343 assert(nsres == NS_OK);
1345 nsAString_InitDepend(&nsstr, html);
1346 nsres = nsIDOMRange_CreateContextualFragment(This->nsrange, &nsstr, &doc_frag);
1347 nsAString_Finish(&nsstr);
1348 if(NS_FAILED(nsres)) {
1349 ERR("CreateContextualFragment failed: %08x\n", nsres);
1350 return E_FAIL;
1353 nsres = nsIDOMRange_InsertNode(This->nsrange, (nsIDOMNode*)doc_frag);
1354 nsIDOMDocumentFragment_Release(doc_frag);
1355 if(NS_FAILED(nsres)) {
1356 ERR("InsertNode failed: %08x\n", nsres);
1357 return E_FAIL;
1360 nsres = nsIDOMRange_Collapse(This->nsrange, FALSE);
1361 assert(nsres == NS_OK);
1362 return S_OK;
1365 static HRESULT WINAPI HTMLTxtRange_moveToElementText(IHTMLTxtRange *iface, IHTMLElement *element)
1367 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1368 HTMLElement *elem;
1369 nsresult nsres;
1371 TRACE("(%p)->(%p)\n", This, element);
1373 elem = unsafe_impl_from_IHTMLElement(element);
1374 if(!elem)
1375 return E_INVALIDARG;
1377 nsres = nsIDOMRange_SelectNodeContents(This->nsrange, elem->node.nsnode);
1378 if(NS_FAILED(nsres)) {
1379 ERR("SelectNodeContents failed: %08x\n", nsres);
1380 return E_FAIL;
1383 return S_OK;
1386 static HRESULT WINAPI HTMLTxtRange_setEndPoint(IHTMLTxtRange *iface, BSTR how,
1387 IHTMLTxtRange *SourceRange)
1389 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1390 HTMLTxtRange *src_range;
1391 nsIDOMNode *ref_node;
1392 INT32 ref_offset;
1393 BOOL set_start;
1394 int how_type;
1395 INT16 cmp;
1396 nsresult nsres;
1398 TRACE("(%p)->(%s %p)\n", This, debugstr_w(how), SourceRange);
1400 how_type = string_to_nscmptype(how);
1401 if(how_type == -1)
1402 return E_INVALIDARG;
1404 src_range = get_range_object(This->doc, SourceRange);
1405 if(!src_range)
1406 return E_FAIL;
1408 switch(how_type) {
1409 case NS_START_TO_START:
1410 case NS_END_TO_START:
1411 nsres = nsIDOMRange_GetStartContainer(src_range->nsrange, &ref_node);
1412 assert(nsres == NS_OK);
1414 nsres = nsIDOMRange_GetStartOffset(src_range->nsrange, &ref_offset);
1415 assert(nsres == NS_OK);
1417 set_start = how_type == NS_START_TO_START;
1418 break;
1419 case NS_END_TO_END:
1420 case NS_START_TO_END:
1421 nsres = nsIDOMRange_GetEndContainer(src_range->nsrange, &ref_node);
1422 assert(nsres == NS_OK);
1424 nsres = nsIDOMRange_GetEndOffset(src_range->nsrange, &ref_offset);
1425 assert(nsres == NS_OK);
1427 set_start = how_type == NS_START_TO_END;
1428 break;
1429 DEFAULT_UNREACHABLE;
1432 nsres = nsIDOMRange_ComparePoint(This->nsrange, ref_node, ref_offset, &cmp);
1433 assert(nsres == NS_OK);
1435 if(set_start) {
1436 if(cmp <= 0) {
1437 nsres = nsIDOMRange_SetStart(This->nsrange, ref_node, ref_offset);
1438 }else {
1439 nsres = nsIDOMRange_Collapse(This->nsrange, FALSE);
1440 assert(nsres == NS_OK);
1442 nsres = nsIDOMRange_SetEnd(This->nsrange, ref_node, ref_offset);
1444 }else {
1445 if(cmp >= 0) {
1446 nsres = nsIDOMRange_SetEnd(This->nsrange, ref_node, ref_offset);
1447 }else {
1448 nsres = nsIDOMRange_Collapse(This->nsrange, TRUE);
1449 assert(nsres == NS_OK);
1451 nsres = nsIDOMRange_SetStart(This->nsrange, ref_node, ref_offset);
1454 assert(nsres == NS_OK);
1456 nsIDOMNode_Release(ref_node);
1457 return S_OK;
1460 static HRESULT WINAPI HTMLTxtRange_compareEndPoints(IHTMLTxtRange *iface, BSTR how,
1461 IHTMLTxtRange *SourceRange, LONG *ret)
1463 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1464 HTMLTxtRange *src_range;
1465 short nsret = 0;
1466 int nscmpt;
1467 nsresult nsres;
1469 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(how), SourceRange, ret);
1471 nscmpt = string_to_nscmptype(how);
1472 if(nscmpt == -1)
1473 return E_INVALIDARG;
1475 src_range = get_range_object(This->doc, SourceRange);
1476 if(!src_range)
1477 return E_FAIL;
1479 nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, nscmpt, src_range->nsrange, &nsret);
1480 if(NS_FAILED(nsres))
1481 ERR("CompareBoundaryPoints failed: %08x\n", nsres);
1483 *ret = nsret;
1484 return S_OK;
1487 static HRESULT WINAPI HTMLTxtRange_findText(IHTMLTxtRange *iface, BSTR String,
1488 LONG count, LONG Flags, VARIANT_BOOL *Success)
1490 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1491 FIXME("(%p)->(%s %d %08x %p)\n", This, debugstr_w(String), count, Flags, Success);
1492 return E_NOTIMPL;
1495 static HRESULT WINAPI HTMLTxtRange_moveToPoint(IHTMLTxtRange *iface, LONG x, LONG y)
1497 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1498 FIXME("(%p)->(%d %d)\n", This, x, y);
1499 return E_NOTIMPL;
1502 static HRESULT WINAPI HTMLTxtRange_getBookmark(IHTMLTxtRange *iface, BSTR *Bookmark)
1504 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1505 FIXME("(%p)->(%p)\n", This, Bookmark);
1506 return E_NOTIMPL;
1509 static HRESULT WINAPI HTMLTxtRange_moveToBookmark(IHTMLTxtRange *iface, BSTR Bookmark,
1510 VARIANT_BOOL *Success)
1512 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1513 FIXME("(%p)->(%s %p)\n", This, debugstr_w(Bookmark), Success);
1514 return E_NOTIMPL;
1517 static HRESULT WINAPI HTMLTxtRange_queryCommandSupported(IHTMLTxtRange *iface, BSTR cmdID,
1518 VARIANT_BOOL *pfRet)
1520 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1521 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1522 return E_NOTIMPL;
1525 static HRESULT WINAPI HTMLTxtRange_queryCommandEnabled(IHTMLTxtRange *iface, BSTR cmdID,
1526 VARIANT_BOOL *pfRet)
1528 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1529 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1530 return E_NOTIMPL;
1533 static HRESULT WINAPI HTMLTxtRange_queryCommandState(IHTMLTxtRange *iface, BSTR cmdID,
1534 VARIANT_BOOL *pfRet)
1536 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1537 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1538 return E_NOTIMPL;
1541 static HRESULT WINAPI HTMLTxtRange_queryCommandIndeterm(IHTMLTxtRange *iface, BSTR cmdID,
1542 VARIANT_BOOL *pfRet)
1544 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1545 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1546 return E_NOTIMPL;
1549 static HRESULT WINAPI HTMLTxtRange_queryCommandText(IHTMLTxtRange *iface, BSTR cmdID,
1550 BSTR *pcmdText)
1552 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1553 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pcmdText);
1554 return E_NOTIMPL;
1557 static HRESULT WINAPI HTMLTxtRange_queryCommandValue(IHTMLTxtRange *iface, BSTR cmdID,
1558 VARIANT *pcmdValue)
1560 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1561 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pcmdValue);
1562 return E_NOTIMPL;
1565 static HRESULT WINAPI HTMLTxtRange_execCommand(IHTMLTxtRange *iface, BSTR cmdID,
1566 VARIANT_BOOL showUI, VARIANT value, VARIANT_BOOL *pfRet)
1568 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1569 FIXME("(%p)->(%s %x v %p)\n", This, debugstr_w(cmdID), showUI, pfRet);
1570 return E_NOTIMPL;
1573 static HRESULT WINAPI HTMLTxtRange_execCommandShowHelp(IHTMLTxtRange *iface, BSTR cmdID,
1574 VARIANT_BOOL *pfRet)
1576 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1577 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1578 return E_NOTIMPL;
1581 static const IHTMLTxtRangeVtbl HTMLTxtRangeVtbl = {
1582 HTMLTxtRange_QueryInterface,
1583 HTMLTxtRange_AddRef,
1584 HTMLTxtRange_Release,
1585 HTMLTxtRange_GetTypeInfoCount,
1586 HTMLTxtRange_GetTypeInfo,
1587 HTMLTxtRange_GetIDsOfNames,
1588 HTMLTxtRange_Invoke,
1589 HTMLTxtRange_get_htmlText,
1590 HTMLTxtRange_put_text,
1591 HTMLTxtRange_get_text,
1592 HTMLTxtRange_parentElement,
1593 HTMLTxtRange_duplicate,
1594 HTMLTxtRange_inRange,
1595 HTMLTxtRange_isEqual,
1596 HTMLTxtRange_scrollIntoView,
1597 HTMLTxtRange_collapse,
1598 HTMLTxtRange_expand,
1599 HTMLTxtRange_move,
1600 HTMLTxtRange_moveStart,
1601 HTMLTxtRange_moveEnd,
1602 HTMLTxtRange_select,
1603 HTMLTxtRange_pasteHTML,
1604 HTMLTxtRange_moveToElementText,
1605 HTMLTxtRange_setEndPoint,
1606 HTMLTxtRange_compareEndPoints,
1607 HTMLTxtRange_findText,
1608 HTMLTxtRange_moveToPoint,
1609 HTMLTxtRange_getBookmark,
1610 HTMLTxtRange_moveToBookmark,
1611 HTMLTxtRange_queryCommandSupported,
1612 HTMLTxtRange_queryCommandEnabled,
1613 HTMLTxtRange_queryCommandState,
1614 HTMLTxtRange_queryCommandIndeterm,
1615 HTMLTxtRange_queryCommandText,
1616 HTMLTxtRange_queryCommandValue,
1617 HTMLTxtRange_execCommand,
1618 HTMLTxtRange_execCommandShowHelp
1621 static inline HTMLTxtRange *impl_from_IOleCommandTarget(IOleCommandTarget *iface)
1623 return CONTAINING_RECORD(iface, HTMLTxtRange, IOleCommandTarget_iface);
1626 static HRESULT WINAPI RangeCommandTarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv)
1628 HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1629 return IHTMLTxtRange_QueryInterface(&This->IHTMLTxtRange_iface, riid, ppv);
1632 static ULONG WINAPI RangeCommandTarget_AddRef(IOleCommandTarget *iface)
1634 HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1635 return IHTMLTxtRange_AddRef(&This->IHTMLTxtRange_iface);
1638 static ULONG WINAPI RangeCommandTarget_Release(IOleCommandTarget *iface)
1640 HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1641 return IHTMLTxtRange_Release(&This->IHTMLTxtRange_iface);
1644 static HRESULT WINAPI RangeCommandTarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
1645 ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
1647 HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1648 FIXME("(%p)->(%s %d %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
1649 return E_NOTIMPL;
1652 static HRESULT exec_indent(HTMLTxtRange *This, VARIANT *in, VARIANT *out)
1654 nsIDOMElement *blockquote_elem, *p_elem;
1655 nsIDOMDocumentFragment *fragment;
1656 nsIDOMNode *tmp;
1658 TRACE("(%p)->(%p %p)\n", This, in, out);
1660 if(!This->doc->nsdoc) {
1661 WARN("NULL nsdoc\n");
1662 return E_NOTIMPL;
1665 create_nselem(This->doc, L"BLOCKQUOTE", &blockquote_elem);
1666 create_nselem(This->doc, L"P", &p_elem);
1668 nsIDOMRange_ExtractContents(This->nsrange, &fragment);
1669 nsIDOMElement_AppendChild(p_elem, (nsIDOMNode*)fragment, &tmp);
1670 nsIDOMDocumentFragment_Release(fragment);
1671 nsIDOMNode_Release(tmp);
1673 nsIDOMElement_AppendChild(blockquote_elem, (nsIDOMNode*)p_elem, &tmp);
1674 nsIDOMElement_Release(p_elem);
1675 nsIDOMNode_Release(tmp);
1677 nsIDOMRange_InsertNode(This->nsrange, (nsIDOMNode*)blockquote_elem);
1678 nsIDOMElement_Release(blockquote_elem);
1680 return S_OK;
1683 static HRESULT WINAPI RangeCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
1684 DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
1686 HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1688 TRACE("(%p)->(%s %d %x %p %p)\n", This, debugstr_guid(pguidCmdGroup), nCmdID,
1689 nCmdexecopt, pvaIn, pvaOut);
1691 if(pguidCmdGroup && IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
1692 switch(nCmdID) {
1693 case IDM_INDENT:
1694 return exec_indent(This, pvaIn, pvaOut);
1695 default:
1696 FIXME("Unsupported cmdid %d of CGID_MSHTML\n", nCmdID);
1698 }else {
1699 FIXME("Unsupported cmd %d of group %s\n", nCmdID, debugstr_guid(pguidCmdGroup));
1702 return E_NOTIMPL;
1705 static const IOleCommandTargetVtbl OleCommandTargetVtbl = {
1706 RangeCommandTarget_QueryInterface,
1707 RangeCommandTarget_AddRef,
1708 RangeCommandTarget_Release,
1709 RangeCommandTarget_QueryStatus,
1710 RangeCommandTarget_Exec
1713 static const tid_t HTMLTxtRange_iface_tids[] = {
1714 IHTMLTxtRange_tid,
1717 static dispex_static_data_t HTMLTxtRange_dispex = {
1718 NULL,
1719 IHTMLTxtRange_tid,
1720 HTMLTxtRange_iface_tids
1723 HRESULT HTMLTxtRange_Create(HTMLDocumentNode *doc, nsIDOMRange *nsrange, IHTMLTxtRange **p)
1725 HTMLTxtRange *ret;
1727 ret = heap_alloc(sizeof(HTMLTxtRange));
1728 if(!ret)
1729 return E_OUTOFMEMORY;
1731 init_dispatch(&ret->dispex, (IUnknown*)&ret->IHTMLTxtRange_iface, &HTMLTxtRange_dispex,
1732 dispex_compat_mode(&doc->node.event_target.dispex));
1734 ret->IHTMLTxtRange_iface.lpVtbl = &HTMLTxtRangeVtbl;
1735 ret->IOleCommandTarget_iface.lpVtbl = &OleCommandTargetVtbl;
1736 ret->ref = 1;
1738 if(nsrange)
1739 nsIDOMRange_AddRef(nsrange);
1740 ret->nsrange = nsrange;
1742 ret->doc = doc;
1743 list_add_head(&doc->range_list, &ret->entry);
1745 *p = &ret->IHTMLTxtRange_iface;
1746 return S_OK;
1749 static inline HTMLDOMRange *impl_from_IHTMLDOMRange(IHTMLDOMRange *iface)
1751 return CONTAINING_RECORD(iface, HTMLDOMRange, IHTMLDOMRange_iface);
1754 static HRESULT WINAPI HTMLDOMRange_QueryInterface(IHTMLDOMRange *iface, REFIID riid, void **ppv)
1756 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1758 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1760 if(IsEqualGUID(&IID_IUnknown, riid)) {
1761 *ppv = &This->IHTMLDOMRange_iface;
1762 }else if(IsEqualGUID(&IID_IHTMLDOMRange, riid)) {
1763 *ppv = &This->IHTMLDOMRange_iface;
1764 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
1765 return *ppv ? S_OK : E_NOINTERFACE;
1766 }else {
1767 *ppv = NULL;
1768 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1769 return E_NOINTERFACE;
1772 IUnknown_AddRef((IUnknown*)*ppv);
1773 return S_OK;
1776 static ULONG WINAPI HTMLDOMRange_AddRef(IHTMLDOMRange *iface)
1778 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1779 LONG ref = InterlockedIncrement(&This->ref);
1781 TRACE("(%p) ref=%d\n", This, ref);
1783 return ref;
1786 static ULONG WINAPI HTMLDOMRange_Release(IHTMLDOMRange *iface)
1788 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1789 LONG ref = InterlockedDecrement(&This->ref);
1791 TRACE("(%p) ref=%d\n", This, ref);
1793 if(!ref) {
1794 if(This->nsrange)
1795 nsIDOMRange_Release(This->nsrange);
1796 release_dispex(&This->dispex);
1797 heap_free(This);
1800 return ref;
1803 static HRESULT WINAPI HTMLDOMRange_GetTypeInfoCount(IHTMLDOMRange *iface, UINT *pctinfo)
1805 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1807 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
1810 static HRESULT WINAPI HTMLDOMRange_GetTypeInfo(IHTMLDOMRange *iface, UINT iTInfo,
1811 LCID lcid, ITypeInfo **ppTInfo)
1813 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1815 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1818 static HRESULT WINAPI HTMLDOMRange_GetIDsOfNames(IHTMLDOMRange *iface, REFIID riid,
1819 LPOLESTR *rgszNames, UINT cNames,
1820 LCID lcid, DISPID *rgDispId)
1822 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1824 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames,
1825 cNames, lcid, rgDispId);
1828 static HRESULT WINAPI HTMLDOMRange_Invoke(IHTMLDOMRange *iface, DISPID dispIdMember,
1829 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1830 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1832 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1834 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid,
1835 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1838 static HRESULT WINAPI HTMLDOMRange_get_startContainer(IHTMLDOMRange *iface, IHTMLDOMNode **p)
1840 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1841 FIXME("(%p)->(%p)\n", This, p);
1842 return E_NOTIMPL;
1845 static HRESULT WINAPI HTMLDOMRange_get_startOffset(IHTMLDOMRange *iface, LONG *p)
1847 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1848 FIXME("(%p)->(%p)\n", This, p);
1849 return E_NOTIMPL;
1852 static HRESULT WINAPI HTMLDOMRange_get_endContainer(IHTMLDOMRange *iface, IHTMLDOMNode **p)
1854 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1855 FIXME("(%p)->(%p)\n", This, p);
1856 return E_NOTIMPL;
1859 static HRESULT WINAPI HTMLDOMRange_get_endOffset(IHTMLDOMRange *iface, LONG *p)
1861 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1862 FIXME("(%p)->(%p)\n", This, p);
1863 return E_NOTIMPL;
1866 static HRESULT WINAPI HTMLDOMRange_get_collapsed(IHTMLDOMRange *iface, VARIANT_BOOL *p)
1868 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1869 FIXME("(%p)->(%p)\n", This, p);
1870 return E_NOTIMPL;
1873 static HRESULT WINAPI HTMLDOMRange_get_commonAncestorContainer(IHTMLDOMRange *iface, IHTMLDOMNode **p)
1875 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1876 FIXME("(%p)->(%p)\n", This, p);
1877 return E_NOTIMPL;
1880 static HRESULT WINAPI HTMLDOMRange_setStart(IHTMLDOMRange *iface, IDispatch *node, LONG offset)
1882 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1883 FIXME("(%p)->(%p, %d)\n", This, node, offset);
1884 return E_NOTIMPL;
1887 static HRESULT WINAPI HTMLDOMRange_setEnd(IHTMLDOMRange *iface, IDispatch *node, LONG offset)
1889 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1890 FIXME("(%p)->(%p, %d)\n", This, node, offset);
1891 return E_NOTIMPL;
1894 static HRESULT WINAPI HTMLDOMRange_setStartBefore(IHTMLDOMRange *iface, IDispatch *node)
1896 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1897 FIXME("(%p)->(%p)\n", This, node);
1898 return E_NOTIMPL;
1901 static HRESULT WINAPI HTMLDOMRange_setStartAfter(IHTMLDOMRange *iface, IDispatch *node)
1903 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1904 FIXME("(%p)->(%p)\n", This, node);
1905 return E_NOTIMPL;
1908 static HRESULT WINAPI HTMLDOMRange_setEndBefore(IHTMLDOMRange *iface, IDispatch *node)
1910 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1911 FIXME("(%p)->(%p)\n", This, node);
1912 return E_NOTIMPL;
1915 static HRESULT WINAPI HTMLDOMRange_setEndAfter(IHTMLDOMRange *iface, IDispatch *node)
1917 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1918 FIXME("(%p)->(%p)\n", This, node);
1919 return E_NOTIMPL;
1922 static HRESULT WINAPI HTMLDOMRange_collapse(IHTMLDOMRange *iface, VARIANT_BOOL tostart)
1924 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1925 FIXME("(%p)->(%x)\n", This, tostart);
1926 return E_NOTIMPL;
1929 static HRESULT WINAPI HTMLDOMRange_selectNode(IHTMLDOMRange *iface, IDispatch *node)
1931 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1932 FIXME("(%p)->(%p)\n", This, node);
1933 return E_NOTIMPL;
1936 static HRESULT WINAPI HTMLDOMRange_selectNodeContents(IHTMLDOMRange *iface, IDispatch *node)
1938 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1939 FIXME("(%p)->(%p)\n", This, node);
1940 return E_NOTIMPL;
1943 static HRESULT WINAPI HTMLDOMRange_compareBoundaryPoints(IHTMLDOMRange *iface, short how,
1944 IDispatch *src_range, LONG *result)
1946 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1947 FIXME("(%p)->(%x, %p, %p)\n", This, how, src_range, result);
1948 return E_NOTIMPL;
1951 static HRESULT WINAPI HTMLDOMRange_deleteContents(IHTMLDOMRange *iface)
1953 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1954 FIXME("(%p)\n", This);
1955 return E_NOTIMPL;
1958 static HRESULT WINAPI HTMLDOMRange_extractContents(IHTMLDOMRange *iface, IDispatch **p)
1960 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1961 FIXME("(%p)->(%p)\n", This, p);
1962 return E_NOTIMPL;
1965 static HRESULT WINAPI HTMLDOMRange_cloneContents(IHTMLDOMRange *iface, IDispatch **p)
1967 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1968 FIXME("(%p)->(%p)\n", This, p);
1969 return E_NOTIMPL;
1972 static HRESULT WINAPI HTMLDOMRange_insertNode(IHTMLDOMRange *iface, IDispatch *node)
1974 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1975 FIXME("(%p)->(%p)\n", This, node);
1976 return E_NOTIMPL;
1979 static HRESULT WINAPI HTMLDOMRange_surroundContents(IHTMLDOMRange *iface, IDispatch *parent)
1981 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1982 FIXME("(%p)->(%p)\n", This, parent);
1983 return E_NOTIMPL;
1986 static HRESULT WINAPI HTMLDOMRange_cloneRange(IHTMLDOMRange *iface, IHTMLDOMRange **p)
1988 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1989 FIXME("(%p)->(%p)\n", This, p);
1990 return E_NOTIMPL;
1993 static HRESULT WINAPI HTMLDOMRange_toString(IHTMLDOMRange *iface, BSTR *p)
1995 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1996 FIXME("(%p)->(%p)\n", This, p);
1997 return E_NOTIMPL;
2000 static HRESULT WINAPI HTMLDOMRange_detach(IHTMLDOMRange *iface)
2002 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
2003 FIXME("(%p)\n", This);
2004 return E_NOTIMPL;
2007 static HRESULT WINAPI HTMLDOMRange_getClientRects(IHTMLDOMRange *iface, IHTMLRectCollection **p)
2009 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
2010 FIXME("(%p)->(%p)\n", This, p);
2011 return E_NOTIMPL;
2014 static HRESULT WINAPI HTMLDOMRange_getBoundingClientRect(IHTMLDOMRange *iface, IHTMLRect **p)
2016 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
2017 FIXME("(%p)->(%p)\n", This, p);
2018 return E_NOTIMPL;
2021 static const IHTMLDOMRangeVtbl HTMLDOMRangeVtbl = {
2022 HTMLDOMRange_QueryInterface,
2023 HTMLDOMRange_AddRef,
2024 HTMLDOMRange_Release,
2025 HTMLDOMRange_GetTypeInfoCount,
2026 HTMLDOMRange_GetTypeInfo,
2027 HTMLDOMRange_GetIDsOfNames,
2028 HTMLDOMRange_Invoke,
2029 HTMLDOMRange_get_startContainer,
2030 HTMLDOMRange_get_startOffset,
2031 HTMLDOMRange_get_endContainer,
2032 HTMLDOMRange_get_endOffset,
2033 HTMLDOMRange_get_collapsed,
2034 HTMLDOMRange_get_commonAncestorContainer,
2035 HTMLDOMRange_setStart,
2036 HTMLDOMRange_setEnd,
2037 HTMLDOMRange_setStartBefore,
2038 HTMLDOMRange_setStartAfter,
2039 HTMLDOMRange_setEndBefore,
2040 HTMLDOMRange_setEndAfter,
2041 HTMLDOMRange_collapse,
2042 HTMLDOMRange_selectNode,
2043 HTMLDOMRange_selectNodeContents,
2044 HTMLDOMRange_compareBoundaryPoints,
2045 HTMLDOMRange_deleteContents,
2046 HTMLDOMRange_extractContents,
2047 HTMLDOMRange_cloneContents,
2048 HTMLDOMRange_insertNode,
2049 HTMLDOMRange_surroundContents,
2050 HTMLDOMRange_cloneRange,
2051 HTMLDOMRange_toString,
2052 HTMLDOMRange_detach,
2053 HTMLDOMRange_getClientRects,
2054 HTMLDOMRange_getBoundingClientRect,
2057 static const tid_t HTMLDOMRange_iface_tids[] = {
2058 IHTMLDOMRange_tid,
2062 static dispex_static_data_t HTMLDOMRange_dispex = {
2063 NULL,
2064 DispHTMLDOMRange_tid,
2065 HTMLDOMRange_iface_tids
2068 HRESULT create_dom_range(nsIDOMRange *nsrange, compat_mode_t compat_mode, IHTMLDOMRange **p)
2070 HTMLDOMRange *ret;
2072 ret = heap_alloc(sizeof(*ret));
2073 if(!ret)
2074 return E_OUTOFMEMORY;
2076 init_dispatch(&ret->dispex, (IUnknown*)&ret->IHTMLDOMRange_iface, &HTMLDOMRange_dispex, compat_mode);
2078 ret->IHTMLDOMRange_iface.lpVtbl = &HTMLDOMRangeVtbl;
2079 ret->ref = 1;
2081 if(nsrange)
2082 nsIDOMRange_AddRef(nsrange);
2083 ret->nsrange = nsrange;
2085 *p = &ret->IHTMLDOMRange_iface;
2086 return S_OK;
2089 void detach_ranges(HTMLDocumentNode *This)
2091 HTMLTxtRange *iter, *next;
2093 LIST_FOR_EACH_ENTRY_SAFE(iter, next, &This->range_list, HTMLTxtRange, entry) {
2094 iter->doc = NULL;
2095 list_remove(&iter->entry);
2099 typedef struct {
2100 IMarkupPointer2 IMarkupPointer2_iface;
2101 LONG ref;
2102 } MarkupPointer;
2104 static inline MarkupPointer *impl_from_IMarkupPointer2(IMarkupPointer2 *iface)
2106 return CONTAINING_RECORD(iface, MarkupPointer, IMarkupPointer2_iface);
2109 static HRESULT WINAPI MarkupPointer2_QueryInterface(IMarkupPointer2 *iface, REFIID riid, void **ppv)
2111 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2113 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
2115 if(IsEqualGUID(&IID_IUnknown, riid)) {
2116 *ppv = &This->IMarkupPointer2_iface;
2117 }else if(IsEqualGUID(&IID_IMarkupPointer, riid)) {
2118 *ppv = &This->IMarkupPointer2_iface;
2119 }else if(IsEqualGUID(&IID_IMarkupPointer2, riid)) {
2120 *ppv = &This->IMarkupPointer2_iface;
2121 }else {
2122 *ppv = NULL;
2123 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
2124 return E_NOINTERFACE;
2127 IUnknown_AddRef((IUnknown*)*ppv);
2128 return S_OK;
2131 static ULONG WINAPI MarkupPointer2_AddRef(IMarkupPointer2 *iface)
2133 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2134 LONG ref = InterlockedIncrement(&This->ref);
2136 TRACE("(%p) ref=%d\n", This, ref);
2138 return ref;
2141 static ULONG WINAPI MarkupPointer2_Release(IMarkupPointer2 *iface)
2143 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2144 LONG ref = InterlockedDecrement(&This->ref);
2146 TRACE("(%p) ref=%d\n", This, ref);
2148 if(!ref)
2149 heap_free(This);
2151 return ref;
2154 static HRESULT WINAPI MarkupPointer2_OwningDoc(IMarkupPointer2 *iface, IHTMLDocument2 **p)
2156 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2157 FIXME("(%p)->(%p)\n", This, p);
2158 return E_NOTIMPL;
2161 static HRESULT WINAPI MarkupPointer2_Gravity(IMarkupPointer2 *iface, POINTER_GRAVITY *p)
2163 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2164 FIXME("(%p)->(%p)\n", This, p);
2165 return E_NOTIMPL;
2168 static HRESULT WINAPI MarkupPointer2_SetGravity(IMarkupPointer2 *iface, POINTER_GRAVITY gravity)
2170 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2171 FIXME("(%p)->(%u)\n", This, gravity);
2172 return E_NOTIMPL;
2175 static HRESULT WINAPI MarkupPointer2_Cling(IMarkupPointer2 *iface, BOOL *p)
2177 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2178 FIXME("(%p)->(%p)\n", This, p);
2179 return E_NOTIMPL;
2182 static HRESULT WINAPI MarkupPointer2_SetCling(IMarkupPointer2 *iface, BOOL cling)
2184 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2185 FIXME("(%p)->(%x)\n", This, cling);
2186 return E_NOTIMPL;
2189 static HRESULT WINAPI MarkupPointer2_Unposition(IMarkupPointer2 *iface)
2191 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2192 FIXME("(%p)\n", This);
2193 return E_NOTIMPL;
2196 static HRESULT WINAPI MarkupPointer2_IsPositioned(IMarkupPointer2 *iface, BOOL *p)
2198 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2199 FIXME("(%p)->(%p)\n", This, p);
2200 return E_NOTIMPL;
2203 static HRESULT WINAPI MarkupPointer2_GetContainer(IMarkupPointer2 *iface, IMarkupContainer **p)
2205 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2206 FIXME("(%p)->(%p)\n", This, p);
2207 return E_NOTIMPL;
2210 static HRESULT WINAPI MarkupPointer2_MoveAdjacentToElement(IMarkupPointer2 *iface, IHTMLElement *element, ELEMENT_ADJACENCY adj)
2212 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2213 FIXME("(%p)->(%p %u)\n", This, element, adj);
2214 return E_NOTIMPL;
2217 static HRESULT WINAPI MarkupPointer2_MoveToPointer(IMarkupPointer2 *iface, IMarkupPointer *pointer)
2219 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2220 FIXME("(%p)->(%p)\n", This, pointer);
2221 return E_NOTIMPL;
2224 static HRESULT WINAPI MarkupPointer2_MoveToContainer(IMarkupPointer2 *iface, IMarkupContainer *container, BOOL at_start)
2226 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2227 FIXME("(%p)->(%p %x)\n", This, container, at_start);
2228 return E_NOTIMPL;
2231 static HRESULT WINAPI MarkupPointer2_Left(IMarkupPointer2 *iface, BOOL move, MARKUP_CONTEXT_TYPE *context,
2232 IHTMLElement **element, LONG *len, OLECHAR *text)
2234 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2235 FIXME("(%p)->(%x %p %p %p %p)\n", This, move, context, element, len, text);
2236 return E_NOTIMPL;
2239 static HRESULT WINAPI MarkupPointer2_Right(IMarkupPointer2 *iface, BOOL move, MARKUP_CONTEXT_TYPE *context,
2240 IHTMLElement **element, LONG *len, OLECHAR *text)
2242 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2243 FIXME("(%p)->(%x %p %p %p %p)\n", This, move, context, element, len, text);
2244 return E_NOTIMPL;
2247 static HRESULT WINAPI MarkupPointer2_CurrentScope(IMarkupPointer2 *iface, IHTMLElement **p)
2249 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2250 FIXME("(%p)->(%p)\n", This, p);
2251 return E_NOTIMPL;
2254 static HRESULT WINAPI MarkupPointer2_IsLeftOf(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2256 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2257 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2258 return E_NOTIMPL;
2261 static HRESULT WINAPI MarkupPointer2_IsLeftOfOrEqualTo(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2263 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2264 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2265 return E_NOTIMPL;
2268 static HRESULT WINAPI MarkupPointer2_IsRightOf(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2270 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2271 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2272 return E_NOTIMPL;
2275 static HRESULT WINAPI MarkupPointer2_IsRightOfOrEqualTo(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2277 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2278 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2279 return E_NOTIMPL;
2282 static HRESULT WINAPI MarkupPointer2_IsEqualTo(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2284 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2285 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2286 return E_NOTIMPL;
2289 static HRESULT WINAPI MarkupPointer2_MoveUnit(IMarkupPointer2 *iface, MOVEUNIT_ACTION action)
2291 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2292 FIXME("(%p)->(%u)\n", This, action);
2293 return E_NOTIMPL;
2296 static HRESULT WINAPI MarkupPointer2_FindText(IMarkupPointer2 *iface, OLECHAR *text, DWORD flags,
2297 IMarkupPointer *end_match, IMarkupPointer *end_search)
2299 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2300 FIXME("(%p)->(%s %x %p %p)\n", This, debugstr_w(text), flags, end_match, end_search);
2301 return E_NOTIMPL;
2304 static HRESULT WINAPI MarkupPointer2_IsAtWordBreak(IMarkupPointer2 *iface, BOOL *p)
2306 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2307 FIXME("(%p)->(%p)\n", This, p);
2308 return E_NOTIMPL;
2311 static HRESULT WINAPI MarkupPointer2_GetMarkupPosition(IMarkupPointer2 *iface, LONG *p)
2313 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2314 FIXME("(%p)->(%p)\n", This, p);
2315 return E_NOTIMPL;
2318 static HRESULT WINAPI MarkupPointer2_MoveToMarkupPosition(IMarkupPointer2 *iface, IMarkupContainer *container, LONG mp)
2320 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2321 FIXME("(%p)->(%p %d)\n", This, container, mp);
2322 return E_NOTIMPL;
2325 static HRESULT WINAPI MarkupPointer2_MoveUnitBounded(IMarkupPointer2 *iface, MOVEUNIT_ACTION action, IMarkupPointer *boundary)
2327 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2328 FIXME("(%p)->(%u %p)\n", This, action, boundary);
2329 return E_NOTIMPL;
2332 static HRESULT WINAPI MarkupPointer2_IsInsideURL(IMarkupPointer2 *iface, IMarkupPointer *right, BOOL *p)
2334 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2335 FIXME("(%p)->(%p %p)\n", This, right, p);
2336 return E_NOTIMPL;
2339 static HRESULT WINAPI MarkupPointer2_MoveToContent(IMarkupPointer2 *iface, IHTMLElement *element, BOOL at_start)
2341 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2342 FIXME("(%p)->(%p %x)\n", This, element, at_start);
2343 return E_NOTIMPL;
2346 static const IMarkupPointer2Vtbl MarkupPointer2Vtbl = {
2347 MarkupPointer2_QueryInterface,
2348 MarkupPointer2_AddRef,
2349 MarkupPointer2_Release,
2350 MarkupPointer2_OwningDoc,
2351 MarkupPointer2_Gravity,
2352 MarkupPointer2_SetGravity,
2353 MarkupPointer2_Cling,
2354 MarkupPointer2_SetCling,
2355 MarkupPointer2_Unposition,
2356 MarkupPointer2_IsPositioned,
2357 MarkupPointer2_GetContainer,
2358 MarkupPointer2_MoveAdjacentToElement,
2359 MarkupPointer2_MoveToPointer,
2360 MarkupPointer2_MoveToContainer,
2361 MarkupPointer2_Left,
2362 MarkupPointer2_Right,
2363 MarkupPointer2_CurrentScope,
2364 MarkupPointer2_IsLeftOf,
2365 MarkupPointer2_IsLeftOfOrEqualTo,
2366 MarkupPointer2_IsRightOf,
2367 MarkupPointer2_IsRightOfOrEqualTo,
2368 MarkupPointer2_IsEqualTo,
2369 MarkupPointer2_MoveUnit,
2370 MarkupPointer2_FindText,
2371 MarkupPointer2_IsAtWordBreak,
2372 MarkupPointer2_GetMarkupPosition,
2373 MarkupPointer2_MoveToMarkupPosition,
2374 MarkupPointer2_MoveUnitBounded,
2375 MarkupPointer2_IsInsideURL,
2376 MarkupPointer2_MoveToContent
2379 HRESULT create_markup_pointer(IMarkupPointer **ret)
2381 MarkupPointer *markup_pointer;
2383 if(!(markup_pointer = heap_alloc(sizeof(*markup_pointer))))
2384 return E_OUTOFMEMORY;
2386 markup_pointer->IMarkupPointer2_iface.lpVtbl = &MarkupPointer2Vtbl;
2387 markup_pointer->ref = 1;
2389 *ret = (IMarkupPointer*)&markup_pointer->IMarkupPointer2_iface;
2390 return S_OK;