gdi32: Try to parse font names without FreeType.
[wine/zf.git] / dlls / mshtml / range.c
blobaa8e8942a8703c6cb1d75bdb917c6266576fc9e6
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_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLTxtRange_iface, &HTMLTxtRange_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 HTMLDOMRange_Create(nsIDOMRange *nsrange, IHTMLDOMRange **p)
2070 HTMLDOMRange *ret;
2072 ret = heap_alloc(sizeof(*ret));
2073 if(!ret)
2074 return E_OUTOFMEMORY;
2076 init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLDOMRange_iface, &HTMLDOMRange_dispex);
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;