user32: Move unpack_message call to User32CallWindowProc.
[wine.git] / dlls / mshtml / range.c
blob59d1a59b0b0b2b00218ea7a3d3a2756bbe03918f
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: %08lx\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: %08lx\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: %08lx\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=%ld\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=%ld\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: %08lx\n", nsres);
956 return S_OK;
958 nsres = nsIDOMRange_DeleteContents(This->nsrange);
959 if(NS_FAILED(nsres))
960 ERR("DeleteContents failed: %08lx\n", nsres);
962 nsres = nsIDOMRange_InsertNode(This->nsrange, (nsIDOMNode*)text_node);
963 if(NS_FAILED(nsres))
964 ERR("InsertNode failed: %08lx\n", nsres);
966 nsres = nsIDOMRange_SetEndAfter(This->nsrange, (nsIDOMNode*)text_node);
967 if(NS_FAILED(nsres))
968 ERR("SetEndAfter failed: %08lx\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: %08lx\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: %08lx\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: %08lx\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: %08lx\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 %ld %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 %ld\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 %ld %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 %ld %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: %08lx\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: %08lx\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: %08lx\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: %08lx\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 LONG 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: %08lx\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 %ld %08lx %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)->(%ld %ld)\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 %ld %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 %ld %lx %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 %ld of CGID_MSHTML\n", nCmdID);
1698 }else {
1699 FIXME("Unsupported cmd %ld 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 L"TextRange",
1719 NULL,
1720 IHTMLTxtRange_tid,
1721 HTMLTxtRange_iface_tids
1724 HRESULT HTMLTxtRange_Create(HTMLDocumentNode *doc, nsIDOMRange *nsrange, IHTMLTxtRange **p)
1726 HTMLTxtRange *ret;
1728 ret = heap_alloc(sizeof(HTMLTxtRange));
1729 if(!ret)
1730 return E_OUTOFMEMORY;
1732 init_dispatch(&ret->dispex, (IUnknown*)&ret->IHTMLTxtRange_iface, &HTMLTxtRange_dispex,
1733 dispex_compat_mode(&doc->node.event_target.dispex));
1735 ret->IHTMLTxtRange_iface.lpVtbl = &HTMLTxtRangeVtbl;
1736 ret->IOleCommandTarget_iface.lpVtbl = &OleCommandTargetVtbl;
1737 ret->ref = 1;
1739 if(nsrange)
1740 nsIDOMRange_AddRef(nsrange);
1741 ret->nsrange = nsrange;
1743 ret->doc = doc;
1744 list_add_head(&doc->range_list, &ret->entry);
1746 *p = &ret->IHTMLTxtRange_iface;
1747 return S_OK;
1750 static inline HTMLDOMRange *impl_from_IHTMLDOMRange(IHTMLDOMRange *iface)
1752 return CONTAINING_RECORD(iface, HTMLDOMRange, IHTMLDOMRange_iface);
1755 static HRESULT WINAPI HTMLDOMRange_QueryInterface(IHTMLDOMRange *iface, REFIID riid, void **ppv)
1757 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1759 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1761 if(IsEqualGUID(&IID_IUnknown, riid)) {
1762 *ppv = &This->IHTMLDOMRange_iface;
1763 }else if(IsEqualGUID(&IID_IHTMLDOMRange, riid)) {
1764 *ppv = &This->IHTMLDOMRange_iface;
1765 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
1766 return *ppv ? S_OK : E_NOINTERFACE;
1767 }else {
1768 *ppv = NULL;
1769 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1770 return E_NOINTERFACE;
1773 IUnknown_AddRef((IUnknown*)*ppv);
1774 return S_OK;
1777 static ULONG WINAPI HTMLDOMRange_AddRef(IHTMLDOMRange *iface)
1779 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1780 LONG ref = InterlockedIncrement(&This->ref);
1782 TRACE("(%p) ref=%ld\n", This, ref);
1784 return ref;
1787 static ULONG WINAPI HTMLDOMRange_Release(IHTMLDOMRange *iface)
1789 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1790 LONG ref = InterlockedDecrement(&This->ref);
1792 TRACE("(%p) ref=%ld\n", This, ref);
1794 if(!ref) {
1795 if(This->nsrange)
1796 nsIDOMRange_Release(This->nsrange);
1797 release_dispex(&This->dispex);
1798 heap_free(This);
1801 return ref;
1804 static HRESULT WINAPI HTMLDOMRange_GetTypeInfoCount(IHTMLDOMRange *iface, UINT *pctinfo)
1806 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1808 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
1811 static HRESULT WINAPI HTMLDOMRange_GetTypeInfo(IHTMLDOMRange *iface, UINT iTInfo,
1812 LCID lcid, ITypeInfo **ppTInfo)
1814 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1816 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1819 static HRESULT WINAPI HTMLDOMRange_GetIDsOfNames(IHTMLDOMRange *iface, REFIID riid,
1820 LPOLESTR *rgszNames, UINT cNames,
1821 LCID lcid, DISPID *rgDispId)
1823 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1825 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames,
1826 cNames, lcid, rgDispId);
1829 static HRESULT WINAPI HTMLDOMRange_Invoke(IHTMLDOMRange *iface, DISPID dispIdMember,
1830 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1831 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1833 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1835 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid,
1836 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1839 static HRESULT WINAPI HTMLDOMRange_get_startContainer(IHTMLDOMRange *iface, IHTMLDOMNode **p)
1841 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1842 FIXME("(%p)->(%p)\n", This, p);
1843 return E_NOTIMPL;
1846 static HRESULT WINAPI HTMLDOMRange_get_startOffset(IHTMLDOMRange *iface, LONG *p)
1848 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1849 FIXME("(%p)->(%p)\n", This, p);
1850 return E_NOTIMPL;
1853 static HRESULT WINAPI HTMLDOMRange_get_endContainer(IHTMLDOMRange *iface, IHTMLDOMNode **p)
1855 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1856 FIXME("(%p)->(%p)\n", This, p);
1857 return E_NOTIMPL;
1860 static HRESULT WINAPI HTMLDOMRange_get_endOffset(IHTMLDOMRange *iface, LONG *p)
1862 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1863 FIXME("(%p)->(%p)\n", This, p);
1864 return E_NOTIMPL;
1867 static HRESULT WINAPI HTMLDOMRange_get_collapsed(IHTMLDOMRange *iface, VARIANT_BOOL *p)
1869 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1870 FIXME("(%p)->(%p)\n", This, p);
1871 return E_NOTIMPL;
1874 static HRESULT WINAPI HTMLDOMRange_get_commonAncestorContainer(IHTMLDOMRange *iface, IHTMLDOMNode **p)
1876 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1877 FIXME("(%p)->(%p)\n", This, p);
1878 return E_NOTIMPL;
1881 static HRESULT WINAPI HTMLDOMRange_setStart(IHTMLDOMRange *iface, IDispatch *node, LONG offset)
1883 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1884 FIXME("(%p)->(%p, %ld)\n", This, node, offset);
1885 return E_NOTIMPL;
1888 static HRESULT WINAPI HTMLDOMRange_setEnd(IHTMLDOMRange *iface, IDispatch *node, LONG offset)
1890 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1891 FIXME("(%p)->(%p, %ld)\n", This, node, offset);
1892 return E_NOTIMPL;
1895 static HRESULT WINAPI HTMLDOMRange_setStartBefore(IHTMLDOMRange *iface, IDispatch *node)
1897 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1898 FIXME("(%p)->(%p)\n", This, node);
1899 return E_NOTIMPL;
1902 static HRESULT WINAPI HTMLDOMRange_setStartAfter(IHTMLDOMRange *iface, IDispatch *node)
1904 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1905 FIXME("(%p)->(%p)\n", This, node);
1906 return E_NOTIMPL;
1909 static HRESULT WINAPI HTMLDOMRange_setEndBefore(IHTMLDOMRange *iface, IDispatch *node)
1911 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1912 FIXME("(%p)->(%p)\n", This, node);
1913 return E_NOTIMPL;
1916 static HRESULT WINAPI HTMLDOMRange_setEndAfter(IHTMLDOMRange *iface, IDispatch *node)
1918 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1919 FIXME("(%p)->(%p)\n", This, node);
1920 return E_NOTIMPL;
1923 static HRESULT WINAPI HTMLDOMRange_collapse(IHTMLDOMRange *iface, VARIANT_BOOL tostart)
1925 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1926 FIXME("(%p)->(%x)\n", This, tostart);
1927 return E_NOTIMPL;
1930 static HRESULT WINAPI HTMLDOMRange_selectNode(IHTMLDOMRange *iface, IDispatch *node)
1932 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1933 FIXME("(%p)->(%p)\n", This, node);
1934 return E_NOTIMPL;
1937 static HRESULT WINAPI HTMLDOMRange_selectNodeContents(IHTMLDOMRange *iface, IDispatch *node)
1939 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1940 FIXME("(%p)->(%p)\n", This, node);
1941 return E_NOTIMPL;
1944 static HRESULT WINAPI HTMLDOMRange_compareBoundaryPoints(IHTMLDOMRange *iface, short how,
1945 IDispatch *src_range, LONG *result)
1947 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1948 FIXME("(%p)->(%x, %p, %p)\n", This, how, src_range, result);
1949 return E_NOTIMPL;
1952 static HRESULT WINAPI HTMLDOMRange_deleteContents(IHTMLDOMRange *iface)
1954 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1955 FIXME("(%p)\n", This);
1956 return E_NOTIMPL;
1959 static HRESULT WINAPI HTMLDOMRange_extractContents(IHTMLDOMRange *iface, IDispatch **p)
1961 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1962 FIXME("(%p)->(%p)\n", This, p);
1963 return E_NOTIMPL;
1966 static HRESULT WINAPI HTMLDOMRange_cloneContents(IHTMLDOMRange *iface, IDispatch **p)
1968 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1969 FIXME("(%p)->(%p)\n", This, p);
1970 return E_NOTIMPL;
1973 static HRESULT WINAPI HTMLDOMRange_insertNode(IHTMLDOMRange *iface, IDispatch *node)
1975 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1976 FIXME("(%p)->(%p)\n", This, node);
1977 return E_NOTIMPL;
1980 static HRESULT WINAPI HTMLDOMRange_surroundContents(IHTMLDOMRange *iface, IDispatch *parent)
1982 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1983 FIXME("(%p)->(%p)\n", This, parent);
1984 return E_NOTIMPL;
1987 static HRESULT WINAPI HTMLDOMRange_cloneRange(IHTMLDOMRange *iface, IHTMLDOMRange **p)
1989 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1990 FIXME("(%p)->(%p)\n", This, p);
1991 return E_NOTIMPL;
1994 static HRESULT WINAPI HTMLDOMRange_toString(IHTMLDOMRange *iface, BSTR *p)
1996 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1997 FIXME("(%p)->(%p)\n", This, p);
1998 return E_NOTIMPL;
2001 static HRESULT WINAPI HTMLDOMRange_detach(IHTMLDOMRange *iface)
2003 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
2004 FIXME("(%p)\n", This);
2005 return E_NOTIMPL;
2008 static HRESULT WINAPI HTMLDOMRange_getClientRects(IHTMLDOMRange *iface, IHTMLRectCollection **p)
2010 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
2011 FIXME("(%p)->(%p)\n", This, p);
2012 return E_NOTIMPL;
2015 static HRESULT WINAPI HTMLDOMRange_getBoundingClientRect(IHTMLDOMRange *iface, IHTMLRect **p)
2017 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
2018 FIXME("(%p)->(%p)\n", This, p);
2019 return E_NOTIMPL;
2022 static const IHTMLDOMRangeVtbl HTMLDOMRangeVtbl = {
2023 HTMLDOMRange_QueryInterface,
2024 HTMLDOMRange_AddRef,
2025 HTMLDOMRange_Release,
2026 HTMLDOMRange_GetTypeInfoCount,
2027 HTMLDOMRange_GetTypeInfo,
2028 HTMLDOMRange_GetIDsOfNames,
2029 HTMLDOMRange_Invoke,
2030 HTMLDOMRange_get_startContainer,
2031 HTMLDOMRange_get_startOffset,
2032 HTMLDOMRange_get_endContainer,
2033 HTMLDOMRange_get_endOffset,
2034 HTMLDOMRange_get_collapsed,
2035 HTMLDOMRange_get_commonAncestorContainer,
2036 HTMLDOMRange_setStart,
2037 HTMLDOMRange_setEnd,
2038 HTMLDOMRange_setStartBefore,
2039 HTMLDOMRange_setStartAfter,
2040 HTMLDOMRange_setEndBefore,
2041 HTMLDOMRange_setEndAfter,
2042 HTMLDOMRange_collapse,
2043 HTMLDOMRange_selectNode,
2044 HTMLDOMRange_selectNodeContents,
2045 HTMLDOMRange_compareBoundaryPoints,
2046 HTMLDOMRange_deleteContents,
2047 HTMLDOMRange_extractContents,
2048 HTMLDOMRange_cloneContents,
2049 HTMLDOMRange_insertNode,
2050 HTMLDOMRange_surroundContents,
2051 HTMLDOMRange_cloneRange,
2052 HTMLDOMRange_toString,
2053 HTMLDOMRange_detach,
2054 HTMLDOMRange_getClientRects,
2055 HTMLDOMRange_getBoundingClientRect,
2058 static const tid_t HTMLDOMRange_iface_tids[] = {
2059 IHTMLDOMRange_tid,
2063 static dispex_static_data_t HTMLDOMRange_dispex = {
2064 L"Range",
2065 NULL,
2066 DispHTMLDOMRange_tid,
2067 HTMLDOMRange_iface_tids
2070 HRESULT create_dom_range(nsIDOMRange *nsrange, compat_mode_t compat_mode, IHTMLDOMRange **p)
2072 HTMLDOMRange *ret;
2074 ret = heap_alloc(sizeof(*ret));
2075 if(!ret)
2076 return E_OUTOFMEMORY;
2078 init_dispatch(&ret->dispex, (IUnknown*)&ret->IHTMLDOMRange_iface, &HTMLDOMRange_dispex, compat_mode);
2080 ret->IHTMLDOMRange_iface.lpVtbl = &HTMLDOMRangeVtbl;
2081 ret->ref = 1;
2083 if(nsrange)
2084 nsIDOMRange_AddRef(nsrange);
2085 ret->nsrange = nsrange;
2087 *p = &ret->IHTMLDOMRange_iface;
2088 return S_OK;
2091 void detach_ranges(HTMLDocumentNode *This)
2093 HTMLTxtRange *iter, *next;
2095 LIST_FOR_EACH_ENTRY_SAFE(iter, next, &This->range_list, HTMLTxtRange, entry) {
2096 iter->doc = NULL;
2097 list_remove(&iter->entry);
2101 typedef struct {
2102 IMarkupPointer2 IMarkupPointer2_iface;
2103 LONG ref;
2104 } MarkupPointer;
2106 static inline MarkupPointer *impl_from_IMarkupPointer2(IMarkupPointer2 *iface)
2108 return CONTAINING_RECORD(iface, MarkupPointer, IMarkupPointer2_iface);
2111 static HRESULT WINAPI MarkupPointer2_QueryInterface(IMarkupPointer2 *iface, REFIID riid, void **ppv)
2113 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2115 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
2117 if(IsEqualGUID(&IID_IUnknown, riid)) {
2118 *ppv = &This->IMarkupPointer2_iface;
2119 }else if(IsEqualGUID(&IID_IMarkupPointer, riid)) {
2120 *ppv = &This->IMarkupPointer2_iface;
2121 }else if(IsEqualGUID(&IID_IMarkupPointer2, riid)) {
2122 *ppv = &This->IMarkupPointer2_iface;
2123 }else {
2124 *ppv = NULL;
2125 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
2126 return E_NOINTERFACE;
2129 IUnknown_AddRef((IUnknown*)*ppv);
2130 return S_OK;
2133 static ULONG WINAPI MarkupPointer2_AddRef(IMarkupPointer2 *iface)
2135 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2136 LONG ref = InterlockedIncrement(&This->ref);
2138 TRACE("(%p) ref=%ld\n", This, ref);
2140 return ref;
2143 static ULONG WINAPI MarkupPointer2_Release(IMarkupPointer2 *iface)
2145 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2146 LONG ref = InterlockedDecrement(&This->ref);
2148 TRACE("(%p) ref=%ld\n", This, ref);
2150 if(!ref)
2151 heap_free(This);
2153 return ref;
2156 static HRESULT WINAPI MarkupPointer2_OwningDoc(IMarkupPointer2 *iface, IHTMLDocument2 **p)
2158 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2159 FIXME("(%p)->(%p)\n", This, p);
2160 return E_NOTIMPL;
2163 static HRESULT WINAPI MarkupPointer2_Gravity(IMarkupPointer2 *iface, POINTER_GRAVITY *p)
2165 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2166 FIXME("(%p)->(%p)\n", This, p);
2167 return E_NOTIMPL;
2170 static HRESULT WINAPI MarkupPointer2_SetGravity(IMarkupPointer2 *iface, POINTER_GRAVITY gravity)
2172 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2173 FIXME("(%p)->(%u)\n", This, gravity);
2174 return E_NOTIMPL;
2177 static HRESULT WINAPI MarkupPointer2_Cling(IMarkupPointer2 *iface, BOOL *p)
2179 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2180 FIXME("(%p)->(%p)\n", This, p);
2181 return E_NOTIMPL;
2184 static HRESULT WINAPI MarkupPointer2_SetCling(IMarkupPointer2 *iface, BOOL cling)
2186 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2187 FIXME("(%p)->(%x)\n", This, cling);
2188 return E_NOTIMPL;
2191 static HRESULT WINAPI MarkupPointer2_Unposition(IMarkupPointer2 *iface)
2193 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2194 FIXME("(%p)\n", This);
2195 return E_NOTIMPL;
2198 static HRESULT WINAPI MarkupPointer2_IsPositioned(IMarkupPointer2 *iface, BOOL *p)
2200 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2201 FIXME("(%p)->(%p)\n", This, p);
2202 return E_NOTIMPL;
2205 static HRESULT WINAPI MarkupPointer2_GetContainer(IMarkupPointer2 *iface, IMarkupContainer **p)
2207 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2208 FIXME("(%p)->(%p)\n", This, p);
2209 return E_NOTIMPL;
2212 static HRESULT WINAPI MarkupPointer2_MoveAdjacentToElement(IMarkupPointer2 *iface, IHTMLElement *element, ELEMENT_ADJACENCY adj)
2214 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2215 FIXME("(%p)->(%p %u)\n", This, element, adj);
2216 return E_NOTIMPL;
2219 static HRESULT WINAPI MarkupPointer2_MoveToPointer(IMarkupPointer2 *iface, IMarkupPointer *pointer)
2221 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2222 FIXME("(%p)->(%p)\n", This, pointer);
2223 return E_NOTIMPL;
2226 static HRESULT WINAPI MarkupPointer2_MoveToContainer(IMarkupPointer2 *iface, IMarkupContainer *container, BOOL at_start)
2228 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2229 FIXME("(%p)->(%p %x)\n", This, container, at_start);
2230 return E_NOTIMPL;
2233 static HRESULT WINAPI MarkupPointer2_Left(IMarkupPointer2 *iface, BOOL move, MARKUP_CONTEXT_TYPE *context,
2234 IHTMLElement **element, LONG *len, OLECHAR *text)
2236 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2237 FIXME("(%p)->(%x %p %p %p %p)\n", This, move, context, element, len, text);
2238 return E_NOTIMPL;
2241 static HRESULT WINAPI MarkupPointer2_Right(IMarkupPointer2 *iface, BOOL move, MARKUP_CONTEXT_TYPE *context,
2242 IHTMLElement **element, LONG *len, OLECHAR *text)
2244 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2245 FIXME("(%p)->(%x %p %p %p %p)\n", This, move, context, element, len, text);
2246 return E_NOTIMPL;
2249 static HRESULT WINAPI MarkupPointer2_CurrentScope(IMarkupPointer2 *iface, IHTMLElement **p)
2251 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2252 FIXME("(%p)->(%p)\n", This, p);
2253 return E_NOTIMPL;
2256 static HRESULT WINAPI MarkupPointer2_IsLeftOf(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2258 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2259 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2260 return E_NOTIMPL;
2263 static HRESULT WINAPI MarkupPointer2_IsLeftOfOrEqualTo(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2265 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2266 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2267 return E_NOTIMPL;
2270 static HRESULT WINAPI MarkupPointer2_IsRightOf(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2272 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2273 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2274 return E_NOTIMPL;
2277 static HRESULT WINAPI MarkupPointer2_IsRightOfOrEqualTo(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2279 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2280 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2281 return E_NOTIMPL;
2284 static HRESULT WINAPI MarkupPointer2_IsEqualTo(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2286 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2287 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2288 return E_NOTIMPL;
2291 static HRESULT WINAPI MarkupPointer2_MoveUnit(IMarkupPointer2 *iface, MOVEUNIT_ACTION action)
2293 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2294 FIXME("(%p)->(%u)\n", This, action);
2295 return E_NOTIMPL;
2298 static HRESULT WINAPI MarkupPointer2_FindText(IMarkupPointer2 *iface, OLECHAR *text, DWORD flags,
2299 IMarkupPointer *end_match, IMarkupPointer *end_search)
2301 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2302 FIXME("(%p)->(%s %lx %p %p)\n", This, debugstr_w(text), flags, end_match, end_search);
2303 return E_NOTIMPL;
2306 static HRESULT WINAPI MarkupPointer2_IsAtWordBreak(IMarkupPointer2 *iface, BOOL *p)
2308 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2309 FIXME("(%p)->(%p)\n", This, p);
2310 return E_NOTIMPL;
2313 static HRESULT WINAPI MarkupPointer2_GetMarkupPosition(IMarkupPointer2 *iface, LONG *p)
2315 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2316 FIXME("(%p)->(%p)\n", This, p);
2317 return E_NOTIMPL;
2320 static HRESULT WINAPI MarkupPointer2_MoveToMarkupPosition(IMarkupPointer2 *iface, IMarkupContainer *container, LONG mp)
2322 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2323 FIXME("(%p)->(%p %ld)\n", This, container, mp);
2324 return E_NOTIMPL;
2327 static HRESULT WINAPI MarkupPointer2_MoveUnitBounded(IMarkupPointer2 *iface, MOVEUNIT_ACTION action, IMarkupPointer *boundary)
2329 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2330 FIXME("(%p)->(%u %p)\n", This, action, boundary);
2331 return E_NOTIMPL;
2334 static HRESULT WINAPI MarkupPointer2_IsInsideURL(IMarkupPointer2 *iface, IMarkupPointer *right, BOOL *p)
2336 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2337 FIXME("(%p)->(%p %p)\n", This, right, p);
2338 return E_NOTIMPL;
2341 static HRESULT WINAPI MarkupPointer2_MoveToContent(IMarkupPointer2 *iface, IHTMLElement *element, BOOL at_start)
2343 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2344 FIXME("(%p)->(%p %x)\n", This, element, at_start);
2345 return E_NOTIMPL;
2348 static const IMarkupPointer2Vtbl MarkupPointer2Vtbl = {
2349 MarkupPointer2_QueryInterface,
2350 MarkupPointer2_AddRef,
2351 MarkupPointer2_Release,
2352 MarkupPointer2_OwningDoc,
2353 MarkupPointer2_Gravity,
2354 MarkupPointer2_SetGravity,
2355 MarkupPointer2_Cling,
2356 MarkupPointer2_SetCling,
2357 MarkupPointer2_Unposition,
2358 MarkupPointer2_IsPositioned,
2359 MarkupPointer2_GetContainer,
2360 MarkupPointer2_MoveAdjacentToElement,
2361 MarkupPointer2_MoveToPointer,
2362 MarkupPointer2_MoveToContainer,
2363 MarkupPointer2_Left,
2364 MarkupPointer2_Right,
2365 MarkupPointer2_CurrentScope,
2366 MarkupPointer2_IsLeftOf,
2367 MarkupPointer2_IsLeftOfOrEqualTo,
2368 MarkupPointer2_IsRightOf,
2369 MarkupPointer2_IsRightOfOrEqualTo,
2370 MarkupPointer2_IsEqualTo,
2371 MarkupPointer2_MoveUnit,
2372 MarkupPointer2_FindText,
2373 MarkupPointer2_IsAtWordBreak,
2374 MarkupPointer2_GetMarkupPosition,
2375 MarkupPointer2_MoveToMarkupPosition,
2376 MarkupPointer2_MoveUnitBounded,
2377 MarkupPointer2_IsInsideURL,
2378 MarkupPointer2_MoveToContent
2381 HRESULT create_markup_pointer(IMarkupPointer **ret)
2383 MarkupPointer *markup_pointer;
2385 if(!(markup_pointer = heap_alloc(sizeof(*markup_pointer))))
2386 return E_OUTOFMEMORY;
2388 markup_pointer->IMarkupPointer2_iface.lpVtbl = &MarkupPointer2Vtbl;
2389 markup_pointer->ref = 1;
2391 *ret = (IMarkupPointer*)&markup_pointer->IMarkupPointer2_iface;
2392 return S_OK;